diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/CREDITS linux.pre11.3/CREDITS
--- linux.vanilla/CREDITS	Tue Jun 15 16:49:44 1999
+++ linux.pre11.3/CREDITS	Tue Jul 20 00:25:06 1999
@@ -324,6 +324,10 @@
 S: 75252 Paris Cedex 05
 S: France
 
+N: Ulf Carlsson
+D: SGI Indy audio (HAL2) drivers
+E: ulfc@bun.falkenberg.se
+
 N: Ed Carp
 E: ecarp@netcom.com
 D: uucp, elm, pine, pico port
@@ -453,6 +457,14 @@
 S: Warrendale, Pennsylvania 15086
 S: USA
 
+N: Alex deVries
+E: puffin@redhat.com
+D: Various SGI parts, bits of HAL2 and Newport
+S: 18 Bernier Terrace
+S: Kanata, Ontario
+S: K2L 2V@
+S: CANADA
+
 N: Eddie C. Dost
 E: ecd@skynet.be
 D: Linux/Sparc kernel hacker
@@ -946,7 +958,7 @@
 E: nkbj@image.dk
 W: http://www.image.dk/~nkbj
 D: 4.4BSD and NeXTstep filesystem support in the old ufs.
-D: Openstep filesystem support in the new ufs.
+D: Openstep filesystem and NeXTstep CDROM support in the new ufs.
 D: Danish HOWTO, Linux+FreeBSD mini-HOWTO.
 S: Dr. Holsts Vej 34, lejl. 164
 S: DK-8230 Åbyhøj
@@ -1603,6 +1615,15 @@
 S: San Jose, California 95129
 S: USA
 
+N: Augusto Cesar Radtke
+E: bishop@sekure.org
+W: http://bishop.sekure.org
+D: {copy,get,put}_user calls updates
+D: Miscellaneous hacks
+S: R. Otto Marquardt, 226 - Garcia
+S: 89020-350 Blumenau - Santa Catarina
+S: Brazil
+
 N: Eric S. Raymond
 E: esr@thyrsus.com
 W: http://www.tuxedo.org/~esr/
@@ -1638,12 +1659,13 @@
 S: France
 
 N: Rik van Riel
-E: H.H.vanRiel@humbolt.geo.uu.nl
-W: http://humbolt.geo.uu.nl/
-D: Maintainer of the mm-patches page (see www.linuxhq.com)
-D: Documentation/sysctl/*, kswapd fixes, random kernel hacker
-S: Vorenkampsweg 1
-S: NL-9488 TG  Zeijerveld
+E: riel@nl.linux.org
+W: http://www.nl.linux.org/~riel/
+D: Linux-MM site, Documentation/sysctl/*, swap/mm readaround
+D: clustering contributor, kswapd fixes, random kernel hacker,
+D: nl.linux.org maintainer, minor scheduler additions
+S: IJsselstraat 23a
+S: 9725 GA  Groningen
 S: The Netherlands
 
 N: William E. Roadcap
@@ -2253,6 +2275,7 @@
 E: lnz@dandelion.com
 W: http://www.dandelion.com/Linux/
 D: BusLogic SCSI driver
+D: Mylex DAC960 PCI RAID driver
 D: Miscellaneous kernel fixes
 S: 3078 Sulphur Spring Court
 S: San Jose, California 95148
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Changes linux.pre11.3/Documentation/Changes
--- linux.vanilla/Documentation/Changes	Thu May 27 22:11:46 1999
+++ linux.pre11.3/Documentation/Changes	Mon Jul 19 23:49:58 1999
@@ -11,18 +11,14 @@
 functional and running at least 2.0.x kernels.
 
    It is originally based on my "Changes" file for 2.0.x kernels and
-therefore owes credit to the same people as that file (Jared Mauch,
-Axel Boldt, Alessandro Sigala, and countless other users all over the
-'net).  Please feel free to submit changes, corrections, gripes,
-flames, money, etc. to me (kaboom@gatech.edu).  If you do so, you don't
+therefore owes credit to the same people as that file (Jared Mauch, Axel
+Boldt, Alessandro Sigala, and countless other users all over the 'net).
+Please feel free to submit changes, corrections, gripes, flames, money,
+etc. to me (chris.ricker@genetics.utah.edu).  If you do so, you don't
 need to bother doing so in the form of a diff, as this is generated by
 texinfo so a diff is useless anyway (though I can incorporate one by
 hand if you insist upon sending it that way ;-).
 
-   For those of you in Europe,
-http://www.datanet.hu/generations/linux/Changes2.html is an
-English-language HTML version.
-
    The most current version should always be available from
 http://cyberbuzz.gatech.edu/kaboom/linux/ as well.
 
@@ -30,11 +26,26 @@
 http://www.linux-france.com/article/sys/Changes-2.2/Changes-2.2.1.html
 pour la traduction français.
 
-   Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
-needs.
+   Nihongo-ban ha kochira desu (text & html)
+http://www.linux.or.jp/JF/JFdocs/kernel-docs-2.2/Changes
+http://www2.palnet.or.jp/~matsuda/Changes-2.2.ja.html
+
+   Visite http://www2.adi.uam.es/~ender/tecnico/cambios22.html para
+obtener la traducción al español de este documento.
+
+   Also, don't forget
+
+   http://www.linuxhq.com/
 
-Last updated: March 16, 1999
-Current Author: Chris Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu).
+   http://www.kernelnotes.org/
+
+   http://www.kernel.org/
+
+   for all your Linux kernel needs.
+
+Last updated: July 13, 1999
+Current Author: Chris Ricker (kaboom@gatech.edu or
+	chris.ricker@genetics.utah.edu).
 
 Current Minimal Requirements
 ****************************
@@ -53,16 +64,16 @@
 - Procps		 1.2.9                   ; ps --version
 - Procinfo               16                      ; procinfo -v
 - Psmisc		 17			 ; pstree -V
-- Net-tools              1.50                    ; hostname -V
+- Net-tools              1.52                    ; hostname -V
 - Loadlin                1.6a
 - Sh-utils               1.16                    ; basename --v
 - Autofs                 3.1.1                   ; automount --version
 - NFS                    2.2beta40               ; showmount --version
 - Bash                   1.14.7                  ; bash -version
 - Ncpfs                  2.2.0                   ; ncpmount -v
-- Pcmcia-cs              3.0.7                   ; cardmgr -V
-- PPP                    2.3.5                   ; pppd --version
-- Util-linux             2.9i                    ; chsh -v
+- Pcmcia-cs              3.0.13                  ; cardmgr -V
+- PPP                    2.3.8                   ; pppd --version
+- Util-linux             2.9t                    ; chsh -v
 
 Upgrade notes
 *************
@@ -86,9 +97,9 @@
 compiled under 2.2, for example.
 
    As of 2.1.115, support for the deprecated major 4 /dev/ttyp* devices
-was removed.  If necessary (eg, you get "out of pty" error messages when
-you obviously are not out of pty's), create major 3 /dev/tty* and major
-2 /dev/pty* devices (see Documentation/devices.txt for more
+was removed.  If necessary (eg, you get "out of pty" error messages
+when you obviously are not out of pty's), create major 3 /dev/tty* and
+major 2 /dev/pty* devices (see Documentation/devices.txt for more
 information).  In general, you should make sure that your /dev
 directory is up-to-date if you are experiencing any problems.
 
@@ -134,8 +145,8 @@
 release.
 
    If you upgrade to libc-5.4.x, you also have to upgrade your dynamic
-linker (ld.so) to at least 1.9.9, or all sorts of weirdness will
-happen.  Actually, ld.so-1.8.2 and later will work, but 1.9.9 is widely
+linker (ld.so) to at least 1.9.9, or all sorts of weirdness will happen.
+Actually, ld.so-1.8.2 and later will work, but 1.9.9 is widely
 available, so if you need to upgrade, use it.  If you get a release
 later than 1.8.5, avoid 1.8.10 as it introduces a few bugs that are
 fixed in later releases.  Please make sure you don't install ld.so-2.x
@@ -158,9 +169,9 @@
 of your boot scripts calls ldconfig, /etc/ld.so.cache is deleted.  Init,
 however, still references that file; as of 2.1.122, the kernel will
 consequently not be able to remount the root file system r/o at system
-shutdown.  To fix this, upgrade to at least the pre6 release of GNU
-libc 2.0.7.  As a temporary workaround, modify your boot scripts to do
-the following before calling ldconfig:
+shutdown.  To fix this, upgrade to at least the pre6 release of GNU libc
+2.0.7.  As a temporary workaround, modify your boot scripts to do the
+following before calling ldconfig:
 
    	ln -f /etc/ld.so.cache /etc/ld.so.cache.old
 
@@ -197,6 +208,12 @@
 and binutils-development packages (Debian puts bfd.h in binutils-dev,
 for example).
 
+Bin86
+=====
+
+   To compile the kernel on the IA32 platform, a real-mode assembler and
+linker is required.  These are found in the bin86 package.
+
 Gnu C
 =====
 
@@ -287,19 +304,17 @@
 larger swap spaces, you need the new mkswap found in util-linux.  You
 also need to upgrade util-linux to get the latest version of mount.
 
-   Partitions on 2048 byte sectored media (certain magneto opticals 
-most prominently) were broken throughout the whole of 2.1 kernel 
-series, meaning that you will be unable to use 2.1-partitioned media on 
-Linux 2.2. This is not a 2.2 bug - 2.2 finally does the right thing! 
-[If you have to interchange media between Linux 2.1 and 2.2, your best 
-bet is to not use partitions at all but create the filesystem on the 
-raw device (e.g. /dev/sda) instead. This is also known as the 
-superfloppy format.]
-
-   To properly create partitions on 2048 byte sectored media with Linux
-2.2, be sure to use no less than fdisk version 2.9i and invoke fdisk
-using '-b 2048' as an option.
-
+   Partitions on 2048-bytes-per-sector media (certain magneto-opticals
+most prominently) were broken throughout the 2.1 kernel series, meaning
+that you will be unable to use 2.1-partitioned media on Linux 2.2. This
+is not a 2.2 bug - 2.2 finally does the right thing!  [If you have to
+interchange media between Linux 2.1 and 2.2, your best bet is to not
+use partitions at all but create the filesystem on the raw device (e.g.
+/dev/sda) instead.  This is also known as the superfloppy format.]
+
+   To properly create partitions on 2048-bytes-per-sector media with
+Linux 2.2, be sure to use no less than fdisk version 2.9i and invoke
+fdisk using '-b 2048' as an option.
 
 RPM
 ===
@@ -311,7 +326,7 @@
 ======
 
    A new "stable" version of DOSEMU is available for 2.2 kernels.
-Upgrade to 0.98.4 or later.
+Upgrade to 0.98.6 or later.
 
 Loadlin
 =======
@@ -329,7 +344,7 @@
 Parallel Ports
 ==============
 
-   As of 2.1.33, parallel port support can now by handled by the parport
+   As of 2.1.33, parallel port support can now be handled by the parport
 driver.  Be aware that with Plug-and-Play support turned on, your
 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
@@ -351,7 +366,9 @@
    When you build your kernel with Syncookie support
 (CONFIG_SYN_COOKIES) the syncookie code still defaults to off (unlike
 the 2.0.30+ behavior).  You have to explicitly enable it by issuing the
-following command: echo 1 > /proc/sys/net/ipv4/tcp_syncookies
+following command:
+
+   echo 1 > /proc/sys/net/ipv4/tcp_syncookies
 
 Bash
 ====
@@ -381,8 +398,8 @@
    To mount SMB (Samba / Windows) shares, you'll need to use the
 smbmount utility included with release 2.0 of Samba.
 Documentation/filesystems/smbfs.txt has more information about this.
-Note that smbmount must have been built against 2.2 headers to work
-with 2.2; if all else fails, recompile it and hope it works ;-).  In
+Note that smbmount must have been built against 2.2 headers to work with
+2.2; 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.
@@ -445,6 +462,7 @@
 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....
@@ -519,6 +537,13 @@
 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
 
+Bin86
+=====
+
+The 0.4 release:
+ftp://metalab.unc.edu/pub/Linux/GCC/bin86-0.4.tar.gz
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/bin86-0.4.tar.gz
+
 Gnu C
 =====
 
@@ -598,9 +623,9 @@
 DOSEMU
 ======
 
-The 0.98.1 release:
-ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.4.tgz
-ftp://ftp.dosemu.org/dosemu/dosemu-0.98.4.tgz
+The 0.98.6 release:
+ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.6.tgz
+ftp://ftp.dosemu.org/dosemu/dosemu-0.98.6.tgz
 
 Loadlin
 =======
@@ -620,7 +645,7 @@
 ==========
 
 The 2.9 release:
-ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/util-linux-2.9i.tar.gz
+ftp://ftp.win.tue.nl/pub/linux/utils/util-linux/util-linux-2.9t.tar.gz
 
 Autofs
 ======
@@ -635,16 +660,16 @@
 ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/dontuse/nfs-server-2.2beta40.tar.gz
 ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/dontuse/nfs-server-2.2beta40.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
+The kernel-level 1.4.4 release:
+ftp://ftp.varesearch.com/pub/support/hjl/knfsd/knfsd-1.4.4.tar.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-1.4.4.tar.gz
 
 Net-tools
 =========
 
-The 1.50 release:
-ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.50.tar.gz
-http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.50.tar.gz
+The 1.52 release:
+ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.52.tar.gz
+http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.52.tar.gz
 
 Ypbind
 ======
@@ -664,8 +689,8 @@
 The 1.14.7 release:
 ftp://ftp.gnu.org/gnu/bash/bash-1.14.7.tar.gz
 
-The 2.02.1 release:
-ftp://ftp.gnu.org/gnu/bash/bash-2.02.1.tar.gz
+The 2.03 release:
+ftp://ftp.gnu.org/gnu/bash/bash-2.03.tar.gz
 
 Ncpfs
 =====
@@ -676,14 +701,14 @@
 SMBfs
 =====
 
-The 2.0.0 release of Samba:
-ftp://ftp.samba.org/pub/samba/samba-2.0.0.tar.gz
+The 2.0.4b release of Samba:
+ftp://ftp.samba.org/pub/samba/samba-2.0.4b.tar.gz
 
 Pcmcia-cs
 =========
 
-The 3.0.7 release:
-ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.7.tar.gz
+The 3.0.13 release:
+ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.13.tar.gz
 
 Setserial
 =========
@@ -695,8 +720,8 @@
 PPP
 ===
 
-The 2.3.5 release:
-ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.5.tar.gz
+The 2.3.8 release:
+ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.8.tar.gz
 
 IP Chains
 =========
@@ -714,8 +739,8 @@
 DHCP clients
 ============
 
-The 2.0b1p18 ISC dhcpclient release:
-ftp://ftp.isc.org/isc/dhcp/test/dhcp-2.0b1pl8.tar.gz
+The 2.0b1pl27 ISC dhcpclient release:
+ftp://ftp.isc.org/isc/dhcp/test/dhcp-2.0b1pl27.tar.gz
 
 The 1.3.17-pl2 PhysTech dhcpcd release:
 ftp://ftp.phystech.com/pub/dhcpcd-1.3.17-pl2.tar.gz
@@ -735,15 +760,15 @@
 Fbset
 =====
 
-The 11/04/98 release:
-http://www.cs.kuleuven.ac.be/~geert/bin/fbset-2.0-pre-19981104.tar.gz
+The 2.1 release:
+http://www.cs.kuleuven.ac.be/~geert/bin/fbset-2.1.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
+The 2.0 release:
+ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-2.0.tar.gz
+ftp://metalab.unc.edu/pub/Linux/hardware/pciutils-2.0.tar.gz
 
 Tunelp
 ======
@@ -767,8 +792,9 @@
 IP utils
 ========
 
-The 03/01/99 release:
-ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.1.99-now-ss990301.tar.gz
+The June 1999 release:
+ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss990630.tar.gz
+ftp://ftp.inr.ac.ru/ip-routing/iputils-ss990610.tar.gz
 
 Patch
 =====
@@ -791,7 +817,7 @@
 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://contrib.redhat.com/ ,
-ftp://developer.redhat.com/ , or ftp://updates.redhat.com/  will have
+ftp://developer.redhat.com/ , or ftp://updates.redhat.com/ will have
 almost everything you need, and Red Hat 5.2 ships with most necessary
 software.
 
@@ -802,5 +828,5 @@
 
 Please send info about any other packages that 2.2 "broke" or about any
 new features of 2.2 that require extra or new packages for use to Chris
-Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu).
+Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/Configure.help linux.pre11.3/Documentation/Configure.help
--- linux.vanilla/Documentation/Configure.help	Tue Jun 15 16:49:44 1999
+++ linux.pre11.3/Documentation/Configure.help	Tue Jul 20 00:25:42 1999
@@ -1844,6 +1844,11 @@
   You will get a boot time penguin logo at no additional cost. Please
   read Documentation/fb/vesafb.txt. If unsure, say Y.
 
+VGA 16-color graphics console
+CONFIG_FB_VGA16
+  This is the frame buffer device driver for VGA 16 color graphic
+  cards. Say Y if you have such a card.
+
 Backward compatibility mode for Xpmac
 CONFIG_FB_COMPAT_XPMAC
   If you use the Xpmac X server (common with mklinux), you'll need to
@@ -4989,6 +4994,17 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
+Aironet Arlan 655 & IC2200 DS support
+CONFIG_ARLAN
+  Aironet makes Arlan. www.aironet.com. Uses www.Telxon.com chip, which is
+  used on several similar cards. Driver is tested on 655 and IC2200 series. 
+  Look for http://www.ylenurme.ee/~elmer/655/ for latest information. 
+  Driver is build as two modules, arlan and arlan-proc. The later is /proc
+  interface and not needed most of time.
+  On some computers the card ends up in non-valid state after some time.
+  Use a ping-reset script to clear it.
+   
+
 LAPB over Ethernet driver
 CONFIG_LAPBETHER
   This is a driver for a pseudo device (typically called /dev/lapb0)
@@ -5115,6 +5131,15 @@
   module, say M here and read Documentation/modules.txt. If you don't
   know what to use this for, you don't need it.
 
+Sealevel Systems 4021 support
+CONFIG_SEALEVEL_4021
+  This is a driver for the Sealevel Systems ACB 56 serial I/O adapter.
+  
+  This driver can only be compiled as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  If you want to do that, say M here. The module will be called
+  sealevel.o.
+
 Frame Relay (DLCI) support
 CONFIG_DLCI
   This is support for the frame relay protocol; frame relay is a fast
@@ -5734,7 +5759,7 @@
   say M here and read Documentation/modules.txt. This is recommended.
   The module will be called yellowfin.o.
 
-Alteon AceNIC / 3Com 3C985 Gigabit Ethernet support.
+Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support
 CONFIG_ACENIC
   Say Y here if you have an Alteon AceNIC or 3Com 3C985 PCI Gigabit
   Ethernet adapter. The driver allows for using the Jumbo Frame
@@ -6492,6 +6517,25 @@
   The module will be called ibmtr.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+IBM Olympic chipset PCI adapter support
+CONFIG_IBMOL
+  This is support for all non-Lanstreamer IBM PCI Token Ring Cards. 
+  Specifically this is all IBM PCI, PCI Wake On Lan, PCI II, PCI II
+  Wake On Lan, and PCI 100/16/4 adapters.
+
+  If you have such an adapter, say Y and read the Token-Ring mini-HOWTO,
+  available via FTP (user:anonymous) from
+  ftp://metalab.unc/edu/pub/Linux/docs/HOWTO.
+
+  This driver is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will will be called olympic.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  Also read the linux/Documentation/networking/olympic.txt or check the 
+  Linux Token Ring Project site for the latest information at
+  http://www.linuxtr.net
+
 SysKonnect adapter support
 CONFIG_SKTR
   This is support for all SysKonnect Token Ring cards, specifically
@@ -7360,6 +7404,18 @@
   Say Y here if you want to try writing to UFS partitions. This is
   experimental, so you should back up your UFS partitions beforehand.
 
+EFS filesystem support (experimental)
+CONFIG_EFS_FS
+  EFS is the filesystem used for CDROMs and filesystems by SGI's IRIX.
+  This implementation only offers read-only access.  If you don't know
+  what all this is about, it's safe to say N.  For more information
+  about EFS see it's homepage at http://aeschi.ch.eu.org/efs.
+
+SGI disklabel support
+CONFIG_SGI_DISKLABEL
+  Say Y to this only if you plan on mounting disks with SGI disklabels.
+  This is not required to mount EFS-format CDROMs.
+
 BSD disklabel (FreeBSD partition tables) support
 CONFIG_BSD_DISKLABEL
   FreeBSD uses its own hard disk partition scheme on your PC. It
@@ -8110,6 +8166,16 @@
 
   If you haven't heard about it, it's safe to say N.
 
+Cyclades-Z interrupt mode operation (EXPERIMENTAL)
+CONFIG_CYZ_INTR
+  The Cyclades-Z family of multiport cards allows 2 (two) driver
+  op modes: polling and interrupt. In polling mode, the driver will
+  check the status of the Cyclades-Z ports every certain amount of
+  time (which is called polling cycle and is configurable). In
+  interrupt mode, it will use an interrupt line (IRQ) in order to check
+  the status of the Cyclades-Z ports. The default op mode is polling.
+  If unsure, say N.
+
 Stallion multiport serial support 
 CONFIG_STALDRV
   Stallion cards give you many serial ports. You would need something
@@ -9191,7 +9257,7 @@
   after the PnP configuration is finished. To do this, say M here and
   read Documentation/modules.txt as well as
   Documentation/sound/README.modules; the module will be called
-  sound.o.
+  soundcore.o.
 
   I'm told that even without a sound card, you can make your computer
   say more than an occasional beep, by programming the PC speaker.
@@ -9764,6 +9830,11 @@
 
 ISDN subsystem
 CONFIG_ISDN
+  CAUTION: the ISDN driver shipped with this kernel distribution
+  is outdated and might not work without problems. An updated driver
+  is available for download. Please read http://www.isdn4linux.de
+  on the WWW for a list of servers.
+
   ISDN ("Integrated Services Digital Networks", called RNIS in France)
   is a special type of fully digital telephone service; it's mostly
   used to connect to your Internet service provider (with SLIP or
@@ -9830,6 +9901,20 @@
   connections. See Documentation/isdn/README.x25 for more information
   if you are thinking about using this.
 
+ISDN diversion services support
+CONFIG_ISDN_DIVERSION
+  This option allows you to use some supplementary diversion
+  services in conjunction with the HiSax driver on an EURO/DSS1
+  line. Supported options are CD (call deflection), CFU (Call 
+  forward unconditional), CFB (Call forward when busy) and CFNR 
+  (call forward not reachable).
+  Additionally the actual CFU, CFB and CFNR state may be 
+  interrogated. The use of CFU, CFB, CFNR and interrogation may
+  be limited to some countries. The keypad protocol is still not
+  implemented.
+  CD should work in all countries if this service has been sub-
+  scribed.
+
 ICN 2B and 4B support
 CONFIG_ISDN_DRV_ICN
   This enables support for two kinds of ISDN-cards made by a German
@@ -9872,6 +9957,24 @@
   called hisax.o. See Documentation/isdn/README.HiSax for more
   information on using this driver.
 
+HiSax Support for EURO/DSS1
+CONFIG_HISAX_EURO
+  Enable this if you have a EURO ISDN line.
+
+Support for german chargeinfo
+CONFIG_DE_AOC
+  If you have german AOC, you can enable this to get the charginfo.
+
+Disable sending complete
+CONFIG_HISAX_NO_SENDCOMPLETE
+  If you have trouble with some ugly exchanges or you live in
+  Australia select this option.
+
+Disable sending low layer compatibility
+CONFIG_HISAX_NO_LLC
+  If you have trouble with some ugly exchanges try to select this
+  option.
+
 HiSax Support for Teles 16.0/8.0
 CONFIG_HISAX_16_0
   This enables HiSax support for the Teles ISDN-cards S0-16.0, S0-8
@@ -9890,13 +9993,15 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for Teles 16.3c
-CONFIG_HISAX_TELES3C
-  This enables HiSax support for the Teles ISDN-cards 16.3c.
-  
-  See Documentation/isdn/README.HiSax on how to configure it using the
-  different cards, a different D-channel protocol, or non-standard
-  IRQ/port settings.
+HiSax Support for Teles PCI
+CONFIG_HISAX_TELESPCI
+  This enables HiSax support for the Teles PCI.
+  See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Teles S0Box
+CONFIG_HISAX_S0BOX
+  This enables HiSax support for the Teles/Creatix parallel port
+  S0BOX.  See Documentation/isdn/README.HiSax on how to configure it.
 
 HiSax Support for AVM A1 (Fritz)
 CONFIG_HISAX_AVM_A1
@@ -9906,7 +10011,17 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for Elsa ISA cards
+HiSax Support for AVM PnP/PCI (Fritz!PNP/PCI)
+CONFIG_HISAX_FRITZPCI
+  This enables HiSax support for the AVM "Fritz!PnP" and "Fritz!PCI".
+  See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for AVM A1 PCMCIA (Fritz)
+CONFIG_HISAX_AVM_A1_PCMCIA
+  This enables HiSax support for the AVM A1 "Fritz!PCMCIA").
+  See Documentation/isdn/README.HiSax on how to configure it.
+
+HiSax Support for Elsa cards
 CONFIG_HISAX_ELSA
   This enables HiSax support for the Elsa Mircolink ISA cards, for the
   Elsa Quickstep series cards and Elsa PCMCIA.
@@ -9949,7 +10064,16 @@
   different cards, a different D-channel protocol, or non-standard
   IRQ/port settings.
 
-HiSax Support for Sedlbauer speed card/win-star
+HiSax Support for HFC-S based cards
+CONFIG_HISAX_HFCS
+  This enables HiSax support for the HFC-S 2BDS0 based cards, like
+  teles 16.3c.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using the
+  different cards, a different D-channel protocol, or non-standard
+  IRQ/port settings.
+
+HiSax Support for Sedlbauer cards
 CONFIG_HISAX_SEDLBAUER
   This enables HiSax support for the Sedlbauer passive ISDN cards.
 
@@ -9986,51 +10110,46 @@
   See Documentation/isdn/README.HiSax on how to configure it using a
   different D-channel protocol, or non-standard IRQ/port settings.
 
+HiSax Support for Siemens I-Surf card
+CONFIG_HISAX_ISURF
+  This enables HiSax support for the Siemens I-Talk/I-Surf card with
+  ISAR chip.
+  See Documentation/isdn/README.HiSax on how to configure it using a
+  different D-channel protocol, or non-standard IRQ/port settings.
+
+HiSax Support for HST Saphir card
+CONFIG_HISAX_HSTSAPHIR
+  This enables HiSax support for the HST Saphir card.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using a
+  different D-channel protocol, or non-standard IRQ/port settings.
+
+HiSax Support for Telekom A4T card
+CONFIG_HISAX_BKM_A4T
+  This enables HiSax support for the Telekom A4T card.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using a
+  different D-channel protocol, or non-standard IRQ/port settings.
+
+HiSax Support for Scitel Quadro card
+CONFIG_HISAX_SCT_QUADRO
+  This enables HiSax support for the Scitel Quadro card.
+  
+  See Documentation/isdn/README.HiSax on how to configure it using a
+  different D-channel protocol, or non-standard IRQ/port settings.
+
+HiSax Support for Gazel cards
+CONFIG_HISAX_GAZEL
+  This enables HiSax support for the Gazel cards.
+
+  See Documentation/isdn/README.HiSax on how to configure it using a
+  different D-channel protocol, or non-standard IRQ/port settings.
+
 HiSax Support for Am7930 (EXPERIMENTAL)
 CONFIG_HISAX_AMD7930
   This enables HiSax support for the AMD7930 chips on some SPARCs.
   This code is not finished yet.
 
-HiSax Support for EURO/DSS1
-CONFIG_HISAX_EURO
-  Say Y or N according to the D-channel protocol which your local
-  telephone service company provides.
-
-  NOTE: If you say Y here and you have only one ISDN card installed,
-  you cannot say Y to "HiSax Support for German 1TR6", below. And vice
-  versa.
-
-Support for German tariff info
-CONFIG_DE_AOC
-  If you want that the HiSax hardware driver sends messages to the
-  upper level of the isdn code on each AOCD (Advice Of Charge, During
-  the call -- transmission of the fee information during a call) and
-  on each AOCE (Advice Of Charge, at the End of the call --
-  transmission of fee information at the end of the call), say Y here.
-  This works only in Germany.
-
-Support for Australian Microlink service (not for std. EURO)
-CONFIG_HISAX_ML
-  If you are in Australia and connected to the Microlink telephone
-  network, enable this, because there are little differences in
-  protocol.
-  
-  Please don't enable this in other countries.
-
-HiSax Support for US/NI-1 (not released yet)
-CONFIG_HISAX_NI1
-  Say Y or N according to the D-channel protocol which your local
-  telephone service company provides.
-
-HiSax Support for German 1TR6
-CONFIG_HISAX_1TR6
-  Say Y or N according to the D-channel protocol which your local
-  telephone service company provides.
-
-  NOTE: If you say Y here and you have only one ISDN card installed,
-  you cannot say Y to "HiSax Support for EURO/DSS1", above. And vice
-  versa.
-
 PCBIT-D support
 CONFIG_ISDN_DRV_PCBIT
   This enables support for the PCBIT ISDN-card. This card is
@@ -10731,6 +10850,11 @@
   Choose Y here if you have this FM radio card, and then fill in the 
   port address below.
 
+  If you have GemTeks combined (PnP) sound- and radio card you must use
+  this driver as a module and setup the card with isapnptools. You must
+  also pass the module a suitable io parameter, 0x248 has been reported
+  to be used by these cards.
+
   In order to control your radio card, you will need to use programs
   that are compatible with the Video for Linux API. Information on 
   this API and pointers to "v4l" programs may be found on the WWW at
@@ -11452,6 +11576,14 @@
   boards from BVM Ltd.  Everyone using one of these boards should say
   Y here.
 
+Compaq SMART2 support
+CONFIG_BLK_CPQ_DA
+   This is the driver for Compaq Smart Array controllers.  
+   Everyone using these boards should say Y here.  
+   See "linux/Documentation/cpqarray.txt" for the current list of 
+   boards supported by this driver, and for further information 
+   on the use of this driver. 
+ 
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet, 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/cpqarray.txt linux.pre11.3/Documentation/cpqarray.txt
--- linux.vanilla/Documentation/cpqarray.txt	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/Documentation/cpqarray.txt	Mon Jul 19 23:50:13 1999
@@ -0,0 +1,107 @@
+This driver is for Compaq's SMART2 Intellegent Disk Array Controllers.
+
+WARNING:
+--------
+
+This driver comes with NO WARRANTY.  It is not officially supported by
+Compaq.  Do not call technical support.  Use at your own risk.
+
+Supported Cards:
+----------------
+
+This driver is known to work with the following cards:
+
+	* SMART (EISA)
+	* SMART-2/E (EISA)
+	* SMART-2/P
+	* SMART-2DH
+	* SMART-2SL
+	* SMART-221
+	* SMART-3100ES
+	* SMART-3200
+	* Integrated Smart Array Controller
+	* SA 4200
+	* SA 4250ES
+
+It should also work with some really old Disk array adapters, but I am
+unable to test against these cards:
+
+	* IDA
+	* IDA-2
+	* IAES
+
+Installing:
+-----------
+
+You need to build a new kernel to use this device, even if you want to
+use a loadable module.  
+
+Apply the patch to a 2.2.x kernel:
+
+# cd linux
+# patch -p1 <smart2.patch
+
+Then build a new kernel and turn on Compaq SMART2 Disk Array support.
+Create device nodes for the diskarray device:
+
+# mkdev.ida [ctlrs]
+
+Where ctlrs is the number of controllers you have (defaults to 1 if not
+specified).
+
+EISA Controllers:
+-----------------
+
+If you want to use an EISA controller you'll have to supply some
+insmod/lilo paramaters.  If the driver is compiled into the kernel, must
+give it the controller's IO port address at boot time (it is no longer
+necessary to specifiy the IRQ).  For example, if you had two SMART-2/E
+controllers, in EISA slots 1 and 2 you'd give it a boot argument like
+this:
+
+	smart2=0x1000,0x2000
+
+If you were loading the driver as a module, you'd give load it like this:
+
+	insmod cpqarray.o eisa=0x1000,0x2000
+
+You can use EISA and PCI adapters at the same time.
+
+Booting:
+--------
+
+You'll need to use a modified lilo if you want to boot from a disk array.
+Its simply a version of lilo with some code added to tell it how to
+understand Compaq diskarray devices.
+
+Device Naming:
+--------------
+
+You need some entries in /dev for the ida device.  The mkdev.ida script
+can make device nodes for you automatically.  Currently the device setup
+is as follows:
+
+Major numbers:
+	72	ida0
+	73	ida1
+	74	ida2
+	etc...
+
+Minor numbers:
+        b7 b6 b5 b4 b3 b2 b1 b0
+        |----+----| |----+----|
+             |           |
+             |           +-------- Partition ID (0=wholedev, 1-15 partition)
+             |
+             +-------------------- Logical Volume number
+
+The suggested device naming scheme is:
+/dev/ida/c0d0		Controller 0, disk 0, whole device
+/dev/ida/c0d0p1		Controller 0, disk 0, partition 1
+/dev/ida/c0d0p2		Controller 0, disk 0, partition 2
+/dev/ida/c0d0p3		Controller 0, disk 0, partition 3
+
+/dev/ida/c1d1		Controller 1, disk 1, whole device
+/dev/ida/c1d1p1		Controller 1, disk 1, partition 1
+/dev/ida/c1d1p2		Controller 1, disk 1, partition 2
+/dev/ida/c1d1p3		Controller 1, disk 1, partition 3
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/fb/tgafb.txt linux.pre11.3/Documentation/fb/tgafb.txt
--- linux.vanilla/Documentation/fb/tgafb.txt	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/Documentation/fb/tgafb.txt	Tue Jul 20 00:25:57 1999
@@ -0,0 +1,51 @@
+[Also cloned from vesafb.txt, thanks to Gerd]
+
+What is tgafb?
+===============
+
+This is a driver for DECChip 21030 based graphics framebuffers, a.k.a. TGA
+cards, specifically the following models
+
+ZLxP-E1 (8bpp, 4 MB VRAM)
+ZLxP-E2 (32bpp, 8 MB VRAM)
+ZLxP-E3 (32bpp, 16 MB VRAM, Zbuffer)
+
+This version, tgafb-1.12, is almost a complete rewrite of the code written
+by Geert Uytterhoeven, which was based on the original TGA console code
+written by Jay Estabrook.
+
+Major new features:
+
+ * Support for multiple resolutions, including setting the resolution at
+   boot time, allowing the use of a fixed-frequency monitor.
+ * Complete code rewrite to follow Geert's skeletonfb spec which will allow
+   future implementation of hardware acceleration and other features.
+
+
+Configuration
+=============
+
+You can pass kernel command line options to tgafb with
+`video=tga:option1,option2:value2,option3' (multiple options should be
+separated by comma, values are separated from options by `:').
+Accepted options:
+
+font:X    - default font to use. All fonts are supported, including the
+            SUN12x22 font which is very nice at high resolutions.
+mode:X    - default video mode. See drivers/video/tgafb.c for a list.
+            
+X11
+===
+
+XF68_FBDev should work just fine, but I haven't tested it.  Running
+the XF86_TGA server (reasonably recent versions of which support all TGA
+cards) works fine for me.
+
+One minor problem with XF86_TGA is when running tgafb in resolutions higher
+than 640x480, on switching VCs from tgafb to X, the entire screen is not
+re-drawn and must be manually refreshed. This is an X server problem, not a
+tgafb problem.
+
+Enjoy!
+
+Martin Lucina <mato@kotelna.sk>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/filesystems/ufs.txt linux.pre11.3/Documentation/filesystems/ufs.txt
--- linux.vanilla/Documentation/filesystems/ufs.txt	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/Documentation/filesystems/ufs.txt	Tue Jul 20 00:26:16 1999
@@ -30,6 +30,10 @@
 		used in NextStep
 		supported as read-only
 
+	nextstep-cd
+		used for NextStep CDROMs (block_size == 2048)
+		supported as read-only
+
 	openstep
 		used in OpenStep
 		supported as read-only
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/CREDITS linux.pre11.3/Documentation/isdn/CREDITS
--- linux.vanilla/Documentation/isdn/CREDITS	Tue Jun 15 16:49:44 1999
+++ linux.pre11.3/Documentation/isdn/CREDITS	Tue Jul 20 00:26:16 1999
@@ -24,7 +24,7 @@
 Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
   For his Sync-PPP-code.
 
-Karsten Keil (isdn4@temic-ech.spacenet.de)
+Karsten Keil (keil@isdn4linux.de)
   For adding 1TR6-support to the Teles-driver.
   For the HiSax-driver.
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/HiSax.cert linux.pre11.3/Documentation/isdn/HiSax.cert
--- linux.vanilla/Documentation/isdn/HiSax.cert	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/Documentation/isdn/HiSax.cert	Tue Jul 20 00:26:16 1999
@@ -0,0 +1,76 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+First:
+
+    HiSax is free software; you can redistribute it and/or modify
+    it under the terms of the 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.
+
+However, if you wish to modify the HiSax sources, please note the following:
+
+HiSax has passed the ITU approval test suite with ELSA Quickstep ISDN cards.
+The certification is only valid for the combination of the tested software
+version and the tested hardware. Any changes to the HiSax source code may
+therefore affect the certification.
+
+If you change the main files of the HiSax ISDN stack, the certification will
+become invalid. Because in most countries it is illegal to connect
+unapproved ISDN equipment to the public network, I have to guarantee that
+changes in HiSax do not affect the certification.
+
+In order to make a valid certification apparent to the user, I have built in
+some validation checks that are made during the make process. The HiSax main
+files are protected by md5 checksums and the md5sum file is pgp signed by
+myself:
+
+KeyID 1024/FF992F6D 1997/01/16 Karsten Keil <keil@temic-ech.spacenet.de>
+Key fingerprint = 92 6B F7 58 EE 86 28 C8  C4 1A E6 DC 39 89 F2 AA
+
+Only if the checksums are OK, and the signature of the file
+"drivers/isdn/hisax/md5sums.asc" match, is the certification valid; a
+message confirming this is then displayed during the hisax init process.
+
+The affected files are:
+
+drivers/isdn/hisax/isac.c
+drivers/isdn/hisax/isdnl1.c
+drivers/isdn/hisax/isdnl2.c
+drivers/isdn/hisax/isdnl3.c
+drivers/isdn/hisax/tei.c
+drivers/isdn/hisax/callc.c
+drivers/isdn/hisax/l3dss1.c
+drivers/isdn/hisax/l3_1tr6.c
+drivers/isdn/hisax/cert.c
+drivers/isdn/hisax/elsa.c
+
+Please send any changes, bugfixes and patches to me rather than implementing
+them directly into the HiSax sources.
+
+This does not reduce your rights granted by the GNU General Public License.
+If you wish to change the sources, go ahead; but note that then the
+certification is invalid even if you use ELSA Quickstep cards.
+
+Here are the certification registration numbers for ELSA Quickstep cards:
+German   D133361J CETECOM ICT Services GmbH 0682
+European D133362J CETECOM ICT Services GmbH 0682
+
+
+Karsten Keil
+keil@isdn4linux.de
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3i
+Charset: noconv
+
+iQCVAwUBNj5OKDpxHvX/mS9tAQFHuQP/WeImlqCcDZ2d132yAvRBWFULlJoSf1P/
+c1lVTeaWvsSaY5Cu9hrKhXXhPzeEaitUbcUBPXdpzFWCA5CE902lnz7AhgRC+HF1
+0qiKgkZZyc/5HKasFymR1+IWSLw30GesP3Di/ZMR3NJi8SlY9PIjx7hnEMunGSRO
+1ufPvfWWuu8=
+=nGJk
+-----END PGP SIGNATURE-----
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/INTERFACE linux.pre11.3/Documentation/isdn/INTERFACE
--- linux.vanilla/Documentation/isdn/INTERFACE	Sun Nov  8 15:08:48 1998
+++ linux.pre11.3/Documentation/isdn/INTERFACE	Tue Jul 20 00:26:16 1999
@@ -1,4 +1,4 @@
-$Id: INTERFACE,v 1.8 1998/02/20 17:38:20 fritz Exp $
+$Id: INTERFACE,v 1.12 1999/07/13 20:59:59 werner Exp $
 
 Description of the Interface between Linklevel and Hardwarelevel
   of isdn4linux:
@@ -478,6 +478,14 @@
       1           = At least one device matching this call (RING on ttyI).
                     HL-driver may send ALERTING on the D-channel in this case.
       2           = Call will be rejected.
+      3           = Incomplete number.
+                    The CalledNumber would match, if more digits are appended.
+                    This feature is needed for Number-Blocks assigned to
+                    a line. In this case, the LL driver should assemble the
+					CalledNumber by handling keypad protocol and try again
+					later with a longer CalledNumber.
+					HL drivers serving ordinary lines should interpret this
+					return code like 0 (nothing matches).
       -1          = An error happened. (Invalid parameters for example.)
 
   ISDN_STAT_RUN:
@@ -526,7 +534,9 @@
       driver      = driver-Id
       command     = ISDN_STAT_BCONN
       arg         = channel-number, locally to the driver. (starting with 0)
-      para        = unused.
+      para.num    = ASCII-String, containing type of connection (for analog
+		    modem only). This will be appended to the CONNECT message
+		    e.g. 14400/V.32bis
 
   ISDN_STAT_DHUP:
 
@@ -645,3 +655,21 @@
       arg         = channel-number, locally to the driver. (starting with 0)
       para.errcode= ISDN_STAT_L1ERR_SEND:     Packet lost while sending.
 		    ISDN_STAT_L1ERR_RECV:     Packet lost while receiving.
+  ISDN_STAT_DISCH:
+
+    With this call, the HL-driver signals the LL to disable or enable the
+    use of supplied channel and driver.
+    The call may be used to reduce the available number of B-channels after
+    loading the driver. The LL has to ignore a disabled channel when searching
+    for free channels. The HL driver itself never delivers STAT callbacks for
+    disabled channels. 	    
+    The LL returns a nonzero code if the operation was not successfull or the
+    selected channel is actually regarded as busy.
+
+    Parameter:
+      driver      = driver-Id
+      command     = ISDN_STAT_DISCH
+      arg         = channel-number, locally to the driver. (starting with 0)
+      parm.num[0] = 0 if channel shall be disabled, else enabled.
+    
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README linux.pre11.3/Documentation/isdn/README
--- linux.vanilla/Documentation/isdn/README	Sun Nov  8 15:08:48 1998
+++ linux.pre11.3/Documentation/isdn/README	Tue Jul 20 00:26:16 1999
@@ -31,7 +31,7 @@
    This mailinglist is bidirectionally gated to the newsgroup
 
      de.alt.comm.isdn4linux
-   
+
   There is also a well maintained FAQ (both english and german) available
   at ftp.franken.de in /pub/isdn4linux/FAQ/
   This FAQ is also available at http://www.lrz-muenchen.de/~ui161ab/www/isdn/
@@ -41,11 +41,11 @@
   In the following Text, the terms MSN and EAZ are used.
 
   MSN is the abbreviation for (M)ultiple(S)ubscriber(N)umber, and applies
-  to Euro(EDSS1)-type lines. Usually it is simply the phone-number.
+  to Euro(EDSS1)-type lines. Usually it is simply the phone number.
 
   EAZ is the abbreviation of (E)ndgeraete(A)uswahl(Z)iffer and
   applies to German 1TR6-type lines. This is a one-digit string,
-  simply appended to the base phone-number
+  simply appended to the base phone number
 
   The internal handling is nearly identical, so replace the appropriate
   term to that one, which applies to your local ISDN-environment.
@@ -56,13 +56,13 @@
   A low-level-driver can register itself through an interface (which is
   defined in isdnif.h) and gets assigned a slot.
   The following char-devices are made available for each channel:
-  
+
   A raw-control-device with the following functions:
      write: raw D-channel-messages (format: depends on driver).
      read:  raw D-channel-messages (format: depends on driver).
      ioctl: depends on driver, i.e. for the ICN-driver, the base-address of
             the ports and the shared memory on the card can be set and read
-            also the boot-code and the protocol software can be loaded into 
+            also the boot-code and the protocol software can be loaded into
             the card.
 
    O N L Y !!!  for debugging (no locking against other devices):
@@ -74,38 +74,38 @@
 
    128 tty-devices (64 cuix and 64 ttyIx) with integrated modem-emulator:
    The functionality is almost the same as that of a serial device
-   (the line-discs are handled by the kernel), which lets you run 
-   SLIP, CSLIP and asynchronous PPP through the devices. We have tested 
+   (the line-discs are handled by the kernel), which lets you run
+   SLIP, CSLIP and asynchronous PPP through the devices. We have tested
    Seyon, minicom, CSLIP (uri-dip) PPP and mgetty (compiled with NO_FAX),
    XCept.
 
    The modem-emulation supports the following:
            1.3.1 Commands:
 
-               ATA	Answer incoming call.
-	       ATD<No.> Dial, the number may contain:
+               ATA      Answer incoming call.
+               ATD<No.> Dial, the number may contain:
                         [0-9] and [,#.*WPT-S]
                         the latter are ignored until 'S'.
-                        The 'S' must precede the number, if 
+                        The 'S' must precede the number, if
                         the line is a SPV (German 1TR6).
-               ATE0	Echo off.
-	       ATE1     Echo on (default).
+               ATE0     Echo off.
+               ATE1     Echo on (default).
                ATH      Hang-up.
-	       ATH1     Off hook (ignored).
+               ATH1     Off hook (ignored).
                ATH0     Hang-up.
-	       ATI      Return "ISDN for Linux...".
+               ATI      Return "ISDN for Linux...".
                ATI0        "
                ATI1        "
-	       ATI2     Report of last connection.
+               ATI2     Report of last connection.
                ATO      On line (data mode).
                ATQ0     Enable result codes (default).
                ATQ1     Disable result codes (default).
-               ATSx=y	Set register x to y.
-	       ATSx?    Show contents of register x.
+               ATSx=y   Set register x to y.
+               ATSx?    Show contents of register x.
                ATV0     Numeric responses.
                ATV1     English responses (default).
-	       ATZ      Load registers and EAZ/MSN from Profile.
-	       AT&Bx    Set Send-Packet-size to x (max. 4000)
+               ATZ      Load registers and EAZ/MSN from Profile.
+               AT&Bx    Set Send-Packet-size to x (max. 4000)
                         The real packet-size may be limited by the
                         low-level-driver used. e.g. the HiSax-Module-
                         limit is 2000. You will get NO Error-Message,
@@ -114,13 +114,13 @@
                         driver may not be selected (see "Automatic
                         Assignment") however the size of outgoing packets
                         will be limited correctly.
-	       AT&D0    Ignore DTR
-	       AT&D2    DTR-low-edge: Hang up and return to 
+               AT&D0    Ignore DTR
+               AT&D2    DTR-low-edge: Hang up and return to
                         command mode (default).
                AT&D3    Same as AT&D2 but also resets all registers.
-	       AT&Ex    Set the EAZ/MSN for this channel to x.
-	       AT&F     Reset all registers and profile to "factory-defaults"
-	       AT&Rx    Select V.110 bitrate adaption.
+               AT&Ex    Set the EAZ/MSN for this channel to x.
+               AT&F     Reset all registers and profile to "factory-defaults"
+               AT&Rx    Select V.110 bitrate adaption.
                         This command enables V.110 protocol with 9600 baud
                         (x=9600), 19200 baud (x=19200) or 38400 baud
                         (x=38400). A value of x=0 disables V.110 switching
@@ -142,24 +142,24 @@
                             The value 198 is choosen arbitrarily. Users
                             _MUST_ negotiate this value before establishing
                             a connection.
-	       AT&Sx    Set window-size (x = 1..8) (not yet implemented)
-	       AT&V     Show all settings.
+               AT&Sx    Set window-size (x = 1..8) (not yet implemented)
+               AT&V     Show all settings.
                AT&W0    Write registers and EAZ/MSN to profile. See also
                         iprofd (5.c in this README).
-               AT&X0	BTX-mode and T.70-mode off (default)
-	       AT&X1    BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
-	       AT&X2    T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
+               AT&X0    BTX-mode and T.70-mode off (default)
+               AT&X1    BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
+               AT&X2    T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
 
            For voice-mode commands refer to README.audio
 
-	   1.3.2 Escape sequence:
+           1.3.2 Escape sequence:
                During a connection, the emulation reacts just like
                a normal modem to the escape sequence <DELAY>+++<DELAY>.
-	       (The escape character - default '+' - can be set in the
+               (The escape character - default '+' - can be set in the
                register 2).
-               The DELAY must at least be 1.5 seconds long and delay 
+               The DELAY must at least be 1.5 seconds long and delay
                between the escape characters must not exceed 0.5 seconds.
-     
+
            1.3.3 Registers:
 
               Nr.  Default  Description
@@ -172,7 +172,7 @@
               4    10       Line feed character (ASCII).
               5    8        Backspace character (ASCII).
               6    3        Delay in seconds before dialing.
-              7    60       Wait for carrier (ignored).
+              7    60       Wait for carrier.
               8    2        Pause time for comma (ignored)
               9    6        Carrier detect time (ignored)
              10    7        Carrier loss to disconnect time (ignored).
@@ -203,8 +203,8 @@
                                       1 = T.70 protocol (Only for BTX!) on
                             Bit 2:    0 = Don't hangup on DTR low.
                                       1 = Hangup on DTR low.
-			    Bit 3:    0 = Standard response messages
-				      1 = Extended response messages
+                            Bit 3:    0 = Standard response messages
+                                      1 = Extended response messages
                             Bit 4:    0 = CALLER NUMBER before every RING.
                                       1 = CALLER NUMBER after first RING.
                             Bit 5:    0 = T.70 extended protocol off
@@ -215,18 +215,25 @@
                                           an incoming call happened (RING) and
                                           the remote party hung up before any
                                           local ATA was given.
-	     14   0         Layer-2 protocol:
-				      0 = X75/LAPB with I-frames
-				      1 = X75/LAPB with UI-frames
+			    Bit 7:    0 = Don't show display messages from net
+                                      1 = Show display messages from net
+				          (S12 Bit 1 must be 0 too)      
+             14   0         Layer-2 protocol:
+                                      0 = X75/LAPB with I-frames
+                                      1 = X75/LAPB with UI-frames
                                       2 = X75/LAPB with BUI-frames
                                       3 = HDLC
                                       4 = Transparent (audio)
                                       7 = V.110, 9600 baud
                                       8 = V.110, 19200 baud
                                       9 = V.110, 38400 baud
-             15   0         Layer-3 protocol: (at the moment always 0)
+                                     10 = Analog Modem (only if hardware supports this)
+                                     11 = Fax G3 (only if hardware supports this)
+             15   0         Layer-3 protocol:
                                       0 = transparent
-	     16   250       Send-Packet-size/16
+                                      1 = transparent with audio features (e.g. DSP)
+                                      2 = Fax G3 (S14 has to be set to 11)
+             16   250       Send-Packet-size/16
              17   8         Window-size (not yet implemented)
              18   4         Bit coded register, Service-Octet-1 to accept,
                             or to be used on dialout:
@@ -254,6 +261,9 @@
                             Set on incoming call (during RING) to
                             octet 3a of calling party number IE (Screening info)
                             See section 4.5.10 of ITU Q.931
+             23   0         Bit coded register:
+                            Bit 0:    0 = Add CPN to RING message off
+                                      1 = Add CPN to RING message on
 
   Last but not least a (at the moment fairly primitive) device to request
   the line-status (/dev/isdninfo) is made available.
@@ -262,7 +272,7 @@
 
   All inactive physical lines are listening to all EAZs for incoming
   calls and are NOT assigned to a specific tty or network interface.
-  When an incoming call is detected, the driver looks first for a network 
+  When an incoming call is detected, the driver looks first for a network
   interface and then for an opened tty which:
 
   1. is configured for the same EAZ.
@@ -270,7 +280,7 @@
   3. (only for network interfaces if the security flag is set)
      contains the caller number in its access list.
   4. Either the channel is not bound exclusively to another Net-interface, or
-     it is bound AND the other checks apply to exactly this Interface.
+     it is bound AND the other checks apply to exactly this interface.
      (For usage of the bind-features, refer to the isdnctrl-man-page)
 
   Only when a matching interface or tty is found is the call accepted
@@ -301,7 +311,7 @@
   Always use the latest module utilities. The current version is
   named in Documentation/Changes. Some old versions of insmod
   are not capable of setting the driver-Ids correctly.
- 
+
 3. Lowlevel-driver configuration.
 
    Configuration depends on how the drivers are built. See the
@@ -310,7 +320,7 @@
 4. Device-inodes
 
    The major and minor numbers and their names are described in
-   Documentation/devices.txt. The major-numbers are:
+   Documentation/devices.txt. The major numbers are:
 
      43 for the ISDN-tty's.
      44 for the ISDN-callout-tty's.
@@ -350,45 +360,64 @@
    g) Set the timeout for hang-up:
        isdnctrl huptimeout isdn0 <timeout_in_seconds>
 
-   h) additionally you may activate charge-hang-up (= Hang up before 
+   h) additionally you may activate charge-hang-up (= Hang up before
       next charge-info, this only works, if your isdn-provider transmits
       the charge-info during and after the connection):
        isdnctrl chargehup isdn0 on
 
-   i) Setup the interface with ifconfig as usual, and set a route to it.
+   i) Set the dial mode of the interface:
+       isdnctrl dialmode isdn0 auto
+      "off" means that you (or the system) cannot make any connection
+        (neither incoming or outgoing connections are possible). Use
+        this if you want to be sure that no connections will be made.
+      "auto" means that the interface is in auto-dial mode, and will
+        attempt to make a connection whenever a network data packet needs
+        the interface's link. Note that this can cause unexpected dialouts,
+        and lead to a high phone bill! Some daemons or other pc's that use
+        this interface can cause this.
+        Incoming connections are also possible.
+      "manual" is a dial mode created to prevent the unexpected dialouts.
+        In this mode, the interface will never make any connections on its
+        own. You must explicitly initiate a connection with "isdnctrl dial
+        isdn0". However, after an idle time of no traffic as configured for
+	the huptimeout value with isdnctrl, the connection _will_ be ended.
+	If you don't want any automatic hangup, set the huptimeout value to 0.
+        "manual" is the default.
 
-   j) (optional) If you run X11 and have Tcl/Tk-wish Version 4.0, you can use
+   j) Setup the interface with ifconfig as usual, and set a route to it.
+
+   k) (optional) If you run X11 and have Tcl/Tk-wish version 4.0, you can use
      the script tools/tcltk/isdnmon. You can add actions for line-status
      changes. See the comments at the beginning of the script for how to
      do that. There are other tty-based tools in the tools-subdirectory
      contributed by Michael Knigge (imon), Volker Götz (imontty) and
      Andreas Kool (isdnmon).
 
-   k) For initial testing, you can set the verbose-level to 2 (default: 0).
+   l) For initial testing, you can set the verbose-level to 2 (default: 0).
       Then all incoming calls are logged, even if they are not addressed
       to one of the configured net-interfaces:
       isdnctrl verbose 2
 
-  Now you are ready! A ping to the set address should now result in a
-  dial-out (look at syslog kernel-messages).
-  The phone-numbers and EAZs can be assigned at any time with isdnctrl.
+  Now you are ready! A ping to the set address should now result in an
+  automatic dial-out (look at syslog kernel-messages).
+  The phone numbers and EAZs can be assigned at any time with isdnctrl.
   You can add as many interfaces as you like with addif following the
-  directions above. Of course, there may be some limitations. But we have 
-  tested as many as 20 interfaces without any problem. However, if you 
-  don't give an interface name to addif, the  kernel will assign a name 
+  directions above. Of course, there may be some limitations. But we have
+  tested as many as 20 interfaces without any problem. However, if you
+  don't give an interface name to addif, the  kernel will assign a name
   which starts with "eth". The number of "eth"-interfaces is limited by
   the kernel.
 
 5. Additional options for isdnctrl:
 
-   "isdnctrl secure <InterfaceName> on" 
+   "isdnctrl secure <InterfaceName> on"
    Only incoming calls, for which the caller-id is listed in the access
    list of the interface are accepted. You can add caller-id's With the
    command "isdnctrl addphone <InterfaceName> in <caller-id>"
    Euro-ISDN does not transmit the leading '0' of the caller-id for an
    incoming call, therefore you should configure it accordingly.
    If the real number for the dialout e.g. is "09311234567" the number
-   to configure here is "9311234567". The pattern-match function 
+   to configure here is "9311234567". The pattern-match function
    works similar to the shell mechanism.
 
      ?     one arbitrary digit
@@ -398,23 +427,23 @@
            a '^' as the first character in a list inverts the list
 
 
-   "isdnctrl secure <InterfaceName> off" 
+   "isdnctrl secure <InterfaceName> off"
    Switch off secure operation (default).
 
-   "isdnctrl ihup <InterfaceName> [on|off]" 
+   "isdnctrl ihup <InterfaceName> [on|off]"
    Switch the hang-up-timer for incoming calls on or off.
 
-   "isdnctrl eaz <InterfaceName>" 
+   "isdnctrl eaz <InterfaceName>"
    Returns the EAZ of an interface.
 
-   "isdnctrl delphone <InterfaceName> in|out <number>" 
+   "isdnctrl delphone <InterfaceName> in|out <number>"
    Deletes a number from one of the access-lists of the interface.
 
-   "isdnctrl delif <InterfaceName>" 
+   "isdnctrl delif <InterfaceName>"
    Removes the interface (and possible slaves) from the kernel.
    (You have to unregister it with "ifconfig <InterfaceName> down" before).
 
-   "isdnctrl callback <InterfaceName> [on|off]" 
+   "isdnctrl callback <InterfaceName> [on|off]"
    Switches an interface to callback-mode. In this mode, an incoming call
    will be rejected and after this the remote-station will be called. If
    you test this feature by using ping, some routers will re-dial very
@@ -435,14 +464,14 @@
    only while an interface is down.
 
    At the moment the following values are supported:
- 
+
    rawip    (Default) Selects raw-IP-encapsulation. This means, MAC-headers
-            are stripped off.  
+            are stripped off.
    ip       IP with type-field. Same as IP but the type-field of the MAC-header
             is preserved.
    x25iface X.25 interface encapsulation (first byte semantics as defined in
-	    ../networking/x25-iface.txt). Use this for running the linux
-	    X.25 network protocol stack (AF_X25 sockets) on top of isdn.
+            ../networking/x25-iface.txt). Use this for running the linux
+            X.25 network protocol stack (AF_X25 sockets) on top of isdn.
    cisco-h  A special-mode for communicating with a Cisco, which is configured
             to do "hdlc"
    ethernet No stripping. Packets are sent with full MAC-header.
@@ -454,7 +483,7 @@
 
 
    NOTE:    x25iface encapsulation is currently experimental. Please
-	    read README.x25 for further details    
+            read README.x25 for further details
 
 
    Watching packets, using standard-tcpdump will fail for all encapsulations
@@ -462,16 +491,16 @@
    without MAC-header. A patch for tcpdump is included in the utility-package
    mentioned above.
 
-   "isdnctrl l2_prot <InterfaceName> <L2-ProtocolName>" 
-   Selects a layer-2-protocol. 
+   "isdnctrl l2_prot <InterfaceName> <L2-ProtocolName>"
+   Selects a layer-2-protocol.
    (With the ICN-driver and the HiSax-driver, "x75i" and "hdlc" is available.
    With other drivers, "x75ui", "x75bui", "x25dte", "x25dce" may be
    possible too. See README.x25 for x25 related l2 protocols.)
 
-   isdnctrl l3_prot <InterfaceName> <L3-ProtocolName> 
+   isdnctrl l3_prot <InterfaceName> <L3-ProtocolName>
    The same for layer-3. (At the moment only "trans" is allowed)
 
-   "isdnctrl list <InterfaceName>" 
+   "isdnctrl list <InterfaceName>"
    Shows all parameters of an interface and the charge-info.
    Try "all" as the interface name.
 
@@ -479,13 +508,13 @@
    Forces hangup of an interface.
 
    "isdnctrl bind <InterfaceName> <DriverId>,<ChannelNumber> [exclusive]"
-   If you are using more than one ISDN-Card, it is sometimes necessary to
-   dial out using a specific Card or even preserve a specific Channel for
-   Dialout of a specific net-interface. This can be done with the above
+   If you are using more than one ISDN card, it is sometimes necessary to
+   dial out using a specific card or even preserve a specific channel for
+   dialout of a specific net-interface. This can be done with the above
    command. Replace <DriverId> by whatever you assigned while loading the
-   module. The <ChannelNumber> is counting from zero. The upper Limit
-   depends on the card used. At the Moment no card supports more than
-   2 Channels, so the upper limit is one.
+   module. The <ChannelNumber> is counted from zero. The upper limit
+   depends on the card used. At the moment no card supports more than
+   2 channels, so the upper limit is one.
 
    "isdnctrl unbind <InterfaceName>"
    unbinds a previously bound interface.
@@ -494,10 +523,10 @@
    If switched on, isdn4linux replies a REJECT to incoming calls, it
    cannot match to any configured interface.
    If switched off, nothing happens in this case.
-   You normally should NOT enable this feature, if the ISDN-adaptor is not
-   the only device, connected to the S0-bus. Otherwise it could happen, that
+   You normally should NOT enable this feature, if the ISDN adapter is not
+   the only device connected to the S0-bus. Otherwise it could happen that
    isdn4linux rejects an incoming call, which belongs to another device on
-   the bus. 
+   the bus.
 
    "isdnctrl addslave <InterfaceName> <SlaveName>
    Creates a slave interface for channel-bundling. Slave interfaces are
@@ -539,9 +568,9 @@
    isdnctrl eaz isdn1 4      # listen on 12345674(1tr6) only.
    ...
    isdnctrl eaz isdn2 987654 # listen on 987654(euro) only.
-   
+
    Same scheme is used with AT&E...  at the tty's.
-  
+
 6. If you want to write a new low-level-driver, you are welcome.
    The interface to the link-level-module is described in the file INTERFACE.
    If the interface should be expanded for any reason, don't do it
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.HiSax linux.pre11.3/Documentation/isdn/README.HiSax
--- linux.vanilla/Documentation/isdn/README.HiSax	Sun Nov  8 15:08:48 1998
+++ linux.pre11.3/Documentation/isdn/README.HiSax	Tue Jul 20 00:26:16 1999
@@ -1,7 +1,7 @@
 HiSax is a Linux hardware-level driver for passive ISDN cards with Siemens
 chipset (ISAC_S 2085/2086/2186, HSCX SAB 82525). It is based on the Teles
 driver from Jan den Ouden.
-It is meant to be used with isdn4linux, an ISDN link-level module for Linux 
+It is meant to be used with isdn4linux, an ISDN link-level module for Linux
 written by Fritz Elfert.
 
     This program is free software; you can redistribute it and/or modify
@@ -25,31 +25,50 @@
 Teles 8.0/16.0/16.3 and compatible ones
 Teles 16.3c
 Teles S0/PCMCIA
-Creatix PnP S0 
+Teles PCI
+Teles S0Box
+Creatix S0Box
+Creatix PnP S0
 Compaq ISDN S0 ISA card
 AVM A1 (Fritz, Teledat 150)
+AVM Fritz PCMCIA
+AVM Fritz PnP
+AVM Fritz PCI
 ELSA Microlink PCC-16, PCF, PCF-Pro, PCC-8
 ELSA Quickstep 1000
 ELSA Quickstep 1000PCI
 ELSA Quickstep 3000 (same settings as QS1000)
+ELSA Quickstep 3000PCI
 ELSA PCMCIA
 ITK ix1-micro Rev.2
 Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
+Eicon.Diehl Diva 2.01 ISA and PCI
 Eicon.Diehl Diva Piccola
 ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
 Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
+PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink)
 HFC-2BS0 based cards (TeleInt SA1)
-Sedlbauer Speed Card (Speed Win, Teledat 100)
-Sedlbauer Speed Star (PCMCIA)
+Sedlbauer Speed Card (Speed Win, Teledat 100, PCI, Fax+)
+Sedlbauer Speed Star/Speed Star2 (PCMCIA)
+Sedlbauer ISDN-Controller PC/104
 USR Sportster internal TA (compatible Stollmann tina-pp V3)
-ith Kommunikationstechnik GmbH MIC 16 ISA card 
+ith Kommunikationstechnik GmbH MIC 16 ISA card
 Traverse Technologie NETjet PCI S0 card
 Dr. Neuhaus Niccy PnP/PCI
+Siemens I-Surf
+ACER P10
+HST Saphir
+Berkom Telekom A4T
+Scitel Quadro
+Gazel ISDN cards
+HFC-PCI based cards
 
 Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
       PCC-8: not tested yet
       Teles PCMCIA is EXPERIMENTAL
       Teles 16.3c is EXPERIMENTAL
+      Teles PCI is EXPERIMENTAL
+      Teles S0Box is EXPERIMENTAL
       Eicon.Diehl Diva U interface not tested
 
 If you know other passive cards with the Siemens chipset, please let me know.
@@ -113,7 +132,7 @@
 correct one during kernel config. Valid values are "1" for German 1TR6,
 "2" for EDSS1 (Euro ISDN) and "3" for leased lines (no D-Channel).
 
-The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying 
+The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying
 the I/O addresses of the ISAC and HSCX chips, respectively.
 
 Card types:
@@ -135,24 +154,37 @@
    11   Eicon.Diehl Diva ISA PnP irq, io
    11   Eicon.Diehl Diva PCI     no parameter
    12   ASUS COM ISDNLink        irq, io  (from isapnp setup)
-   13   HFC-2BS0 based cards     irq, io  
+   13   HFC-2BS0 based cards     irq, io
    14   Teles 16.3c PnP          irq, io
-   15   Sedlbauer Speed Card     irq, io  
-   16   USR Sportster internal   irq, io  
-   17   MIC card                 irq, io  
+   15   Sedlbauer Speed Card     irq, io
+   15   Sedlbauer PC/104         irq, io
+   15   Sedlbauer Speed PCI	 no parameter
+   16   USR Sportster internal   irq, io
+   17   MIC card                 irq, io
    18   ELSA Quickstep 1000PCI   no parameter
    19   Compaq ISDN S0 ISA card  irq, io0, io1, io (from isapnp setup io=IO2)
    20   NETjet PCI card          no parameter
+   21   Teles PCI                no parameter
    22   Sedlbauer Speed Star (PCMCIA) irq, io (set with card manager)
    24   Dr. Neuhaus Niccy PnP    irq, io0, io1 (from isapnp setup)
    24   Dr. Neuhaus Niccy PCI    no parameter
+   25   Teles S0Box              irq, io (of the used lpt port)
+   26   AVM A1 PCMCIA (Fritz!)   irq, io (set with card manager)
+   27   AVM PnP (Fritz!PnP)      irq, io  (from isapnp setup)
+   27   AVM PCI (Fritz!PCI)      no parameter
+   28   Sedlbauer Speed Fax+     irq, io (from isapnp setup)
+   29	Siemens I-Surf           irq, io, memory (from isapnp setup)   
+   30	ACER P10                 irq, io (from isapnp setup)   
+   31	HST Saphir               irq, io
+   32	Telekom A4T              none
+   33	Scitel Quadro		 subcontroller (4*S0, subctrl 1...4)
+   34	Gazel ISDN cards (ISA)   irq,io
+   34	Gazel ISDN cards (PCI)   none
+   35	HFC 2BDS0 PCI            none
 
 
-        
-At the moment IRQ sharing is not possible. Please make sure that your IRQ
-is free and enabled for ISA use.
-Note: For using the ELSA PCMCIA you need the cardmanager under MSDOS for
-enabling at the moment, then boot linux with loadlin.
+At the moment IRQ sharing is only possible with PCI cards. Please make sure
+that your IRQ is free and enabled for ISA use.
 
 
 Examples for module loading
@@ -169,7 +201,7 @@
 4. Any ELSA PCC/PCF card, Euro ISDN
    modprobe hisax type=6 protocol=2
 
-5. Teles 16.3 PnP, Euro ISDN, with isapnp configured 
+5. Teles 16.3 PnP, Euro ISDN, with isapnp configured
    isapnp config:  (INT 0 (IRQ 10 (MODE +E)))
  		   (IO 0 (BASE 0x0580))
                    (IO 1 (BASE 0x0180))
@@ -210,8 +242,8 @@
                 Note: the ID string must start with an alphabetical character!
 
 Card types:
-       
-  type  
+
+type
     1 	Teles 16.0     	        pa=irq  pb=membase  pc=iobase
     2 	Teles  8.0              pa=irq  pb=membase
     3 	Teles 16.3              pa=irq  pb=iobase
@@ -227,22 +259,40 @@
    12   ASUS COM ISDNLink       ONLY WORKS AS A MODULE !
    13	HFC-2BS0 based cards    pa=irq  pb=io
    14   Teles 16.3c PnP         ONLY WORKS AS A MODULE !
-   15	Sedlbauer Speed Card    pa=irq  pb=io (Speed Win only as module !)  
+   15	Sedlbauer Speed Card    pa=irq  pb=io (Speed Win only as module !)
+   15   Sedlbauer PC/104        pa=irq  pb=io
+   15   Sedlbauer Speed PCI	no parameter
    16   USR Sportster internal  pa=irq  pb=io
    17   MIC card                pa=irq  pb=io
    18   ELSA Quickstep 1000PCI  no parameter
    19   Compaq ISDN S0 ISA card ONLY WORKS AS A MODULE !
    20   NETjet PCI card         no parameter
-   21   Sedlbauer Speed Star (PCMCIA)  pa=irq, pb=io  (set with card manager)
+   21   Teles PCI               no parameter
+   22   Sedlbauer Speed Star (PCMCIA)  pa=irq, pb=io  (set with card manager)
+   24   Dr. Neuhaus Niccy PnP   ONLY WORKS AS A MODULE !
+   24   Dr. Neuhaus Niccy PCI   no parameter
+   25   Teles S0Box             pa=irq, pb=io (of the used lpt port)
+   26   AVM A1 PCMCIA (Fritz!)  pa=irq, pb=io (set with card manager)
+   27   AVM PnP (Fritz!PnP)     ONLY WORKS AS A MODULE !
+   27   AVM PCI (Fritz!PCI)     no parameter
+   28   Sedlbauer Speed Fax+    ONLY WORKS AS A MODULE !
+   29	Siemens I-Surf          ONLY WORKS AS A MODULE !
+   30	ACER P10                ONLY WORKS AS A MODULE !
+   31	HST Saphir              pa=irq, pb=io
+   32	Telekom A4T             no parameter
+   33	Scitel Quadro		subcontroller (4*S0, subctrl 1...4)
+   34	Gazel ISDN cards (ISA)  pa=irq, pb=io
+   34	Gazel ISDN cards (PCI)  no parameter
+   35	HFC 2BDS0 PCI           no parameter
 
 Running the driver
 ------------------
 
-When you insmod isdn.o and hisax.o (or with the in-kernel version, during 
+When you insmod isdn.o and hisax.o (or with the in-kernel version, during
 boot time), a few lines should appear in your syslog. Look for something like:
 
 Apr 13 21:01:59 kke01 kernel: HiSax: Driver for Siemens chip set ISDN cards
-Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.1
+Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.9
 Apr 13 21:01:59 kke01 kernel: HiSax: Revisions 1.14/1.9/1.10/1.25/1.8
 Apr 13 21:01:59 kke01 kernel: HiSax: Total 1 card defined
 Apr 13 21:01:59 kke01 kernel: HiSax: Card 1 Protocol EDSS1 Id=HiSax1 (0)
@@ -257,7 +307,7 @@
 Apr 13 21:01:59 kke01 kernel: HiSax: 2 channels added
 
 This means that the card is ready for use.
-Cabling problems or line-downs are not detected, and only some ELSA cards can 
+Cabling problems or line-downs are not detected, and only some ELSA cards can
 detect the S0 power.
 
 Remember that, according to the new strategy for accessing low-level drivers
@@ -265,8 +315,7 @@
 insmod: Simply append hisax_id=<SomeString> to the insmod command line. This
 string MUST NOT start with a digit or a small 'x'!
 
-At this point you can run a 'cat /dev/isdnctrl0' and view debugging 
-messages. 
+At this point you can run a 'cat /dev/isdnctrl0' and view debugging messages.
 
 At the moment, debugging messages are enabled with the hisaxctrl tool:
 
@@ -283,28 +332,35 @@
 
 With DebugCmd set to 1:
 
-         1  Link-level <--> hardware-level communication
-         2  Top state machine
-         4  D-Channel Q.931 (call control messages)
-         8  D-Channel Q.921
-        16  B-Channel X.75
-        32  D-Channel l2
-        64  B-Channel l2
-       128  D-Channel link state debugging
-       256  B-Channel link state debugging
-       512  TEI debug
-      1024  LOCK debug in callc.c
-      2048  More paranoid debug in callc.c (not for normal use)
+   0x0001  Link-level <--> hardware-level communication
+   0x0002  Top state machine
+   0x0004  D-Channel Frames for isdnlog
+   0x0008  D-Channel Q.921
+   0x0010  B-Channel X.75
+   0x0020  D-Channel l2
+   0x0040  B-Channel l2
+   0x0080  D-Channel link state debugging
+   0x0100  B-Channel link state debugging
+   0x0200  TEI debug
+   0x0400  LOCK debug in callc.c
+   0x0800  More paranoid debug in callc.c (not for normal use)
+   0x1000  D-Channel l1 state debugging
+   0x2000  B-Channel l1 state debugging
 
 With DebugCmd set to 11:
 
-         1  Warnings (default: on)
-         2  IRQ status
-         4  ISAC
-         8  ISAC FIFO
-        16  HSCX
-        32  HSCX FIFO (attention: full B-Channel output!)
-        64  D-Channel LAPD frame types
+   0x0001  Warnings (default: on)
+   0x0002  IRQ status
+   0x0004  ISAC
+   0x0008  ISAC FIFO
+   0x0010  HSCX
+   0x0020  HSCX FIFO (attention: full B-Channel output!)
+   0x0040  D-Channel LAPD frame types
+   0x0080  IPAC debug
+   0x0100  HFC receive debug
+   0x0200  ISAC monitor debug
+   0x0400  D-Channel frames for isdnlog (set with 1 0x4 too)
+   0x0800  D-Channel message verbose
 
 With DebugCmd set to 13:
 
@@ -317,27 +373,39 @@
 
 Because of some obscure problems with some switch equipment, the delay
 between the CONNECT message and sending the first data on the B-channel is now
-configurable with 
+configurable with
 
 hisaxctrl <DriverId> 2 <delay>
 <delay> in ms Value between 50 and 800 ms is recommended.
 
+Downloading Firmware
+--------------------
+At the moment, the Sedlbauer speed fax+ is the only card, which
+needs to download firmware.
+The firmware is downloaded with the hisaxctrl tool:
+
+    hisaxctrl <DriverId> 9 <firmware_filename>
+
+<DriverId> default is HiSax, if you didn't specify one,
+
+where <firmware_filename> is the filename of the firmware file.
+
+For example, 'hisaxctrl HiSax 9 ISAR.BIN' downloads the firmware for
+ISAR based cards (like the Sedlbauer speed fax+).
 
 Warning
 -------
-HiSax is a work in progress and may crash your machine. It has not been
-certified and therefore operation on your PTT's ISDN network is probably
-illegal.
-
+HiSax is a work in progress and may crash your machine.
+For certification look at HiSax.cert file.
 
 Limitations
 -----------
 At this time, HiSax only works on Euro ISDN lines and German 1TR6 lines.
-For leased lines see appendix. 
+For leased lines see appendix.
 
-Bugs 
+Bugs
 ----
-If you find any, please let me know. 
+If you find any, please let me know.
 
 
 Thanks
@@ -354,8 +422,10 @@
 	Stephan von Krawczynski
 	Juergen Quade for the Leased Line part
 	Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE), for ELSA PCMCIA support
+	Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff
+	Ton van Rosmalen for Teles PCI
         and more people who are hunting bugs. (If I forgot somebody, please
-	send me a mail). 
+	send me a mail).
 
         Firma ELSA GmbH
         Firma Eicon.Diehl GmbH
@@ -364,20 +434,23 @@
 	Firma S.u.S.E
 	Firma ith Kommunikationstechnik GmbH
 	Firma Traverse Technologie Australia
-        
+	Firma Medusa GmbH  (www.medusa.de).
+	Firma Quant-X Austria for sponsoring a DEC Alpha board+CPU
+	Firma Cologne Chip Designs GmbH
+
         My girl friend and partner in life Ute for her patience with me.
 
 
 Enjoy,
 
-Karsten Keil   
-keil@temic-ech.spacenet.de
+Karsten Keil
+keil@isdn4linux.de
 
 
 Appendix: Teles PCMCIA driver
 -----------------------------
 
-See 
+See
    http://www.stud.uni-wuppertal.de/~ea0141/pcmcia.html
 for instructions.
 
@@ -451,7 +524,7 @@
       /sbin/isdnctrl l2_prot isdn0 hdlc
       # Attention you must not set an outgoing number !!! This won't work !!!
       # The incomming number is LEASED0 for the first card, LEASED1 for the
-      # second and so on. 
+      # second and so on.
       /sbin/isdnctrl addphone isdn0 in LEASED0
       # Here is no need to bind the channel.
    c) in case the remote partner is a CISCO:
@@ -461,11 +534,11 @@
    e) set the routes
       /sbin/route add -host ${REMOTE_IP} isdn0
       /sbin/route add default gw ${REMOTE_IP}
-   f) switch the card into leased mode for each used B-channel 
+   f) switch the card into leased mode for each used B-channel
       /sbin/hisaxctrl HiSax 5 1
- 
+
 Remarks:
-a) If you have a CISCO don't forget to switch off the KEEP ALIVE option!
+a) Use state of the art isdn4k-utils
 
 Here an example script:
 #!/bin/sh
@@ -517,6 +590,7 @@
 			/sbin/isdnctrl encap isdn0s cisco-h
 		fi
 	fi
+	/sbin/isdnctrl dialmode isdn0 manual
 	# configure tcp/ip
 	/sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP}
 	/sbin/route add -host ${REMOTE_IP} isdn0
@@ -526,6 +600,7 @@
 	/sbin/hisaxctrl HiSax 5 1
         if [ ${I4L_LEASED_128K} = "yes" ]; then
 		# B-CHANNEL 2
+		sleep 10; /* Wait for master */
 		/sbin/hisaxctrl HiSax 5 2
 	fi
 	;;
@@ -547,4 +622,3 @@
 	exit 1
 esac
 exit 0
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.act2000 linux.pre11.3/Documentation/isdn/README.act2000
--- linux.vanilla/Documentation/isdn/README.act2000	Sat Jan  9 21:50:34 1999
+++ linux.pre11.3/Documentation/isdn/README.act2000	Tue Jul 20 00:26:16 1999
@@ -1,4 +1,4 @@
-$Id: README.act2000,v 1.1 1997/09/24 23:50:16 fritz Exp $
+$Id: README.act2000,v 1.2 1998/04/29 19:49:06 he Exp $
 
 This document describes the ACT2000 driver for the
 IBM Active 2000 ISDN card.
@@ -7,7 +7,7 @@
 Version. Currently, only the ISA-Bus version of the card is supported.
 However MCA and PCMCIA will follow soon.
 
-The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
+The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set
 manually using the DIP switches.
 
 Setting up the DIP switches for the IBM Active 2000 ISDN card:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.audio linux.pre11.3/Documentation/isdn/README.audio
--- linux.vanilla/Documentation/isdn/README.audio	Sun Nov  8 15:08:48 1998
+++ linux.pre11.3/Documentation/isdn/README.audio	Tue Jul 20 00:26:16 1999
@@ -1,4 +1,4 @@
-$Id: README.audio,v 1.5 1997/02/23 23:53:46 fritz Exp $
+$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $
 
 ISDN subsystem for Linux.
   Description of audio mode.
@@ -50,13 +50,25 @@
                          the application. See below for data format
 
         AT+VSD=x,y       Set silence-detection parameters.
-                         NO EFFECT, supported for compatibility
-                         only. Possible parameters:
-                           x = 0 ... 31
-                           y = 0 ... 255
+                         Possible parameters:
+                           x = 0 ... 31  sensitivity threshold level.
+                                         (default 0 , deactivated)
+                           y = 0 ... 255 range of interval in units
+                                         of 0.1 second. (default 70)
         AT+VSD=?         Report possible parameters.
         AT+VSD?          Show current parameters.
 
+        AT+VDD=x,y       Set DTMF-detection parameters.
+                         Only possible if online and during this connection.
+                         Possible parameters:
+                           x = 0 ... 15  sensitivity threshold level.
+                                         (default 0 , I4L soft-decode)
+                                         (1-15 soft-decode off, hardware on)
+                           y = 0 ... 255 tone duration in units of 5ms.
+                                         Not for I4L soft decode (default 8, 40ms)
+        AT+VDD=?         Report possible parameters.
+        AT+VDD?          Show current parameters.
+
         AT+VSM=x         Select audio data format.
                          Possible parameters:
                            2 = ADPCM-2
@@ -102,13 +114,14 @@
     <DLE>C                  Touchtone "C" received.
     <DLE>D                  Touchtone "D" received.
 
+    <DLE>q                  quiet. Silence detected after non-silence.
+    <DLE>s                  silence. Silence detected from the
+                            start of recording.
+
     Currently unsupported DLE sequences:
 
     <DLE>c                  FAX calling tone received.
     <DLE>b                  busy tone received.
-    <DLE>q                  quiet. Silence detected after non-silence.
-    <DLE>s                  silence. Silence detected from the
-                            start of recording.
 
   Audio playback.
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.avmb1 linux.pre11.3/Documentation/isdn/README.avmb1
--- linux.vanilla/Documentation/isdn/README.avmb1	Sun Nov  8 15:08:48 1998
+++ linux.pre11.3/Documentation/isdn/README.avmb1	Tue Jul 20 00:26:16 1999
@@ -1,10 +1,22 @@
+Driver for active AVM Controller.
+
 The driver provides a kernel capi2.0 Interface (kernelcapi) and
 on top of this a User-Level-CAPI2.0-interface (capi)
 and a driver to connect isdn4linux with CAPI2.0 (capidrv).
+The lowlevel interface can be used to implement a CAPI2.0
+also for passive cards since July 1999.
 
-The Author can be reached at calle@calle.in-berlin.de
-The command avmcapictrl is part of the isdn4linux-utils.
-t4-files can be found at ftp.avm.de.
+The author can be reached at calle@calle.in-berlin.de.
+The command avmcapictrl is part of the isdn4k-utils.
+t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware
+
+Currently supported cards:
+	B1 ISA (all versions)
+	B1 PCI
+	T1/T1B (HEMA card)
+	M1
+	M2
+	B1 PCMCIA
 
 Installing
 ----------
@@ -26,32 +38,145 @@
 AVM GmbH provides several t4-files for the different D-channel
 protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn.
 
-If you do not compile the driver as modules, you have to add the
-card(s) and load them after booting:
-
-avmcapictrl add 0x150 15
-avmcapictrl load /lib/isdn/b1.t4 1
-
-if you configure as modules you have two possibilities:
+if you configure as modules load the modules this way:
 
 insmod /lib/modules/current/misc/capiutil.o
-insmod /lib/modules/current/misc/kernelcapi.o portbase=0x150 irq=15
+insmod /lib/modules/current/misc/b1.o
+insmod /lib/modules/current/misc/kernelcapi.o
 insmod /lib/modules/current/misc/capidrv.o
 insmod /lib/modules/current/misc/capi.o
-avmcapictrl load /lib/isdn/b1.t4
 
-or
+if you have an B1-PCI card load the module b1pci.o
+insmod /lib/modules/current/misc/b1pci.o
+and load the firmware with
+avmcapictrl load /lib/isdn/b1.t4 1
 
-insmod /lib/modules/current/misc/capiutil.o
-insmod /lib/modules/current/misc/kernelcapi.o
-insmod /lib/modules/current/misc/capidrv.o
-insmod /lib/modules/current/misc/capi.o
+if you have an B1-ISA card load the module b1isa.o
+and add the card by calling
 avmcapictrl add 0x150 15
-avmcapictrl load /lib/isdn/b1.t4
+and load the firmware by calling
+avmcapictrl load /lib/isdn/b1.t4 1
+
+if you have an T1-ISA card load the module t1isa.o
+and add the card by calling
+avmcapictrl add 0x450 15 T1 0
+and load the firmware by calling
+avmcapictrl load /lib/isdn/t1.t4 1
+
+if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o
+before you insert the card.
+
+Leased Lines with B1
+--------------------
+Init card and load firmware.
+For an D64S use "FV: 1" as phone number
+For an D64S2 use "FV: 1" and "FV: 2" for multilink
+or "FV: 1,2" to use CAPI channel bundling.
+
+/proc-Interface
+-----------------
+
+/proc/capi:
+  dr-xr-xr-x   2 root     root            0 Jul  1 14:03 .
+  dr-xr-xr-x  82 root     root            0 Jun 30 19:08 ..
+  -r--r--r--   1 root     root            0 Jul  1 14:03 applications
+  -r--r--r--   1 root     root            0 Jul  1 14:03 applstats
+  -r--r--r--   1 root     root            0 Jul  1 14:03 capi20
+  -r--r--r--   1 root     root            0 Jul  1 14:03 capidrv
+  -r--r--r--   1 root     root            0 Jul  1 14:03 controller
+  -r--r--r--   1 root     root            0 Jul  1 14:03 contrstats
+  -r--r--r--   1 root     root            0 Jul  1 14:03 driver
+  -r--r--r--   1 root     root            0 Jul  1 14:03 ncci
+  -r--r--r--   1 root     root            0 Jul  1 14:03 users
+
+/proc/capi/applications:
+   applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen
+	level3cnt: capi_register parameter
+	datablkcnt: capi_register parameter
+	ncci-cnt: current number of nccis (connections)
+	recvqueuelen: number of messages on receive queue
+   for example:
+1 -2 16 2048 1 0
+2 2 7 2048 1 0
+
+/proc/capi/applstats:
+   applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg
+	recvctlmsg: capi messages received without DATA_B3_IND
+	recvdatamsg: capi DATA_B3_IND received
+	sentctlmsg: capi messages sent without DATA_B3_REQ
+	sentdatamsg: capi DATA_B3_REQ sent
+   for example:
+1 2057 1699 1721 1699
+
+/proc/capi/capi20: statistics of capi.o (/dev/capi20)
+    minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg
+	minor: minor device number of capi device
+	nopen: number of calls to devices open
+	nrecvdropmsg: capi messages dropped (messages in recvqueue in close)
+	nrecvctlmsg: capi messages received without DATA_B3_IND
+	nrecvdatamsg: capi DATA_B3_IND received
+	nsentctlmsg: capi messages sent without DATA_B3_REQ
+	nsentdatamsg: capi DATA_B3_REQ sent
+
+   for example:
+1 2 18 0 16 2
+
+/proc/capi/capidrv: statistics of capidrv.o (capi messages)
+    nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg
+	nrecvctlmsg: capi messages received without DATA_B3_IND
+	nrecvdatamsg: capi DATA_B3_IND received
+	nsentctlmsg: capi messages sent without DATA_B3_REQ
+	nsentdatamsg: capi DATA_B3_REQ sent
+   for example:
+2780 2226 2256 2226
+
+/proc/capi/controller:
+   controller drivername state cardname   controllerinfo
+   for example:
+1 b1pci      running  b1pci-e000       B1 3.07-01 0xe000 19
+2 t1isa      running  t1isa-450        B1 3.07-01 0x450 11 0
+3 b1pcmcia   running  m2-150           B1 3.07-01 0x150 5
+
+/proc/capi/contrstats:
+    controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg
+	nrecvctlmsg: capi messages received without DATA_B3_IND
+	nrecvdatamsg: capi DATA_B3_IND received
+	nsentctlmsg: capi messages sent without DATA_B3_REQ
+	nsentdatamsg: capi DATA_B3_REQ sent
+   for example:
+1 2845 2272 2310 2274
+2 2 0 2 0
+3 2 0 2 0
+
+/proc/capi/driver:
+   drivername ncontroller
+   for example:
+b1pci                            1
+t1isa                            1
+b1pcmcia                         1
+b1isa                            0
+
+/proc/capi/ncci:
+   apllid ncci winsize sendwindow
+   for example:
+1 0x10101 8 0
+
+/proc/capi/users: kernelmodules that use the kernelcapi.
+   name
+   for example:
+capidrv
+capi20
 
 Questions
 ---------
-Check out the FAQ (ftp.franken.de).
+Check out the FAQ (ftp.franken.de) or subscribe to the
+linux-avmb1@calle.in-berlin.de mailing list by sending
+a mail to majordomo@calle.in-berlin.de with
+subscribe linux-avmb1
+in the body.
+
+German documentaion and several scripts can be found at
+ftp://ftp.avm.de/cardware/b1/linux/
 
 Bugs 
 ----
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.concap linux.pre11.3/Documentation/isdn/README.concap
--- linux.vanilla/Documentation/isdn/README.concap	Sat Jan  9 21:50:34 1999
+++ linux.pre11.3/Documentation/isdn/README.concap	Tue Jul 20 00:26:16 1999
@@ -256,3 +256,4 @@
 of the concap interface when a trivial concap protocol is used.
 Nevertheless, the device remains able to support encapsulation
 protocol configuration.
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.eicon linux.pre11.3/Documentation/isdn/README.eicon
--- linux.vanilla/Documentation/isdn/README.eicon	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/Documentation/isdn/README.eicon	Tue Jul 20 00:26:16 1999
@@ -0,0 +1,88 @@
+$Id: README.eicon,v 1.4 1999/07/11 17:17:30 armin Exp $
+
+(c) 1999 Cytronics & Melware
+
+This document describes the eicon driver for the
+Eicon.Diehl active ISDN cards.
+
+It is meant to be used with isdn4linux, an ISDN link-level module for Linux.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the 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.
+
+
+
+Supported Cards
+---------------
+
+- S-Card ISA
+- SX-Card ISA
+- SXn-Card ISA
+- SCOM-Card ISA
+- Quadro-Card ISA
+- S2M-Card ISA
+- DIVA Server BRI/PCI 2M
+- DIVA Server PRI/PCI 2M (9M 23M 30M)
+  (Only analog modem functions of the DSPs are currently implemented)
+
+ISDN D-Channel Protocols
+------------------------
+
+- ETSI (Euro-DSS1) 
+- 1TR6 (German ISDN) *not testet*
+
+
+
+You can load the module simply by using the insmod or modprobe function :
+
+  insmod eicon [id=driverid] [membase=<membase>] [irq=<irq>]
+
+
+The module will automatically probe the PCI-cards. If the id-options
+is omitted, the driver will assume 'eicon0' for the first pci card and
+increases the digit with each further card. With a given driver-id
+the module appends a number starting with '0'.
+
+For ISA-cards you have to specify membase, irq and id. If id or
+membase is missing/invalid, the driver will not be loaded except
+PCI-cards were found. Additional ISA-cards and irq/membase changes
+can be done with the eiconctrl utility.
+
+After loading the module, you have to download the protocol and
+dsp-code by using the eiconctrl utility of isdn4k-utils.
+
+
+Example for loading and starting a BRI card with E-DSS1 Protocol.
+
+	eiconctrl [-d DriverId] load etsi
+
+
+Example for loading and starting a PRI card with E-DSS1 Protocol.
+
+	eiconctrl [-d DriverId] load etsi -s2 -n
+
+
+Details about using the eiconctrl utility are in 'man eiconctrl'
+or will be printed by starting eiconctrl without any parameters.
+
+
+
+Any reports about bugs, errors and even wishes are welcome.
+
+
+Have fun !
+
+Armin Schindler
+mac@melware.de
+http://www.melware.de
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.icn linux.pre11.3/Documentation/isdn/README.icn
--- linux.vanilla/Documentation/isdn/README.icn	Sun Nov  8 15:08:48 1998
+++ linux.pre11.3/Documentation/isdn/README.icn	Tue Jul 20 00:26:16 1999
@@ -1,4 +1,4 @@
-$Id: README.icn,v 1.5 1997/04/23 18:55:55 fritz Exp $
+$Id: README.icn,v 1.6 1998/04/29 19:49:08 he Exp $
 
 You can get the ICN-ISDN-card from:
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/isdn/README.x25 linux.pre11.3/Documentation/isdn/README.x25
--- linux.vanilla/Documentation/isdn/README.x25	Sat Jan  9 21:50:34 1999
+++ linux.pre11.3/Documentation/isdn/README.x25	Tue Jul 20 00:26:16 1999
@@ -1,29 +1,24 @@
- 
-X25 support within isdn4linux
-
-
-This is experimental code and should be used with linux version 2.1.72.
-or later. Use it completely at your own risk.
-
+  
+X.25 support within isdn4linux
+==============================
 
+This is alpha/beta test code. Use it completely at your own risk.
 As new versions appear, the stuff described here might suddenly change
 or become invalid without notice.
 
 Keep in mind:
 
-You are using an experimental kernel (2.1.x series) with an experimental
-x25 protocol implementation and experimental x25-on-top-of-isdn extensions.
-Thus, be prepared to face problems related therefrom.
+You are using several new parts of the 2.2.x kernel series which
+have not been tested in a large scale. Therefore, you might encounter
+more bugs as usual.
 
-- If you connect to an x25 neighbour not operated by yourself, ASK the
+- If you connect to an X.25 neighbour not operated by yourself, ASK the
   other side first. Be prepared that bugs in the protocol implementation
-  might result in problems (even crashing the peer, however such ugly events
-  should only happen if your peer's protocol implementation has serious bugs).
+  might result in problems.
 
 - This implementation has never wiped out my whole hard disk yet. But as
-  this is experimental code, don't blame me if that happened to you. Take
-  appropriate actions (such as backing up important data) before
-  trying this code.
+  this is experimental code, don't blame me if that happened to you.
+  Backing up important data will never harm.
 
 - Monitor your isdn connections while using this software. This should
   prevent you from undesired phone bills in case of driver problems.
@@ -32,7 +27,7 @@
 
 
 How to configure the kernel
-
+===========================
  
 The ITU-T (former CCITT) X.25 network protocol layer has been implemented
 in the Linux source tree since version 2.1.16. The isdn subsystem might be 
@@ -48,32 +43,33 @@
 compilation. You currently also need to enable
 "Prompt for development and/or incomplete code/drivers" from the
 "Code maturity level options" menu. For the x25trace utility to work
-you also need to enable "Packet socket" (I recommend to choose "y",
-not "m" for testing) from the networking options.
+you also need to enable "Packet socket".
 
+For local testing it is also recommended to enable the isdnloop driver
+from the isdn subsystem's configuration menu.
 
-For testing you should also select the isdnloop driver from the
-isdn subsystem's configuration menu.
+For testing, it is recommended that all isdn drivers and the X.25 PLP
+protocol are compiled as loadable modules. Like this, you can recover
+from certain errors by simply unloading and reloading the modules.
 
 
 
 What's it for? How to use it?
+=============================
 
-
-X25 on top of isdn might be useful with two different scenarios:
+X.25 on top of isdn might be useful with two different scenarios:
 
 - You might want to access a public X.25 data network from your Linux box.
   You can use i4l if you were physically connected to the X.25 switch
-  by an ISDN line (leased line as well as dial up connection should work,
-  but connecting to x.25 network switches is currently untested. Testing
-  needs to be done by somebody with access to such a switch.) 
-
-- Or you might want to operate certain ISDN teleservices on 
-  your linux box. A lot of those teleservices run on top of the ISO-8208 
-  network layer protocol. ISO-8208 is essentially the same as ITU-T X.25.
+  by an ISDN line (leased line as well as dial up connection should work)
+
+- Or you might want to operate certain ISDN teleservices on your linux
+  box. A lot of those teleservices run on top of the ISO-8208
+  (DTE-DTE mode) network layer protocol. ISO-8208 is essentially the
+  same as ITU-T X.25.
 
-  Popular candidates of such teleservices are EUROFILE transfer or any
-  teleservice applying ITU-T recommendation T.90 (i.e., AFAIK, G4 Fax).
+  Popular candidates of such teleservices are EUROfile transfer or any
+  teleservice applying ITU-T recommendation T.90.
 
 To use the X.25 protocol on top of isdn, just create an isdn network
 interface as usual, configure your own and/or peer's ISDN numbers,
@@ -81,21 +77,18 @@
 
    isdnctrl encap <iface-name> x25iface.
 
-Once encap is set like this, the device can be used by the x25 packet layer.
+Once encap is set like this, the device can be used by the X.25 packet layer.
 
-All the stuff needed for x25 is implemented inside the isdn link
+All the stuff needed for X.25 is implemented inside the isdn link
 level (mainly isdn_net.c and some new source files). Thus, it should
-work with every existing HL driver. I was able to successfully open x25
+work with every existing HL driver. I was able to successfully open X.25
 connections on top of the isdnloop driver and the hisax driver.
 "x25iface"-encapsulation bypasses demand dialing. Dialing will be
-initiated when the upper (x25 packet) layer requests the lapb datalink to
-be established. But hangup timeout is still active. The connection
-will not automatically be re-established by the isdn_net module
-itself when new data arrives after the hangup timeout. But
-the x25 network code will re-establish the datalink connection
-(resulting in re-dialing and an x25 protocol reset) when new data is
-to be transmitted. (This currently does not work properly with the
-isdnloop driver, see "known problems" below)
+initiated when the upper (X.25 packet) layer requests the lapb datalink to
+be established. But hangup timeout is still active. Whenever a hangup
+occurs, all existing X.25 connections on that link will be cleared
+It is recommended to use sufficiently large hangup-timeouts for the
+isdn interfaces.
 
 
 In order to set up a conforming protocol stack you also need to
@@ -114,104 +107,64 @@
    isdnctrl l2_prot <iface-name> x25dce
 
 However, x25dte or x25dce is currently not supported by any real HL
-level driver. The main difference between x75 and x25dte/dce is that
+level driver. The main difference between x75i and x25dte/dce is that
 x25d[tc]e uses fixed lap_b addresses. With x75i, the side which
 initiates the isdn connection uses the DTE's lap_b address while the
-called side used the DCE's lap_b address. Thus, l2_prot x75i will
-probably work if you access a public x25 network as long as the
-corresponding isdn connection is set up by you. However, I've never
-tested this.
-
-
+called side used the DCE's lap_b address. Thus, l2_prot x75i might
+probably work if you access a public X.25 network as long as the
+corresponding isdn connection is set up by you. At least one test
+was successful to connect via isdn4linux to an X.25 switch using this
+trick. At the switch side, a terminal adapter X.21 was used to connect
+it to the isdn.
 
-How to use the test installation?
 
+How to set up a test installation?
+==================================
 
-To test x25 on top of isdn, you need to get
+To test X.25 on top of isdn, you need to get
 
-- a patched version of the "isdnctrl" program that supports setting the new
-  x25 specific parameters.
+- a recent version of the "isdnctrl" program that supports setting the new
+  X.25 specific parameters.
 
-- the x25-utils-2.1.x package from ftp.pspt.fi/pub/ham/linux/ax25
-  or any mirror site (i.e. ftp://ftp.gwdg.de/pub/linux/misc/ax25/).
+- the x25-utils-2.X package from 
+  ftp://ftp.hes.iki.fi/pub/ham/linux/ax25/x25utils-*
+  (don't confuse the x25-utils with the ax25-utils)
 
-- a kernel patch that enhances isdn4linux to provide x25 network
-  interface support. (This file is part of that kernel patch).
-
-- an application that uses linux AF_X25 sockets program. 
+- an application program that uses linux PF_X25 sockets (some are
+  contained in the x25-util package).
 
 Before compiling the user level utilities make sure that the compiler/
-preprocessor will fetch the proper (patched) kernel header files. Either make
-/usr/include/linux a symbolic link pointing to your developer kernel's
-include/linux directory or set the appropriate compiler flags.
-
-It is recommended that all isdn drivers and the x25 PLP protocol 
-are compiled as loadable modules. Like this, you can recover
-from certain errors by simply unloading and reloading the modules.
+preprocessor will fetch the proper kernel header files of this kernel
+source tree. Either make /usr/include/linux a symbolic link pointing to 
+this kernel's include/linux directory or set the appropriate compiler flags.
 
 When all drivers and interfaces are loaded and configured you need to
-ifconfig the network interfaces up and add x25-routes to them. Use
+ifconfig the network interfaces up and add X.25-routes to them. Use
 the usual ifconfig tool.
 
 ifconfig <iface-name> up
 
 But a special x25route tool (distributed with the x25-util package)
-is needed to set up x25 routes. I.e. 
+is needed to set up X.25 routes. I.e. 
 
 x25route add 01 <iface-name>
 
-will cause all x.25 connections to the destination x.25-address
+will cause all x.25 connections to the destination X.25-address
 "01" to be routed to your created isdn network interface.
 
-
-There are currently no real x25 applications available. However, for
+There are currently no real X.25 applications available. However, for
 tests, the x25-utils package contains a modified version of telnet
-and telnetd that uses x25 sockets instead of tcp/ip sockets. Use
-this for your first tests. Furthermore, there is an x25.echod and a client
-named "eftp" (which contains some experimental code to download files
-from a remote eft server using the EUROfile transfer protocol).
-It available at ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/eftp4linux-*
+and telnetd that uses X.25 sockets instead of tcp/ip sockets. You can
+use those for your first tests. Furthermore, you might check
+ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/ which contains some
+alpha-test implementation ("eftp4linux") of the EUROfile transfer
+protocol.
+
+The scripts distributed with the eftp4linux test releases might also
+provide useful examples for setting up X.25 on top of isdn.
 
 The x25-utility package also contains an x25trace tool that can be
-used to monitor x25 packets received by the network interfaces.
+used to monitor X.25 packets received by the network interfaces.
 The /proc/net/x25* files also contain useful information. 
 
-The eftp4linux test release also contains an "ix25test" script that can
-be used for testing x25 on top of isdn4linux. Edit
-this script according to your local needs and then call it as
-
-ix25test start
-
-This will set up a sample configuration using the isdnloop and hisax
-driver and create some isdn network interfaces.
-It is recommended that all other isdn drivers and the
-x25 module are unloaded before calling this script.
-
-
-
-Known problems and deficiencies:
-
-The isdnloop HL driver apparently has problems to re-establish a
-connection that has been hung up from the outgoing device. You have to
-unload the isdnloop driver after the faked isdn-connection is closed
-and insmod it again. With the Hisax driver, this problem is not present.
-
-Sometimes the x25 module cannot be unloaded (decrementation of its use
-count seems to get lost occasionally).
-
-Using the x25 based telnet and telnetd programm to establish connection
-from your own to your own computer repeatedly sometimes totally locked
-up my system. However, this kernel patch also modifies
-net/x25/af_x25.c to include a workaround. With this workaround
-enabled, my system is stable. (If you want to disable the
-workaround, just undefine ISDN_X25_FIXES in af_x25.c).
-
-The latter problem could be reproduced by using hisax as well as the
-isdnloop driver. It seems that it is not caused by the isdn code.
-Somehow, the inode of a socket is freed while a process still refers
-the socket's wait queue. This causes problems when the process tries to
-remove itself from the wait queue (referred by the dangling
-sock->sleep pointer) before returning from a select() system call.
-
 - Henner
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/nbd.txt linux.pre11.3/Documentation/nbd.txt
--- linux.vanilla/Documentation/nbd.txt	Sun Nov  8 15:08:49 1998
+++ linux.pre11.3/Documentation/nbd.txt	Mon Jul 19 23:50:34 1999
@@ -4,11 +4,11 @@
    means, that it works on my computer, and it worked on one of school
    computers.
    
-   What is it: With this compiled in the kernel, linux can use a remote
+   What is it: With this compiled in the kernel, Linux can use a remote
    server as one of its block devices. So every time the client computer
    wants to read /dev/nd0, it sends a request over TCP to the server, which
    will reply with the data read. This can be used for stations with
-   low-disk space (or even diskless - if you boot from floppy) to
+   low disk space (or even diskless - if you boot from floppy) to
    borrow disk space from another computer. Unlike NFS, it is possible to
    put any filesystem on it etc. It is impossible to use NBD as a root
    filesystem, since it requires a user-level program to start. It also
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/Configurable linux.pre11.3/Documentation/networking/Configurable
--- linux.vanilla/Documentation/networking/Configurable	Sun Nov  8 15:08:47 1998
+++ linux.pre11.3/Documentation/networking/Configurable	Mon Jul 19 23:50:47 1999
@@ -20,11 +20,11 @@
 	7000
 
 Others are already accessible via the related user space programs.
-For example, MAX_WINDOW has a default of 32k which is a good choice for
-modern hardware, but if you have a slow (8 bit) ethercard and/or a slow
+For example, MAX_WINDOW has a default of 32 k which is a good choice for
+modern hardware, but if you have a slow (8 bit) Ethernet card and/or a slow
 machine, then this will be far too big for the card to keep up with fast 
-Tx'ing machines on the same net, resulting in overruns and receive errors.
-A value of about 4k would be more appropriate, which can be set via:
+machines transmitting on the same net, resulting in overruns and receive errors.
+A value of about 4 k would be more appropriate, which can be set via:
 
 	# route add -net 192.168.3.0 window 4096
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/DLINK.txt linux.pre11.3/Documentation/networking/DLINK.txt
--- linux.vanilla/Documentation/networking/DLINK.txt	Sun Nov  8 15:08:47 1998
+++ linux.pre11.3/Documentation/networking/DLINK.txt	Mon Jul 19 23:50:53 1999
@@ -18,8 +18,8 @@
 	pocket adapters, for the parallel port on a Linux based machine.
 	Some adapter "clones" will also work.  Xircom is _not_ a clone...
 	These drivers _can_ be used as loadable modules,
-	and were developed for use on Linux v1.1.13 and above.
-	For use on Linux v1.0.X, or earlier releases, see below.
+	and were developed for use on Linux 1.1.13 and above.
+	For use on Linux 1.0.X, or earlier releases, see below.
 
 	I have used these drivers for NFS, ftp, telnet and X-clients on
 	remote machines. Transmissions with ftp seems to work as
@@ -57,7 +57,7 @@
 	de620.h       Macros for de620.c
 
 	If you are upgrading from the d-link tar release, there will
-	also be a "dlink-patches" file that will patch Linux v1.1.18:
+	also be a "dlink-patches" file that will patch Linux 1.1.18:
 		linux/drivers/net/Makefile
 		linux/drivers/net/CONFIG
 		linux/drivers/net/MODULES
@@ -162,10 +162,10 @@
 
 	6. USING THE DRIVERS WITH EARLIER RELEASES.
 
-	The later v1.1.X releases of the Linux kernel include some
+	The later 1.1.X releases of the Linux kernel include some
 	changes in the networking layer (a.k.a. NET3). This affects
 	these drivers in a few places.  The hints that follow are
-	_not_ tested by me, since I don't have the diskspace to keep
+	_not_ tested by me, since I don't have the disk space to keep
 	all releases on-line.
 	Known needed changes to date:
 	- release patchfile: some patches will fail, but they should
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/arcnet-hardware.txt linux.pre11.3/Documentation/networking/arcnet-hardware.txt
--- linux.vanilla/Documentation/networking/arcnet-hardware.txt	Sat Jan  9 21:50:35 1999
+++ linux.pre11.3/Documentation/networking/arcnet-hardware.txt	Mon Jul 19 23:51:05 1999
@@ -20,14 +20,14 @@
 ARCnet is a network type which works in a way similar to popular Ethernet
 networks but which is also different in some very important ways.
 
-First of all, you can get ARCnet cards in at least two speeds: 2.5Mbps
-(slower than Ethernet) and 100Mbps (faster than normal Ethernet).  In fact,
+First of all, you can get ARCnet cards in at least two speeds: 2.5 Mbps
+(slower than Ethernet) and 100 Mbps (faster than normal Ethernet).  In fact,
 there are others as well, but these are less common.  The different hardware
 types, as far as I'm aware, are not compatible and so you cannot wire a
-100Mbps card to a 2.5Mbps card, and so on.  From what I hear, my driver does
-work with 100Mbps cards, but I haven't been able to verify this myself,
-since I only have the 2.5Mbps variety.  It is probably not going to saturate
-your 100Mbps card.  Stop complaining :)
+100 Mbps card to a 2.5 Mbps card, and so on.  From what I hear, my driver does
+work with 100 Mbps cards, but I haven't been able to verify this myself,
+since I only have the 2.5 Mbps variety.  It is probably not going to saturate
+your 100 Mbps card.  Stop complaining. :)
 
 You also cannot connect an ARCnet card to any kind of Ethernet card and
 expect it to work.  
@@ -52,17 +52,17 @@
 useful for realtime networks.
 
 In addition, all known ARCnet cards have an (almost) identical programming
-interface.  This means that with one "arcnet" driver you can support any
-card; whereas, with Ethernet, each manufacturer uses what is sometimes a
+interface.  This means that with one ARCnet driver you can support any
+card, whereas with Ethernet each manufacturer uses what is sometimes a
 completely different programming interface, leading to a lot of different,
 sometimes very similar, Ethernet drivers.  Of course, always using the same
 programming interface also means that when high-performance hardware
-facilities like PCI busmastering DMA appear, it's hard to take advantage of
+facilities like PCI bus mastering DMA appear, it's hard to take advantage of
 them.  Let's not go into that.
 
 One thing that makes ARCnet cards difficult to program for, however, is the
 limit on their packet sizes; standard ARCnet can only send packets that are
-up to 508 bytes in length.  This is smaller than the internet "bare minimum"
+up to 508 bytes in length.  This is smaller than the Internet "bare minimum"
 of 576 bytes, let alone the Ethernet MTU of 1500.  To compensate, an extra
 level of encapsulation is defined by RFC1201, which I call "packet
 splitting," that allows "virtual packets" to grow as large as 64K each,
@@ -1005,9 +1005,9 @@
     only (the JP0 jumper is hardwired), and BNC only.
 	
 This is a LCS-8830-T made by SMC, I think ('SMC' only appears on one PLCC,
-nowhere else, not even on the few xeroxed sheets from the manual).
+nowhere else, not even on the few Xeroxed sheets from the manual).
 
-SMC Arcnet Board Type LCS-8830-T
+SMC ARCnet Board Type LCS-8830-T
 
    ------------------------------------
   |                                    |
@@ -1070,7 +1070,7 @@
 
 DIP Switches 1-5 of SW2 encode the RAM and ROM Address Range:
 
-Switches        Ram           Rom
+Switches        RAM           ROM
 12345           Address Range  Address Range
 00000		C:0000-C:07ff	C:2000-C:3fff
 10000		C:0800-C:0fff
@@ -1170,11 +1170,11 @@
 DIP Switches:
 
 	The DIP switches accessible on the accessible end of the card while
-        it is installed, is used to set the arcnet address.  There are 8
+        it is installed, is used to set the ARCnet address.  There are 8
         switches.  Use an address from 1 to 254.
 
 	Switch No.
-	12345678	Arcnet address
+	12345678	ARCnet address
 	-----------------------------------------
 	00000000	FF  	(Don't use this!)
 	00000001	FE
@@ -1222,7 +1222,7 @@
         from the upper memory regions, and then attempting to load ARCETHER
         using these addresses.
 
-	I recommend using an arcnet memory address of 0xD000, and putting
+	I recommend using an ARCnet memory address of 0xD000, and putting
         the EMS page frame at 0xC000 while using QEMM stealth mode.  That
         way, you get contiguous high memory from 0xD100 almost all the way
         the end of the megabyte.
@@ -1687,7 +1687,7 @@
                 |____________________________________________| |__|
 
 
-UM9065L : Arcnet Controller
+UM9065L : ARCnet Controller
 
 SW 1    : Shared Memory Address and I/O Base
 
@@ -1800,7 +1800,7 @@
 J1-J5       IRQ Select
 J6-J21      Unknown (Probably extra timeouts & ROM enable ...)
 LED1        Activity LED 
-BNC         Coax connector (STAR arcnet)
+BNC         Coax connector (STAR ARCnet)
 RAM         2k of SRAM
 ROM         Boot ROM socket
 UFS         Unidentified Flying Sockets
@@ -1905,7 +1905,7 @@
 ------------------------
   - from Vojtech Pavlik <Vojtech.Pavlik@st.mff.cuni.cz>
 
-This is another SMC 90C65 based arcnet card. I couldn't identify the
+This is another SMC 90C65-based ARCnet card. I couldn't identify the
 manufacturer, but it might be DataPoint, because the card has the
 original arcNet logo in its upper right corner.
 
@@ -1942,9 +1942,9 @@
 SW2 1-8:    Node ID Select
 SW3 1-5:    IRQ Select   
     6-7:    Extra Timeout
-    8  :    Rom Enable   
+    8  :    ROM Enable   
 BNC         Coax connector
-XTAL        20MHz Crystal
+XTAL        20 MHz Crystal
 
 
 Setting the Node ID
@@ -2081,11 +2081,11 @@
     6-8     Base I/O Address Select
 SW2 1-8     Node ID Select (ID0-ID7)
 J1          IRQ Select
-J2          Rom Enable
+J2          ROM Enable
 J3          Extra Timeout
 LED1        Activity LED 
-BNC         Coax connector (BUS arcnet)
-RJ          Twisted Pair Connector (daisychain)
+BNC         Coax connector (BUS ARCnet)
+RJ          Twisted Pair Connector (daisy chain)
 
 
 Setting the Node ID
@@ -2419,7 +2419,7 @@
 
 Legend:
 
-COM90C65:       Arcnet Probe
+COM90C65:       ARCnet Probe
 S1  1-8:    Node ID Select
 S2  1-3:    I/O Base Address Select
     4-6:    Memory Base Address Select
@@ -2791,7 +2791,7 @@
 SW2 1-8:    Node ID Select (ID0-ID7)
 SW3 1-5:    IRQ Select   
     6-7:    Extra Timeout
-    8  :    Rom Enable   
+    8  :    ROM Enable   
 JP1         Led connector
 BNC         Coax connector
 
@@ -3089,7 +3089,7 @@
 0 = Jumper Installed
 1 = Open
 
-Top Jumper line Bit 7 = Rom Enable 654=Memory location 321=I/O
+Top Jumper line Bit 7 = ROM Enable 654=Memory location 321=I/O
 
 Settings for Memory Location (Top Jumper Line)
 456     Address selected
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/arcnet.txt linux.pre11.3/Documentation/networking/arcnet.txt
--- linux.vanilla/Documentation/networking/arcnet.txt	Sun Nov  8 15:08:46 1998
+++ linux.pre11.3/Documentation/networking/arcnet.txt	Mon Jul 19 23:51:05 1999
@@ -1,4 +1,3 @@
-
 ----------------------------------------------------------------------------
 NOTE:  See also arcnet-hardware.txt in this directory for jumper-setting
 and cabling information if you're like many of us and didn't happen to get a
@@ -92,10 +91,10 @@
 	http://www.perftech.com/ or ftp to ftp.perftech.com.
 	
 Novell makes a networking stack for DOS which includes ARCnet drivers.  Try
-ftp'ing to ftp.novell.com.
+FTPing to ftp.novell.com.
 
 You can get the Crynwr packet driver collection (including arcether.com, the
-one you'll want to use with arcnet cards) from
+one you'll want to use with ARCnet cards) from
 oak.oakland.edu:/simtel/msdos/pktdrvr. It won't work perfectly on a 386+
 without patches, though, and also doesn't like several cards.  Fixed
 versions are available on my WWW page, or via e-mail if you don't have WWW
@@ -183,7 +182,7 @@
 -----------------------
 
 Configure and rebuild Linux.  When asked, answer 'm' to "Generic ARCnet 
-support" and to support for your ARcnet chipset if you want to use the
+support" and to support for your ARCnet chipset if you want to use the
 loadable module. You can also say 'y' to "Generic ARCnet support" and 'm' 
 to the chipset support if you wish.
 
@@ -269,7 +268,7 @@
 	Arcether client, assuming you remember to load winpkt of course.
 
 LAN Manager and Windows for Workgroups: These programs use protocols that
-        are incompatible with the internet standard.  They try to pretend
+        are incompatible with the Internet standard.  They try to pretend
         the cards are Ethernet, and confuse everyone else on the network. 
         
         However, v2.00 and higher of the Linux ARCnet driver supports this
@@ -288,7 +287,7 @@
 	you're completely insane, and/or you need to build some kind of
 	hybrid network that uses both encapsulation types.
 
-OS2: I've been told it works under Warp Connect with an ARCnet driver from
+OS/2: I've been told it works under Warp Connect with an ARCnet driver from
 	SMC.  You need to use the 'arc0e' interface for this.  If you get
 	the SMC driver to work with the TCP/IP stuff included in the
 	"normal" Warp Bonus Pack, let me know.
@@ -309,7 +308,7 @@
 The ARCnet driver v2.10 ALPHA supports three protocols, each on its own
 "virtual network device":
 
-	arc0  - RFC1201 protocol, the official internet standard which just
+	arc0  - RFC1201 protocol, the official Internet standard which just
 		happens to be 100% compatible with Novell's TRXNET driver. 
 		Version 1.00 of the ARCnet driver supported _only_ this
 		protocol.  arc0 is the fastest of the three protocols (for
@@ -331,13 +330,13 @@
 		reasons yet to be determined.  (Probably it's the smaller
 		MTU that does it.)
 		
-	arc0s - The "[s]imple" RFC1051 protocol is the "previous" internet
+	arc0s - The "[s]imple" RFC1051 protocol is the "previous" Internet
 		standard that is completely incompatible with the new
 		standard.  Some software today, however, continues to
 		support the old standard (and only the old standard)
 		including NetBSD and AmiTCP.  RFC1051 also does not support
 		RFC1201's packet splitting, and the MTU of 507 is still
-		smaller than the internet "requirement," so it's quite
+		smaller than the Internet "requirement," so it's quite
 		possible that you may run into problems.  It's also slower
 		than RFC1201 by about 25%, for the same reason as arc0e.
 		
@@ -388,16 +387,16 @@
    Linux but runs the free Microsoft LANMAN Client instead.
 
    Worse, one of the Linux computers (freedom) also has a modem and acts as
-   a router to my internet provider.  The other Linux box (insight) also has
+   a router to my Internet provider.  The other Linux box (insight) also has
    its own IP address and needs to use freedom as its default gateway.  The
-   XT (patience), however, does not have its own internet IP address and so
+   XT (patience), however, does not have its own Internet IP address and so
    I assigned it one on a "private subnet" (as defined by RFC1597).
 
    To start with, take a simple network with just insight and freedom. 
    Insight needs to:
    	- talk to freedom via RFC1201 (arc0) protocol, because I like it
 	  more and it's faster.
-	- use freedom as its internet gateway.
+	- use freedom as its Internet gateway.
 	
    That's pretty easy to do.  Set up insight like this:
    	ifconfig arc0 insight
@@ -417,20 +416,20 @@
    	/* and default gateway is configured by pppd */
    	
    Great, now insight talks to freedom directly on arc0, and sends packets
-   to the internet through freedom.  If you didn't know how to do the above,
+   to the Internet through freedom.  If you didn't know how to do the above,
    you should probably stop reading this section now because it only gets
    worse.
 
    Now, how do I add patience into the network?  It will be using LANMAN
    Client, which means I need the arc0e device.  It needs to be able to talk
    to both insight and freedom, and also use freedom as a gateway to the
-   internet.  (Recall that patience has a "private IP address" which won't
-   work on the internet; that's okay, I configured Linux IP masquerading on
+   Internet.  (Recall that patience has a "private IP address" which won't
+   work on the Internet; that's okay, I configured Linux IP masquerading on
    freedom for this subnet).
    
    So patience (necessarily; I don't have another IP number from my
    provider) has an IP address on a different subnet than freedom and
-   insight, but needs to use freedom as an internet gateway.  Worse, most
+   insight, but needs to use freedom as an Internet gateway.  Worse, most
    DOS networking programs, including LANMAN, have braindead networking
    schemes that rely completely on the netmask and a 'default gateway' to
    determine how to route packets.  This means that to get to freedom or
@@ -449,7 +448,7 @@
    
    This way, freedom will send all packets for patience through arc0e,
    giving its IP address as gatekeeper (on the private subnet).  When it
-   talks to insight or the internet, it will use its "freedom" internet IP
+   talks to insight or the Internet, it will use its "freedom" Internet IP
    address.
    
    You will notice that we haven't configured the arc0e device on insight. 
@@ -473,7 +472,7 @@
    
                                                     
           [RFC1201 NETWORK]                   [ETHER-ENCAP NETWORK]
-      (registered internet subnet)           (RFC1597 private subnet)
+      (registered Internet subnet)           (RFC1597 private subnet)
   
                              (IP Masquerade)
           /---------------\         *            /---------------\
@@ -523,7 +522,7 @@
 Once the driver is running, you can run the arcdump shell script (available
 from me or in the full ARCnet package, if you have it) as root to list the
 contents of the arcnet buffers at any time.  To make any sense at all out of
-this, you should grab the pertinent RFC's. (some are listed near the top of
+this, you should grab the pertinent RFCs. (some are listed near the top of
 arcnet.c).  arcdump assumes your card is at 0xD0000.  If it isn't, edit the
 script.
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/olympic.txt linux.pre11.3/Documentation/networking/olympic.txt
--- linux.vanilla/Documentation/networking/olympic.txt	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/Documentation/networking/olympic.txt	Mon Jul 19 23:28:59 1999
@@ -0,0 +1,75 @@
+
+IBM PCI Pit/Pit-Phy/Olympic CHIPSET BASED TOKEN RING CARDS README
+
+Release 0.2.0 - Release    
+	June 8th 1999 Peter De Schrijver & Mike Phillips
+
+
+Thanks:
+Erik De Cock, Adrian Bridgett and Frank Fiene for their 
+patience and testing.  
+Paul Norton without whose tr.c code we would have had
+a lot more work to do.
+ 
+Options:
+
+The driver accepts three options: ringspeed, pkt_buf_sz, and  
+message_level.
+
+These options can be specified differently for each card found. 
+
+ringspeed:  Has one of three settings 0 (default), 4 or 16.  0 will 
+make the card autosense the ringspeed and join at the appropriate speed, 
+this will be the default option for most people.  4 or 16 allow you to 
+explicitly force the card to operate at a certain speed.  The card will fail 
+if you try to insert it at the wrong speed. (Although some hubs will allow 
+this so be *very* careful).  The main purpose for explicitly setting the ring
+speed is for when the card is first on the ring.  In autosense mode, if the card
+cannot detect any active monitors on the ring it will not open, so you must 
+re-init the card at the appropriate speed.  Unfortunately at present the only
+way of doing this is rmmod and insmod which is a bit tough if it is compiled
+in the kernel.
+
+pkt_buf_sz:  This is this initial receive buffer allocation size.  This will
+default to 4096 if no value is entered. You may increase performance of the 
+driver by setting this to a value larger than the network packet size, although
+the driver now re-sizes buffers based on MTU settings as well. 
+
+message_level: Controls level of messages created by the driver. Defaults to 0:
+which only displays start-up and critical messages.  Presently any non-zero 
+value will display all soft messages as well.  NB This does not turn 
+debuging messages on, that must be done by modified the source code.
+
+Multi-card:
+
+The driver will detect multiple cards and will work with shared interrupts,
+each card is assigned the next token ring device, i.e. tr0 , tr1, tr2.  The 
+driver should also happily reside in the system with other drivers.  It has 
+been tested with ibmtr.c running, and I personnally have had one Olicom PCI 
+card and two IBM olympic cards (all on the same interrupt), all running
+together. 
+
+Variable MTU size:
+
+The driver can handle a MTU size upto either 4500 or 18000 depending upon 
+ring speed.  The driver also changes the size of the receive buffers as part
+of the mtu re-sizing, so if you set mtu = 18000, you will need to be able
+to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring 
+position = 296,000 bytes of memory space, plus of course anything 
+necessary for the tx sk_buff's.  Remember this is per card, so if you are
+building routers, gateway's etc, you could start to use a lot of memory
+real fast.
+
+Network Monitor Mode:
+
+By modifying the #define OLYMPIC_NETWORK_MONITOR from 0 to 1 in the 
+source code the driver will implement a quasi network monitoring 
+mode.  All unexpected MAC frames (beaconing etc.) will be received
+by the driver and the source and destination addresses printed. 
+Also an entry will be added in  /proc/net called olympic_tr. This 
+displays low level information about the configuration of the ring and
+the adapter. This feature has been designed for network adiministrators
+to assist in the diagnosis of network / ring problems.
+
+6/8/99 Peter De Schrijver and Mike Phillips
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/policy-routing.txt linux.pre11.3/Documentation/networking/policy-routing.txt
--- linux.vanilla/Documentation/networking/policy-routing.txt	Sun Nov  8 15:08:47 1998
+++ linux.pre11.3/Documentation/networking/policy-routing.txt	Mon Jul 19 23:28:58 1999
@@ -83,7 +83,7 @@
 2.	Opposite case. Just forget all that you know about routing
 	tables. Every rule is supplied with its own gateway, device
 	info. record. This approach is not appropriate for automated
-	route maintanance, but it is ideal for manual configuration.
+	route maintenance, but it is ideal for manual configuration.
 
 	HOWTO:  iproute addrule [ from PREFIX ] [ to PREFIX ] [ tos TOS ]
 		[ dev INPUTDEV] [ pref PREFERENCE ] route [ gw GATEWAY ]
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/networking/z8530drv.txt linux.pre11.3/Documentation/networking/z8530drv.txt
--- linux.vanilla/Documentation/networking/z8530drv.txt	Sun Nov  8 15:08:46 1998
+++ linux.pre11.3/Documentation/networking/z8530drv.txt	Mon Jul 19 23:28:58 1999
@@ -252,7 +252,7 @@
 
 speed 1200		# the default baudrate
 clock dpll		# clock source: 
-			# 	dpll     = normal halfduplex operation
+			# 	dpll     = normal half duplex operation
 			# 	external = MODEM provides own Rx/Tx clock
 			#	divider  = use full duplex divider if
 			#		   installed (1)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/Introduction linux.pre11.3/Documentation/sound/Introduction
--- linux.vanilla/Documentation/sound/Introduction	Thu May 27 22:11:48 1999
+++ linux.pre11.3/Documentation/sound/Introduction	Mon Jul 19 23:29:00 1999
@@ -1,6 +1,6 @@
-Soundcore	Notes on Modular Sound Drivers and Soundcore
+Introduction	Notes on Modular Sound Drivers and Soundcore
 Wade Hampton 
-11/20/1998
+6/30/1999
 
 Purpose:  
 ========
@@ -10,13 +10,21 @@
 
 Note, some of this probably should be added to the Sound-HOWTO!
 
+
 Copying:
 ========
 none
 
+
 History:
 ========
-0.1.0  11/20/1998  First version
+0.1.0  11/20/1998  First version, draft
+1.0.0  11/1998     Alan Cox changes, incorporation in 2.2.0
+                   as /usr/src/linux/Documentation/sound/Introduction
+1.1.0  6/30/1999   Second version, added notes on making the drivers,
+                   added info on multiple sound cards of similar types,]
+                   added more diagnostics info, added info about esd.
+                   added info on OSS and ALSA.
 
 
 Modular Sound Drivers:
@@ -58,6 +66,53 @@
 for the same or a similar feature (dma1= versus dma16=).  As a last 
 resort, inspect the code (search for MODULE_PARM).
 
+Notes:
+
+1.  There is a new OpenSource sound driver called ALSA which is
+    currently under development:  http://www.alsa-project.org/
+    I have not tried it nor am I aware of its status, but it is
+    currently under development.
+
+2.  The commercial OSS driver may be obtained from the site:
+    http://www/opensound.com.  This may be used for cards that
+    are unsupported by the kernel driver, or may be used
+    by other operating systems.  
+
+3.  The enlightenment sound daemon may be used for playing
+    multiple sounds at the same time via a single card, eliminating
+    some of the requirements for multiple sound card systems.  For
+    more information, see:  http://www.tux.org/~ricdude/EsounD.html  
+    The "esd" program may be used with the real-player and mpeg 
+    players like mpg123 and x11amp.
+
+
+Building the Modules:
+=====================
+
+This document does not provide full details on building the 
+kernel, etc.  The notes below apply only to making the kernel
+sound modules.   If this conflicts with the kernel's README,
+the README takes precedence. 
+
+1.  To make the kernel sound modules, cd to your /usr/src/linux
+    directory (typically) and type make config, make menuconfig, 
+    or make xconfig (to start the command line, dialog, or x-based
+    configuration tool).  
+
+2.  Select the Sound option and a dialog will be displayed.  
+
+3.  Select M (module) for "Sound card support".
+
+4.  Select your sound driver(s) as a module.  For ProAudio, Sound
+    Blaster, etc., select M (module) for OSS sound modules.
+    [thanks to marvin stodolsky <stodolsk@erols.com>]A
+
+5.  Make the kernel (e.g., make dep ; make bzImage), and install
+    the kernel.
+
+6.  Make the modules and install them (make modules; make modules_install).
+
+
 
 INSMOD:
 =======
@@ -82,6 +137,9 @@
 /sbin/insmod uart401
 /sbin/insmod sb io=$SB_BASE irq=$SB_IRQ dma=$SB_DMA dma16=$SB_DMA2 mpu_io=$SB_MP
 
+When using sound as a module, I typically put these commands
+in a file such as /root/soundon.sh.
+
 
 MODPROBE:
 =========
@@ -117,8 +175,8 @@
 	soundcore               1968   8  [sb sound]
 
 
-Removing 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
@@ -134,6 +192,25 @@
 /sbin/rmmod soundlow
 /sbin/rmmod soundcore
 
+When using sound as a module, I typically put these commands
+in a script such as /root/soundoff.sh.
+
+
+Removing Sound for use with OSS: 
+================================ 
+
+If you get really stuck or have a card that the kernel modules
+will not support, you can get a commercial sound driver from
+http://www.opensound.com.  Before loading the commercial sound
+driver, you should do the following:
+
+1.  remove sound modules (detailed above)
+2.  remove the sound modules from /etc/conf.modules
+3.  move the sound modules from /lib/modules/<kernel>/misc
+    (for example, I make a /lib/modules/<kernel>/misc/tmp
+    directory and copy the sound module files to that 
+    directory).
+
 
 Multiple Sound Cards:
 =====================
@@ -154,11 +231,30 @@
 first (in my case "sb") and then load the other one
 (in my case "cs4232").
 
+If you have two cards of the same type that are jumpered 
+cards or different PnP revisions, you may load the same 
+module twice.  For example, I have a SoundBlaster vibra 16
+and an older SoundBlaster 16 (jumpers).  To load the module
+twice, you need to do the following:
+
+1.  Copy the sound modules to a new name.  For example
+    sb.o could be copied (or symlinked) to sb1.o for the
+    second SoundBlasster.
+
+2.  Make a second entry in /etc/conf.modules, for example,
+    sound1 or sb1.  This second entry should refer to the
+    new module names for example sb1, and should include
+    the I/O, etc. for the second sound card.
+
+3.  Update your soundon.sh script, etc.
+
 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.
+send me an E-MAIL.  PCI sound cards should not have this problem.a
+Since this was originally release, I have received a couple of 
+mails from people who have accomplished this!
 
 
 Sound Problems:
@@ -175,6 +271,8 @@
       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.
+      You should really do this BEFORE attempting to get
+      sound working!
   
   B)  Check (cat) /proc/interrupts, /proc/ioports,
       and /proc/dma.  Are you trying to use an address,
@@ -184,22 +282,44 @@
       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
+      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.
+      another location.  Sometimes this is the only way 
+      and it is more or less trial and error.
 
-2)  If you get motorboating (the same sound or part of a 
+2)  If you get motor-boating (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.
+    or DMA conflict.  Move the card to another IRQ or DMA
+    port.  This has happened to me when playing long files 
+    when I had an IRQ conflict.
+
+3.  If you get dropouts or pauses when playing high sample
+    rate files such as using mpg123 or x11amp/xmms, you may 
+    have too slow of a CPU and may have to use the options to 
+    play the files at 1/2 speed.  For example, you may use
+    the -2 or -4 option on mpg123.  You may also get this
+    when trying to play mpeg files stored on a CD-ROM
+    (my Toshiba T8000 PII/366 sometimes has this problem).
+
+4.  If you get "cannot access device" errors, your /dev/dsp
+    files, etc. may be set to owner root, mode 600.  You 
+    may have to use the command:
+      chmod 666 /dev/dsp /dev/mixer /dev/audio
+
+5.  If you get "device busy" errors, another program has the
+    sound device open.  For example, if using the Enlightenment
+    sound daemon "esd", the "esd" program has the sound device.
+    If using "esd", please RTFM the docs on ESD.  For example,
+    esddsp <program> may be used to play files via a non-esd
+    aware program.
+
 
-3)  Ask for help on the sound list or send E-MAIL to the
+6)  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).
+7)  Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB).
 
 
 Configuring Sound:
@@ -210,7 +330,8 @@
 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.
+2)  On the command line when using insmod or in a bash script
+    using command line calls to load sound.
 
 3)  In /etc/conf.modules when using modprobe.
 
@@ -224,7 +345,6 @@
 Anyone want to write a linuxconf module for configuring sound?
 
 
-
 For More Information (RTFM):
 ============================
 1)  Information on kernel modules:  linux/Documentation/modules.txt
@@ -242,12 +362,17 @@
 
 7)  The sndconfig and rhsound documentation from Red Hat.
 
-8)  The Linux-sound mailing list:  sound-list@redhat.com
+8)  The Linux-sound mailing list:  sound-list@redhat.com.
+
+9)  Enlightenment documentation (for info on esd)
+    http://www.tux.org/~ricdude/EsounD.html.
 
+10) ALSA home page:  http://www.alsa-project.org/
 
 
 Contact Information:
 ====================
 Wade Hampton:  (whampton@staffnet.com)
+
 
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sound/OPL3-SA2 linux.pre11.3/Documentation/sound/OPL3-SA2
--- linux.vanilla/Documentation/sound/OPL3-SA2	Tue Jan 19 02:57:22 1999
+++ linux.pre11.3/Documentation/sound/OPL3-SA2	Mon Jul 19 23:29:00 1999
@@ -46,6 +46,21 @@
 then email me if you are willing to experiment in an effort to make it
 work.
 
+************************************************************************
+* I have now had two such machines, and I have fixed this to work
+* properly when built into the kernel.  The Toshiba Libretto series, or
+* at least models 70CT and 110CT which I have owned, use a Yamaha
+* OPL3-SAx (OPL3-SA3 according to documentation) sound chip, IRQ 5,
+* IO addresses 220/530/388/330/370 and DMA 1,0 (_not_ 0,1).  All these
+* configuration settings can be gathered by booting another OS which
+* recognizes the card already.
+*
+* I have made things 'just work' for the non-modular case on such
+* machines when configured properly.
+*
+* David Luyer <luyer@ucs.uwa.edu.au>
+************************************************************************
+
 If you are using isapnp, follow the directions in its documentation to
 produce a configuration file.  Here is the relevant excerpt I use for
 my SAx card from my isapnp.conf:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/README linux.pre11.3/Documentation/sysctl/README
--- linux.vanilla/Documentation/sysctl/README	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/Documentation/sysctl/README	Mon Jul 19 23:29:00 1999
@@ -1,4 +1,4 @@
-Documentation for /proc/sys/		kernel version 2.2.5
+Documentation for /proc/sys/		kernel version 2.2.10
 	(c) 1998, 1999,  Rik van Riel <riel@nl.linux.org>
 
 'Why', I hear you ask, 'would anyone even _want_ documentation
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/fs.txt linux.pre11.3/Documentation/sysctl/fs.txt
--- linux.vanilla/Documentation/sysctl/fs.txt	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/Documentation/sysctl/fs.txt	Mon Jul 19 23:29:00 1999
@@ -1,4 +1,4 @@
-Documentation for /proc/sys/fs/*	kernel version 2.2.5
+Documentation for /proc/sys/fs/*	kernel version 2.2.10
 	(c) 1998, 1999,  Rik van Riel <riel@nl.linux.org>
 
 For general info and legal blurb, please look in README.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/kernel.txt linux.pre11.3/Documentation/sysctl/kernel.txt
--- linux.vanilla/Documentation/sysctl/kernel.txt	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/Documentation/sysctl/kernel.txt	Mon Jul 19 23:29:00 1999
@@ -1,4 +1,4 @@
-Documentation for /proc/sys/kernel/*	kernel version 2.2.5
+Documentation for /proc/sys/kernel/*	kernel version 2.2.10
 	(c) 1998, 1999,  Rik van Riel <riel@nl.linux.org>
 
 For general info and legal blurb, please look in README.
@@ -76,12 +76,21 @@
 
 domainname & hostname:
 
-These files can be controlled to set the domainname and
-hostname of your box. For the classic darkstar.frop.org
-a simple:
+These files can be used to set the NIS/YP domainname and the
+hostname of your box in exactly the same way as the commands
+domainname and hostname, i.e.:
 # echo "darkstar" > /proc/sys/kernel/hostname
-# echo "frop.org" > /proc/sys/kernel/domainname
-would suffice to set your hostname and domainname.
+# echo "mydomain" > /proc/sys/kernel/domainname
+has the same effect as
+# hostname "darkstar" > /proc/sys/kernel/hostname
+# domainname "mydomain" > /proc/sys/kernel/domainname
+
+Note, however, that the classic darkstar.frop.org has the
+hostname "darkstar" and DNS (Internet Domain Name Server)
+domainname "frop.org", not to be confused with the NIS (Network
+Information Service) or YP (Yellow Pages) domainname. These two
+domain names are in general different. For a detailed discussion
+see the hostname(1) man page.
 
 ==============================================================
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/sunrpc.txt linux.pre11.3/Documentation/sysctl/sunrpc.txt
--- linux.vanilla/Documentation/sysctl/sunrpc.txt	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/Documentation/sysctl/sunrpc.txt	Mon Jul 19 23:29:00 1999
@@ -1,4 +1,4 @@
-Documentation for /proc/sys/sunrpc/*	kernel version 2.2.5
+Documentation for /proc/sys/sunrpc/*	kernel version 2.2.10
 	(c) 1998, 1999,  Rik van Riel <riel@nl.linux.org>
 
 For general info and legal blurb, please look in README.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysctl/vm.txt linux.pre11.3/Documentation/sysctl/vm.txt
--- linux.vanilla/Documentation/sysctl/vm.txt	Thu May 27 22:11:48 1999
+++ linux.pre11.3/Documentation/sysctl/vm.txt	Mon Jul 19 23:29:00 1999
@@ -1,4 +1,4 @@
-Documentation for /proc/sys/vm/*	kernel version 2.2.5
+Documentation for /proc/sys/vm/*	kernel version 2.2.10
 	(c) 1998, 1999,  Rik van Riel <riel@nl.linux.org>
 
 For general info and legal blurb, please look in README.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Documentation/sysrq.txt linux.pre11.3/Documentation/sysrq.txt
--- linux.vanilla/Documentation/sysrq.txt	Sun Nov  8 15:08:50 1998
+++ linux.pre11.3/Documentation/sysrq.txt	Mon Jul 19 23:29:00 1999
@@ -9,8 +9,8 @@
 
 *  How do I enable the magic SysRQ key?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-You need to say yes to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
-configuring the kernel. This option is only available it 2.1.x or later
+You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when
+configuring the kernel. This option is only available in 2.1.x or later
 kernels.
 
 *  How do I use the magic SysRQ key?
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/MAINTAINERS linux.pre11.3/MAINTAINERS
--- linux.vanilla/MAINTAINERS	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/MAINTAINERS	Tue Jul 20 00:26:35 1999
@@ -16,8 +16,8 @@
 	SMC etherpower for that.)
 
 3.	Make sure your changes compile correctly in multiple
-	configurations. In paticular check changes work both as a module
-	and built into the kernel.
+	configurations. In particular check that changes work both as a
+	module and built into the kernel.
 
 4.	When you are happy with a change make it generally available for
 	testing and await feedback.
@@ -28,7 +28,7 @@
 	and variable names.  These aren't as silly as they seem. One
 	job the maintainers (and especially Linus) do is to keep things
 	looking the same. Sometimes this means that the clever hack in
-	your driver to get around a problem actual needs to become a
+	your driver to get around a problem actually needs to become a
 	generalized kernel feature ready for next time. See 
 	Documentation/CodingStyle for guidance here.
 
@@ -49,8 +49,8 @@
 
 Maintainers List (try to look for most precise areas first)
 
-Note: For the hard of thinking, this list is meant to remain in Alphabetical
-order. If you could add yourselves to it in Alphabetical order that would
+Note: For the hard of thinking, this list is meant to remain in alphabetical
+order. If you could add yourselves to it in alphabetical order that would
 so much easier [Ed]
 
 P: Person
@@ -170,6 +170,12 @@
 W:	http://www.dandelion.com/Linux/
 S:	Maintained
 
+CIRRUS LOGIC GENERIC FBDEV DRIVER
+P:	Jeff Garzik
+M:	jgarzik@pobox.com
+L:	linux-fbdev@vuser.vu.union.edu
+S:	Maintained
+
 CONFIGURE, MENUCONFIG, XCONFIG
 P:	Michael Elizabeth Chastain
 M:	mec@shout.net
@@ -258,6 +264,18 @@
 L:	linux-eata@i-connect.net, linux-scsi@vger.rutgers.edu
 S:	Maintained
 
+COMPAQ SMART2 RAID DRIVER
+P:	Charles White	
+M:	Charles White <arrays@compaq.com>
+L:	compaqandlinux@yps.org	
+S:	Maintained
+
+DAC960 RAID DRIVER
+P:	Leonard N. Zubkoff
+M:	Leonard N. Zubkoff <lnz@dandelion.com>
+L:	linux-raid@vger.rutgers.edu
+S:	Maintained
+
 EATA ISA/EISA/PCI SCSI DRIVER
 P:	Dario Ballabio
 M:	dario@milano.europe.dg.com
@@ -447,6 +465,12 @@
 L:	linux-pmac@samba.anu.edu.au
 S:	Maintained
 
+LOGICAL VOLUME MANAGER
+P:    Heinz Mauelshagen
+M:    linux.LVM@ez-darmstadt.telekom.de
+W:    http://linux.msede.com/lvm
+S:    Maintained
+
 M68K
 P:	Jes Sorensen
 M:	Jes.Sorensen@cern.ch
@@ -560,6 +584,16 @@
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
+OLYMPIC NETWORK DRIVER
+P:	Peter De Shrijver
+M:	p2@ace.ulyssis.sutdent.kuleuven.ac.be	
+P:	Mike Phillips
+M:	phillim@amtrak.com
+L:	linux-net@vger.rutgers.edu
+L:	linux-tr@emissary.aus-etc.com
+W:	http://www.linuxtr.net
+S:	Maintained
+
 OPL3-SA2, SA3, and SAx DRIVER
 P:	Scott Murray
 M:	scottm@interlog.com
@@ -626,7 +660,7 @@
 
 REAL TIME CLOCK DRIVER
 P:	Paul Gortmaker
-M	gpg109@rsphy1.anu.edu.au
+M:	gpg109@rsphy1.anu.edu.au
 L:	linux-kernel@vger.rutgers.edu
 S:	Maintained
 
@@ -655,11 +689,6 @@
 W:	http://www.torque.net/sg
 S:	Maintained
 
-SCSI GENERIC
-L:	linux-scsi@vger.rutgers.edu
-M:	douglas.gilbert@rbcds.com
-S:	Maintained
-
 SCSI SUBSYSTEM
 L:	linux-scsi@vger.rutgers.edu
 S:	Unmaintained
@@ -678,9 +707,10 @@
 S:	Maintained
 
 SMB FILESYSTEM
-P:	Volker Lendecke
-M:	vl@kki.org
-L:	samba@listproc.anu.edu.au
+P:	Andrew Tridgell
+M:	tridge@samba.org
+W:	http://samba.org/
+L:	samba@samba.org
 S:	Maintained
 
 SMP: (except SPARC)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/Makefile linux.pre11.3/Makefile
--- linux.vanilla/Makefile	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/Makefile	Mon Jul 19 23:51:45 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 2
-SUBLEVEL = 10
+SUBLEVEL = 11
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -27,6 +27,7 @@
 AR	=$(CROSS_COMPILE)ar
 NM	=$(CROSS_COMPILE)nm
 STRIP	=$(CROSS_COMPILE)strip
+OBJCOPY	=$(CROSS_COMPILE)objcopy
 OBJDUMP	=$(CROSS_COMPILE)objdump
 MAKE	=make
 GENKSYMS=/sbin/genksyms
@@ -70,7 +71,7 @@
 #
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory 
 # relocations required by build roots.  This is not defined in the
-# makefile but the arguement can be passed to make if needed.
+# makefile but the argument can be passed to make if needed.
 #
 
 #
@@ -88,6 +89,9 @@
 
 CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
 
+# use '-fno-strict-aliasing', but only if the compiler can take it
+CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
+
 ifdef CONFIG_SMP
 CFLAGS += -D__SMP__
 AFLAGS += -D__SMP__
@@ -162,6 +166,10 @@
 DRIVERS := $(DRIVERS) drivers/pnp/pnp.a
 endif
 
+ifdef CONFIG_SGI
+DRIVERS := $(DRIVERS) drivers/sgi/sgi.a
+endif
+
 ifdef CONFIG_VT
 DRIVERS := $(DRIVERS) drivers/video/video.a
 endif
@@ -174,6 +182,10 @@
 DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a
 endif
 
+ifeq ($(CONFIG_TC),y)
+DRIVERS := $(DRIVERS) drivers/tc/tc.a
+endif
+
 ifeq ($(CONFIG_USB),y)
 DRIVERS := $(DRIVERS) drivers/usb/usb.a
 endif
@@ -287,7 +299,7 @@
 fs lib mm ipc kernel drivers net: dummy
 	$(MAKE) $(subst $@, _dir_$@, $@)
 
-MODFLAGS = -DMODULE
+MODFLAGS += -DMODULE
 ifdef CONFIG_MODULES
 ifdef CONFIG_MODVERSIONS
 MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h
@@ -323,7 +335,7 @@
 	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; \
+	for f in *.o; do [ -r $$f ] && echo $$f; done > $$MODLIB/.allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \
 	if [ -s $$MODLIB/.misc ]; then inst_mod $$MODLIB/.misc misc; fi; \
 	rm -f $$MODLIB/.misc $$MODLIB/.allmods; \
@@ -343,8 +355,8 @@
 
 clean:	archclean
 	rm -f kernel/ksyms.lst include/linux/compile.h
-	rm -f core `find . -name '*.[oas]' ! -regex '.*lxdialog/.*' \
-		! -regex '.*ksymoops/.*' -print`
+	rm -f core `find . -name '*.[oas]' ! \( -regex '.*lxdialog/.*' \
+		-o -regex '.*ksymoops/.*' \) -print`
 	rm -f core `find . -type f -name 'core' -print`
 	rm -f core `find . -name '.*.flags' -print`
 	rm -f vmlinux System.map
@@ -391,7 +403,7 @@
 sums:
 	find . -type f -print | sort | xargs sum > .SUMS
 
-dep-files: scripts/mkdep archdep include/linux/version.h
+dep-files: scripts/mkdep archdep include/linux/version.h new-genksyms
 	scripts/mkdep init/*.c > .depend
 	scripts/mkdep `find $(FINDHPATH) -follow -name \*.h ! -name modversions.h -print` > .hdepend
 #	set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep ;done
@@ -401,7 +413,19 @@
 MODVERFILE :=
 
 ifdef CONFIG_MODVERSIONS
+
 MODVERFILE := $(TOPDIR)/include/linux/modversions.h
+
+new-genksyms:
+	@$(GENKSYMS) -k $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) </dev/null \
+	2>/dev/null || ( echo -e "\nYou need a new version of the genksyms\
+	program, which is part of\nthe modutils package. Please read the file\
+	Documentation/Changes\nfor more information.\n"; exit 1 )
+
+else
+
+new-genksyms:
+
 endif
 
 depend dep: dep-files $(MODVERFILE)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/README linux.pre11.3/README
--- linux.vanilla/README	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/README	Mon Jul 19 23:51:51 1999
@@ -91,7 +91,7 @@
 
 SOFTWARE REQUIREMENTS
 
-   Compiling and running the 2.2.x kernels requires up-to-date
+   Compiling and running the 2.2.xx kernels requires up-to-date
    versions of various software packages.  Consult
    ./Documentation/Changes for the minimum version numbers required
    and how to get updates for these packages.  Beware that using
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/boot/bootp.c linux.pre11.3/arch/alpha/boot/bootp.c
--- linux.vanilla/arch/alpha/boot/bootp.c	Sun Nov  8 15:08:23 1998
+++ linux.pre11.3/arch/alpha/boot/bootp.c	Mon Jul 19 23:28:33 1999
@@ -200,11 +200,11 @@
         load(START_ADDR+(4*KERNEL_SIZE), KERNEL_ORIGIN, KERNEL_SIZE);
         load(START_ADDR, START_ADDR+(4*KERNEL_SIZE), KERNEL_SIZE);
 
-	memset((char*)ZERO_PAGE, 0, PAGE_SIZE);
-	strcpy((char*)ZERO_PAGE, envval);
+	memset((char*)ZERO_PAGE(0), 0, PAGE_SIZE);
+	strcpy((char*)ZERO_PAGE(0), envval);
 #ifdef INITRD_SIZE
-	((long *)(ZERO_PAGE+256))[0] = initrd_start;
-	((long *)(ZERO_PAGE+256))[1] = INITRD_SIZE;
+	((long *)(ZERO_PAGE(0)+256))[0] = initrd_start;
+	((long *)(ZERO_PAGE(0)+256))[1] = INITRD_SIZE;
 #endif
 
 	runkernel();
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/boot/main.c linux.pre11.3/arch/alpha/boot/main.c
--- linux.vanilla/arch/alpha/boot/main.c	Wed Mar 10 21:13:00 1999
+++ linux.pre11.3/arch/alpha/boot/main.c	Mon Jul 19 23:28:33 1999
@@ -182,7 +182,7 @@
 		nbytes = 0;
 	}
 	envval[nbytes] = '\0';
-	strcpy((char*)ZERO_PAGE, envval);
+	strcpy((char*)ZERO_PAGE(0), envval);
 
 	srm_printk(" Ok\nNow booting the kernel\n");
 	runkernel();
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/Makefile linux.pre11.3/arch/alpha/kernel/Makefile
--- linux.vanilla/arch/alpha/kernel/Makefile	Thu Jan 14 01:25:21 1999
+++ linux.pre11.3/arch/alpha/kernel/Makefile	Mon Jul 19 23:28:33 1999
@@ -105,7 +105,7 @@
 endif
 
 # Device support
-ifdef CONFIG_ALPHA_MIATA
+ifneq ($(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
 O_OBJS   += es1888.o
 endif
 ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_cia.c linux.pre11.3/arch/alpha/kernel/core_cia.c
--- linux.vanilla/arch/alpha/kernel/core_cia.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/core_cia.c	Mon Jul 19 23:28:34 1999
@@ -535,8 +535,6 @@
 		 * Set up the PCI->physical memory translation windows.
 		 * For now, windows 1,2 and 3 are disabled.  In the future,
 		 * we may want to use them to do scatter/gather DMA. 
-		 *
-		 * Window 0 goes at 1 GB and is 1 GB large.
 		 */
 
 		*(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_mcpcia.c linux.pre11.3/arch/alpha/kernel/core_mcpcia.c
--- linux.vanilla/arch/alpha/kernel/core_mcpcia.c	Sun Nov  8 15:08:25 1998
+++ linux.pre11.3/arch/alpha/kernel/core_mcpcia.c	Mon Jul 19 23:28:34 1999
@@ -18,7 +18,6 @@
 #include <asm/system.h>
 #include <asm/pci.h>
 #include <asm/hwrpb.h>
-#include <asm/mmu_context.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/core_pyxis.c linux.pre11.3/arch/alpha/kernel/core_pyxis.c
--- linux.vanilla/arch/alpha/kernel/core_pyxis.c	Sun Nov  8 15:08:25 1998
+++ linux.pre11.3/arch/alpha/kernel/core_pyxis.c	Mon Jul 19 23:28:34 1999
@@ -425,17 +425,22 @@
 {
 	/*
 	 * Set up the PCI->physical memory translation windows.
-	 * For now, windows 1,2 and 3 are disabled.  In the future, we may
+	 * For now, windows 2 and 3 are disabled.  In the future, we may
 	 * want to use them to do scatter/gather DMA. 
 	 *
 	 * Window 0 goes at 1 GB and is 1 GB large.
+	 * Window 1 goes at 2 GB and is 1 GB large.
 	 */
 
-	*(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+	*(vuip)PYXIS_W0_BASE = PYXIS_DMA_WIN_BASE_DEFAULT | 1U;
 	*(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
 	*(vuip)PYXIS_T0_BASE = 0;
 
-	*(vuip)PYXIS_W1_BASE = 0x0 ;
+	*(vuip)PYXIS_W1_BASE = (PYXIS_DMA_WIN_BASE_DEFAULT +
+				PYXIS_DMA_WIN_SIZE_DEFAULT) | 1U;
+	*(vuip)PYXIS_W1_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+	*(vuip)PYXIS_T1_BASE = PYXIS_DMA_WIN_SIZE_DEFAULT;
+
 	*(vuip)PYXIS_W2_BASE = 0x0 ;
 	*(vuip)PYXIS_W3_BASE = 0x0 ;
 	mb();
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/entry.S linux.pre11.3/arch/alpha/kernel/entry.S
--- linux.vanilla/arch/alpha/kernel/entry.S	Thu May 27 22:11:48 1999
+++ linux.pre11.3/arch/alpha/kernel/entry.S	Mon Jul 19 23:28:33 1999
@@ -527,6 +527,8 @@
 	call_pal PAL_swpctx
 	unop
 	bsr	$1,undo_switch_stack
+	lda	$8,0x3fff
+	bic	$30,$8,$8
 	mov	$17,$0
 	ret	$31,($26),1
 .end alpha_switch_to
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/es1888.c linux.pre11.3/arch/alpha/kernel/es1888.c
--- linux.vanilla/arch/alpha/kernel/es1888.c	Sun Nov  8 15:08:24 1998
+++ linux.pre11.3/arch/alpha/kernel/es1888.c	Mon Jul 19 23:28:33 1999
@@ -32,6 +32,7 @@
 		continue;
 	inb(0x022a);			/* pause */
 	outb(0xc6, 0x022c);		/* enable extended mode */
+	inb(0x022a);			/* pause, also forces the write */
 	while (inb(0x022c) & 0x80)	/* wait for bit 7 to deassert */
 		continue;
 	outb(0xb1, 0x022c);		/* setup for write to Interrupt CR */
@@ -44,4 +45,5 @@
 	while (inb(0x022c) & 0x80)	/* wait for bit 7 to deassert */
 		continue;
 	outb(0x18, 0x022c);		/* set DMA channel 1 */
+	inb(0x022c);			/* force the write */
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/irq.h linux.pre11.3/arch/alpha/kernel/irq.h
--- linux.vanilla/arch/alpha/kernel/irq.h	Thu Dec 31 18:10:39 1998
+++ linux.pre11.3/arch/alpha/kernel/irq.h	Mon Jul 19 23:28:33 1999
@@ -24,6 +24,23 @@
 
 extern void handle_irq(int irq, int ack, struct pt_regs * regs);
 
+extern char _stext;
+static inline void alpha_do_profile (unsigned long pc)
+{
+	if (prof_buffer && current->pid) {
+		pc -= (unsigned long) &_stext;
+		pc >>= prof_shift;
+		/*
+		 * Don't ignore out-of-bounds PC values silently,
+		 * put them into the last histogram slot, so if
+		 * present, they will show up as a sharp peak.
+		 */
+		if (pc > prof_len - 1)
+			pc = prof_len - 1;
+		atomic_inc((atomic_t *)&prof_buffer[pc]);
+	}
+}
+
 #define RTC_IRQ    8
 #ifdef CONFIG_RTC
 #define TIMER_IRQ  0			 /* timer is the pit */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/machvec.h linux.pre11.3/arch/alpha/kernel/machvec.h
--- linux.vanilla/arch/alpha/kernel/machvec.h	Thu Jan 14 01:25:21 1999
+++ linux.pre11.3/arch/alpha/kernel/machvec.h	Mon Jul 19 23:28:34 1999
@@ -36,7 +36,6 @@
 
 #define DO_EV4_MMU							\
 	max_asn:			EV4_MAX_ASN,			\
-	mmu_context_mask:		~0UL,				\
 	mv_get_mmu_context:		ev4_get_mmu_context,		\
 	mv_flush_tlb_current:		ev4_flush_tlb_current,		\
 	mv_flush_tlb_other:		ev4_flush_tlb_other,		\
@@ -44,7 +43,6 @@
 
 #define DO_EV5_MMU							\
 	max_asn:			EV5_MAX_ASN,			\
-	mmu_context_mask:		~0UL,				\
 	mv_get_mmu_context:		ev5_get_mmu_context,		\
 	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
 	mv_flush_tlb_other:		ev5_flush_tlb_other,		\
@@ -52,7 +50,6 @@
 
 #define DO_EV6_MMU							\
 	max_asn:			EV6_MAX_ASN,			\
-	mmu_context_mask:		0xfffffffffful,			\
 	mv_get_mmu_context:		ev5_get_mmu_context,		\
 	mv_flush_tlb_current:		ev5_flush_tlb_current,		\
 	mv_flush_tlb_other:		ev5_flush_tlb_other,		\
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/osf_sys.c linux.pre11.3/arch/alpha/kernel/osf_sys.c
--- linux.vanilla/arch/alpha/kernel/osf_sys.c	Thu May 27 22:11:48 1999
+++ linux.pre11.3/arch/alpha/kernel/osf_sys.c	Mon Jul 19 23:28:33 1999
@@ -925,6 +925,7 @@
 			return -EINVAL;
 		cpu = (struct percpu_struct*)
 		  ((char*)hwrpb + hwrpb->processor_offset);
+		w = cpu->type;
 		if (put_user(w, (unsigned long *)buffer))
 			return -EFAULT;
 		return 1;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/process.c linux.pre11.3/arch/alpha/kernel/process.c
--- linux.vanilla/arch/alpha/kernel/process.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/process.c	Mon Jul 19 23:52:02 1999
@@ -76,7 +75,7 @@
 }
 
 #ifdef __SMP__
-void
+int
 cpu_idle(void *unused)
 {
 	/* An endless idle loop with no priority at all.  */
@@ -329,7 +328,6 @@
 	p->tss.ksp = (unsigned long) childstack;
 	p->tss.pal_flags = 1;	/* set FEN, clear everything else */
 	p->tss.flags = current->tss.flags;
-	p->mm->context = 0;
 
 	return 0;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/proto.h linux.pre11.3/arch/alpha/kernel/proto.h
--- linux.vanilla/arch/alpha/kernel/proto.h	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/proto.h	Mon Jul 19 23:28:33 1999
@@ -193,7 +193,7 @@
 
 /* process.c */
 extern void generic_kill_arch (int mode, char *reboot_cmd);
-extern void cpu_idle(void *) __attribute__((noreturn));
+extern int cpu_idle(void *) __attribute__((noreturn));
 
 /* ptrace.c */
 extern int ptrace_set_bpt (struct task_struct *child);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/setup.c linux.pre11.3/arch/alpha/kernel/setup.c
--- linux.vanilla/arch/alpha/kernel/setup.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/setup.c	Mon Jul 19 23:28:33 1999
@@ -66,7 +66,7 @@
  * initialized, we need to copy things out into a more permanent
  * place.
  */
-#define PARAM			ZERO_PAGE
+#define PARAM			ZERO_PAGE(0)
 #define COMMAND_LINE		((char*)(PARAM + 0x0000))
 #define COMMAND_LINE_SIZE	256
 #define INITRD_START		(*(unsigned long *) (PARAM+0x100))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/signal.c linux.pre11.3/arch/alpha/kernel/signal.c
--- linux.vanilla/arch/alpha/kernel/signal.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/signal.c	Mon Jul 19 23:52:02 1999
@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include <linux/signal.h>
 #include <linux/stddef.h>
 
 #include <asm/bitops.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/smp.c linux.pre11.3/arch/alpha/kernel/smp.c
--- linux.vanilla/arch/alpha/kernel/smp.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/smp.c	Mon Jul 19 23:52:02 1999
@@ -95,6 +95,8 @@
 smp_store_cpu_info(int cpuid)
 {
 	cpu_data[cpuid].loops_per_sec = loops_per_sec;
+	cpu_data[cpuid].last_asn
+	  = (cpuid << WIDTH_HARDWARE_ASN) + ASN_FIRST_VERSION;
 }
 
 /*
@@ -105,12 +107,6 @@
 {
 	cpu_data[cpuid].prof_counter = 1;
 	cpu_data[cpuid].prof_multiplier = 1;
-
-#ifdef NOT_YET_PROFILING
-	load_profile_irq(mid_xlate[cpu], lvl14_resolution);
-	if (cpu == smp_boot_cpuid)
-		enable_pil_irq(14);
-#endif
 }
 
 /*
@@ -587,11 +583,9 @@
 	int user = user_mode(regs);
 	struct cpuinfo_alpha *data = &cpu_data[cpu];
 
-#ifdef NOT_YET_PROFILING
-	clear_profile_irq(mid_xlate[cpu]);
+	/* Record kernel PC */
 	if (!user)
 		alpha_do_profile(regs->pc);
-#endif
 
 	if (!--data->prof_counter) {
 		/* We need to make like a normal interrupt -- otherwise
@@ -628,28 +622,7 @@
 int __init
 setup_profiling_timer(unsigned int multiplier)
 {
-#ifdef NOT_YET_PROFILING
-	int i;
-	unsigned long flags;
-
-	/* Prevent level14 ticker IRQ flooding. */
-	if((!multiplier) || (lvl14_resolution / multiplier) < 500)
-	        return -EINVAL;
-
-	save_and_cli(flags);
-	for (i = 0; i < NR_CPUS; i++) {
-	        if (cpu_present_mask & (1L << i)) {
-	                load_profile_irq(mid_xlate[i],
-					 lvl14_resolution / multiplier);
-	                prof_multiplier[i] = multiplier;
-	        }
-	}
-	restore_flags(flags);
-
-	return 0;
-#else
 	return -EINVAL;
-#endif
 }
 
 
@@ -891,9 +864,11 @@
 void
 flush_tlb_mm(struct mm_struct *mm)
 {
-	if (mm == current->mm)
+	if (mm == current->mm) {
 		flush_tlb_current(mm);
-	else
+		if (atomic_read(&mm->count) == 1)
+			return;
+	} else
 		flush_tlb_other(mm);
 
 	if (smp_call_function(ipi_flush_tlb_mm, mm, 1, 1)) {
@@ -921,15 +896,17 @@
 	struct flush_tlb_page_struct data;
 	struct mm_struct *mm = vma->vm_mm;
 
+	if (mm == current->mm) {
+		flush_tlb_current_page(mm, vma, addr);
+		if (atomic_read(&current->mm->count) == 1)
+			return;
+	} else
+		flush_tlb_other(mm);
+	
 	data.vma = vma;
 	data.mm = mm;
 	data.addr = addr;
 
-	if (mm == current->mm)
-		flush_tlb_current_page(mm, vma, addr);
-	else
-		flush_tlb_other(mm);
-	
 	if (smp_call_function(ipi_flush_tlb_page, &data, 1, 1)) {
 		printk(KERN_CRIT "flush_tlb_page: timed out\n");
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/sys_dp264.c linux.pre11.3/arch/alpha/kernel/sys_dp264.c
--- linux.vanilla/arch/alpha/kernel/sys_dp264.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/sys_dp264.c	Mon Jul 19 23:28:34 1999
@@ -393,8 +393,8 @@
 {
 	layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
 	common_pci_fixup(monet_map_irq, monet_swizzle);
-	/* es1888_init(); */ /* later? */
 	SMC669_Init(1);
+	es1888_init();
 }
 
 static void __init
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/kernel/time.c linux.pre11.3/arch/alpha/kernel/time.c
--- linux.vanilla/arch/alpha/kernel/time.c	Tue Jun 15 16:49:45 1999
+++ linux.pre11.3/arch/alpha/kernel/time.c	Mon Jul 19 23:28:33 1999
@@ -94,6 +94,11 @@
 	smp_percpu_timer_interrupt(regs);
 	if (smp_processor_id() != smp_boot_cpuid)
 		return;
+#else
+	/* Not SMP, do kernel PC profiling here */
+	if (!user_mode(regs)) {
+		alpha_do_profile(regs->pc);
+	}
 #endif
 
 	write_lock(&xtime_lock);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/math-emu/ieee-math.c linux.pre11.3/arch/alpha/math-emu/ieee-math.c
--- linux.vanilla/arch/alpha/math-emu/ieee-math.c	Thu May 27 22:11:48 1999
+++ linux.pre11.3/arch/alpha/math-emu/ieee-math.c	Mon Jul 19 23:28:34 1999
@@ -704,20 +704,21 @@
  *       FPCR_INV if invalid operation occurred, etc.
  */
 unsigned long
-ieee_CVTQT (int f, unsigned long a, unsigned long *b)
+ieee_CVTQT (int f, long a, unsigned long *b)
 {
 	EXTENDED op_b;
 
-	op_b.s    = 0;
-	op_b.f[0] = a;
-	op_b.f[1] = 0;
-	if (sign(a) < 0) {
-		op_b.s = 1;
-		op_b.f[0] = -a;
+	if (a != 0) {
+		op_b.s = (a < 0 ? 1 : 0);
+		op_b.f[0] = (a < 0 ? -a : a);
+		op_b.f[1] = 0;
+		op_b.e = 55;
+		normalize(&op_b);
+		return round_t_ieee(f, &op_b, b);
+	} else {
+		*b = 0;
+		return 0;
 	}
-	op_b.e = 55;
-	normalize(&op_b);
-	return round_t_ieee(f, &op_b, b);
 }
 
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/math-emu/ieee-math.h linux.pre11.3/arch/alpha/math-emu/ieee-math.h
--- linux.vanilla/arch/alpha/math-emu/ieee-math.h	Thu May 27 22:11:48 1999
+++ linux.pre11.3/arch/alpha/math-emu/ieee-math.h	Mon Jul 19 23:28:34 1999
@@ -20,7 +20,7 @@
 extern unsigned long ieee_CVTST (int rm, unsigned long a, unsigned long *b);
 extern unsigned long ieee_CVTTS (int rm, unsigned long a, unsigned long *b);
 extern unsigned long ieee_CVTQS (int rm, unsigned long a, unsigned long *b);
-extern unsigned long ieee_CVTQT (int rm, unsigned long a, unsigned long *b);
+extern unsigned long ieee_CVTQT (int rm, long a, unsigned long *b);
 extern unsigned long ieee_CVTTQ (int rm, unsigned long a, unsigned long *b);
 
 extern unsigned long ieee_CMPTEQ (unsigned long a, unsigned long b,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/mm/fault.c linux.pre11.3/arch/alpha/mm/fault.c
--- linux.vanilla/arch/alpha/mm/fault.c	Sun Nov  8 15:08:23 1998
+++ linux.pre11.3/arch/alpha/mm/fault.c	Mon Jul 19 23:52:02 1999
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <asm/io.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/mmu_context.h>
@@ -28,64 +29,20 @@
 extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
 
 
-#ifdef __SMP__
-unsigned long last_asn[NR_CPUS] = { /* gag */
-  ASN_FIRST_VERSION +  (0 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (1 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (2 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (3 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (4 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (5 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (6 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (7 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (8 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION +  (9 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (10 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (11 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (12 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (13 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (14 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (15 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (16 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (17 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (18 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (19 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (20 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (21 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (22 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (23 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (24 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (25 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (26 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (27 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (28 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (29 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (30 << WIDTH_HARDWARE_ASN),
-  ASN_FIRST_VERSION + (31 << WIDTH_HARDWARE_ASN)
-};
-#else
-unsigned long asn_cache = ASN_FIRST_VERSION;
-#endif /* __SMP__ */
-
 /*
- * Select a new ASN for a task.
+ * Force a new ASN for a task.
  */
 
+#ifndef __SMP__
+unsigned long last_asn = ASN_FIRST_VERSION;
+#endif
+
 void
 get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
 {
-	unsigned long asn = asn_cache;
-
-	if ((asn & HARDWARE_ASN_MASK) < MAX_ASN)
-		++asn;
-	else {
-		tbiap();
-		imb();
-		asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
-	}
-	asn_cache = asn;
-	mm->context = asn;			/* full version + asn */
-	p->tss.asn = asn & HARDWARE_ASN_MASK;	/* just asn */
+	unsigned long new = __get_new_mmu_context();
+	mm->context = new;
+	p->tss.asn = new & HARDWARE_ASN_MASK;
 }
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/alpha/mm/init.c linux.pre11.3/arch/alpha/mm/init.c
--- linux.vanilla/arch/alpha/mm/init.c	Tue Jun 15 16:49:46 1999
+++ linux.pre11.3/arch/alpha/mm/init.c	Mon Jul 19 23:28:33 1999
@@ -174,7 +174,7 @@
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
 
-static struct thread_struct *
+static inline struct thread_struct *
 load_PCB(struct thread_struct * pcb)
 {
 	register unsigned long sp __asm__("$30");
@@ -219,7 +219,7 @@
 
 	/* Initialize the kernel's page tables.  Linux puts the vptb in
 	   the last slot of the L1 page table.  */
-	memset((void *) ZERO_PAGE, 0, PAGE_SIZE);
+	memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE);
 	memset(swapper_pg_dir, 0, PAGE_SIZE);
 	newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
 	pgd_val(swapper_pg_dir[1023]) =
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/process.c linux.pre11.3/arch/arm/kernel/process.c
--- linux.vanilla/arch/arm/kernel/process.c	Sun Nov  8 15:08:44 1998
+++ linux.pre11.3/arch/arm/kernel/process.c	Mon Jul 19 23:52:23 1999
@@ -27,9 +27,7 @@
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/config.h>
-#include <linux/unistd.h>
 #include <linux/delay.h>
-#include <linux/smp.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/arm/kernel/time.c linux.pre11.3/arch/arm/kernel/time.c
--- linux.vanilla/arch/arm/kernel/time.c	Wed Mar 24 10:55:10 1999
+++ linux.pre11.3/arch/arm/kernel/time.c	Mon Jul 19 23:52:23 1999
@@ -23,8 +23,6 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/Makefile linux.pre11.3/arch/i386/Makefile
--- linux.vanilla/arch/i386/Makefile	Thu Dec 31 18:10:39 1998
+++ linux.pre11.3/arch/i386/Makefile	Mon Jul 19 23:28:28 1999
@@ -62,6 +62,13 @@
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
+vmlinux: arch/i386/vmlinux.lds
+
+arch/i386/vmlinux.lds: arch/i386/vmlinux.lds.S FORCE
+	gcc -E -C -P -I$(HPATH) -imacros $(HPATH)/asm-i386/page_offset.h -Ui386 arch/i386/vmlinux.lds.S >arch/i386/vmlinux.lds
+
+FORCE: ;
+
 zImage: vmlinux
 	@$(MAKEBOOT) zImage
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/boot/setup.S linux.pre11.3/arch/i386/boot/setup.S
--- linux.vanilla/arch/i386/boot/setup.S	Tue Jun 15 16:49:46 1999
+++ linux.pre11.3/arch/i386/boot/setup.S	Mon Jul 19 23:28:27 1999
@@ -757,11 +757,11 @@
 ! with no keyboard attached...
 
 empty_8042:
-       push    cx
-       mov     cx,#0xFFFF
+       push    ecx
+       mov     ecx,#0xFFFFFF
 
 empty_8042_loop:
-       dec     cx
+       dec     ecx
        jz      empty_8042_end_loop
 
 	call	delay
@@ -775,7 +775,7 @@
 	test	al,#2		! is input buffer full?
 	jnz	empty_8042_loop	! yes - loop
 empty_8042_end_loop:
-        pop     cx
+        pop     ecx
 	ret
 
 !
Binary files linux.vanilla/arch/i386/boot/tools/build and linux.pre11.3/arch/i386/boot/tools/build differ
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/config.in linux.pre11.3/arch/i386/config.in
--- linux.vanilla/arch/i386/config.in	Wed Apr 28 19:14:24 1999
+++ linux.pre11.3/arch/i386/config.in	Mon Jul 19 23:28:28 1999
@@ -33,6 +33,10 @@
   define_bool CONFIG_X86_GOOD_APIC y
 fi
 
+choice 'Maximum Physical Memory' \
+	"1GB		CONFIG_1GB \
+	 2GB		CONFIG_2GB" 1GB
+
 bool 'Math emulation' CONFIG_MATH_EMULATION
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/defconfig linux.pre11.3/arch/i386/defconfig
--- linux.vanilla/arch/i386/defconfig	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/arch/i386/defconfig	Mon Jul 19 23:52:37 1999
@@ -21,6 +21,8 @@
 CONFIG_X86_POPAD_OK=y
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
+CONFIG_1GB=y
+# CONFIG_2GB is not set
 # CONFIG_MATH_EMULATION is not set
 # CONFIG_MTRR is not set
 CONFIG_SMP=y
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/i386_ksyms.c linux.pre11.3/arch/i386/kernel/i386_ksyms.c
--- linux.vanilla/arch/i386/kernel/i386_ksyms.c	Thu May 27 22:11:49 1999
+++ linux.pre11.3/arch/i386/kernel/i386_ksyms.c	Mon Jul 19 23:28:30 1999
@@ -42,6 +42,8 @@
 EXPORT_SYMBOL(disable_irq_nosync);
 EXPORT_SYMBOL(kernel_thread);
 
+EXPORT_SYMBOL(init_mm);
+
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__down_failed_trylock);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/irq.c linux.pre11.3/arch/i386/kernel/irq.c
--- linux.vanilla/arch/i386/kernel/irq.c	Thu May 27 22:11:49 1999
+++ linux.pre11.3/arch/i386/kernel/irq.c	Mon Jul 19 23:53:05 1999
@@ -139,7 +139,7 @@
 /*
  * Controller mappings for all interrupt sources:
  */
-irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
 
 
 /*
@@ -927,6 +927,17 @@
 		return;
 
 	spin_lock_irqsave(&irq_controller_lock,flags);
+
+#ifdef __SMP__
+        /* Make sure no interrupt handler is in progress when we
+           manipulate the action list and free the structure */
+        while (irq_desc[irq].status & IRQ_INPROGRESS) {
+                spin_unlock_irqrestore(&irq_controller_lock,flags);
+                udelay(1000);
+                spin_lock_irqsave(&irq_controller_lock,flags);
+        }
+#endif
+
 	for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
 		if (action->dev_id != dev_id)
 			continue;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/kernel/irq.h linux.pre11.3/arch/i386/kernel/irq.h
--- linux.vanilla/arch/i386/kernel/irq.h	Thu May 27 22:11:49 1999
+++ linux.pre11.3/arch/i386/kernel/irq.h	Tue Jul 20 01:50:34 1999
@@ -40,6 +40,7 @@
 	struct hw_interrupt_type *handler;	/* handle/enable/disable functions */
 	struct irqaction *action;		/* IRQ action list */
 	unsigned int depth;			/* Disable depth for nested irq disables */
+	unsigned int unused[4];
 } irq_desc_t;
 
 /*
@@ -214,8 +215,8 @@
 	"\n" __ALIGN_STR"\n" \
 	"common_interrupt:\n\t" \
 	SAVE_ALL \
-	"pushl $ret_from_intr\n\t" \
-	"jmp "SYMBOL_NAME_STR(do_IRQ));
+	"call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \
+	"jmp ret_from_intr\n");
 
 /*
  * subtle. orig_eax is used by the signal code to distinct between
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/math-emu/fpu_emu.h linux.pre11.3/arch/i386/math-emu/fpu_emu.h
--- linux.vanilla/arch/i386/math-emu/fpu_emu.h	Sun Nov  8 15:08:21 1998
+++ linux.pre11.3/arch/i386/math-emu/fpu_emu.h	Mon Jul 19 23:53:16 1999
@@ -165,8 +165,6 @@
 #define signpositive(a) ( (signbyte(a) & 0x80) == 0 )
 #define signnegative(a) (signbyte(a) & 0x80)
 
-#include "fpu_proto.h"
-
 static inline void reg_copy(FPU_REG const *x, FPU_REG *y)
 {
   *(short *)&(y->exp) = *(const short *)&(x->exp); 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/mm/init.c linux.pre11.3/arch/i386/mm/init.c
--- linux.vanilla/arch/i386/mm/init.c	Tue Jan 26 09:44:20 1999
+++ linux.pre11.3/arch/i386/mm/init.c	Mon Jul 19 23:53:23 1999
@@ -168,6 +168,8 @@
 	printk("%d reserved pages\n",reserved);
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
+	printk("%ld pages in file cache\n",page_cache_size-cached);
+	printk("%ld pages in page cache\n",page_cache_size);
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
 	show_buffers();
 #ifdef CONFIG_NET
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/mm/ioremap.c linux.pre11.3/arch/i386/mm/ioremap.c
--- linux.vanilla/arch/i386/mm/ioremap.c	Thu Dec  3 14:11:59 1998
+++ linux.pre11.3/arch/i386/mm/ioremap.c	Mon Jul 19 23:28:28 1999
@@ -93,12 +93,17 @@
 {
 	void * addr;
 	struct vm_struct * area;
-	unsigned long offset;
+	unsigned long offset, last_addr;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
 
 	/*
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
-	if (phys_addr >= 0xA0000 && (phys_addr+size) <= 0x100000)
+	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
 		return phys_to_virt(phys_addr);
 
 	/*
@@ -112,13 +117,7 @@
 	 */
 	offset = phys_addr & ~PAGE_MASK;
 	phys_addr &= PAGE_MASK;
-	size = PAGE_ALIGN(size + offset);
-
-	/*
-	 * Don't allow mappings that wrap..
-	 */
-	if (!size || size > phys_addr + size)
-		return NULL;
+	size = PAGE_ALIGN(last_addr) - phys_addr;
 
 	/*
 	 * Ok, go for it..
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/vmlinux.lds linux.pre11.3/arch/i386/vmlinux.lds
--- linux.vanilla/arch/i386/vmlinux.lds	Mon Dec 28 23:09:40 1998
+++ linux.pre11.3/arch/i386/vmlinux.lds	Tue Jul 20 01:51:19 1999
@@ -1,12 +1,12 @@
 /* ld script to make i386 Linux kernel
- * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
  */
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
 ENTRY(_start)
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
+  . = 0xC0000000  + 0x100000;
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/i386/vmlinux.lds.S linux.pre11.3/arch/i386/vmlinux.lds.S
--- linux.vanilla/arch/i386/vmlinux.lds.S	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/i386/vmlinux.lds.S	Mon Jul 19 23:28:33 1999
@@ -0,0 +1,69 @@
+/* ld script to make i386 Linux kernel
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+  . = PAGE_OFFSET_RAW + 0x100000;
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;			/* End of text section */
+
+  .data : {			/* Data */
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  _edata = .;			/* End of data section */
+
+  . = ALIGN(8192);		/* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  . = ALIGN(4096);		/* Init code and data */
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+
+  __bss_start = .;		/* BSS */
+  .bss : {
+	*(.bss)
+	}
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/Makefile linux.pre11.3/arch/mips/Makefile
--- linux.vanilla/arch/mips/Makefile	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/Makefile	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.13 1998/08/17 10:16:23 ralf Exp $
+# $Id: Makefile,v 1.17 1999/05/02 20:56:18 harald Exp $
 #
 # 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
@@ -36,7 +36,7 @@
 CROSS_COMPILE  = $(tool-prefix)
 endif
 
-LINKFLAGS	= -static #-N
+LINKFLAGS	= -static -N
 MODFLAGS	+= -mlong-calls
 
 #
@@ -97,22 +97,37 @@
 SUBDIRS       += arch/mips/algor
 #LOADADDR      += 0x80000000
 endif
+
+#
+# DECstation family
+#
+ifdef CONFIG_DECSTATION
+CORE_FILES    += arch/mips/dec/dec.o
+SUBDIRS       += arch/mips/dec arch/mips/dec/prom
+LIBS          += arch/mips/dec/prom/rexlib.a
+LOADADDR      += 0x80040000
+endif
+
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
 ifdef CONFIG_MIPS_JAZZ
 CORE_FILES    += arch/mips/jazz/jazz.o
-SUBDIRS       += arch/mips/jazz
-LOADADDR      += 0x80000000
+SUBDIRS       += arch/mips/jazz arch/mips/arc
+LIBS          += arch/mips/arc/arclib.a
+LOADADDR      += 0x80080000
 endif
+
 ifdef CONFIG_SNI_RM200_PCI
 CORE_FILES    += arch/mips/sni/sni.o
-SUBDIRS       += arch/mips/sni
-LOADADDR      += 0x80000000
+SUBDIRS       += arch/mips/sni arch/mips/arc
+LIBS          += arch/mips/arc/arclib.a
+LOADADDR      += 0x80080000
 endif
+
 ifdef CONFIG_SGI
-LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/sgi/prom/promlib.a
-SUBDIRS       += arch/mips/sgi/kernel arch/mips/sgi/prom
+LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
+SUBDIRS       += arch/mips/sgi/kernel arch/mips/arc
 #
 # Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
 # 0x88002000 for production kernels.  Note that the value must be
@@ -123,6 +138,14 @@
 endif
 
 #
+# Baget/MIPS
+#
+ifdef CONFIG_BAGET_MIPS
+SUBDIRS       += arch/mips/baget arch/mips/baget/prom
+LIBS          += arch/mips/baget/baget.a arch/mips/baget/prom/bagetlib.a
+endif
+
+#
 # Choosing incompatible machines durings configuration will result in
 # error messages during linking.  Select a default linkscript if
 # none has been choosen above.
@@ -150,7 +173,16 @@
 
 SUBDIRS := $(SUBDIRS) $(addprefix arch/mips/, kernel mm lib tools)
 CORE_FILES := arch/mips/kernel/kernel.o arch/mips/mm/mm.o $(CORE_FILES)
-LIBS := arch/mips/lib/lib.a $(LIBS) arch/mips/lib/lib.a
+LIBS := arch/mips/lib/lib.a $(LIBS)
+
+ifdef CONFIG_BAGET_MIPS
+
+BAGETBOOT = $(MAKE) -C arch/$(ARCH)/baget
+
+balo:  vmlinux
+	$(BAGETBOOT) balo
+
+endif
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/algor/README linux.pre11.3/arch/mips/algor/README
--- linux.vanilla/arch/mips/algor/README	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/algor/README	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,5 @@
+The code for the Algorithmics P4032 evaluation board is currently under
+development.  I'll release it when it's up to the same strength as
+the other ports.
+
+  Ralf
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/Makefile linux.pre11.3/arch/mips/arc/Makefile
--- linux.vanilla/arch/mips/arc/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/Makefile	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,23 @@
+# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
+# Makefile for the SGI arcs prom monitor library routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+OBJS  = console.o init.o printf.o memory.o tree.o env.o \
+      cmdline.o misc.o time.o file.o identify.o
+
+all: arclib.a
+
+arclib.a: $(OBJS)
+	$(AR) rcs arclib.a $(OBJS)
+	sync
+
+dep:
+	$(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/cmdline.c linux.pre11.3/arch/mips/arc/cmdline.c
--- linux.vanilla/arch/mips/arc/cmdline.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/cmdline.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,64 @@
+/*
+ * cmdline.c: Kernel command line creation using ARCS argc/argv.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+/* #define DEBUG_CMDLINE */
+
+char arcs_cmdline[CL_SIZE];
+
+__initfunc(char *prom_getcmdline(void))
+{
+	return &(arcs_cmdline[0]);
+}
+
+static char *ignored[] = {
+	"ConsoleIn=",
+	"ConsoleOut=",
+	"SystemPartition=",
+	"OSLoader=",
+	"OSLoadPartition=",
+	"OSLoadFilename="
+};
+#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
+
+__initfunc(void prom_init_cmdline(void))
+{
+	char *cp;
+	int actr, i;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+		for(i = 0; i < NENTS(ignored); i++) {
+			int len = strlen(ignored[i]);
+
+			if(!strncmp(prom_argv[actr], ignored[i], len))
+				goto pic_cont;
+		}
+		/* Ok, we want it. */
+		strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+
+	pic_cont:
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+
+#ifdef DEBUG_CMDLINE
+	prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0]));
+#endif
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/console.c linux.pre11.3/arch/mips/arc/console.c
--- linux.vanilla/arch/mips/arc/console.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/console.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,50 @@
+/*
+ * console.c: SGI arcs console code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ * Compability with board caches, Ulf Carlsson
+ *
+ * $Id: console.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/sgialib.h>
+#include <asm/bcache.h>
+
+/* The romvec is not compatible with board caches.  Thus we disable it during
+ * romvec action.  Since r4xx0.c is always compiled and linked with your kernel,
+ * this shouldn't cause any harm regardless what MIPS processor you have.
+ *
+ * The romvec write and read functions seem to interfere with the serial lines
+ * in some way. You should be careful with them.
+ */
+extern struct bcache_ops *bcops;
+
+#ifdef CONFIG_SGI_PROM_CONSOLE
+void prom_putchar(char c)
+#else
+__initfunc(void prom_putchar(char c))
+#endif
+{
+	long cnt;
+	char it = c;
+
+	bcops->bc_disable();
+	romvec->write(1, &it, 1, &cnt);
+	bcops->bc_enable();
+}
+
+#ifdef CONFIG_SGI_PROM_CONSOLE
+char prom_getchar(void)
+#else
+__initfunc(char prom_getchar(void))
+#endif
+{
+	long cnt;
+	char c;
+
+	bcops->bc_disable();
+	romvec->read(0, &c, 1, &cnt);
+	bcops->bc_enable();
+	return c;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/env.c linux.pre11.3/arch/mips/arc/env.c
--- linux.vanilla/arch/mips/arc/env.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/env.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,22 @@
+/*
+ * env.c: ARCS environment variable routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: env.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/sgialib.h>
+
+__initfunc(char *prom_getenv(char *name))
+{
+	return romvec->get_evar(name);
+}
+
+__initfunc(long prom_setenv(char *name, char *value))
+{
+	return romvec->set_evar(name, value);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/file.c linux.pre11.3/arch/mips/arc/file.c
--- linux.vanilla/arch/mips/arc/file.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/file.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,59 @@
+/*
+ * file.c: ARCS firmware interface to files.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: file.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <asm/sgialib.h>
+
+__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt))
+{
+	return romvec->get_vdirent(fd, ent, num, cnt);
+}
+
+__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd))
+{
+	return romvec->open(name, md, fd);
+}
+
+__initfunc(long prom_close(unsigned long fd))
+{
+	return romvec->close(fd);
+}
+
+__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
+{
+	return romvec->read(fd, buf, num, cnt);
+}
+
+__initfunc(long prom_getrstatus(unsigned long fd))
+{
+	return romvec->get_rstatus(fd);
+}
+
+__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
+{
+	return romvec->write(fd, buf, num, cnt);
+}
+
+__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm))
+{
+	return romvec->seek(fd, off, sm);
+}
+
+__initfunc(long prom_mount(char *name, enum linux_mountops op))
+{
+	return romvec->mount(name, op);
+}
+
+__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf))
+{
+	return romvec->get_finfo(fd, buf);
+}
+
+__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk))
+{
+	return romvec->set_finfo(fd, flags, msk);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/identify.c linux.pre11.3/arch/mips/arc/identify.c
--- linux.vanilla/arch/mips/arc/identify.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/identify.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,68 @@
+/*
+ * identify.c: identify machine by looking up system identifier
+ *
+ * Copyright (C) 1998 Thomas Bogendoerfer
+ * 
+ * This code is based on arch/mips/sgi/kernel/system.c, which is
+ * 
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+
+struct smatch {
+    char *name;
+    int group;
+    int type;
+    int flags;
+};
+
+static struct smatch mach_table[] = {
+    { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS },
+    { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 },
+    { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 },
+    { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 }
+};
+
+int prom_flags;
+
+static struct smatch * __init string_to_mach(char *s)
+{
+    int i;
+    
+    for (i = 0; i < sizeof (mach_table); i++) {
+	if(!strcmp(s, mach_table[i].name))
+	    return &mach_table[i];
+    }
+    prom_printf("\nYeee, could not determine architecture type <%s>\n", s);
+    prom_printf("press a key to reboot\n");
+    prom_getchar();
+    romvec->imode();
+    return NULL;
+}
+
+void __init prom_identify_arch(void)
+{
+    pcomponent *p;
+    struct smatch *mach;
+    
+    /* The root component tells us what machine architecture we
+     * have here.
+     */
+    p = prom_getchild(PROM_NULL_COMPONENT);
+    printk("ARCH: %s\n", p->iname);
+    mach = string_to_mach(p->iname);
+
+    mips_machgroup = mach->group;
+    mips_machtype = mach->type;
+    prom_flags = mach->flags;
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/init.c linux.pre11.3/arch/mips/arc/init.c
--- linux.vanilla/arch/mips/arc/init.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/init.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,67 @@
+/*
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: init.c,v 1.2 1999/02/25 21:22:49 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+
+#include <asm/sgialib.h>
+
+/* #define DEBUG_PROM_INIT */
+
+/* Master romvec interface. */
+struct linux_romvec *romvec;
+struct linux_promblock *sgi_pblock;
+int prom_argc;
+char **prom_argv, **prom_envp;
+unsigned short prom_vers, prom_rev;
+
+extern void prom_testtree(void);
+
+__initfunc(int prom_init(int argc, char **argv, char **envp))
+{
+	struct linux_promblock *pb;
+
+	romvec = ROMVECTOR;
+	pb = sgi_pblock = PROMBLOCK;
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	if(pb->magic != 0x53435241) {
+		prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
+		while(1)
+			;
+	}
+
+	prom_init_cmdline();
+
+	prom_vers = pb->ver;
+	prom_rev = pb->rev;
+	prom_identify_arch();
+#ifdef CONFIG_SGI
+	printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n",
+		    prom_vers, prom_rev);
+#else
+	printk("PROMLIB: ARC firmware Version %d Revision %d\n",
+		    prom_vers, prom_rev);
+#endif
+	prom_meminit();
+
+#if 0
+	prom_testtree();
+#endif
+
+#ifdef DEBUG_PROM_INIT
+	{
+		prom_printf("Press a key to reboot\n");
+		(void) prom_getchar();
+		romvec->imode();
+	}
+#endif
+	return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/memory.c linux.pre11.3/arch/mips/arc/memory.c
--- linux.vanilla/arch/mips/arc/memory.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/memory.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,208 @@
+/*
+ * memory.c: PROM library functions for acquiring/using memory descriptors
+ *           given to us from the ARCS firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: memory.c,v 1.5 1999/04/14 21:25:02 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+
+#include <asm/sgialib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+
+/* #define DEBUG */
+
+__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr))
+{
+	return romvec->get_mdesc(curr);
+}
+
+#ifdef DEBUG /* convenient for debugging */
+static char *arcs_mtypes[8] = {
+	"Exception Block",
+	"ARCS Romvec Page",
+	"Free/Contig RAM",
+	"Generic Free RAM",
+	"Bad Memory",
+	"Standlong Program Pages",
+	"ARCS Temp Storage Area",
+	"ARCS Permanent Storage Area"
+};
+
+static char *arc_mtypes[8] = {
+	"Exception Block",
+	"SystemParameterBlock",
+	"FreeMemory",
+	"Bad Memory",
+	"LoadedProgram",
+	"FirmwareTemporary",
+	"FirmwarePermanent",
+	"FreeContigiuous"
+};
+#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
+#endif
+
+static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS];
+
+__initfunc(struct prom_pmemblock *prom_getpblock_array(void))
+{
+	return &prom_pblocks[0];
+}
+
+#define MEMTYPE_DONTUSE   0
+#define MEMTYPE_PROM      1
+#define MEMTYPE_FREE      2
+
+static int __init prom_memtype_classify (union linux_memtypes type)
+{
+    if (prom_flags & PROM_FLAG_ARCS) {
+	switch (type.arcs) {
+	 case arcs_free:
+	 case arcs_fcontig:
+	    return MEMTYPE_FREE;
+	 case arcs_atmp:
+	 case arcs_aperm:
+	    return MEMTYPE_PROM;
+	 default:
+	    return MEMTYPE_DONTUSE;
+	}
+    } else {
+	switch (type.arc) {
+	 case arc_free:
+	 case arc_fcontig:
+	    return MEMTYPE_FREE;
+	 case arc_rvpage:
+	 case arc_atmp:
+	 case arc_aperm:
+	    return MEMTYPE_PROM;
+	 default:
+	    return MEMTYPE_DONTUSE;
+	}
+    }
+}
+
+__initfunc(static void prom_setup_memupper(void))
+{
+	struct prom_pmemblock *p, *highest;
+
+	for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) {
+		if(p->base == 0xdeadbeef)
+			prom_printf("WHEEE, bogus pmemblock\n");
+		if(!highest || p->base > highest->base)
+			highest = p;
+	}
+	mips_memory_upper = highest->base + highest->size;
+#ifdef DEBUG
+	prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n",
+		    mips_memory_upper);
+#endif
+}
+
+__initfunc(void prom_meminit(void))
+{
+	struct linux_mdesc *p;
+	int totram;
+	int i = 0;
+
+	p = prom_getmdesc(PROM_NULL_MDESC);
+#ifdef DEBUG
+	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
+	while(p) {
+		prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
+			    i, p, p->base, p->pages, mtypes(p->type));
+		p = prom_getmdesc(p);
+		i++;
+	}
+#endif
+	p = prom_getmdesc(PROM_NULL_MDESC);
+	totram = 0;
+	i = 0;
+	while(p) {
+	    prom_pblocks[i].type = prom_memtype_classify (p->type);
+	    prom_pblocks[i].base = ((p->base<<PAGE_SHIFT) + 0x80000000);
+	    prom_pblocks[i].size = p->pages << PAGE_SHIFT;
+	    switch (prom_pblocks[i].type) {
+	     case MEMTYPE_FREE:
+		totram += prom_pblocks[i].size;
+#ifdef DEBUG
+		prom_printf("free_chunk[%d]: base=%08lx size=%d\n",
+			    i, prom_pblocks[i].base,
+			    prom_pblocks[i].size);
+#endif
+		i++;
+		break;
+	     case MEMTYPE_PROM:
+#ifdef DEBUG
+		prom_printf("prom_chunk[%d]: base=%08lx size=%d\n",
+			    i, prom_pblocks[i].base,
+			    prom_pblocks[i].size);
+#endif
+		i++;
+		break;
+	     default:
+		break;
+	    }
+	    p = prom_getmdesc(p);
+	}
+	prom_pblocks[i].base = 0xdeadbeef;
+	prom_pblocks[i].size = 0; /* indicates last elem. of array */
+	printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n",
+		    totram, (totram/1024), (totram/1024/1024));
+
+	/* Setup upper physical memory bound. */
+	prom_setup_memupper();
+}
+
+/* Called from mem_init() to fixup the mem_map page settings. */
+__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end))
+{
+	struct prom_pmemblock *p;
+	int i, nents;
+
+	/* Determine number of pblockarray entries. */
+	p = prom_getpblock_array();
+	for(i = 0; p[i].size; i++)
+		;
+	nents = i;
+restart:
+	while(start < end) {
+		for(i = 0; i < nents; i++) {
+			if((p[i].type == MEMTYPE_FREE) &&
+			   (start >= (p[i].base)) &&
+			   (start < (p[i].base + p[i].size))) {
+				start = p[i].base + p[i].size;
+				start &= PAGE_MASK;
+				goto restart;
+			}
+		}
+		set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags);
+		start += PAGE_SIZE;
+	}
+}
+
+void prom_free_prom_memory (void)
+{
+    struct prom_pmemblock *p;
+    unsigned long addr;
+    unsigned long num_pages = 0;
+
+    for(p = prom_getpblock_array(); p->size != 0; p++) {
+	if (p->type == MEMTYPE_PROM) {
+	    for (addr = p->base; addr < p->base + p->size; addr += PAGE_SIZE) {
+		mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+		free_page(addr);
+		num_pages++;
+	    }
+	}
+    }
+    printk ("Freeing prom memory: %dk freed\n",num_pages << (PAGE_SHIFT - 10));
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/misc.c linux.pre11.3/arch/mips/arc/misc.c
--- linux.vanilla/arch/mips/arc/misc.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/misc.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,84 @@
+/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
+ *
+ * misc.c: Miscellaneous ARCS PROM routines.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/bcache.h>
+#include <asm/sgialib.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+
+extern unsigned long mips_cputype;
+extern void *sgiwd93_host;
+extern void reset_wd33c93(void *instance);
+
+void prom_halt(void)
+{
+	bcops->bc_disable();
+	cli();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	romvec->halt();
+}
+
+void prom_powerdown(void)
+{
+	bcops->bc_disable();
+	cli();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	romvec->pdown();
+}
+
+/* XXX is this a soft reset basically? XXX */
+void prom_restart(void)
+{
+	bcops->bc_disable();
+	cli();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	romvec->restart();
+}
+
+void prom_reboot(void)
+{
+	bcops->bc_disable();
+	cli();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	romvec->reboot();
+}
+
+void prom_imode(void)
+{
+	bcops->bc_disable();
+	cli();
+#if CONFIG_SCSI_SGIWD93
+	reset_wd33c93(sgiwd93_host);
+#endif
+	romvec->imode();
+}
+
+long prom_cfgsave(void)
+{
+	return romvec->cfg_save();
+}
+
+struct linux_sysid *prom_getsysid(void)
+{
+	return romvec->get_sysid();
+}
+
+__initfunc(void prom_cacheflush(void))
+{
+	romvec->cache_flush();
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/printf.c linux.pre11.3/arch/mips/arc/printf.c
--- linux.vanilla/arch/mips/arc/printf.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/printf.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,40 @@
+/*
+ * printf.c: Putting things on the screen using SGI arcs
+ *           PROM facilities.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ *
+ * $Id: printf.c,v 1.2 1999/06/12 18:42:38 ulfc Exp $
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <asm/sgialib.h>
+
+static char ppbuf[1024];
+
+#ifdef CONFIG_SGI_PROM_CONSOLE
+void prom_printf(char *fmt, ...)
+#else
+__initfunc(void prom_printf(char *fmt, ...))
+#endif
+{
+	va_list args;
+	char ch, *bptr;
+	int i;
+
+	va_start(args, fmt);
+	i = vsprintf(ppbuf, fmt, args);
+
+	bptr = ppbuf;
+
+	while((ch = *(bptr++)) != 0) {
+		if(ch == '\n')
+			prom_putchar('\r');
+
+		prom_putchar(ch);
+	}
+	va_end(args);
+	return;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/salone.c linux.pre11.3/arch/mips/arc/salone.c
--- linux.vanilla/arch/mips/arc/salone.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/salone.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,25 @@
+/*
+ * salone.c: Routines to load into memory and execute stand-along
+ *           program images using ARCS PROM firmware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: salone.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <asm/sgialib.h>
+
+__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr))
+{
+	return romvec->load(name, end, pc, eaddr);
+}
+
+__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp))
+{
+	return romvec->invoke(pc, sp, argc, argv, envp);
+}
+
+__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp))
+{
+	return romvec->exec(name, argc, argv, envp);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/time.c linux.pre11.3/arch/mips/arc/time.c
--- linux.vanilla/arch/mips/arc/time.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/time.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,19 @@
+/*
+ * time.c: Extracting time information from ARCS prom.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: time.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <asm/sgialib.h>
+
+__initfunc(struct linux_tinfo *prom_gettinfo(void))
+{
+	return romvec->get_tinfo();
+}
+
+__initfunc(unsigned long prom_getrtime(void))
+{
+	return romvec->get_rtime();
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/arc/tree.c linux.pre11.3/arch/mips/arc/tree.c
--- linux.vanilla/arch/mips/arc/tree.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/arc/tree.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,109 @@
+/*
+ * tree.c: PROM component device tree code.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: tree.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $
+ */
+#include <linux/init.h>
+#include <asm/sgialib.h>
+
+#define DEBUG_PROM_TREE
+
+__initfunc(pcomponent *prom_getsibling(pcomponent *this))
+{
+	if(this == PROM_NULL_COMPONENT)
+		return PROM_NULL_COMPONENT;
+	return romvec->next_component(this);
+}
+
+__initfunc(pcomponent *prom_getchild(pcomponent *this))
+{
+	return romvec->child_component(this);
+}
+
+__initfunc(pcomponent *prom_getparent(pcomponent *child))
+{
+	if(child == PROM_NULL_COMPONENT)
+		return PROM_NULL_COMPONENT;
+	return romvec->parent_component(child);
+}
+
+__initfunc(long prom_getcdata(void *buffer, pcomponent *this))
+{
+	return romvec->component_data(buffer, this);
+}
+
+__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data))
+{
+	return romvec->child_add(this, tmp, data);
+}
+
+__initfunc(long prom_delcomponent(pcomponent *this))
+{
+	return romvec->comp_del(this);
+}
+
+__initfunc(pcomponent *prom_componentbypath(char *path))
+{
+	return romvec->component_by_path(path);
+}
+
+#ifdef DEBUG_PROM_TREE
+static char *classes[] = {
+	"system", "processor", "cache", "adapter", "controller", "peripheral",
+	"memory"
+};
+
+static char *types[] = {
+	"arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache",
+	"memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter",
+	"multi-func adapter", "disk controller", "tp controller",
+	"cdrom controller", "worm controller", "serial controller",
+	"net controller", "display controller", "parallel controller",
+	"pointer controller", "keyboard controller", "audio controller",
+	"misc controller", "disk peripheral", "floppy peripheral",
+	"tp peripheral", "modem peripheral", "monitor peripheral",
+	"printer peripheral", "pointer peripheral", "keyboard peripheral",
+	"terminal peripheral", "line peripheral", "net peripheral",
+	"misc peripheral", "anonymous"
+};
+
+static char *iflags[] = {
+	"bogus", "read only", "removable", "console in", "console out",
+	"input", "output"
+};
+
+__initfunc(static void dump_component(pcomponent *p))
+{
+	prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
+		    p, classes[p->class], types[p->type],
+		    iflags[p->iflags], p->vers, p->rev);
+	prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
+		    p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
+}
+
+__initfunc(static void traverse(pcomponent *p, int op))
+{
+	dump_component(p);
+	if(prom_getchild(p))
+		traverse(prom_getchild(p), 1);
+	if(prom_getsibling(p) && op)
+		traverse(prom_getsibling(p), 1);
+}
+
+__initfunc(void prom_testtree(void))
+{
+	pcomponent *p;
+
+	p = prom_getchild(PROM_NULL_COMPONENT);
+	dump_component(p);
+	p = prom_getchild(p);
+	while(p) {
+		dump_component(p);
+		p = prom_getsibling(p);
+	}
+	prom_printf("press a key\n");
+	prom_getchar();
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/Makefile linux.pre11.3/arch/mips/baget/Makefile
--- linux.vanilla/arch/mips/baget/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/Makefile	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,75 @@
+# $Id$
+#
+# Makefile for the Baget specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+all: baget.a 
+
+image:	../../../vmlinux
+	cp -f $< $@
+
+O_TARGET := baget.a
+O_OBJS   := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o
+
+ifeq ($(CONFIG_SERIAL),y)
+	OX_OBJS += vacserial.o
+else
+	ifeq ($(CONFIG_SERIAL),m)
+		MX_OBJS += vacserial.o
+	endif
+endif
+ifeq ($(CONFIG_VAC_RTC),y)
+	OX_OBJS += vacrtc.o
+else
+	ifeq ($(CONFIG_VAC_RTC),m)
+		MX_OBJS += vacrtc.o
+	endif
+endif
+
+bagetIRQ.o : bagetIRQ.S
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+
+##################### Baget Loader stuff ########################
+
+dummy.c:
+	touch $@
+
+image.bin: image
+	$(OBJCOPY) -O binary $< $@
+
+ramdisk.bin:
+	echo "Dummy ramdisk used. Provide your own if needed !" > $@
+
+dummy.o: dummy.c image.bin ramdisk.bin
+	$(CC) $(CFLAGS) -c -o $@ $<
+	$(OBJCOPY) --add-section=.vmlinux=image.bin \
+                   --add-section=.ramdisk=ramdisk.bin   $@ 
+
+balo.h: image
+	$(NM) $< | awk ' \
+            BEGIN               { printf "/* DO NOT EDIT THIS FILE */\n" }    \
+	    /kernel_entry/      { printf "#define START 0x%s\n", $$1 }        \
+            /balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \
+	    /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \
+                       ' > $@
+balo.o:   balo.c balo.h
+	$(CC) $(CFLAGS) -c $< 
+
+balo_supp.o: balo_supp.S
+	$(CC) $(CFLAGS) -c $<
+
+balo:   balo.o dummy.o balo_supp.o print.o
+	$(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ 
+
+clean:
+	rm -f balo.o balo.h dummy.o dummy.c hello.o image.bin image balo_supp.o
+	rm -f $(O_OBJS) $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/baget.c linux.pre11.3/arch/mips/baget/baget.c
--- linux.vanilla/arch/mips/baget/baget.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/baget.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,104 @@
+/* $Id$
+ *
+ * baget.c: Baget low level stuff
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ *
+ */
+#include <stdarg.h>
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+
+#include <asm/baget/baget.h>
+
+/* 
+ * Following values are set by BALO into RAM disk buffer parameters
+ */
+unsigned long balo_ramdisk_base = 0xBA;  /* Signature for BALO ! */
+unsigned long balo_ramdisk_size = 0;
+
+
+/*
+ *  Following code is based on routines from 'mm/vmalloc.c'
+ *  Additional parameters  ioaddr  is needed to iterate across real I/O address.
+ */
+static inline int alloc_area_pte(pte_t * pte, unsigned long address, 
+				 unsigned long size, unsigned long ioaddr)
+{
+        unsigned long end;
+
+        address &= ~PMD_MASK;
+        end = address + size;
+        if (end > PMD_SIZE)
+                end = PMD_SIZE;
+        while (address < end) {
+                unsigned long page;
+                if (!pte_none(*pte))
+                        printk("kseg2_alloc_io: page already exists\n");
+		/*
+		 *  For MIPS looks pretty to have transparent mapping
+		 *  for KSEG2 areas  -- user can't access one, and no 
+		 *  problems with  virtual <--> physical  translation.
+		 */
+                page = ioaddr & PAGE_MASK;
+
+                set_pte(pte, __pte(page | pgprot_val(PAGE_USERIO) |
+				  _PAGE_GLOBAL | __READABLE | __WRITEABLE));
+                address += PAGE_SIZE;
+		ioaddr  += PAGE_SIZE;
+                pte++;
+        }
+        return 0;
+}
+
+static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, 
+				 unsigned long size, unsigned long ioaddr)
+{
+        unsigned long end;
+
+        address &= ~PGDIR_MASK;
+        end = address + size;
+        if (end > PGDIR_SIZE)
+                end = PGDIR_SIZE;
+        while (address < end) {
+                pte_t * pte = pte_alloc_kernel(pmd, address);
+                if (!pte)
+                        return -ENOMEM;
+                if (alloc_area_pte(pte, address, end - address, ioaddr))
+                        return -ENOMEM;
+                address = (address + PMD_SIZE) & PMD_MASK;
+		ioaddr  += PMD_SIZE;
+                pmd++;
+        }
+        return 0;
+}
+
+int kseg2_alloc_io (unsigned long address, unsigned long size)
+{
+        pgd_t * dir;
+        unsigned long end = address + size;
+
+        dir = pgd_offset_k(address);
+        flush_cache_all();
+        while (address < end) {
+                pmd_t *pmd;
+                pgd_t olddir = *dir;
+
+                pmd = pmd_alloc_kernel(dir, address);
+                if (!pmd)
+                        return -ENOMEM;
+                if (alloc_area_pmd(pmd, address, end - address, address))
+                        return -ENOMEM;
+                if (pgd_val(olddir) != pgd_val(*dir))
+                        set_pgdir(address, *dir);
+                address = (address + PGDIR_SIZE) & PGDIR_MASK;
+                dir++;
+        }
+        flush_tlb_all();
+        return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/bagetIRQ.S linux.pre11.3/arch/mips/baget/bagetIRQ.S
--- linux.vanilla/arch/mips/baget/bagetIRQ.S	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/bagetIRQ.S	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,98 @@
+/* $Id$
+ * bagetIRQ.S: Interrupt exception dispatch code for Baget/MIPS
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+
+	.text
+	.set    mips1
+	.set    reorder
+	.set    macro
+	.set    noat
+	.align	5
+
+NESTED(bagetIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI				# Important: mark KERNEL mode !
+
+	la      a1, baget_interrupt
+	.set	push
+	.set    noreorder
+	jal	a1
+	.set    pop 
+	move	a0, sp                                          
+
+	la      a1, ret_from_irq
+	jr	a1
+END(bagetIRQ)
+	
+#define DBE_HANDLER       0x1C
+	
+NESTED(try_read, PT_SIZE, sp)
+	mfc0	t3, CP0_STATUS		# save flags and
+	CLI				#  disable interrupts
+
+	li	t0, KSEG2
+	sltu    t1, t0, a0              # Is it KSEG2 address ?               
+	beqz	t1, mapped              # No - already mapped !    
+					 
+	move    t0, a0		        
+	ori	t0, 0xfff
+	xori    t0, 0xfff               # round address to page
+
+	ori     t1, t0, 0xf00           # prepare EntryLo (N,V,D,G) 
+
+	mfc0    t2,   CP0_ENTRYHI       # save ASID value
+	mtc0	zero, CP0_INDEX
+	mtc0	t0,   CP0_ENTRYHI       # Load MMU values ...
+	mtc0    t1,   CP0_ENTRYLO0
+	nop                             # let it understand
+	nop
+	tlbwi				# ... and write ones
+	nop
+	nop
+	mtc0    t2,  CP0_ENTRYHI           
+	
+mapped:		
+	la	t0, exception_handlers
+	lw	t1, DBE_HANDLER(t0)	# save real handler
+	la	t2, dbe_handler			
+	sw	t2, DBE_HANDLER(t0)	# set temporary local handler
+	li	v0, -1			# default (failure) value
+	
+	li	t2, 1
+	beq	t2, a1, 1f
+	li	t2, 2
+	beq	t2, a1, 2f
+	li	t2, 4
+	beq	t2, a1, 4f
+	b	out
+
+1:	lbu	v0, (a0)		# byte
+	b	out
+
+2:	lhu	v0, (a0)		# short
+	b	out
+
+4:	lw	v0, (a0)		# word
+	
+out:		
+	sw	t1, DBE_HANDLER(t0)	# restore real handler
+	mtc0	t3, CP0_STATUS		# restore CPU flags
+	jr	ra			
+	
+dbe_handler:	
+	li	v0, -1			# mark our failure
+	.set	push
+	.set	noreorder
+	b	out			# "no problems !"
+	rfe				#   return from trap
+	.set	pop
+END(try_read)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/balo.c linux.pre11.3/arch/mips/baget/balo.c
--- linux.vanilla/arch/mips/baget/balo.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/balo.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,190 @@
+/* $Id$
+ *
+ * balo.c: BAget LOader
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ *
+ */
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/addrspace.h>
+
+#include <asm/baget/baget.h>
+
+#include "balo.h"  /* Includes some kernel symbol values */
+
+static char *banner = "\nBaget Linux Loader v0.2\n";
+
+static void mem_move (long *to, long *from, long size)
+{
+	while (size > 0) { 
+		*to++ = *from++;
+		size -= sizeof(long);
+	}
+}
+
+static volatile int *mem_limit     = (volatile int*)KSEG1;
+static volatile int *mem_limit_dbe = (volatile int*)KSEG1;
+
+static int can_write (volatile int* p) {
+        return p <  (int*)(KSEG1+BALO_OFFSET) ||
+               p >= (int*)(KSEG1+BALO_OFFSET+BALO_SIZE);
+}
+
+static volatile enum balo_state_enum {
+	BALO_INIT,
+	MEM_INIT,
+	MEM_PROBE,
+	START_KERNEL
+} balo_state = BALO_INIT;
+
+
+static __inline__ void reset_and_jump(int start, int mem_upper)
+{
+	__asm__ __volatile__(
+                ".set\tnoreorder\n\t"
+                ".set\tnoat\n\t"
+                "mfc0\t$1,$12\n\t"
+                "nop\n\t"
+                "nop\n\t"
+                "nop\n\t"
+                "ori\t$1,$1,0xff00\n\t"
+                "xori\t$1,$1,0xff00\n\t"
+                "mtc0\t$1,$12\n\t"
+                "nop\n\t"
+                "nop\n\t"
+                "nop\n\t"
+		"move\t$4,%1\n\t"
+		"jr\t%0\n\t"
+		"nop\n\t"
+                ".set\tat\n\t"
+                ".set\treorder"           
+                : /* no outputs */
+                :"Ir" (start), "Ir" (mem_upper)
+                :"$1", "$4", "memory");
+}
+
+static void start_kernel(void)
+{
+	extern char _vmlinux_start, _vmlinux_end;
+	extern char _ramdisk_start, _ramdisk_end;
+
+        outs( "Relocating Linux... " );
+	mem_move((long*)KSEG0, (long*)&_vmlinux_start, 
+                 &_vmlinux_end-&_vmlinux_start);
+	outs("done.\n");
+
+	if (&_ramdisk_start != &_ramdisk_end) {
+		outs("Setting up RAMDISK... ");
+		if (*(unsigned long*)RAMDISK_BASE != 0xBA) {
+			outs("Bad RAMDISK_BASE signature in system image.\n");
+                        balo_hungup();
+		}
+		*(unsigned long*)RAMDISK_BASE = (unsigned long)&_ramdisk_start;
+		*(unsigned long*)RAMDISK_SIZE = &_ramdisk_end -&_ramdisk_start;
+		outs("done.\n");
+	}
+
+	{ 
+		extern void flush_cache_low(int isize, int dsize);
+		flush_cache_low(256*1024,256*1024);
+	}
+
+        balo_printf( "Kernel entry: %x\n\n", START);
+	balo_state = START_KERNEL;
+	reset_and_jump(START, (int)mem_limit-KSEG1+KSEG0);
+}
+
+
+static void mem_probe(void)
+{
+	balo_state = MEM_PROBE;
+	outs("RAM: <");
+	while(mem_limit < mem_limit_dbe) {
+                if (can_write(mem_limit) && *mem_limit != 0) 
+                        break; /* cycle found */
+		outc('.');
+		if (can_write(mem_limit)) 
+                        *mem_limit = -1; /* mark */
+                mem_limit += 0x40000;
+	}
+	outs(">\n");
+	start_kernel();
+}
+
+volatile unsigned int int_cause;
+volatile unsigned int epc;
+volatile unsigned int badvaddr;
+
+static void print_regs(void)
+{
+        balo_printf("CAUSE=%x EPC=%x BADVADDR=%x\n",
+                    int_cause, epc, badvaddr);
+}
+
+void int_handler(struct pt_regs *regs)
+{ 
+        switch (balo_state) {
+	case BALO_INIT:
+                balo_printf("\nBALO: trap in balo itself.\n");
+		print_regs();
+                balo_hungup();
+		break;
+	case MEM_INIT:
+                if ((int_cause & CAUSE_MASK) != CAUSE_DBE) {
+                        balo_printf("\nBALO: unexpected trap during memory init.\n");
+			print_regs();
+                        balo_hungup();
+		} else {
+			mem_probe();
+		}
+		break;
+	case MEM_PROBE:
+                balo_printf("\nBALO: unexpected trap during memory probe.\n");
+		print_regs();
+                balo_hungup();
+		break;
+	case START_KERNEL:
+                balo_printf("\nBALO: unexpected kernel trap.\n");
+		print_regs();
+                balo_hungup();
+		break;
+	}
+        balo_printf("\nBALO: unexpected return from handler.\n");
+	print_regs();
+        balo_hungup();
+}
+
+static void mem_init(void)
+{
+	balo_state = MEM_INIT;
+
+	while(1) {
+		*mem_limit_dbe;
+		if (can_write(mem_limit_dbe)) 
+			*mem_limit_dbe = 0;
+
+		mem_limit_dbe += 0x40000; /* +1M */
+	}
+        /*  no return: must go to int_handler */
+}
+
+void balo_entry(void)
+{
+        extern void except_vec3_generic(void);
+
+	cli(); 
+	outs(banner);
+        memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
+	mem_init();
+}
+
+/* Needed for linking */
+
+int vsprintf(char *buf, const char *fmt, va_list arg)
+{
+	outs("BALO: vsprintf called.\n");
+	balo_hungup();
+	return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/balo_supp.S linux.pre11.3/arch/mips/baget/balo_supp.S
--- linux.vanilla/arch/mips/baget/balo_supp.S	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/balo_supp.S	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,143 @@
+/* $Id$
+ * balo_supp.S: BAget Loader supplement
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+	
+	.text
+	.set    mips1
+	
+	/* General exception vector. */
+NESTED(except_vec3_generic, 0, sp)
+	.set    noat
+	la	k0, except_vec3_generic_code
+	jr	k0
+END(except_vec3_generic)
+
+NESTED(except_vec3_generic_code, 0, sp)
+	SAVE_ALL 
+	mfc0	k1, CP0_CAUSE
+	la	k0, int_cause
+	sw      k1, (k0)
+
+        mfc0    k1, CP0_EPC
+        la      k0, epc
+        sw      k1, (k0)
+
+        mfc0    k1, CP0_BADVADDR
+        la      k0, badvaddr
+        sw      k1, (k0)
+
+	la	k0, int_handler 
+        .set    noreorder
+	jal	k0
+        .set    reorder
+	move	a0, sp
+
+        RESTORE_ALL_AND_RET
+END(except_vec3_generic_code)
+
+        .align  5
+NESTED(flush_cache_low, PT_SIZE, sp)
+        .set    at
+        .set    macro
+        .set    noreorder
+        
+        move    t1, a0  # ISIZE
+        move    t2, a1  # DSIZE
+
+        mfc0    t3, CP0_STATUS       # Save the status register.
+        mtc0    zero, CP0_STATUS     # Disable interrupts.
+        la      v0, 1f
+        or      v0, KSEG1            # Run uncached.
+        j       v0
+        nop
+/*
+ * Flush the instruction cache.
+ */
+1:
+        li      v0, ST0_DE | ST0_CE
+        mtc0    v0, CP0_STATUS       # Isolate and swap caches.
+        li      t0, KSEG1
+        subu    t0, t0, t1
+        li      t1, KSEG1
+        la      v0, 1f                          # Run cached
+        j       v0
+        nop
+1:
+        addu    t0, t0, 64
+        sb      zero, -64(t0)
+        sb      zero, -60(t0)
+        sb      zero, -56(t0)
+        sb      zero, -52(t0)
+        sb      zero, -48(t0)
+        sb      zero, -44(t0)
+        sb      zero, -40(t0)
+        sb      zero, -36(t0)
+        sb      zero, -32(t0)
+        sb      zero, -28(t0)
+        sb      zero, -24(t0)
+        sb      zero, -20(t0)
+        sb      zero, -16(t0)
+        sb      zero, -12(t0)
+        sb      zero, -8(t0)
+        bne     t0, t1, 1b
+        sb      zero, -4(t0)
+        
+        la      v0, 1f
+        or      v0, KSEG1
+        j       v0                              # Run uncached
+        nop
+/*
+ * Flush the data cache.
+ */
+1:
+        li      v0, ST0_DE
+        mtc0    v0, CP0_STATUS       # Isolate and swap back caches
+        li      t0, KSEG1
+        subu    t0, t0, t2
+        la      v0, 1f
+        j       v0                              # Back to cached mode
+        nop
+1:
+        addu    t0, t0, 64
+        sb      zero, -64(t0)
+        sb      zero, -60(t0)
+        sb      zero, -56(t0)
+        sb      zero, -52(t0)
+        sb      zero, -48(t0)
+        sb      zero, -44(t0)
+        sb      zero, -40(t0)
+        sb      zero, -36(t0)
+        sb      zero, -32(t0)
+        sb      zero, -28(t0)
+        sb      zero, -24(t0)
+        sb      zero, -20(t0)
+        sb      zero, -16(t0)
+        sb      zero, -12(t0)
+        sb      zero, -8(t0)
+        bne     t0, t1, 1b
+        sb      zero, -4(t0)
+
+        nop                                     # Insure isolated stores
+        nop                                     #   out of pipe.
+        nop
+        nop
+        mtc0    t3, CP0_STATUS                 # Restore status reg.
+        nop                                    # Insure cache unisolated.
+        nop
+        nop
+        nop
+        j       ra
+        nop
+END(flush_cache_low)
+
+/* To satisfy macros only */
+EXPORT(kernelsp)
+	PTR	0x80001000
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/irq.c linux.pre11.3/arch/mips/baget/irq.c
--- linux.vanilla/arch/mips/baget/irq.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/irq.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,438 @@
+/*
+ * Code to handle Baget/MIPS IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1998 Vladimir Roganov & Gleb Raiko
+ *      Code (mostly sleleton and comments) derived from DECstation IRQ
+ *      handling.
+ *
+ * $Id$
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/baget/baget.h>
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+
+atomic_t __mips_bh_counter;
+
+/*
+ * This table is a correspondence between IRQ numbers and CPU PILs
+ */
+ 
+static int irq_to_pil_map[BAGET_IRQ_NR] = { 
+	7/*fixme: dma_err -1*/,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 0x00 - 0x0f */
+	-1,-1,-1,-1, 3,-1,-1,-1, 2, 2, 2,-1, 3,-1,-1,3/*fixme: lance*/, /* 0x10 - 0x1f */
+        -1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1, 7,-1,-1,-1, /* 0x20 - 0x2f */
+	-1, 3, 2/*fixme systimer:3*/, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3  /* 0x30 - 0x3f */
+};
+
+static inline int irq_to_pil(int irq_nr) 
+{
+	int pil = -1;
+
+	if (irq_nr >= BAGET_IRQ_NR) 
+		baget_printk("irq_to_pil: too large irq_nr = 0x%x\n", irq_nr);
+	else {
+		pil = irq_to_pil_map[irq_nr];
+		if (pil == -1)
+			baget_printk("irq_to_pil: unknown irq = 0x%x\n", irq_nr);
+	}
+
+	return pil;
+}
+
+/* Function for careful CP0 interrupt mask access */
+
+static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+{
+	unsigned long status = read_32bit_cp0_register(CP0_STATUS);
+	status &= ~((clr_mask & 0xFF) << 8);
+	status |=   (set_mask & 0xFF) << 8;
+	write_32bit_cp0_register(CP0_STATUS, status);
+}
+
+/* 
+ *  These two functions may be used for unconditional IRQ
+ *  masking via their PIL protection.
+ */
+
+static inline void mask_irq(unsigned int irq_nr)
+{
+        modify_cp0_intmask(irq_to_pil(irq_nr), 0);
+}
+
+static inline void unmask_irq(unsigned int irq_nr)
+{
+	modify_cp0_intmask(0, irq_to_pil(irq_nr));
+}
+
+/*
+ * The following section is introduced for masking/unasking IRQ
+ * only while no more IRQs uses same CPU PIL.
+ *
+ * These functions are used in request_irq, free_irq, but it looks
+ * they cannot change something: CP0_STATUS is private for any
+ * process, and their action is invisible for system.
+ */
+
+static volatile unsigned int pil_in_use[BAGET_PIL_NR] = { 0, };
+
+void mask_irq_count(int irq_nr) 
+{
+	unsigned long flags;
+	int pil = irq_to_pil(irq_nr);
+	
+	save_and_cli(flags);
+	if (!--pil_in_use[pil])
+		mask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+void unmask_irq_count(int irq_nr) 
+{
+	unsigned long flags;
+	int pil = irq_to_pil(irq_nr);
+	
+	save_and_cli(flags);
+	if (!pil_in_use[pil]++)
+		unmask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+/*
+ * Two functions below are exported versions of mask/unmask IRQ
+ */
+
+void disable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	mask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	unmask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+/*
+ * Data definition for static irqaction allocation.
+ * It is used while SLAB module is not initialized.
+ */
+
+#define MAX_STATIC_ALLOC 4 
+struct irqaction static_irqaction[MAX_STATIC_ALLOC];
+int static_irq_count = 0;
+ 
+/*
+ * Pointers to the low-level handlers: first the general ones, then the
+ * fast ones, then the bad ones.
+ */
+static struct irqaction *irq_action[BAGET_IRQ_NR] = { NULL, };
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	struct irqaction * action;
+
+	for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
+		action = irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			i, kstat.irqs[0][i],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, "\n");
+	}
+	return len;
+}
+
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts enabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
+ */
+static void do_IRQ(int irq, struct pt_regs * regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+	cpu = smp_processor_id();
+	hardirq_enter(cpu);
+	kstat.irqs[cpu][irq]++;
+
+	mask_irq(irq);  
+	action = *(irq + irq_action);
+	if (action) {
+		if (!(action->flags & SA_INTERRUPT))
+			__sti();
+		action = *(irq + irq_action);
+		do_random = 0;
+        	do {
+			do_random |= action->flags;
+			action->handler(irq, action->dev_id, regs);
+			action = action->next;
+        	} while (action);
+		if (do_random & SA_SAMPLE_RANDOM)
+			add_interrupt_randomness(irq);
+		__cli();
+	} else {
+		printk("do_IRQ: Unregistered IRQ (0x%X) occured\n", irq);
+	}
+	unmask_irq(irq);
+	hardirq_exit(cpu);
+
+	/* unmasking and bottom half handling is done magically for us. */
+}
+
+/*
+ *  What to do in case of 'no VIC register available' for current interrupt
+ */
+static void vic_reg_error(unsigned long address, unsigned char active_pils) 
+{
+	printk("\nNo VIC register found: reg=%08lx active_pils=%02x\n"
+	       "Current interrupt mask from CP0_CAUSE: %02x\n", 
+	       address, 0xff & active_pils, 
+	       0xff & (read_32bit_cp0_register(CP0_CAUSE)>>8));
+	{ int i; for (i=0; i<10000; i++) udelay(1000); }
+}	
+
+static char baget_fpu_irq = BAGET_FPU_IRQ;
+#define BAGET_INT_FPU {(unsigned long)&baget_fpu_irq, 1}
+
+/*
+ *  Main interrupt handler: interrupt demultiplexer
+ */
+asmlinkage void baget_interrupt(struct pt_regs *regs)
+{
+	static struct baget_int_reg int_reg[BAGET_PIL_NR] = { 
+		BAGET_INT_NONE, BAGET_INT_NONE, BAGET_INT0_ACK, BAGET_INT1_ACK,
+		BAGET_INT_NONE, BAGET_INT_FPU,  BAGET_INT_NONE, BAGET_INT5_ACK 
+	};
+	unsigned char active_pils;
+	while ((active_pils = read_32bit_cp0_register(CP0_CAUSE)>>8)) {
+		int pil;
+		struct baget_int_reg* reg;
+
+                for (pil = 0; pil < BAGET_PIL_NR; pil++) {
+                        if (!(active_pils & (1<<pil))) continue;
+ 			
+			reg = &int_reg[pil];
+
+			if (reg->address) {
+                                extern int try_read(unsigned long,int);
+				int irq  = try_read(reg->address, reg->size);
+
+				if (irq != -1) 
+				      do_IRQ(BAGET_IRQ_MASK(irq), regs);
+				else 
+				      vic_reg_error(reg->address, active_pils);
+			} else {
+				printk("baget_interrupt: unknown interrupt "
+				       "(pil = %d)\n", pil);
+			}
+		}
+	}
+}
+
+/*
+ * Idea is to put all interrupts
+ * in a single table and differenciate them just by number.
+ */
+int setup_baget_irq(int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	p = irq_action + irq;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	save_and_cli(flags);
+	*p = new;
+	restore_flags(flags);
+
+	if (!shared) {
+		unmask_irq_count(irq);
+	}
+
+	return 0;
+}
+
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction * action = NULL;
+
+	if (irq >= BAGET_IRQ_NR)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+	if (irq_to_pil_map[irq] < 0) 
+		return -EINVAL;
+
+        if (irqflags & SA_STATIC_ALLOC) {
+		unsigned long flags;
+
+		save_and_cli(flags);
+		if (static_irq_count < MAX_STATIC_ALLOC)
+			action = &static_irqaction[static_irq_count++];
+		else 
+			printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed "
+			       "using kmalloc\n", irq, devname);
+		restore_flags(flags);
+	}
+  
+	if (action == NULL)
+		action = (struct irqaction *)
+			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+
+	if (!action) 
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_baget_irq(irq, action);
+
+	if (retval)
+		kfree(action);
+
+	return retval;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction * action, **p;
+	unsigned long flags;
+
+	if (irq >= BAGET_IRQ_NR) 
+		printk("Trying to free IRQ%d\n",irq);
+
+	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		save_and_cli(flags);
+		*p = action->next;
+		if (!irq[irq_action])
+			unmask_irq_count(irq);
+		restore_flags(flags);
+
+		if (action->flags & SA_STATIC_ALLOC)
+		{
+			/* This interrupt is marked as specially allocated
+			 * so it is a bad idea to free it.
+			 */
+			printk("Attempt to free statically allocated "
+			       "IRQ%d (%s)\n", irq, action->name);
+			return;
+		}
+ 
+		kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n",irq);
+}
+
+static int baget_irq_canonicalize(int irq) 
+{
+	return irq;
+}
+
+int (*irq_cannonicalize)(int irq) = baget_irq_canonicalize; 
+
+unsigned long probe_irq_on (void)
+{
+	/* TODO */
+	return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+	/* TODO */
+	return 0;
+}
+
+
+static void write_err_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	*(volatile char*) BAGET_WRERR_ACK = 0;
+}
+
+__initfunc(void init_IRQ(void))
+{
+	irq_setup();
+
+	/* Enable access to VIC interrupt registers */
+	vac_outw(0xacef | 0x8200, VAC_PIO_FUNC);
+
+	/* Enable interrupts for pils 2 and 3 (lines 0 and 1) */
+	modify_cp0_intmask(0, (1<<2)|(1<<3));
+
+	if (request_irq(0/*fixme*/, write_err_interrupt, 
+			SA_INTERRUPT|SA_STATIC_ALLOC, "write_err", NULL) < 0) 
+		printk("init_IRQ: unable to register write_err irq\n");
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/ld.script.balo linux.pre11.3/arch/mips/baget/ld.script.balo
--- linux.vanilla/arch/mips/baget/ld.script.balo	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/ld.script.balo	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,124 @@
+OUTPUT_FORMAT("elf32-bigmips")
+OUTPUT_ARCH(mips)
+ENTRY(balo_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = 0x80400000;
+  .rel.text      : { *(.rel.text)	}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)	}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)	}
+  .rela.got      : { *(.rela.got)	}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.init      : { *(.rel.init)	}
+  .rela.init     : { *(.rela.init)	}
+  .rel.fini      : { *(.rel.fini)	}
+  .rela.fini     : { *(.rela.fini)	}
+  .rel.bss       : { *(.rel.bss)	}
+  .rela.bss      : { *(.rela.bss)	}
+  .rel.plt       : { *(.rel.plt)	}
+  .rela.plt      : { *(.rela.plt)	}
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+
+  _etext = .;
+  PROVIDE (etext = .);
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  *(.text.init) 
+  *(.data.init) 
+  . = ALIGN(4096);	/* Align double page for init_task_union */
+  __init_end = .;
+
+   *(.fini)    
+  *(.reginfo) 
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+    _fdata = . ;
+    *(.data)
+    CONSTRUCTORS
+
+  *(.data1) 
+  _gp = . + 0x8000;
+  *(.lit8) 
+  *(.lit4) 
+  *(.ctors)   
+  *(.dtors)   
+  *(.got.plt) *(.got) 
+  *(.dynamic) 
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  *(.sdata) 
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __bss_start = .;
+  _fbss = .;
+
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  _end = . ;
+  PROVIDE (end = .);
+   *(.sbss)
+   *(.scommon)
+
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  *(.stab) 
+  *(.stabstr) 
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  *(.debug) 
+  *(.debug_srcinfo) 
+  *(.debug_aranges) 
+  *(.debug_pubnames) 
+  *(.debug_sfnames) 
+  *(.line) 
+  /* These must appear regardless of  .  */
+  *(.gptab.data) *(.gptab.sdata) 
+  *(.gptab.bss) *(.gptab.sbss) 
+
+  _vmlinux_start = .;
+  *(.vmlinux)
+  _vmlinux_end = .;
+
+  _ramdisk_start = .;
+  *(.ramdisk)
+  _ramdisk_end = .;
+
+} =0
+
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/print.c linux.pre11.3/arch/mips/baget/print.c
--- linux.vanilla/arch/mips/baget/print.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/print.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,118 @@
+/* $Id$
+ *
+ * print.c: Simple print fascility
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ *
+ */
+#include <stdarg.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/baget/baget.h>
+
+/*
+ *  Define this to see 'baget_printk' (debug) messages
+ */
+// #define BAGET_PRINTK
+
+/* 
+ *  This function is same for BALO and Linux baget_printk,
+ *  and normally prints characted to second (UART A) console.
+ */
+
+static void delay(void) {}
+
+static void outc_low(char c)
+{
+        int i;
+        vac_outb(c, VAC_UART_B_TX);
+        for (i=0; i<10000; i++) 
+                delay();
+}
+
+void outc(char c)
+{
+        if (c == '\n')
+                outc_low('\r');
+        outc_low(c);
+}
+
+void outs(char *s) 
+{
+        while(*s) outc(*s++);
+}
+
+void baget_write(char *s, int l)
+{
+        while(l--)
+                outc(*s++);
+}
+
+int baget_printk(const char *fmt, ...)
+{
+#ifdef BAGET_PRINTK
+        va_list args;
+        int i;
+        static char buf[1024];
+
+        va_start(args, fmt);
+        i = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf)-4 */
+        va_end(args);
+        baget_write(buf, i);
+        return i;
+#else
+	return 0;
+#endif
+}
+
+static __inline__ void puthex( int a )
+{
+        static char s[9];
+        static char e[] = "0123456789ABCDEF";
+        int i;
+        for( i = 7; i >= 0; i--, a >>= 4 ) s[i] = e[a & 0x0F];
+        s[8] = '\0';
+        outs( s );
+}
+
+__initfunc(void balo_printf( char *f, ... )) 
+{
+        int *arg = (int*)&f + 1;
+        char c; 
+        int format = 0;
+
+        while((c = *f++) != 0) {
+                switch(c) {
+                default:
+                        if(format) {
+                                outc('%');
+                                format = 0;
+                        }
+                        outc( c );
+                        break;
+                case '%':
+                        if( format ){
+                                format = 0;
+                                outc(c);
+                        } else format = 1;
+                        break;
+                case 'x':
+                        if(format) puthex( *arg++ );
+                        else outc(c);
+                        format = 0;
+                        break;
+                case 's':
+                        if( format ) outs((char *)*arg++);
+                        else outc(c);
+                        format = 0;
+                        break;
+                }
+        }
+}
+
+__initfunc(void balo_hungup(void))
+{ 
+        outs("Hunging up.\n");
+        while(1); 
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/prom/Makefile linux.pre11.3/arch/mips/baget/prom/Makefile
--- linux.vanilla/arch/mips/baget/prom/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/prom/Makefile	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,15 @@
+# $Id$
+# Makefile for the Baget/MIPS prom emulator library routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := bagetlib.a
+O_OBJS   := init.o
+
+all: 	$(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/prom/init.c linux.pre11.3/arch/mips/baget/prom/init.c
--- linux.vanilla/arch/mips/baget/prom/init.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/prom/init.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,20 @@
+/*
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov 
+ *
+ * $Id$
+ */
+#include <linux/init.h>
+#include <asm/bootinfo.h>
+
+char arcs_cmdline[CL_SIZE];
+
+__initfunc(int prom_init(unsigned int mem_upper))
+{
+	mips_memory_upper = mem_upper;
+	mips_machgroup  = MACH_GROUP_UNKNOWN;
+	mips_machtype   = MACH_UNKNOWN;
+	arcs_cmdline[0] = 0;
+	return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/reset.c linux.pre11.3/arch/mips/baget/reset.c
--- linux.vanilla/arch/mips/baget/reset.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/reset.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <asm/baget/baget.h>
+
+
+#define R3000_RESET_VEC  0xbfc00000
+typedef void vector(void);
+
+
+static void baget_reboot(char *from_fun)
+{
+	cli();
+	baget_printk("\n%s: jumping to RESET code...\n", from_fun);
+	(*(vector*)R3000_RESET_VEC)();
+}
+
+/* fixme: proper functionality */
+
+void baget_machine_restart(char *command)
+{
+	baget_reboot("restart");
+}
+
+void baget_machine_halt(void)
+{
+	baget_reboot("halt");
+}
+
+void baget_machine_power_off(void)
+{
+	baget_reboot("power off");
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/setup.c linux.pre11.3/arch/mips/baget/setup.c
--- linux.vanilla/arch/mips/baget/setup.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/setup.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,494 @@
+/* $Id$
+ *
+ * setup.c: Baget/MIPS specific setup, including init of the feature struct.
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ *
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/irq.h>
+#include <asm/addrspace.h>
+#include <asm/reboot.h>
+
+#include <asm/baget/baget.h>
+
+extern long mips_memory_upper;
+
+extern void wbflush_setup(void);
+
+#define CACHEABLE_STR(val) ((val) ? "not cached" : "cached")
+#define MIN(a,b)           (((a)<(b)) ? (a):(b)) 
+		
+__initfunc(static void vac_show(void))
+{ 
+	int i;
+	unsigned short val, decode = vac_inw(VAC_DECODE_CTRL);
+	unsigned short a24_base = vac_inw(VAC_A24_BASE);
+	unsigned long  a24_addr = ((unsigned long)
+					   (a24_base & VAC_A24_MASK)) << 16;
+	char *decode_mode[]  = { "eprom", "vsb", "shared", "dram" };
+	char *address_mode[] = { "", ", A16", ", A32/A24", ", A32/A24/A16" };
+	char *state[] = { "", " on write", " on read", " on read/write", };
+	char *region_mode[] = { "inactive", "shared", "vsb", "vme" };
+	char *asiz[]        = { "user", "A32", "A16", "A24" };
+	unsigned short regs[] = { VAC_REG1,     VAC_REG2, VAC_REG3  };
+	unsigned short bndr[] = { VAC_DRAM_MASK,VAC_BNDR2,VAC_BNDR3 };
+	unsigned short io_sels[] = { VAC_IOSEL0_CTRL,
+				     VAC_IOSEL1_CTRL,
+				     VAC_IOSEL2_CTRL,
+				     VAC_IOSEL3_CTRL,
+				     VAC_IOSEL4_CTRL,
+				     VAC_IOSEL5_CTRL };
+	
+	printk("[DSACKi %s, DRAMCS%s qualified, boundary%s qualified%s]\n",
+	       (decode & VAC_DECODE_DSACKI)     ? "on" : "off",
+	       (decode & VAC_DECODE_QFY_DRAMCS) ? ""   : " not",
+	       (decode & VAC_DECODE_QFY_BNDR)   ? ""   : " not",
+	       (decode & VAC_DECODE_FPUCS)      ? ", fpu" : "");
+
+	printk("slave0 ");
+	if (decode & VAC_DECODE_RDR_SLSEL0)
+		printk("at %08lx (%d MB)\t[dram %s]\n",
+		       ((unsigned long)vac_inw(VAC_SLSEL0_BASE))<<16,
+		       ((0xffff ^ vac_inw(VAC_SLSEL0_MASK)) + 1) >> 4,
+		       (decode & VAC_DECODE_QFY_SLSEL0) ? "qualified" : "");
+	else
+		printk("off\n");
+
+	printk("slave1 ");
+	if (decode & VAC_DECODE_RDR_SLSEL1)
+		printk("at %08lx (%d MB)\t[%s%s, %s]\n",
+		       ((unsigned long)vac_inw(VAC_SLSEL1_BASE))<<16,
+		       ((0xffff ^ vac_inw(VAC_SLSEL1_MASK)) + 1) >> 4,
+		       decode_mode[VAC_DECODE_MODE_VAL(decode)],
+		       address_mode[VAC_DECODE_CMP_SLSEL1_VAL(decode)],
+		       (decode & VAC_DECODE_QFY_SLSEL1) ? "qualified" : "");
+	else
+		printk("off\n");
+
+	printk("icf global at %04x, module at %04x [%s]\n",
+		       ((unsigned int)
+			VAC_ICFSEL_GLOBAL_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4,
+		       ((unsigned int)
+			VAC_ICFSEL_MODULE_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4,
+		       (decode & VAC_DECODE_QFY_ICFSEL) ? "qualified" : "");
+
+	
+	printk("region0 at 00000000 (%dMB)\t[dram, %s, delay %d cpuclk"
+	       ", cached]\n",
+	       (vac_inw(VAC_DRAM_MASK)+1)>>4,
+	       (decode & VAC_DECODE_DSACK) ? "D32" : "3state",
+	       VAC_DECODE_CPUCLK_VAL(decode));
+	
+	for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) {
+		unsigned long from = 
+			((unsigned long)vac_inw(bndr[i]))<<16;
+		unsigned long to   = 
+			((unsigned long)
+			 ((i+1 == sizeof(bndr)/sizeof(bndr[0])) ? 
+			  0xff00 : vac_inw(bndr[i+1])))<<16;
+		
+		
+		val = vac_inw(regs[i]);
+		printk("region%d at %08lx (%dMB)\t[%s %s/%s, %s]\n", 
+		       i+1,
+		       from,
+		       (unsigned int)((to - from) >> 20),
+		       region_mode[VAC_REG_MODE(val)],
+		       asiz[VAC_REG_ASIZ_VAL(val)],
+		       ((val & VAC_REG_WORD) ?  "D16" : "D32"),
+		       CACHEABLE_STR(val&VAC_A24_A24_CACHINH));
+		
+		if (a24_addr >= from && a24_addr < to)
+			printk("\ta24 at %08lx (%dMB)\t[vme, A24/%s, %s]\n",
+			       a24_addr,
+			       MIN((unsigned int)(a24_addr - from)>>20, 32),
+			       (a24_base & VAC_A24_DATAPATH) ?  "user" :
+			       ((a24_base & VAC_A24_D32_ENABLE)  ?  
+				"D32" : "D16"),
+			       CACHEABLE_STR(a24_base & VAC_A24_A24_CACHINH));
+	}
+
+	printk("region4 at ff000000 (15MB)\t[eprom]\n");
+	val = vac_inw(VAC_EPROMCS_CTRL);
+	printk("\t[ack %d cpuclk%s, %s%srecovery %d cpuclk, "
+	       "read %d%s, write %d%s, assert %d%s]\n",
+	       VAC_CTRL_DELAY_DSACKI_VAL(val),
+	       state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)],
+	       (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "",
+	       (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "",
+	       VAC_CTRL_RECOVERY_IOSELI_VAL(val),
+	       VAC_CTRL_DELAY_IORD_VAL(val)/2,
+	       (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "",
+	       VAC_CTRL_DELAY_IOWR_VAL(val)/2,
+	       (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "",
+	       VAC_CTRL_DELAY_IOSELI_VAL(val)/2,
+	       (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "");
+	
+	printk("region5 at fff00000 (896KB)\t[local io, %s]\n",
+	       CACHEABLE_STR(vac_inw(VAC_A24_BASE) & VAC_A24_IO_CACHINH));
+
+	for (i = 0; i < sizeof(io_sels)/sizeof(io_sels[0]); i++) {
+		val = vac_inw(io_sels[i]);
+		printk("\tio%d[ack %d cpuclk%s, %s%srecovery %d cpuclk, "
+		       "\n\t read %d%s cpuclk, write %d%s cpuclk, "
+		       "assert %d%s%s cpuclk]\n",
+		       i, 
+		       VAC_CTRL_DELAY_DSACKI_VAL(val),
+		       state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)],
+		       (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "",
+		       (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "",
+		       VAC_CTRL_RECOVERY_IOSELI_VAL(val),
+		       VAC_CTRL_DELAY_IORD_VAL(val)/2,
+		       (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "",
+		       VAC_CTRL_DELAY_IOWR_VAL(val)/2,
+		       (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "",
+		       VAC_CTRL_DELAY_IOSELI_VAL(val)/2,
+		       (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "",
+		       (vac_inw(VAC_DEV_LOC) & VAC_DEV_LOC_IOSEL(i)) ? 
+		          ", id" : "");
+	}
+		
+	printk("region6 at fffe0000 (128KB)\t[vme, A16/%s, "
+	       "not cached]\n",
+	       (a24_base & VAC_A24_A16D32_ENABLE) ? 
+	       ((a24_base & VAC_A24_A16D32) ? "D32" : "D16") : "user");
+		       
+	val = vac_inw(VAC_SHRCS_CTRL);
+	printk("shared[ack %d cpuclk%s, %s%srecovery %d cpuclk, "
+	       "read %d%s, write %d%s, assert %d%s]\n",
+	       VAC_CTRL_DELAY_DSACKI_VAL(val),
+	       state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)],
+	       (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "",
+	       (val & VAC_CTRL_DSACK1) ? "dsack1*, " : "",
+	       VAC_CTRL_RECOVERY_IOSELI_VAL(val),
+	       VAC_CTRL_DELAY_IORD_VAL(val)/2,
+	       (VAC_CTRL_DELAY_IORD_VAL(val)&1) ? ".5" : "",
+	       VAC_CTRL_DELAY_IOWR_VAL(val)/2,
+	       (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "",
+	       VAC_CTRL_DELAY_IOSELI_VAL(val)/2,
+	       (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "");
+}
+
+__initfunc(static void vac_init(void))
+{
+	unsigned short mem_limit = ((mips_memory_upper-KSEG0) >> 16);
+
+	switch(vac_inw(VAC_ID)) {
+	case 0x1AC0:
+		printk("VAC068-F5: ");
+		break;
+	case 0x1AC1:
+		printk("VAC068A: ");
+		break;
+	default:
+		panic("Unknown VAC revision number");
+	}
+	
+	vac_outw(mem_limit-1, VAC_DRAM_MASK); 
+	vac_outw(mem_limit, VAC_BNDR2);
+	vac_outw(mem_limit, VAC_BNDR3);
+	vac_outw(((BAGET_A24M_BASE>>16)&~VAC_A24_D32_ENABLE)|VAC_A24_DATAPATH,
+		 VAC_A24_BASE);
+	vac_outw(VAC_REG_INACTIVE|VAC_REG_ASIZ0,VAC_REG1);
+	vac_outw(VAC_REG_INACTIVE|VAC_REG_ASIZ0,VAC_REG2);
+	vac_outw(VAC_REG_MWB|VAC_REG_ASIZ1,VAC_REG3);
+	vac_outw(BAGET_A24S_BASE>>16,VAC_SLSEL0_BASE);
+	vac_outw(BAGET_A24S_MASK>>16,VAC_SLSEL0_MASK);
+	vac_outw(BAGET_A24S_BASE>>16,VAC_SLSEL1_BASE);
+	vac_outw(BAGET_A24S_MASK>>16,VAC_SLSEL1_MASK);
+	vac_outw(BAGET_GSW_BASE|BAGET_MSW_BASE(0),VAC_ICFSEL_BASE);
+	vac_outw(VAC_DECODE_FPUCS|
+		 VAC_DECODE_CPUCLK(3)|
+		 VAC_DECODE_RDR_SLSEL0|VAC_DECODE_RDR_SLSEL1|
+		 VAC_DECODE_DSACK|
+		 VAC_DECODE_QFY_BNDR|
+		 VAC_DECODE_QFY_ICFSEL|
+		 VAC_DECODE_QFY_SLSEL1|VAC_DECODE_QFY_SLSEL0|
+		 VAC_DECODE_CMP_SLSEL1_HI|
+		 VAC_DECODE_DRAMCS|
+		 VAC_DECODE_QFY_DRAMCS|
+		 VAC_DECODE_DSACKI,VAC_DECODE_CTRL);
+	vac_outw(VAC_PIO_FUNC_UART_A_TX|VAC_PIO_FUNC_UART_A_RX|
+		 VAC_PIO_FUNC_UART_B_TX|VAC_PIO_FUNC_UART_B_RX|
+		 VAC_PIO_FUNC_IOWR|
+		 VAC_PIO_FUNC_IOSEL3|
+		 VAC_PIO_FUNC_IRQ7|VAC_PIO_FUNC_IRQ10|VAC_PIO_FUNC_IRQ11|
+		 VAC_PIO_FUNC_IOSEL2|
+		 VAC_PIO_FUNC_FCIACK,VAC_PIO_FUNC);
+	vac_outw(VAC_PIO_DIR_FCIACK |
+		 VAC_PIO_DIR_OUT(0) |
+		 VAC_PIO_DIR_OUT(1) |
+		 VAC_PIO_DIR_OUT(2) |
+		 VAC_PIO_DIR_OUT(3) |
+		 VAC_PIO_DIR_IN(4)  |
+		 VAC_PIO_DIR_OUT(5) |
+		 VAC_PIO_DIR_OUT(6) |
+		 VAC_PIO_DIR_OUT(7) |
+		 VAC_PIO_DIR_OUT(8) |
+		 VAC_PIO_DIR_IN(9)  |
+		 VAC_PIO_DIR_OUT(10)|
+		 VAC_PIO_DIR_OUT(11)|
+		 VAC_PIO_DIR_OUT(12)|
+		 VAC_PIO_DIR_OUT(13),VAC_PIO_DIRECTION);
+	vac_outw(VAC_DEV_LOC_IOSEL(2),VAC_DEV_LOC);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(1)|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_SHRCS_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(1)|
+		 VAC_CTRL_DSACK0|VAC_CTRL_DSACK1|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_EPROMCS_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(2)|
+		 VAC_CTRL_DSACK0|VAC_CTRL_DSACK1|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL0_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(2)|
+		 VAC_CTRL_DSACK0|VAC_CTRL_DSACK1|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL1_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(2)|
+		 VAC_CTRL_DSACK0|VAC_CTRL_DSACK1|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL2_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(2)|
+		 VAC_CTRL_DSACK0|VAC_CTRL_DSACK1|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL3_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(2)|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL4_CTRL);
+	vac_outw(VAC_CTRL_IOWR|
+		 VAC_CTRL_DELAY_IOWR(3)|
+		 VAC_CTRL_DELAY_IORD(3)|
+		 VAC_CTRL_RECOVERY_IOSELI(2)|
+		 VAC_CTRL_DELAY_DSACKI(8),VAC_IOSEL5_CTRL);
+
+        vac_show();
+}
+
+__initfunc(static void vac_start(void))
+{
+	vac_outw(0, VAC_ID);
+	vac_outw(VAC_INT_CTRL_TIMER_DISABLE|
+		 VAC_INT_CTRL_UART_B_DISABLE|
+		 VAC_INT_CTRL_UART_A_DISABLE|
+		 VAC_INT_CTRL_MBOX_DISABLE|
+		 VAC_INT_CTRL_PIO4_DISABLE|
+		 VAC_INT_CTRL_PIO7_DISABLE|
+		 VAC_INT_CTRL_PIO8_DISABLE|
+		 VAC_INT_CTRL_PIO9_DISABLE,VAC_INT_CTRL);
+	vac_outw(VAC_INT_CTRL_TIMER_PIO10|
+		 VAC_INT_CTRL_UART_B_PIO7|
+		 VAC_INT_CTRL_UART_A_PIO7,VAC_INT_CTRL);
+	/* 
+	 *  Set quadro speed for both UARTs.
+	 *  To do it we need use formulae from VIC/VAC manual,
+	 *  keeping in mind Baget's 50MHz frequency...
+	 */
+	vac_outw((500000/(384*16))<<8,VAC_CPU_CLK_DIV); 
+}
+
+__initfunc(static void vic_show(void))
+{
+	unsigned char val;
+	char *timeout[]  = { "4", "16", "32", "64", "128", "256", "disabled" };
+	char *deadlock[] = { "[dedlk only]", "[dedlk only]", 
+			     "[dedlk], [halt w/ rmc], [lberr]",
+			     "[dedlk], [halt w/o rmc], [lberr]" };
+
+	val = vic_inb(VIC_IFACE_CFG);
+	if (val & VIC_IFACE_CFG_VME)
+		printk("VMEbus controller ");
+	if (val & VIC_IFACE_CFG_TURBO)
+		printk("turbo ");
+	if (val & VIC_IFACE_CFG_MSTAB)
+		printk("metastability delay ");
+	printk("%s ",
+	       deadlock[VIC_IFACE_CFG_DEADLOCK_VAL(val)]);
+	
+
+	printk("interrupts: ");
+	val = vic_inb(VIC_ERR_INT);
+	if (!(val & VIC_ERR_INT_SYSFAIL))
+		printk("[sysfail]");
+	if (!(val & VIC_ERR_INT_TIMO))
+		printk("[timeout]");
+	if (!(val & VIC_ERR_INT_WRPOST))
+		printk("[write post]");
+	if (!(val & VIC_ERR_INT_ACFAIL))
+		printk("[acfail] ");
+	printk("\n");
+	
+	printk("timeouts: ");
+	val = vic_inb(VIC_XFER_TIMO);
+	printk("local %s, vme %s ",
+	       timeout[VIC_XFER_TIMO_LOCAL_PERIOD_VAL(val)],
+	       timeout[VIC_XFER_TIMO_VME_PERIOD_VAL(val)]);
+	if (val & VIC_XFER_TIMO_VME)
+		printk("acquisition ");
+	if (val & VIC_XFER_TIMO_ARB)
+		printk("arbitration ");
+	printk("\n");
+
+	val = vic_inb(VIC_LOCAL_TIM);
+	printk("pas time: (%d,%d), ds time: %d\n",
+	       VIC_LOCAL_TIM_PAS_ASSERT_VAL(val),
+	       VIC_LOCAL_TIM_PAS_DEASSERT_VAL(val),
+	       VIC_LOCAT_TIM_DS_DEASSERT_VAL(val));
+
+	val = vic_inb(VIC_BXFER_DEF);
+	printk("dma: ");
+	if (val & VIC_BXFER_DEF_DUAL)
+		printk("[dual path]");
+	if (val & VIC_BXFER_DEF_LOCAL_CROSS)
+		printk("[local boundary cross]");
+	if (val & VIC_BXFER_DEF_VME_CROSS)
+		printk("[vme boundary cross]");
+	
+}
+
+__initfunc(static void vic_init(void))
+{
+	 unsigned char id = vic_inb(VIC_ID);
+	 if ((id & 0xf0) != 0xf0)
+		 panic("VIC not found");
+	 printk(" VIC068A Rev. %X: ", id & 0x0f);
+
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_II);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT1);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT2);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT3);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT4);
+/*	 
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT5);
+*/
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT6);
+
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT7);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_DMA_INT);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		  VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT1);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		  VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT2);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		  VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT3);
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		  VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT4);
+/*	 
+	 vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_LEVEL|
+		  VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT5);
+*/
+	 vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		  VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT6);
+	 vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		  VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT7);
+
+	 vic_outb(VIC_INT_IPL(3)|
+		  VIC_INT_SWITCH(0)|
+		  VIC_INT_SWITCH(1)|
+		  VIC_INT_SWITCH(2)|
+		  VIC_INT_SWITCH(3), VIC_ICGS_INT);
+	 vic_outb(VIC_INT_IPL(3)|
+		  VIC_INT_SWITCH(0)|
+		  VIC_INT_SWITCH(1)|
+		  VIC_INT_SWITCH(2)|
+		  VIC_INT_SWITCH(3), VIC_ICMS_INT);
+	 vic_outb(VIC_INT_IPL(6)|
+		  VIC_ERR_INT_SYSFAIL|
+		  VIC_ERR_INT_TIMO|
+		  VIC_ERR_INT_WRPOST|
+		  VIC_ERR_INT_ACFAIL, VIC_ERR_INT);
+	 vic_outb(VIC_ICxS_BASE_ID(0xf), VIC_ICGS_BASE);
+	 vic_outb(VIC_ICxS_BASE_ID(0xe), VIC_ICMS_BASE);
+	 vic_outb(VIC_LOCAL_BASE_ID(0x6), VIC_LOCAL_BASE);
+	 vic_outb(VIC_ERR_BASE_ID(0x3), VIC_ERR_BASE);
+	 vic_outb(VIC_XFER_TIMO_VME_PERIOD_32|
+		  VIC_XFER_TIMO_LOCAL_PERIOD_32, VIC_XFER_TIMO);
+	 vic_outb(VIC_LOCAL_TIM_PAS_ASSERT(2)|
+		  VIC_LOCAT_TIM_DS_DEASSERT(1)|
+		  VIC_LOCAL_TIM_PAS_DEASSERT(1), VIC_LOCAL_TIM);
+	 vic_outb(VIC_BXFER_DEF_VME_CROSS|
+		  VIC_BXFER_DEF_LOCAL_CROSS|
+		  VIC_BXFER_DEF_AMSR|
+		  VIC_BXFER_DEF_DUAL, VIC_BXFER_DEF);
+	 vic_outb(VIC_SSxCR0_LOCAL_XFER_SINGLE|
+		  VIC_SSxCR0_A32|VIC_SSxCR0_D32|
+		  VIC_SS0CR0_TIMER_FREQ_NONE, VIC_SS0CR0);
+	 vic_outb(VIC_SSxCR1_TF1(0xf)|
+		  VIC_SSxCR1_TF2(0xf), VIC_SS0CR1);
+	 vic_outb(VIC_SSxCR0_LOCAL_XFER_SINGLE|
+		  VIC_SSxCR0_A24|VIC_SSxCR0_D32, VIC_SS1CR0);
+	 vic_outb(VIC_SSxCR1_TF1(0xf)|
+		  VIC_SSxCR1_TF2(0xf), VIC_SS1CR1);
+         vic_outb(VIC_IFACE_CFG_NOHALT|
+		  VIC_IFACE_CFG_NOTURBO, VIC_IFACE_CFG);
+	 vic_outb(VIC_AMS_CODE(0), VIC_AMS);
+	 vic_outb(VIC_BXFER_CTRL_INTERLEAVE(0), VIC_BXFER_CTRL);
+	 vic_outb(0, VIC_BXFER_LEN_LO);
+	 vic_outb(0, VIC_BXFER_LEN_HI);
+	 vic_outb(VIC_REQ_CFG_FAIRNESS_DISABLED|
+		  VIC_REQ_CFG_LEVEL(3)|
+		  VIC_REQ_CFG_RR_ARBITRATION, VIC_REQ_CFG);
+	 vic_outb(VIC_RELEASE_BLKXFER_BLEN(0)|
+		  VIC_RELEASE_RWD, VIC_RELEASE);
+	 vic_outb(VIC_IC6_RUN, VIC_IC6);
+	 vic_outb(0, VIC_IC7);
+	 
+	 vic_show();
+}
+
+static void vic_start(void)
+{
+	vic_outb(VIC_INT_IPL(3)|
+		 VIC_INT_NOAUTO|
+		 VIC_INT_EDGE|
+		 VIC_INT_HIGH|
+		 VIC_INT_ENABLE, VIC_LINT7);
+}
+
+__initfunc(void baget_irq_setup(void))
+{
+	extern void bagetIRQ(void);
+
+        /* Now, it's safe to set the exception vector. */
+	set_except_vector(0, bagetIRQ);
+}
+
+extern void baget_machine_restart(char *command);
+extern void baget_machine_halt(void);
+extern void baget_machine_power_off(void);
+ 
+__initfunc(void baget_setup(void))
+{
+	printk("BT23/63-201n found.\n");
+	*BAGET_WRERR_ACK = 0;
+	irq_setup = baget_irq_setup;
+
+	wbflush_setup();
+
+        _machine_restart   = baget_machine_restart;
+        _machine_halt      = baget_machine_halt;
+        _machine_power_off = baget_machine_power_off;
+
+	vac_init();
+	vic_init();
+	vac_start();
+	vic_start();
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/time.c linux.pre11.3/arch/mips/baget/time.c
--- linux.vanilla/arch/mips/baget/time.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/time.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,96 @@
+/* $Id$
+ * time.c: Baget/MIPS specific time handling details
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>  
+
+#include <asm/baget/baget.h>
+
+/* 
+ *  To have precision clock, we need to fix available clock frequency
+ */
+#define FREQ_NOM  79125  /* Baget frequency ratio */
+#define FREQ_DEN  10000
+static inline int timer_intr_valid(void) 
+{
+	static unsigned long long ticks, valid_ticks;
+
+	if (ticks++ * FREQ_DEN >= valid_ticks * FREQ_NOM) {
+		/* 
+		 *  We need no overflow checks, 
+		 *  due baget unable to work 3000 years...
+		 *  At least without reboot...
+		 */
+		valid_ticks++;
+		return 1;
+	}
+	return 0;
+}
+
+void static timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	if (timer_intr_valid()) {
+	sti();
+	do_timer(regs);
+	}
+}
+
+__initfunc(static void timer_enable(void))
+{
+	unsigned char ss0cr0 = vic_inb(VIC_SS0CR0);
+	ss0cr0 &= ~VIC_SS0CR0_TIMER_FREQ_MASK;
+	ss0cr0 |= VIC_SS0CR0_TIMER_FREQ_1000HZ;
+	vic_outb(ss0cr0, VIC_SS0CR0);
+
+	vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE|
+		 VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); 
+}
+
+__initfunc(void time_init(void))
+{
+	if (request_irq(BAGET_VIC_TIMER_IRQ, timer_interrupt, 
+			SA_INTERRUPT|SA_STATIC_ALLOC, "timer", NULL) < 0) 
+		printk("time_init: unable request irq for system timer\n");
+
+	timer_enable();
+
+	/* We don't call sti() here, because it is too early for baget */
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        *tv = xtime;
+        restore_flags(flags);
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+        unsigned long flags;
+  
+        save_and_cli(flags);
+        xtime = *tv;
+        time_state = TIME_BAD;
+        time_maxerror = MAXPHASE;
+        time_esterror = MAXPHASE;
+        restore_flags(flags);
+} 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/vacserial.c linux.pre11.3/arch/mips/baget/vacserial.c
--- linux.vanilla/arch/mips/baget/vacserial.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/vacserial.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,2943 @@
+/* $Id$
+ * vacserial.c: VAC UART serial driver
+ *              This code stealed and adopted from linux/drivers/char/serial.c
+ *              See that for author info
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+
+#undef  SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO
+#define SERIAL_DO_RESTART
+
+#define CONFIG_SERIAL_SHARE_IRQ
+
+/* Set of debugging defines */
+
+#undef  SERIAL_DEBUG_INTR
+#undef  SERIAL_DEBUG_OPEN
+#undef  SERIAL_DEBUG_FLOW
+#undef  SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+
+#define RS_STROBE_TIME (10*HZ)
+#define RS_ISR_PASS_LIMIT  2 /* Beget is not a super-computer (old=256) */
+
+#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+
+#define SERIAL_INLINE
+  
+#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
+#define DBG_CNT(s) baget_printk("(%s):[%x] refc=%d, serc=%d, ttyc=%d-> %s\n", \
+  kdevname(tty->device),(info->flags),serial_refcount,info->count,tty->count,s)
+#else
+#define DBG_CNT(s)
+#endif
+
+#define  QUAD_UART_SPEED  /* Useful for Baget */
+
+/*
+ * End of serial driver configuration section.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+#endif
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/serial.h>
+#include <asm/baget/baget.h>
+
+#define BAGET_VAC_UART_IRQ 0x35
+
+/*
+ *  Implementation note:
+ *  It was descovered by means of advanced electronic tools,
+ *  if the driver works via TX_READY interrupts then VIC generates
+ *  strange self-eliminating traps. Thus, the driver is rewritten to work
+ *  via TX_EMPTY
+ */
+
+/* VAC-specific check/debug switches */
+
+#undef CHECK_REG_INDEX
+#undef DEBUG_IO_PORT_A
+
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+	
+static char *serial_name = "VAC Serial driver";
+static char *serial_version = "4.26";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+ 
+/*
+ * IRQ_timeout		- How long the timeout should be for each IRQ
+ * 				should be after the IRQ has been active.
+ */
+
+static struct async_struct *IRQ_ports[NR_IRQS];
+static int IRQ_timeout[NR_IRQS];
+#ifdef CONFIG_SERIAL_CONSOLE
+static struct console sercons;
+#endif
+
+static void autoconfig(struct serial_state * info);
+static void change_speed(struct async_struct *info);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+
+/*
+ * Here we define the default xmit fifo size used for each type of
+ * UART
+ */
+static struct serial_uart_config uart_config[] = {
+        { "unknown",  1, 0 },  /* Must go first  --  used as unasigned */
+        { "VAC UART", 1, 0 }
+}; 
+#define VAC_UART_TYPE 1   /* Just index in above array */
+
+static struct serial_state rs_table[] = {
+/*
+ * VAC has tricky layout for pair of his SIO registers,
+ *  so we need special function to access ones.
+ *  To identify port we use their TX offset
+ */
+        { 0, 9600, VAC_UART_B_TX, BAGET_VAC_UART_IRQ, 
+          STD_COM_FLAGS }, /* VAC UART B */
+        { 0, 9600, VAC_UART_A_TX, BAGET_VAC_UART_IRQ, 
+          STD_COM_FLAGS }  /* VAC UART A */
+};
+
+#define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
+
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write.  We need to
+ * lock it in case the copy_from_user 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;
+static struct semaphore tmp_buf_sem = MUTEX;
+
+static inline int serial_paranoia_check(struct async_struct *info,
+					kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null async_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, kdevname(device), routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, kdevname(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+  To unify UART A/B access we will use following function 
+  to compute register offsets by register index.
+ */
+
+#define VAC_UART_MODE       0
+#define VAC_UART_TX         1
+#define VAC_UART_RX         2
+#define VAC_UART_INT_MASK   3
+#define VAC_UART_INT_STATUS 4
+
+#define VAC_UART_REG_NR     5
+
+static inline int uart_offset_map(unsigned long port, int reg_index) 
+{
+	static const unsigned int ind_to_reg[VAC_UART_REG_NR][NR_PORTS] = {
+		{ VAC_UART_B_MODE,       VAC_UART_A_MODE       },
+		{ VAC_UART_B_TX,         VAC_UART_A_TX         },
+		{ VAC_UART_B_RX,         VAC_UART_A_RX         },
+		{ VAC_UART_B_INT_MASK,   VAC_UART_A_INT_MASK   },
+		{ VAC_UART_B_INT_STATUS, VAC_UART_A_INT_STATUS }
+	};
+#ifdef CHECK_REG_INDEX
+	if (reg_index > VAC_UART_REG_NR) panic("vacserial: bad reg_index");
+#endif
+        return ind_to_reg[reg_index][port == VAC_UART_B_TX ? 0 : 1];
+}
+
+static inline unsigned int serial_inw(struct async_struct *info, int offset)
+{
+	int val = vac_inw(uart_offset_map(info->port,offset));
+#ifdef DEBUG_IO_PORT_A
+	if (info->port == VAC_UART_A_TX)
+		printk("UART_A_IN: reg = 0x%04x, val = 0x%04x\n", 
+		       uart_offset_map(info->port,offset), val);
+#endif
+	return val;
+}
+
+static inline unsigned int serial_inp(struct async_struct *info, int offset)
+{
+	return serial_inw(info, offset);
+}
+
+static inline unsigned int serial_in(struct async_struct *info, int offset)
+{
+	return serial_inw(info, offset);
+}
+
+static inline void serial_outw(struct async_struct *info,int offset, int value)
+{
+#ifdef DEBUG_IO_PORT_A
+	if (info->port == VAC_UART_A_TX)
+		printk("UART_A_OUT: offset = 0x%04x, val = 0x%04x\n", 
+		       uart_offset_map(info->port,offset), value);
+#endif
+	vac_outw(value, uart_offset_map(info->port,offset));
+}
+
+static inline void serial_outp(struct async_struct *info,int offset, int value)
+{
+	serial_outw(info,offset,value);
+}
+
+static inline void serial_out(struct async_struct *info,int offset, int value)
+{
+	serial_outw(info,offset,value);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+	
+	save_flags(flags); cli();
+        if (info->IER & VAC_UART_INT_TX_EMPTY) {
+                info->IER &= ~VAC_UART_INT_TX_EMPTY;
+		serial_out(info, VAC_UART_INT_MASK, info->IER);
+	}
+	restore_flags(flags);
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_start"))
+		return;
+	
+	save_flags(flags); cli();
+	if (info->xmit_cnt && info->xmit_buf 
+            && !(info->IER & VAC_UART_INT_TX_EMPTY)) {
+                info->IER |= VAC_UART_INT_TX_EMPTY;
+		serial_out(info, VAC_UART_INT_MASK, info->IER);
+	}
+	restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(struct async_struct *info,
+				  int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(struct async_struct *info,
+				   int *status)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned short rx;
+	unsigned char ch;
+	int ignored = 0;
+	struct	async_icount *icount;
+
+	icount = &info->state->icount;
+	do {
+		rx = serial_inw(info, VAC_UART_RX);
+		ch = VAC_UART_RX_DATA_MASK & rx;
+
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			break;
+		*tty->flip.char_buf_ptr = ch;
+		icount->rx++;
+		
+#ifdef SERIAL_DEBUG_INTR
+		baget_printk("DR%02x:%02x...", rx, *status);
+#endif
+		*tty->flip.flag_buf_ptr = 0;
+		if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE 
+			       | VAC_UART_STATUS_RX_ERR_PARITY 
+			       | VAC_UART_STATUS_RX_ERR_FRAME 
+			       | VAC_UART_STATUS_RX_ERR_OVERRUN)) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & VAC_UART_STATUS_RX_BREAK_CHANGE) {
+				*status &= ~(VAC_UART_STATUS_RX_ERR_FRAME 
+					     | VAC_UART_STATUS_RX_ERR_PARITY);
+				icount->brk++;
+			} else if (*status & VAC_UART_STATUS_RX_ERR_PARITY)
+				icount->parity++;
+			else if (*status & VAC_UART_STATUS_RX_ERR_FRAME)
+				icount->frame++;
+			if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN)
+				icount->overrun++;
+
+			/*
+			 * Now check to see if character should be
+			 * ignored, and mask off conditions which
+			 * should be ignored.
+			 */
+			if (*status & info->ignore_status_mask) {
+				if (++ignored > 100)
+					break;
+				goto ignore_char;
+			}
+			*status &= info->read_status_mask;
+		
+			if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE)) {
+#ifdef SERIAL_DEBUG_INTR
+				baget_printk("handling break....");
+#endif
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				if (info->flags & ASYNC_SAK)
+					do_SAK(tty);
+			} else if (*status & VAC_UART_STATUS_RX_ERR_PARITY)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & VAC_UART_STATUS_RX_ERR_FRAME)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+			if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) {
+				/*
+				 * Overrun is special, since it's
+				 * reported immediately, and doesn't
+				 * affect the current character
+				 */
+				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+					tty->flip.count++;
+					tty->flip.flag_buf_ptr++;
+					tty->flip.char_buf_ptr++;
+					*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+				}
+			}
+		}
+		tty->flip.flag_buf_ptr++;
+		tty->flip.char_buf_ptr++;
+		tty->flip.count++;
+	ignore_char:
+		*status = serial_inw(info, VAC_UART_INT_STATUS);
+	} while ((*status & VAC_UART_STATUS_RX_READY));
+	tty_flip_buffer_push(tty);
+}
+
+static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
+{
+	int count;
+	
+	if (info->x_char) {
+		serial_outw(info, VAC_UART_TX, 
+			    (((unsigned short)info->x_char)<<8));
+		info->state->icount.tx++;
+		info->x_char = 0;
+		if (intr_done)
+			*intr_done = 0;
+		return;
+	}
+	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
+	    info->tty->hw_stopped) {
+                info->IER &= ~VAC_UART_INT_TX_EMPTY;
+		serial_outw(info, VAC_UART_INT_MASK, info->IER);
+		return;
+	}
+	count = info->xmit_fifo_size;
+	do {
+		serial_out(info, VAC_UART_TX, 
+			   (unsigned short)info->xmit_buf[info->xmit_tail++] \
+			   << 8);
+		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+		info->state->icount.tx++;
+		if (--info->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+	
+	if (info->xmit_cnt < WAKEUP_CHARS)
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+#ifdef SERIAL_DEBUG_INTR
+	baget_printk("THRE...");
+#endif
+	if (intr_done)
+		*intr_done = 0;
+
+	if (info->xmit_cnt <= 0) {
+                info->IER &= ~VAC_UART_INT_TX_EMPTY;
+		serial_outw(info, VAC_UART_INT_MASK, info->IER);
+	}
+}
+
+static _INLINE_ void check_modem_status(struct async_struct *info)
+{
+#if 0 /* VAC hasn't modem control */
+	wake_up_interruptible(&info->open_wait);
+	rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); 
+#endif
+}
+
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+
+
+/*
+ *  Specific functions needed for VAC UART interrupt enter/leave
+ */
+
+#define VAC_INT_CTRL_UART_ENABLE  \
+   (VAC_INT_CTRL_TIMER_PIO10|VAC_INT_CTRL_UART_B_PIO7|VAC_INT_CTRL_UART_A_PIO7)
+
+#define VAC_INT_CTRL_UART_DISABLE(info) \
+   (VAC_INT_CTRL_TIMER_PIO10 | \
+    ((info->port == VAC_UART_A_TX) ? \
+     (VAC_INT_CTRL_UART_A_DISABLE|VAC_INT_CTRL_UART_B_PIO7) : \
+     (VAC_INT_CTRL_UART_A_PIO7|VAC_INT_CTRL_UART_B_DISABLE)))
+
+/*
+ *  Following two functions were proposed by Pavel Osipenko 
+ *  to make VAC/VIC behaviour more regular.
+ */
+static void intr_begin(struct async_struct* info) 
+{
+	serial_outw(info, VAC_UART_INT_MASK, 0);
+}
+
+static void intr_end(struct async_struct* info)
+{
+	vac_outw(VAC_INT_CTRL_UART_DISABLE(info), VAC_INT_CTRL);
+	vac_outw(VAC_INT_CTRL_UART_ENABLE,        VAC_INT_CTRL); 
+
+	serial_outw(info, VAC_UART_INT_MASK, info->IER);
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	int status;
+	struct async_struct * info;
+	int pass_counter = 0;
+	struct async_struct *end_mark = 0;
+
+#ifdef SERIAL_DEBUG_INTR
+	baget_printk("rs_interrupt(%d)...", irq);
+#endif
+
+	info = IRQ_ports[irq];
+	if (!info)
+		return;
+
+	do {
+	        intr_begin(info);  /* Mark we begin port handling */
+
+		if (!info->tty ||
+		     (serial_inw (info, VAC_UART_INT_STATUS) 
+		      & VAC_UART_STATUS_INTS) == 0) 
+		    {
+			if (!end_mark)
+				end_mark = info;
+			goto next;
+		    }
+		end_mark = 0;
+
+		info->last_active = jiffies;
+
+		status = serial_inw(info, VAC_UART_INT_STATUS);
+#ifdef SERIAL_DEBUG_INTR
+		baget_printk("status = %x...", status);
+#endif
+		if (status & VAC_UART_STATUS_RX_READY) {
+			receive_chars(info, &status);
+		}
+		check_modem_status(info);
+                if (status & VAC_UART_STATUS_TX_EMPTY)
+			transmit_chars(info, 0);
+
+	next:
+		intr_end(info);   /* Mark this port handled */
+
+		info = info->next_port;
+		if (!info) {
+			info = IRQ_ports[irq];
+			if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+				break; 	/* Prevent infinite loops */
+			}
+			continue;
+		}
+	} while (end_mark != info);
+#ifdef SERIAL_DEBUG_INTR
+	baget_printk("end.\n");
+#endif
+
+
+}
+#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */
+
+
+/* The original driver was simplified here: 
+   two functions were joined to reduce code */
+
+#define rs_interrupt_single rs_interrupt
+
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+	run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+	struct async_struct	*info = (struct async_struct *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+}
+
+/*
+ * ---------------------------------------------------------------
+ * Low level utility subroutines for the serial driver:  routines to
+ * figure out the appropriate timeout for an interrupt chain, routines
+ * to initialize and startup a serial port, and routines to shutdown a
+ * serial port.  Useful stuff like that.
+ * ---------------------------------------------------------------
+ */
+
+/*
+ * This routine figures out the correct timeout for a particular IRQ.
+ * It uses the smallest timeout of all of the serial ports in a
+ * particular interrupt chain.  Now only used for IRQ 0....
+ */
+static void figure_IRQ_timeout(int irq)
+{
+	struct	async_struct	*info;
+	int	timeout = 60*HZ;	/* 60 seconds === a long time :-) */
+
+	info = IRQ_ports[irq];
+	if (!info) {
+		IRQ_timeout[irq] = 60*HZ;
+		return;
+	}
+	while (info) {
+		if (info->timeout < timeout)
+			timeout = info->timeout;
+		info = info->next_port;
+	}
+	if (!irq)
+		timeout = timeout / 2;
+	IRQ_timeout[irq] = timeout ? timeout : 1;
+}
+
+static int startup(struct async_struct * info)
+{
+	unsigned long flags;
+	int	retval=0;
+	void (*handler)(int, void *, struct pt_regs *);
+	struct serial_state *state= info->state;
+	unsigned long page;
+
+	page = get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	save_flags(flags); cli();
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		free_page(page);
+		goto errout;
+	}
+	if (!state->port || !state->type) {
+		if (info->tty)
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		free_page(page);
+		goto errout;
+	}
+	if (info->xmit_buf)
+		free_page(page);
+	else
+		info->xmit_buf = (unsigned char *) page;
+
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("starting up ttys%d (irq %d)...", info->line, state->irq);
+#endif
+
+	if (uart_config[info->state->type].flags & UART_STARTECH) {
+		/* Wake up UART */
+		serial_outp(info, VAC_UART_MODE, 0);
+		serial_outp(info, VAC_UART_INT_MASK, 0);
+	}
+
+	/*
+	 * Allocate the IRQ if necessary
+	 */
+	if (state->irq && (!IRQ_ports[state->irq] ||
+			  !IRQ_ports[state->irq]->next_port)) {
+
+		if (IRQ_ports[state->irq]) {
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+			free_irq(state->irq, NULL);
+				handler = rs_interrupt;
+#else
+			retval = -EBUSY;
+			goto errout;
+#endif /* CONFIG_SERIAL_SHARE_IRQ */
+		} else 
+			handler = rs_interrupt_single;
+
+
+		retval = request_irq(state->irq, handler, IRQ_T(info),
+				     "serial", NULL);
+		if (retval) {
+			if (capable(CAP_SYS_ADMIN)) {
+				if (info->tty)
+					set_bit(TTY_IO_ERROR,
+						&info->tty->flags);
+				retval = 0;
+			}
+			goto errout;
+		}
+	}
+
+	/*
+	 * Insert serial port into IRQ chain.
+	 */
+	info->prev_port = 0;
+	info->next_port = IRQ_ports[state->irq];
+	if (info->next_port)
+		info->next_port->prev_port = info;
+	IRQ_ports[state->irq] = info;
+	figure_IRQ_timeout(state->irq);
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+     /* (void) serial_inw(info, VAC_UART_INT_STATUS); */   /* (see above) */
+	(void) serial_inw(info, VAC_UART_RX);
+
+	/*
+	 * Now, initialize the UART 
+	 */
+	serial_outp(info, VAC_UART_MODE, VAC_UART_MODE_INITIAL); /*reset DLAB*/
+
+	/*
+	 * Finally, enable interrupts
+	 */
+	info->IER = VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS | \
+                        VAC_UART_INT_RX_READY;
+	serial_outp(info, VAC_UART_INT_MASK, info->IER); /*enable interrupts*/
+	
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void)serial_inp(info, VAC_UART_INT_STATUS);
+	(void)serial_inp(info, VAC_UART_RX);
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	/*
+	 * Set up serial timers...
+	 */
+	timer_table[RS_TIMER].expires = jiffies + 2*HZ/100;
+	timer_active |= 1 << RS_TIMER;
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(info);
+
+	info->flags |= ASYNC_INITIALIZED;
+	restore_flags(flags);
+	return 0;
+	
+errout:
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct async_struct * info)
+{
+	unsigned long	flags;
+	struct serial_state *state;
+	int		retval;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("Shutting down serial port %d (irq %d)....", info->line,
+	       state->irq);
+#endif
+	
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->delta_msr_wait);
+	
+	/*
+	 * First unlink the serial port from the IRQ chain...
+	 */
+	if (info->next_port)
+		info->next_port->prev_port = info->prev_port;
+	if (info->prev_port)
+		info->prev_port->next_port = info->next_port;
+	else
+		IRQ_ports[state->irq] = info->next_port;
+	figure_IRQ_timeout(state->irq);
+	
+	/*
+	 * Free the IRQ, if necessary
+	 */
+	if (state->irq && (!IRQ_ports[state->irq] ||
+			  !IRQ_ports[state->irq]->next_port)) {
+		if (IRQ_ports[state->irq]) {
+			free_irq(state->irq, NULL);
+			retval = request_irq(state->irq, rs_interrupt_single,
+					     IRQ_T(info), "serial", NULL);
+			
+			if (retval)
+				printk("serial shutdown: request_irq: error %d"
+				       "  Couldn't reacquire IRQ.\n", retval);
+		} else
+			free_irq(state->irq, NULL);
+	}
+
+	if (info->xmit_buf) {
+		free_page((unsigned long) info->xmit_buf);
+		info->xmit_buf = 0;
+	}
+
+	info->IER = 0;
+	serial_outp(info, VAC_UART_INT_MASK, 0x00);	/* disable all intrs */
+	
+	/* disable break condition */
+	serial_out(info, VAC_UART_MODE, serial_inp(info, VAC_UART_MODE) & \
+		   ~VAC_UART_MODE_SEND_BREAK);
+	
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+/*
+ *  When we set line mode, we call this function 
+ *  for Baget-specific adjustments.
+ */
+
+static inline unsigned short vac_uart_mode_fixup (unsigned short cval)
+{
+#ifdef QUAD_UART_SPEED
+	/* 
+	 *  When we are using 4-x advantage in speed:
+	 *
+	 *  Disadvantage : can't support 75, 150 bauds
+	 *  Advantage    : can support 19200, 38400 bauds
+	 */
+	char speed = 7 & (cval >> 10);
+	cval &= ~(7 << 10);
+	cval |= VAC_UART_MODE_BAUD(speed-2);
+#endif
+
+	/* 
+	 *  In general, we have Tx and Rx ON all time
+	 *  and use int mask flag for their disabling.
+	 */
+	cval |= VAC_UART_MODE_RX_ENABLE;
+	cval |= VAC_UART_MODE_TX_ENABLE;
+	cval |= VAC_UART_MODE_CHAR_RX_ENABLE;
+	cval |= VAC_UART_MODE_CHAR_TX_ENABLE;
+
+        /* Low 4 bits are not used in UART */	
+	cval &= ~0xf; 
+
+	return cval; 
+}
+
+/*
+ * 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)
+{
+	unsigned short port;
+	int	quot = 0, baud_base, baud;
+	unsigned cflag, cval;
+	int	bits;
+	unsigned long	flags;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+	if (!(port = info->port))
+		return;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	      case CS7: cval = 0x0;  bits = 9; break;
+	      case CS8: cval = VAC_UART_MODE_8BIT_CHAR; bits = 10; break;
+	      /* Never happens, but GCC is too dumb to figure it out */
+	      case CS5: 
+	      case CS6: 
+	      default:  cval = 0x0; bits = 9; break;
+	      }
+	cval &= ~VAC_UART_MODE_PARITY_ENABLE;
+	if (cflag & PARENB) {
+		cval |= VAC_UART_MODE_PARITY_ENABLE;
+		bits++;
+	}
+	if (cflag & PARODD)
+		cval |= VAC_UART_MODE_PARITY_ODD;
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(info->tty);
+	baud_base = info->state->baud_base;
+	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;
+	}
+	/* If the quotient is ever zero, default to 9600 bps */
+	if (!quot)
+		quot = baud_base / 9600;
+	info->quot = quot;
+	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	serial_out(info, VAC_UART_INT_MASK, info->IER);
+
+	/*
+	 * Set up parity check flag
+	 */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	info->read_status_mask = VAC_UART_STATUS_RX_ERR_OVERRUN | \
+                VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_RX_READY;
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= VAC_UART_STATUS_RX_ERR_FRAME | \
+			VAC_UART_STATUS_RX_ERR_PARITY;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE;
+	
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(info->tty))
+		info->ignore_status_mask |= VAC_UART_STATUS_RX_ERR_PARITY | \
+			VAC_UART_STATUS_RX_ERR_FRAME;
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty))
+			info->ignore_status_mask |= \
+				VAC_UART_STATUS_RX_ERR_OVERRUN;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		info->ignore_status_mask |= VAC_UART_STATUS_RX_READY;
+	save_flags(flags); cli();
+
+
+	switch (baud) {
+	default:
+	case 9600:
+		cval |= VAC_UART_MODE_BAUD(7);
+		break;
+	case 4800:
+		cval |= VAC_UART_MODE_BAUD(6);
+		break;
+	case 2400:
+		cval |= VAC_UART_MODE_BAUD(5);
+		break;
+	case 1200:
+		cval |= VAC_UART_MODE_BAUD(4);
+		break;
+	case 600:
+		cval |= VAC_UART_MODE_BAUD(3);
+		break;
+	case 300:
+		cval |= VAC_UART_MODE_BAUD(2);
+		break;
+#ifndef QUAD_UART_SPEED
+	case 150:
+#else
+	case 38400:
+#endif
+		cval |= VAC_UART_MODE_BAUD(1);
+		break;
+#ifndef QUAD_UART_SPEED
+	case 75:
+#else
+	case 19200:
+#endif
+		cval |= VAC_UART_MODE_BAUD(0);
+		break;
+	}
+
+	/* Baget VAC need some adjustments for computed value */
+	cval = vac_uart_mode_fixup(cval);
+
+	serial_outp(info, VAC_UART_MODE, cval);
+	restore_flags(flags);
+}
+
+static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_put_char"))
+		return;
+
+	if (!tty || !info->xmit_buf)
+		return;
+
+	save_flags(flags); cli();
+	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+		restore_flags(flags);
+		return;
+	}
+
+	info->xmit_buf[info->xmit_head++] = ch;
+	info->xmit_head &= SERIAL_XMIT_SIZE-1;
+	info->xmit_cnt++;
+	restore_flags(flags);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !info->xmit_buf)
+		return;
+
+	save_flags(flags); cli();
+        info->IER |= VAC_UART_INT_TX_EMPTY;
+	serial_out(info, VAC_UART_INT_MASK, info->IER);
+	restore_flags(flags);
+}
+
+static int rs_write(struct tty_struct * tty, int from_user,
+		    const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+		
+	if (serial_paranoia_check(info, tty->device, "rs_write"))
+		return 0;
+
+	if (!tty || !info->xmit_buf || !tmp_buf)
+		return 0;
+
+	save_flags(flags);
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count,
+				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
+
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+			cli();
+			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count,
+				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
+			memcpy(info->xmit_buf + info->xmit_head, buf, c);
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+	}
+	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
+            !(info->IER & VAC_UART_INT_TX_EMPTY)) {
+                info->IER |= VAC_UART_INT_TX_EMPTY;
+		serial_out(info, VAC_UART_INT_MASK, info->IER);
+	}
+	return ret;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	int	ret;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+		return 0;
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+		return 0;
+	return info->xmit_cnt;
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	unsigned long flags; 
+				
+	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+		return;
+
+	save_flags(flags); cli();
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	restore_flags(flags); 
+
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_send_char"))
+		return;
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+                info->IER |= VAC_UART_INT_TX_EMPTY;
+		serial_out(info, VAC_UART_INT_MASK, info->IER);
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	baget_printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+		return;
+	
+	if (I_IXOFF(tty))
+		rs_send_xchar(tty, STOP_CHAR(tty));
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	baget_printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+		return;
+	
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			rs_send_xchar(tty, START_CHAR(tty));
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct async_struct * info,
+			   struct serial_struct * retinfo)
+{
+	struct serial_struct tmp;
+	struct serial_state *state = info->state;
+   
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = state->type;
+	tmp.line = state->line;
+	tmp.port = state->port;
+	tmp.irq = state->irq;
+	tmp.flags = state->flags;
+	tmp.xmit_fifo_size = state->xmit_fifo_size;
+	tmp.baud_base = state->baud_base;
+	tmp.close_delay = state->close_delay;
+	tmp.closing_wait = state->closing_wait;
+	tmp.custom_divisor = state->custom_divisor;
+	tmp.hub6 = state->hub6;
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_serial_info(struct async_struct * info,
+			   struct serial_struct * new_info)
+{
+	struct serial_struct new_serial;
+ 	struct serial_state old_state, *state;
+	unsigned int		i,change_irq,change_port;
+	int 			retval = 0;
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+	state = info->state;
+	old_state = *state;
+  
+	change_irq = new_serial.irq != state->irq;
+	change_port = (new_serial.port != state->port) ||
+		(new_serial.hub6 != state->hub6);
+  
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (change_irq || change_port ||
+		    (new_serial.baud_base != state->baud_base) ||
+		    (new_serial.type != state->type) ||
+		    (new_serial.close_delay != state->close_delay) ||
+		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (state->flags & ~ASYNC_USR_MASK)))
+			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));
+		state->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	new_serial.irq = irq_cannonicalize(new_serial.irq);
+
+	if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
+	    (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) ||
+	    (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) ||
+	    (new_serial.type == PORT_STARTECH)) {
+		return -EINVAL;
+	}
+
+	if ((new_serial.type != state->type) ||
+	    (new_serial.xmit_fifo_size <= 0))
+		new_serial.xmit_fifo_size =
+			uart_config[state->type].dfl_xmit_fifo_size;
+
+	/* Make sure address is not already in use */
+	if (new_serial.type) {
+		for (i = 0 ; i < NR_PORTS; i++)
+			if ((state != &rs_table[i]) &&
+			    (rs_table[i].port == new_serial.port) &&
+			    rs_table[i].type)
+				return -EADDRINUSE;
+	}
+
+	if ((change_port || change_irq) && (state->count > 1))
+		return -EBUSY;
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	state->baud_base = new_serial.baud_base;
+	state->flags = ((state->flags & ~ASYNC_FLAGS) |
+			(new_serial.flags & ASYNC_FLAGS));
+	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
+		       (info->flags & ASYNC_INTERNAL_FLAGS));
+	state->custom_divisor = new_serial.custom_divisor;
+	state->type = new_serial.type;
+	state->close_delay = new_serial.close_delay * HZ/100;
+	state->closing_wait = new_serial.closing_wait * HZ/100;
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	info->xmit_fifo_size = state->xmit_fifo_size =
+		new_serial.xmit_fifo_size;
+
+	release_region(state->port,8); 
+	if (change_port || change_irq) {
+		/*
+		 * We need to shutdown the serial port at the old
+		 * port/irq combination.
+		 */
+		shutdown(info);
+		state->irq = new_serial.irq;
+		info->port = state->port = new_serial.port;
+		info->hub6 = state->hub6 = new_serial.hub6;
+	}
+	if (state->type != PORT_UNKNOWN)
+		request_region(state->port,8,"serial(set)");
+
+	
+check_and_exit:
+	if (!state->port || !state->type)
+		return 0;
+	if (state->flags & ASYNC_INITIALIZED) {
+		if (((old_state.flags & ASYNC_SPD_MASK) !=
+		     (state->flags & ASYNC_SPD_MASK)) ||
+		    (old_state.custom_divisor != state->custom_divisor)) {
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+				info->tty->alt_speed = 57600;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+				info->tty->alt_speed = 115200;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+				info->tty->alt_speed = 230400;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+				info->tty->alt_speed = 460800;
+			change_speed(info);
+		}
+	} else
+		retval = startup(info);
+	return retval;
+}
+
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space. 
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int *value)
+{
+	unsigned short status;
+	unsigned int result;
+	unsigned long flags; 
+
+	save_flags(flags); cli();
+	status = serial_inw(info, VAC_UART_INT_STATUS);
+	restore_flags(flags);
+	result = ((status & VAC_UART_STATUS_TX_EMPTY) ? TIOCSER_TEMT : 0);
+	return put_user(result,value);
+}
+
+
+static int get_modem_info(struct async_struct * info, unsigned int *value)
+{
+	unsigned int result;
+
+	result = TIOCM_CAR | TIOCM_DSR;
+	return put_user(result,value);
+}
+
+static int set_modem_info(struct async_struct * info, unsigned int cmd,
+			  unsigned int *value)
+{
+	int error;
+	unsigned int arg;
+
+	error = get_user(arg, value);
+	if (error)
+		return error;
+	switch (cmd) {
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int do_autoconfig(struct async_struct * info)
+{
+	int			retval;
+	
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	
+	if (info->state->count > 1)
+		return -EBUSY;
+	
+	shutdown(info);
+
+	autoconfig(info->state);
+
+	retval = startup(info);
+	if (retval)
+		return retval;
+	return 0;
+}
+
+/*
+ * rs_break() --- routine which turns the break handling on or off
+ */
+static void rs_break(struct tty_struct *tty, int break_state)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_break"))
+		return;
+
+	if (!info->port)
+		return;
+	save_flags(flags); cli();
+	if (break_state == -1)
+		serial_outp(info, VAC_UART_MODE,
+			   serial_inp(info, VAC_UART_MODE) | \
+			    VAC_UART_MODE_SEND_BREAK);
+	else
+		serial_outp(info, VAC_UART_MODE,
+			   serial_inp(info, VAC_UART_MODE) & \
+			    ~VAC_UART_MODE_SEND_BREAK);
+	restore_flags(flags);
+}
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int error;
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	struct serial_icounter_struct *p_cuser;	/* user space */
+	unsigned long flags; 
+
+	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+	
+	switch (cmd) {
+		case TIOCMGET:
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+		case TIOCGSERIAL:
+			return get_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSSERIAL:
+			return set_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSERCONFIG:
+			return do_autoconfig(info);
+
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, (unsigned int *) arg);
+
+		case TIOCSERGSTRUCT:
+			if (copy_to_user((struct async_struct *) arg,
+					 info, sizeof(struct async_struct)))
+				return -EFAULT;
+			return 0;
+				
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		case TIOCMIWAIT:
+			save_flags(flags); cli();
+			/* note the counters on entry */
+			cprev = info->state->icount;
+			restore_flags(flags);
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				save_flags(flags); cli(); 
+				cnow = info->state->icount; /* atomic copy */
+				restore_flags(flags); 
+				if (cnow.rng == cprev.rng && 
+				    cnow.dsr == cprev.dsr && 
+				    cnow.dcd == cprev.dcd && 
+				    cnow.cts == cprev.cts)
+					return -EIO; /* no change => error */
+				if ( ((arg & TIOCM_RNG) && 
+				      (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) && 
+				      (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD)  && 
+				      (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) && 
+				      (cnow.cts != cprev.cts)) ) {
+					return 0;
+				}
+				cprev = cnow;
+			}
+			/* NOTREACHED */
+
+		/* 
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		case TIOCGICOUNT:
+			save_flags(flags); cli(); 
+			cnow = info->state->icount;
+			restore_flags(flags);
+			p_cuser = (struct serial_icounter_struct *) arg;
+			error = put_user(cnow.cts, &p_cuser->cts);
+			if (error) return error;
+			error = put_user(cnow.dsr, &p_cuser->dsr);
+			if (error) return error;
+			error = put_user(cnow.rng, &p_cuser->rng);
+			if (error) return error;
+			error = put_user(cnow.dcd, &p_cuser->dcd);
+			if (error) return error;
+                        error = put_user(cnow.rx, &p_cuser->rx);
+                        if (error) return error;
+                        error = put_user(cnow.tx, &p_cuser->tx);
+                        if (error) return error;
+                        error = put_user(cnow.frame, &p_cuser->frame);
+                        if (error) return error;
+                        error = put_user(cnow.overrun, &p_cuser->overrun);
+                        if (error) return error;
+                        error = put_user(cnow.parity, &p_cuser->parity);
+                        if (error) return error;
+                        error = put_user(cnow.brk, &p_cuser->brk);
+                        if (error) return error;
+                        error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+
+			if (error) return error;
+			return 0;
+
+                case TIOCSERGWILD:
+                case TIOCSERSWILD:
+                       /* "setserial -W" is called in Debian boot */
+                        printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
+                        return 0;
+ 
+		default:
+			return -ENOIOCTLCMD;
+		}
+	return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	
+	if (   (tty->termios->c_cflag == old_termios->c_cflag)
+	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
+		== RELEVANT_IFLAG(old_termios->c_iflag)))
+	  return;
+
+	change_speed(info);
+
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rs_start(tty);
+	}
+
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ * 
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct serial_state *state;
+	unsigned long flags;
+
+	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+		return;
+
+	state = info->state;
+	
+	save_flags(flags); cli();
+	
+	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("rs_close ttys%d, count = %d\n", 
+		     info->line, state->count);
+#endif
+	if ((tty->count == 1) && (state->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		baget_printk("rs_close: bad serial port count; "
+			     "tty->count is 1, "
+			     "state->count is %d\n", state->count);
+		state->count = 1;
+	}
+	if (--state->count < 0) {
+		baget_printk("rs_close: bad serial port count for "
+			     "ttys%d: %d\n",
+			     info->line, state->count);
+		state->count = 0;
+	}
+	if (state->count) {
+		DBG_CNT("before DEC-2");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->state->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->state->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->IER &= ~(VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS);
+	info->read_status_mask &= ~VAC_UART_STATUS_RX_READY;
+	if (info->flags & ASYNC_INITIALIZED) {
+		serial_outw(info, VAC_UART_INT_MASK, info->IER);
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		rs_wait_until_sent(tty, info->timeout);
+	}
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	MOD_DEC_USE_COUNT;
+	restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	int lsr;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+		return;
+
+	if (info->state->type == PORT_UNKNOWN)
+		return;
+
+        if (info->xmit_fifo_size == 0)
+                return; /* Just in case.... */
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 * 
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout)
+	  char_time = MIN(char_time, timeout);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	baget_printk("In rs_wait_until_sent(%d) check=%lu...", 
+		     timeout, char_time);
+	baget_printk("jiff=%lu...", jiffies);
+#endif
+	while (!((lsr = serial_inp(info, VAC_UART_INT_STATUS)) & \
+		 VAC_UART_STATUS_TX_EMPTY)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		baget_printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		current->state = TASK_INTERRUPTIBLE;
+		current->counter = 0;	/* make us low-priority */
+		schedule_timeout(char_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && ((orig_jiffies + timeout) < jiffies))
+			break;
+	}
+	current->state = TASK_RUNNING;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	baget_printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_hangup(struct tty_struct *tty)
+{
+	struct async_struct * info = (struct async_struct *)tty->driver_data;
+	struct serial_state *state = info->state;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+		return;
+
+	state = info->state;
+	
+	rs_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	state->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   struct async_struct *info)
+{
+	struct wait_queue wait = { current, NULL };
+	struct serial_state *state = info->state;
+	int		retval;
+	int		do_clocal = 0,  extra_count = 0;  
+	unsigned long   flags; 
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+		    return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+		    return -EBUSY;
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (state->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+	
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, state->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(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("block_til_ready before block: ttys%d, count = %d\n",
+	       state->line, state->count);
+#endif
+	save_flags(flags); cli(); 
+	if (!tty_hung_up_p(filp)) {
+		extra_count = 1; 
+		state->count--;
+	}
+	restore_flags(flags); 
+	info->blocked_open++;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		baget_printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, state->count);
+#endif
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (extra_count)
+		state->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, state->count);
+#endif
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+
+static int get_async_struct(int line, struct async_struct **ret_info)
+{
+	struct async_struct *info;
+	struct serial_state *sstate;
+
+	sstate = rs_table + line;
+	sstate->count++;
+	if (sstate->info) {
+		*ret_info = sstate->info;
+		return 0;
+	}
+	info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
+	if (!info) {
+		sstate->count--;
+		return -ENOMEM;
+	}
+	memset(info, 0, sizeof(struct async_struct));
+	info->magic = SERIAL_MAGIC;
+	info->port = sstate->port;
+	info->flags = sstate->flags;
+	info->xmit_fifo_size = sstate->xmit_fifo_size;
+	info->line = line;
+	info->tqueue.routine = do_softint;
+	info->tqueue.data = info;
+	info->state = sstate;
+	if (sstate->info) {
+		kfree_s(info, sizeof(struct async_struct));
+		*ret_info = sstate->info;
+		return 0;
+	}
+	*ret_info = sstate->info = info;
+	return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+	struct async_struct	*info;
+	int 			retval, line;
+	unsigned long		page;
+
+	MOD_INC_USE_COUNT; 
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= NR_PORTS)) {
+		MOD_DEC_USE_COUNT; 
+		return -ENODEV;
+	}
+	retval = get_async_struct(line, &info);
+	if (retval) {
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+        tty->driver_data = info;
+        info->tty = tty;
+	if (serial_paranoia_check(info, tty->device, "rs_open")) {
+	        /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ 
+		return -ENODEV;
+	}
+
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("rs_open %s%d, count = %d\n", 
+		     tty->driver.name, info->line,
+		     info->state->count);
+#endif
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	if (!tmp_buf) {
+		page = get_free_page(GFP_KERNEL);
+		if (!page) {
+			/* MOD_DEC_USE_COUNT; "info->tty" will cause this */
+			return -ENOMEM;
+		}
+		if (tmp_buf)
+			free_page(page);
+		else
+			tmp_buf = (unsigned char *) page;
+	}
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+		/* MOD_DEC_USE_COUNT; "info->tty" will cause this */
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval) {
+		/* MOD_DEC_USE_COUNT; "info->tty" will cause this */
+		return retval;
+	}
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+		 /* MOD_DEC_USE_COUNT; "info->tty" will cause this */
+#ifdef SERIAL_DEBUG_OPEN
+		 baget_printk("rs_open returning after block_til_ready "
+			      "with %d\n",
+			      retval);
+#endif
+		 return retval;
+	}
+
+	if ((info->state->count == 1) &&
+	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->state->normal_termios;
+		else 
+			*tty->termios = info->state->callout_termios;
+		change_speed(info);
+	}
+#ifdef CONFIG_SERIAL_CONSOLE
+	if (sercons.cflag && sercons.index == line) {
+		tty->termios->c_cflag = sercons.cflag;
+		sercons.cflag = 0;
+		change_speed(info);
+	}
+#endif
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+	baget_printk("rs_open ttys%d successful...", info->line);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline int line_info(char *buf, struct serial_state *state)
+{
+	struct async_struct *info = state->info, scr_info;
+	int	ret;
+
+	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
+		      state->line, uart_config[state->type].name, 
+		      state->port, state->irq);
+
+	if (!state->port || (state->type == PORT_UNKNOWN)) {
+		ret += sprintf(buf+ret, "\n");
+		return ret;
+	}
+
+	/*
+	 * Figure out the current RS-232 lines
+	 */
+	if (!info) {
+		info = &scr_info;	/* This is just for serial_{in,out} */
+
+		info->magic = SERIAL_MAGIC;
+		info->port = state->port;
+		info->flags = state->flags;
+		info->quot = 0;
+		info->tty = 0;
+	}
+	
+	if (info->quot) {
+		ret += sprintf(buf+ret, " baud:%d",
+			       state->baud_base / info->quot);
+	}
+
+	ret += sprintf(buf+ret, " tx:%d rx:%d",
+		      state->icount.tx, state->icount.rx);
+
+	if (state->icount.frame)
+		ret += sprintf(buf+ret, " fe:%d", state->icount.frame);
+	
+	if (state->icount.parity)
+		ret += sprintf(buf+ret, " pe:%d", state->icount.parity);
+	
+	if (state->icount.brk)
+		ret += sprintf(buf+ret, " brk:%d", state->icount.brk);	
+
+	if (state->icount.overrun)
+		ret += sprintf(buf+ret, " oe:%d", state->icount.overrun);
+
+	return ret;
+}
+
+int rs_read_proc(char *page, char **start, off_t off, int count,
+		 int *eof, void *data)
+{
+	int i, len = 0, l;
+	off_t	begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+	for (i = 0; i < NR_PORTS && len < 4000; i++) {
+                l = line_info(page + len, &rs_table[i]);
+                len += l;
+ 		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static _INLINE_ void show_serial_version(void)
+{
+ 	printk(KERN_INFO "%s version %s with", serial_name, serial_version);
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+	printk(" SHARE_IRQ");
+#endif
+#define SERIAL_OPT
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+	printk(" DETECT_IRQ");
+#endif
+#ifdef SERIAL_OPT
+	printk(" enabled\n");
+#else
+	printk(" no serial options enabled\n");
+#endif
+#undef SERIAL_OPT
+}
+
+
+/*
+ * 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.
+ */
+
+/*
+ *  Functionality of this function is reduced: we already know we have a VAC,
+ *  but still need to perform some important actions (see code :-).
+ */
+static void autoconfig(struct serial_state * state)
+{
+	struct async_struct *info, scr_info; 
+	unsigned long flags;
+
+	/* Setting up important parameters */
+	state->type = VAC_UART_TYPE;
+	state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size;
+
+	info = &scr_info;       /* This is just for serial_{in,out} */   
+
+	info->magic = SERIAL_MAGIC;
+        info->port  = state->port;
+        info->flags = state->flags;
+
+        save_flags(flags); cli();
+
+	/* + Flush VAC input fifo */ 
+        (void)serial_in(info, VAC_UART_RX);
+        (void)serial_in(info, VAC_UART_RX);
+        (void)serial_in(info, VAC_UART_RX);
+        (void)serial_in(info, VAC_UART_RX);
+
+	/* Disable interrupts */
+        serial_outp(info, VAC_UART_INT_MASK, 0);
+
+        restore_flags(flags);
+}
+
+int register_serial(struct serial_struct *req);
+void unregister_serial(int line);
+
+EXPORT_SYMBOL(register_serial);
+EXPORT_SYMBOL(unregister_serial);
+
+/*
+ *  Important function for VAC UART check and reanimation.
+ */
+
+static void rs_timer(void)
+{
+        static unsigned long last_strobe = 0;
+        struct async_struct *info;
+        unsigned int    i;
+        unsigned long flags;
+
+        if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
+                for (i=1; i < NR_IRQS; i++) {
+                        info = IRQ_ports[i];
+                        if (!info)
+                                continue;
+                        save_flags(flags); cli();
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+                        if (info->next_port) {
+                                do {
+                                        serial_out(info, VAC_UART_INT_MASK, 0);
+                                        info->IER |= VAC_UART_INT_TX_EMPTY;
+                                        serial_out(info, VAC_UART_INT_MASK, 
+						   info->IER);
+                                        info = info->next_port;
+                                } while (info);
+				rs_interrupt(i, NULL, NULL);
+                        } else
+#endif /* CONFIG_SERIAL_SHARE_IRQ */
+                                rs_interrupt_single(i, NULL, NULL);
+                        restore_flags(flags);
+                }
+        }
+        last_strobe = jiffies;
+        timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME;
+        timer_active |= 1 << RS_TIMER;
+
+	/*
+	 *  It looks this code for case we share IRQ with console...
+	 */
+
+        if (IRQ_ports[0]) {
+                save_flags(flags); cli();
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+                rs_interrupt(0, NULL, NULL);
+#else
+                rs_interrupt_single(0, NULL, NULL);
+#endif
+                restore_flags(flags);
+
+                timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2;
+        }
+}
+ 
+/*
+ * The serial driver boot-time initialization code!
+ */
+__initfunc(int rs_init(void))
+{
+	int i;
+	struct serial_state * state;
+	extern void atomwide_serial_init (void);
+	extern void dualsp_serial_init (void);
+
+#ifdef CONFIG_ATOMWIDE_SERIAL
+	atomwide_serial_init ();
+#endif
+#ifdef CONFIG_DUALSP_SERIAL
+	dualsp_serial_init ();
+#endif
+
+	init_bh(SERIAL_BH, do_serial_bh);
+	timer_table[RS_TIMER].fn = rs_timer;
+	timer_table[RS_TIMER].expires = 0;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		IRQ_ports[i] = 0;
+		IRQ_timeout[i] = 0;
+	}
+
+
+/*
+ *  It is not a good idea to share interrupts with console,
+ *  but it looks we cannot avoid it.
+ */
+#if 0 
+
+#ifdef CONFIG_SERIAL_CONSOLE
+	/*
+	 *	The interrupt of the serial console port
+	 *	can't be shared.
+	 */
+	if (sercons.flags & CON_CONSDEV) {
+		for(i = 0; i < NR_PORTS; i++)
+			if (i != sercons.index &&
+			    rs_table[i].irq == rs_table[sercons.index].irq)
+				rs_table[i].irq = 0;
+	}
+#endif
+
+#endif
+	show_serial_version();
+
+	/* Initialize the tty_driver structure */
+	
+	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.driver_name = "serial";
+	serial_driver.name = "ttyS";
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64;
+	serial_driver.num = NR_PORTS;
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+	serial_driver.init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver.flags = TTY_DRIVER_REAL_RAW;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+
+	serial_driver.open = rs_open;
+	serial_driver.close = rs_close;
+	serial_driver.write = rs_write;
+	serial_driver.put_char = rs_put_char;
+	serial_driver.flush_chars = rs_flush_chars;
+	serial_driver.write_room = rs_write_room;
+	serial_driver.chars_in_buffer = rs_chars_in_buffer;
+	serial_driver.flush_buffer = rs_flush_buffer;
+	serial_driver.ioctl = rs_ioctl;
+	serial_driver.throttle = rs_throttle;
+	serial_driver.unthrottle = rs_unthrottle;
+	serial_driver.send_xchar = rs_send_xchar;
+	serial_driver.set_termios = rs_set_termios;
+	serial_driver.stop = rs_stop;
+	serial_driver.start = rs_start;
+	serial_driver.hangup = rs_hangup;
+	serial_driver.break_ctl = rs_break;
+	serial_driver.wait_until_sent = rs_wait_until_sent;
+	serial_driver.read_proc = rs_read_proc;
+	
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+	callout_driver.name = "cua";
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
+
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout driver\n");
+	
+	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+		state->magic = SSTATE_MAGIC;
+		state->line = i;
+		state->type = PORT_UNKNOWN;
+		state->custom_divisor = 0;
+		state->close_delay = 5*HZ/10;
+		state->closing_wait = 30*HZ;
+		state->callout_termios = callout_driver.init_termios;
+		state->normal_termios = serial_driver.init_termios;
+		state->icount.cts = state->icount.dsr = 
+			state->icount.rng = state->icount.dcd = 0;
+		state->icount.rx = state->icount.tx = 0;
+		state->icount.frame = state->icount.parity = 0;
+		state->icount.overrun = state->icount.brk = 0;
+		state->irq = irq_cannonicalize(state->irq);
+		if (check_region(state->port,8))
+			continue;
+	        if (state->flags & ASYNC_BOOT_AUTOCONF)
+ 			autoconfig(state);
+	}
+
+	/*
+	 * Detect the IRQ only once every port is initialised,
+	 * because some 16450 do not reset to 0 the MCR register.
+	 */
+	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
+		if (state->type == PORT_UNKNOWN)
+			continue;
+		printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n",
+		       state->line,
+		       (state->flags & ASYNC_FOURPORT) ? " FourPort" : "",
+		       state->port, state->irq,
+		       uart_config[state->type].name);
+	}
+	return 0;
+}
+
+/*
+ * register_serial and unregister_serial allows for serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+int register_serial(struct serial_struct *req)
+{
+	int i;
+	unsigned long flags;
+	struct serial_state *state;
+
+	save_flags(flags);
+	cli();
+	for (i = 0; i < NR_PORTS; i++) {
+		if (rs_table[i].port == req->port)
+			break;
+	}
+	if (i == NR_PORTS) {
+		for (i = 0; i < NR_PORTS; i++)
+			if ((rs_table[i].type == PORT_UNKNOWN) &&
+			    (rs_table[i].count == 0))
+				break;
+	}
+	if (i == NR_PORTS) {
+		restore_flags(flags);
+		return -1;
+	}
+	state = &rs_table[i];
+	if (rs_table[i].count) {
+		restore_flags(flags);
+		printk("Couldn't configure serial #%d (port=%d,irq=%d): "
+		       "device already open\n", i, req->port, req->irq);
+		return -1;
+	}
+	state->irq = req->irq;
+	state->port = req->port;
+	state->flags = req->flags;
+
+	autoconfig(state);
+	if (state->type == PORT_UNKNOWN) {
+		restore_flags(flags);
+		printk("register_serial(): autoconfig failed\n");
+		return -1;
+	}
+	restore_flags(flags);
+
+	printk(KERN_INFO "tty%02d at 0x%04x (irq = %d) is a %s\n",
+	       state->line, state->port, state->irq,
+	       uart_config[state->type].name);
+	return state->line;
+}
+
+void unregister_serial(int line)
+{
+	unsigned long flags;
+	struct serial_state *state = &rs_table[line];
+
+	save_flags(flags);
+	cli();
+	if (state->info && state->info->tty)
+		tty_hangup(state->info->tty);
+	state->type = PORT_UNKNOWN;
+	printk(KERN_INFO "tty%02d unloaded\n", state->line);
+	restore_flags(flags);
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return rs_init();
+}
+
+void cleanup_module(void) 
+{
+	unsigned long flags;
+	int e1, e2;
+	int i;
+
+	printk("Unloading %s: version %s\n", serial_name, serial_version); 
+	save_flags(flags);
+	cli();
+
+	timer_active &= ~(1 << RS_TIMER);
+	timer_table[RS_TIMER].fn = NULL;
+	timer_table[RS_TIMER].expires = 0;
+        remove_bh(SERIAL_BH);
+
+	if ((e1 = tty_unregister_driver(&serial_driver)))
+		printk("SERIAL: failed to unregister serial driver (%d)\n",
+		       e1);
+	if ((e2 = tty_unregister_driver(&callout_driver)))
+		printk("SERIAL: failed to unregister callout driver (%d)\n", 
+		       e2);
+	restore_flags(flags);
+
+	for (i = 0; i < NR_PORTS; i++) {
+		if (rs_table[i].type != PORT_UNKNOWN)
+			release_region(rs_table[i].port, 8);
+	}
+	if (tmp_buf) {
+		free_page((unsigned long) tmp_buf);
+		tmp_buf = NULL;
+	}
+}
+#endif /* MODULE */
+
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+
+#define BOTH_EMPTY (VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_TX_EMPTY)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct async_struct *info)
+{
+	int lsr;
+	unsigned int tmout = 1000000;
+
+	do {
+		lsr = serial_inp(info, VAC_UART_INT_STATUS);
+		if (--tmout == 0) break;
+	} while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
+}
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ */
+static void serial_console_write(struct console *co, const char *s,
+				unsigned count)
+{
+	struct serial_state *ser;
+	int ier;
+	unsigned i;
+	struct async_struct scr_info; /* serial_{in,out} because HUB6 */
+
+	ser = rs_table + co->index;
+	scr_info.magic = SERIAL_MAGIC;
+	scr_info.port = ser->port;
+	scr_info.flags = ser->flags;
+
+	/*
+	 *	First save the IER then disable the interrupts
+	 */
+	ier = serial_inp(&scr_info, VAC_UART_INT_MASK);
+	serial_outw(&scr_info, VAC_UART_INT_MASK, 0x00);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(&scr_info);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		serial_outp(&scr_info, VAC_UART_TX, (unsigned short)*s << 8);
+		if (*s == 10) {
+			wait_for_xmitr(&scr_info);
+			serial_outp(&scr_info, VAC_UART_TX, 13 << 8);
+		}
+	}
+
+	/*
+	 *	Finally, Wait for transmitter & holding register to empty
+	 * 	and restore the IER
+	 */
+	wait_for_xmitr(&scr_info);
+	serial_outp(&scr_info, VAC_UART_INT_MASK, ier);
+}
+
+/*
+ *	Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+	struct serial_state *ser;
+	int ier;
+	int lsr;
+	int c;
+	struct async_struct scr_info; /* serial_{in,out} because HUB6 */
+
+	ser = rs_table + co->index;
+	scr_info.magic = SERIAL_MAGIC;
+	scr_info.port = ser->port;
+	scr_info.flags = ser->flags;
+
+	/*
+	 *	First save the IER then disable the interrupts so
+	 *	that the real driver for the port does not get the
+	 *	character.
+	 */
+	ier = serial_inp(&scr_info, VAC_UART_INT_MASK);
+	serial_outp(&scr_info, VAC_UART_INT_MASK, 0x00);
+
+	do {
+		lsr = serial_inp(&scr_info, VAC_UART_INT_STATUS);
+	} while (!(lsr & VAC_UART_STATUS_RX_READY));
+	c = serial_inp(&scr_info, VAC_UART_RX);
+
+	/*
+	 *	Restore the interrupts
+	 */
+	serial_outp(&scr_info, VAC_UART_INT_MASK, ier);
+
+	return c;
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ *	Setup initial baud/bits/parity. We do two things here:
+ *	- construct a cflag setting for the first rs_open()
+ *	- initialize the serial port
+ *	Return non-zero if we didn't find a serial port.
+ */
+__initfunc(static int serial_console_setup(struct console *co, char *options))
+{
+	struct serial_state *ser;
+	unsigned cval;
+	int	baud = 9600;
+	int	bits = 8;
+	int	parity = 'n';
+	int	cflag = CREAD | HUPCL | CLOCAL;
+	int	quot = 0;
+	char	*s;
+	struct async_struct scr_info; /* serial_{in,out} because HUB6 */
+
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while(*s >= '0' && *s <= '9')
+			s++;
+		if (*s) parity = *s++;
+		if (*s) bits   = *s - '0';
+	}
+
+	/*
+	 *	Now construct a cflag setting.
+	 */
+	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;
+	}
+	switch(bits) {
+		case 7:
+			cflag |= CS7;
+			break;
+		default:
+		case 8:
+			cflag |= CS8;
+			break;
+	}
+	switch(parity) {
+		case 'o': case 'O':
+			cflag |= PARODD;
+			break;
+		case 'e': case 'E':
+			cflag |= PARENB;
+			break;
+	}
+	co->cflag = cflag;
+
+	/*
+	 *	Divisor, bytesize and parity
+	 */
+	ser = rs_table + co->index;
+	scr_info.magic = SERIAL_MAGIC;
+	scr_info.port = ser->port;
+	scr_info.flags = ser->flags;
+
+	quot = ser->baud_base / baud;
+	cval = cflag & (CSIZE | CSTOPB);
+
+	cval >>= 4;
+
+	cval &= ~VAC_UART_MODE_PARITY_ENABLE;
+	if (cflag & PARENB)
+		cval |= VAC_UART_MODE_PARITY_ENABLE;
+	if (cflag & PARODD)
+		cval |= VAC_UART_MODE_PARITY_ODD;
+
+	/*
+	 *	Disable UART interrupts, set DTR and RTS high
+	 *	and set speed.
+	 */
+	switch (baud) {
+	default:
+	case 9600:
+		cval |= VAC_UART_MODE_BAUD(7);
+		break;
+	case 4800:
+		cval |= VAC_UART_MODE_BAUD(6);
+		break;
+	case 2400:
+		cval |= VAC_UART_MODE_BAUD(5);
+		break;
+	case 1200:
+		cval |= VAC_UART_MODE_BAUD(4);
+		break;
+	case 600:
+		cval |= VAC_UART_MODE_BAUD(3);
+		break;
+	case 300:
+		cval |= VAC_UART_MODE_BAUD(2);
+		break;
+#ifndef QUAD_UART_SPEED
+	case 150:
+#else
+	case 38400:
+#endif
+		cval |= VAC_UART_MODE_BAUD(1);
+		break;
+#ifndef QUAD_UART_SPEED
+	case 75:
+#else
+	case 19200:
+#endif
+		cval |= VAC_UART_MODE_BAUD(0);
+		break;
+	}
+
+	/* Baget VAC need some adjustments for computed value */
+	cval = vac_uart_mode_fixup(cval);
+
+        serial_outp(&scr_info, VAC_UART_MODE, cval);  
+	serial_outp(&scr_info, VAC_UART_INT_MASK, 0);
+
+	return 0;
+}
+
+static struct console sercons = {
+	"ttyS",
+	serial_console_write,
+	NULL,
+	serial_console_device,
+	serial_console_wait_key,
+	NULL,
+	serial_console_setup,
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+/*
+ *	Register console.
+ */
+__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+{
+	register_console(&sercons);
+	return kmem_start;
+}
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+#undef PRINT_DEBUG_PORT_INFO
+
+/*
+ * This is the interface to the remote debugger stub.
+ * I've put that here to be able to control the serial
+ * device more directly.
+ */
+
+static int initialized = 0;
+
+static int rs_debug_init(struct async_struct *info)
+{
+	int quot;
+
+	autoconfig(info);	/* autoconfigure ttyS0, whatever that is */
+
+#ifdef PRINT_DEBUG_PORT_INFO
+	baget_printk("kgdb debug interface:: tty%02d at 0x%04x", 
+		     info->line, info->port);
+	switch (info->type) {
+		case PORT_8250:
+			baget_printk(" is a 8250\n");
+			break;
+		case PORT_16450:
+			baget_printk(" is a 16450\n");
+			break;
+		case PORT_16550:
+			baget_printk(" is a 16550\n");
+			break;
+		case PORT_16550A:
+			baget_printk(" is a 16550A\n");
+			break;
+		case PORT_16650:
+			baget_printk(" is a 16650\n");
+			break;
+		default:
+			baget_printk(" is of unknown type -- unusable\n");
+			break;
+	}
+#endif
+	
+	if (info->port == PORT_UNKNOWN)
+		return -1;
+
+	/*
+	 * Clear all interrupts
+	 */
+
+	(void)serial_inp(info, VAC_UART_INT_STATUS);
+	(void)serial_inp(info, VAC_UART_RX);
+
+	/*
+	 * Now, initialize the UART 
+	 */
+	serial_outp(info,VAC_UART_MODE,VAC_UART_MODE_INITIAL); /* reset DLAB */
+	if (info->flags & ASYNC_FOURPORT) {
+		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+		info->MCR_noint = UART_MCR_DTR | UART_MCR_OUT1;
+	} else {
+		info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+		info->MCR_noint = UART_MCR_DTR | UART_MCR_RTS;
+	}
+
+	info->MCR = info->MCR_noint;	     /* no interrupts, please */
+	/*
+	 * and set the speed of the serial port
+	 * (currently hardwired to 9600 8N1
+	 */
+
+	quot = info->baud_base / 9600;	     /* baud rate is fixed to 9600 */
+	/* FIXME: if rs_debug interface is needed, we need to set speed here */
+
+	return 0;
+}
+
+int putDebugChar(char c)
+{
+	struct async_struct *info = rs_table;
+
+	if (!initialized) { 		/* need to init device first */
+		if (rs_debug_init(info) == 0)
+			initialized = 1;
+		else
+			return 0;
+	}
+
+	while ((serial_inw(info, VAC_UART_INT_STATUS) & \
+                VAC_UART_STATUS_TX_EMPTY) == 0)
+		;
+	serial_out(info, VAC_UART_TX, (unsigned short)c << 8);
+
+	return 1;
+}
+
+char getDebugChar(void)
+{
+	struct async_struct *info = rs_table;
+
+	if (!initialized) { 		/* need to init device first */
+		if (rs_debug_init(info) == 0)
+			initialized = 1;
+		else
+			return 0;
+	}
+	while (!(serial_inw(info, VAC_UART_INT_STATUS) & \
+		 VAC_UART_STATUS_RX_READY))
+		;
+
+	return(serial_inp(info, VAC_UART_RX));
+}
+
+#endif /* CONFIG_REMOTE_DEBUG */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/baget/wbflush.c linux.pre11.3/arch/mips/baget/wbflush.c
--- linux.vanilla/arch/mips/baget/wbflush.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/baget/wbflush.c	Mon Jul 19 23:28:47 1999
@@ -0,0 +1,24 @@
+/*
+ * Setup the right wbflush routine for Baget/MIPS.
+ *
+ * Copyright (C) 1999 Gleb Raiko & Vladimir Roganov
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/init.h>
+
+void (*__wbflush) (void);
+
+static void wbflush_baget(void);
+
+__initfunc(void wbflush_setup(void))
+{
+	__wbflush = wbflush_baget;
+}
+
+/*
+ * Baget/MIPS doesnt need to write back the WB.
+ */
+static void wbflush_baget(void)
+{
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/Makefile linux.pre11.3/arch/mips/boot/Makefile
--- linux.vanilla/arch/mips/boot/Makefile	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/boot/Makefile	Mon Jul 19 23:28:36 1999
@@ -1,11 +1,10 @@
-#
-# arch/mips/boot/Makefile
+# $Id: Makefile,v 1.9 1999/04/07 18:45:23 harald Exp $
 #
 # This file is subject to the terms and conditions of the GNU General Public
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1995 by Ralf Baechle
+# Copyright (C) 1995, 1998 by Ralf Baechle
 #
 
 .S.s:
@@ -16,35 +15,37 @@
 OBJS  = milo.o a.out.o
 
 #
+# Some DECstations need all possible sections of an ECOFF executable
+#
+ifdef CONFIG_DECSTATION
+  E2EFLAGS = -a
+else
+  E2EFLAGS =
+endif
+
+#
 # Drop some uninteresting sections in the kernel.
 # This is only relevant for ELF kernels but doesn't hurt a.out
 #
 drop-sections	= .reginfo .mdebug
 strip-flags	= $(addprefix --remove-section=,$(drop-sections))
 
-#
-# Fake compressed boot
-#
-zImage:	$(CONFIGURE) mkboot $(TOPDIR)/vmlinux
-	$(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp
-	./mkboot zImage.tmp zImage
-	rm -f zImage.tmp
+all: vmlinux.ecoff addinitrd
 
-mkboot: mkboot.c
+vmlinux.ecoff:	$(CONFIGURE) elf2ecoff $(TOPDIR)/vmlinux
+	./elf2ecoff $(TOPDIR)/vmlinux vmlinux.ecoff $(E2EFLAGS)
+
+elf2ecoff: elf2ecoff.c
 	$(HOSTCC) -o $@ $^
 
-zdisk:	zImage
-	if [ -f /etc/remote-mcopy ]; then \
-		ssh rio mcopy -o - a:vmlinux <zImage; \
-	else \
-		mcopy -o zImage a:vmlinux; \
-	fi
+addinitrd: addinitrd.c
+	$(HOSTCC) -o $@ $^
 
 # Don't build dependencies, this may die if $(CC) isn't gcc
 dep:
 
 clean:
-	rm -f zImage zImage.tmp mkboot
+	rm -f vmlinux.ecoff
 
 dummy:
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/addinitrd.c linux.pre11.3/arch/mips/boot/addinitrd.c
--- linux.vanilla/arch/mips/boot/addinitrd.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/boot/addinitrd.c	Mon Jul 19 23:28:36 1999
@@ -0,0 +1,112 @@
+/*
+ * addinitrd - program to add a initrd image to an ecoff kernel
+ *
+ * (C) 1999 Thomas Bogendoerfer
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "ecoff.h"
+
+#define MIPS_PAGE_SIZE	4096
+#define MIPS_PAGE_MASK	(MIPS_PAGE_SIZE-1)
+
+#define swab16(x) \
+        ((unsigned short)( \
+                (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
+                (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
+
+#define swab32(x) \
+        ((unsigned int)( \
+                (((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
+                (((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
+                (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
+                (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
+
+#define SWAB(a)	(swab ? swab32(a) : (a))
+
+void die (char *s)
+{
+	perror (s);
+	exit (1);
+}
+
+int main (int argc, char *argv[])
+{
+	int fd_vmlinux,fd_initrd,fd_outfile;
+	FILHDR efile;
+	AOUTHDR eaout;
+	SCNHDR esecs[3];
+	struct stat st;
+	char buf[1024];
+	unsigned long loadaddr;
+	unsigned long initrd_header[2];
+	int i;
+	int swab = 0;
+
+	if (argc != 4) {
+		printf ("Usage: %s <vmlinux> <initrd> <outfile>\n",argv[0]);
+		exit (1);
+	}
+
+	if ((fd_vmlinux = open (argv[1],O_RDWR)) < 0)
+		 die ("open vmlinux");
+	if (read (fd_vmlinux, &efile, sizeof efile) != sizeof efile)
+		die ("read file header");
+	if (read (fd_vmlinux, &eaout, sizeof eaout) != sizeof eaout)
+		die ("read aout header");
+	if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs)
+		die ("read section headers");
+
+	/*
+	 * check whether the file is good for us
+	 */
+	/* TBD */
+
+	/*
+	 * check, if we have to swab words
+	 */
+	if (ntohs(0xaa55) == 0xaa55) {
+		if (efile.f_magic == swab16(MIPSELMAGIC))
+			swab = 1;
+	} else {
+		if (efile.f_magic == swab16(MIPSEBMAGIC))
+			swab = 1;
+	}
+
+	if ((fd_initrd = open (argv[2], O_RDONLY)) < 0)
+		die ("open initrd");
+	if (fstat (fd_initrd, &st) < 0)
+		die ("fstat initrd");
+	loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size) 
+			+ MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8;
+	if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size)))
+		loadaddr += MIPS_PAGE_SIZE;
+	initrd_header[0] = SWAB(0x494E5244);
+	initrd_header[1] = SWAB(st.st_size);
+	eaout.dsize = esecs[1].s_size = initrd_header[1] = SWAB(st.st_size+8);
+	eaout.data_start = esecs[1].s_vaddr = esecs[1].s_paddr = SWAB(loadaddr);
+
+	if ((fd_outfile = open (argv[3], O_RDWR|O_CREAT|O_TRUNC,0666)) < 0)
+		die ("open outfile");
+	if (write (fd_outfile, &efile, sizeof efile) != sizeof efile)
+		die ("write file header");
+	if (write (fd_outfile, &eaout, sizeof eaout) != sizeof eaout)
+		die ("write aout header");
+	if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs)
+		die ("write section headers");
+	while ((i = read (fd_vmlinux, buf, sizeof buf)) > 0)
+		if (write (fd_outfile, buf, i) != i)
+			die ("write vmlinux");
+	if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header)
+		die ("write initrd header");
+	while ((i = read (fd_initrd, buf, sizeof buf)) > 0)
+		if (write (fd_outfile, buf, i) != i)
+			die ("write initrd");
+	close (fd_vmlinux);
+	close (fd_initrd);
+	return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/ecoff.h linux.pre11.3/arch/mips/boot/ecoff.h
--- linux.vanilla/arch/mips/boot/ecoff.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/boot/ecoff.h	Mon Jul 19 23:28:36 1999
@@ -0,0 +1,62 @@
+/*
+ * Some ECOFF definitions.
+ */
+typedef struct filehdr {
+        unsigned short  f_magic;        /* magic number */
+        unsigned short  f_nscns;        /* number of sections */
+        long            f_timdat;       /* time & date stamp */
+        long            f_symptr;       /* file pointer to symbolic header */
+        long            f_nsyms;        /* sizeof(symbolic hdr) */
+        unsigned short  f_opthdr;       /* sizeof(optional hdr) */
+        unsigned short  f_flags;        /* flags */
+} FILHDR;
+#define FILHSZ  sizeof(FILHDR)
+
+#define OMAGIC		0407
+#define MIPSEBMAGIC	0x160
+#define MIPSELMAGIC	0x162
+
+typedef struct scnhdr {
+        char            s_name[8];      /* section name */
+        long            s_paddr;        /* physical address, aliased s_nlib */
+        long            s_vaddr;        /* virtual address */
+        long            s_size;         /* section size */
+        long            s_scnptr;       /* file ptr to raw data for section */
+        long            s_relptr;       /* file ptr to relocation */
+        long            s_lnnoptr;      /* file ptr to gp histogram */
+        unsigned short  s_nreloc;       /* number of relocation entries */
+        unsigned short  s_nlnno;        /* number of gp histogram entries */
+        long            s_flags;        /* flags */
+} SCNHDR;
+#define SCNHSZ		sizeof(SCNHDR)
+#define SCNROUND	((long)16)
+
+typedef struct aouthdr {
+        short   magic;          /* see above                            */
+        short   vstamp;         /* version stamp                        */
+        long    tsize;          /* text size in bytes, padded to DW bdry*/
+        long    dsize;          /* initialized data "  "                */
+        long    bsize;          /* uninitialized data "   "             */
+        long    entry;          /* entry pt.                            */
+        long    text_start;     /* base of text used for this file      */
+        long    data_start;     /* base of data used for this file      */
+        long    bss_start;      /* base of bss used for this file       */
+        long    gprmask;        /* general purpose register mask        */
+        long    cprmask[4];     /* co-processor register masks          */
+        long    gp_value;       /* the gp value used for this object    */
+} AOUTHDR;
+#define AOUTHSZ sizeof(AOUTHDR)
+
+#define OMAGIC		0407
+#define NMAGIC		0410
+#define ZMAGIC		0413
+#define SMAGIC		0411
+#define LIBMAGIC        0443
+
+#define N_TXTOFF(f, a) \
+ ((a).magic == ZMAGIC || (a).magic == LIBMAGIC ? 0 : \
+  ((a).vstamp < 23 ? \
+   ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + 7) & 0xfffffff8) : \
+   ((FILHSZ + AOUTHSZ + (f).f_nscns * SCNHSZ + SCNROUND-1) & ~(SCNROUND-1)) ) )
+#define N_DATOFF(f, a) \
+  N_TXTOFF(f, a) + (a).tsize;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/boot/elf2ecoff.c linux.pre11.3/arch/mips/boot/elf2ecoff.c
--- linux.vanilla/arch/mips/boot/elf2ecoff.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/boot/elf2ecoff.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 1995
+ *	Ted Lemon (hereinafter referred to as the author)
+ *
+ * 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.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* elf2ecoff.c
+
+   This program converts an elf executable to an ECOFF executable.
+   No symbol table is retained.   This is useful primarily in building
+   net-bootable kernels for machines (e.g., DECstation and Alpha) which
+   only support the ECOFF object file format. */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+#include <limits.h>
+
+#include "ecoff.h"
+
+/*
+ * Some extra ELF definitions
+ * MIPS hosts may already have definitions, so we define it conditional.
+ */
+#ifndef PT_MIPS_REGINFO
+#define PT_MIPS_REGINFO 0x70000000      /* Register usage information */
+#endif
+
+/* -------------------------------------------------------------------- */
+
+struct sect {
+  unsigned long vaddr;
+  unsigned long len;
+};
+
+int phcmp ();
+char *saveRead (int file, off_t offset, off_t len, char *name);
+int copy (int, int, off_t, off_t);
+int translate_syms (int, int, off_t, off_t, off_t, off_t);
+void convert_elf_hdr (Elf32_Ehdr *);
+void convert_elf_phdrs (Elf32_Phdr *, int);
+void convert_elf_shdrs (Elf32_Shdr *, int);
+void convert_ecoff_filehdr(struct filehdr *);
+void convert_ecoff_aouthdr(struct aouthdr *);
+void convert_ecoff_esecs(struct scnhdr *, int);
+extern int errno;
+int *symTypeTable;
+int must_convert_endian = 0;
+int format_bigendian = 0;
+
+main (int argc, char **argv, char **envp)
+{
+  Elf32_Ehdr ex;
+  Elf32_Phdr *ph;
+  Elf32_Shdr *sh;
+  Elf32_Sym *symtab;
+  char *shstrtab;
+  int strtabix, symtabix;
+  int i, pad;
+  struct sect text, data, bss;
+  struct filehdr efh;
+  struct aouthdr eah;
+  struct scnhdr esecs [6];
+  int infile, outfile;
+  unsigned long cur_vma = ULONG_MAX;
+  int addflag = 0;
+  int nosecs;
+
+  text.len = data.len = bss.len = 0;
+  text.vaddr = data.vaddr = bss.vaddr = 0;
+
+  /* Check args... */
+  if (argc < 3 || argc > 4)
+    {
+    usage:
+      fprintf (stderr,
+	       "usage: elf2aout <elf executable> <a.out executable> [-a]\n");
+      exit (1);
+    }
+  if (argc == 4)
+    {
+      if (strcmp (argv [3], "-a"))
+	goto usage;
+      addflag = 1;
+    }
+
+  /* Try the input file... */
+  if ((infile = open (argv [1], O_RDONLY)) < 0)
+    {
+      fprintf (stderr, "Can't open %s for read: %s\n",
+	       argv [1], strerror (errno));
+      exit (1);
+    }
+
+  /* Read the header, which is at the beginning of the file... */
+  i = read (infile, &ex, sizeof ex);
+  if (i != sizeof ex)
+    {
+      fprintf (stderr, "ex: %s: %s.\n",
+	       argv [1], i ? strerror (errno) : "End of file reached");
+      exit (1);
+    }
+
+  if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
+	format_bigendian = 1;
+
+  if (ntohs (0xaa55) == 0xaa55) {
+	if (!format_bigendian)
+		must_convert_endian = 1;
+  } else {
+	if (format_bigendian)
+		must_convert_endian = 1;
+  }
+  if (must_convert_endian)
+	convert_elf_hdr (&ex);
+
+  /* Read the program headers... */
+  ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff,
+				ex.e_phnum * sizeof (Elf32_Phdr), "ph");
+  if (must_convert_endian)
+	convert_elf_phdrs (ph, ex.e_phnum);
+  /* Read the section headers... */
+  sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff,
+				ex.e_shnum * sizeof (Elf32_Shdr), "sh");
+  if (must_convert_endian)
+	convert_elf_shdrs (sh, ex.e_shnum);
+  /* Read in the section string table. */
+  shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset,
+		       sh [ex.e_shstrndx].sh_size, "shstrtab");
+
+  /* Figure out if we can cram the program header into an ECOFF
+     header...  Basically, we can't handle anything but loadable
+     segments, but we can ignore some kinds of segments.  We can't
+     handle holes in the address space.  Segments may be out of order,
+     so we sort them first. */
+
+  qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp);
+
+  for (i = 0; i < ex.e_phnum; i++)
+    {
+      /* Section types we can ignore... */
+      if (ph [i].p_type == PT_NULL || ph [i].p_type == PT_NOTE ||
+	  ph [i].p_type == PT_PHDR || ph [i].p_type == PT_MIPS_REGINFO)
+	continue;
+      /* Section types we can't handle... */
+      else if (ph [i].p_type != PT_LOAD)
+        {
+	  fprintf (stderr, "Program header %d type %d can't be converted.\n");
+	  exit (1);
+	}
+      /* Writable (data) segment? */
+      if (ph [i].p_flags & PF_W)
+	{
+	  struct sect ndata, nbss;
+
+	  ndata.vaddr = ph [i].p_vaddr;
+	  ndata.len = ph [i].p_filesz;
+	  nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz;
+	  nbss.len = ph [i].p_memsz - ph [i].p_filesz;
+
+	  combine (&data, &ndata, 0);
+	  combine (&bss, &nbss, 1);
+	}
+      else
+	{
+	  struct sect ntxt;
+
+	  ntxt.vaddr = ph [i].p_vaddr;
+	  ntxt.len = ph [i].p_filesz;
+
+	  combine (&text, &ntxt, 0);
+	}
+      /* Remember the lowest segment start address. */
+      if (ph [i].p_vaddr < cur_vma)
+	cur_vma = ph [i].p_vaddr;
+    }
+
+  /* Sections must be in order to be converted... */
+  if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
+      text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr)
+    {
+      fprintf (stderr, "Sections ordering prevents a.out conversion.\n");
+      exit (1);
+    }
+
+  /* If there's a data section but no text section, then the loader
+     combined everything into one section.   That needs to be the
+     text section, so just make the data section zero length following
+     text. */
+  if (data.len && !text.len)
+    {
+      text = data;
+      data.vaddr = text.vaddr + text.len;
+      data.len = 0;
+    }
+
+  /* If there is a gap between text and data, we'll fill it when we copy
+     the data, so update the length of the text segment as represented in
+     a.out to reflect that, since a.out doesn't allow gaps in the program
+     address space. */
+  if (text.vaddr + text.len < data.vaddr)
+    text.len = data.vaddr - text.vaddr;
+
+  /* We now have enough information to cons up an a.out header... */
+  eah.magic = OMAGIC;
+  eah.vstamp = 200;
+  eah.tsize = text.len;
+  eah.dsize = data.len;
+  eah.bsize = bss.len;
+  eah.entry = ex.e_entry;
+  eah.text_start = text.vaddr;
+  eah.data_start = data.vaddr;
+  eah.bss_start = bss.vaddr;
+  eah.gprmask = 0xf3fffffe;
+  memset (&eah.cprmask, '\0', sizeof eah.cprmask);
+  eah.gp_value = 0; /* unused. */
+
+  if (format_bigendian)
+    efh.f_magic = MIPSEBMAGIC;
+  else
+    efh.f_magic = MIPSELMAGIC;
+  if (addflag)
+    nosecs = 6;
+  else
+    nosecs = 3;
+  efh.f_nscns = nosecs;
+  efh.f_timdat = 0;	/* bogus */
+  efh.f_symptr = 0;
+  efh.f_nsyms = 0;
+  efh.f_opthdr = sizeof eah;
+  efh.f_flags = 0x100f; /* Stripped, not sharable. */
+
+  memset (esecs, 0, sizeof esecs);
+  strcpy (esecs [0].s_name, ".text");
+  strcpy (esecs [1].s_name, ".data");
+  strcpy (esecs [2].s_name, ".bss");
+  if (addflag) {
+    strcpy (esecs [3].s_name, ".rdata");
+    strcpy (esecs [4].s_name, ".sdata");
+    strcpy (esecs [5].s_name, ".sbss");
+  }
+  esecs [0].s_paddr = esecs [0].s_vaddr = eah.text_start;
+  esecs [1].s_paddr = esecs [1].s_vaddr = eah.data_start;
+  esecs [2].s_paddr = esecs [2].s_vaddr = eah.bss_start;
+  if (addflag) {
+    esecs [3].s_paddr = esecs [3].s_vaddr = 0;
+    esecs [4].s_paddr = esecs [4].s_vaddr = 0;
+    esecs [5].s_paddr = esecs [5].s_vaddr = 0;
+  }
+  esecs [0].s_size = eah.tsize;
+  esecs [1].s_size = eah.dsize;
+  esecs [2].s_size = eah.bsize;
+  if (addflag) {
+    esecs [3].s_size = 0;
+    esecs [4].s_size = 0;
+    esecs [5].s_size = 0;
+  }
+  esecs [0].s_scnptr = N_TXTOFF (efh, eah);
+  esecs [1].s_scnptr = N_DATOFF (efh, eah);
+#define ECOFF_SEGMENT_ALIGNMENT(a) 0x10
+#define ECOFF_ROUND(s,a) (((s)+(a)-1)&~((a)-1))
+  esecs [2].s_scnptr = esecs [1].s_scnptr +
+	  ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (&eah));
+  if (addflag) {
+    esecs [3].s_scnptr = 0;
+    esecs [4].s_scnptr = 0;
+    esecs [5].s_scnptr = 0;
+  }
+  esecs [0].s_relptr = esecs [1].s_relptr
+	  = esecs [2].s_relptr = 0;
+  esecs [0].s_lnnoptr = esecs [1].s_lnnoptr
+	  = esecs [2].s_lnnoptr = 0;
+  esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0;
+  esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0;
+  if (addflag) {
+    esecs [3].s_relptr = esecs [4].s_relptr 
+  	  = esecs [5].s_relptr = 0;
+    esecs [3].s_lnnoptr = esecs [4].s_lnnoptr
+	  = esecs [5].s_lnnoptr = 0;
+    esecs [3].s_nreloc = esecs [4].s_nreloc = esecs [5].s_nreloc = 0;
+    esecs [3].s_nlnno = esecs [4].s_nlnno = esecs [5].s_nlnno = 0;
+  }
+  esecs [0].s_flags = 0x20;
+  esecs [1].s_flags = 0x40;
+  esecs [2].s_flags = 0x82;
+  if (addflag) {
+    esecs [3].s_flags = 0x100;
+    esecs [4].s_flags = 0x200;
+    esecs [5].s_flags = 0x400;
+  }
+
+  /* Make the output file... */
+  if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0)
+    {
+      fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno));
+      exit (1);
+    }
+
+  if (must_convert_endian)
+	convert_ecoff_filehdr (&efh);
+  /* Write the headers... */
+  i = write (outfile, &efh, sizeof efh);
+  if (i != sizeof efh)
+    {
+      perror ("efh: write");
+      exit (1);
+
+    for (i = 0; i < nosecs; i++)
+      {
+        printf ("Section %d: %s phys %x  size %x  file offset %x\n", 
+	      i, esecs [i].s_name, esecs [i].s_paddr,
+	      esecs [i].s_size, esecs [i].s_scnptr);
+      }
+    }
+  fprintf (stderr, "wrote %d byte file header.\n", i);
+
+  if (must_convert_endian)
+	convert_ecoff_aouthdr (&eah);
+  i = write (outfile, &eah, sizeof eah);
+  if (i != sizeof eah)
+    {
+      perror ("eah: write");
+      exit (1);
+    }
+  fprintf (stderr, "wrote %d byte a.out header.\n", i);
+
+  if (must_convert_endian)
+	convert_ecoff_esecs (&esecs[0], nosecs);
+  i = write (outfile, &esecs, nosecs * sizeof(struct scnhdr));
+  if (i != nosecs * sizeof(struct scnhdr))
+    {
+      perror ("esecs: write");
+      exit (1);
+    }
+  fprintf (stderr, "wrote %d bytes of section headers.\n", i);
+
+  if (pad = ((sizeof efh + sizeof eah + nosecs * sizeof(struct scnhdr)) & 15))
+    {
+      pad = 16 - pad;
+      i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad);
+      if (i < 0)
+	{
+	  perror ("ipad: write");
+	  exit (1);
+	}
+      fprintf (stderr, "wrote %d byte pad.\n", i);
+    }
+
+  /* Copy the loadable sections.   Zero-fill any gaps less than 64k;
+     complain about any zero-filling, and die if we're asked to zero-fill
+     more than 64k. */
+  for (i = 0; i < ex.e_phnum; i++)
+    {
+      /* Unprocessable sections were handled above, so just verify that
+	 the section can be loaded before copying. */
+      if (ph [i].p_type == PT_LOAD && ph [i].p_filesz)
+	{
+	  if (cur_vma != ph [i].p_vaddr)
+	    {
+	      unsigned long gap = ph [i].p_vaddr - cur_vma;
+	      char obuf [1024];
+	      if (gap > 65536)
+		{
+		  fprintf (stderr, "Intersegment gap (%d bytes) too large.\n",
+			   gap);
+		  exit (1);
+		}
+	      fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap);
+	      memset (obuf, 0, sizeof obuf);
+	      while (gap)
+		{
+		  int count = write (outfile, obuf, (gap > sizeof obuf
+						     ? sizeof obuf : gap));
+		  if (count < 0)
+		    {
+		      fprintf (stderr, "Error writing gap: %s\n",
+			       strerror (errno));
+		      exit (1);
+		    }
+		  gap -= count;
+		}
+	    }
+fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz);
+	  copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz);
+	  cur_vma = ph [i].p_vaddr + ph [i].p_filesz;
+	}
+    }
+
+   /*
+     * Write a page of padding for boot PROMS that read entire pages.
+     * Without this, they may attempt to read past the end of the
+     * data section, incur an error, and refuse to boot.
+     */
+    {
+	char obuf[4096];
+	memset(obuf, 0, sizeof obuf);
+	if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) {
+	    fprintf(stderr, "Error writing PROM padding: %s\n",
+		    strerror(errno));
+	    exit(1);
+	}
+    }
+
+  /* Looks like we won... */
+  exit (0);
+}
+
+copy (out, in, offset, size)
+     int out, in;
+     off_t offset, size;
+{
+  char ibuf [4096];
+  int remaining, cur, count;
+
+  /* Go the the start of the ELF symbol table... */
+  if (lseek (in, offset, SEEK_SET) < 0)
+    {
+      perror ("copy: lseek");
+      exit (1);
+    }
+
+  remaining = size;
+  while (remaining)
+    {
+      cur = remaining;
+      if (cur > sizeof ibuf)
+	cur = sizeof ibuf;
+      remaining -= cur;
+      if ((count = read (in, ibuf, cur)) != cur)
+	{
+	  fprintf (stderr, "copy: read: %s\n",
+		   count ? strerror (errno) : "premature end of file");
+	  exit (1);
+	}
+      if ((count = write (out, ibuf, cur)) != cur)
+	{
+	  perror ("copy: write");
+	  exit (1);
+	}
+    }
+}
+
+/* Combine two segments, which must be contiguous.   If pad is true, it's
+   okay for there to be padding between. */
+combine (base, new, pad)
+     struct sect *base, *new;
+     int pad;
+{
+  if (!base -> len)
+    *base = *new;
+  else if (new -> len)
+    {
+      if (base -> vaddr + base -> len != new -> vaddr)
+	{
+	  if (pad)
+	    base -> len = new -> vaddr - base -> vaddr;
+	  else
+	    {
+	      fprintf (stderr,
+		       "Non-contiguous data can't be converted.\n");
+	      exit (1);
+	    }
+	}
+      base -> len += new -> len;
+    }
+}
+
+phcmp (h1, h2)
+     Elf32_Phdr *h1, *h2;
+{
+  if (h1 -> p_vaddr > h2 -> p_vaddr)
+    return 1;
+  else if (h1 -> p_vaddr < h2 -> p_vaddr)
+    return -1;
+  else
+    return 0;
+}
+
+char *saveRead (int file, off_t offset, off_t len, char *name)
+{
+  char *tmp;
+  int count;
+  off_t off;
+  if ((off = lseek (file, offset, SEEK_SET)) < 0)
+    {
+      fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno));
+      exit (1);
+    }
+  if (!(tmp = (char *)malloc (len)))
+    {
+      fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len);
+      exit (1);
+    }
+  count = read (file, tmp, len);
+  if (count != len)
+    {
+      fprintf (stderr, "%s: read: %s.\n",
+	       name, count ? strerror (errno) : "End of file reached");
+      exit (1);
+    }
+  return tmp;
+}
+
+#define swab16(x) \
+	((unsigned short)( \
+		(((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
+		(((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
+
+#define swab32(x) \
+	((unsigned int)( \
+		(((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
+		(((unsigned int)(x) & (unsigned int)0x0000ff00UL) <<  8) | \
+		(((unsigned int)(x) & (unsigned int)0x00ff0000UL) >>  8) | \
+		(((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
+
+void convert_elf_hdr (Elf32_Ehdr *e)
+{
+	e->e_type      = swab16(e->e_type);
+	e->e_machine   = swab16(e->e_machine);
+	e->e_version   = swab32(e->e_version);
+	e->e_entry     = swab32(e->e_entry);
+	e->e_phoff     = swab32(e->e_phoff);
+	e->e_shoff     = swab32(e->e_shoff);
+	e->e_flags     = swab32(e->e_flags);
+	e->e_ehsize    = swab16(e->e_ehsize);
+	e->e_phentsize = swab16(e->e_phentsize);
+	e->e_phnum     = swab16(e->e_phnum);
+	e->e_shentsize = swab16(e->e_shentsize);
+	e->e_shnum     = swab16(e->e_shnum);
+	e->e_shstrndx  = swab16(e->e_shstrndx);
+}
+
+void convert_elf_phdrs (Elf32_Phdr *p, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++,p++) {
+		p->p_type   = swab32(p->p_type);
+		p->p_offset = swab32(p->p_offset);
+		p->p_vaddr  = swab32(p->p_vaddr);
+		p->p_paddr  = swab32(p->p_paddr);
+		p->p_filesz = swab32(p->p_filesz);
+		p->p_memsz  = swab32(p->p_memsz);
+		p->p_flags  = swab32(p->p_flags);
+		p->p_align  = swab32(p->p_align);
+	}
+
+}
+
+void convert_elf_shdrs (Elf32_Shdr *s, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++,s++) {
+		s->sh_name      = swab32(s->sh_name);
+		s->sh_type      = swab32(s->sh_type);
+		s->sh_flags     = swab32(s->sh_flags);
+		s->sh_addr      = swab32(s->sh_addr);
+		s->sh_offset    = swab32(s->sh_offset);
+		s->sh_size      = swab32(s->sh_size);
+		s->sh_link      = swab32(s->sh_link);
+		s->sh_info      = swab32(s->sh_info);
+		s->sh_addralign = swab32(s->sh_addralign);
+		s->sh_entsize   = swab32(s->sh_entsize);
+	}
+}
+
+void convert_ecoff_filehdr(struct filehdr *f)
+{
+	f->f_magic  = swab16(f->f_magic);
+	f->f_nscns  = swab16(f->f_nscns);
+	f->f_timdat = swab32(f->f_timdat);
+	f->f_symptr = swab32(f->f_symptr);
+	f->f_nsyms  = swab32(f->f_nsyms);
+	f->f_opthdr = swab16(f->f_opthdr);
+	f->f_flags  = swab16(f->f_flags);
+}
+
+void convert_ecoff_aouthdr(struct aouthdr *a)
+{
+	a->magic      = swab16(a->magic);
+	a->vstamp     = swab16(a->vstamp);
+	a->tsize      = swab32(a->tsize);
+	a->dsize      = swab32(a->dsize);
+	a->bsize      = swab32(a->bsize);
+	a->entry      = swab32(a->entry);
+	a->text_start = swab32(a->text_start);
+	a->data_start = swab32(a->data_start);
+	a->bss_start  = swab32(a->bss_start);
+	a->gprmask    = swab32(a->gprmask);
+	a->cprmask[0] = swab32(a->cprmask[0]);
+	a->cprmask[1] = swab32(a->cprmask[1]);
+	a->cprmask[2] = swab32(a->cprmask[2]);
+	a->cprmask[3] = swab32(a->cprmask[3]);
+	a->gp_value   = swab32(a->gp_value);
+}
+
+void convert_ecoff_esecs(struct scnhdr *s, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++, s++) {
+		s->s_paddr   = swab32(s->s_paddr);
+		s->s_vaddr   = swab32(s->s_vaddr);
+		s->s_size    = swab32(s->s_size);
+		s->s_scnptr  = swab32(s->s_scnptr);
+		s->s_relptr  = swab32(s->s_relptr);
+		s->s_lnnoptr = swab32(s->s_lnnoptr);
+		s->s_nreloc  = swab16(s->s_nreloc);
+		s->s_nlnno   = swab16(s->s_nlnno);
+		s->s_flags   = swab32(s->s_flags);
+	}
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/config.in linux.pre11.3/arch/mips/config.in
--- linux.vanilla/arch/mips/config.in	Tue Feb 23 14:21:32 1999
+++ linux.pre11.3/arch/mips/config.in	Mon Jul 19 23:28:36 1999
@@ -14,6 +14,8 @@
 bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'Support for Algorithmics P4032' CONFIG_ALGOR_P4032
+  bool 'Support for BAGET MIPS series' CONFIG_BAGET_MIPS
+  bool 'Support for DECstations' CONFIG_DECSTATION
 fi
 bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
@@ -33,14 +35,13 @@
 if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
 	define_bool CONFIG_MIPS_JAZZ y
-	define_bool CONFIG_VIDEO_G364 y
-	define_bool CONFIG_VGA_CONSOLE y
+	define_bool CONFIG_FB y
+	define_bool CONFIG_FB_G364 y	
 fi
 if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
 	define_bool CONFIG_MIPS_JAZZ y
 fi
 if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
-	define_bool CONFIG_VGA_CONSOLE y
 	define_bool CONFIG_PCI y
 fi
 endmenu
@@ -61,14 +62,23 @@
 
 mainmenu_option next_comment
 comment 'General setup'
+
+if [ "$CONFIG_PCI" = "y" ]; then
+  bool '   PCI quirks' CONFIG_PCI_QUIRKS
+  if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
+  fi
+  bool '   Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
+fi
+
 if [ "$CONFIG_DECSTATION" = "y" ]; then
-  bool 'Compile the kernel into the ECOFF object format' CONFIG_ECOFF_KERNEL
   define_bool CONFIG_CPU_LITTLE_ENDIAN y
 else
-  define_bool CONFIG_ELF_KERNEL y
   bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
 fi
 
+define_bool CONFIG_ELF_KERNEL y
+
 if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then
   define_bool CONFIG_BINFMT_IRIX y
   define_bool CONFIG_FORWARD_KEYBOARD y
@@ -77,7 +87,6 @@
 define_bool CONFIG_BINFMT_ELF y
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
   tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA
 fi
 
@@ -86,7 +95,7 @@
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
-if [ "$CONFIG_SGI" != "y" ]; then
+if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
   tristate 'Parallel port support' CONFIG_PARPORT
 fi
 endmenu
@@ -105,6 +114,16 @@
 
 endmenu
 
+if [ "$CONFIG_DECSTATION" = "y" ]; then
+	mainmenu_option next_comment
+	comment 'TURBOchannel support'
+		bool 'TURBOchannel support' CONFIG_TC
+#		if [ "$CONFIG_TC" = "y" ]; then
+# 			tristate 'MAGMA Parallel port support' CONFIG_PARPORT
+#		fi
+	endmenu
+fi
+
 source drivers/block/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
@@ -117,7 +136,7 @@
 tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
-	if [ "$CONFIG_SGI" = "y" ]; then
+	if [ "$CONFIG_SGI" = "y" -o "$CONFIG_DECSTATION" = "y" ]; then
 		comment 'SCSI support type (disk, tape, CDrom)'
 
 		dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
@@ -133,9 +152,15 @@
 
 		#mainmenu_option next_comment
 		comment 'SCSI low-level drivers'
-
+		if [ "$CONFIG_SGI" = "y" ]; then
 		dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI
 	else
+			if [ "$CONFIG_TC" = "y" ]; then
+				dep_tristate 'DEC NCR53C94 Scsi Driver' CONFIG_SCSI_DECNCR $CONFIG_SCSI
+			fi
+			dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI
+		fi
+	else
 		source drivers/scsi/Config.in
 	fi
 fi
@@ -147,7 +172,7 @@
 
   bool 'Network device support' CONFIG_NETDEVICES
   if [ "$CONFIG_NETDEVICES" = "y" ]; then
-    if [ "$CONFIG_SGI" != "y" ]; then
+    if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
 	source drivers/net/Config.in
     else
 	tristate 'Dummy net driver support' CONFIG_DUMMY
@@ -160,52 +185,113 @@
 	if [ ! "$CONFIG_PPP" = "n" ]; then
 	  comment 'CCP compressors for PPP are only built as modules.'
 	fi
+        if [ "$CONFIG_SGI" = "y" ]; then
 	bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ
     fi
+	if [ "$CONFIG_DECSTATION" = "y" ]; then
+          bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE
+        fi
+	if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
+	  tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE
+	  tristate 'Baget Backplane Shared Memory support' CONFIG_BAGETBSM
+	fi
+    fi
   fi
   endmenu
 fi
 
-if [ "$CONFIG_SGI" != "y" ]; then
-	source drivers/net/hamradio/Config.in
+if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
+  source drivers/net/hamradio/Config.in
 
-	mainmenu_option next_comment
-	comment 'ISDN subsystem'
 
-	tristate 'ISDN support' CONFIG_ISDN
-	if [ "$CONFIG_ISDN" != "n" ]; then
-	  source drivers/isdn/Config.in
-	fi
-	endmenu
+  mainmenu_option next_comment
+  comment 'ISDN subsystem'
 
-	mainmenu_option next_comment
-	comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+  if [ "$CONFIG_NET" != "n" ]; then
+    tristate 'ISDN support' CONFIG_ISDN
+    if [ "$CONFIG_ISDN" != "n" ]; then
+      source drivers/isdn/Config.in
+    fi
+  fi
+  endmenu
 
-	bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
-	if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-	  source drivers/cdrom/Config.in
-	fi
-	endmenu
+
+  mainmenu_option next_comment
+  comment comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+
+  bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
+  if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+    source drivers/cdrom/Config.in
+  fi
+  endmenu
+fi
+
+if [ "$CONFIG_DECSTATION" != "y" ]; then
+  source drivers/char/Config.in
+else
+  mainmenu_option next_comment
+  comment 'DECstation Character devices'
+
+  bool 'Virtual terminal' CONFIG_VT
+  if [ "$CONFIG_VT" = "y" ]; then
+    bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
+  fi
+  tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
+  if [ "$CONFIG_SGI" = "y" ]; then
+    bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE
+  fi
+  if [ "$CONFIG_SERIAL" = "y" ]; then
+    bool 'DZ11 Serial Support' CONFIG_DZ
+    if [ "$CONFIG_TC" = "y" ]; then
+      bool 'Z85C30 Serial Support' CONFIG_ZS
+    fi
+    bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
+  fi
+  bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
+  if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+    int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+  fi
+  bool 'Keyboard Support' CONFIG_KEYBOARD
+  bool 'Mouse Support' CONFIG_MOUSE
+#    bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+  endmenu
 fi
 
-source drivers/char/Config.in
+# source drivers/usb/Config.in
 
 source fs/Config.in
 
-comment 'Console drivers'
-source drivers/video/Config.in
+if [ "$CONFIG_VT" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Console drivers'
+  if [ "$CONFIG_SGI" = "y" ]; then
+    tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
+    if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
+      define_bool CONFIG_DUMMY_CONSOLE y
+    fi
+  else
+    if [ "$CONFIG_DECSTATION" != "y" ]; then
+    bool 'VGA text console' CONFIG_VGA_CONSOLE
+    fi
+    bool 'Support for frame buffer devices' CONFIG_FB
+    source drivers/video/Config.in
+  fi
+  endmenu
+fi
 
-mainmenu_option next_comment
-comment 'Sound'
+if [ "$CONFIG_DECSTATION" != "y" ]; then
+  mainmenu_option next_comment
+  comment 'Sound'
 
-tristate 'Sound card support' CONFIG_SOUND
-if [ "$CONFIG_SOUND" != "n" ]; then
+  tristate 'Sound card support' CONFIG_SOUND
+  if [ "$CONFIG_SOUND" != "n" ]; then
   source drivers/sound/Config.in
+  fi
+  endmenu
 fi
-endmenu
 
 if [ "$CONFIG_SGI" = "y" ]; then
-  source drivers/sgi/char/Config.in
+  source drivers/sgi/Config.in
 fi
 
 mainmenu_option next_comment
@@ -216,6 +302,8 @@
 if [ "$CONFIG_MODULES" = "y" ]; then
   bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE
 fi
-bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
+if [ "$CONFIG_SERIAL" = "y" ]; then
+  bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
+fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/Makefile linux.pre11.3/arch/mips/dec/Makefile
--- linux.vanilla/arch/mips/dec/Makefile	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/dec/Makefile	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,30 @@
+#
+# Makefile for the DECstation family specific parts of the kernel
+#
+# 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).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: dec.o
+O_TARGET := dec.o
+O_OBJS	 := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o
+
+ifdef CONFIG_PROM_CONSOLE
+O_OBJS   += promcon.o
+endif
+
+ifdef CONFIG_SERIAL
+O_OBJS   += serial.o
+endif
+
+int-handler.o:	int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/boot/Makefile linux.pre11.3/arch/mips/dec/boot/Makefile
--- linux.vanilla/arch/mips/dec/boot/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/boot/Makefile	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,26 @@
+#
+# Makefile for the DECstation family specific parts of the kernel
+#
+# 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).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+netboot: all
+	mipsel-linux-ld -N -G 0 -T ld.ecoff ../../boot/zImage \
+		dec_boot.o ramdisk.img -o nbImage
+
+all: dec_boot.o
+
+O_TARGET := dec_boot.o
+O_OBJS	 := decstation.o
+
+clean:
+	rm -f nbImage
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/boot/decstation.c linux.pre11.3/arch/mips/dec/boot/decstation.c
--- linux.vanilla/arch/mips/dec/boot/decstation.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/boot/decstation.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,91 @@
+/*
+ * arch/mips/dec/decstation.c
+ */
+#include <linux/config.h>
+
+#define RELOC
+#define INITRD
+#define DEBUG_BOOT
+
+/*
+ * Magic number indicating REX PROM available on DECSTATION.
+ */
+#define	REX_PROM_MAGIC		0x30464354
+
+#define REX_PROM_CLEARCACHE	0x7c/4
+#define REX_PROM_PRINTF		0x30/4
+
+#define VEC_RESET		0xBFC00000		/* Prom base address */
+#define	PMAX_PROM_ENTRY(x)	(VEC_RESET+((x)*8))	/* Prom jump table */
+#define	PMAX_PROM_PRINTF	PMAX_PROM_ENTRY(17)
+
+#define PARAM	(k_start + 0x2000)
+
+#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
+#define INITRD_START (*(unsigned long *) (PARAM+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
+
+extern int _ftext, _end;		/* begin and end of kernel image */
+extern void *__rd_start, *__rd_end;	/* begin and end of ramdisk image */
+extern void kernel_entry(int, char **, unsigned long, int *);
+
+void * memcpy(void * dest, const void *src, unsigned int count)
+{
+	unsigned long *tmp = (unsigned long *) dest, *s = (unsigned long *) src;
+
+	count >>= 2;
+	while (count--)
+		*tmp++ = *s++;
+
+	return dest;
+}
+
+void dec_entry(int argc, char **argv,
+	       unsigned long magic, int *prom_vec)
+{
+	void (*rex_clear_cache)(void);
+	int (*prom_printf)(char *, ...);
+	unsigned long k_start, len;
+
+	/*
+	 * The DS5100 leaves cpu with BEV enabled, clear it.
+	 */
+	asm(	"lui\t$8,0x3000\n\t"
+		"mtc0\t$8,$12\n\t"
+		".section\t.sdata\n\t"
+		".section\t.sbss\n\t"
+		".section\t.text"
+		: : : "$8");
+
+#ifdef DEBUG_BOOT
+	if (magic == REX_PROM_MAGIC) {
+	prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF);
+	} else {
+		prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF;
+	}
+	prom_printf("Launching kernel...\n");
+#endif
+
+	k_start = (unsigned long) (&kernel_entry) & 0xffff0000;
+
+#ifdef RELOC
+	/*
+	 * Now copy kernel image to it's destination.
+	 */
+	len = ((unsigned long) (&_end) - k_start);
+	memcpy((void *)k_start, &_ftext, len);
+#endif
+
+	if (magic == REX_PROM_MAGIC) {
+		rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE);
+		rex_clear_cache();
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	LOADER_TYPE = 1;
+	INITRD_START = (long)&__rd_start;
+	INITRD_SIZE = (long)&__rd_end - (long)&__rd_start;
+#endif
+
+	kernel_entry(argc, argv, magic, prom_vec);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/boot/ld.ecoff linux.pre11.3/arch/mips/dec/boot/ld.ecoff
--- linux.vanilla/arch/mips/dec/boot/ld.ecoff	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/boot/ld.ecoff	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,43 @@
+OUTPUT_FORMAT("ecoff-littlemips")
+OUTPUT_ARCH(mips)
+ENTRY(dec_entry)
+SECTIONS
+{
+  . = 0x80200000;
+
+  .text :
+  {
+    _ftext = .;
+    *(.text)
+    *(.fixup)
+  }
+  .rdata :
+  {
+    *(.rodata .rdata)
+  }
+  .data :
+  {
+    . = ALIGN(0x1000);
+    ramdisk.img (.data)
+    *(.data)
+  }
+  .sdata :
+  {
+    *(.sdata)
+  }
+  _gp = .;
+  .sbss :
+  {
+    *(.sbss)
+    *(.scommon)
+  }
+  .bss :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  /DISCARD/ : {
+    *(.reginfo .mdebug .note)
+  }
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/int-handler.S linux.pre11.3/arch/mips/dec/int-handler.S
--- linux.vanilla/arch/mips/dec/int-handler.S	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/dec/int-handler.S	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,362 @@
+/*
+ * arch/mips/dec/int-handler.S
+ *
+ * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
+ *
+ * Written by Ralf Baechle and Andreas Busse, modified for DECStation
+ * support by Paul Antoine and Harald Koerfgen.
+ *
+ * completly rewritten:
+ * Copyright (C) 1998 Harald Koerfgen
+ *
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/stackframe.h>
+#include <asm/addrspace.h>
+
+#include <asm/dec/interrupts.h>
+
+
+		.text
+		.set	noreorder
+/*
+ * decstation_handle_int: Interrupt handler for DECStations
+ *
+ * FIXME: Detection of spurious interrupts not yet implemented!
+ *
+ * We follow the model in the Indy interrupt code by David Miller, where he
+ * says: a lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop
+ *    and moving across all the pending IRQ bits in the cause
+ *    register is _NOT_ the answer, the common case is one
+ *    pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register
+ *    IRQ mask, that would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs
+ *    off, nothing in between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the DECStations look basically (barring
+ * software IRQs which we don't use at all) like...
+ *
+ * DS2100/3100's, aka kn01, aka Pmax:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        SCSI
+ *             3        Lance Ethernet
+ *             4        DZ11 serial
+ *             5        RTC
+ *             6        Memory Controller
+ *             7        FPU
+ *
+ * DS5000/200, aka kn02, aka 3max:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        TurboChannel
+ *             3        RTC
+ *             4        Reserved
+ *             5        Memory Controller
+ *             6        Reserved
+ *             7        FPU
+ *
+ * DS5000/1xx's, aka kn02ba, aka 3min:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        TurboChannel Slot 0
+ *             3        TurboChannel Slot 1
+ *             4        TurboChannel Slot 2
+ *             5        TurboChannel Slot 3 (ASIC)
+ *             6        Halt button
+ *             7        FPU
+ *
+ * DS5000/2x's, aka kn02ca, aka maxine:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Periodic Interrupt (100usec)
+ *             3        RTC
+ *             4        I/O write timeout
+ *             5        TurboChannel (ASIC)
+ *             6        Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
+ *             7        FPU
+ *
+ * DS5000/2xx's, aka kn03, aka 3maxplus:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        System Board (ASIC)
+ *             3        RTC
+ *             4        Reserved
+ *             5        Memory
+ *             6        Halt Button
+ *             7        FPU
+ *
+ * We handle the IRQ according to _our_ priority.
+ * Priority is:
+ *
+ * Highest ----     RTC
+ *                  SCSI (if separate from TC)
+ *                  Ethernet (if separate from TC)
+ *		    Serial (if separate from TC)
+ *                  TurboChannel (if there is one!)
+ *                  Memory Controller (execept kmin)
+ * Lowest  ----     Halt (if there is one!)
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ *
+ */
+		.align	5
+		NESTED(decstation_handle_int, PT_SIZE, ra)
+		.set	noat
+		SAVE_ALL
+		CLI				# TEST: interrupts should be off
+		.set	at
+		.set	noreorder
+
+		/*
+		 * Get pending Interrupts
+		 */
+		mfc0	t0,CP0_CAUSE		# get pending interrupts
+		mfc0	t2,CP0_STATUS
+		la	t1,cpu_mask_tbl
+		and	t0,t2			# isolate allowed ones
+
+		/* insert detection of spurious interrupts here */
+
+		/*
+		 * Find irq with highest priority
+		 */
+1:		lw	t2,(t1)
+		move	t3,t0
+		and	t3,t2
+		beq	t3,zero,1b
+		 addu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+		lw	a0,%lo(cpu_irq_nr-cpu_mask_tbl-PTRSIZE)(t1)
+		lw	t0,%lo(cpu_ivec_tbl-cpu_mask_tbl-PTRSIZE)(t1)
+		bgez	a0, handle_it		# irq_nr >= 0?
+						# irq_nr < 0: a0 contains an address
+		nop
+		jr	t0
+		 nop				# delay slot
+
+/*
+ * Handle "IRQ Controller" Interrupts
+ * Masked Interrupts are still visible and have to be masked "by hand".
+ * %hi(KN02_CSR_ADDR) does not work so all addresses are hardcoded :-(.
+ */
+		EXPORT(kn02_io_int)
+kn02_io_int:	lui	t0,0xbff0		# get interrupt status and mask
+		lw	t0,(t0)
+		la	t1,asic_mask_tbl
+		move	t3,t0
+		sll	t3,16			# shift interrupt status
+		b	find_int
+		 and	t0,t3			# mask out allowed ones
+
+		EXPORT(kn03_io_int)
+kn03_io_int:	lui	t2,0xbf84		# upper part of IOASIC Address
+		lw	t0,0x0110(t2)		# get status: IOASIC isr
+		lw	t3,0x0120(t2)		# get mask:   IOASIC isrm
+		la	t1,asic_mask_tbl
+		b	find_int
+		 and	t0,t3			# mask out allowed ones
+
+		EXPORT(kn02ba_io_int)
+kn02ba_io_int:	lui	t2,0xbc04		
+		lw	t0,0x0110(t2)		# IOASIC isr, works for maxine also
+		lw	t3,0x0120(t2)		# IOASIC isrm
+		la	t1,asic_mask_tbl
+		and	t0,t3
+
+		/*
+		 * Find irq with highest priority
+		 */
+find_int:	lw	t2,(t1)
+		move	t3,t0
+		and	t3,t2
+		beq	zero,t3,find_int
+		 addu	t1,PTRSIZE		# delay slot
+
+		/*
+		 * Do the low-level stuff
+		 */
+		lw	a0,%lo(asic_irq_nr-asic_mask_tbl-PTRSIZE)(t1)
+                nop
+
+handle_it:	jal	do_IRQ
+		 move	a1,sp
+		j	ret_from_irq
+		 nop
+		
+		END(decstation_handle_int)
+/*
+  * Interrupt routines common to all DECStations first.
+ */
+		EXPORT(dec_intr_fpu)
+dec_intr_fpu:	PANIC("Unimplemented FPU interrupt handler")
+
+/*
+ * Halt interrupt
+ */
+		EXPORT(intr_halt)
+intr_halt:	la	k0,0xbc000000
+		jr	k0
+		 nop
+
+/*
+ * Generic unimplemented interrupt routines - ivec_tbl is initialised to
+ * point all interrupts here.  The table is then filled in by machine-specific
+ * initialisation in dec_setup().
+ */
+		EXPORT(dec_intr_unimplemented)
+dec_intr_unimplemented:
+		mfc0	a1,CP0_CAUSE		# cheats way of printing an arg!
+		nop				# to be sure...
+		PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%x");
+
+		EXPORT(asic_intr_unimplemented)
+asic_intr_unimplemented:
+		move	a1,t0			# cheats way of printing an arg!
+		PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%x");
+
+/*
+ * FIXME: This interrupt vector table is experimental.  It is initialised with 
+ *	  *_intr_unimplemented and filled in with the addresses of
+ *	  machine-specific interrupt routines in dec_setup()  Paul 10/5/97.
+ *
+ *	  The mask_tbls contain the interrupt masks which are used. It is 
+ *	  initialised with all possible interrupt status bits set, so that 
+ * 	  unused Interrupts are catched.				Harald
+ */
+		.data
+		EXPORT(cpu_mask_tbl)
+cpu_mask_tbl:
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000		# these two are unlikely 
+		.word	0x00000000		# to be used
+		.word	0x0000ff00		# End of list
+
+		EXPORT(cpu_irq_nr)
+cpu_irq_nr:
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000
+		.word	0x00000000		# these two are unlikely 
+		.word	0x00000000		# to be used
+		.word	0x00ffffff		# End of list
+
+		EXPORT(cpu_ivec_tbl)
+cpu_ivec_tbl:
+		PTR	dec_intr_unimplemented
+		PTR	dec_intr_unimplemented
+		PTR	dec_intr_unimplemented
+		PTR	dec_intr_unimplemented
+		PTR	dec_intr_unimplemented
+		PTR	dec_intr_unimplemented
+		PTR	dec_intr_unimplemented	# these two are unlikely
+		PTR	dec_intr_unimplemented	# to be used
+		PTR	dec_intr_unimplemented	# EOL
+
+		EXPORT(asic_mask_tbl)
+asic_mask_tbl:
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0xffffffff			# EOL
+
+		EXPORT(asic_irq_nr)
+asic_irq_nr:
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0
+		.word	0xffffffff		# EOL
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/irq.c linux.pre11.3/arch/mips/dec/irq.c
--- linux.vanilla/arch/mips/dec/irq.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/irq.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,269 @@
+/*
+ * Code to handle DECstation IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle
+ *
+ * $Id: irq.c,v 1.3 1999/04/11 17:06:16 harald Exp $
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <asm/dec/interrupts.h>
+
+extern volatile unsigned int *isr;	/* address of the interrupt status register     */
+extern volatile unsigned int *imr;	/* address of the interrupt mask register       */
+extern decint_t dec_interrupt[NR_INTS];
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+
+static inline void mask_irq(unsigned int irq_nr)
+{
+    unsigned int dummy;
+
+    if (dec_interrupt[irq_nr].iemask) {		/* This is an ASIC interrupt    */
+	*imr &= ~dec_interrupt[irq_nr].iemask;
+	dummy = *imr;
+	dummy = *imr;
+    } else			/* This is a cpu interrupt        */
+	set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) & ~dec_interrupt[irq_nr].cpu_mask);
+}
+
+static inline void unmask_irq(unsigned int irq_nr)
+{
+    unsigned int dummy;
+
+    if (dec_interrupt[irq_nr].iemask) {		/* This is an ASIC interrupt    */
+	*imr |= dec_interrupt[irq_nr].iemask;
+	dummy = *imr;
+	dummy = *imr;
+    }
+    set_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) | dec_interrupt[irq_nr].cpu_mask);
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+    unsigned long flags;
+
+    save_and_cli(flags);
+    mask_irq(irq_nr);
+    restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+    unsigned long flags;
+
+    save_and_cli(flags);
+    unmask_irq(irq_nr);
+    restore_flags(flags);
+}
+
+/*
+ * Pointers to the low-level handlers: first the general ones, then the
+ * fast ones, then the bad ones.
+ */
+extern void interrupt(void);
+
+static struct irqaction *irq_action[32] =
+{
+    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
+};
+
+int get_irq_list(char *buf)
+{
+    int i, len = 0;
+    struct irqaction *action;
+
+    for (i = 0; i < 32; i++) {
+	action = irq_action[i];
+	if (!action)
+	    continue;
+	len += sprintf(buf + len, "%2d: %8d %c %s",
+		       i, kstat.irqs[0][i],
+		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
+		       action->name);
+	for (action = action->next; action; action = action->next) {
+	    len += sprintf(buf + len, ",%s %s",
+			   (action->flags & SA_INTERRUPT) ? " +" : "",
+			   action->name);
+	}
+	len += sprintf(buf + len, "\n");
+    }
+    return len;
+}
+
+atomic_t __mips_bh_counter;
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts enabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
+ */
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
+{
+    struct irqaction *action;
+    int do_random, cpu;
+
+    cpu = smp_processor_id();
+    hardirq_enter(cpu);
+    kstat.irqs[cpu][irq]++;
+
+    mask_irq(irq);
+    action = *(irq + irq_action);
+    if (action) {
+	if (!(action->flags & SA_INTERRUPT))
+	    __sti();
+	action = *(irq + irq_action);
+	do_random = 0;
+	do {
+	    do_random |= action->flags;
+	    action->handler(irq, action->dev_id, regs);
+	    action = action->next;
+	} while (action);
+	if (do_random & SA_SAMPLE_RANDOM)
+	    add_interrupt_randomness(irq);
+	unmask_irq(irq);
+	__cli();
+    }
+    hardirq_exit(cpu);
+
+    /* unmasking and bottom half handling is done magically for us. */
+}
+
+/*
+ * Idea is to put all interrupts
+ * in a single table and differenciate them just by number.
+ */
+int setup_dec_irq(int irq, struct irqaction *new)
+{
+    int shared = 0;
+    struct irqaction *old, **p;
+    unsigned long flags;
+
+    p = irq_action + irq;
+    if ((old = *p) != NULL) {
+	/* Can't share interrupts unless both agree to */
+	if (!(old->flags & new->flags & SA_SHIRQ))
+	    return -EBUSY;
+
+	/* Can't share interrupts unless both are same type */
+	if ((old->flags ^ new->flags) & SA_INTERRUPT)
+	    return -EBUSY;
+
+	/* add new interrupt at end of irq queue */
+	do {
+	    p = &old->next;
+	    old = *p;
+	} while (old);
+	shared = 1;
+    }
+    if (new->flags & SA_SAMPLE_RANDOM)
+	rand_initialize_irq(irq);
+
+    save_and_cli(flags);
+    *p = new;
+
+    if (!shared) {
+	unmask_irq(irq);
+    }
+    restore_flags(flags);
+    return 0;
+}
+
+int request_irq(unsigned int irq,
+		void (*handler) (int, void *, struct pt_regs *),
+		unsigned long irqflags,
+		const char *devname,
+		void *dev_id)
+{
+    int retval;
+    struct irqaction *action;
+
+    if (irq >= 32)
+	return -EINVAL;
+    if (!handler)
+	return -EINVAL;
+
+    action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+    if (!action)
+	return -ENOMEM;
+
+    action->handler = handler;
+    action->flags = irqflags;
+    action->mask = 0;
+    action->name = devname;
+    action->next = NULL;
+    action->dev_id = dev_id;
+
+    retval = setup_dec_irq(irq, action);
+
+    if (retval)
+	kfree(action);
+    return retval;
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+    struct irqaction *action, **p;
+    unsigned long flags;
+
+    if (irq > 39) {
+	printk("Trying to free IRQ%d\n", irq);
+	return;
+    }
+    for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+	if (action->dev_id != dev_id)
+	    continue;
+
+	/* Found it - now free it */
+	save_and_cli(flags);
+	*p = action->next;
+	if (!irq[irq_action])
+	    mask_irq(irq);
+	restore_flags(flags);
+	kfree(action);
+	return;
+    }
+    printk("Trying to free free IRQ%d\n", irq);
+}
+
+unsigned long probe_irq_on(void)
+{
+    /* TODO */
+    return 0;
+}
+
+int probe_irq_off(unsigned long irqs)
+{
+    /* TODO */
+    return 0;
+}
+
+__initfunc(void init_IRQ(void))
+{
+    irq_setup();
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/Makefile linux.pre11.3/arch/mips/dec/prom/Makefile
--- linux.vanilla/arch/mips/dec/prom/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/Makefile	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,29 @@
+# $Id: $
+# Makefile for the DECstation prom monitor library routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+OBJS  = init.o memory.o cmdline.o identify.o locore.o
+
+all: 	rexlib.a
+
+rexlib.a: $(OBJS)
+	$(AR) rcs rexlib.a $(OBJS)
+	sync
+
+locore.o: locore.S
+
+dep:
+	$(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/cmdline.c linux.pre11.3/arch/mips/dec/prom/cmdline.c
--- linux.vanilla/arch/mips/dec/prom/cmdline.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/cmdline.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,46 @@
+/*
+ * cmdline.c: read the command line passed to us by the PROM.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ *
+ * $Id: $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#include "prom.h"
+
+#undef PROM_DEBUG
+
+#ifdef PROM_DEBUG
+extern int (*prom_printf)(char *, ...);
+#endif
+
+char arcs_cmdline[CL_SIZE];
+
+__initfunc(void prom_init_cmdline(int argc, char **argv, unsigned long magic))
+{
+	int start_arg, i;
+
+	/*
+	 * collect args and prepare cmd_line
+	 */
+	if (magic != REX_PROM_MAGIC)
+		start_arg = 1;
+	else
+		start_arg = 2;
+	for (i = start_arg; i < argc; i++) {
+		strcat(arcs_cmdline, argv[i]);
+		if (i < (argc - 1))
+			strcat(arcs_cmdline, " ");
+	}
+
+#ifdef PROM_DEBUG
+	prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
+#endif
+
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/dectypes.h linux.pre11.3/arch/mips/dec/prom/dectypes.h
--- linux.vanilla/arch/mips/dec/prom/dectypes.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/dectypes.h	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,14 @@
+#ifndef DECTYPES
+#define	DECTYPES
+
+#define DS2100_3100	1	/* DS2100/3100	Pmax		*/
+#define DS5000_200	2	/* DS5000/200	3max		*/
+#define DS5000_1XX	3	/* DS5000/1xx	kmin		*/
+#define DS5000_2X0	4	/* DS5000/2x0	3max+		*/
+#define DS5800		5	/* DS5800	Isis		*/
+#define DS5400		6	/* DS5400	MIPSfair	*/
+#define DS5000_XX	7	/* DS5000/xx	maxine		*/
+#define DS5500		11	/* DS5500	MIPSfair-2	*/
+#define DS5100		12	/* DS5100	MIPSmate	*/
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/identify.c linux.pre11.3/arch/mips/dec/prom/identify.c
--- linux.vanilla/arch/mips/dec/prom/identify.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/identify.c	Mon Jul 19 23:53:54 1999
@@ -0,0 +1,98 @@
+/*
+ * identify.c: machine identification code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
+ *
+ * $Id: $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#include "dectypes.h"
+#include "prom.h"
+
+extern char *(*prom_getenv)(char *);
+extern int (*prom_printf)(char *, ...);
+extern int (*rex_getsysid)(void);
+
+extern unsigned long mips_machgroup;
+extern unsigned long mips_machtype;
+
+__initfunc(void prom_identify_arch (unsigned int magic))
+{
+	unsigned char dec_cpunum, dec_firmrev, dec_etc;
+	int dec_systype;
+	unsigned long dec_sysid;
+
+	if (magic != REX_PROM_MAGIC) {
+		dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0);
+	} else {
+		dec_sysid = rex_getsysid();
+		if (dec_sysid == 0) {
+			prom_printf("Zero sysid returned from PROMs! Assuming PMAX-like machine.\n");
+			dec_sysid = 1;
+		}
+	}
+
+	dec_cpunum = (dec_sysid & 0xff000000) >> 24;
+	dec_systype = (dec_sysid & 0xff0000) >> 16;
+	dec_firmrev = (dec_sysid & 0xff00) >> 8;
+	dec_etc = dec_sysid & 0xff;
+
+	/* We're obviously one of the DEC machines */
+	mips_machgroup = MACH_GROUP_DEC;
+
+	/*
+	 * FIXME: This may not be an exhaustive list of DECStations/Servers!
+	 * Put all model-specific initialisation calls here.
+	 */
+	prom_printf("This DECstation is a ");
+
+	switch (dec_systype) {
+	case DS2100_3100:
+		prom_printf("DS2100/3100\n");
+		mips_machtype = MACH_DS23100;
+		break;
+	case DS5100:		/* DS5100 MIPSMATE */
+		prom_printf("DS5100\n");
+		mips_machtype = MACH_DS5100;
+		break;
+	case DS5000_200:	/* DS5000 3max */
+		prom_printf("DS5000/200\n");
+		mips_machtype = MACH_DS5000_200;
+		break;
+	case DS5000_1XX:	/* DS5000/100 3min */
+		prom_printf("DS5000/1xx\n");
+		mips_machtype = MACH_DS5000_1XX;
+		break;
+	case DS5000_2X0:	/* DS5000/240 3max+ */
+		prom_printf("DS5000/2x0\n");
+		mips_machtype = MACH_DS5000_2X0;
+		break;
+	case DS5000_XX:	/* Personal DS5000/2x */
+		prom_printf("Personal DS5000/xx\n");
+		mips_machtype = MACH_DS5000_XX;
+		break;
+	case DS5800:		/* DS5800 Isis */
+		prom_printf("DS5800\n");
+		mips_machtype = MACH_DS5800;
+		break;
+	case DS5400:		/* DS5400 MIPSfair */
+		prom_printf("DS5400\n");
+		mips_machtype = MACH_DS5400;
+		break;
+	case DS5500:		/* DS5500 MIPSfair-2 */
+		prom_printf("DS5500\n");
+		mips_machtype = MACH_DS5500;
+		break;
+	default:
+		prom_printf("unknown, id is %x", dec_systype);
+		mips_machtype = MACH_DSUNKNOWN;
+		break;
+	}
+}
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/init.c linux.pre11.3/arch/mips/dec/prom/init.c
--- linux.vanilla/arch/mips/dec/prom/init.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/init.c	Mon Jul 19 23:53:55 1999
@@ -0,0 +1,95 @@
+/*
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ *
+ * $Id: $
+ */
+#include <linux/init.h>
+#include "prom.h"
+
+/*
+ * PROM Interface (whichprom.c)
+ */
+typedef struct {
+	int pagesize;
+	unsigned char bitmap[0];
+} memmap;
+
+int (*rex_bootinit)(void);
+int (*rex_bootread)(void);
+int (*rex_getbitmap)(memmap *);
+unsigned long *(*rex_slot_address)(int);
+void *(*rex_gettcinfo)(void);
+int (*rex_getsysid)(void);
+void (*rex_clear_cache)(void);
+
+int (*prom_getchar)(void);
+char *(*prom_getenv)(char *);
+int (*prom_printf)(char *, ...);
+
+int (*pmax_open)(char*, int);
+int (*pmax_lseek)(int, long, int);
+int (*pmax_read)(int, void *, int);
+int (*pmax_close)(int);
+
+extern void prom_meminit(unsigned int);
+extern void prom_identify_arch(unsigned int);
+extern void prom_init_cmdline(int, char **, unsigned long);
+
+/*
+ * Detect which PROM's the DECSTATION has, and set the callback vectors
+ * appropriately.
+ */
+__initfunc(void which_prom(unsigned long magic, int *prom_vec))
+{
+	/*
+	 * No sign of the REX PROM's magic number means we assume a non-REX
+	 * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx)
+	 */
+	if (magic == REX_PROM_MAGIC)
+	{
+		/*
+		 * Set up prom abstraction structure with REX entry points.
+		 */
+		rex_bootinit = (int (*)(void)) *(prom_vec + REX_PROM_BOOTINIT);
+		rex_bootread = (int (*)(void)) *(prom_vec + REX_PROM_BOOTREAD);
+		rex_getbitmap = (int (*)(memmap *)) *(prom_vec + REX_PROM_GETBITMAP);
+		prom_getchar = (int (*)(void)) *(prom_vec + REX_PROM_GETCHAR);
+		prom_getenv = (char *(*)(char *)) *(prom_vec + REX_PROM_GETENV);
+		rex_getsysid = (int (*)(void)) *(prom_vec + REX_PROM_GETSYSID);
+		rex_gettcinfo = (void *(*)(void)) *(prom_vec + REX_PROM_GETTCINFO);
+		prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF);
+		rex_slot_address = (unsigned long *(*)(int)) *(prom_vec + REX_PROM_SLOTADDR);
+		rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE);
+	}
+	else
+	{
+		/*
+		 * Set up prom abstraction structure with non-REX entry points.
+		 */
+		prom_getchar = (int (*)(void)) PMAX_PROM_GETCHAR;
+		prom_getenv = (char *(*)(char *)) PMAX_PROM_GETENV;
+		prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF;
+		pmax_open = (int (*)(char *, int)) PMAX_PROM_OPEN;
+		pmax_lseek = (int (*)(int, long, int)) PMAX_PROM_LSEEK;
+		pmax_read = (int (*)(int, void *, int)) PMAX_PROM_READ;
+		pmax_close = (int (*)(int)) PMAX_PROM_CLOSE;
+	}
+} 
+
+__initfunc(int prom_init(int argc, char **argv,
+	       unsigned long magic, int *prom_vec))
+{
+	/* Determine which PROM's we have (and therefore which machine we're on!) */
+	which_prom(magic, prom_vec);
+
+	if (magic == REX_PROM_MAGIC)
+		rex_clear_cache();
+
+	prom_meminit(magic);
+	prom_identify_arch(magic);
+	prom_init_cmdline(argc, argv, magic);
+
+	return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/locore.S linux.pre11.3/arch/mips/dec/prom/locore.S
--- linux.vanilla/arch/mips/dec/prom/locore.S	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/locore.S	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,30 @@
+/*
+ * locore.S
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+	.text
+
+/*
+ * Simple general exception handling routine. This one is used for the
+ * Memory sizing routine for pmax machines. HK
+ */
+
+NESTED(genexcept_early, 0, sp)
+	.set	noat
+	.set	noreorder
+
+	mfc0	k0, CP0_STATUS
+	la	k1, mem_err
+
+	sw	k0,0(k1)
+
+	mfc0	k0, CP0_EPC
+	nop
+	addiu	k0,4		# skip the causing instruction
+	jr	k0
+	 rfe
+END(genexcept_early)
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/memory.c linux.pre11.3/arch/mips/dec/prom/memory.c
--- linux.vanilla/arch/mips/dec/prom/memory.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/memory.c	Mon Jul 19 23:53:55 1999
@@ -0,0 +1,103 @@
+/*
+ * memory.c: memory initialisation code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
+ *
+ * $Id: $
+ */
+#include <asm/addrspace.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include "prom.h"
+
+typedef struct {
+	int pagesize;
+	unsigned char bitmap[0];
+} memmap;
+
+extern int (*rex_getbitmap)(memmap *);
+
+#undef PROM_DEBUG
+
+#ifdef PROM_DEBUG
+extern int (*prom_printf)(char *, ...);
+#endif
+
+extern unsigned long mips_memory_upper;
+
+volatile unsigned long mem_err = 0;	/* So we know an error occured */
+
+/*
+ * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
+ * off the end of real memory.  Only suitable for the 2100/3100's (PMAX).
+ */
+
+#define CHUNK_SIZE 0x400000
+
+__initfunc(unsigned long pmax_get_memory_size(void))
+{
+	volatile unsigned char *memory_page, dummy;
+	char	old_handler[0x80];
+	extern char genexcept_early;
+
+	/* Install exception handler */
+	memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80);
+	memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80);
+
+	/* read unmapped and uncached (KSEG1)
+	 * DECstations have at least 4MB RAM
+	 * Assume less than 480MB of RAM, as this is max for 5000/2xx
+	 * FIXME this should be replaced by the first free page!
+	 */
+	for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE;
+	     (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000));
+  	     memory_page += CHUNK_SIZE) {
+		dummy = *memory_page;
+	}
+	memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80);
+	return (unsigned long)memory_page - KSEG1 - CHUNK_SIZE;
+}
+
+/*
+ * Use the REX prom calls to get hold of the memory bitmap, and thence
+ * determine memory size.
+ */
+__initfunc(unsigned long rex_get_memory_size(void))
+{
+	int i, bitmap_size;
+	unsigned long mem_size = 0;
+	memmap *bm;
+
+	/* some free 64k */
+	bm = (memmap *) 0x80028000;
+
+	bitmap_size = rex_getbitmap(bm);
+
+	for (i = 0; i < bitmap_size; i++) {
+		/* FIXME: very simplistically only add full sets of pages */
+		if (bm->bitmap[i] == 0xff)
+			mem_size += (8 * bm->pagesize);
+	}
+	return (mem_size);
+}
+
+__initfunc(void prom_meminit(unsigned int magic))
+{
+	if (magic != REX_PROM_MAGIC)
+		mips_memory_upper = KSEG0 + pmax_get_memory_size();
+	else
+		mips_memory_upper = KSEG0 + rex_get_memory_size();
+
+#ifdef PROM_DEBUG
+	prom_printf("mips_memory_upper: 0x%08x\n", mips_memory_upper);
+#endif
+}
+
+/* Called from mem_init() to fixup the mem_map page settings. */
+__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end))
+{
+}
+
+void prom_free_prom_memory (void)
+{
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/prom/prom.h linux.pre11.3/arch/mips/dec/prom/prom.h
--- linux.vanilla/arch/mips/dec/prom/prom.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/prom/prom.h	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,51 @@
+/*  
+ * Miscellaneous definitions used to call the routines contained in the boot
+ * PROMs on various models of DECSTATION's.
+ * the rights to redistribute these changes.
+ */
+
+#ifndef __ASM_DEC_PROM_H 
+#define __ASM_DEC_PROM_H 
+
+/*
+ * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's.  Many of
+ * these will work for MIPSen as well!
+ */
+#define VEC_RESET		0xBFC00000		/* Prom base address */
+#define	PMAX_PROM_ENTRY(x)	(VEC_RESET+((x)*8))	/* Prom jump table */
+
+#define	PMAX_PROM_HALT		PMAX_PROM_ENTRY(2)	/* valid on MIPSen */
+#define	PMAX_PROM_AUTOBOOT	PMAX_PROM_ENTRY(5)	/* valid on MIPSen */
+#define	PMAX_PROM_OPEN		PMAX_PROM_ENTRY(6)
+#define	PMAX_PROM_READ		PMAX_PROM_ENTRY(7)
+#define	PMAX_PROM_CLOSE		PMAX_PROM_ENTRY(10)
+#define	PMAX_PROM_LSEEK		PMAX_PROM_ENTRY(11)
+#define PMAX_PROM_GETCHAR       PMAX_PROM_ENTRY(12)
+#define	PMAX_PROM_PUTCHAR	PMAX_PROM_ENTRY(13)	/* 12 on MIPSen */
+#define	PMAX_PROM_GETS		PMAX_PROM_ENTRY(15)
+#define	PMAX_PROM_PRINTF	PMAX_PROM_ENTRY(17)
+#define	PMAX_PROM_GETENV	PMAX_PROM_ENTRY(33)	/* valid on MIPSen */
+
+/*
+ * Magic number indicating REX PROM available on DECSTATION.  Found in
+ * register a2 on transfer of control to program from PROM.
+ */
+#define	REX_PROM_MAGIC		0x30464354
+
+/*
+ * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's, and
+ * DS5000/2x0.
+ */
+#define REX_PROM_GETBITMAP	0x84/4	/* get mem bitmap */
+#define REX_PROM_GETCHAR	0x24/4	/* getch() */
+#define REX_PROM_GETENV		0x64/4	/* get env. variable */
+#define REX_PROM_GETSYSID	0x80/4	/* get system id */
+#define REX_PROM_GETTCINFO	0xa4/4
+#define REX_PROM_PRINTF		0x30/4	/* printf() */
+#define REX_PROM_SLOTADDR	0x6c/4	/* slotaddr */
+#define REX_PROM_BOOTINIT	0x54/4	/* open() */
+#define REX_PROM_BOOTREAD	0x58/4	/* read() */
+#define REX_PROM_CLEARCACHE	0x7c/4
+
+#endif /* __ASM_DEC_PROM_H */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/promcon.c linux.pre11.3/arch/mips/dec/promcon.c
--- linux.vanilla/arch/mips/dec/promcon.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/promcon.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,71 @@
+/*
+ * Wrap-around code for a console using the
+ * DECstation PROM io-routines.
+ *
+ * Copyright (c) 1998 Harald Koerfgen 
+ */
+
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+
+extern int (*prom_getchar) (void);
+extern int (*prom_printf) (char *,...);
+
+static void prom_console_write(struct console *co, const char *s,
+			       unsigned count)
+{
+    unsigned i;
+
+    /*
+     *    Now, do each character
+     */
+    for (i = 0; i < count; i++) {
+	if (*s == 10)
+	    prom_printf("%c", 13);
+	prom_printf("%c", *s++);
+    }
+}
+
+static int prom_console_wait_key(struct console *co)
+{
+    return prom_getchar();
+}
+
+__initfunc(static int prom_console_setup(struct console *co, char *options))
+{
+    return 0;
+}
+
+static kdev_t prom_console_device(struct console *c)
+{
+    return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console sercons =
+{
+    "ttyS",
+    prom_console_write,
+    NULL,
+    prom_console_device,
+    prom_console_wait_key,
+    NULL,
+    prom_console_setup,
+    CON_PRINTBUFFER,
+    -1,
+    0,
+    NULL
+};
+
+/*
+ *    Register console.
+ */
+
+__initfunc(long prom_console_init(long kmem_start, long kmem_end))
+{
+    register_console(&sercons);
+    return kmem_start;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/reset.c linux.pre11.3/arch/mips/dec/reset.c
--- linux.vanilla/arch/mips/dec/reset.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/dec/reset.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,25 @@
+/*
+ *  $Id: reset.c,v 1.4 1999/04/11 17:06:16 harald Exp $
+ *
+ *  Reset a DECstation machine.
+ *
+ */
+
+void (*back_to_prom)(void) = (void (*)(void))0xBFC00000;
+
+void dec_machine_restart(char *command)
+{
+	back_to_prom();
+}
+
+void dec_machine_halt(void)
+{
+	back_to_prom();
+}
+
+void dec_machine_power_off(void)
+{
+    /* DECstations don't have a software power switch */
+	back_to_prom();
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/rtc-dec.c linux.pre11.3/arch/mips/dec/rtc-dec.c
--- linux.vanilla/arch/mips/dec/rtc-dec.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/rtc-dec.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,36 @@
+
+/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $
+
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * RTC routines for DECstation style attached Dallas chip.
+ *
+ * Copyright (C) 1998 by Ralf Baechle, Harald Koerfgen
+ */
+#include <linux/mc146818rtc.h>
+
+extern char *dec_rtc_base;
+
+static unsigned char dec_rtc_read_data(unsigned long addr)
+{
+    return (dec_rtc_base[addr * 4]);
+}
+
+static void dec_rtc_write_data(unsigned char data, unsigned long addr)
+{
+    dec_rtc_base[addr * 4] = data;
+}
+
+static int dec_rtc_bcd_mode(void)
+{
+    return 0;
+}
+
+struct rtc_ops dec_rtc_ops =
+{
+    &dec_rtc_read_data,
+    &dec_rtc_write_data,
+    &dec_rtc_bcd_mode
+};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/serial.c linux.pre11.3/arch/mips/dec/serial.c
--- linux.vanilla/arch/mips/dec/serial.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/serial.c	Mon Jul 19 23:53:55 1999
@@ -0,0 +1,98 @@
+/*
+ * sercons.c
+ *      choose the right serial device at boot time
+ *
+ * triemer 6-SEP-1998
+ *      sercons.c is designed to allow the three different kinds 
+ *      of serial devices under the decstation world to co-exist
+ *      in the same kernel.  The idea here is to abstract 
+ *      the pieces of the drivers that are common to this file
+ *      so that they do not clash at compile time and runtime.
+ *
+ * HK 16-SEP-1998 v0.002
+ *      removed the PROM console as this is not a real serial
+ *      device. Added support for PROM console in drivers/char/tty_io.c
+ *      instead. Although it may work to enable more than one 
+ *      console device I strongly recommend to use only one.
+ */
+
+#include <linux/config.h>
+#include <asm/init.h>
+#include <asm/dec/machtype.h>
+
+#ifdef CONFIG_ZS
+extern int zs_init(void);
+#endif
+
+#ifdef CONFIG_DZ
+extern int dz_init(void);
+#endif
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+#ifdef CONFIG_ZS
+extern long zs_serial_console_init(long, long);
+#endif
+
+#ifdef CONFIG_DZ
+extern long dz_serial_console_init(long, long);
+#endif
+
+#endif
+
+/* rs_init - starts up the serial interface -
+   handle normal case of starting up the serial interface */
+
+#ifdef CONFIG_SERIAL
+
+__initfunc(int rs_init(void))
+{
+
+#if defined(CONFIG_ZS) && defined(CONFIG_DZ)
+    if (IOASIC)
+	return zs_init();
+    else
+	return dz_init();
+#else
+
+#ifdef CONFIG_ZS
+    return zs_init();
+#endif
+
+#ifdef CONFIG_DZ
+    return dz_init();
+#endif
+
+#endif
+}
+
+#endif
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/* serial_console_init handles the special case of starting
+ *   up the console on the serial port
+ */
+__initfunc(long serial_console_init(long kmem_start, long kmem_end))
+{
+#if defined(CONFIG_ZS) && defined(CONFIG_DZ)
+    if (IOASIC)
+	kmem_start = zs_serial_console_init(kmem_start, kmem_end);
+    else
+	kmem_start = dz_serial_console_init(kmem_start, kmem_end);
+#else
+
+#ifdef CONFIG_ZS
+    kmem_start = zs_serial_console_init(kmem_start, kmem_end);
+#endif
+
+#ifdef CONFIG_DZ
+    kmem_start = dz_serial_console_init(kmem_start, kmem_end);
+#endif
+
+#endif
+
+    return kmem_start;
+}
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/setup.c linux.pre11.3/arch/mips/dec/setup.c
--- linux.vanilla/arch/mips/dec/setup.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/dec/setup.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,503 @@
+/*
+ * Setup the interrupt stuff.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ */
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/param.h>
+#include <asm/mipsregs.h>
+#include <asm/bootinfo.h>
+#include <asm/init.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/kn02.h>
+#include <asm/dec/kn02xa.h>
+#include <asm/dec/kn03.h>
+#include <asm/dec/ioasic_ints.h>
+
+extern asmlinkage void decstation_handle_int(void);
+
+void dec_init_kn01(void);
+void dec_init_kn230(void);
+void dec_init_kn02(void);
+void dec_init_kn02ba(void);
+void dec_init_kn02ca(void);
+void dec_init_kn03(void);
+
+char *dec_rtc_base = (char *) KN01_RTC_BASE;	/* Assume DS2100/3100 initially */
+
+decint_t dec_interrupt[NR_INTS];
+
+/* 
+ * Information regarding the IRQ Controller
+ *
+ * isr and imr are also hardcoded for different machines in int_handler.S
+ */
+
+volatile unsigned int *isr = 0L;	/* address of the interrupt status register     */
+volatile unsigned int *imr = 0L;	/* address of the interrupt mask register       */
+
+extern void dec_machine_restart(char *command);
+extern void dec_machine_halt(void);
+extern void dec_machine_power_off(void);
+
+extern void wbflush_setup(void);
+
+extern struct rtc_ops dec_rtc_ops;
+
+extern void intr_halt(void);
+
+extern int setup_dec_irq(int, struct irqaction *);
+
+void (*board_time_init) (struct irqaction * irq);
+
+__initfunc(static void dec_irq_setup(void))
+{
+    switch (mips_machtype) {
+    case MACH_DS23100:
+	dec_init_kn01();
+	break;
+    case MACH_DS5100:		/*  DS5100 MIPSMATE */
+	dec_init_kn230();
+	break;
+    case MACH_DS5000_200:	/* DS5000 3max */
+	dec_init_kn02();
+	break;
+    case MACH_DS5000_1XX:	/* DS5000/100 3min */
+	dec_init_kn02ba();
+	break;
+    case MACH_DS5000_2X0:	/* DS5000/240 3max+ */
+	dec_init_kn03();
+	break;
+    case MACH_DS5000_XX:	/* Personal DS5000/2x */
+	dec_init_kn02ca();
+	break;
+    case MACH_DS5800:		/* DS5800 Isis */
+	panic("Don't know how to set this up!");
+	break;
+    case MACH_DS5400:		/* DS5400 MIPSfair */
+	panic("Don't know how to set this up!");
+	break;
+    case MACH_DS5500:		/* DS5500 MIPSfair-2 */
+	panic("Don't know how to set this up!");
+	break;
+    }
+    set_except_vector(0, decstation_handle_int);
+}
+
+/*
+ * enable the periodic interrupts
+ */
+__initfunc(static void dec_time_init(struct irqaction *irq))
+{
+    /*
+     * Here we go, enable periodic rtc interrupts.
+     */
+
+#ifndef LOG_2_HZ
+#  define LOG_2_HZ 7
+#endif
+
+    CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A);
+    CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
+    setup_dec_irq(CLOCK, irq);
+}
+
+__initfunc(void decstation_setup(void))
+{
+    irq_setup = dec_irq_setup;
+    board_time_init = dec_time_init;
+
+    wbflush_setup();
+
+    _machine_restart = dec_machine_restart;
+    _machine_halt = dec_machine_halt;
+    _machine_power_off = dec_machine_power_off;
+
+    rtc_ops = &dec_rtc_ops;
+}
+
+/*
+ * Machine-specific initialisation for kn01, aka Pmax, aka DS2100, DS3100,
+ * and possibly also the DS5100.
+ */
+__initfunc(void dec_init_kn01(void))
+{
+    /*
+     * Setup some memory addresses.
+     */
+    dec_rtc_base = (char *) KN01_RTC_BASE;
+
+    /*
+     * Setup interrupt structure
+     */
+    dec_interrupt[CLOCK].cpu_mask = IE_IRQ3;
+    dec_interrupt[CLOCK].iemask = 0;
+    cpu_mask_tbl[0] = IE_IRQ3;
+    cpu_irq_nr[0] = CLOCK;
+
+    dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0;
+    dec_interrupt[SCSI_INT].iemask = 0;
+    cpu_mask_tbl[1] = IE_IRQ0;
+    cpu_irq_nr[1] = SCSI_INT;
+
+    dec_interrupt[ETHER].cpu_mask = IE_IRQ1;
+    dec_interrupt[ETHER].iemask = 0;
+    cpu_mask_tbl[2] = IE_IRQ1;
+    cpu_irq_nr[2] = ETHER;
+
+    dec_interrupt[SERIAL].cpu_mask = IE_IRQ2;
+    dec_interrupt[SERIAL].iemask = 0;
+    cpu_mask_tbl[3] = IE_IRQ2;
+    cpu_irq_nr[3] = SERIAL;
+
+    dec_interrupt[MEMORY].cpu_mask = IE_IRQ4;
+    dec_interrupt[MEMORY].iemask = 0;
+    cpu_mask_tbl[4] = IE_IRQ4;
+    cpu_irq_nr[4] = MEMORY;
+
+    dec_interrupt[FPU].cpu_mask = IE_IRQ5;
+    dec_interrupt[FPU].iemask = 0;
+    cpu_mask_tbl[5] = IE_IRQ5;
+    cpu_irq_nr[5] = FPU;
+}				/* dec_init_kn01 */
+
+/*
+ * Machine-specific initialisation for kn230, aka MIPSmate, aka DS5100
+ *
+ * There are a lot of experiments to do, this is definitely incomplete.
+ */
+__initfunc(void dec_init_kn230(void))
+{
+    /*
+     * Setup some memory addresses.
+     */
+    dec_rtc_base = (char *) KN01_RTC_BASE;
+
+    /*
+     * Setup interrupt structure
+     */
+    dec_interrupt[CLOCK].cpu_mask = IE_IRQ2;
+    dec_interrupt[CLOCK].iemask = 0;
+    cpu_mask_tbl[0] = IE_IRQ2;
+    cpu_irq_nr[0] = CLOCK;
+
+    dec_interrupt[FPU].cpu_mask = IE_IRQ5;
+    dec_interrupt[FPU].iemask = 0;
+    cpu_mask_tbl[5] = IE_IRQ5;
+    cpu_irq_nr[5] = FPU;
+}				/* dec_init_kn230 */
+
+/*
+ * Machine-specific initialisation for kn02, aka 3max, aka DS5000/2xx.
+ */
+__initfunc(void dec_init_kn02(void))
+{
+    /*
+     * Setup some memory addresses. FIXME: probably incomplete!
+     */
+    dec_rtc_base = (char *) KN02_RTC_BASE;
+    isr = (volatile unsigned int *) KN02_CSR_ADDR;
+    imr = (volatile unsigned int *) KN02_CSR_ADDR;
+
+    /*
+     * Setup IOASIC interrupt
+     */
+    cpu_ivec_tbl[1] = kn02_io_int;
+    cpu_mask_tbl[1] = IE_IRQ0;
+    cpu_irq_nr[1] = -1;
+    *imr = *imr & 0xff00ff00;
+
+    /*
+     * Setup interrupt structure
+     */
+    dec_interrupt[CLOCK].cpu_mask = IE_IRQ1;
+    dec_interrupt[CLOCK].iemask = 0;
+    cpu_mask_tbl[0] = IE_IRQ1;
+    cpu_irq_nr[0] = CLOCK;
+
+    dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0;
+    dec_interrupt[SCSI_INT].iemask = KN02_SLOT5;
+    asic_mask_tbl[0] = KN02_SLOT5;
+    asic_irq_nr[0] = SCSI_INT;
+
+    dec_interrupt[ETHER].cpu_mask = IE_IRQ0;
+    dec_interrupt[ETHER].iemask = KN02_SLOT6;
+    asic_mask_tbl[1] = KN02_SLOT6;
+    asic_irq_nr[1] = ETHER;
+
+    dec_interrupt[SERIAL].cpu_mask = IE_IRQ0;
+    dec_interrupt[SERIAL].iemask = KN02_SLOT7;
+    asic_mask_tbl[2] = KN02_SLOT7;
+    asic_irq_nr[2] = SERIAL;
+
+    dec_interrupt[TC0].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC0].iemask = KN02_SLOT0;
+    asic_mask_tbl[3] = KN02_SLOT0;
+    asic_irq_nr[3] = TC0;
+
+    dec_interrupt[TC1].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC1].iemask = KN02_SLOT1;
+    asic_mask_tbl[4] = KN02_SLOT1;
+    asic_irq_nr[4] = TC1;
+
+    dec_interrupt[TC2].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC2].iemask = KN02_SLOT2;
+    asic_mask_tbl[5] = KN02_SLOT2;
+    asic_irq_nr[5] = TC2;
+
+    dec_interrupt[MEMORY].cpu_mask = IE_IRQ3;
+    dec_interrupt[MEMORY].iemask = 0;
+    cpu_mask_tbl[2] = IE_IRQ3;
+    cpu_irq_nr[2] = MEMORY;
+
+    dec_interrupt[FPU].cpu_mask = IE_IRQ5;
+    dec_interrupt[FPU].iemask = 0;
+    cpu_mask_tbl[3] = IE_IRQ5;
+    cpu_irq_nr[3] = FPU;
+
+}				/* dec_init_kn02 */
+
+/*
+ * Machine-specific initialisation for kn02ba, aka 3min, aka DS5000/1xx.
+ */
+__initfunc(void dec_init_kn02ba(void))
+{
+    /*
+     * Setup some memory addresses.
+     */
+    dec_rtc_base = (char *) KN02XA_RTC_BASE;
+    isr = (volatile unsigned int *) KN02XA_SIR_ADDR;
+    imr = (volatile unsigned int *) KN02XA_SIRM_ADDR;
+
+    /*
+     * Setup IOASIC interrupt
+     */
+    cpu_mask_tbl[0] = IE_IRQ3;
+    cpu_irq_nr[0] = -1;
+    cpu_ivec_tbl[0] = kn02ba_io_int;
+    *imr = 0;
+
+    /*
+     * Setup interrupt structure
+     */
+    dec_interrupt[CLOCK].cpu_mask = IE_IRQ3;
+    dec_interrupt[CLOCK].iemask = KMIN_CLOCK;
+    asic_mask_tbl[0] = KMIN_CLOCK;
+    asic_irq_nr[0] = CLOCK;
+
+    dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3;
+    dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS;
+    asic_mask_tbl[1] = SCSI_DMA_INTS;
+    asic_irq_nr[1] = SCSI_DMA_INT;
+
+    dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3;
+    dec_interrupt[SCSI_INT].iemask = SCSI_CHIP;
+    asic_mask_tbl[2] = SCSI_CHIP;
+    asic_irq_nr[2] = SCSI_INT;
+
+    dec_interrupt[ETHER].cpu_mask = IE_IRQ3;
+    dec_interrupt[ETHER].iemask = LANCE_INTS;
+    asic_mask_tbl[3] = LANCE_INTS;
+    asic_irq_nr[3] = ETHER;
+
+    dec_interrupt[SERIAL].cpu_mask = IE_IRQ3;
+    dec_interrupt[SERIAL].iemask = SERIAL_INTS;
+    asic_mask_tbl[4] = SERIAL_INTS;
+    asic_irq_nr[4] = SERIAL;
+
+    dec_interrupt[MEMORY].cpu_mask = IE_IRQ3;
+    dec_interrupt[MEMORY].iemask = KMIN_TIMEOUT;
+    asic_mask_tbl[5] = KMIN_TIMEOUT;
+    asic_irq_nr[5] = MEMORY;
+
+    dec_interrupt[TC0].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC0].iemask = 0;
+    cpu_mask_tbl[1] = IE_IRQ0;
+    cpu_irq_nr[1] = TC0;
+
+    dec_interrupt[TC1].cpu_mask = IE_IRQ1;
+    dec_interrupt[TC1].iemask = 0;
+    cpu_mask_tbl[2] = IE_IRQ1;
+    cpu_irq_nr[2] = TC1;
+
+    dec_interrupt[TC2].cpu_mask = IE_IRQ2;
+    dec_interrupt[TC2].iemask = 0;
+    cpu_mask_tbl[3] = IE_IRQ2;
+    cpu_irq_nr[3] = TC2;
+
+    dec_interrupt[HALT].cpu_mask = IE_IRQ4;
+    dec_interrupt[HALT].iemask = 0;
+    cpu_mask_tbl[4] = IE_IRQ4;
+    cpu_irq_nr[4] = HALT;
+
+    dec_interrupt[FPU].cpu_mask = IE_IRQ5;
+    dec_interrupt[FPU].iemask = 0;
+    cpu_mask_tbl[5] = IE_IRQ5;
+    cpu_irq_nr[5] = FPU;
+
+}				/* dec_init_kn02ba */
+
+/*
+ * Machine-specific initialisation for kn02ca, aka maxine, aka DS5000/2x.
+ */
+__initfunc(void dec_init_kn02ca(void))
+{
+    /*
+     * Setup some memory addresses. FIXME: probably incomplete!
+     */
+    dec_rtc_base = (char *) KN02XA_RTC_BASE;
+    isr = (volatile unsigned int *) KN02XA_SIR_ADDR;
+    imr = (volatile unsigned int *) KN02XA_SIRM_ADDR;
+
+    /*
+     * Setup IOASIC interrupt
+     */
+    cpu_ivec_tbl[1] = kn02ba_io_int;
+    cpu_irq_nr[1] = -1;
+    cpu_mask_tbl[1] = IE_IRQ3;
+    *imr = 0;
+
+    /*
+     * Setup interrupt structure
+     */
+    dec_interrupt[CLOCK].cpu_mask = IE_IRQ1;
+    dec_interrupt[CLOCK].iemask = 0;
+    cpu_mask_tbl[0] = IE_IRQ1;
+    cpu_irq_nr[0] = CLOCK;
+
+    dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3;
+    dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS;
+    asic_mask_tbl[0] = SCSI_DMA_INTS;
+    asic_irq_nr[0] = SCSI_DMA_INT;
+
+    dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3;
+    dec_interrupt[SCSI_INT].iemask = SCSI_CHIP;
+    asic_mask_tbl[1] = SCSI_CHIP;
+    asic_irq_nr[1] = SCSI_INT;
+
+    dec_interrupt[ETHER].cpu_mask = IE_IRQ3;
+    dec_interrupt[ETHER].iemask = LANCE_INTS;
+    asic_mask_tbl[2] = LANCE_INTS;
+    asic_irq_nr[2] = ETHER;
+
+    dec_interrupt[SERIAL].cpu_mask = IE_IRQ3;
+    dec_interrupt[SERIAL].iemask = XINE_SERIAL_INTS;
+    asic_mask_tbl[3] = XINE_SERIAL_INTS;
+    asic_irq_nr[3] = SERIAL;
+
+    dec_interrupt[TC0].cpu_mask = IE_IRQ3;
+    dec_interrupt[TC0].iemask = MAXINE_TC0;
+    asic_mask_tbl[4] = MAXINE_TC0;
+    asic_irq_nr[4] = TC0;
+
+    dec_interrupt[TC1].cpu_mask = IE_IRQ3;
+    dec_interrupt[TC1].iemask = MAXINE_TC1;
+    asic_mask_tbl[5] = MAXINE_TC1;
+    asic_irq_nr[5] = TC1;
+
+    dec_interrupt[MEMORY].cpu_mask = IE_IRQ2;
+    dec_interrupt[MEMORY].iemask = 0;
+    cpu_mask_tbl[2] = IE_IRQ2;
+    cpu_irq_nr[2] = MEMORY;
+
+    dec_interrupt[HALT].cpu_mask = IE_IRQ4;
+    dec_interrupt[HALT].iemask = 0;
+    cpu_mask_tbl[3] = IE_IRQ4;
+    cpu_irq_nr[3] = HALT;
+
+    dec_interrupt[FPU].cpu_mask = IE_IRQ5;
+    dec_interrupt[FPU].iemask = 0;
+    cpu_mask_tbl[4] = IE_IRQ5;
+    cpu_irq_nr[4] = FPU;
+
+}				/* dec_init_kn02ca */
+
+/*
+ * Machine-specific initialisation for kn03, aka 3max+, aka DS5000/240.
+ */
+__initfunc(void dec_init_kn03(void))
+{
+    /*
+     * Setup some memory addresses. FIXME: probably incomplete!
+     */
+    dec_rtc_base = (char *) KN03_RTC_BASE;
+    isr = (volatile unsigned int *) KN03_SIR_ADDR;
+    imr = (volatile unsigned int *) KN03_SIRM_ADDR;
+
+    /*
+     * Setup IOASIC interrupt
+     */
+    cpu_ivec_tbl[1] = kn03_io_int;
+    cpu_mask_tbl[1] = IE_IRQ0;
+    cpu_irq_nr[1] = -1;
+    *imr = 0;
+
+    /*
+     * Setup interrupt structure
+     */
+    dec_interrupt[CLOCK].cpu_mask = IE_IRQ1;
+    dec_interrupt[CLOCK].iemask = 0;
+    cpu_mask_tbl[0] = IE_IRQ1;
+    cpu_irq_nr[0] = CLOCK;
+
+    dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ0;
+    dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS;
+    asic_mask_tbl[0] = SCSI_DMA_INTS;
+    asic_irq_nr[0] = SCSI_DMA_INT;
+
+    dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0;
+    dec_interrupt[SCSI_INT].iemask = SCSI_CHIP;
+    asic_mask_tbl[1] = SCSI_CHIP;
+    asic_irq_nr[1] = SCSI_INT;
+
+    dec_interrupt[ETHER].cpu_mask = IE_IRQ0;
+    dec_interrupt[ETHER].iemask = LANCE_INTS;
+    asic_mask_tbl[2] = LANCE_INTS;
+    asic_irq_nr[2] = ETHER;
+
+    dec_interrupt[SERIAL].cpu_mask = IE_IRQ0;
+    dec_interrupt[SERIAL].iemask = SERIAL_INTS;
+    asic_mask_tbl[3] = SERIAL_INTS;
+    asic_irq_nr[3] = SERIAL;
+
+    dec_interrupt[TC0].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC0].iemask = KN03_TC0;
+    asic_mask_tbl[4] = KN03_TC0;
+    asic_irq_nr[4] = TC0;
+
+    dec_interrupt[TC1].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC1].iemask = KN03_TC1;
+    asic_mask_tbl[5] = KN03_TC1;
+    asic_irq_nr[5] = TC1;
+
+    dec_interrupt[TC2].cpu_mask = IE_IRQ0;
+    dec_interrupt[TC2].iemask = KN03_TC2;
+    asic_mask_tbl[6] = KN03_TC2;
+    asic_irq_nr[6] = TC2;
+
+    dec_interrupt[MEMORY].cpu_mask = IE_IRQ3;
+    dec_interrupt[MEMORY].iemask = 0;
+    cpu_mask_tbl[2] = IE_IRQ3;
+    cpu_irq_nr[2] = MEMORY;
+
+    dec_interrupt[HALT].cpu_mask = IE_IRQ4;
+    dec_interrupt[HALT].iemask = 0;
+    cpu_mask_tbl[3] = IE_IRQ4;
+    cpu_irq_nr[3] = HALT;
+
+    dec_interrupt[FPU].cpu_mask = IE_IRQ5;
+    dec_interrupt[FPU].iemask = 0;
+    cpu_mask_tbl[4] = IE_IRQ5;
+    cpu_irq_nr[4] = FPU;
+
+}				/* dec_init_kn03 */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/time.c linux.pre11.3/arch/mips/dec/time.c
--- linux.vanilla/arch/mips/dec/time.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/time.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,439 @@
+
+/*
+ *  linux/arch/mips/kernel/time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * This file contains the time handling details for PC-style clocks as
+ * found in some MIPS systems.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern volatile unsigned long lost_ticks;
+
+/*
+ * Change this if you have some constant time drift
+ */
+/* This is the value for the PC-style PICs. */
+/* #define USECS_PER_JIFFY (1000020/HZ) */
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi = 0, timerlo = 0;
+
+/*
+ * On MIPS only R4000 and better have a cycle counter.
+ *
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+    u32 count;
+    unsigned long res, tmp;
+
+    /* Last jiffy when do_fast_gettimeoffset() was called. */
+    static unsigned long last_jiffies = 0;
+    unsigned long quotient;
+
+    /*
+     * Cached "1/(clocks per usec)*2^32" value.
+     * It has to be recalculated once each jiffy.
+     */
+    static unsigned long cached_quotient = 0;
+
+    tmp = jiffies;
+
+    quotient = cached_quotient;
+
+    if (last_jiffies != tmp) {
+	last_jiffies = tmp;
+	__asm__(".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"lwu\t%0,%2\n\t"
+		"dsll32\t$1,%1,0\n\t"
+		"or\t$1,$1,%0\n\t"
+		"ddivu\t$0,$1,%3\n\t"
+		"mflo\t$1\n\t"
+		"dsll32\t%0,%4,0\n\t"
+		"nop\n\t"
+		"ddivu\t$0,%0,$1\n\t"
+		"mflo\t%0\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+      :	"=&r"(quotient)
+      :	"r"(timerhi),
+		"m"(timerlo),
+		"r"(tmp),
+		"r"(USECS_PER_JIFFY)
+      :	"$1");
+	cached_quotient = quotient;
+    }
+    /* Get last timer tick in absolute kernel time */
+    count = read_32bit_cp0_register(CP0_COUNT);
+
+    /* .. relative to previous jiffy (32 bits is enough) */
+    count -= timerlo;
+//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo);
+
+    __asm__("multu\t%1,%2\n\t"
+	    "mfhi\t%0"
+  :	    "=r"(res)
+  :	    "r"(count),
+	    "r"(quotient));
+
+    /*
+     * Due to possible jiffies inconsistencies, we need to check 
+     * the result so that we'll get a timer that is monotonic.
+     */
+    if (res >= USECS_PER_JIFFY)
+	res = USECS_PER_JIFFY - 1;
+
+    return res;
+}
+
+/* This function must be called with interrupts disabled 
+ * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
+ * 
+ * However, the pc-audio speaker driver changes the divisor so that
+ * it gets interrupted rather more often - it loads 64 into the
+ * counter rather than 11932! This has an adverse impact on
+ * do_gettimeoffset() -- it stops working! What is also not
+ * good is that the interval that our timer function gets called
+ * is no longer 10.0002 ms, but 9.9767 ms. To get around this
+ * would require using a different timing source. Maybe someone
+ * could use the RTC - I know that this can interrupt at frequencies
+ * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
+ * it so that at startup, the timer code in sched.c would select
+ * using either the RTC or the 8253 timer. The decision would be
+ * based on whether there was any other device around that needed
+ * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
+ * and then do some jiggery to have a version of do_timer that 
+ * advanced the clock by 1/1024 s. Every time that reached over 1/100
+ * of a second, then do all the old code. If the time was kept correct
+ * then do_gettimeoffset could just return 0 - there is no low order
+ * divider that can be accessed.
+ *
+ * Ideally, you would be able to use the RTC for the speaker driver,
+ * but it appears that the speaker driver really needs interrupt more
+ * often than every 120 us or so.
+ *
+ * Anyway, this needs more thought....          pjsg (1993-08-28)
+ * 
+ * If you are really that interested, you should be reading
+ * comp.protocols.time.ntp!
+ */
+
+#define TICK_SIZE tick
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+    /*
+     * This is a kludge until I find a way for the
+     * DECstations without bus cycle counter. HK
+     */
+    return 0;
+}
+
+static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset;
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+    unsigned long flags;
+
+    save_and_cli(flags);
+    *tv = xtime;
+    tv->tv_usec += do_gettimeoffset();
+
+    /*
+     * xtime is atomically updated in timer_bh. lost_ticks is
+     * nonzero if the timer bottom half hasnt executed yet.
+     */
+    if (lost_ticks)
+	tv->tv_usec += USECS_PER_JIFFY;
+
+    restore_flags(flags);
+
+    if (tv->tv_usec >= 1000000) {
+	tv->tv_usec -= 1000000;
+	tv->tv_sec++;
+    }
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+    cli();
+    /* This is revolting. We need to set the xtime.tv_usec
+     * correctly. However, the value in this location is
+     * is value at the last tick.
+     * Discover what correction gettimeofday
+     * would have done, and then undo it!
+     */
+    tv->tv_usec -= do_gettimeoffset();
+
+    if (tv->tv_usec < 0) {
+	tv->tv_usec += 1000000;
+	tv->tv_sec--;
+    }
+    xtime = *tv;
+    time_state = TIME_BAD;
+    time_maxerror = MAXPHASE;
+    time_esterror = MAXPHASE;
+    sti();
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ */
+static int 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;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static void inline
+ timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+    volatile unsigned char dummy;
+
+    dummy = CMOS_READ(RTC_REG_C);	/* ACK RTC Interrupt */
+    do_timer(regs);
+
+    /*
+     * 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 > 500000 - (tick >> 1) &&
+	xtime.tv_usec < 500000 + (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 */
+}
+
+static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+    unsigned int count;
+
+    /*
+     * The cycle counter is only 32 bit which is good for about
+     * a minute at current count rates of upto 150MHz or so.
+     */
+    count = read_32bit_cp0_register(CP0_COUNT);
+    timerhi += (count < timerlo);	/* Wrap around */
+    timerlo = count;
+
+    timer_interrupt(irq, dev_id, regs);
+}
+
+/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
+ * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
+ * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
+ *
+ * [For the Julian calendar (which was used in Russia before 1917,
+ * Britain & colonies before 1752, anywhere else before 1582,
+ * and is still in use by some communities) leave out the
+ * -year/100+year/400 terms, and add 10.]
+ *
+ * This algorithm was first published by Gauss (I think).
+ *
+ * WARNING: this function will overflow on 2106-02-07 06:28:16 on
+ * machines were long is 32-bit! (However, as time_t is signed, we
+ * will already get problems at other places on 2038-01-19 03:14:08)
+ */
+static inline unsigned long mktime(unsigned int year, unsigned int mon,
+				   unsigned int day, unsigned int hour,
+				   unsigned int min, unsigned int sec)
+{
+    if (0 >= (int) (mon -= 2)) {	/* 1..12 -> 11,12,1..10 */
+	mon += 12;		/* Puts Feb last since it has leap day */
+	year -= 1;
+    }
+    return (((
+		 (unsigned long) (year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) +
+		 year * 365 - 719499
+	     ) * 24 + hour	/* now have hours */
+	    ) * 60 + min	/* now have minutes */
+	) * 60 + sec;		/* finally seconds */
+}
+
+char cyclecounter_available;
+
+static inline void init_cycle_counter(void)
+{
+    switch (mips_cputype) {
+    case CPU_UNKNOWN:
+    case CPU_R2000:
+    case CPU_R3000:
+    case CPU_R3000A:
+    case CPU_R3041:
+    case CPU_R3051:
+    case CPU_R3052:
+    case CPU_R3081:
+    case CPU_R3081E:
+    case CPU_R6000:
+    case CPU_R6000A:
+    case CPU_R8000:		/* Not shure about that one, play safe */
+	cyclecounter_available = 0;
+	break;
+    case CPU_R4000PC:
+    case CPU_R4000SC:
+    case CPU_R4000MC:
+    case CPU_R4200:
+    case CPU_R4400PC:
+    case CPU_R4400SC:
+    case CPU_R4400MC:
+    case CPU_R4600:
+    case CPU_R10000:
+    case CPU_R4300:
+    case CPU_R4650:
+    case CPU_R4700:
+    case CPU_R5000:
+    case CPU_R5000A:
+    case CPU_R4640:
+    case CPU_NEVADA:
+	cyclecounter_available = 1;
+	break;
+    }
+}
+
+struct irqaction irq0 =
+{timer_interrupt, SA_INTERRUPT, 0,
+ "timer", NULL, NULL};
+
+
+void (*board_time_init) (struct irqaction * irq);
+
+__initfunc(void time_init(void))
+{
+    unsigned int year, mon, day, hour, min, sec;
+    int i;
+
+    /* 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);
+    }
+    /*
+     * The DECstation RTC is used as a TOY (Time Of Year).
+     * The PROM will reset the year to either '70, '71 or '72.
+     * This hack will only work until Dec 31 2001.
+     */
+    year += 1927;
+
+    xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+    xtime.tv_usec = 0;
+
+    init_cycle_counter();
+
+    if (cyclecounter_available) {
+	write_32bit_cp0_register(CP0_COUNT, 0);
+	do_gettimeoffset = do_fast_gettimeoffset;
+	irq0.handler = r4k_timer_interrupt;
+    }
+    board_time_init(&irq0);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/dec/wbflush.c linux.pre11.3/arch/mips/dec/wbflush.c
--- linux.vanilla/arch/mips/dec/wbflush.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/dec/wbflush.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,104 @@
+/*
+ * Setup the right wbflush routine for the different DECstations.
+ *
+ * Created with information from:
+ *      DECstation 3100 Desktop Workstation Functional Specification
+ *      DECstation 5000/200 KN02 System Module Functional Specification
+ *      mipsel-linux-objdump --disassemble vmunix | grep "wbflush" :-)
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ */
+
+#include <asm/bootinfo.h>
+#include <asm/init.h>
+
+static void wbflush_kn01(void);
+static void wbflush_kn210(void);
+static void wbflush_kn02ba(void);
+static void wbflush_kn03(void);
+
+void (*__wbflush) (void);
+
+__initfunc(void wbflush_setup(void))
+{
+	switch (mips_machtype) {
+	case MACH_DS23100:
+	    __wbflush = wbflush_kn01;
+	    break;
+	case MACH_DS5100:	/*  DS5100 MIPSMATE */
+	    __wbflush = wbflush_kn210;
+	    break;
+	case MACH_DS5000_200:	/* DS5000 3max */
+	    __wbflush = wbflush_kn01;
+	    break;
+	case MACH_DS5000_1XX:	/* DS5000/100 3min */
+	    __wbflush = wbflush_kn02ba;
+	    break;
+	case MACH_DS5000_2X0:	/* DS5000/240 3max+ */
+	    __wbflush = wbflush_kn03;
+	    break;
+	case MACH_DS5000_XX:	/* Personal DS5000/2x */
+	    __wbflush = wbflush_kn02ba;
+	    break;
+	}
+}
+
+/*
+ * For the DS3100 and DS5000/200 the writeback buffer functions
+ * as part of Coprocessor 0.
+ */
+static void wbflush_kn01(void)
+{
+    asm(".set\tpush\n\t"
+	".set\tnoreorder\n\t"
+	"1:\tbc0f\t1b\n\t"
+	"nop\n\t"
+	".set\tpop");
+}
+
+/*
+ * For the DS5100 the writeback buffer seems to be a part of Coprocessor 3.
+ * But CP3 has to enabled first.
+ */
+static void wbflush_kn210(void)
+{
+    asm(".set\tpush\n\t"
+	".set\tnoreorder\n\t"
+	"mfc0\t$2,$12\n\t"
+	"lui\t$3,0x8000\n\t"
+	"or\t$3,$2,$3\n\t"
+	"mtc0\t$3,$12\n\t"
+	"nop\n"
+	"1:\tbc3f\t1b\n\t"
+	"nop\n\t"
+	"mtc0\t$2,$12\n\t"
+	"nop\n\t"
+	".set\tpop"
+  : : :"$2", "$3");
+}
+
+/*
+ * Looks like some magic with the System Interrupt Mask Register
+ * in the famous IOASIC for kmins and maxines.
+ */
+static void wbflush_kn02ba(void)
+{
+    asm(".set\tpush\n\t"
+	".set\tnoreorder\n\t"
+	"lui\t$2,0xbc04\n\t"
+	"lw\t$3,0x120($2)\n\t"
+	"lw\t$3,0x120($2)\n\t"
+	".set\tpop"
+  : : :"$2", "$3");
+}
+
+/*
+ * The DS500/2x0 doesnt need to write back the WB.
+ */
+static void wbflush_kn03(void)
+{
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/defconfig linux.pre11.3/arch/mips/defconfig
--- linux.vanilla/arch/mips/defconfig	Wed Mar 10 21:13:00 1999
+++ linux.pre11.3/arch/mips/defconfig	Mon Jul 19 23:28:45 1999
@@ -10,13 +10,11 @@
 #
 # Machine selection
 #
-CONFIG_ACER_PICA_61=y
+# CONFIG_ACER_PICA_61 is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI is not set
 CONFIG_SNI_RM200_PCI=y
-CONFIG_MIPS_JAZZ=y
-CONFIG_VGA_CONSOLE=y
 CONFIG_PCI=y
 
 #
@@ -34,8 +32,10 @@
 #
 # General setup
 #
-CONFIG_ELF_KERNEL=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_PCI_OLD_PROC=y
 CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_ELF_KERNEL=y
 # CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
@@ -49,21 +49,21 @@
 # Loadable module support
 #
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
 
 #
 # Block devices
 #
-CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
+CONFIG_BLK_DEV_FD=m
+CONFIG_BLK_DEV_IDE=m
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDEDISK=m
+CONFIG_BLK_DEV_IDECD=m
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
@@ -75,10 +75,10 @@
 #
 # Additional Block Devices
 #
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_MD is not set
-# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM=m
 # CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
@@ -106,7 +106,6 @@
 # (it is safe to leave these untouched)
 #
 # CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
 # CONFIG_SKB_LARGE is not set
 
 #
@@ -124,8 +123,8 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -134,12 +133,13 @@
 #
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_LOGGING is not set
 
 #
 # 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
@@ -147,20 +147,25 @@
 # 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_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_SYM53C8XX is not set
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
-CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
-CONFIG_SCSI_NCR53C8XX_SYNC=5
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
 # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_PAS16 is not set
@@ -169,13 +174,12 @@
 # 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
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
-CONFIG_JAZZ_ESP=y
-CONFIG_JAZZ_ESP=y
 
 #
 # Network device support
@@ -185,7 +189,6 @@
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_NET_ETHERNET=y
-CONFIG_MIPS_JAZZ_SONIC=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -211,6 +214,8 @@
 # CONFIG_NET_RADIO is not set
 # CONFIG_TR is not set
 # CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_RCPCI is not set
 # CONFIG_WAN_DRIVERS is not set
 # CONFIG_LAPBETHER is not set
 # CONFIG_X25_ASY is not set
@@ -235,7 +240,7 @@
 # CONFIG_ISDN is not set
 
 #
-# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+# comment
 #
 # CONFIG_CD_NO_IDESCSI is not set
 
@@ -244,18 +249,26 @@
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_SERIAL=m
 # 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_RTC=y
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
 # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
 
 #
 # Ftape, the floppy tape device driver
@@ -265,69 +278,85 @@
 #
 # Filesystems
 #
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
+CONFIG_QUOTA=y
+CONFIG_AUTOFS_FS=m
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_UMSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_MINIX_FS=m
+# CONFIG_NTFS_FS is not set
+CONFIG_HPFS_FS=m
+CONFIG_PROC_FS=y
+CONFIG_ROMFS_FS=m
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=m
+CONFIG_SUNRPC=m
+CONFIG_LOCKD=m
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
 # CONFIG_SMD_DISKLABEL is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 
 #
 # Native Language Support
 #
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=y
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_KOI8_R is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
 
 #
 # Console drivers
 #
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 
 #
 # Sound
@@ -337,7 +366,7 @@
 #
 # Kernel hacking
 #
-CONFIG_CROSSCOMPILE=y
+# CONFIG_CROSSCOMPILE is not set
 # CONFIG_MIPS_FPE_MODULE is not set
 # CONFIG_REMOTE_DEBUG is not set
 # CONFIG_MAGIC_SYSRQ is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/Makefile linux.pre11.3/arch/mips/jazz/Makefile
--- linux.vanilla/arch/mips/jazz/Makefile	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/Makefile	Mon Jul 19 23:28:46 1999
@@ -1,3 +1,4 @@
+# $Id: Makefile,v 1.6 1999/02/25 21:57:01 tsbogend Exp $
 #
 # Makefile for the Jazz family specific parts of the kernel
 #
@@ -13,7 +14,8 @@
 
 all: jazz.o
 O_TARGET := jazz.o
-O_OBJS	 := hw-access.o int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o
+O_OBJS	 := int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o floppy-jazz.o \
+	    kbd-jazz.o
 
 int-handler.o: int-handler.S
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/floppy-jazz.c linux.pre11.3/arch/mips/jazz/floppy-jazz.c
--- linux.vanilla/arch/mips/jazz/floppy-jazz.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/floppy-jazz.c	Mon Jul 19 23:28:46 1999
@@ -14,11 +14,11 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <asm/addrspace.h>
-#include <asm/vector.h>
 #include <asm/jazz.h>
 #include <asm/jazzdma.h>
 #include <asm/keyboard.h>
 #include <asm/pgtable.h>
+#include <asm/floppy.h>
 
 static unsigned char jazz_fd_inb(unsigned int port)
 {
@@ -108,7 +108,7 @@
 	return order;
 }
 
-extern inline unsigned long jazz_fd_dma_mem_alloc(unsigned long size)
+static unsigned long jazz_fd_dma_mem_alloc(unsigned long size)
 {
 	int order = __get_order(size);
 	unsigned long mem;
@@ -121,14 +121,14 @@
 	return mem;
 }
 
-extern inline void jazz_fd_dma_mem_free(unsigned long addr,
+static void jazz_fd_dma_mem_free(unsigned long addr,
                                         unsigned long size)
 {       
-	vdma_free(PHYSADDR(addr));
+	vdma_free(vdma_phys2log(PHYSADDR(addr)));
 	free_pages(addr, __get_order(size));	
 }
 
-static void std_fd_drive_type(unsigned long n)
+static unsigned long jazz_fd_drive_type(unsigned long n)
 {
 	/* XXX This is wrong for machines with ED 2.88mb disk drives like the
 	   Olivetti M700.  Anyway, we should suck this from the ARC
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/hw-access.c linux.pre11.3/arch/mips/jazz/hw-access.c
--- linux.vanilla/arch/mips/jazz/hw-access.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/hw-access.c	Thu Jan  1 01:00:00 1970
@@ -1,90 +0,0 @@
-/* $Id: hw-access.c,v 1.11 1998/09/16 22:50:39 ralf Exp $
- *
- * Low-level hardware access stuff for Jazz family machines.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <asm/addrspace.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <asm/keyboard.h>
-#include <asm/pgtable.h>
-
-static volatile keyboard_hardware *jazz_kh = 
-	(keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS;
-
-#define KBD_STAT_IBF		0x02	/* Keyboard input buffer full */
-
-static unsigned char jazz_read_input(void)
-{
-	return jazz_kh->data;
-}
-
-static void jazz_write_output(unsigned char val)
-{
-	int status;
-
-	do {
-		status = jazz_kh->command;
-	} while (status & KBD_STAT_IBF);
-	jazz_kh->data = val;
-}
-
-static void jazz_write_command(unsigned char val)
-{
-	int status;
-
-	do {
-		status = jazz_kh->command;
-	} while (status & KBD_STAT_IBF);
-	jazz_kh->command = val;
-}
-
-static unsigned char jazz_read_status(void)
-{
-	return jazz_kh->command;
-}
-
-__initfunc(void jazz_keyboard_setup(void))
-{
-	kbd_read_input = jazz_read_input;
-	kbd_write_output = jazz_write_output;
-	kbd_write_command = jazz_write_command;
-	kbd_read_status = jazz_read_status;
-	request_irq(JAZZ_KEYBOARD_IRQ, keyboard_interrupt,
-	            0, "keyboard", NULL);
-	request_region(0x60, 16, "keyboard");
-	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
-	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE)
-	                  | JAZZ_IE_KEYBOARD);
-}
-
-int jazz_ps2_request_irq(void)
-{
-    extern void aux_interrupt(int, void *, struct pt_regs *);
-    int ret;
-    
-    ret = request_irq(JAZZ_MOUSE_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL);
-    if (!ret)
-	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 
-			  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | 
-			  JAZZ_IE_MOUSE);
-    return ret;
-}
-
-void jazz_ps2_free_irq(void)
-{
-    r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 
-		      r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | 
-		      JAZZ_IE_MOUSE);
-    free_irq(JAZZ_MOUSE_IRQ, NULL);
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/int-handler.S linux.pre11.3/arch/mips/jazz/int-handler.S
--- linux.vanilla/arch/mips/jazz/int-handler.S	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/int-handler.S	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: int-handler.S,v 1.6 1998/08/28 15:55:19 ralf Exp $
+/* $Id: int-handler.S,v 1.14 1999/05/01 22:40:34 ralf Exp $
  *
  * 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
@@ -91,51 +91,8 @@
  * whistles and bells and we're aware of the problem.
  */
 ll_isa_irq:	lw	a0,JAZZ_EISA_IRQ_ACK
-		lui	s0,%hi(JAZZ_PORT_BASE)
-		li	s1,1
-		andi	t0,a0,8				# which pic?
-		bnez	t0,ack_second
-		andi	a0,7				# delay slot
 
-		/*
-		 * Acknowledge first pic
-		 */
-		lb	t2,%lo(JAZZ_PORT_BASE)+0x21(s0)
-		lui	s4,%hi(cache_21)
-		lb	t0,%lo(cache_21)(s4)
-		sllv	s1,s1,a0
-		or	t0,s1
-		sb	t0,%lo(cache_21)(s4)
-		sb	t0,%lo(JAZZ_PORT_BASE)+0x21(s0)
-		li	t2,0x20
-		sb	t2,%lo(JAZZ_PORT_BASE)+0x20(s0)
-		/*
-		 * Now call the real handler
-		 */
-		jal	do_IRQ
-		 move	a1,sp
-		j	ret_from_irq
-		nop
-
-		.align	5
-ack_second:	/*
-		 * Acknowledge second pic
-		 */
-		lbu	t2,%lo(JAZZ_PORT_BASE)+0xa1(s0)
-		lui	s4,%hi(cache_A1)
-		lb	t3,%lo(cache_A1)(s4)
-		sllv	s1,s1,a0
-		or	t3,s1
-		sb	t3,%lo(cache_A1)(s4)
-		sb	t3,%lo(JAZZ_PORT_BASE)+0xa1(s0)
-		li	t3,0x20
-		sb	t3,%lo(JAZZ_PORT_BASE)+0xa0(s0)
-		sb	t3,%lo(JAZZ_PORT_BASE)+0x20(s0)
-		/*
-		 * Now call the real handler
-		 */
-		or      a0, 8
-		jal	do_IRQ
+		jal	i8259_do_irq
 		 move	a1,sp
 
 		j	ret_from_irq
@@ -144,7 +101,7 @@
 /*
  * Hmm...  This is not just a plain PC clone so the question is
  * which devices on Jazz machines can generate an (E)ISA NMI?
- * (Writing to nonexistant memory?)
+ * (Writing to nonexistent memory?)
  */
 ll_isa_nmi:	li	s1,~IE_IRQ3
 		PANIC("Unimplemented isa_nmi handler")
@@ -152,7 +109,7 @@
 /*
  * Timer IRQ - remapped to be more similar to an IBM compatible.
  *
- * The timer interrupt is handled specially to insure that the jiffies
+ * The timer interrupt is handled specially to ensure that the jiffies
  * variable is updated at all times.  Specifically, the timer interrupt is
  * just like the complete handlers except that it is invoked with interrupts
  * disabled and should never re-enable them.  If other interrupts were
@@ -163,7 +120,7 @@
 ll_timer:	lw	zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
 		li	s1,~IE_IRQ4
 
-		li	a0,0
+		li	a0, JAZZ_TIMER_IRQ
 		jal	do_IRQ
 		 move	a1,sp
 
@@ -228,14 +185,14 @@
 		b	loc_call
 
 /*
- * Floppy IRQ, remapped to level 6
+ * Floppy IRQ
  */
 loc_floppy:	li	s1,~JAZZ_IE_FLOPPY
 		li	a0,JAZZ_FLOPPY_IRQ
 		b	loc_call
 
 /*
- * Sound? What sound hardware (whistle) ???
+ * Sound IRQ
  */
 loc_sound:	PANIC("Unimplemented loc_sound handler")
 loc_video:	PANIC("Unimplemented loc_video handler")
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/jazzdma.c linux.pre11.3/arch/mips/jazz/jazzdma.c
--- linux.vanilla/arch/mips/jazz/jazzdma.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/jazzdma.c	Mon Jul 19 23:28:46 1999
@@ -97,6 +97,7 @@
     unsigned int frame;
     unsigned long laddr;
     int i;
+    unsigned long flags;
 
     /* check arguments */
   
@@ -113,6 +114,7 @@
         return VDMA_ERROR;	/* invalid physical address */
     }
   
+    save_and_cli (flags);
     /*
      * Find free chunk
      */
@@ -123,8 +125,10 @@
         while (entry[first].owner != VDMA_PAGE_EMPTY &&
                first < VDMA_PGTBL_ENTRIES)
             first++;
-        if (first+pages > VDMA_PGTBL_ENTRIES) /* nothing free */
+        if (first+pages > VDMA_PGTBL_ENTRIES) { /* nothing free */
+	    restore_flags (flags);
             return VDMA_ERROR;
+	}
 
         last = first+1;
         while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
@@ -170,6 +174,7 @@
         printk("\n");
     }
   
+    restore_flags(flags);
     return laddr;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/kbd-jazz.c linux.pre11.3/arch/mips/jazz/kbd-jazz.c
--- linux.vanilla/arch/mips/jazz/kbd-jazz.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/jazz/kbd-jazz.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,102 @@
+/* $Id: kbd-jazz.c,v 1.1 1998/10/28 12:38:10 ralf Exp $
+ *
+ * Low-level hardware access stuff for Jazz family machines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/pc_keyb.h>
+#include <asm/keyboard.h>
+#include <asm/jazz.h>
+
+#define jazz_kh ((keyboard_hardware *) JAZZ_KEYBOARD_ADDRESS)
+
+static void jazz_request_region(void)
+{
+	/* No I/O ports are being used on Jazz.  */
+}
+
+static int jazz_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	int res;
+
+	res = request_irq(JAZZ_KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
+	if (res != 0)
+		return res;
+
+	/* jazz_request_irq() should do this ...  */
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE)
+	                  | JAZZ_IE_KEYBOARD);
+
+	return 0;
+}
+
+static int jazz_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	int ret;
+    
+	ret = request_irq(JAZZ_MOUSE_IRQ, handler, 0, "PS/2 Mouse", NULL);
+	if (ret != 0)
+		return ret;
+
+		r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 
+				  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | 
+				  JAZZ_IE_MOUSE);
+	return 0;
+}
+
+static void jazz_aux_free_irq(void)
+{
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 
+	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE)
+	                  | JAZZ_IE_MOUSE);
+	free_irq(JAZZ_MOUSE_IRQ, NULL);
+}
+
+static unsigned char jazz_read_input(void)
+{
+	return jazz_kh->data;
+}
+
+static void jazz_write_output(unsigned char val)
+{
+	int status;
+
+	do {
+		status = jazz_kh->command;
+	} while (status & KBD_STAT_IBF);
+	jazz_kh->data = val;
+}
+
+static void jazz_write_command(unsigned char val)
+{
+	int status;
+
+	do {
+		status = jazz_kh->command;
+	} while (status & KBD_STAT_IBF);
+	jazz_kh->command = val;
+}
+
+static unsigned char jazz_read_status(void)
+{
+	return jazz_kh->command;
+}
+
+struct kbd_ops jazz_kbd_ops = {
+	jazz_request_region,
+	jazz_request_irq,
+
+	jazz_aux_request_irq,
+	jazz_aux_free_irq,
+
+	jazz_read_input,
+	jazz_write_output,
+	jazz_write_command,
+	jazz_read_status
+};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/reset.c linux.pre11.3/arch/mips/jazz/reset.c
--- linux.vanilla/arch/mips/jazz/reset.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/reset.c	Mon Jul 19 23:28:46 1999
@@ -3,7 +3,7 @@
  *
  *  Reset a Jazz machine.
  *
- *  $Id: reset.c,v 1.2 1998/03/04 12:17:40 ralf Exp $
+ *  $Id: reset.c,v 1.3 1998/03/04 08:29:10 ralf Exp $
  */
 
 #include <linux/sched.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/rtc-jazz.c linux.pre11.3/arch/mips/jazz/rtc-jazz.c
--- linux.vanilla/arch/mips/jazz/rtc-jazz.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/rtc-jazz.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: rtc-jazz.c,v 1.3 1998/08/28 15:55:19 ralf Exp $
+/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/jazz/setup.c linux.pre11.3/arch/mips/jazz/setup.c
--- linux.vanilla/arch/mips/jazz/setup.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/jazz/setup.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.14 1998/09/16 22:50:40 ralf Exp $
+/* $Id: setup.c,v 1.20 1999/02/25 21:57:47 tsbogend Exp $
  *
  * Setup pointers to hardware-dependent routines.
  *
@@ -12,7 +12,6 @@
 #include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/kbd_ll.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
@@ -40,7 +39,6 @@
 static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
 
 extern asmlinkage void jazz_handle_int(void);
-extern void jazz_keyboard_setup(void);
 
 extern void jazz_machine_restart(char *command);
 extern void jazz_machine_halt(void);
@@ -48,6 +46,9 @@
 
 extern struct ide_ops std_ide_ops;
 extern struct rtc_ops jazz_rtc_ops;
+extern struct kbd_ops jazz_kbd_ops;
+extern struct fd_ops *fd_ops;
+extern struct fd_ops jazz_fd_ops;
 
 void (*board_time_init)(struct irqaction *irq);
 
@@ -55,7 +56,7 @@
 {
         /* set the clock to 100 Hz */
         r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
-        setup_x86_irq(0, irq);
+        i8259_setup_irq(JAZZ_TIMER_IRQ, irq);
 }
 
 __initfunc(static void jazz_irq_setup(void))
@@ -75,43 +76,16 @@
 	r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
 	request_region(0x20, 0x20, "pic1");
 	request_region(0xa0, 0x20, "pic2");
-	setup_x86_irq(2, &irq2);
+	i8259_setup_irq(2, &irq2);
 }
 
 __initfunc(void jazz_setup(void))
 {
-    tag *atag;
-
-    /*
-     * we just check if a tag_screen_info can be gathered
-     * in setup_arch(), if yes we don't proceed futher...
-     */
-    atag = bi_TagFind(tag_screen_info);
-    if (!atag) {
-	/*
-	 * If no, we try to find the tag_arc_displayinfo which is
-	 * always created by Milo for an ARC box (for now Milo only
-	 * works on ARC boxes :) -Stoned.
-	 */
-	atag = bi_TagFind(tag_arcdisplayinfo);
-	if (atag) {
-	    screen_info.orig_x = 
-		((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x;
-	    screen_info.orig_y = 
-		((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y;
-	    screen_info.orig_video_cols  = 
-		((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns;
-	    screen_info.orig_video_lines  = 
-		((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
-	}
-    }
-
 	add_wired_entry (0x02000017, 0x03c00017, 0xe0000000, PM_64K);
 	add_wired_entry (0x02400017, 0x02440017, 0xe2000000, PM_16M);
 	add_wired_entry (0x01800017, 0x01000017, 0xe4000000, PM_4M);
 
 	irq_setup = jazz_irq_setup;
-	keyboard_setup = jazz_keyboard_setup;
 	mips_io_port_base = JAZZ_PORT_BASE;
 	isa_slot_offset = 0xe3000000;
 	request_region(0x00,0x20,"dma1");
@@ -128,6 +102,8 @@
 #ifdef CONFIG_BLK_DEV_IDE
 	ide_ops = &std_ide_ops;
 #endif
-	conswitchp = &fb_con;
+	conswitchp = &dummy_con;
 	rtc_ops = &jazz_rtc_ops;
+	kbd_ops = &jazz_kbd_ops;
+	fd_ops = &jazz_fd_ops;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/Makefile linux.pre11.3/arch/mips/kernel/Makefile
--- linux.vanilla/arch/mips/kernel/Makefile	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/Makefile	Mon Jul 19 23:28:37 1999
@@ -23,10 +23,14 @@
 endif
 
 #
-# SGI's have very different interrupt/timer hardware.
+# SGIs have very different interrupt/timer hardware.
 #
 ifndef CONFIG_SGI
-O_OBJS += irq.o time.o
+  ifndef CONFIG_DECSTATION
+    ifndef CONFIG_BAGET_MIPS
+      O_OBJS += irq.o time.o
+    endif
+  endif
 endif
 
 #
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/entry.S linux.pre11.3/arch/mips/kernel/entry.S
--- linux.vanilla/arch/mips/kernel/entry.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/entry.S	Mon Jul 19 23:28:37 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
  *
- * $Id: entry.S,v 1.15 1998/10/14 20:26:26 ralf Exp $
+ * $Id: entry.S,v 1.14 1999/04/12 19:13:21 harald Exp $
  */
 
 /*
@@ -146,7 +146,7 @@
 		BUILD_HANDLER(adel,ade,ade,silent)		/* #4  */
 		BUILD_HANDLER(ades,ade,ade,silent)		/* #5  */
 		BUILD_HANDLER(ibe,ibe,cli,verbose)		/* #6  */
-		BUILD_HANDLER(dbe,dbe,cli,verbose)		/* #7  */
+		BUILD_HANDLER(dbe,dbe,cli,silent)		/* #7  */
 		BUILD_HANDLER(bp,bp,sti,silent)			/* #9  */
 		BUILD_HANDLER(ri,ri,sti,silent)			/* #10 */
 		BUILD_HANDLER(cpu,cpu,sti,silent)		/* #11 */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/fpe.c linux.pre11.3/arch/mips/kernel/fpe.c
--- linux.vanilla/arch/mips/kernel/fpe.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/fpe.c	Mon Jul 19 23:28:45 1999
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 1997 Ralf Baechle
  *
- * $Id: fpe.c,v 1.2 1998/03/27 08:53:39 ralf Exp $
+ * $Id: fpe.c,v 1.4 1999/05/01 22:40:35 ralf Exp $
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -39,7 +39,7 @@
 
 /*
  * For easier experimentation we never increment/decrement
- * the module useable counter.
+ * the module usable counter.
  */
 int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31));
 int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31));
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/gdb-low.S linux.pre11.3/arch/mips/kernel/gdb-low.S
--- linux.vanilla/arch/mips/kernel/gdb-low.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/gdb-low.S	Mon Jul 19 23:28:38 1999
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 1995 Andreas Busse
  *
- * $Id: gdb-low.S,v 1.3 1997/12/02 05:51:05 ralf Exp $
+ * $Id: gdb-low.S,v 1.4 1997/12/01 17:57:26 ralf Exp $
  */
 
 #include <linux/sys.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/gdb-stub.c linux.pre11.3/arch/mips/kernel/gdb-stub.c
--- linux.vanilla/arch/mips/kernel/gdb-stub.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/gdb-stub.c	Mon Jul 19 23:28:38 1999
@@ -12,7 +12,7 @@
  *
  *  Copyright (C) 1995 Andreas Busse
  *
- * $Id: gdb-stub.c,v 1.4 1997/12/02 05:51:06 ralf Exp $
+ * $Id: gdb-stub.c,v 1.7 1999/06/12 18:39:28 ulfc Exp $
  */
 
 /*
@@ -326,7 +326,7 @@
 	{ 7, SIGBUS },			/* data bus error */
 	{ 9, SIGTRAP },			/* break */
 	{ 10, SIGILL },			/* reserved instruction */
-/*	{ 11, SIGILL },		*/	/* cpu unusable */
+/*	{ 11, SIGILL },		*/	/* CPU unusable */
 	{ 12, SIGFPE },			/* overflow */
 	{ 13, SIGTRAP },		/* trap */
 	{ 14, SIGSEGV },		/* virtual instruction cache coherency */
@@ -362,8 +362,6 @@
 
 	initialized = 1;
 	restore_flags(flags);
-
-	breakpoint();
 }
 
 
@@ -379,7 +377,7 @@
 }
 
 /*
- * Convert the MIPS hardware trap type code to a unix signal number.
+ * Convert the MIPS hardware trap type code to a Unix signal number.
  */
 static int computeSignal(int tt)
 {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/head.S linux.pre11.3/arch/mips/kernel/head.S
--- linux.vanilla/arch/mips/kernel/head.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/head.S	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.13 1998/10/14 20:26:27 ralf Exp $
+/* $Id: head.S,v 1.11 1998/10/18 13:27:12 tsbogend Exp $
  *
  * arch/mips/kernel/head.S
  *
@@ -408,15 +408,7 @@
 
 probe_done:
 
-#ifndef CONFIG_SGI
-	/* Get the memory upper limit the bootloader passed to us
-	 * in a0
-	 */
-	la	t0, mips_memory_upper
-	nop
-	sw	a0, (t0)		
-#else
-	/* On SGI's the firmware/bootloader passes argc/argp/envp
+	/* The firmware/bootloader passes argc/argp/envp
 	 * to us as arguments.  But clear bss first because
 	 * the romvec and other important info is stored there
 	 * by prom_init().
@@ -431,6 +423,7 @@
 
 	jal	prom_init /* prom_init(argc, argv, envp); */
 	 nop
+#ifdef CONFIG_SGI
 	jal	sgi_sysinit
 	 nop
 #endif
@@ -440,18 +433,6 @@
 	 nop
 #endif
 
-	/* Get the very one tags we need early in the boot process */
-	nop
-	jal	bi_EarlySnarf
-	 nop
-#ifndef CONFIG_SGI
-	/* Clear BSS first so that there are no surprises... */
-	la	t0, _edata
-	la	t1, _end
-1:	addiu	t0, 1
-	bne	t0, t1, 1b
-	sb	zero, -1(t0)
-#endif
 	/*
 	 * Determine the mmu/cache attached to this machine,
 	 * then flush the tlb and caches.  On the r4xx0
@@ -460,34 +441,10 @@
 	jal	loadmmu
 	 nop
 
-	la	t2, mips_cputype
-	lw	t4, (t2)
-	li	t1, CPU_R2000
-	li	t2, CPU_R3000
-	li	t3, CPU_R3000A
-	beq	t4,t1,2f
-	 nop		
-
-	beq	t4,t2,2f
-	 nop		
-
-	beq	t4,t3,2f
-	 nop		
-
-	jal	wire_mappings_r4xx0
-	 nop	
-
-	b	9f
-	 nop
-
-2:
-	jal	wire_mappings_r3000
-	 nop	
-
 	/*
 	 * Stack for kernel and init, current variable
 	 */
-9:	la	$28, init_task_union
+	la	$28, init_task_union
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
 	sw	t0, kernelsp
 	subu	sp, t0, 4*SZREG
@@ -509,81 +466,6 @@
 	 nop					# delay slot
 	END(kernel_entry)
 
-/*
- * wire_mappings - used to map hardware registers, r4xx0 version.
- */
-LEAF(wire_mappings_r4xx0)
-	mtc0	zero, CP0_WIRED
-	nop
-	nop
-	nop
-	j	ra
-	 nop
-	END(wire_mappings_r4xx0)
-
-/*
- * R3000 version of wire_mappings.
- */
-LEAF(wire_mappings_r3000)
-	/*
-	 * Get base address of map0 table for the
-	 * the board we're running on
-	 */
-	lw	t1, mips_machtype
-	la	t0, map0table
-	sll	t1, PTRLOG		# machtype used as index
-	addu	t0, t1
-	lw	t0, (t0)		# get base address
-	nop
-	/* Get number of wired TLB entries and
-	 * loop over selected map0 table.
-	 */
-	lw	t1, (t0)		# number of wired TLB entries
-	move	t2, zero		# TLB entry counter
-	addiu	t3, t1, 1		# wire one additional entry
-	beqz	t1, 2f			# null, exit
-	 nop
-
-	addiu	t0, 8
-1:
-	lw	t4, 24(t0)		# PageMask
-	ld	t5,  0(t0)		# entryHi
-	ld	t6,  8(t0)		# entryLo0
-	addiu	t2, 1			# increment ctr
-	mtc0	t2, CP0_INDEX		# set TLB entry
-	nop
-	mtc0	t5, CP0_ENTRYHI
-	nop
-	mtc0	t6, CP0_ENTRYLO0
-	addiu	t0, 32
-	bne	t1, t2, 1b		# next TLB entry
-	 tlbwi
-
-	/* We use only 4k pages. Therefore the PageMask register
-	 * is expected to be setup for 4k pages.
-	 */
-2:
-	/* Now map the pagetables */
-	mtc0	zero, CP0_INDEX
-	la	t0, TLB_ROOT
-	mtc0	t0, CP0_ENTRYHI
-	nop
-	la	t0, swapper_pg_dir
-	srl	t0, 12
-	ori	t0, (0x00e0|0x0100)	# uncachable, dirty, valid
-	mtc0	t0, CP0_ENTRYLO0
-	nop
-	tlbwi				# delayed
-
-	/* Load the context register with zero.  To see why, look
-	 * at how the tlb refill code above works.
-	 */
-	mtc0	zero, CP0_CONTEXT
-
-	jr	ra
-	 nop
-	END(wire_mappings_r3000)
-
 	/* CPU type probing code, called at Kernel entry. */
 	LEAF(cpu_probe)
 	mfc0	t0, CP0_PRID
@@ -707,115 +589,6 @@
 	b	probe_done
 	 nop
 	END(cpu_probe)
-
-	.data
-/*
- * Build an entry for table of wired entries
- */
-#define MAPDATA(q1,q2,q3,w1)                                    \
-		.quad	q1;                                     \
-		.quad	q2;                                     \
-		.quad	q3;                                     \
-		.word	w1;                                     \
-		.word	0
-
-/*
- * Initial mapping tables for supported Mips boards.
- * First item is always the number of wired TLB entries,
- * following by EntryHi/EntryLo pairs and page mask.
- * Since everything must be quad-aligned (8) we insert
- * some dummy zeros.
- *
- * Keep in mind that the PFN does not depend on the page size in the
- * TLB page mask register.  See milo's lib/dumptlb.c for how to decode
- * and encode these entries.  Don't see the same routine in the linux
- * kernel distribution, since it is older and unreliable.
- */
-
-/*
- * Address table of mapping tables for supported Mips boards.
- * Add your own stuff here but don't forget to define your
- * target system in bootinfo.h
- */
-
-map0table:	PTR	map0_dummy		# machtype = unknown
-		PTR	map0_rpc		# Deskstation rPC44
-		PTR	map0_tyne		# Deskstation Tyne
-		PTR	map0_pica61		# Acer Pica-61
-		PTR	map0_magnum4000		# MIPS Magnum 4000PC (RC4030)
-		PTR	map0_dummy
-		PTR	map0_dummy		# DEC Personal DECStation 5000/2x (for now)
-		PTR	map0_sni_rm200_pci	# SNI RM200 PCI
-		PTR	map0_dummy		# SGI INDY
-
-map0_dummy:	.word	0			# 0 entries
-
-		.align  3
-/*
- * Deskstation rpc44 mappings.  This machine has its EISA bus at physical
- * address 0xa0000000 which we map for 32M, but that doesn't match EISA
- * spec.  Not sure what to do about this.  Its I/O ports are memory mapped
- * at physical memory location 0xb0000000.
- */
-map0_rpc: 	.word   2			# no. of wired TLB entries
-		.word	0			# pad for alignment
-
-MAPDATA(0xffffffffe0000000, 0x02800017, 0x00000001, PM_16M)	# ISA Memory space
-MAPDATA(0xffffffffe2000000, 0x02c00017, 0x00000001, PM_64K)	# ISA I/O Space
-
-/*
- * Initial mappings for Deskstation Tyne boards.
- */
-map0_tyne: 	.word   2			# no. of wired TLB entries
-		.word	0			# pad for alignment
-
-MAPDATA(0xffffffffe0000000, 0x04020017, 0x00000001, PM_1M)	# VESA DMA cache
-MAPDATA(0xffffffffe2000000, 0x24000017, 0x04000017, PM_16M)	# VESA I/O and memory space
-
-/*
- * Initial mapping for ACER PICA-61 boards.
- * FIXME: These are rather preliminary since many drivers, such as serial,
- * parallel, scsi and ethernet need some changes to distinguish between "local"
- * (built-in) and "optional" (ISA/PCI) I/O hardware. Local video ram is mapped
- * to the same location as the bios maps it to. Console driver has been changed
- * accordingly (new video type: VIDEO_TYPE_PICA_S3).
- * FIXME: Remove or merge some of the mappings.
- */
-map0_pica61:	.word  	7			# no. wired TLB entries
-		.word	0			# dummy
-
-MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K)	# Local I/O space
-MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K)	# Interrupt source register
-MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M)	# Local video control
-MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M)	# Extended video control
-MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M)	# Local video memory (BIOS mapping)
-MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M)	# ISA I/O and ISA memory space (both 16M)
-MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)	# PCR (???)
-
-/*
- * Initial mapping for Mips Magnum 4000PC systems.
- * Do you believe me now that the Acer and Mips boxes are nearly the same ? :-)
- * FIXME: Remove or merge some of the mappings.
- */
-map0_magnum4000:
-		.word  	8			# no. wired TLB entries
-		.word	0			# dummy
-
-MAPDATA(0xffffffffe1000000, 0x03ffc013, 0x00000001, PM_256K)	# 0
-MAPDATA(0xffffffffe0000000, 0x02000017, 0x00000001, PM_64K)	# 1 local I/O
-MAPDATA(0xffffffffe0100000, 0x03c00017, 0x00000001, PM_4K)	# 2 IRQ source
-MAPDATA(0xffffffffe0200000, 0x01800017, 0x01804017, PM_1M)	# 3 local video ctrl
-MAPDATA(0xffffffffe0400000, 0x01808017, 0x0180c017, PM_1M)	# 4 ext. video ctrl
-MAPDATA(0xffffffffe0800000, 0x01000017, 0x01010017, PM_4M)	# 5 local video mem.
-MAPDATA(0xffffffffe2000000, 0x02400017, 0x02440017, PM_16M)	# 6 ISA I/O and mem.
-MAPDATA(0xffffffffffffe000, 0x00000001, 0x0001ffd7, PM_4K)	# 7 PCR
-
-/*
- * The RM200 doesn't need any wired entries.
- */
-map0_sni_rm200_pci:
-		.word  	0			# no. wired TLB entries
-		.word	0			# dummy
 
 /*
  * This buffer is reserved for the use of the cache error handler.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/init_task.c linux.pre11.3/arch/mips/kernel/init_task.c
--- linux.vanilla/arch/mips/kernel/init_task.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/init_task.c	Mon Jul 19 23:28:44 1999
@@ -6,7 +6,6 @@
 
 static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
-static struct files * 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 --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/ipc.c linux.pre11.3/arch/mips/kernel/ipc.c
--- linux.vanilla/arch/mips/kernel/ipc.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/ipc.c	Mon Jul 19 23:53:55 1999
@@ -1,5 +1,4 @@
-/*
- * linux/arch/mips/kernel/ipc.c
+/* $Id$
  *
  * This file contains various random system calls that
  * have a non-standard calling sequence on the Linux/MIPS
@@ -22,106 +21,92 @@
  *
  * This is really horribly ugly.  FIXME: Get rid of this wrapper.
  */
-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 --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irix5sys.h linux.pre11.3/arch/mips/kernel/irix5sys.h
--- linux.vanilla/arch/mips/kernel/irix5sys.h	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/irix5sys.h	Mon Jul 19 23:28:44 1999
@@ -1,4 +1,4 @@
-/* $Id: irix5sys.h,v 1.2 1998/08/17 10:16:25 ralf Exp $
+/* $Id: irix5sys.h,v 1.2 1998/08/25 09:14:39 ralf Exp $
  *
  * irix5sys.h: 32-bit IRIX5 ABI system call table.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixelf.c linux.pre11.3/arch/mips/kernel/irixelf.c
--- linux.vanilla/arch/mips/kernel/irixelf.c	Fri Nov 13 01:37:10 1998
+++ linux.pre11.3/arch/mips/kernel/irixelf.c	Mon Jul 19 23:28:38 1999
@@ -1,4 +1,5 @@
-/*
+/* $Id: irixelf.c,v 1.17.2.2 1999/06/22 20:53:26 ralf Exp $
+ *
  * irixelf.c: Code to load IRIX ELF executables which conform to
  *            the MIPS ABI.
  *
@@ -309,7 +310,7 @@
 		return 0xffffffff;
 	}
 
-	file = current->files->fd[elf_exec_fileno];
+	file = fget(elf_exec_fileno);
 
 	eppnt = elf_phdata;
 	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
@@ -367,6 +368,7 @@
 	}
 
 	/* Now use mmap to map the library into memory. */
+	fput(file);
 	sys_close(elf_exec_fileno);
 	if(error < 0 && error > -1024) {
 #ifdef DEBUG_ELF
@@ -617,8 +619,9 @@
 	unsigned int load_addr, elf_bss, elf_brk;
 	unsigned int elf_entry, interp_load_addr = 0;
 	unsigned int start_code, end_code, end_data, elf_stack;
-	int elf_exec_fileno, retval, has_interp, has_ephdr, i;
+	int elf_exec_fileno, retval, has_interp, has_ephdr, size, i;
 	char *elf_interpreter;
+	struct file *file;
 	mm_segment_t old_fs;
 	
 	load_addr = 0;
@@ -634,17 +637,15 @@
 #endif
 
 	/* Now read in all of the header information */
-	elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
-						 elf_ex.e_phnum, GFP_KERNEL);
+	size = elf_ex.e_phentsize * elf_ex.e_phnum;
+	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 	if (elf_phdata == NULL)
 		return -ENOMEM;
 	
-	retval = read_exec(bprm->dentry, elf_ex.e_phoff, (char *) elf_phdata,
-			   elf_ex.e_phentsize * elf_ex.e_phnum, 1);
-	if (retval < 0) {
-		kfree (elf_phdata);
-		return retval;
-	}
+	retval = read_exec(bprm->dentry, elf_ex.e_phoff,
+	                   (char *) elf_phdata, size, 1);
+	if (retval < 0)
+		goto out_phdata;
 	
 #ifdef DEBUG_ELF
 	dump_phdrs(elf_phdata, elf_ex.e_phnum);
@@ -669,12 +670,10 @@
 
 	elf_bss = 0;
 	elf_brk = 0;
-	elf_exec_fileno = open_dentry(bprm->dentry, O_RDONLY);
-
-	if (elf_exec_fileno < 0) {
-		kfree (elf_phdata);
-		return elf_exec_fileno;
-	}
+	retval = open_dentry(bprm->dentry, O_RDONLY);
+	if (retval < 0)
+		goto out_phdata;
+	file = fget(elf_exec_fileno = retval);
 	
 	elf_stack = 0xffffffff;
 	elf_interpreter = NULL;
@@ -686,40 +685,26 @@
 	                                   &interpreter_dentry,
 					   &interp_elf_ex, elf_phdata, bprm,
 					   elf_ex.e_phnum);
-	if(retval) {
-		kfree(elf_phdata);
-		sys_close(elf_exec_fileno);
-		return retval;
-	}
+	if(retval)
+		goto out_file;
 	
 	if(elf_interpreter) {
 		retval = verify_irix_interpreter(&interp_elf_ex);
-		if(retval) {
-			kfree(elf_interpreter);
-			kfree(elf_phdata);
-			sys_close(elf_exec_fileno);
-			return retval;
-		}
+		if(retval)
+			goto out_interp;
 	}
 	
 	/* OK, we are done with that, now set up the arg stuff,
 	 * and then start this sucker up.
 	 */
-	if (!bprm->sh_bang) {
-		if (!bprm->p) {
-			if(elf_interpreter) {
-			      kfree(elf_interpreter);
-			}
-			kfree (elf_phdata);
-			sys_close(elf_exec_fileno);
-			return -E2BIG;
-		}
-	}
+	retval = -E2BIG;
+	if (!bprm->sh_bang && !bprm->p)
+		goto out_interp;
 	
 	/* Flush all traces of the currently running executable */
 	retval = flush_old_exec(bprm);
 	if (retval)
-		return retval;
+		goto out_interp;
 
 	/* OK, This is the point of no return */
 	current->mm->end_data = 0;
@@ -741,8 +726,7 @@
 	old_fs = get_fs();
 	set_fs(get_ds());
 	
-	map_executable(current->files->fd[elf_exec_fileno], elf_phdata,
-		       elf_ex.e_phnum, &elf_stack, &load_addr,
+	map_executable(file, elf_phdata, elf_ex.e_phnum, &elf_stack, &load_addr,
 		       &start_code, &elf_bss, &end_code, &end_data, &elf_brk);
 
 	if(elf_interpreter) {
@@ -762,6 +746,7 @@
 	set_fs(old_fs);
 	
 	kfree(elf_phdata);
+	fput(file);
 	sys_close(elf_exec_fileno);
 	current->personality = PER_IRIX32;
 
@@ -824,6 +809,17 @@
 	if (current->flags & PF_PTRACED)
 		send_sig(SIGTRAP, current, 0);
 	return 0;
+
+out_interp:
+	if(elf_interpreter) {
+	      kfree(elf_interpreter);
+	}
+out_file:
+	fput(file);
+	sys_close(elf_exec_fileno);
+out_phdata:
+	kfree (elf_phdata);
+	return retval;
 }
 
 static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
@@ -839,9 +835,8 @@
 /* This is really simpleminded and specialized - we are loading an
  * a.out library that is given an ELF header.
  */
-static inline int do_load_irix_library(int fd)
+static inline int do_load_irix_library(struct file *file)
 {
-	struct file * file;
 	struct elfhdr elf_ex;
 	struct elf_phdr *elf_phdata  =  NULL;
 	struct dentry *dentry;
@@ -854,14 +849,12 @@
 	int i,j, k;
 
 	len = 0;
-	file = current->files->fd[fd];
+	if (!file->f_op)
+		return -EACCES;
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 	elf_bss = 0;
 	
-	if (!file || !file->f_op)
-		return -EACCES;
-
 	/* Seek to the beginning of the file. */
 	if (file->f_op->llseek) {
 		if ((error = file->f_op->llseek(file, 0, 0)) != 0)
@@ -940,10 +933,15 @@
 
 static int load_irix_library(int fd)
 {
-	int retval;
+	int retval = -EACCES;
+	struct file *file;
 
 	MOD_INC_USE_COUNT;
-	retval = do_load_irix_library(fd);
+	file = fget(fd);
+	if (file) {
+		retval = do_load_irix_library(file);
+		fput(file);
+	}
 	MOD_DEC_USE_COUNT;
 	return retval;
 }
@@ -984,9 +982,12 @@
 			return -ENOEXEC;
 		}
 
-	filp = current->files->fd[fd];
-	if(!filp || !filp->f_op) {
+	filp = fget(fd);
+	if (!filp)
+		return -EACCES;
+	if(!filp->f_op) {
 		printk("irix_mapelf: Bogon filp!\n");
+		fput(file);
 		return -EACCES;
 	}
 
@@ -1004,6 +1005,7 @@
 
 		if(retval != (hp->p_vaddr & 0xfffff000)) {
 			printk("irix_mapelf: do_mmap fails with %d!\n", retval);
+			fput(file);
 			return retval;
 		}
 	}
@@ -1011,6 +1013,7 @@
 #ifdef DEBUG_ELF
 	printk("irix_mapelf: Success, returning %08lx\n", user_phdrp->p_vaddr);
 #endif
+	fput(file);
 	return user_phdrp->p_vaddr;
 }
 
@@ -1026,7 +1029,13 @@
  */
 static int dump_write(struct file *file, const void *addr, int nr)
 {
-	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+	int r;
+
+	down(&file->f_dentry->d_inode->i_sem);
+	r = file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+	up(&file->f_dentry->d_inode->i_sem);
+
+	return r;
 }
 
 static int dump_seek(struct file *file, off_t off)
@@ -1108,10 +1117,10 @@
 #undef DUMP_SEEK
 
 #define DUMP_WRITE(addr, nr)	\
-	if (!dump_write(&file, (addr), (nr))) \
+	if (!dump_write(file, (addr), (nr))) \
 		goto close_coredump;
 #define DUMP_SEEK(off)	\
-	if (!dump_seek(&file, (off))) \
+	if (!dump_seek(file, (off))) \
 		goto close_coredump;
 /* Actual dumper.
  *
@@ -1122,7 +1131,7 @@
 static int irix_core_dump(long signr, struct pt_regs * regs)
 {
 	int has_dumped = 0;
-	struct file file;
+	struct file *file;
 	struct dentry *dentry;
 	struct inode *inode;
 	mm_segment_t fs;
@@ -1191,26 +1200,28 @@
 	
 	fs = get_fs();
 	set_fs(KERNEL_DS);
+
 	memcpy(corefile,"core.", 5);
 #if 0
 	memcpy(corefile+5,current->comm,sizeof(current->comm));
 #else
 	corefile[4] = '\0';
 #endif
-	dentry = open_namei(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
-	if (IS_ERR(dentry)) {
-		inode = NULL;
+	file = filp_open(corefile, O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
+	if (IS_ERR(file))
 		goto end_coredump;
-	}
+	dentry = file->f_dentry;
 	inode = dentry->d_inode;
+	if (inode->i_nlink > 1)
+		goto close_coredump;	/* multiple links - don't dump */
+
 	if (!S_ISREG(inode->i_mode))
-		goto end_coredump;
+		goto close_coredump;
 	if (!inode->i_op || !inode->i_op->default_file_ops)
-		goto end_coredump;
-	if (init_private_file(&file, dentry, 3))
-		goto end_coredump;
-	if (!file.f_op->write)
 		goto close_coredump;
+	if (!file->f_op->write)
+		goto close_coredump;
+
 	has_dumped = 1;
 	current->flags |= PF_DUMPCORE;
 
@@ -1346,7 +1357,7 @@
 	}
 
 	for(i = 0; i < numnote; i++)
-		if (!writenote(&notes[i], &file))
+		if (!writenote(&notes[i], file))
 			goto close_coredump;
 	
 	set_fs(fs);
@@ -1368,19 +1379,17 @@
 		DUMP_WRITE((void *)addr, len);
 	}
 
-	if ((off_t) file.f_pos != offset) {
+	if ((off_t) file->f_pos != offset) {
 		/* Sanity check. */
-		printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n",
-		       (off_t) file.f_pos, offset);
+		printk("elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
+		       (off_t) file->f_pos, offset);
 	}
 
  close_coredump:
-	if (file.f_op->release)
-		file.f_op->release(inode, &file);
+	filp_close(file, NULL);
 
  end_coredump:
 	set_fs(fs);
-	dput(dentry);
 #ifndef CONFIG_BINFMT_ELF
 	MOD_DEC_USE_COUNT;
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixinv.c linux.pre11.3/arch/mips/kernel/irixinv.c
--- linux.vanilla/arch/mips/kernel/irixinv.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/irixinv.c	Mon Jul 19 23:28:45 1999
@@ -5,7 +5,7 @@
  *
  * Miguel de Icaza, 1997.
  *
- * $Id: irixinv.c,v 1.3 1998/03/27 08:53:40 ralf Exp $
+ * $Id: irixinv.c,v 1.3 1998/04/05 11:23:51 ralf Exp $
  */
 #include <linux/mm.h>
 #include <linux/init.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixioctl.c linux.pre11.3/arch/mips/kernel/irixioctl.c
--- linux.vanilla/arch/mips/kernel/irixioctl.c	Thu May 27 22:11:50 1999
+++ linux.pre11.3/arch/mips/kernel/irixioctl.c	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: irixioctl.c,v 1.4 1998/03/04 12:17:41 ralf Exp $
+/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $
  * irixioctl.c: A fucking mess...
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -11,6 +11,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/tty.h>
+#include <linux/file.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctl.h>
@@ -33,15 +34,13 @@
 {
 	struct file *filp;
 
-	file = fcheck(fd);
-	if(!file)
+	if(!(filp = fcheck(fd)))
 		return ((struct tty_struct *) 0);
 	if(filp->private_data) {
 		struct tty_struct *ttyp = (struct tty_struct *) filp->private_data;
 
-		if(ttyp->magic == TTY_MAGIC) {
+		if(ttyp->magic == TTY_MAGIC)
 			return ttyp;
-		}
 	}
 	return ((struct tty_struct *) 0);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irixsig.c linux.pre11.3/arch/mips/kernel/irixsig.c
--- linux.vanilla/arch/mips/kernel/irixsig.c	Sun Nov  8 15:10:06 1998
+++ linux.pre11.3/arch/mips/kernel/irixsig.c	Mon Jul 19 23:28:45 1999
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: irixsig.c,v 1.11 1998/03/26 07:39:09 ralf Exp $
+ * $Id: irixsig.c,v 1.10.2.2 1999/06/17 12:06:39 ralf Exp $
  */
 
 #include <linux/kernel.h>
@@ -272,6 +272,7 @@
 			default:
 				lock_kernel();
 				sigaddset(&current->signal, signr);
+				recalc_sigpending(current);
 				current->flags |= PF_SIGNALED;
 				do_exit(exit_code);
 				/* NOTREACHED */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/irq.c linux.pre11.3/arch/mips/kernel/irq.c
--- linux.vanilla/arch/mips/kernel/irq.c	Mon Dec 28 23:09:40 1998
+++ linux.pre11.3/arch/mips/kernel/irq.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.13 1998/05/28 03:17:55 ralf Exp $
+/* $Id: irq.c,v 1.15 1999/02/25 21:50:49 tsbogend Exp $
  *
  * 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
@@ -12,6 +12,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
+#include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -27,9 +28,21 @@
 #include <asm/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
+#include <asm/sni.h>
 
-unsigned char cache_21 = 0xff;
-unsigned char cache_A1 = 0xff;
+/*
+ * This contains the irq mask for both 8259A irq controllers, it's an
+ * int so we can deal with the third PIC in some systems like the RM300.
+ * (XXX This is broken for big endian.)
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) (((unsigned char *)&(y))[x])
+#define __word(x,y) (((unsigned short *)&(y))[x])
+#define __long(x,y) (((unsigned int *)&(y))[x])
+
+#define cached_21       (__byte(0,cached_irq_mask))
+#define cached_A1       (__byte(1,cached_irq_mask))
 
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
@@ -39,31 +52,23 @@
  * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
  * PCI devices.  Other onboard hardware needs specific routines.
  */
-static inline void mask_irq(unsigned int irq_nr)
+static inline void mask_irq(unsigned int irq)
 {
-	unsigned char mask;
-
-	mask = 1 << (irq_nr & 7);
-	if (irq_nr < 8) {
-		cache_21 |= mask;
-		outb(cache_21,0x21);
+	cached_irq_mask |= 1 << irq;
+	if (irq & 8) {
+		outb(cached_A1, 0xa1);
 	} else {
-		cache_A1 |= mask;
-		outb(cache_A1,0xA1);
+		outb(cached_21, 0x21);
 	}
 }
 
-static inline void unmask_irq(unsigned int irq_nr)
+static inline void unmask_irq(unsigned int irq)
 {
-	unsigned char mask;
-
-	mask = ~(1 << (irq_nr & 7));
-	if (irq_nr < 8) {
-		cache_21 &= mask;
-		outb(cache_21,0x21);
+	cached_irq_mask &= ~(1 << irq);
+	if (irq & 8) {
+		outb(cached_A1, 0xa1);
 	} else {
-		cache_A1 &= mask;
-		outb(cache_A1,0xA1);
+		outb(cached_21, 0x21);
 	}
 }
 
@@ -84,13 +89,11 @@
 	restore_flags(flags);
 }
 
-/*
- * Pointers to the low-level handlers: first the general ones, then the
- * fast ones, then the bad ones.
- */
-extern void interrupt(void);
-
-static struct irqaction *irq_action[32] = {
+static struct irqaction *irq_action[NR_IRQS] = {
+	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,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@@ -122,6 +125,59 @@
 
 atomic_t __mips_bh_counter;
 
+static inline void i8259_mask_and_ack_irq(int irq)
+{
+	cached_irq_mask |= 1 << irq;
+
+	if (irq & 8) {
+		inb(0xa1);
+		outb(cached_A1, 0xa1);
+		outb(0x62, 0x20);		/* Specific EOI to cascade */
+                outb(0x20, 0xa0);
+        } else {
+		inb(0x21);
+		outb(cached_21, 0x21);
+		outb(0x20, 0x20);
+        }
+}
+
+asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+	cpu = smp_processor_id();
+	hardirq_enter(cpu);
+
+	if (irq >= 16)
+		goto out;
+
+	i8259_mask_and_ack_irq(irq);
+
+	kstat.irqs[cpu][irq]++;
+
+	action = *(irq + irq_action);
+	if (!action)
+		goto out;
+
+	if (!(action->flags & SA_INTERRUPT))
+		__sti();
+	action = *(irq + irq_action);
+	do_random = 0;
+       	do {
+		do_random |= action->flags;
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+       	} while (action);
+	if (do_random & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	__cli();
+	unmask_irq (irq);
+
+out:
+	hardirq_exit(cpu);
+}
+
 /*
  * do_IRQ handles IRQ's that have been installed without the
  * SA_INTERRUPT flag: it uses the full signal-handling return
@@ -135,23 +191,9 @@
 	int do_random, cpu;
 
 	cpu = smp_processor_id();
-	irq_enter(cpu, irq);
+	hardirq_enter(cpu);
 	kstat.irqs[cpu][irq]++;
 
-	/*
-	 * mask and ack quickly, we don't want the irq controller
-	 * thinking we're snobs just because some other CPU has
-	 * disabled global interrupts (we have already done the
-	 * INT_ACK cycles, it's too late to try to pretend to the
-	 * controller that we aren't taking the interrupt).
-	 *
-	 * Commented out because we've already done this in the
-	 * machinespecific part of the handler.  It's reasonable to
-	 * do this here in a highlevel language though because that way
-	 * we could get rid of a good part of duplicated code ...
-	 */
-        /* mask_and_ack_irq(irq); */
-
 	action = *(irq + irq_action);
 	if (action) {
 		if (!(action->flags & SA_INTERRUPT))
@@ -165,21 +207,14 @@
         	} while (action);
 		if (do_random & SA_SAMPLE_RANDOM)
 			add_interrupt_randomness(irq);
-		unmask_irq (irq);
 		__cli();
 	}
-	irq_exit(cpu, irq);
+	hardirq_exit(cpu);
 
 	/* unmasking and bottom half handling is done magically for us. */
 }
 
-/*
- * Used only for setup of PC style interrupts and therefore still
- * called setup_x86_irq.  Later on I'll provide a machine specific
- * function with similar purpose.  Idea is to put all interrupts
- * in a single table and differenciate them just by number.
- */
-int setup_x86_irq(int irq, struct irqaction * new)
+int i8259_setup_irq(int irq, struct irqaction * new)
 {
 	int shared = 0;
 	struct irqaction *old, **p;
@@ -216,11 +251,15 @@
 	return 0;
 }
 
+/*
+ * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
+ * non i8259 devices.  They will have to be replaced by architecture
+ * specific variants.  For now we still use this as broken as it is because
+ * it used to work ...
+ */
 int request_irq(unsigned int irq, 
 		void (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, 
-		const char * devname,
-		void *dev_id)
+		unsigned long irqflags, const char * devname, void *dev_id)
 {
 	int retval;
 	struct irqaction * action;
@@ -241,7 +280,7 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
-	retval = setup_x86_irq(irq, action);
+	retval = i8259_setup_irq(irq, action);
 
 	if (retval)
 		kfree(action);
@@ -275,7 +314,7 @@
 
 unsigned long probe_irq_on (void)
 {
-	unsigned int i, irqs = 0, irqmask;
+	unsigned int i, irqs = 0;
 	unsigned long delay;
 
 	/* first, enable any unassigned (E)ISA irqs */
@@ -291,19 +330,17 @@
 		/* about 100ms delay */;
 
 	/* now filter out any obviously spurious interrupts */
-	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
-	return irqs & ~irqmask;
+	return irqs & ~cached_irq_mask;
 }
 
 int probe_irq_off (unsigned long irqs)
 {
-	unsigned int i, irqmask;
+	unsigned int i;
 
-	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
 #ifdef DEBUG
 	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
 #endif
-	irqs &= irqmask;
+	irqs &= cached_irq_mask;
 	if (!irqs)
 		return 0;
 	i = ffz(~irqs);
@@ -314,13 +351,36 @@
 
 int (*irq_cannonicalize)(int irq);
 
-static int i8259a_irq_cannonicalize(int irq)
+static int i8259_irq_cannonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
 }
 
+__initfunc(static void i8259_init(void))
+{
+	/* Init master interrupt controller */
+	outb(0x11, 0x20); /* Start init sequence */
+	outb(0x00, 0x21); /* Vector base */
+	outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+	outb(0x01, 0x21); /* Select 8086 mode */
+	outb(0xff, 0x21); /* Mask all */
+        
+	/* Init slave interrupt controller */
+	outb(0x11, 0xa0); /* Start init sequence */
+	outb(0x08, 0xa1); /* Vector base */
+	outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
+	outb(0x01, 0xa1); /* Select 8086 mode */
+	outb(0xff, 0xa1); /* Mask all */
+
+	outb(cached_A1, 0xa1);
+	outb(cached_21, 0x21);
+}
+
 __initfunc(void init_IRQ(void))
 {
-	irq_cannonicalize = i8259a_irq_cannonicalize;
+	irq_cannonicalize = i8259_irq_cannonicalize;
+	/* i8259_init(); */
 	irq_setup();
 }
+
+EXPORT_SYMBOL(irq_cannonicalize);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/mips_ksyms.c linux.pre11.3/arch/mips/kernel/mips_ksyms.c
--- linux.vanilla/arch/mips/kernel/mips_ksyms.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/mips_ksyms.c	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: mips_ksyms.c,v 1.12 1998/09/16 22:50:41 ralf Exp $
+/* $Id: mips_ksyms.c,v 1.19 1999/04/11 18:37:55 harald Exp $
  *
  * Export MIPS-specific functions needed for loadable modules.
  *
@@ -13,6 +13,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <asm/irq.h>
 #include <linux/in6.h>
 #include <linux/pci.h>
 
@@ -50,23 +51,25 @@
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strpbrk);
 
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(__mips_bh_counter);
 EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
-//EXPORT_SYMBOL(enable_irq);
-//EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Userspace access stuff.
  */
-EXPORT_SYMBOL(__copy_user);
-EXPORT_SYMBOL(__bzero);
-EXPORT_SYMBOL(__strncpy_from_user_nocheck_asm);
-EXPORT_SYMBOL(__strncpy_from_user_asm);
-EXPORT_SYMBOL(__strlen_user_nocheck_asm);
-EXPORT_SYMBOL(__strlen_user_asm);
+EXPORT_SYMBOL_NOVERS(__copy_user);
+EXPORT_SYMBOL_NOVERS(__bzero);
+EXPORT_SYMBOL_NOVERS(__strncpy_from_user_nocheck_asm);
+EXPORT_SYMBOL_NOVERS(__strncpy_from_user_asm);
+EXPORT_SYMBOL_NOVERS(__strlen_user_nocheck_asm);
+EXPORT_SYMBOL_NOVERS(__strlen_user_asm);
 
 
 /* Networking helper routines. */
@@ -77,6 +80,10 @@
  */
 EXPORT_SYMBOL(flush_page_to_ram);
 EXPORT_SYMBOL(flush_cache_all);
+EXPORT_SYMBOL(dma_cache_wback_inv);
+EXPORT_SYMBOL(dma_cache_inv);
+
+EXPORT_SYMBOL(invalid_pte_table);
 
 /*
  * Base address of ports for Intel style I/O.
@@ -106,12 +113,12 @@
 int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31));
 
 #ifdef CONFIG_MIPS_FPE_MODULE
-EXPORT_SYMBOL(force_sig);
 EXPORT_SYMBOL(__compute_return_epc);
 EXPORT_SYMBOL(register_fpe);
 EXPORT_SYMBOL(unregister_fpe);
 #endif
 
-#if CONFIG_PCI
-EXPORT_SYMBOL(pci_devices);
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(screen_info);
 #endif
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/pci.c linux.pre11.3/arch/mips/kernel/pci.c
--- linux.vanilla/arch/mips/kernel/pci.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/pci.c	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.6 1998/08/19 21:53:50 ralf Exp $
+/* $Id: pci.c,v 1.8 1999/05/01 22:40:36 ralf Exp $
  *
  * 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
@@ -36,13 +36,13 @@
 }
 
 /*
- * The functions below are machine specific and must be reimplented for
+ * The functions below are machine specific and must be reimplimented for
  * each PCI chipset configuration.  We just run the hook to the machine
  * specific implementation.
  */
 void pcibios_fixup (void)
 {
-	return pci_ops->pcibios_fixup();
+	pci_ops->pcibios_fixup();
 }
 
 int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
@@ -88,11 +88,6 @@
 
 __initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
 {
-}
-
-__initfunc(char *pcibios_setup(char *str))
-{
-	return str;
 }
 
 #endif /* defined(CONFIG_PCI) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/process.c linux.pre11.3/arch/mips/kernel/process.c
--- linux.vanilla/arch/mips/kernel/process.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/process.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.11 1998/08/17 12:14:53 ralf Exp $
+/* $Id: process.c,v 1.11 1999/01/03 17:50:51 ralf Exp $
  *
  * 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
@@ -144,4 +144,41 @@
 		(current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	memcpy(&dump->regs[0], regs, sizeof(struct pt_regs));
 	memcpy(&dump->regs[EF_SIZE/4], &current->tss.fpu, sizeof(current->tss.fpu));
+}
+
+/*
+ * Create a kernel thread
+ */
+pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	long retval;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"move\t$6,$sp\n\t"
+		"move\t$4,%5\n\t"
+		"li\t$2,%1\n\t"
+		"syscall\n\t"
+		"beq\t$6,$sp,1f\n\t"
+		"subu\t$sp,32\n\t"	/* delay slot */
+		"jalr\t%4\n\t"
+		"move\t$4,%3\n\t"	/* delay slot */
+		"move\t$4,$2\n\t"
+		"li\t$2,%2\n\t"
+		"syscall\n"
+		"1:\taddiu\t$sp,32\n\t"
+		"move\t%0,$2\n\t"
+		".set\treorder"
+		:"=r" (retval)
+		:"i" (__NR_clone), "i" (__NR_exit),
+		 "r" (arg), "r" (fn),
+		 "r" (flags | CLONE_VM)
+		 /*
+		  * The called subroutine might have destroyed any of the
+		  * at, result, argument or temporary registers ...
+		  */
+		:"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+		 "$9","$10","$11","$12","$13","$14","$15","$24","$25");
+
+	return retval;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/ptrace.c linux.pre11.3/arch/mips/kernel/ptrace.c
--- linux.vanilla/arch/mips/kernel/ptrace.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/ptrace.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.11 1998/10/19 16:26:31 ralf Exp $
+/* $Id: ptrace.c,v 1.12 1999/06/13 16:30:32 ralf Exp $
  *
  * 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
@@ -259,6 +259,7 @@
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
+	unsigned int flags;
 	int res;
 
 	lock_kernel();
@@ -297,22 +298,26 @@
 		    (current->uid != child->uid) ||
 	 	    (current->gid != child->egid) ||
 		    (current->gid != child->sgid) ||
-	 	    (current->gid != child->gid)) && 
-		    !capable(CAP_SYS_PTRACE)) {
+	 	    (current->gid != child->gid) ||
+		    (!cap_issubset(child->cap_permitted,
+		                  current->cap_permitted)) ||
+                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)){
 			res = -EPERM;
 			goto out;
 		}
 		/* the same process cannot be attached many times */
-		if (child->flags & PF_PTRACED) {
-			res = -EPERM;
+		if (child->flags & PF_PTRACED)
 			goto out;
-		}
 		child->flags |= PF_PTRACED;
+
+		write_lock_irqsave(&tasklist_lock, flags);
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
 			child->p_pptr = current;
 			SET_LINKS(child);
 		}
+		write_unlock_irqrestore(&tasklist_lock, flags);
+
 		send_sig(SIGSTOP, child, 1);
 		res = 0;
 		goto out;
@@ -337,15 +342,16 @@
 	case PTRACE_PEEKDATA: {
 		unsigned long tmp;
 
+		down(&child->mm->mmap_sem);
 		res = read_long(child, addr, &tmp);
+		up(&child->mm->mmap_sem);
 		if (res < 0)
 			goto out;
 		res = put_user(tmp,(unsigned long *) data);
 		goto out;
 		}
 
-	/* read the word at location addr in the USER area. */
-/* #define DEBUG_PEEKUSR */
+	/* Read the word at location addr in the USER area.  */
 	case PTRACE_PEEKUSR: {
 		struct pt_regs *regs;
 		unsigned long tmp;
@@ -353,12 +359,15 @@
 		regs = (struct pt_regs *) ((unsigned long) child +
 		       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
 		tmp = 0;  /* Default return value. */
-		if (addr < 32 && addr >= 0)
-			tmp = regs->regs[addr];
-		else if (addr >= 32 && addr < 64) {
-			unsigned long long *fregs;
 
+		switch(addr) {
+		case 0 ... 31:
+			tmp = regs->regs[addr];
+			break;
+		case FPR_BASE ... FPR_BASE + 31:
 			if (child->used_math) {
+				unsigned long long *fregs;
+
 				if (last_task_used_math == child) {
 					enable_cp1();
 					r4xx0_save_fp(child);
@@ -371,35 +380,32 @@
 			} else {
 				tmp = -1;	/* FP not yet used  */
 			}
-		} else {
-			addr -= 64;
-			switch(addr) {
-			case 0:
-				tmp = regs->cp0_epc;
-				break;
-			case 1:
-				tmp = regs->cp0_cause;
-				break;
-			case 2:
-				tmp = regs->cp0_badvaddr;
-				break;
-			case 3:
-				tmp = regs->lo;
-				break;
-			case 4:
-				tmp = regs->hi;
-				break;
-			case 5:
-				tmp = child->tss.fpu.hard.control;
-				break;
-			case 6:	/* implementation / version register */
-				tmp = 0;	/* XXX */
-				break;
-			default:
-				tmp = 0;
-				res = -EIO;
-				goto out;
-			}
+			break;
+		case PC:
+			tmp = regs->cp0_epc;
+			break;
+		case CAUSE:
+			tmp = regs->cp0_cause;
+			break;
+		case BADVADDR:
+			tmp = regs->cp0_badvaddr;
+			break;
+		case MMHI:
+			tmp = regs->hi;
+			break;
+		case MMLO:
+			tmp = regs->lo;
+			break;
+		case FPC_CSR:
+			tmp = child->tss.fpu.hard.control;
+			break;
+		case FPC_EIR:	/* implementation / version register */
+			tmp = 0;	/* XXX */
+			break;
+		default:
+			tmp = 0;
+			res = -EIO;
+			goto out;
 		}
 		res = put_user(tmp, (unsigned long *) data);
 		goto out;
@@ -407,20 +413,22 @@
 
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
+		down(&child->mm->mmap_sem);
 		res = write_long(child,addr,data);
+		up(&child->mm->mmap_sem);
 		goto out;
 
 	case PTRACE_POKEUSR: {
+		unsigned long long *fregs;
 		struct pt_regs *regs;
 		int res = 0;
 
-		regs = (struct pt_regs *) ((unsigned long) child +
-		       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
-		if (addr < 32 && addr >= 0)
-			regs->regs[addr] = data;
-		else if (addr >= 32 && addr < 64) {
-			unsigned long long *fregs;
-
+		switch (addr) {
+		case 0 ... 31:
+			regs = (struct pt_regs *) ((unsigned long) child +
+			       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
+			break;
+		case FPR_BASE ... FPR_BASE + 31:
 			if (child->used_math) {
 				if (last_task_used_math == child) {
 					enable_cp1();
@@ -437,26 +445,23 @@
 			fregs = (unsigned long long *)
 				&child->tss.fpu.hard.fp_regs[0];
 			fregs[(addr - 32)] = (unsigned long long) data;
-		} else {
-			addr -= 64;
-			switch (addr) {
-			case 0:
-				regs->cp0_epc = data;
-				break;
-			case 3:
-				regs->lo = data;
-				break;
-			case 4:
-				regs->hi = data;
-				break;
-			case 5:
-				child->tss.fpu.hard.control = data;
-				break;
-			default:
-				/* The rest are not allowed. */
-				res = -EIO;
-				break;
-			};
+			break;
+		case PC:
+			regs->cp0_epc = data;
+			break;
+		case MMHI:
+			regs->hi = data;
+			break;
+		case MMLO:
+			regs->lo = data;
+			break;
+		case FPC_CSR:
+			child->tss.fpu.hard.control = data;
+			break;
+		default:
+			/* The rest are not allowed. */
+			res = -EIO;
+			break;
 		}
 		goto out;
 		}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r2300_fpu.S linux.pre11.3/arch/mips/kernel/r2300_fpu.S
--- linux.vanilla/arch/mips/kernel/r2300_fpu.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/r2300_fpu.S	Mon Jul 19 23:28:42 1999
@@ -1,16 +1,17 @@
-/*
+/* $Id: r2300_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $
  * r2300_fpu.S: Save/restore floating point context for signal handlers.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 1998 by Ralf Baechle
  *
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r2300_fpu.S,v 1.3 1997/12/01 16:54:20 ralf Exp $
+ * Further modifications to make this work:
+ * Copyright (c) 1998 Harald Koerfgen
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
@@ -18,123 +19,103 @@
 #include <asm/offset.h>
 #include <asm/regdef.h>
 
-	.set	mips3
+#define EX(a,b)							\
+9:	a,##b;							\
+	.section __ex_table,"a";				\
+	PTR	9b,bad_stack;					\
+	.previous
+
 	.set	noreorder
+	.set	mips1
 	/* Save floating point context */
-	.align	5
-	LEAF(r2300_save_fp_context)
-	mfc0	t0,CP0_STATUS
-	sll	t0,t0,2
-
-	bgez	t0,1f
-	 nop
-
-	cfc1	t0,fcr31
-	/* Store the 32 single precision registers */
-	swc1	$f0,(SC_FPREGS+0)(a0)
-	swc1	$f1,(SC_FPREGS+8)(a0)
-	swc1	$f2,(SC_FPREGS+16)(a0)
-	swc1	$f3,(SC_FPREGS+24)(a0)
-	swc1	$f4,(SC_FPREGS+32)(a0)
-	swc1	$f5,(SC_FPREGS+40)(a0)
-	swc1	$f6,(SC_FPREGS+48)(a0)
-	swc1	$f7,(SC_FPREGS+56)(a0)
-	swc1	$f8,(SC_FPREGS+64)(a0)
-	swc1	$f9,(SC_FPREGS+72)(a0)
-	swc1	$f10,(SC_FPREGS+80)(a0)
-	swc1	$f11,(SC_FPREGS+88)(a0)
-	swc1	$f12,(SC_FPREGS+96)(a0)
-	swc1	$f13,(SC_FPREGS+104)(a0)
-	swc1	$f14,(SC_FPREGS+112)(a0)
-	swc1	$f15,(SC_FPREGS+120)(a0)
-	swc1	$f16,(SC_FPREGS+128)(a0)
-	swc1	$f17,(SC_FPREGS+136)(a0)
-	swc1	$f18,(SC_FPREGS+144)(a0)
-	swc1	$f19,(SC_FPREGS+152)(a0)
-	swc1	$f20,(SC_FPREGS+160)(a0)
-	swc1	$f21,(SC_FPREGS+168)(a0)
-	swc1	$f22,(SC_FPREGS+176)(a0)
-	swc1	$f23,(SC_FPREGS+184)(a0)
-	swc1	$f24,(SC_FPREGS+192)(a0)
-	swc1	$f25,(SC_FPREGS+200)(a0)
-	swc1	$f26,(SC_FPREGS+208)(a0)
-	swc1	$f27,(SC_FPREGS+216)(a0)
-	swc1	$f28,(SC_FPREGS+224)(a0)
-	swc1	$f29,(SC_FPREGS+232)(a0)
-	swc1	$f30,(SC_FPREGS+240)(a0)
-	swc1	$f31,(SC_FPREGS+248)(a0)
-	sw	t0,SC_FPC_CSR(a0)
+LEAF(r2300_save_fp_context)
+
+	cfc1	t1,fcr31
+	EX(swc1	$f0,(SC_FPREGS+0)(a0))
+	EX(swc1	$f1,(SC_FPREGS+8)(a0))
+	EX(swc1	$f2,(SC_FPREGS+16)(a0))
+	EX(swc1	$f3,(SC_FPREGS+24)(a0))
+	EX(swc1	$f4,(SC_FPREGS+32)(a0))
+	EX(swc1	$f5,(SC_FPREGS+40)(a0))
+	EX(swc1	$f6,(SC_FPREGS+48)(a0))
+	EX(swc1	$f7,(SC_FPREGS+56)(a0))
+	EX(swc1	$f8,(SC_FPREGS+64)(a0))
+	EX(swc1	$f9,(SC_FPREGS+72)(a0))
+	EX(swc1	$f10,(SC_FPREGS+80)(a0))
+	EX(swc1	$f11,(SC_FPREGS+88)(a0))
+	EX(swc1	$f12,(SC_FPREGS+96)(a0))
+	EX(swc1	$f13,(SC_FPREGS+104)(a0))
+	EX(swc1	$f14,(SC_FPREGS+112)(a0))
+	EX(swc1	$f15,(SC_FPREGS+120)(a0))
+	EX(swc1	$f16,(SC_FPREGS+128)(a0))
+	EX(swc1	$f17,(SC_FPREGS+136)(a0))
+	EX(swc1	$f18,(SC_FPREGS+144)(a0))
+	EX(swc1	$f19,(SC_FPREGS+152)(a0))
+	EX(swc1	$f20,(SC_FPREGS+160)(a0))
+	EX(swc1	$f21,(SC_FPREGS+168)(a0))
+	EX(swc1	$f22,(SC_FPREGS+176)(a0))
+	EX(swc1	$f23,(SC_FPREGS+184)(a0))
+	EX(swc1	$f24,(SC_FPREGS+192)(a0))
+	EX(swc1	$f25,(SC_FPREGS+200)(a0))
+	EX(swc1	$f26,(SC_FPREGS+208)(a0))
+	EX(swc1	$f27,(SC_FPREGS+216)(a0))
+	EX(swc1	$f28,(SC_FPREGS+224)(a0))
+	EX(swc1	$f29,(SC_FPREGS+232)(a0))
+	EX(swc1	$f30,(SC_FPREGS+240)(a0))
+	EX(swc1	$f31,(SC_FPREGS+248)(a0))
+	EX(sw	t1,SC_FPC_CSR(a0))
 	cfc1	t0,$0				# implementation/version
 	jr	ra
 	.set	nomacro
-	 sw	t0,SC_FPC_EIR(a0)
-	.set	macro
-1:
-	jr	ra
-	.set	nomacro
-	 nop
+	 EX(sw	t0,SC_FPC_EIR(a0))
 	.set	macro
 	END(r2300_save_fp_context)
 
 /*
- * Restore fpu state:
+ * Restore FPU state:
  *  - fp gp registers
  *  - cp1 status/control register
  *
- * We base the decission which registers to restore from the signal stack
+ * We base the decision which registers to restore from the signal stack
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-	LEAF(r2300_restore_fp_context)
-	mfc0	t0,CP0_STATUS
-	sll	t0,t0,2
-
-	bgez	t0,1f
-	 nop
-
-	 lw	t0,SC_FPC_CSR(a0)
-	/* Restore the 16 odd double precision registers only
-	 * when enabled in the cp0 status register.
-	 */
-	ldc1	$f0,(SC_FPREGS+0)(a0)
-	ldc1	$f1,(SC_FPREGS+8)(a0)
-	ldc1	$f2,(SC_FPREGS+16)(a0)
-	ldc1	$f3,(SC_FPREGS+24)(a0)
-	ldc1	$f4,(SC_FPREGS+32)(a0)
-	ldc1	$f5,(SC_FPREGS+40)(a0)
-	ldc1	$f6,(SC_FPREGS+48)(a0)
-	ldc1	$f7,(SC_FPREGS+56)(a0)
-	ldc1	$f8,(SC_FPREGS+64)(a0)
-	ldc1	$f9,(SC_FPREGS+72)(a0)
-	ldc1	$f10,(SC_FPREGS+80)(a0)
-	ldc1	$f11,(SC_FPREGS+88)(a0)
-	ldc1	$f12,(SC_FPREGS+96)(a0)
-	ldc1	$f13,(SC_FPREGS+104)(a0)
-	ldc1	$f14,(SC_FPREGS+112)(a0)
-	ldc1	$f15,(SC_FPREGS+120)(a0)
-	ldc1	$f16,(SC_FPREGS+128)(a0)
-	ldc1	$f17,(SC_FPREGS+136)(a0)
-	ldc1	$f18,(SC_FPREGS+144)(a0)
-	ldc1	$f19,(SC_FPREGS+152)(a0)
-	ldc1	$f20,(SC_FPREGS+160)(a0)
-	ldc1	$f21,(SC_FPREGS+168)(a0)
-	ldc1	$f22,(SC_FPREGS+176)(a0)
-	ldc1	$f23,(SC_FPREGS+184)(a0)
-	ldc1	$f24,(SC_FPREGS+192)(a0)
-	ldc1	$f25,(SC_FPREGS+200)(a0)
-	ldc1	$f26,(SC_FPREGS+208)(a0)
-	ldc1	$f27,(SC_FPREGS+216)(a0)
-	ldc1	$f28,(SC_FPREGS+224)(a0)
-	ldc1	$f29,(SC_FPREGS+232)(a0)
-	ldc1	$f30,(SC_FPREGS+240)(a0)
-	ldc1	$f31,(SC_FPREGS+248)(a0)
+LEAF(r2300_restore_fp_context)
+	EX(lw t0,SC_FPC_CSR(a0))
+	EX(lwc1	$f0,(SC_FPREGS+0)(a0))
+	EX(lwc1	$f1,(SC_FPREGS+8)(a0))
+	EX(lwc1	$f2,(SC_FPREGS+16)(a0))
+	EX(lwc1	$f3,(SC_FPREGS+24)(a0))
+	EX(lwc1	$f4,(SC_FPREGS+32)(a0))
+	EX(lwc1	$f5,(SC_FPREGS+40)(a0))
+	EX(lwc1	$f6,(SC_FPREGS+48)(a0))
+	EX(lwc1	$f7,(SC_FPREGS+56)(a0))
+	EX(lwc1	$f8,(SC_FPREGS+64)(a0))
+	EX(lwc1	$f9,(SC_FPREGS+72)(a0))
+	EX(lwc1	$f10,(SC_FPREGS+80)(a0))
+	EX(lwc1	$f11,(SC_FPREGS+88)(a0))
+	EX(lwc1	$f12,(SC_FPREGS+96)(a0))
+	EX(lwc1	$f13,(SC_FPREGS+104)(a0))
+	EX(lwc1	$f14,(SC_FPREGS+112)(a0))
+	EX(lwc1	$f15,(SC_FPREGS+120)(a0))
+	EX(lwc1	$f16,(SC_FPREGS+128)(a0))
+	EX(lwc1	$f17,(SC_FPREGS+136)(a0))
+	EX(lwc1	$f18,(SC_FPREGS+144)(a0))
+	EX(lwc1	$f19,(SC_FPREGS+152)(a0))
+	EX(lwc1	$f20,(SC_FPREGS+160)(a0))
+	EX(lwc1	$f21,(SC_FPREGS+168)(a0))
+	EX(lwc1	$f22,(SC_FPREGS+176)(a0))
+	EX(lwc1	$f23,(SC_FPREGS+184)(a0))
+	EX(lwc1	$f24,(SC_FPREGS+192)(a0))
+	EX(lwc1	$f25,(SC_FPREGS+200)(a0))
+	EX(lwc1	$f26,(SC_FPREGS+208)(a0))
+	EX(lwc1	$f27,(SC_FPREGS+216)(a0))
+	EX(lwc1	$f28,(SC_FPREGS+224)(a0))
+	EX(lwc1	$f29,(SC_FPREGS+232)(a0))
+	EX(lwc1	$f30,(SC_FPREGS+240)(a0))
+	EX(lwc1	$f31,(SC_FPREGS+248)(a0))
 	jr	ra
-	.set	nomacro
 	 ctc1	t0,fcr31
-	.set	macro
-1:
-	jr	ra
-	.set	nomacro
-	 nop
-	.set	macro
 	END(r2300_restore_fp_context)
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r2300_misc.S linux.pre11.3/arch/mips/kernel/r2300_misc.S
--- linux.vanilla/arch/mips/kernel/r2300_misc.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/r2300_misc.S	Mon Jul 19 23:53:55 1999
@@ -1,14 +1,17 @@
-/* $Id: r2300_misc.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $
+/* $Id: r2300_misc.S,v 1.3 1999/05/01 22:40:36 ralf Exp $
  * r2300_misc.S: Misc. exception handling code for R3000/R2000.
  *
  * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
  *
- * Multi-cpu abstraction reworking:
+ * Multi-CPU abstraction reworking:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Further modifications to make this work:
+ * Copyright (c) 1998 Harald Koerfgen
+ * Copyright (c) 1998 Gleb Raiko & Vladimir Roganov
  */
-#include <linux/config.h>
-
 #include <asm/asm.h>
+#include <asm/current.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
 #include <asm/fpregdef.h>
@@ -18,380 +21,175 @@
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/regdef.h>
+#include <asm/segment.h>
 #include <asm/stackframe.h>
 
 	.text
 	.set	mips1
 	.set	noreorder
 
-	.align	5
-	NESTED(r2300_handle_tlbl, PT_SIZE, sp)
-	.set	noat
-	/* Check whether this is a refill or an invalid exception */
-	mfc0	k0,CP0_BADVADDR
-	mfc0	k1,CP0_ENTRYHI
-	ori	k0,0xfff			# clear ASID...
-	xori	k0,0xfff			# in BadVAddr
-	andi	k1,0xfc0			# get current ASID
-	or	k0,k1				# make new entryhi
-	mfc0	k1,CP0_ENTRYHI
-	mtc0	k0,CP0_ENTRYHI
-	nop					# for pipeline
-	nop
-	nop
-	tlbp
-	nop					# for pipeline
-	nop
-	mfc0	k0,CP0_INDEX
-
-	bgez	k0,invalid_tlbl			# bad addr in c0_badvaddr
-	 mtc0	k1,CP0_ENTRYHI
-
-	/* Damn... The next nop is required on the R4400PC V5.0, but
-	 * I don't know why - at least there is no documented
-	 * reason as for the others :-(
-	 * And I haven't tested it as being necessary on R3000 - PMA.
-	 * (The R3000 pipeline has only 5 stages, so it's probably not
-	 * required -- Ralf)
-	 */
-	nop
-
-#ifdef CONF_DEBUG_TLB
-	/* OK, this is a double fault. Let's see whether this is
-	 * due to an invalid entry in the page_table.
-	 */
-	/* used to be dmfc0 */
-	mfc0	k0,CP0_BADVADDR
-	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
-	 *        and I suspect that it should be different for
-	 *	  the R[23]000.  PMA
-	 *        (No, it's the assembler way to do
-	 *            k0 = k0 / PAGE_SIZE;
-	 *            k0 = k0 * sizeof(pte_t)
-	 *        Acutally the R4xx0 code will have to change when
-	 *        switching to 64 bit ... -- Ralf)
-	 */
-	srl	k0,12				# get PFN?
-	sll	k0,2
-	lui	k1,%HI(TLBMAP)
-	addu	k0,k1
-	lw	k1,(k0)
-	andi	k1,(_PAGE_PRESENT|_PAGE_ACCESSED)
-	bnez	k1,reload_pgd_entries
-	 nop
-
-	.set	noat
-	SAVE_ALL
-	.set	at
-	PRINT("Double fault caused by invalid entries in pgd:\n")
-	mfc0	a1,CP0_BADVADDR
-	PRINT("Double fault address     : %08lx\n")
-	mfc0	a1,CP0_EPC
-	PRINT("c0_epc                   : %08lx\n")
-
-	jal	show_regs
-	 move	a0,sp
+#undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */
 
-	jal	dump_tlb_nonwired
-	 nop
+	/* ABUSE of CPP macros 101. */
 
-	mfc0	a0,CP0_BADVADDR
+	/* After this macro runs, the pte faulted on is
+	 * in register PTE, a ptr into the table in which
+	 * the pte belongs is in PTR.
+	 */
+#define LOAD_PTE(pte, ptr) \
+	mfc0	pte, CP0_BADVADDR; \
+	_GET_CURRENT(ptr); \
+	srl	pte, pte, 22; \
+	lw	ptr, THREAD_PGDIR(ptr); \
+	sll	pte, pte, 2; \
+	addu	ptr, pte, ptr; \
+	mfc0	pte, CP0_CONTEXT; \
+	lw	ptr, (ptr); \
+	andi	pte, pte, 0xffc; \
+	addu	ptr, ptr, pte; \
+	lw	pte, (ptr); \
+	nop;
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr) \
+	lw	ptr, (ptr)	; \
+	nop			; \
+	mtc0	ptr, CP0_ENTRYLO0; \
+	nop;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	.set	macro; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_sys_call; \
+	 nop; \
+	.set	noat; \
+	.set	nomacro;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	.set	push;       \
+	.set	reorder;    \
+	 lw	pte, (ptr); \
+	.set	pop; 
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	sw	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	.set    push;       \
+	.set    reorder;    \
+	lw      pte, (ptr); \
+	.set    pop;
+ 
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	sw	pte, (ptr);
 
-	jal	dump_list_current
-	 nop
+	.set	noreorder
 
+	.align	5
+NESTED(r2300_handle_tlbl, PT_SIZE, sp)
 	.set	noat
-	STI
-	.set	at
-	PANIC("Corrupted pagedir")
-	.set	noat
-
-reload_pgd_entries:
-#endif /* CONF_DEBUG_TLB */
 
-	/* Load missing pair of entries from the pgd and return. */
-	mfc0	k1,CP0_CONTEXT
-	lw	k0,(k1)			# Never causes nested exception
-	mfc0	k1,CP0_EPC		# get the return PC
-	srl	k0,12			# Convert to EntryLo format
-	mtc0	k0,CP0_ENTRYLO0
-	nop				# for pipeline
-	tlbwr
-	nop				# for pipeline
+#ifndef NOTLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+        tlbp
 	nop
+        PTE_PRESENT(k0, k1, nopage_tlbl)
+        PTE_MAKEVALID(k0, k1)
+        PTE_RELOAD(k1)
+	tlbwi
 	nop
-	/* We don't know whether the original access was read or
-	 * write, so return and see what happens...
-	 */
-	jr	k1
-	 rfe
-
-	/* Handle invalid exception
-	 *
-	 * There are two possible causes for an invalid (tlbl)
-	 * exception:
-	 * 1) pages with present bit set but the valid bit clear
-	 * 2) nonexistant pages
-	 * Case one needs fast handling, therefore don't save
-	 * registers yet.
-	 *
-	 * k0 contains c0_index.
-	 */
-invalid_tlbl:	
-#ifdef CONFIG_TLB_SHUTDOWN
-	/* Remove entry so we don't need to care later
-	 * For sake of the pipeline the tlbwi insn has been moved down.
-	 * Moving it around is juggling with explosives...
-	 */
-	/* FIXME: Why is Ralf setting bit 3 of k1?  This may need to
-	 *	  be changed for R[236]000! PMA
-	 *        (The new ENTRYHI value will then point represent a
-	 *        inique virtual address outside the 32 bit address
-	 *        limit.  This is just paranoia to avoid a tlb
-	 *        shutdown.  This whole part of the routine is probably
-	 *        no longer required and can be removed -- Ralf)
-	 */
-	lui	k1,0x0008
-	or	k0,k1
-	sll	k0,12				# make it EntryHi format
-	mtc0	k0,CP0_ENTRYHI
-	mtc0	zero,CP0_ENTRYLO0
-#endif
-	/* Test present bit in entry */
-	mfc0	k0,CP0_BADVADDR
-	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
-	 *        and I suspect that it should be different for
-	 *	  the R[23]000.  PMA
-	 *        (No, it's the assembler way to do
-	 *            k0 = k0 / PAGE_SIZE;
-	 *            k0 = k0 * sizeof(pte_t)
-	 *        Acutally the R4xx0 code will have to change when
-	 *        switching to 64 bit ... -- Ralf)
-	 */
-	srl	k0,12
-	sll	k0,2
-#ifdef CONFIG_TLB_SHUTDOWN
-	tlbwi						# do not move!
-#endif
-	lui	k1,%HI(TLBMAP)
-	addu	k0,k1
-	lw	k1,(k0)
-	andi	k1,(_PAGE_PRESENT|_PAGE_READ)
-	xori	k1,(_PAGE_PRESENT|_PAGE_READ)
-
-	bnez	k1,nopage_tlbl
-	 lw	k1,(k0)
-
-	/* Present and read bits are set -> set valid and accessed bits */
-	ori	k1,(_PAGE_VALID|_PAGE_ACCESSED)
-	sw	k1,(k0)
-	mfc0	k1,CP0_EPC
+	mfc0	k0, CP0_EPC
 	nop
-
-	jr	k1
+	jr	k0
 	 rfe
-
-	/* Page doesn't exist. Lots of work which is less important
-	 * for speed needs to be done, so hand it all over to the
-	 * kernel memory management routines.
-	 */
 nopage_tlbl:
-	SAVE_ALL
-	mfc0	a2,CP0_BADVADDR
-	STI
-	.set	at
-	/* a0 (struct pt_regs *) regs
-	 * a1 (unsigned long)    0 for read access
-	 * a2 (unsigned long)    faulting virtual address
-	 */
-	move	a0,sp
-	jal	do_page_fault
-	 li	a1,0
-
-	j	ret_from_sys_call
-	 nop
-	END(r2300_handle_tlbl)
+#endif
 
+	DO_FAULT(0)
+END(r2300_handle_tlbl)
 
-	.text
-	.align	5
-	NESTED(r2300_handle_tlbs, PT_SIZE, sp)
+NESTED(r2300_handle_tlbs, PT_SIZE, sp)
 	.set	noat
-	/* It is impossible that is a nested reload exception.
-	 * Therefore this must be a invalid exception.
-	 * Two possible cases:
-	 * 1) Page exists but not dirty.
-	 * 2) Page doesn't exist yet. Hand over to the kernel.
-	 *
-	 * Test whether present bit in entry is set
-	 */
-	/* used to be dmfc0 */
-	mfc0	k0,CP0_BADVADDR
-	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
-	 *        and I suspect that it should be different for
-	 *	  the R[23]000.  PMA
-	 */
-	srl	k0,12
-	sll	k0,2
-	lui	k1,%HI(TLBMAP)
-	addu	k0,k1
-	lw	k1,(k0)
-	tlbp					# find faulting entry
-	andi	k1,(_PAGE_PRESENT|_PAGE_WRITE)
-	xori	k1,(_PAGE_PRESENT|_PAGE_WRITE)
 
-	bnez	k1,nopage_tlbs
-	 lw	k1,(k0)
-
-	/* Present and writable bits set: set accessed and dirty bits. */
-	ori	k1,k1,(_PAGE_ACCESSED|_PAGE_MODIFIED| \
-		       _PAGE_VALID|_PAGE_DIRTY)
-	sw	k1,(k0)
-	/* Now reload the entry into the TLB */
-	/* FIXME: Why has Ralf set bit 2?  Should it be different for
-	 *	  R[23]000?  PMA
-	 *        (The ori/xori combination actually _clears_ bit 2.
-	 *        This is required for the R4xx0 these CPUs always
-	 *        map page pairs; a page pair of 4k pages therfore
-	 *        has always an address with bit 2 set to zero. -- Ralf)
-	 */
-	ori	k0,0x0004
-	xori	k0,0x0004
-	lw	k0,(k0)
-	srl	k0,12
-	mtc0	k0,CP0_ENTRYLO0
-	mfc0	k1,CP0_EPC
-	nop				# for pipeline
+#ifndef NOTLB_OPTIMIZE
+	LOAD_PTE(k0, k1)
+	tlbp                            # find faulting entry
+	nop
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_RELOAD(k1)
 	tlbwi
-	nop				# for pipeline
 	nop
+	mfc0	k0, CP0_EPC
 	nop
-
-	jr	k1
+	jr	k0
 	 rfe
-
-	/* Page doesn't exist. Lots of work which is less important
-	 * for speed needs to be done, so hand it all over to the
-	 * kernel memory management routines.
-	 */
 nopage_tlbs:
-nowrite_mod:
-#ifdef CONFIG_TLB_SHUTDOWN
-	/* Remove entry so we don't need to care later */
-	mfc0	k0,CP0_INDEX
-#ifdef CONF_DEBUG_TLB
-	bgez	k0,2f
-	 nop
-	/* We got a tlbs exception but found no matching entry in
-	 * the tlb.  This should never happen.  Paranoia makes us
-	 * check it, though.
-	 */
-	SAVE_ALL
-	jal	show_regs
-	 move	a0,sp
-	.set	at
-	mfc0	a1,CP0_BADVADDR
-	PRINT("c0_badvaddr == %08lx\n")
-	mfc0	a1,CP0_INDEX
-	PRINT("c0_index    == %08x\n")
-	mfc0	a1,CP0_ENTRYHI
-	PRINT("c0_entryhi  == %08x\n")
-	.set	noat
-	STI
-	.set	at
-	PANIC("Tlbs or tlbm exception with no matching entry in tlb")
-1:
-	j	1b
-	 nop
-2:
-#endif /* CONF_DEBUG_TLB */
-	/* FIXME: Why is Ralf setting bit 3 of k1?  This may need to
-	 *	  be changed for R[236]000! PMA
-	 *        (The new ENTRYHI value will then point represent a
-	 *        inique virtual address outside the 32 bit address
-	 *        limit.  This is just paranoia to avoid a tlb
-	 *        shutdown.  This whole part of the routine is probably
-	 *        no longer required and can be removed -- Ralf)
-	 */
-	lui	k1,0x0008
-	or	k0,k1
-	sll	k0,12
-	mtc0	k0,CP0_ENTRYHI
-	mtc0	zero,CP0_ENTRYLO0
-	nop				# for pipeline
-	nop				# R4000 V2.2 requires 4 NOPs
-	nop
-	nop
-	tlbwi
-#endif /* CONFIG_TLB_SHUTDOWN */
-	.set	noat
-	SAVE_ALL
-	mfc0	a2,CP0_BADVADDR
-	STI
-	.set	at
-	/* a0 (struct pt_regs *) regs
-	 * a1 (unsigned long)    1 for write access
-	 * a2 (unsigned long)    faulting virtual address
-	 */
-	move	a0,sp
-	jal	do_page_fault
-	 li	a1,1
-
-	j	ret_from_sys_call
-	 nop
-	END(r2300_handle_tlbs)
+#endif
 
+	DO_FAULT(1)
+END(r2300_handle_tlbs)
 
 	.align	5
-	NESTED(r2300_handle_mod, PT_SIZE, sp)
+NESTED(r2300_handle_mod, PT_SIZE, sp)
 	.set	noat
-	/* Two possible cases:
-	 * 1) Page is writable but not dirty -> set dirty and return
-	 * 2) Page is not writable -> call C handler
-	 */
-	/* used to be dmfc0 */
-	mfc0	k0,CP0_BADVADDR
-	/* FIXME: This srl/sll sequence is as it is for the R4xx0,
-	 *        and I suspect that it should be different for
-	 *	  the R[23]000.  PMA
-	 */
-	srl	k0,12
-	sll	k0,2
-	lui	k1,%HI(TLBMAP)
-	addu	k0,k1
-	lw	k1,(k0)
+#ifndef NOTLB_OPTIMIZE
+	LOAD_PTE(k0, k1)
 	tlbp					# find faulting entry
-	andi	k1,_PAGE_WRITE
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	.set	push
+	.set    reorder
+	lw	k0, (k1)
+	.set    pop
 
-	beqz	k1,nowrite_mod
-	 lw	k1,(k0)
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
 
-	/* Present and writable bits set: set accessed and dirty bits. */
-	ori	k1,(_PAGE_ACCESSED|_PAGE_DIRTY)
-	sw	k1,(k0)
-	/* Now reload the entry into the tlb */
-	/* FIXME: Why has Ralf set bit 2?  Should it be different for
-	 *	  R[23]000?  PMA
-	 *        (The ori/xori combination actually _clears_ bit 2.
-	 *        This is required for the R4xx0 these CPUs always
-	 *        map page pairs; a page pair of 4k pages therfore
-	 *        has always an address with bit 2 set to zero. -- Ralf)
-	 */
-	ori	k0,0x0004
-	xori	k0,0x0004
-	lw	k0,(k0)
-	srl	k0,12
-	mtc0	k0,CP0_ENTRYLO0
-	mfc0	k1,CP0_EPC
-	nop				# for pipeline
-	nop
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1)
 	nop
 	tlbwi
-	nop				# for pipeline
 	nop
+	mfc0	k0, CP0_EPC
 	nop
-
-	jr	k1
+	jr	k0
 	 rfe
-	END(r2300_handle_mod)
-	.set	at
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+END(r2300_handle_mod)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r2300_switch.S linux.pre11.3/arch/mips/kernel/r2300_switch.S
--- linux.vanilla/arch/mips/kernel/r2300_switch.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/r2300_switch.S	Mon Jul 19 23:28:45 1999
@@ -1,12 +1,15 @@
-/*
- * r2300_switch.S: R3000/R2000 specific task switching code.
+/* $Id: r2300_switch.S,v 1.6 1999/06/13 16:30:32 ralf Exp $
+ *
+ * r2300_switch.S: R2300 specific task switching code.
  *
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Andreas Busse
  *
  * Multi-cpu abstraction and macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r2300_switch.S,v 1.4 1998/04/04 13:59:38 ralf Exp $
+ * Further modifications to make this work:
+ * Copyright (c) 1998 Harald Koerfgen
  */
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
@@ -15,6 +18,7 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsconfig.h>
 #include <asm/mipsregs.h>
+#include <asm/offset.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -23,68 +27,137 @@
 
 #include <asm/asmmacro.h>
 
-/* XXX The following is fucking losing... find a better way dave. */
-MODE_ALIAS	=	0x00e0			# uncachable, dirty, valid
-
-	.text
 	.set	mips1
-	.set	noreorder
+	.align	5
+
 /*
- * Code necessary to switch tasks on an Linux/MIPS machine.
- * FIXME: We don't need to disable interrupts anymore.
+ * task_struct *r4xx0_resume(task_struct *prev,
+ *                           task_struct *next)
  */
-	.align	5
-	LEAF(r2300_resume)
-	mfc0	t1,CP0_STATUS		# Save status register
-	sw	t1,THREAD_STATUS($28)
-	ori	t2,t1,0x1f		# Disable interrupts
-	xori	t2,0x1e
-	mtc0	t2,CP0_STATUS
-	CPU_SAVE_NONSCRATCH($28)
-	sll	t2,t1,2			# Save floating point state
-	bgez	t2,1f
-	 sw	ra,THREAD_REG31($28)
-	FPU_SAVE($28, t0)
-1:
-	move	$28, a0
-	lw	t0,THREAD_PGDIR($28)	# Switch the root pointer
-	li	t1,TLB_ROOT		# get PFN
-	mtc0	t1,CP0_ENTRYHI
-	mtc0	zero,CP0_INDEX
-	srl	t0,12			# PFN is 12 bits west
-	ori	t0,MODE_ALIAS		# want uncachable, dirty, valid
-	mtc0	t0,CP0_ENTRYLO0
-	lw	a2,THREAD_STATUS($28)
-	tlbwi
-
-	/* Flush TLB. */
-	mfc0	t3,CP0_STATUS		# disable interrupts...
-	ori	t4,t3,1
-	xori	t4,1
-	mtc0	t4,CP0_STATUS
-	lw      t0,mips_tlb_entries
-	mtc0	zero,CP0_ENTRYLO0
-1:
-	subu	t0,1
-	mtc0	t0,CP0_INDEX
-	lui	t1,0x0008
-	or	t1,t0,t1
-	sll	t1,12
-	mtc0	t1,CP0_ENTRYHI
-	bne	t2,t0,1b
-	 tlbwi
-
-	ori	t1,a2,1			# Restore FPU, pipeline magic
-	xori	t1,1
-	mtc0	t1,CP0_STATUS
-	sll	t0,a2,2
-	bgez	t0,1f
-	 lw	ra,THREAD_REG31($28)
-	FPU_RESTORE($28, t0)
-1:
+LEAF(r2300_resume)
+	.set	reorder
+	mfc0	t1, CP0_STATUS
+	.set	noreorder
+	sw	t1, THREAD_STATUS(a0)
+	CPU_SAVE_NONSCRATCH(a0)
+	sw	ra, THREAD_REG31(a0)
+
+	/*
+	 * The order of restoring the registers takes care of the race
+	 * updating $28, $29 and kernelsp without disabling ints.
+	 */
+	move	$28, a1
 	CPU_RESTORE_NONSCRATCH($28)
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
-	sw	t0,kernelsp
+	sw	t0, kernelsp
+	mfc0	t1, CP0_STATUS		/* Do we really need this? */
+	li	a3, 0xff00
+	and	t1, a3
+	lw	a2, THREAD_STATUS($28)
+	nor	a3, $0, a3
+	and	a2, a3
+	lw	a3, TASK_MM($28)
+	or	a2, t1
+	lw	a3, MM_CONTEXT(a3)
+	mtc0	a2, CP0_STATUS
+	andi	a3, 0xfc0
+	mtc0	a3, CP0_ENTRYHI
 	jr	ra
-	 mtc0	a2,CP0_STATUS			# Restore status register
+	 move	v0, a0
 	END(r2300_resume)
+
+/*
+ * Do lazy fpu context switch.  Saves FPU context to the process in a0
+ * and loads the new context of the current process.
+ */
+
+#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS)
+
+LEAF(r2300_lazy_fpu_switch)
+	mfc0	t0, CP0_STATUS			# enable cp1
+	li	t3, 0x20000000
+	or	t0, t3
+	mtc0	t0, CP0_STATUS
+
+	beqz	a0, 2f				# Save floating point state
+	 nor	t3, zero, t3
+	.set	reorder
+	lw	t1, ST_OFF(a0)			# last thread looses fpu
+	.set	noreorder
+	and	t1, t3
+	sw	t1, ST_OFF(a0)
+	swc1	$f0, (THREAD_FPU + 0x00)(a0)
+	FPU_SAVE(a0, t1)			# clobbers t1
+
+2:
+	lwc1	$f0, (THREAD_FPU + 0x00)($28)
+	.set	reorder
+	FPU_RESTORE($28, t0)		# clobbers t0
+	jr	ra
+	END(r2300_lazy_fpu_switch)
+
+/*
+ * Save a thread's fp context.
+ */
+	.set	noreorder
+LEAF(r2300_save_fp)
+	FPU_SAVE(a0, t1)			# clobbers t1
+	jr	ra
+	 swc1	$f0, (THREAD_FPU + 0x00)(a0)
+	END(r2300_save_fp)
+
+/*
+ * Load the FPU with signalling NANS.  This bit pattern we're using has
+ * the property that no matter wether considered as single or as double
+ * precission represents signaling NANS.
+ *
+ * We initialize fcr31 to rounding to nearest, no exceptions.
+ */
+
+#define FPU_DEFAULT  0x00000000
+
+LEAF(r2300_init_fpu)
+	mfc0	t0, CP0_STATUS
+	li	t1, 0x20000000
+	or	t0, t1
+	mtc0	t0, CP0_STATUS
+
+	li	t1, FPU_DEFAULT
+	ctc1	t1, fcr31
+
+	li	t0, -1
+
+	mtc1	t0, $f0
+	mtc1	t0, $f1
+	mtc1	t0, $f2
+	mtc1	t0, $f3
+	mtc1	t0, $f4
+	mtc1	t0, $f5
+	mtc1	t0, $f6
+	mtc1	t0, $f7
+	mtc1	t0, $f8
+	mtc1	t0, $f9
+	mtc1	t0, $f10
+	mtc1	t0, $f11
+	mtc1	t0, $f12
+	mtc1	t0, $f13
+	mtc1	t0, $f14
+	mtc1	t0, $f15
+	mtc1	t0, $f16
+	mtc1	t0, $f17
+	mtc1	t0, $f18
+	mtc1	t0, $f19
+	mtc1	t0, $f20
+	mtc1	t0, $f21
+	mtc1	t0, $f22
+	mtc1	t0, $f23
+	mtc1	t0, $f24
+	mtc1	t0, $f25
+	mtc1	t0, $f26
+	mtc1	t0, $f27
+	mtc1	t0, $f28
+	mtc1	t0, $f29
+	mtc1	t0, $f30
+	jr	ra
+	 mtc1	t0, $f31
+	END(r2300_init_fpu)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_fpu.S linux.pre11.3/arch/mips/kernel/r4k_fpu.S
--- linux.vanilla/arch/mips/kernel/r4k_fpu.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/r4k_fpu.S	Mon Jul 19 23:28:44 1999
@@ -10,7 +10,7 @@
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r4k_fpu.S,v 1.4 1998/04/04 13:59:38 ralf Exp $
+ * $Id: r4k_fpu.S,v 1.5 1999/05/01 22:40:36 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
@@ -79,11 +79,11 @@
 	END(r4k_save_fp_context)
 
 /*
- * Restore fpu state:
+ * Restore FPU state:
  *  - fp gp registers
  *  - cp1 status/control register
  *
- * We base the decission which registers to restore from the signal stack
+ * We base the decision which registers to restore from the signal stack
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_misc.S linux.pre11.3/arch/mips/kernel/r4k_misc.S
--- linux.vanilla/arch/mips/kernel/r4k_misc.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/r4k_misc.S	Mon Jul 19 23:53:55 1999
@@ -6,14 +6,13 @@
  * Multi-cpu abstraction and reworking:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r4k_misc.S,v 1.3 1997/09/07 04:51:07 ralf Exp $
+ * $Id: r4k_misc.S,v 1.4 1997/12/01 17:57:30 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/current.h>
 #include <asm/offset.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
-#include <asm/current.h>
 #include <asm/fpregdef.h>
 #include <asm/mipsconfig.h>
 #include <asm/mipsregs.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r4k_switch.S linux.pre11.3/arch/mips/kernel/r4k_switch.S
--- linux.vanilla/arch/mips/kernel/r4k_switch.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/r4k_switch.S	Mon Jul 19 23:28:45 1999
@@ -1,10 +1,10 @@
-/* $Id: r4k_switch.S,v 1.4 1998/07/14 09:15:33 ralf Exp $
+/* $Id: r4k_switch.S,v 1.7 1999/06/13 16:30:32 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995, 1996, 1998 by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996, 1998, 1999 by Ralf Baechle
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1994, 1995, 1996, by Andreas Busse
  */
@@ -24,30 +24,41 @@
 
 #include <asm/asmmacro.h>
 
+/*
+ * task_struct *r4xx0_resume(task_struct *prev,
+ *                           task_struct *next)
+ */
 	.set	noreorder
 	.set	mips3
 	.align	5
 	LEAF(r4xx0_resume)
 	mfc0	t1, CP0_STATUS
-	sw	t1, THREAD_STATUS($28)
-	CPU_SAVE_NONSCRATCH($28)
-	sw	ra, THREAD_REG31($28)
+	sw	t1, THREAD_STATUS(a0)
+	CPU_SAVE_NONSCRATCH(a0)
+	sw	ra, THREAD_REG31(a0)
 
 	/*
 	 * The order of restoring the registers takes care of the race
 	 * updating $28, $29 and kernelsp without disabling ints.
 	 */
-	move	$28, a0
+	move	$28, a1
 	CPU_RESTORE_NONSCRATCH($28)
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
 	sw	t0, kernelsp
-	lw	a3, TASK_MM($28)
+	mfc0	t1, CP0_STATUS		/* Do we really need this? */
+	li	a3, 0xff00
+	and	t1, a3
 	lw	a2, THREAD_STATUS($28)
+	nor	a3, $0, a3
+	and	a2, a3
+	lw	a3, TASK_MM($28)
+	or	a2, t1
 	lw	a3, MM_CONTEXT(a3)
 	mtc0	a2, CP0_STATUS
 	andi	a3, a3, 0xff
+	mtc0	a3, CP0_ENTRYHI
 	jr	ra
-	 mtc0	a3, CP0_ENTRYHI
+	 move	v0, a0
 	END(r4xx0_resume)
 
 /*
@@ -104,8 +115,8 @@
 
 /*
  * Load the FPU with signalling NANS.  This bit pattern we're using has
- * the property that no matter wether considered as single or as double
- * precission represents signaling NANS.
+ * the property that no matter whether considered as single or as double
+ * precision represents signaling NANS.
  *
  * We initialize fcr31 to rounding to nearest, no exceptions.
  */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/r6000_fpu.S linux.pre11.3/arch/mips/kernel/r6000_fpu.S
--- linux.vanilla/arch/mips/kernel/r6000_fpu.S	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/r6000_fpu.S	Mon Jul 19 23:28:44 1999
@@ -10,7 +10,7 @@
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r6000_fpu.S,v 1.3 1997/12/01 16:56:56 ralf Exp $
+ * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
@@ -19,6 +19,7 @@
 #include <asm/regdef.h>
 
 	.set	noreorder
+	.set	mips2
 	/* Save floating point context */
 	LEAF(r6000_save_fp_context)
 	mfc0	t0,CP0_STATUS
@@ -50,11 +51,11 @@
 	 nop
 	END(r6000_save_fp_context)
 
-/* Restore fpu state:
+/* Restore FPU state:
  *  - fp gp registers
  *  - cp1 status/control register
  *
- * We base the decission which registers to restore from the signal stack
+ * We base the decision which registers to restore from the signal stack
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/scall_o32.S linux.pre11.3/arch/mips/kernel/scall_o32.S
--- linux.vanilla/arch/mips/kernel/scall_o32.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/scall_o32.S	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: scall_o32.S,v 1.5 1998/08/19 21:53:50 ralf Exp $
+/* $Id: scall_o32.S,v 1.4 1998/06/25 20:01:01 ralf Exp $
  *
  * 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
@@ -44,6 +44,7 @@
 	beqz	t2, illegal_syscall;
 
 	subu	t0, t3, 5		# 5 or more arguments?
+	sw	a3, PT_R26(sp)		# save a3 for syscall restarting
 	bgez	t0, stackargs
 
 stack_done:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/setup.c linux.pre11.3/arch/mips/kernel/setup.c
--- linux.vanilla/arch/mips/kernel/setup.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/setup.c	Mon Jul 19 23:53:55 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.12 1998/08/18 20:45:06 ralf Exp $
+/* $Id: setup.c,v 1.15.2.2 1999/06/17 12:06:39 ralf Exp $
  *
  * 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
@@ -29,7 +29,6 @@
 #include <linux/blk.h>
 #endif
 #ifdef CONFIG_RTC
-#include <linux/ioport.h>
 #include <linux/timex.h>
 #endif
 
@@ -76,7 +75,6 @@
  * information is being use to continue the screen output just below
  * the BIOS printed text and with the same text resolution.
  */
-struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO;
 struct screen_info screen_info = DEFAULT_SCREEN_INFO;
 
 #ifdef CONFIG_BLK_DEV_FD
@@ -92,39 +90,25 @@
 extern struct rtc_ops no_rtc_ops;
 struct rtc_ops *rtc_ops;
 
+extern struct kbd_ops no_kbd_ops;
+struct kbd_ops *kbd_ops;
+
 /*
  * Setup information
  *
- * These are intialized so they are in the .data section
+ * These are initialized so they are in the .data section
  */
 unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
 unsigned long mips_cputype = CPU_UNKNOWN;
 unsigned long mips_machtype = MACH_UNKNOWN;
 unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
-unsigned long mips_tlb_entries = 48; /* Guess which CPU I've got :) */
-unsigned long mips_vram_base = KSEG0;
 
 unsigned char aux_device_present;
-extern int root_mountflags;
 extern int _end;
 
-extern char empty_zero_page[PAGE_SIZE];
-
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define PARAM	empty_zero_page
-#if 0
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#endif
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (*(unsigned long *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-
 static char command_line[CL_SIZE] = { 0, };
        char saved_command_line[CL_SIZE];
+extern char arcs_cmdline[CL_SIZE];
 
 /*
  * The board specific setup routine sets irq_setup to point to a board
@@ -153,7 +137,11 @@
            unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
 	unsigned long memory_end;
-	tag* atag;
+#ifdef CONFIG_BLK_DEV_INITRD
+	unsigned long tmp;
+	unsigned long *initrd_header;
+#endif
+	void baget_setup(void);
 	void cobalt_setup(void);
 	void decstation_setup(void);
 	void deskstation_setup(void);
@@ -161,18 +149,6 @@
 	void sni_rm200_pci_setup(void);
 	void sgi_setup(void);
 
-	/* Perhaps a lot of tags are not getting 'snarfed' - */
-	/* please help yourself */
-
-	atag = bi_TagFind(tag_machtype);
-	memcpy(&mips_machtype, TAGVALPTR(atag), atag->size);
-
-	atag = bi_TagFind(tag_machgroup);
-	memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size);
-
-	atag = bi_TagFind(tag_vram_base);
-	memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size);
-
 	/* Save defaults for configuration-dependent routines.  */
 	irq_setup = default_irq_setup;
 
@@ -185,14 +161,25 @@
 #endif
 
 	rtc_ops = &no_rtc_ops;
+	kbd_ops = &no_kbd_ops;
 
 	switch(mips_machgroup)
 	{
+#ifdef CONFIG_BAGET_MIPS
+	case MACH_GROUP_UNKNOWN: 
+		baget_setup();
+		break;
+#endif
 #ifdef CONFIG_COBALT_MICRO_SERVER
 	case MACH_GROUP_COBALT:
 		cobalt_setup();
 		break;
 #endif
+#ifdef CONFIG_DECSTATION
+	case MACH_GROUP_DEC:
+		decstation_setup();
+		break;
+#endif
 #ifdef CONFIG_MIPS_JAZZ
 	case MACH_GROUP_JAZZ:
 		jazz_setup();
@@ -212,9 +199,6 @@
 		panic("Unsupported architecture");
 	}
 
-	atag = bi_TagFind(tag_drive_info);
-	memcpy(&drive_info, TAGVALPTR(atag), atag->size);
-
 	memory_end = mips_memory_upper;
 	/*
 	 * Due to prefetching and similar mechanism the CPU sometimes
@@ -225,20 +209,7 @@
 	memory_end -= 128;
 	memory_end &= PAGE_MASK;
 
-#ifdef CONFIG_BLK_DEV_RAM
-	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
-	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
-	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
-#endif
-
-	atag = bi_TagFind(tag_mount_root_rdonly);
-	if (atag)
-	  root_mountflags |= MS_RDONLY;
-
-	atag = bi_TagFind(tag_command_line);
-	if (atag)
-		memcpy(&command_line, TAGVALPTR(atag), atag->size);	  
-
+        strncpy (command_line, arcs_cmdline, CL_SIZE);
 	memcpy(saved_command_line, command_line, CL_SIZE);
 	saved_command_line[CL_SIZE-1] = '\0';
 
@@ -247,15 +218,21 @@
 	*memory_end_p = memory_end;
 
 #ifdef CONFIG_BLK_DEV_INITRD
-	if (LOADER_TYPE) {
-		initrd_start = INITRD_START;
-		initrd_end = INITRD_START+INITRD_SIZE;
+	tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
+	if (tmp < (unsigned long)&_end)
+		tmp += PAGE_SIZE;
+	initrd_header = (unsigned long *)tmp;
+	if (initrd_header[0] == 0x494E5244) {
+		initrd_start = (unsigned long)&initrd_header[2];
+		initrd_end = initrd_start + initrd_header[1];
+		initrd_below_start_ok = 1;
 		if (initrd_end > memory_end) {
 			printk("initrd extends beyond end of memory "
 			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
 			       initrd_end,memory_end);
-		initrd_start = 0;
-		}
+			initrd_start = 0;
+		} else
+			*memory_start_p = initrd_end;
 	}
 #endif
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/signal.c linux.pre11.3/arch/mips/kernel/signal.c
--- linux.vanilla/arch/mips/kernel/signal.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/signal.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.24 1998/09/16 22:50:42 ralf Exp $
+/* $Id: signal.c,v 1.18.2.1 1999/06/17 12:06:40 ralf Exp $
  *
  *  linux/arch/mips/kernel/signal.c
  *
@@ -392,6 +392,7 @@
 		}
 	/* fallthrough */
 	case ERESTARTNOINTR:		/* Userland will reload $v0.  */
+		regs->regs[7] = regs->regs[26];
 		regs->cp0_epc -= 8;
 	}
 
@@ -491,6 +492,7 @@
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
 			case SIGABRT: case SIGFPE: case SIGSEGV:
+			case SIGBUS:
 				lock_kernel();
 				if (current->binfmt
 				    && current->binfmt->core_dump
@@ -502,6 +504,7 @@
 			default:
 				lock_kernel();
 				sigaddset(&current->signal, signr);
+				recalc_sigpending(current);
 				current->flags |= PF_SIGNALED;
 				do_exit(exit_code);
 				/* NOTREACHED */
@@ -524,6 +527,7 @@
 		if (regs->regs[2] == ERESTARTNOHAND ||
 		    regs->regs[2] == ERESTARTSYS ||
 		    regs->regs[2] == ERESTARTNOINTR) {
+			regs->regs[7] = regs->regs[26];
 			regs->cp0_epc -= 8;
 		}
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/softfp.S linux.pre11.3/arch/mips/kernel/softfp.S
--- linux.vanilla/arch/mips/kernel/softfp.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/softfp.S	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: softfp.S,v 1.1 1998/07/14 09:33:48 ralf Exp $
+/* $Id: softfp.S,v 1.1 1998/07/16 19:10:02 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/syscall.c linux.pre11.3/arch/mips/kernel/syscall.c
--- linux.vanilla/arch/mips/kernel/syscall.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/syscall.c	Mon Jul 19 23:28:38 1999
@@ -1,10 +1,10 @@
-/* $Id: syscall.c,v 1.10 1998/08/20 14:38:40 ralf Exp $
+/* $Id: syscall.c,v 1.10 1999/02/15 02:16:52 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995 - 1998 by Ralf Baechle
+ * Copyright (C) 1995 - 1999 by Ralf Baechle
  *
  * TODO:  Implement the compatibility syscalls.
  *        Don't waste that much memory for empty entries in the syscall
@@ -80,11 +80,10 @@
 asmlinkage int sys_idle(void)
 {
 	unsigned long start_idle = 0;
-        int ret = -EPERM;
 
-	lock_kernel();
 	if (current->pid != 0)
-		goto out;
+		return -EPERM;
+
 	/* endless idle loop with no priority at all */
 	current->priority = 0;
 	current->counter = 0;
@@ -110,10 +109,8 @@
 			start_idle = 0;
 		schedule();
 	}
-	ret = 0;
-out:
-	unlock_kernel();
-	return ret;
+
+	return 0;
 }
 
 asmlinkage int sys_fork(struct pt_regs regs)
@@ -121,9 +118,7 @@
 	int res;
 
 	save_static(&regs);
-	lock_kernel();
 	res = do_fork(SIGCHLD, regs.regs[29], &regs);
-	unlock_kernel();
 	return res;
 }
 
@@ -134,13 +129,11 @@
 	int res;
 
 	save_static(&regs);
-	lock_kernel();
 	clone_flags = regs.regs[4];
 	newsp = regs.regs[5];
 	if (!newsp)
 		newsp = regs.regs[29];
 	res = do_fork(clone_flags, newsp, &regs);
-	unlock_kernel();
 	return res;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/syscalls.h linux.pre11.3/arch/mips/kernel/syscalls.h
--- linux.vanilla/arch/mips/kernel/syscalls.h	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/syscalls.h	Mon Jul 19 23:28:38 1999
@@ -1,4 +1,4 @@
-/* $Id: syscalls.h,v 1.16 1998/09/16 22:50:43 ralf Exp $
+/* $Id: syscalls.h,v 1.15 1998/09/19 19:16:17 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/sysirix.c linux.pre11.3/arch/mips/kernel/sysirix.c
--- linux.vanilla/arch/mips/kernel/sysirix.c	Thu May 27 22:11:50 1999
+++ linux.pre11.3/arch/mips/kernel/sysirix.c	Mon Jul 19 23:28:44 1999
@@ -1,4 +1,4 @@
-/* $Id: sysirix.c,v 1.12 1998/08/17 10:16:27 ralf Exp $
+/* $Id: sysirix.c,v 1.19 1999/06/13 16:30:33 ralf Exp $
  *
  * sysirix.c: IRIX system call emulation.
  *
@@ -172,7 +172,7 @@
 	case PR_RESIDENT:
 		printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n",
 		       current->comm, current->pid);
-		error = 0; /* Compatability indeed. */
+		error = 0; /* Compatibility indeed. */
 		break;
 
 	case PR_ATTACHADDR:
@@ -734,8 +734,9 @@
 	struct statfs kbuf;
 	int error, i;
 
-	/* We don't support this feature yet. */
 	lock_kernel();
+
+	/* We don't support this feature yet. */
 	if(fs_type) {
 		error = -EINVAL;
 		goto out;
@@ -1622,8 +1623,7 @@
 		__put_user(0, &buf->f_basetype[i]);
 	__put_user(0, &buf->f_flag);
 	__put_user(kbuf.f_namelen, &buf->f_namemax);
-	for(i = 0; i < 32; i++)
-		__put_user(0, &buf->f_fstr[i]);
+	__clear_user(&buf->f_fstr, sizeof(buf->f_fstr));
 
 out_f:
 	fput(file);
@@ -1917,8 +1917,8 @@
 		__put_user(0, &buf->f_basetype[i]);
 	__put_user(0, &buf->f_flag);
 	__put_user(kbuf.f_namelen, &buf->f_namemax);
-	for(i = 0; i < 32; i++)
-		__put_user(0, &buf->f_fstr[i]);
+	__clear_user(buf->f_fstr, sizeof(buf->f_fstr[i]));
+
 out_f:
 	fput(file);
 out:
@@ -1983,22 +1983,21 @@
 #define NAME_OFFSET32(de) ((int) ((de)->d_name - (char *) (de)))
 #define ROUND_UP32(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
 
-static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offset, ino_t ino)
+static int irix_filldir32(void *__buf, const char *name, int namlen,
+                          off_t offset, ino_t ino)
 {
 	struct irix_dirent32 *dirent;
-	struct irix_dirent32_callback *buf = (struct irix_dirent32_callback *)__buf;
+	struct irix_dirent32_callback *buf =
+		 (struct irix_dirent32_callback *)__buf;
 	unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
-	int retval;
 
 #ifdef DEBUG_GETDENTS
 	printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
 	       reclen, namlen, buf->count);
 #endif
 	buf->error = -EINVAL;	/* only used if we fail.. */
-	if (reclen > buf->count) {
-		retval = -EINVAL;
-		goto out;
-	}
+	if (reclen > buf->count)
+		return -EINVAL;
 	dirent = buf->previous;
 	if (dirent)
 		__put_user(offset, &dirent->d_off);
@@ -2012,10 +2011,7 @@
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 
-	retval = 0;
-
-out:
-	return retval;
+	return 0;
 }
 
 asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob)
@@ -2040,10 +2036,6 @@
 	if (!inode)
 		goto out_putf;
 
-	inode = dentry->d_inode;
-	if (!inode)
-		goto out_putf;
-
 	buf.current_dir = (struct irix_dirent32 *) dirent;
 	buf.previous = NULL;
 	buf.count = count;
@@ -2111,13 +2103,10 @@
 	struct irix_dirent64_callback * buf =
 		(struct irix_dirent64_callback *) __buf;
 	unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
-	int retval;
 
 	buf->error = -EINVAL;	/* only used if we fail.. */
-	if (reclen > buf->count) {
-		retval = -EINVAL;
-		goto out;
-	}
+	if (reclen > buf->count)
+		return -EINVAL;
 	dirent = buf->previous;
 	if (dirent)
 		__put_user(offset, &dirent->d_off);
@@ -2125,15 +2114,13 @@
 	buf->previous = dirent;
 	__put_user(ino, &dirent->d_ino);
 	__put_user(reclen, &dirent->d_reclen);
-	copy_to_user(dirent->d_name, name, namlen);
+	__copy_to_user(dirent->d_name, name, namlen);
 	__put_user(0, &dirent->d_name[namlen]);
 	((char *) dirent) += reclen;
 	buf->curr = dirent;
 	buf->count -= reclen;
 
-	retval = 0;
-out:
-	return retval;
+	return 0;
 }
 
 asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
@@ -2437,3 +2424,4 @@
 
 	return -ENOSYS;
 }
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/sysmips.c linux.pre11.3/arch/mips/kernel/sysmips.c
--- linux.vanilla/arch/mips/kernel/sysmips.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/kernel/sysmips.c	Mon Jul 19 23:28:41 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
- * $Id: sysmips.c,v 1.4 1998/05/07 15:20:05 ralf Exp $
+ * $Id: sysmips.c,v 1.6 1998/08/25 09:14:42 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/linkage.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/time.c linux.pre11.3/arch/mips/kernel/time.c
--- linux.vanilla/arch/mips/kernel/time.c	Wed Mar 24 10:55:10 1999
+++ linux.pre11.3/arch/mips/kernel/time.c	Mon Jul 19 23:53:55 1999
@@ -1,16 +1,12 @@
-/*
- *  linux/arch/mips/kernel/time.c
+/* $Id: time.c,v 1.12 1999/06/13 16:30:34 ralf Exp $
  *
  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *  Copyright (C) 1996, 1997, 1998  Ralf Baechle
  *
  * This file contains the time handling details for PC-style clocks as
  * found in some MIPS systems.
- *
- * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
- *		"A Kernel Model for Precision Timekeeping" by Dave Mills
- *
- * $Id: time.c,v 1.6 1998/08/17 13:57:44 ralf Exp $
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/sched.h>
@@ -67,7 +63,7 @@
 
 	quotient = cached_quotient;
 
-	if (last_jiffies != tmp) {
+	if (tmp && last_jiffies != tmp) {
 		last_jiffies = tmp;
 		__asm__(".set\tnoreorder\n\t"
 			".set\tnoat\n\t"
@@ -340,6 +336,25 @@
 static void inline
 timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
+#ifdef CONFIG_PROFILE
+	if(!user_mode(regs)) {
+		if (prof_buffer && current->pid) {
+			extern int _stext;
+			unsigned long pc = regs->cp0_epc;
+
+			pc -= (unsigned long) &_stext;
+			pc >>= prof_shift;
+			/*
+			 * Dont ignore out-of-bounds pc values silently,
+			 * put them into the last histogram slot, so if
+			 * present, they will show up as a sharp peak.
+			 */
+			if (pc > prof_len-1)
+				pc = prof_len-1;
+			atomic_inc((atomic_t *)&prof_buffer[pc]);
+		}
+	}
+#endif
 	do_timer(regs);
 
 	/*
@@ -375,6 +390,16 @@
 	timerlo = count;
 
 	timer_interrupt(irq, dev_id, regs);
+
+	if (!jiffies)
+	{
+		/*
+		 * If jiffies has overflowed in this timer_interrupt we must
+		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
+		 * quotient calc still valid. -arca
+		 */
+		timerhi = timerlo = 0;
+	}
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -456,7 +481,7 @@
 
 __initfunc(void time_init(void))
 {
-	unsigned int year, mon, day, hour, min, sec;
+	unsigned int epoch, year, mon, day, hour, min, sec;
 	int i;
 
 	/* The Linux interpretation of the CMOS clock register contents:
@@ -488,13 +513,17 @@
 	    BCD_TO_BIN(mon);
 	    BCD_TO_BIN(year);
 	  }
-#if 0	/* the IBM way */
-	if ((year += 1900) < 1970)
-		year += 100;
-#else
-	/* Acer PICA clock starts from 1980.  True for all MIPS machines?  */
-	year += 1980;
-#endif
+
+	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c so
+	   no stupid things will happen to timekeeping.  Who knows, maybe Ultrix
+  	   also uses 1952 as epoch ...  */
+	if (year > 10 && year < 44) {
+		epoch = 1980;
+	} else if (year < 96) {
+		epoch = 1952;
+	}
+	year += epoch;
+
 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
 	xtime.tv_usec = 0;
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/traps.c linux.pre11.3/arch/mips/kernel/traps.c
--- linux.vanilla/arch/mips/kernel/traps.c	Wed Jan  6 23:02:18 1999
+++ linux.pre11.3/arch/mips/kernel/traps.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.20 1998/10/14 20:26:26 ralf Exp $
+/* $Id: traps.c,v 1.20 1999/06/13 16:30:34 ralf Exp $
  *
  * 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
@@ -202,17 +202,16 @@
 	 * Assume it would be too dangerous to continue ...
 	 */
 	force_sig(SIGBUS, current);
+show_regs(regs); while(1);
 }
 
 void do_ibe(struct pt_regs *regs)
 {
-show_regs(regs); while(1);
 	ibe_board_handler(regs);
 }
 
 void do_dbe(struct pt_regs *regs)
 {
-show_regs(regs); while(1);
 	dbe_board_handler(regs);
 }
 
@@ -325,7 +324,7 @@
 	/*
 	 * (A short test says that IRIX 5.3 sends SIGTRAP for all break
 	 * insns, even for break codes that indicate arithmetic failures.
-	 * Wiered ...)
+	 * Weird ...)
 	 */
 	force_sig(SIGTRAP, current);
 }
@@ -341,7 +340,7 @@
 	/*
 	 * (A short test says that IRIX 5.3 sends SIGTRAP for all break
 	 * insns, even for break codes that indicate arithmetic failures.
-	 * Wiered ...)
+	 * Weird ...)
 	 */
 	force_sig(SIGTRAP, current);
 }
@@ -465,8 +464,8 @@
 extern asmlinkage void r2300_restore_fp_context(struct sigcontext *sc);
 extern asmlinkage void r6000_restore_fp_context(struct sigcontext *sc);
 
-extern asmlinkage void r4xx0_resume(void *tsk);
-extern asmlinkage void r2300_resume(void *tsk);
+extern asmlinkage void *r4xx0_resume(void *last, void *next);
+extern asmlinkage void *r2300_resume(void *last, void *next);
 
 __initfunc(void trap_init(void))
 {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/kernel/unaligned.c linux.pre11.3/arch/mips/kernel/unaligned.c
--- linux.vanilla/arch/mips/kernel/unaligned.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/kernel/unaligned.c	Mon Jul 19 23:28:45 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1998 by Ralf Baechle
  *
- * $Id: unaligned.c,v 1.5 1998/08/17 13:57:44 ralf Exp $
+ * $Id: unaligned.c,v 1.5 1999/05/01 22:40:39 ralf Exp $
  *
  * This file contains exception handler for address error exception with the
  * special capability to execute faulting instructions in software.  The
@@ -17,7 +17,7 @@
  * Putting data to unaligned addresses is a bad practice even on Intel where
  * only the performance is affected.  Much worse is that such code is non-
  * portable.  Due to several programs that die on MIPS due to alignment
- * problems I decieded to implement this handler anyway though I originally
+ * problems I decided to implement this handler anyway though I originally
  * didn't intend to do this at all for user code.
  *
  * For now I enable fixing of address errors by default to make life easier.
@@ -140,7 +140,7 @@
 		goto sigbus;
 
 	/*
-	 * The remaining opcodes are the ones that are really of interrest.
+	 * The remaining opcodes are the ones that are really of interest.
 	 */
 	case lh_op:
 		check_axs(pc, addr, 2);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/Makefile linux.pre11.3/arch/mips/lib/Makefile
--- linux.vanilla/arch/mips/lib/Makefile	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/Makefile	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.12 1998/05/28 03:17:57 ralf Exp $
+# $Id: Makefile,v 1.9 1999/01/04 16:03:50 ralf Exp $
 #
 # Makefile for MIPS-specific library files..
 #
@@ -10,7 +10,7 @@
 
 L_TARGET = lib.a
 L_OBJS	= csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
-	  floppy-no.o ide-std.o ide-no.o rtc-std.o rtc-no.o memset.o memcpy.o \
-	  strlen_user.o strncpy_user.o tags.o watch.o
+	  floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
+	  rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o watch.o
 
 include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/csum_partial.S linux.pre11.3/arch/mips/lib/csum_partial.S
--- linux.vanilla/arch/mips/lib/csum_partial.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/csum_partial.S	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: csum_partial.S,v 1.3 1998/05/07 14:17:45 ralf Exp $
+/* $Id: csum_partial.S,v 1.2 1998/05/07 23:44:01 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/csum_partial_copy.c linux.pre11.3/arch/mips/lib/csum_partial_copy.c
--- linux.vanilla/arch/mips/lib/csum_partial_copy.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/csum_partial_copy.c	Mon Jul 19 23:28:45 1999
@@ -14,7 +14,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * $Id: csum_partial_copy.c,v 1.2 1998/09/16 13:29:32 ralf Exp $
+ * $Id: csum_partial_copy.c,v 1.2 1998/09/19 19:16:17 ralf Exp $
  */
 #include <net/checksum.h>
 #include <linux/types.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/floppy-std.c linux.pre11.3/arch/mips/lib/floppy-std.c
--- linux.vanilla/arch/mips/lib/floppy-std.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/lib/floppy-std.c	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: floppy-std.c,v 1.2 1998/05/28 03:17:57 ralf Exp $
+/* $Id: floppy-std.c,v 1.3 1998/10/28 12:38:13 ralf Exp $
  *
  * 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
@@ -12,7 +12,6 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
-#include <linux/kbdcntrlr.h>
 #include <linux/kernel.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/ide-no.c linux.pre11.3/arch/mips/lib/ide-no.c
--- linux.vanilla/arch/mips/lib/ide-no.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/ide-no.c	Mon Jul 19 23:28:45 1999
@@ -1,4 +1,4 @@
-/* $Id: ide-no.c,v 1.2 1998/05/28 03:17:57 ralf Exp $
+/* $Id: ide-no.c,v 1.2.2.2 1999/06/17 12:06:40 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/ide-std.c linux.pre11.3/arch/mips/lib/ide-std.c
--- linux.vanilla/arch/mips/lib/ide-std.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/ide-std.c	Mon Jul 19 23:28:45 1999
@@ -1,5 +1,4 @@
-/*
- * include/asm-mips/types.h
+/* $Id: ide-std.c,v 1.3.2.2 1999/06/17 12:06:41 ralf Exp $
  *
  * 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
@@ -9,6 +8,8 @@
  *
  * Copyright (C) 1998 by Ralf Baechle
  */
+#include <linux/sched.h>
+#include <linux/ioport.h>
 #include <linux/hdreg.h>
 #include <asm/ptrace.h>
 #include <asm/ide.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/kbd-no.c linux.pre11.3/arch/mips/lib/kbd-no.c
--- linux.vanilla/arch/mips/lib/kbd-no.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/lib/kbd-no.c	Mon Jul 19 23:28:45 1999
@@ -0,0 +1,63 @@
+/* $Id: kbd-no.c,v 1.1 1998/10/28 12:38:14 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Stub keyboard and psaux routines to keep Linux from crashing on machines
+ * without a keyboard.
+ *
+ * Copyright (C) 1998 by Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <asm/keyboard.h>
+
+static void no_kbd_request_region(void)
+{
+	/* No I/O ports are being used on the Indy.  */
+}
+
+static int no_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	return -ENODEV;
+}
+
+static int no_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	return -ENODEV;
+}
+
+static void no_aux_free_irq(void)
+{
+}
+
+static unsigned char no_kbd_read_input(void)
+{
+	return 0;
+}
+
+static void no_kbd_write_output(unsigned char val)
+{
+}
+
+static void no_kbd_write_command(unsigned char val)
+{
+}
+
+static unsigned char no_kbd_read_status(void)
+{
+	return 0;
+}
+
+struct kbd_ops no_kbd_ops = {
+	no_kbd_request_region,
+	no_kbd_request_irq,
+
+	no_aux_request_irq,
+	no_aux_free_irq,
+
+	no_kbd_read_input,
+	no_kbd_write_output,
+	no_kbd_write_command,
+	no_kbd_read_status
+};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/kbd-std.c linux.pre11.3/arch/mips/lib/kbd-std.c
--- linux.vanilla/arch/mips/lib/kbd-std.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/lib/kbd-std.c	Mon Jul 19 23:28:45 1999
@@ -0,0 +1,81 @@
+/* $Id: kbd-std.c,v 1.1 1998/10/28 12:38:14 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Routines for standard PC style keyboards accessible via I/O ports.
+ *
+ * Copyright (C) 1998 by Ralf Baechle
+ */
+#include <linux/pc_keyb.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <asm/keyboard.h>
+#include <asm/io.h>
+
+#define KEYBOARD_IRQ 1
+#define AUX_IRQ 12
+
+static void std_kbd_request_region(void)
+{
+	request_region(0x60, 16, "keyboard");
+}
+
+static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
+}
+
+static int std_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	return request_irq(AUX_IRQ, handler, 0, "PS/2 Mouse", NULL);
+}
+
+static void std_aux_free_irq(void)
+{
+	free_irq(AUX_IRQ, NULL);
+}
+
+static unsigned char std_kbd_read_input(void)
+{
+	return inb(KBD_DATA_REG);
+}
+
+static void std_kbd_write_output(unsigned char val)
+{
+	int status;
+
+	do {
+		status = inb(KBD_CNTL_REG);
+	} while (status & KBD_STAT_IBF);
+	outb(val, KBD_DATA_REG);
+}
+
+static void std_kbd_write_command(unsigned char val)
+{
+	int status;
+
+	do {
+		status = inb(KBD_CNTL_REG);
+	} while (status & KBD_STAT_IBF);
+	outb(val, KBD_CNTL_REG);
+}
+
+static unsigned char std_kbd_read_status(void)
+{
+	return inb(KBD_STATUS_REG);
+}
+
+struct kbd_ops std_kbd_ops = {
+	std_kbd_request_region,
+	std_kbd_request_irq,
+
+	std_aux_request_irq,
+	std_aux_free_irq,
+
+	std_kbd_read_input,
+	std_kbd_write_output,
+	std_kbd_write_command,
+	std_kbd_read_status
+};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/memcpy.S linux.pre11.3/arch/mips/lib/memcpy.S
--- linux.vanilla/arch/mips/lib/memcpy.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/memcpy.S	Mon Jul 19 23:28:45 1999
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * $Id: memcpy.S,v 1.4 1998/07/03 14:05:33 ralf Exp $
+ * $Id: memcpy.S,v 1.3 1998/07/10 01:14:49 ralf Exp $
  *
  * Unified implementation of memcpy, memmove and the __copy_user backend.
  * For __rmemcpy and memmove an exception is always a kernel bug, therefore
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/memset.S linux.pre11.3/arch/mips/lib/memset.S
--- linux.vanilla/arch/mips/lib/memset.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/memset.S	Mon Jul 19 23:28:45 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1998 by Ralf Baechle
  *
- * $Id: memset.S,v 1.2 1998/04/25 17:01:45 ralf Exp $
+ * $Id: memset.S,v 1.1 1998/05/04 09:12:54 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/offset.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/strlen_user.S linux.pre11.3/arch/mips/lib/strlen_user.S
--- linux.vanilla/arch/mips/lib/strlen_user.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/strlen_user.S	Mon Jul 19 23:28:45 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1996, 1998 by Ralf Baechle
  *
- * $Id: strlen_user.S,v 1.3 1998/05/03 11:13:45 ralf Exp $
+ * $Id: strlen_user.S,v 1.2 1998/05/04 09:12:54 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/offset.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/strncpy_user.S linux.pre11.3/arch/mips/lib/strncpy_user.S
--- linux.vanilla/arch/mips/lib/strncpy_user.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/strncpy_user.S	Mon Jul 19 23:28:45 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1996 by Ralf Baechle
  *
- * $Id: strncpy_user.S,v 1.3 1998/05/03 11:13:45 ralf Exp $
+ * $Id: strncpy_user.S,v 1.2 1998/05/04 09:12:54 ralf Exp $
  */
 #include <linux/errno.h>
 #include <asm/asm.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/tags.c linux.pre11.3/arch/mips/lib/tags.c
--- linux.vanilla/arch/mips/lib/tags.c	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/tags.c	Thu Jan  1 01:00:00 1970
@@ -1,75 +0,0 @@
-/*
- *  linux/arch/mips/lib/tags.c
- *
- *  Copyright (C) 1996  Stoned Elipot
- */
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-
-/*
- * Parse the tags present in upper memory to find out
- * a pecular one.
- *
- * Parameter: type - tag type to find
- * 
- * returns  : NULL  - failure
- *            !NULL - pointer on the tag structure found 
- */
-tag *
-bi_TagFind(enum bi_tag type)
-{
-	tag* t = (tag*)(mips_memory_upper - sizeof(tag));
-
-	while((t->tag != tag_dummy) && (t->tag != type))
-		t = (tag*)(NEXTTAGPTR(t));
-
-	if (t->tag == tag_dummy)		/* tag not found */
-		return (tag*)NULL;
-
-	return t;
-}
-
-/*
- * Snarf from the tag list in memory end some tags needed
- * before the kernel reachs setup_arch()
- *
- * add yours here if you want to, but *beware*: the kernel var
- * that will hold the values you want to snarf have to be
- * in .data section of the kernel, so initialized in to whatever
- * value in the kernel's sources.
- */
-void bi_EarlySnarf(void)
-{
-	tag* atag;
-  
-	/* for wire_mappings() */
-	atag = bi_TagFind(tag_machgroup);
-	if (atag)
-		memcpy(&mips_machgroup, TAGVALPTR(atag), atag->size);
-	else {
-		/* useless for boxes without text video mode but....*/
-		panic("machine group not specified by bootloader");
-	}
-
-	atag = bi_TagFind(tag_machtype);
-	if (atag)
-		memcpy(&mips_machtype, TAGVALPTR(atag), atag->size);
-	else {
-		/* useless for boxes without text video mode but....*/
-		panic("machine type not specified by bootloader");
-	}
-
-	/* for tlbflush() */
-	atag = bi_TagFind(tag_tlb_entries);
-	if (atag)
-		memcpy(&mips_tlb_entries, TAGVALPTR(atag), atag->size);
-	else {
-		/* useless for boxes without text video mode but....*/
-		panic("number of TLB entries not specified by bootloader");
-	}
-
-	return;
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/lib/watch.S linux.pre11.3/arch/mips/lib/watch.S
--- linux.vanilla/arch/mips/lib/watch.S	Sun Nov  8 15:08:30 1998
+++ linux.pre11.3/arch/mips/lib/watch.S	Mon Jul 19 23:28:45 1999
@@ -1,6 +1,6 @@
 /*
  * Kernel debug stuff to use the Watch registers.
- * Usefull to find stack overflows, dangeling pointers etc.
+ * Useful to find stack overflows, dangling pointers etc.
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/Makefile linux.pre11.3/arch/mips/mm/Makefile
--- linux.vanilla/arch/mips/mm/Makefile	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/Makefile	Mon Jul 19 23:28:37 1999
@@ -15,4 +15,8 @@
 O_OBJS   += umap.o
 endif
 
+ifdef CONFIG_BAGET_MIPS
+O_OBJS   += umap.o
+endif
+
 include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/andes.c linux.pre11.3/arch/mips/mm/andes.c
--- linux.vanilla/arch/mips/mm/andes.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/andes.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: andes.c,v 1.6 1998/10/16 19:22:42 ralf Exp $
+/* $Id: andes.c,v 1.6 1999/01/04 16:03:52 ralf Exp $
  *
  * andes.c: MMU and cache operations for the R10000 (ANDES).
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/fault.c linux.pre11.3/arch/mips/mm/fault.c
--- linux.vanilla/arch/mips/mm/fault.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/fault.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.12 1998/10/19 21:27:37 ralf Exp $
+/* $Id: fault.c,v 1.9 1999/01/04 16:03:53 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/init.c linux.pre11.3/arch/mips/mm/init.c
--- linux.vanilla/arch/mips/mm/init.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/init.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.13 1998/10/16 19:22:42 ralf Exp $
+/* $Id: init.c,v 1.13 1999/05/01 22:40:40 ralf Exp $
  *
  * 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
@@ -35,12 +35,6 @@
 #endif
 #include <asm/mmu_context.h>
 
-/*
- * Define this to effectivly disable the userpage colouring shit.
- */
-#define CONF_GIVE_A_SHIT_ABOUT_COLOURS
-
-extern void deskstation_tyne_dma_init(void);
 extern void show_net_buffers(void);
 
 void __bad_pte_kernel(pmd_t *pmd)
@@ -59,7 +53,7 @@
 {
 	pte_t *page;
 
-	page = (pte_t *) __get_free_page(GFP_KERNEL);
+	page = (pte_t *) __get_free_page(GFP_USER);
 	if (pmd_none(*pmd)) {
 		if (page) {
 			clear_page((unsigned long)page);
@@ -126,6 +120,7 @@
 	case CPU_R4400SC:
 	case CPU_R4400MC:
 		order = 3;
+		break;
 	default:
 		order = 0;
 	}
@@ -137,6 +132,7 @@
 	pg = MAP_NR(empty_zero_page);
 	while(pg < MAP_NR(empty_zero_page) + (1 << order)) {
 		set_bit(PG_reserved, &mem_map[pg].flags);
+		atomic_set(&mem_map[pg].count, 0);
 		pg++;
 	}
 
@@ -243,83 +239,6 @@
 	return pte_mkdirty(mk_pte(page, PAGE_SHARED));
 }
 
-#ifdef __SMP__
-spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED;
-#endif
-struct upcache user_page_cache[8] __attribute__((aligned(32)));
-static unsigned long user_page_order;
-unsigned long user_page_colours;
-
-unsigned long get_user_page_slow(int which)
-{
-	unsigned long chunk;
-	struct upcache *up = &user_page_cache[0];
-	struct page *p, *res;
-	int i;
-
-	do {
-		chunk = __get_free_pages(GFP_KERNEL, user_page_order);
-	} while(chunk==0);
-
-	p = mem_map + MAP_NR(chunk);
-	res = p + which;
-	spin_lock(&user_page_lock);
-	for (i=user_page_colours; i>=0; i--,p++,up++,chunk+=PAGE_SIZE) {
-		atomic_set(&p->count, 1);
-		p->age = PAGE_INITIAL_AGE;
-
-		if (p != res) {
-			if(up->count < USER_PAGE_WATER) {
-				p->next = up->list;
-				up->list = p;
-				up->count++;
-			} else
-				free_pages(chunk, 0);
-		}
-	}
-	spin_unlock(&user_page_lock);
-
-	return page_address(res);
-}
-
-static inline void user_page_setup(void)
-{
-	unsigned long assoc = 0;
-	unsigned long dcache_log, icache_log, cache_log;
-	unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
-
-	switch(mips_cputype) {
-	case CPU_R4000SC:
-	case CPU_R4000MC:
-	case CPU_R4400SC:
-	case CPU_R4400MC:
-		cache_log = 3;	/* => 32k, sucks  */
-		break;
-
-        case CPU_R4600:                 /* two way set associative caches?  */
-        case CPU_R4700:
-        case CPU_R5000:
-        case CPU_NEVADA:
-		assoc = 1;
-		/* fall through */
-	default:
-		/* use bigger cache  */
-		icache_log = (config >> 9) & 7;
-		dcache_log = (config >> 6) & 7;
-		if (dcache_log > icache_log)
-			cache_log = dcache_log;
-		else
-			cache_log = icache_log;
-	}
-
-#ifdef CONF_GIVE_A_SHIT_ABOUT_COLOURS
-	cache_log = assoc = 0;
-#endif
-
-	user_page_order = cache_log - assoc;
-	user_page_colours = (1 << (cache_log - assoc)) - 1;
-}
-
 void show_mem(void)
 {
 	int i, free = 0, total = 0, reserved = 0;
@@ -375,8 +294,9 @@
 #endif
 
 	end_mem &= PAGE_MASK;
-	max_mapnr = num_physpages = MAP_NR(end_mem);
+	max_mapnr = MAP_NR(end_mem);
 	high_memory = (void *)end_mem;
+	num_physpages = 0;
 
 	/* mark usable pages in the mem_map[] */
 	start_mem = PAGE_ALIGN(start_mem);
@@ -384,15 +304,12 @@
 	for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++)
 		clear_bit(PG_reserved, &mem_map[tmp].flags);
 
-
-#ifdef CONFIG_SGI
 	prom_fixup_mem_map(start_mem, (unsigned long)high_memory);
-#endif
 
 	for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) {
 		/*
 		 * This is only for PC-style DMA.  The onboard DMA
-		 * of Jazz and Tyne machines is completly different and
+		 * of Jazz and Tyne machines is completely different and
 		 * not handled via a flag in mem_map_t.
 		 */
 		if (tmp >= MAX_DMA_ADDRESS)
@@ -406,6 +323,7 @@
 				datapages++;
 			continue;
 		}
+		num_physpages++;
 		atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
 #ifdef CONFIG_BLK_DEV_INITRD
 		if (!initrd_start || (tmp < initrd_start || tmp >=
@@ -423,9 +341,6 @@
 		max_mapnr << (PAGE_SHIFT-10),
 		codepages << (PAGE_SHIFT-10),
 		datapages << (PAGE_SHIFT-10));
-
-	/* Initialize allocator for colour matched mapped pages.  */
-	user_page_setup();
 }
 
 extern char __init_begin, __init_end;
@@ -433,7 +348,9 @@
 void free_initmem(void)
 {
 	unsigned long addr;
-        
+
+	prom_free_prom_memory ();
+    
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
 		mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/loadmmu.c linux.pre11.3/arch/mips/mm/loadmmu.c
--- linux.vanilla/arch/mips/mm/loadmmu.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/loadmmu.c	Mon Jul 19 23:28:37 1999
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: loadmmu.c,v 1.7 1998/03/27 08:53:41 ralf Exp $
+ * $Id: loadmmu.c,v 1.9.2.2 1999/06/17 12:06:42 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -53,7 +53,7 @@
 
 int (*user_mode)(struct pt_regs *);
 
-asmlinkage void (*resume)(void *tsk);
+asmlinkage void *(*resume)(void *last, void *next);
 
 extern void ld_mmu_r2300(void);
 extern void ld_mmu_r4xx0(void);
@@ -66,6 +66,7 @@
 	switch(mips_cputype) {
 	case CPU_R2000:
 	case CPU_R3000:
+	case CPU_R3000A:
 		printk("Loading R[23]00 MMU routines.\n");
 		ld_mmu_r2300();
 		break;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/r2300.c linux.pre11.3/arch/mips/mm/r2300.c
--- linux.vanilla/arch/mips/mm/r2300.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/r2300.c	Mon Jul 19 23:28:37 1999
@@ -1,8 +1,13 @@
-/* $Id: r2300.c,v 1.7 1998/10/16 19:22:43 ralf Exp $
- *
+/*
  * r2300.c: R2000 and R3000 specific mmu/cache code.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * with a lot of changes to make this thing work for R3000s
+ * Copyright (C) 1998 Harald Koerfgen
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ *
+ * $Id: r2300.c,v 1.8 1999/04/11 17:13:56 harald Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -11,12 +16,40 @@
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/mmu_context.h>
 #include <asm/system.h>
 #include <asm/sgialib.h>
-#include <asm/mmu_context.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+/*
+ * Temporarily disabled
+ *
+#include <asm/wbflush.h>
+ */
+
+/*
+ * According to the paper written by D. Miller about Linux cache & TLB
+ * flush implementation, DMA/Driver coherence should be done at the 
+ * driver layer.  Thus, normally, we don't need flush dcache for R3000.
+ * Define this if driver does not handle cache consistency during DMA ops.
+ */
+#undef DO_DCACHE_FLUSH
+
+/*
+ *  Unified cache space description structure
+ */
+static struct cache_space {
+	unsigned long ca_flags;  /* Cache space access flags */
+	int           size;      /* Cache space size */
+} icache, dcache;
+
+#undef DEBUG_TLB
+#undef DEBUG_CACHE
 
 extern unsigned long mips_tlb_entries;
 
+#define NTLB_ENTRIES       64  /* Fixed on all R23000 variants... */
+
 /* page functions */
 void r2300_clear_page(unsigned long page)
 {
@@ -94,80 +127,425 @@
 		 "I" (PAGE_SIZE));
 }
 
-/* Cache operations. */
-static inline void r2300_flush_cache_all(void) { }
-static void r2300_flush_cache_mm(struct mm_struct *mm) { }
+__initfunc(static unsigned long size_cache(unsigned long ca_flags))
+{
+	unsigned long flags, status, dummy, size;
+	volatile unsigned long *p;
+
+	p = (volatile unsigned long *) KSEG0;
+
+	save_and_cli(flags);
+
+	/* isolate cache space */
+	write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC);
+
+	*p = 0xa5a55a5a;
+	dummy = *p;
+	status = read_32bit_cp0_register(CP0_STATUS);
+
+	if (dummy != 0xa5a55a5a || (status & (1<<19))) {
+		size = 0;
+	} else {
+		for (size = 512; size <= 0x40000; size <<= 1)
+			*(p + size) = 0;
+		*p = -1;
+		for (size = 512; 
+		     (size <= 0x40000) && (*(p + size) == 0); 
+		     size <<= 1)
+			;
+		if (size > 0x40000)
+			size = 0;
+	}
+	restore_flags(flags);
+
+	return size * sizeof(*p);
+}
+
+__initfunc(static void probe_dcache(void))
+{
+	dcache.size = size_cache(dcache.ca_flags = ST0_DE);
+	printk("Data cache %dkb\n", dcache.size >> 10);
+}
+
+__initfunc(static void probe_icache(void))
+{
+	icache.size = size_cache(icache.ca_flags = ST0_DE|ST0_CE);
+	printk("Instruction cache %dkb\n", icache.size >> 10);
+}
+
+static inline unsigned long get_phys_page (unsigned long page,
+					   struct mm_struct *mm)
+{
+        page &= PAGE_MASK;
+	if (page >= KSEG0 && page < KSEG1) {
+		/*
+		 *  We already have physical address
+		 */
+		return page;
+	} else {
+		if (!mm) {
+			printk ("get_phys_page: vaddr without mm\n");
+			return 0;
+		} else {
+			/* 
+			 *  Find a physical page using mm_struct
+			 */
+			pgd_t *page_dir;
+			pmd_t *page_middle;
+			pte_t *page_table, pte;
+
+			unsigned long address = page;
+
+			page_dir = pgd_offset(mm, address);
+			if (pgd_none(*page_dir))
+				return 0; 
+			page_middle = pmd_offset(page_dir, address);
+			if (pmd_none(*page_middle))
+				return 0; 
+			page_table = pte_offset(page_middle, address);
+			pte = *page_table;
+			if (!pte_present(pte))
+				return 0; 
+			return pte_page(pte);
+	}
+	}
+}
+
+static inline void flush_cache_space_page(struct cache_space *space,
+					  unsigned long page)
+{
+	register unsigned long i, flags, size = space->size;
+	register volatile unsigned char *p = (volatile unsigned char*) page;
+
+#ifndef DO_DCACHE_FLUSH
+	if (space == &dcache)
+		return;
+#endif
+	if (size > PAGE_SIZE)
+		size = PAGE_SIZE;
+
+	save_and_cli(flags);
+
+	/* isolate cache space */
+	write_32bit_cp0_register(CP0_STATUS, (space->ca_flags|flags)&~ST0_IEC);
+
+	for (i = 0; i < size; i += 64) {
+		asm ( 	"sb\t$0,(%0)\n\t"
+			"sb\t$0,4(%0)\n\t"
+			"sb\t$0,8(%0)\n\t"
+			"sb\t$0,12(%0)\n\t"
+			"sb\t$0,16(%0)\n\t"
+			"sb\t$0,20(%0)\n\t"
+			"sb\t$0,24(%0)\n\t"
+			"sb\t$0,28(%0)\n\t"
+ 		        "sb\t$0,32(%0)\n\t"
+ 			"sb\t$0,36(%0)\n\t"
+ 			"sb\t$0,40(%0)\n\t"
+ 			"sb\t$0,44(%0)\n\t"
+ 			"sb\t$0,48(%0)\n\t"
+ 			"sb\t$0,52(%0)\n\t"
+ 			"sb\t$0,56(%0)\n\t"
+ 			"sb\t$0,60(%0)\n\t"
+			: : "r" (p) );
+		p += 64;
+	}
+
+	restore_flags(flags);
+}
+
+static inline void flush_cache_space_all(struct cache_space *space)
+{
+	unsigned long page = KSEG0;
+	int size = space->size;
+
+#ifndef DO_DCACHE_FLUSH
+	if (space == &dcache)
+		return;
+#endif
+	while(size > 0) { 
+		flush_cache_space_page(space, page);
+		page += PAGE_SIZE; size -= PAGE_SIZE;
+        }
+}
+
+static inline void r2300_flush_cache_all(void)
+{
+	flush_cache_space_all(&dcache);
+	flush_cache_space_all(&icache);
+}
+ 
+static void r2300_flush_cache_mm(struct mm_struct *mm)
+{
+	if(mm->context == 0) 
+		return;
+#ifdef DEBUG_CACHE
+		printk("cmm[%d]", (int)mm->context);
+#endif
+	/*
+	 *  This function is called not offen, so it looks
+	 *  enough good to flush all caches than scan mm_struct,
+	 *  count pages to flush (and, very probably, flush more
+	 *  than cache space size :-)
+ */
+	flush_cache_all();
+}
+
 static void r2300_flush_cache_range(struct mm_struct *mm,
 				    unsigned long start,
 				    unsigned long end)
 {
+	/*
+	 *  In general, we need to flush both i- & d- caches here.
+	 *  Optimization: if cache space is less than given range,
+	 *  it is more quickly to flush all cache than all pages in range.
+	 */
+
+	unsigned long page;
+	int icache_done = 0, dcache_done = 0;
+
+	if(mm->context == 0) 
+		return;
+#ifdef DEBUG_CACHE
+	printk("crange[%d]", (int)mm->context);
+#endif
+	if (end - start >= icache.size) {
+		flush_cache_space_all(&icache);
+		icache_done = 1;
+	}
+	if (end - start >= dcache.size) {
+		flush_cache_space_all(&dcache);
+		dcache_done = 1;
+	}
+	if (icache_done && dcache_done)
+		return;
+
+	for (page = start; page < end; page += PAGE_SIZE) {
+		unsigned long phys_page = get_phys_page(page, mm);
+		
+		if (phys_page) {
+			if (!icache_done) 
+				flush_cache_space_page(&icache, phys_page);
+			if (!dcache_done) 
+				flush_cache_space_page(&dcache, phys_page);
+		}
+	}
 }
 
 static void r2300_flush_cache_page(struct vm_area_struct *vma,
 				   unsigned long page)
 {
+	struct mm_struct *mm = vma->vm_mm;
+
+	if(mm->context == 0)
+		return;
+#ifdef DEBUG_CACHE
+	printk("cpage[%d,%08lx]", (int)mm->context, page);
+#endif
+	/*
+	 *  User changes page, so we need to check:
+         *     is icache page flush needed ?
+	 *  It looks we don't need to flush dcache,
+	 *  due it is write-transparent on R3000
+	 */
+	if (vma->vm_flags & VM_EXEC) {
+		unsigned long phys_page = get_phys_page(page, vma->vm_mm);
+		if (phys_page)
+			flush_cache_space_page(&icache, phys_page); 
+	}
 }
 
 static void r2300_flush_page_to_ram(unsigned long page)
 {
-	/* XXX What we want to do here is perform a displacement
-	 * XXX flush because there are circumstances where you do
-	 * XXX indeed want to remove stale data from the cache.
-	 * XXX (DMA operations for example, where the cache cannot
-	 * XXX  "see" this data get changed.)
+	/*
+	 *  We need to flush both i- & d- caches :-(
 	 */
+	unsigned long phys_page = get_phys_page(page, NULL);
+#ifdef DEBUG_CACHE
+	printk("cram[%08lx]", page);
+#endif
+	if (phys_page) {
+		flush_cache_space_page(&icache, phys_page);
+		flush_cache_space_page(&dcache, phys_page);
+	}
+}
+
+static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size)
+{
+	register unsigned long i, flags;
+	register volatile unsigned char *p = (volatile unsigned char*) start;
+
+/*
+ * Temporarily disabled
+	wbflush();
+	 */
+
+	/*
+	 * Invalidate dcache
+	 */
+	if (size < 64)
+		size = 64;
+
+	if (size > dcache.size)
+		size = dcache.size;
+
+	save_and_cli(flags);
+
+	/* isolate cache space */
+	write_32bit_cp0_register(CP0_STATUS, (ST0_DE|flags)&~ST0_IEC);
+
+	for (i = 0; i < size; i += 64) {
+		asm ( 	"sb\t$0,(%0)\n\t"
+			"sb\t$0,4(%0)\n\t"
+			"sb\t$0,8(%0)\n\t"
+			"sb\t$0,12(%0)\n\t"
+			"sb\t$0,16(%0)\n\t"
+			"sb\t$0,20(%0)\n\t"
+			"sb\t$0,24(%0)\n\t"
+			"sb\t$0,28(%0)\n\t"
+ 		        "sb\t$0,32(%0)\n\t"
+ 			"sb\t$0,36(%0)\n\t"
+ 			"sb\t$0,40(%0)\n\t"
+ 			"sb\t$0,44(%0)\n\t"
+ 			"sb\t$0,48(%0)\n\t"
+ 			"sb\t$0,52(%0)\n\t"
+ 			"sb\t$0,56(%0)\n\t"
+ 			"sb\t$0,60(%0)\n\t"
+			: : "r" (p) );
+		p += 64;
+	}
+
+	restore_flags(flags);
 }
 
 static void r2300_flush_cache_sigtramp(unsigned long page)
 {
+	/*
+	 *  We need only flush i-cache here
+	 *
+	 *  This function receives virtual address (from signal.c),
+	 *  but this moment we have needed mm_struct in 'current'
+	 */
+	unsigned long phys_page = get_phys_page(page, current->mm);
+#ifdef DEBUG_CACHE
+		printk("csigtramp[%08lx]", page);
+#endif
+	if (phys_page)
+		flush_cache_space_page(&icache, phys_page);  
 }
 
 /* TLB operations. */
 static inline void r2300_flush_tlb_all(void)
 {
 	unsigned long flags;
+	unsigned long old_ctx;
 	int entry;
 
+#ifdef DEBUG_TLB
+	printk("[tlball]");
+#endif
+
 	save_and_cli(flags);
+	old_ctx = (get_entryhi() & 0xfc0);
 	write_32bit_cp0_register(CP0_ENTRYLO0, 0);
-	for(entry = 0; entry < mips_tlb_entries; entry++) {
-		write_32bit_cp0_register(CP0_INDEX, entry);
-		write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x8) << 12));
+	for(entry = 0; entry < NTLB_ENTRIES; entry++) {
+		write_32bit_cp0_register(CP0_INDEX, entry << 8);
+		write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12));
 		__asm__ __volatile__("tlbwi");
 	}
+	set_entryhi(old_ctx);
 	restore_flags(flags);
 }
 
 static void r2300_flush_tlb_mm(struct mm_struct *mm)
 {
+	if(mm->context != 0) {
+		unsigned long flags;
+
+#ifdef DEBUG_TLB
+		printk("[tlbmm<%d>]", mm->context);
+#endif
+		save_and_cli(flags);
+		get_new_mmu_context(mm, asid_cache);
 	if(mm == current->mm)
-		r2300_flush_tlb_all();
+			set_entryhi(mm->context & 0xfc0);
+		restore_flags(flags);
+	}
 }
 
 static void r2300_flush_tlb_range(struct mm_struct *mm, unsigned long start,
 				  unsigned long end)
 {
+	if(mm->context != 0) {
+		unsigned long flags;
+		int size;
+
+#ifdef DEBUG_TLB
+		printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xfc0),
+		       start, end);
+#endif
+		save_and_cli(flags);
+		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+		if(size <= NTLB_ENTRIES) {
+			int oldpid = (get_entryhi() & 0xfc0);
+			int newpid = (mm->context & 0xfc0);
+
+			start &= PAGE_MASK;
+			end += (PAGE_SIZE - 1);
+			end &= PAGE_MASK;
+			while(start < end) {
+				int idx;
+
+				set_entryhi(start | newpid);
+				start += PAGE_SIZE;
+				tlb_probe();
+				idx = get_index();
+				set_entrylo0(0);
+				set_entryhi(KSEG0);
+				if(idx < 0)
+					continue;
+				tlb_write_indexed();
+			}
+			set_entryhi(oldpid);
+		} else {
+			get_new_mmu_context(mm, asid_cache);
 	if(mm == current->mm)
-		r2300_flush_tlb_all();
+				set_entryhi(mm->context & 0xfc0);
+		}
+		restore_flags(flags);
+	}
 }
 
 static void r2300_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-	if(vma->vm_mm == current->mm)
-		r2300_flush_tlb_all();
+	if(vma->vm_mm->context != 0) {
+		unsigned long flags;
+		int oldpid, newpid, idx;
+
+#ifdef DEBUG_TLB
+		printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
+#endif
+		newpid = (vma->vm_mm->context & 0xfc0);
+		page &= PAGE_MASK;
+		save_and_cli(flags);
+		oldpid = (get_entryhi() & 0xfc0);
+		set_entryhi(page | newpid);
+		tlb_probe();
+		idx = get_index();
+		set_entrylo0(0);
+		set_entryhi(KSEG0);
+		if(idx < 0)
+			goto finish;
+		tlb_write_indexed();
+
+finish:
+		set_entryhi(oldpid);
+		restore_flags(flags);
+	}
 }
 
 /* Load a new root pointer into the TLB. */
 static void r2300_load_pgd(unsigned long pg_dir)
 {
-	unsigned long flags;
-
-	save_and_cli(flags);
-	write_32bit_cp0_register(CP0_ENTRYHI, TLB_ROOT);
-	write_32bit_cp0_register(CP0_INDEX, 0);
-	write_32bit_cp0_register(CP0_ENTRYLO0, ((pg_dir >> 6) | 0x00e0));
-	__asm__ __volatile__("tlbwi");
-	restore_flags(flags);
 }
 
 /*
@@ -199,17 +577,63 @@
 		 "=r" (dummy2)
 		:"r" ((unsigned long) invalid_pte_table),
 		 "0" (page),
-		 "1" (USER_PTRS_PER_PGD/8));
+		 "1" (PAGE_SIZE/(sizeof(pmd_t)*8)));
 }
 
 static void r2300_update_mmu_cache(struct vm_area_struct * vma,
 				   unsigned long address, pte_t pte)
 {
-	r2300_flush_tlb_page(vma, address);
-	/*
-	 * FIXME: We should also reload a new entry into the TLB to
-	 * avoid unnecessary exceptions.
-	 */
+	unsigned long flags;
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	int idx, pid;
+
+	pid = (get_entryhi() & 0xfc0);
+
+#ifdef DEBUG_TLB
+	if((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) {
+		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
+		       (int) (vma->vm_mm->context & 0xfc0), pid);
+	}
+#endif
+
+	save_and_cli(flags);
+	address &= PAGE_MASK;
+	set_entryhi(address | (pid));
+	pgdp = pgd_offset(vma->vm_mm, address);
+	tlb_probe();
+	pmdp = pmd_offset(pgdp, address);
+	idx = get_index();
+	ptep = pte_offset(pmdp, address);
+	set_entrylo0(pte_val(*ptep));
+	set_entryhi(address | (pid));
+	if(idx < 0) {
+		tlb_write_random();
+#if 0
+		printk("[MISS]");
+#endif
+	} else {
+		tlb_write_indexed();
+#if 0
+		printk("[HIT]");
+#endif
+	}
+#if 0
+	if(!strcmp(current->comm, "args")) {
+		printk("<");
+		for(idx = 0; idx < NTLB_ENTRIES; idx++) {
+			set_index(idx);
+			tlb_read();
+			address = get_entryhi();
+			if((address & 0xfc0) != 0)
+				printk("[%08lx]", address);
+		}
+		printk(">\n");
+	}
+#endif
+	set_entryhi(pid);
+	restore_flags(flags);
 }
 
 static void r2300_show_regs(struct pt_regs * regs)
@@ -248,6 +672,7 @@
 static void r2300_add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
 				  unsigned long entryhi, unsigned long pagemask)
 {
+printk("r2300_add_wired_entry");
         /*
 	 * FIXME, to be done
 	 */
@@ -255,14 +680,19 @@
 
 static int r2300_user_mode(struct pt_regs *regs)
 {
-	return !(regs->cp0_status & 0x4);
+	return !(regs->cp0_status & ST0_KUP);
 }
 
 __initfunc(void ld_mmu_r2300(void))
 {
+	printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
+
 	clear_page = r2300_clear_page;
 	copy_page = r2300_copy_page;
 
+	probe_icache();
+	probe_dcache();
+
 	flush_cache_all = r2300_flush_cache_all;
 	flush_cache_mm = r2300_flush_cache_mm;
 	flush_cache_range = r2300_flush_cache_range;
@@ -274,16 +704,19 @@
 	flush_tlb_mm = r2300_flush_tlb_mm;
 	flush_tlb_range = r2300_flush_tlb_range;
 	flush_tlb_page = r2300_flush_tlb_page;
-	r3000_asid_setup();
+
+        dma_cache_wback_inv = r3k_dma_cache_wback_inv;
 
 	load_pgd = r2300_load_pgd;
 	pgd_init = r2300_pgd_init;
 	update_mmu_cache = r2300_update_mmu_cache;
+	r3000_asid_setup();
 
 	show_regs = r2300_show_regs;
     
         add_wired_entry = r2300_add_wired_entry;
 
 	user_mode = r2300_user_mode;
+
 	flush_tlb_all();
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/r4xx0.c linux.pre11.3/arch/mips/mm/r4xx0.c
--- linux.vanilla/arch/mips/mm/r4xx0.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/r4xx0.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.30 1998/10/16 19:22:43 ralf Exp $
+/* $Id: r4xx0.c,v 1.21.2.2 1999/06/17 12:06:42 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/r6000.c linux.pre11.3/arch/mips/mm/r6000.c
--- linux.vanilla/arch/mips/mm/r6000.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/r6000.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: r6000.c,v 1.6 1998/10/16 19:22:44 ralf Exp $
+/* $Id: r6000.c,v 1.6 1999/01/04 16:03:54 ralf Exp $
  *
  * r6000.c: MMU and cache routines for the R6000 processors.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/mm/tfp.c linux.pre11.3/arch/mips/mm/tfp.c
--- linux.vanilla/arch/mips/mm/tfp.c	Sun Nov  8 15:08:29 1998
+++ linux.pre11.3/arch/mips/mm/tfp.c	Mon Jul 19 23:28:37 1999
@@ -1,4 +1,4 @@
-/* $Id: tfp.c,v 1.6 1998/10/16 19:22:44 ralf Exp $
+/* $Id: tfp.c,v 1.6 1999/01/04 16:03:55 ralf Exp $
  *
  * tfp.c: MMU and cache routines specific to the r8000 (TFP).
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/Makefile linux.pre11.3/arch/mips/sgi/kernel/Makefile
--- linux.vanilla/arch/mips/sgi/kernel/Makefile	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/Makefile	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 1998/06/25 20:19:17 ralf Exp $
+# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $
 # Makefile for the SGI specific kernel interface routines
 # under Linux.
 #
@@ -13,8 +13,11 @@
 .S.o:
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
-OBJS  = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \
-	indy_timer.o indyIRQ.o reset.o setup.o time.o
+OBJS  = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
+        system.o indy_timer.o indyIRQ.o reset.o setup.o time.o
+ifdef CONFIG_SGI_PROM_CONSOLE
+OBJS += promcon.o
+endif
 
 all: sgikern.a
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indyIRQ.S linux.pre11.3/arch/mips/sgi/kernel/indyIRQ.S
--- linux.vanilla/arch/mips/sgi/kernel/indyIRQ.S	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/indyIRQ.S	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: indyIRQ.S,v 1.3 1998/03/21 22:39:53 ralf Exp $
+/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $
  * indyIRQ.S: Interrupt exception dispatch code for FullHouse and
  *            Guiness.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_hpc.c linux.pre11.3/arch/mips/sgi/kernel/indy_hpc.c
--- linux.vanilla/arch/mips/sgi/kernel/indy_hpc.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/indy_hpc.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: indy_hpc.c,v 1.4 1998/07/14 09:12:27 ralf Exp $
+/* $Id: indy_hpc.c,v 1.6 1999/05/07 22:34:31 ulfc Exp $
  *
  * indy_hpc.c: Routines for generic manipulation of the HPC controllers.
  *
@@ -43,7 +43,8 @@
 	prom_printf("sgihpc_init: ");
 #endif
 
-	if(sid & 1) {
+	/* This test works now thanks to William J. Earl */
+	if ((sid & 1) == 0 ) {
 #ifdef DEBUG_SGIHPC
 		prom_printf("GUINESS ");
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_int.c linux.pre11.3/arch/mips/sgi/kernel/indy_int.c
--- linux.vanilla/arch/mips/sgi/kernel/indy_int.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/indy_int.c	Mon Jul 19 23:53:55 1999
@@ -1,12 +1,14 @@
-/* $Id: indy_int.c,v 1.9 1998/05/28 03:18:00 ralf Exp $
+/* $Id: indy_int.c,v 1.13 1999/06/12 17:26:15 ulfc Exp $
  *
  * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
  *             found on INDY workstations..
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) 
+ *                    - Indigo2 changes
+ *                    - Interrupt handling fixes
  */
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <linux/errno.h>
@@ -35,6 +37,7 @@
 #include <asm/sgihpc.h>
 #include <asm/sgint23.h>
 #include <asm/sgialib.h>
+#include <asm/gdb-stub.h>
 
 /* #define DEBUG_SGINT */
 
@@ -51,10 +54,6 @@
 
 extern asmlinkage void indyIRQ(void);
 
-#ifdef CONFIG_REMOTE_DEBUG
-extern void rs_kgdb_hook(int);
-#endif
-
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 unsigned long spurious_count = 0;
@@ -274,7 +273,7 @@
 	int do_random, cpu;
 
 	cpu = smp_processor_id();
-	irq_enter(cpu, irq);
+	hardirq_enter(cpu);
 	kstat.irqs[0][irq]++;
 
 	printk("Got irq %d, press a key.", irq);
@@ -310,7 +309,7 @@
 			add_interrupt_randomness(irq);
 		__cli();
 	}
-	irq_exit(cpu, irq);
+	hardirq_exit(cpu);
 
 	/* unmasking and bottom half handling is done magically for us. */
 }
@@ -448,10 +447,23 @@
 		action = local_irq_action[irq];
 	}
 
-	irq_enter(cpu, irq);
+	/* if irq == 0, then the interrupt has already been cleared */
+	if ( irq == 0 ) { goto end; }
+	/* if action == NULL, then we do have a handler for the irq */
+	if ( action == NULL ) { goto no_handler; }
+	
+	hardirq_enter(cpu);
 	kstat.irqs[0][irq + 16]++;
 	action->handler(irq, action->dev_id, regs);
-	irq_exit(cpu, irq);
+	hardirq_exit(cpu);
+	goto end;
+
+no_handler:
+	printk("No handler for local0 irq: %i\n", irq);
+
+end:	
+	return;	
+	
 }
 
 void indy_local1_irqdispatch(struct pt_regs *regs)
@@ -472,10 +484,23 @@
 		irq = lc1msk_to_irqnr[mask];
 		action = local_irq_action[irq];
 	}
-	irq_enter(cpu, irq);
+	/* if irq == 0, then the interrupt has already been cleared */
+	/* not sure if it is needed here, but it is needed for local0 */
+	if ( irq == 0 ) { goto end; }
+	/* if action == NULL, then we do have a handler for the irq */
+	if ( action == NULL ) { goto no_handler; }
+	
+	hardirq_enter(cpu);
 	kstat.irqs[0][irq + 24]++;
 	action->handler(irq, action->dev_id, regs);
-	irq_exit(cpu, irq);
+	hardirq_exit(cpu);
+	goto end;
+	
+no_handler:
+	printk("No handler for local1 irq: %i\n", irq);
+
+end:	
+	return;	
 }
 
 void indy_buserror_irq(struct pt_regs *regs)
@@ -483,13 +508,13 @@
 	int cpu = smp_processor_id();
 	int irq = 6;
 
-	irq_enter(cpu, irq);
+	hardirq_enter(cpu);
 	kstat.irqs[0][irq]++;
 	printk("Got a bus error IRQ, shouldn't happen yet\n");
 	show_regs(regs);
 	printk("Spinning...\n");
 	while(1);
-	irq_exit(cpu, irq);
+	hardirq_exit(cpu);
 }
 
 /* Misc. crap just to keep the kernel linking... */
@@ -506,9 +531,6 @@
 __initfunc(void sgint_init(void))
 {
 	int i;
-#ifdef CONFIG_REMOTE_DEBUG
-	char *ctype;
-#endif
 
 	sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE);
 	sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE);
@@ -563,9 +585,16 @@
 		}
 	}
 
-	ioc_icontrol = &sgi_i3regs->ints;
-	ioc_timers = &sgi_i3regs->timers;
-	ioc_tclear = &sgi_i3regs->tclear;
+	/* Indy uses an INT3, Indigo2 uses an INT2 */
+	if (sgi_guiness) {
+		ioc_icontrol = &sgi_i3regs->ints;
+		ioc_timers = &sgi_i3regs->timers;
+		ioc_tclear = &sgi_i3regs->tclear;
+	} else {
+		ioc_icontrol = &sgi_i2regs->ints;
+		ioc_timers = &sgi_i2regs->timers;
+		ioc_tclear = &sgi_i2regs->tclear;
+	}
 
 	/* Mask out all interrupts. */
 	ioc_icontrol->imask0 = 0;
@@ -575,28 +604,4 @@
 
 	/* Now safe to set the exception vector. */
 	set_except_vector(0, indyIRQ);
-
-#ifdef CONFIG_REMOTE_DEBUG
-	ctype = prom_getcmdline();
-	for(i = 0; i < strlen(ctype); i++) {
-		if(ctype[i]=='k' && ctype[i+1]=='g' &&
-		   ctype[i+2]=='d' && ctype[i+3]=='b' &&
-		   ctype[i+4]=='=' && ctype[i+5]=='t' &&
-		   ctype[i+6]=='t' && ctype[i+7]=='y' &&
-		   ctype[i+8]=='d' &&
-		   (ctype[i+9] == '1' || ctype[i+9] == '2')) {
-			printk("KGDB: Using serial line /dev/ttyd%d for "
-			       "session\n", (ctype[i+9] - '0'));
-				if(ctype[i+9]=='1')
-					rs_kgdb_hook(1);
-				else if(ctype[i+9]=='2')
-					rs_kgdb_hook(0);
-				else {
-					printk("KGDB: whoops bogon tty line "
-					       "requested, disabling session\n");
-				}
-
-		}
-	}
-#endif
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_mc.c linux.pre11.3/arch/mips/sgi/kernel/indy_mc.c
--- linux.vanilla/arch/mips/sgi/kernel/indy_mc.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/indy_mc.c	Mon Jul 19 23:28:46 1999
@@ -2,8 +2,9 @@
  * indy_mc.c: Routines for manipulating the INDY memory controller.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes
  *
- * $Id: indy_mc.c,v 1.3 1998/04/25 15:43:32 ralf Exp $
+ * $Id: indy_mc.c,v 1.4 1999/05/07 22:34:32 ulfc Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -150,6 +151,8 @@
 			tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */
 			tmpreg |= SGIMC_GIOPARM_PLINEEXP1;
 			tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */
+			/* someone forgot this poor little guy... */
+			tmpreg |= SGIMC_GIOPARM_GFX64; 	/* GFX at 64 bits */
 		}
 	}
 	mcmisc_regs->gioparm = tmpreg; /* poof */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_sc.c linux.pre11.3/arch/mips/sgi/kernel/indy_sc.c
--- linux.vanilla/arch/mips/sgi/kernel/indy_sc.c	Sun Nov  8 15:10:06 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/indy_sc.c	Mon Jul 19 23:53:55 1999
@@ -1,4 +1,4 @@
-/* $Id: indy_sc.c,v 1.9 1998/08/17 12:14:55 ralf Exp $
+/* $Id: indy_sc.c,v 1.9 1999/05/12 21:57:49 ulfc Exp $
  *
  * indy_sc.c: Indy cache managment functions.
  *
@@ -9,7 +9,6 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/autoconf.h>
 
 #include <asm/bcache.h>
 #include <asm/sgi.h>
@@ -38,6 +37,7 @@
 		.set	noreorder
 		.set	mips3
 		.set	noat
+		mfc0	$2, $12
 		li	$1, 0x80	# Go 64 bit
 		mtc0	$1, $12
 
@@ -50,12 +50,12 @@
 		bne	%0, %1, 1b
 		daddu	%0, 32
 
-		mtc0	$0, $12		# Back to 32 bit
+		mtc0	$2, $12		# Back to 32 bit
 		nop; nop; nop; nop;
 		.set mips0
 		.set reorder"
-		: "=r" (first), "=r" (last)
-		: "0" (first), "1" (last)
+		: /* no output */
+		: "r" (first), "r" (last)
 		: "$1");
 }
 
@@ -69,7 +69,10 @@
 #endif
 	/* Which lines to flush?  */
 	first_line = SC_INDEX(addr);
-	last_line = SC_INDEX(SC_ROUND(addr + size));
+	if (size <= SC_LINE)
+		last_line = SC_INDEX(addr);
+	else
+		last_line = SC_INDEX(addr + size - 1);
 
 	__save_and_cli(flags);
 	if (first_line <= last_line) {
@@ -80,8 +83,8 @@
 	/* Cache index wrap around.  Due to the way the buddy system works
 	   this case should not happen.  We're prepared to handle it,
 	   though. */
-	indy_sc_wipe(last_line, SC_SIZE);
-	indy_sc_wipe(0, first_line);
+	indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
+	indy_sc_wipe(0, last_line);
 out:
 	__restore_flags(flags);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/indy_timer.c linux.pre11.3/arch/mips/sgi/kernel/indy_timer.c
--- linux.vanilla/arch/mips/sgi/kernel/indy_timer.c	Wed Mar 24 10:55:10 1999
+++ linux.pre11.3/arch/mips/sgi/kernel/indy_timer.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: indy_timer.c,v 1.9 1998/06/25 20:15:02 ralf Exp $
+/* $Id: indy_timer.c,v 1.12 1999/06/13 16:30:36 ralf Exp $
  *
  * indy_timer.c: Setting up the clock on the INDY 8254 controller.
  *
@@ -262,12 +262,12 @@
 	int cpu = smp_processor_id();
 	int irq = 4;
 
-	irq_enter(cpu, irq);
+	hardirq_enter(cpu);
 	kstat.irqs[0][irq]++;
 	printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
 	prom_getchar();
 	prom_imode();
-	irq_exit(cpu, irq);
+	hardirq_exit(cpu);
 }
 
 void do_gettimeofday(struct timeval *tv)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/promcon.c linux.pre11.3/arch/mips/sgi/kernel/promcon.c
--- linux.vanilla/arch/mips/sgi/kernel/promcon.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/arch/mips/sgi/kernel/promcon.c	Mon Jul 19 23:28:46 1999
@@ -0,0 +1,73 @@
+/*
+ * Wrap-around code for a console using the
+ * SGI PROM io-routines.
+ *
+ * Copyright (c) 1999 Ulf Carlsson
+ *
+ * Derived from DECstation promcon.c
+ * Copyright (c) 1998 Harald Koerfgen 
+ */
+
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+
+#include <asm/sgialib.h>
+
+static void prom_console_write(struct console *co, const char *s,
+			       unsigned count)
+{
+    unsigned i;
+
+    /*
+     *    Now, do each character
+     */
+    for (i = 0; i < count; i++) {
+	if (*s == 10)
+	    prom_printf("%c", 13);
+	prom_printf("%c", *s++);
+    }
+}
+
+static int prom_console_wait_key(struct console *co)
+{
+    return prom_getchar();
+}
+
+__initfunc(static int prom_console_setup(struct console *co, char *options))
+{
+    return 0;
+}
+
+static kdev_t prom_console_device(struct console *c)
+{
+    return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console sercons =
+{
+    "ttyS",
+    prom_console_write,
+    NULL,
+    prom_console_device,
+    prom_console_wait_key,
+    NULL,
+    prom_console_setup,
+    CON_PRINTBUFFER,
+    -1,
+    0,
+    NULL
+};
+
+/*
+ *    Register console.
+ */
+
+__initfunc(long sgi_prom_console_init(long kmem_start, long kmem_end))
+{
+    register_console(&sercons);
+    return kmem_start;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/reset.c linux.pre11.3/arch/mips/sgi/kernel/reset.c
--- linux.vanilla/arch/mips/sgi/kernel/reset.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/reset.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: reset.c,v 1.6 1998/07/09 19:57:47 ralf Exp $
+/* $Id: reset.c,v 1.6 1999/04/10 12:21:30 ulfc Exp $
  *
  * Reset a SGI.
  *
@@ -33,7 +33,9 @@
 #define POWERDOWN_FREQ		(HZ / 4)
 #define PANIC_FREQ		(HZ / 8)
 
-static struct timer_list power_timer, blink_timer, debounce_timer;
+static unsigned char sgi_volume;
+
+static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer;
 static int shuting_down, has_paniced;
 
 static void sgi_machine_restart(char *command) __attribute__((noreturn));
@@ -129,14 +131,50 @@
 	add_timer(&power_timer);
 }
 
-static inline void volume_up_button(void)
+void inline sgi_volume_set(unsigned char volume)
+{
+	sgi_volume = volume;
+
+	hpc3c0->pbus_extregs[2][0] = sgi_volume;
+	hpc3c0->pbus_extregs[2][1] = sgi_volume;
+}
+
+void inline sgi_volume_get(unsigned char *volume)
 {
-	/* Later when we have sound support ... */
+	*volume = sgi_volume;
 }
 
-static inline void volume_down_button(void)
+static inline void volume_up_button(unsigned long data)
 {
-	/* Later when we have sound support ... */
+	del_timer(&volume_timer);
+
+	if (sgi_volume < 0xff)
+		sgi_volume++;
+
+	hpc3c0->pbus_extregs[2][0] = sgi_volume;
+	hpc3c0->pbus_extregs[2][1] = sgi_volume;
+
+	if (ioc_icontrol->istat1 & 2) {
+		volume_timer.expires = jiffies + 1;
+		add_timer(&volume_timer);
+	}
+
+}
+
+static inline void volume_down_button(unsigned long data)
+{
+	del_timer(&volume_timer);
+
+	if (sgi_volume > 0)
+		sgi_volume--;
+
+	hpc3c0->pbus_extregs[2][0] = sgi_volume;
+	hpc3c0->pbus_extregs[2][1] = sgi_volume;
+
+	if (ioc_icontrol->istat1 & 2) {
+		volume_timer.expires = jiffies + 1;
+		add_timer(&volume_timer);
+	}
 }
 
 static void panel_int(int irq, void *dev_id, struct pt_regs *regs)
@@ -156,10 +194,18 @@
 
 	if (!(buttons & 2))		/* Power button was pressed */
 		power_button();
-	if (!(buttons & 0x40))		/* Volume up button was pressed */
-		volume_up_button();
-	if (!(buttons & 0x10))		/* Volume down button was pressed */
-		volume_down_button();
+	if (!(buttons & 0x40)) {	/* Volume up button was pressed */
+		init_timer(&volume_timer);
+		volume_timer.function = volume_up_button;
+		volume_timer.expires = jiffies + 1;
+		add_timer(&volume_timer);
+	}
+	if (!(buttons & 0x10)) {	/* Volume down button was pressed */
+		init_timer(&volume_timer);
+		volume_timer.function = volume_down_button;
+		volume_timer.expires = jiffies + 1;
+		add_timer(&volume_timer);
+	}
 }
 
 static int panic_event(struct notifier_block *this, unsigned long event,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/setup.c linux.pre11.3/arch/mips/sgi/kernel/setup.c
--- linux.vanilla/arch/mips/sgi/kernel/setup.c	Sun Nov  8 15:10:06 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/setup.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.13 1998/09/16 22:50:46 ralf Exp $
+/* $Id: setup.c,v 1.24 1999/06/12 17:26:15 ulfc Exp $
  *
  * setup.c: SGI specific setup, including init of the feature struct.
  *
@@ -14,6 +14,7 @@
 #include <linux/console.h>
 #include <linux/sched.h>
 #include <linux/mc146818rtc.h>
+#include <linux/pc_keyb.h>
 
 #include <asm/addrspace.h>
 #include <asm/bcache.h>
@@ -25,16 +26,55 @@
 #include <asm/sgimc.h>
 #include <asm/sgihpc.h>
 #include <asm/sgint23.h>
+#include <asm/gdb-stub.h>
 
-extern int serial_console; /* in sgiserial.c  */
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+extern void breakpoint(void);
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+#endif
 
 extern struct rtc_ops indy_rtc_ops;
 void indy_reboot_setup(void);
+void sgi_volume_set(unsigned char);
 
-static volatile struct hpc_keyb *sgi_kh = (struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64);
+static int remote_debug = 0;
+
+#define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64))
 
 #define KBD_STAT_IBF		0x02	/* Keyboard input buffer full */
 
+static void sgi_request_region(void)
+{
+	/* No I/O ports are being used on the Indy.  */
+}
+
+static int sgi_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	/* Dirty hack, this get's called as a callback from the keyboard
+	   driver.  We piggyback the initialization of the front panel
+	   button handling on it even though they're technically not
+	   related with the keyboard driver in any way.  Doing it from
+	   indy_setup wouldn't work since kmalloc isn't initialized yet.  */
+	indy_reboot_setup();
+
+	return request_irq(SGI_KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
+}
+
+static int sgi_aux_request_irq(void (*handler)(int, void *, struct pt_regs *))
+{
+	/* Nothing to do, interrupt is shared with the keyboard hw  */
+	return 0;
+}
+
+static void sgi_aux_free_irq(void)
+{
+	/* Nothing to do, interrupt is shared with the keyboard hw  */
+}
+
 static unsigned char sgi_read_input(void)
 {
 	return sgi_kh->data;
@@ -65,27 +105,28 @@
 	return sgi_kh->command;
 }
 
-__initfunc(static void sgi_keyboard_setup(void))
-{
-	kbd_read_input = sgi_read_input;
-	kbd_write_output = sgi_write_output;
-	kbd_write_command = sgi_write_command;
-	kbd_read_status = sgi_read_status;
-
-	request_irq(SGI_KEYBOARD_IRQ, keyboard_interrupt,
-	            0, "keyboard", NULL);
-
-	/* Dirty hack, this get's called as a callback from the keyboard
-	   driver.  We piggyback the initialization of the front panel
-	   button handling on it even though they're technically not
-	   related with the keyboard driver in any way.  Doing it from
-	   indy_setup wouldn't work since kmalloc isn't initialized yet.  */
-	indy_reboot_setup();
-}
+struct kbd_ops sgi_kbd_ops = {
+	sgi_request_region,
+	sgi_request_irq,
+
+	sgi_aux_request_irq,
+	sgi_aux_free_irq,
+
+	sgi_read_input,
+	sgi_write_output,
+	sgi_write_command,
+	sgi_read_status
+};
 
 __initfunc(static void sgi_irq_setup(void))
 {
 	sgint_init();
+
+#ifdef CONFIG_REMOTE_DEBUG
+	if (remote_debug)
+		set_debug_traps();
+	breakpoint(); /* you may move this line to whereever you want :-) */
+#endif
 }
 
 __initfunc(void sgi_setup(void))
@@ -93,9 +134,12 @@
 #ifdef CONFIG_SERIAL_CONSOLE
 	char *ctype;
 #endif
+#ifdef CONFIG_REMOTE_DEBUG
+	char *kgdb_ttyd;
+#endif
+
 
 	irq_setup = sgi_irq_setup;
-	keyboard_setup = sgi_keyboard_setup;
 
 	/* Init the INDY HPC I/O controller.  Need to call this before
 	 * fucking with the memory controller because it needs to know the
@@ -115,23 +159,55 @@
 	 * line and "d2" for the second serial line.
 	 */
 	ctype = prom_getenv("console");
-	serial_console = 0;
 	if(*ctype == 'd') {
 		if(*(ctype+1)=='2')
-			serial_console = 1;
+			console_setup ("ttyS1", NULL);
 		else
-			serial_console = 2;
-		if(!serial_console) {
-			prom_printf("Weird console env setting %s\n", ctype);
-			prom_printf("Press a key to reboot.\n");
-			prom_getchar();
-			prom_imode();
-		}
+			console_setup ("ttyS0", NULL);
+	}
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+	kgdb_ttyd = prom_getcmdline();
+	if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) {
+		int line;
+		kgdb_ttyd += strlen("kgdb=ttyd");
+		if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2')
+			printk("KGDB: Uknown serial line /dev/ttyd%c, "
+			       "falling back to /dev/ttyd1\n", *kgdb_ttyd);
+		line = *kgdb_ttyd == '2' ? 0 : 1;
+		printk("KGDB: Using serial line /dev/ttyd%d for session\n",
+		       line ? 1 : 2);
+		rs_kgdb_hook(line);
+
+		prom_printf("KGDB: Using serial line /dev/ttyd%d for session, "
+			    "please connect your debugger\n", line ? 1 : 2);
+
+		remote_debug = 1;
+		/* Breakpoints and stuff are in sgi_irq_setup() */
 	}
 #endif
 
+#ifdef CONFIG_SGI_PROM_CONSOLE
+	console_setup("ttyS0", NULL);
+#endif
+	  
+	sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10));
+
 #ifdef CONFIG_VT
+#ifdef CONFIG_SGI_NEWPORT_CONSOLE
 	conswitchp = &newport_con;
+#else
+	conswitchp = &dummy_con;
+#endif
 #endif
+
 	rtc_ops = &indy_rtc_ops;
+	kbd_ops = &sgi_kbd_ops;
+#ifdef CONFIG_PSMOUSE
+	aux_device_present = 0xaa;
+#endif
+#ifdef CONFIG_VIDEO_VINO
+	init_vino();
+#endif
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/system.c linux.pre11.3/arch/mips/sgi/kernel/system.c
--- linux.vanilla/arch/mips/sgi/kernel/system.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/system.c	Mon Jul 19 23:28:46 1999
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: system.c,v 1.4 1998/03/27 08:53:45 ralf Exp $
+ * $Id: system.c,v 1.7 1998/10/18 22:55:34 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -21,28 +21,6 @@
 	int type;
 };
 
-static struct smatch sgi_mtable[] = {
-	{ "SGI-IP4", ip4 },
-	{ "SGI-IP5", ip5 },
-	{ "SGI-IP6", ip6 },
-	{ "SGI-IP7", ip7 },
-	{ "SGI-IP9", ip9 },
-	{ "SGI-IP12", ip12 },
-	{ "SGI-IP15", ip15 },
-	{ "SGI-IP17", ip17 },
-	{ "SGI-IP19", ip19 },
-	{ "SGI-IP20", ip20 },
-	{ "SGI-IP21", ip21 },
-	{ "SGI-IP22", ip22 },
-	{ "SGI-IP25", ip25 },
-	{ "SGI-IP26", ip26 },
-	{ "SGI-IP28", ip28 },
-	{ "SGI-IP30", ip30 },
-	{ "SGI-IP32", ip32 }
-};
-
-#define NUM_MACHS 17 /* for now */
-
 static struct smatch sgi_cputable[] = {
 	{ "MIPS-R2000", CPU_R2000 },
 	{ "MIPS-R3000", CPU_R3000 },
@@ -57,28 +35,13 @@
 
 #define NUM_CPUS 9 /* for now */
 
-__initfunc(static enum sgi_mach string_to_mach(char *s))
-{
-	int i;
-
-	for(i = 0; i < NUM_MACHS; i++) {
-		if(!strcmp(s, sgi_mtable[i].name))
-			return (enum sgi_mach) sgi_mtable[i].type;
-	}
-	prom_printf("\nYeee, could not determine SGI architecture type <%s>\n", s);
-	prom_printf("press a key to reboot\n");
-	prom_getchar();
-	romvec->imode();
-	return (enum sgi_mach) 0;
-}
-
 __initfunc(static int string_to_cpu(char *s))
 {
 	int i;
 
 	for(i = 0; i < NUM_CPUS; i++) {
 		if(!strcmp(s, sgi_cputable[i].name))
-			return sgi_mtable[i].type;
+			return sgi_cputable[i].type;
 	}
 	prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s);
 	prom_printf("press a key to reboot\n");
@@ -101,8 +64,6 @@
 	 * have here.
 	 */
 	p = prom_getchild(PROM_NULL_COMPONENT);
-	printk("ARCH: %s\n", p->iname);
-	sgimach = string_to_mach(p->iname);
 
 	/* Now scan for cpu(s). */
 	toplev = p = prom_getchild(p);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/kernel/time.c linux.pre11.3/arch/mips/sgi/kernel/time.c
--- linux.vanilla/arch/mips/sgi/kernel/time.c	Sun Nov  8 15:08:31 1998
+++ linux.pre11.3/arch/mips/sgi/kernel/time.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.2 1998/03/27 08:53:45 ralf Exp $
+/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $
  * time.c: Generic SGI time_init() code, this will dispatch to the
  *         appropriate per-architecture time/counter init code.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/Makefile linux.pre11.3/arch/mips/sgi/prom/Makefile
--- linux.vanilla/arch/mips/sgi/prom/Makefile	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/Makefile	Thu Jan  1 01:00:00 1970
@@ -1,23 +0,0 @@
-# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
-# Makefile for the SGI arcs prom monitor library routines
-# under Linux.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-# Note 2! The CFLAGS definitions are now in the main makefile...
-
-OBJS  = console.o init.o printf.o memory.o tree.o tags.o env.o \
-      cmdline.o misc.o time.o file.o
-
-all: promlib.a
-
-promlib.a: $(OBJS)
-	$(AR) rcs promlib.a $(OBJS)
-	sync
-
-dep:
-	$(CPP) -M *.c > .depend
-
-include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/cmdline.c linux.pre11.3/arch/mips/sgi/prom/cmdline.c
--- linux.vanilla/arch/mips/sgi/prom/cmdline.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/cmdline.c	Thu Jan  1 01:00:00 1970
@@ -1,64 +0,0 @@
-/*
- * cmdline.c: Kernel command line creation using ARCS argc/argv.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: cmdline.c,v 1.3 1998/03/27 08:53:46 ralf Exp $
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/sgialib.h>
-#include <asm/bootinfo.h>
-
-/* #define DEBUG_CMDLINE */
-
-extern char arcs_cmdline[CL_SIZE];
-
-__initfunc(char *prom_getcmdline(void))
-{
-	return &(arcs_cmdline[0]);
-}
-
-static char *ignored[] = {
-	"ConsoleIn=",
-	"ConsoleOut=",
-	"SystemPartition=",
-	"OSLoader=",
-	"OSLoadPartition=",
-	"OSLoadFilename="
-};
-#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
-
-__initfunc(void prom_init_cmdline(void))
-{
-	char *cp;
-	int actr, i;
-
-	actr = 1; /* Always ignore argv[0] */
-
-	cp = &(arcs_cmdline[0]);
-	while(actr < prom_argc) {
-		for(i = 0; i < NENTS(ignored); i++) {
-			int len = strlen(ignored[i]);
-
-			if(!strncmp(prom_argv[actr], ignored[i], len))
-				goto pic_cont;
-		}
-		/* Ok, we want it. */
-		strcpy(cp, prom_argv[actr]);
-		cp += strlen(prom_argv[actr]);
-		*cp++ = ' ';
-
-	pic_cont:
-		actr++;
-	}
-	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
-		--cp;
-	*cp = '\0';
-
-#ifdef DEBUG_CMDLINE
-	prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0]));
-#endif
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/console.c linux.pre11.3/arch/mips/sgi/prom/console.c
--- linux.vanilla/arch/mips/sgi/prom/console.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/console.c	Thu Jan  1 01:00:00 1970
@@ -1,26 +0,0 @@
-/*
- * console.c: SGI arcs console code.
- *
- * Copyright (C) 1996 David S. Miller (dm@sgi.com)
- *
- * $Id: console.c,v 1.2 1998/03/27 08:53:46 ralf Exp $
- */
-#include <linux/init.h>
-#include <asm/sgialib.h>
-
-__initfunc(void prom_putchar(char c))
-{
-	long cnt;
-	char it = c;
-
-	romvec->write(1, &it, 1, &cnt);
-}
-
-__initfunc(char prom_getchar(void))
-{
-	long cnt;
-	char c;
-
-	romvec->read(0, &c, 1, &cnt);
-	return c;
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/env.c linux.pre11.3/arch/mips/sgi/prom/env.c
--- linux.vanilla/arch/mips/sgi/prom/env.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/env.c	Thu Jan  1 01:00:00 1970
@@ -1,22 +0,0 @@
-/*
- * env.c: ARCS environment variable routines.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: env.c,v 1.2 1998/03/27 08:53:46 ralf Exp $
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/sgialib.h>
-
-__initfunc(char *prom_getenv(char *name))
-{
-	return romvec->get_evar(name);
-}
-
-__initfunc(long prom_setenv(char *name, char *value))
-{
-	return romvec->set_evar(name, value);
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/file.c linux.pre11.3/arch/mips/sgi/prom/file.c
--- linux.vanilla/arch/mips/sgi/prom/file.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/file.c	Thu Jan  1 01:00:00 1970
@@ -1,59 +0,0 @@
-/*
- * file.c: ARCS firmware interface to files.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: file.c,v 1.2 1998/03/27 08:53:47 ralf Exp $
- */
-#include <linux/init.h>
-#include <asm/sgialib.h>
-
-__initfunc(long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt))
-{
-	return romvec->get_vdirent(fd, ent, num, cnt);
-}
-
-__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd))
-{
-	return romvec->open(name, md, fd);
-}
-
-__initfunc(long prom_close(unsigned long fd))
-{
-	return romvec->close(fd);
-}
-
-__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
-{
-	return romvec->read(fd, buf, num, cnt);
-}
-
-__initfunc(long prom_getrstatus(unsigned long fd))
-{
-	return romvec->get_rstatus(fd);
-}
-
-__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
-{
-	return romvec->write(fd, buf, num, cnt);
-}
-
-__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm))
-{
-	return romvec->seek(fd, off, sm);
-}
-
-__initfunc(long prom_mount(char *name, enum linux_mountops op))
-{
-	return romvec->mount(name, op);
-}
-
-__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf))
-{
-	return romvec->get_finfo(fd, buf);
-}
-
-__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk))
-{
-	return romvec->set_finfo(fd, flags, msk);
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/init.c linux.pre11.3/arch/mips/sgi/prom/init.c
--- linux.vanilla/arch/mips/sgi/prom/init.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/init.c	Thu Jan  1 01:00:00 1970
@@ -1,61 +0,0 @@
-/*
- * init.c: PROM library initialisation code.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: init.c,v 1.2 1998/03/27 08:53:47 ralf Exp $
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/sgialib.h>
-
-/* #define DEBUG_PROM_INIT */
-
-/* Master romvec interface. */
-struct linux_romvec *romvec;
-struct linux_promblock *sgi_pblock;
-int prom_argc;
-char **prom_argv, **prom_envp;
-unsigned short prom_vers, prom_rev;
-
-extern void prom_testtree(void);
-
-__initfunc(int prom_init(int argc, char **argv, char **envp))
-{
-	struct linux_promblock *pb;
-
-	romvec = ROMVECTOR;
-	pb = sgi_pblock = PROMBLOCK;
-	prom_argc = argc;
-	prom_argv = argv;
-	prom_envp = envp;
-
-	if(pb->magic != 0x53435241) {
-		prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
-		while(1)
-			;
-	}
-
-	prom_init_cmdline();
-
-	prom_vers = pb->ver;
-	prom_rev = pb->rev;
-	printk("PROMLIB: SGI ARCS firmware Version %d Revision %d\n",
-		    prom_vers, prom_rev);
-	prom_meminit();
-	prom_setup_archtags();
-
-#if 0
-	prom_testtree();
-#endif
-
-#ifdef DEBUG_PROM_INIT
-	{
-		prom_printf("Press a key to reboot\n");
-		(void) prom_getchar();
-		romvec->imode();
-	}
-#endif
-	return 0;
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/memory.c linux.pre11.3/arch/mips/sgi/prom/memory.c
--- linux.vanilla/arch/mips/sgi/prom/memory.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/memory.c	Thu Jan  1 01:00:00 1970
@@ -1,131 +0,0 @@
-/*
- * memory.c: PROM library functions for acquiring/using memory descriptors
- *           given to us from the ARCS firmware.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: memory.c,v 1.2 1998/03/27 08:53:47 ralf Exp $
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-
-#include <asm/sgialib.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/bootinfo.h>
-
-/* #define DEBUG */
-
-__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr))
-{
-	return romvec->get_mdesc(curr);
-}
-
-#ifdef DEBUG /* convenient for debugging */
-static char *mtypes[8] = {
-	"Exception Block",
-	"ARCS Romvec Page",
-	"Free/Contig RAM",
-	"Generic Free RAM",
-	"Bad Memory",
-	"Standlong Program Pages",
-	"ARCS Temp Storage Area",
-	"ARCS Permanent Storage Area"
-};
-#endif
-
-static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS];
-
-__initfunc(struct prom_pmemblock *prom_getpblock_array(void))
-{
-	return &prom_pblocks[0];
-}
-
-__initfunc(static void prom_setup_memupper(void))
-{
-	struct prom_pmemblock *p, *highest;
-
-	for(p = prom_getpblock_array(), highest = 0; p->size != 0; p++) {
-		if(p->base == 0xdeadbeef)
-			prom_printf("WHEEE, bogus pmemblock\n");
-		if(!highest || p->base > highest->base)
-			highest = p;
-	}
-	mips_memory_upper = highest->base + highest->size;
-#ifdef DEBUG
-	prom_printf("prom_setup_memupper: mips_memory_upper = %08lx\n",
-		    mips_memory_upper);
-#endif
-}
-
-__initfunc(void prom_meminit(void))
-{
-	struct linux_mdesc *p;
-	int totram;
-	int i = 0;
-
-	p = prom_getmdesc(PROM_NULL_MDESC);
-#ifdef DEBUG
-	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
-	while(p) {
-		prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n",
-			    i, p, p->base, p->pages, mtypes[p->type]);
-		p = prom_getmdesc(p);
-		i++;
-	}
-#endif
-	p = prom_getmdesc(PROM_NULL_MDESC);
-	totram = 0;
-	i = 0;
-	while(p) {
-		if(p->type == free || p->type == fcontig) {
-			prom_pblocks[i].base =
-				((p->base<<PAGE_SHIFT) + 0x80000000);
-			prom_pblocks[i].size = p->pages << PAGE_SHIFT;
-			totram += prom_pblocks[i].size;
-#ifdef DEBUG
-			prom_printf("free_chunk[%d]: base=%08lx size=%d\n",
-				    i, prom_pblocks[i].base,
-				    prom_pblocks[i].size);
-#endif
-			i++;
-		}
-		p = prom_getmdesc(p);
-	}
-	prom_pblocks[i].base = 0xdeadbeef;
-	prom_pblocks[i].size = 0; /* indicates last elem. of array */
-	printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n",
-		    totram, (totram/1024), (totram/1024/1024));
-
-	/* Setup upper physical memory bound. */
-	prom_setup_memupper();
-}
-
-/* Called from mem_init() to fixup the mem_map page settings. */
-__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end))
-{
-	struct prom_pmemblock *p;
-	int i, nents;
-
-	/* Determine number of pblockarray entries. */
-	p = prom_getpblock_array();
-	for(i = 0; p[i].size; i++)
-		;
-	nents = i;
-	while(start < end) {
-		for(i = 0; i < nents; i++) {
-			if((start >= (p[i].base)) &&
-			   (start < (p[i].base + p[i].size))) {
-				start = p[i].base + p[i].size;
-				start &= PAGE_MASK;
-				continue;
-			}
-		}
-		set_bit(PG_reserved, &mem_map[MAP_NR(start)].flags);
-		start += PAGE_SIZE;
-	}
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/misc.c linux.pre11.3/arch/mips/sgi/prom/misc.c
--- linux.vanilla/arch/mips/sgi/prom/misc.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/misc.c	Thu Jan  1 01:00:00 1970
@@ -1,84 +0,0 @@
-/* $Id: misc.c,v 1.6 1998/07/08 15:59:13 ralf Exp $
- *
- * misc.c: Miscellaneous ARCS PROM routines.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bcache.h>
-#include <asm/sgialib.h>
-#include <asm/bootinfo.h>
-#include <asm/system.h>
-
-extern unsigned long mips_cputype;
-extern void *sgiwd93_host;
-extern void reset_wd33c93(void *instance);
-
-void prom_halt(void)
-{
-	bcops->bc_disable();
-	cli();
-#if CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
-	romvec->halt();
-}
-
-void prom_powerdown(void)
-{
-	bcops->bc_disable();
-	cli();
-#if CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
-	romvec->pdown();
-}
-
-/* XXX is this a soft reset basically? XXX */
-void prom_restart(void)
-{
-	bcops->bc_disable();
-	cli();
-#if CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
-	romvec->restart();
-}
-
-void prom_reboot(void)
-{
-	bcops->bc_disable();
-	cli();
-#if CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
-	romvec->reboot();
-}
-
-void prom_imode(void)
-{
-	bcops->bc_disable();
-	cli();
-#if CONFIG_SCSI_SGIWD93
-	reset_wd33c93(sgiwd93_host);
-#endif
-	romvec->imode();
-}
-
-long prom_cfgsave(void)
-{
-	return romvec->cfg_save();
-}
-
-struct linux_sysid *prom_getsysid(void)
-{
-	return romvec->get_sysid();
-}
-
-__initfunc(void prom_cacheflush(void))
-{
-	romvec->cache_flush();
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/printf.c linux.pre11.3/arch/mips/sgi/prom/printf.c
--- linux.vanilla/arch/mips/sgi/prom/printf.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/printf.c	Thu Jan  1 01:00:00 1970
@@ -1,35 +0,0 @@
-/*
- * printf.c: Putting things on the screen using SGI arcs
- *           PROM facilities.
- *
- * Copyright (C) 1996 David S. Miller (dm@sgi.com)
- *
- * $Id: printf.c,v 1.2 1998/03/27 08:53:48 ralf Exp $
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/sgialib.h>
-
-static char ppbuf[1024];
-
-__initfunc(void prom_printf(char *fmt, ...))
-{
-	va_list args;
-	char ch, *bptr;
-	int i;
-
-	va_start(args, fmt);
-	i = vsprintf(ppbuf, fmt, args);
-
-	bptr = ppbuf;
-
-	while((ch = *(bptr++)) != 0) {
-		if(ch == '\n')
-			prom_putchar('\r');
-
-		prom_putchar(ch);
-	}
-	va_end(args);
-	return;
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/salone.c linux.pre11.3/arch/mips/sgi/prom/salone.c
--- linux.vanilla/arch/mips/sgi/prom/salone.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/salone.c	Thu Jan  1 01:00:00 1970
@@ -1,25 +0,0 @@
-/*
- * salone.c: Routines to load into memory and execute stand-along
- *           program images using ARCS PROM firmware.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: salone.c,v 1.2 1998/03/27 08:53:48 ralf Exp $
- */
-#include <linux/init.h>
-#include <asm/sgialib.h>
-
-__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr))
-{
-	return romvec->load(name, end, pc, eaddr);
-}
-
-__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp))
-{
-	return romvec->invoke(pc, sp, argc, argv, envp);
-}
-
-__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp))
-{
-	return romvec->exec(name, argc, argv, envp);
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/tags.c linux.pre11.3/arch/mips/sgi/prom/tags.c
--- linux.vanilla/arch/mips/sgi/prom/tags.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/tags.c	Thu Jan  1 01:00:00 1970
@@ -1,69 +0,0 @@
-/*
- * tags.c: Initialize the arch tags the way the MIPS kernel setup
- *         expects.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: tags.c,v 1.2 1998/03/27 08:53:48 ralf Exp $
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/addrspace.h>
-#include <asm/sgialib.h>
-#include <asm/bootinfo.h>
-#include <asm/sgimc.h>
-
-/* XXX This tag thing is a fucking rats nest, I'm very inclined to completely
- * XXX rework the MIPS people's multi-arch code _NOW_.
- */
-
-static unsigned long machtype_SGI_INDY = MACH_SGI_INDY;
-static unsigned long machgroup_SGI = MACH_GROUP_SGI;
-static unsigned long memlower_SGI_INDY = (KSEG0 + SGIMC_SEG0_BADDR);
-static unsigned long cputype_SGI_INDY = CPU_R4400SC;
-static unsigned long tlb_entries_SGI_INDY = 48;
-static unsigned long dummy_SGI_INDY = 0;
-static struct drive_info_struct dummy_dinfo_SGI_INDY = { { 0, }, };
-char arcs_cmdline[CL_SIZE];
-
-#define TAG(t,l)   {tag_##t,(l)} /* XXX RATS NEST CODE!!! XXX */
-#define TAGVAL(v)  (void*)&(v)   /* XXX FUCKING LOSING!!! XXX */
-
-tag_def taglist_sgi_indy[] = {
-	{TAG(machtype, ULONGSIZE), TAGVAL(machtype_SGI_INDY)},
-	{TAG(machgroup, ULONGSIZE), TAGVAL(machgroup_SGI)},
-	{TAG(memlower, ULONGSIZE), TAGVAL(memlower_SGI_INDY)},
-	{TAG(cputype, ULONGSIZE), TAGVAL(cputype_SGI_INDY)},
-	{TAG(tlb_entries, ULONGSIZE), TAGVAL(tlb_entries_SGI_INDY)},
-	{TAG(vram_base, ULONGSIZE), TAGVAL(dummy_SGI_INDY)},
-	{TAG(drive_info, DRVINFOSIZE), TAGVAL(dummy_dinfo_SGI_INDY)},
-	{TAG(mount_root_rdonly, ULONGSIZE), TAGVAL(dummy_SGI_INDY)},
-	{TAG(command_line, CL_SIZE), TAGVAL(arcs_cmdline[0])},
-	{TAG(dummy, 0), NULL}
-	/* XXX COLOSTOMY BAG!!!! XXX */
-};
-
-__initfunc(void prom_setup_archtags(void))
-{
-	tag_def *tdp = &taglist_sgi_indy[0];
-	tag *tp;
-
-	tp = (tag *) (mips_memory_upper - sizeof(tag));
-	while(tdp->t.tag != tag_dummy) {
-		unsigned long size;
-		char *d;
-
-		*tp = tdp->t;
-		size = tp->size;
-		d = (char *) tdp->d;
-		tp = (tag *)(((unsigned long)tp) - (tp->size));
-		if(size)
-			memcpy(tp, d, size);
-
-		tp--;
-		tdp++;
-	}
-	*tp = tdp->t; /* copy last dummy element over */
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/time.c linux.pre11.3/arch/mips/sgi/prom/time.c
--- linux.vanilla/arch/mips/sgi/prom/time.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/time.c	Thu Jan  1 01:00:00 1970
@@ -1,19 +0,0 @@
-/*
- * time.c: Extracting time information from ARCS prom.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: time.c,v 1.2 1998/03/27 08:53:49 ralf Exp $
- */
-#include <linux/init.h>
-#include <asm/sgialib.h>
-
-__initfunc(struct linux_tinfo *prom_gettinfo(void))
-{
-	return romvec->get_tinfo();
-}
-
-__initfunc(unsigned long prom_getrtime(void))
-{
-	return romvec->get_rtime();
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sgi/prom/tree.c linux.pre11.3/arch/mips/sgi/prom/tree.c
--- linux.vanilla/arch/mips/sgi/prom/tree.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sgi/prom/tree.c	Thu Jan  1 01:00:00 1970
@@ -1,109 +0,0 @@
-/*
- * tree.c: PROM component device tree code.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: tree.c,v 1.2 1998/03/27 08:53:49 ralf Exp $
- */
-#include <linux/init.h>
-#include <asm/sgialib.h>
-
-#define DEBUG_PROM_TREE
-
-__initfunc(pcomponent *prom_getsibling(pcomponent *this))
-{
-	if(this == PROM_NULL_COMPONENT)
-		return PROM_NULL_COMPONENT;
-	return romvec->next_component(this);
-}
-
-__initfunc(pcomponent *prom_getchild(pcomponent *this))
-{
-	return romvec->child_component(this);
-}
-
-__initfunc(pcomponent *prom_getparent(pcomponent *child))
-{
-	if(child == PROM_NULL_COMPONENT)
-		return PROM_NULL_COMPONENT;
-	return romvec->parent_component(child);
-}
-
-__initfunc(long prom_getcdata(void *buffer, pcomponent *this))
-{
-	return romvec->component_data(buffer, this);
-}
-
-__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data))
-{
-	return romvec->child_add(this, tmp, data);
-}
-
-__initfunc(long prom_delcomponent(pcomponent *this))
-{
-	return romvec->comp_del(this);
-}
-
-__initfunc(pcomponent *prom_componentbypath(char *path))
-{
-	return romvec->component_by_path(path);
-}
-
-#ifdef DEBUG_PROM_TREE
-static char *classes[] = {
-	"system", "processor", "cache", "adapter", "controller", "peripheral",
-	"memory"
-};
-
-static char *types[] = {
-	"arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache",
-	"memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter",
-	"multi-func adapter", "disk controller", "tp controller",
-	"cdrom controller", "worm controller", "serial controller",
-	"net controller", "display controller", "parallel controller",
-	"pointer controller", "keyboard controller", "audio controller",
-	"misc controller", "disk peripheral", "floppy peripheral",
-	"tp peripheral", "modem peripheral", "monitor peripheral",
-	"printer peripheral", "pointer peripheral", "keyboard peripheral",
-	"terminal peripheral", "line peripheral", "net peripheral",
-	"misc peripheral", "anonymous"
-};
-
-static char *iflags[] = {
-	"bogus", "read only", "removable", "console in", "console out",
-	"input", "output"
-};
-
-__initfunc(static void dump_component(pcomponent *p))
-{
-	prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>",
-		    p, classes[p->class], types[p->type],
-		    iflags[p->iflags], p->vers, p->rev);
-	prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n",
-		    p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
-}
-
-__initfunc(static void traverse(pcomponent *p, int op))
-{
-	dump_component(p);
-	if(prom_getchild(p))
-		traverse(prom_getchild(p), 1);
-	if(prom_getsibling(p) && op)
-		traverse(prom_getsibling(p), 1);
-}
-
-__initfunc(void prom_testtree(void))
-{
-	pcomponent *p;
-
-	p = prom_getchild(PROM_NULL_COMPONENT);
-	dump_component(p);
-	p = prom_getchild(p);
-	while(p) {
-		dump_component(p);
-		p = prom_getsibling(p);
-	}
-	prom_printf("press a key\n");
-	prom_getchar();
-}
-#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/Makefile linux.pre11.3/arch/mips/sni/Makefile
--- linux.vanilla/arch/mips/sni/Makefile	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/Makefile	Mon Jul 19 23:28:46 1999
@@ -1,3 +1,4 @@
+# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $
 #
 # Makefile for the SNI specific part of the kernel
 #
@@ -5,8 +6,6 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
-# $Id: Makefile,v 1.2 1997/12/20 13:27:14 ralf Exp $
-#
 
 .S.s:
 	$(CPP) $(CFLAGS) $< -o $*.s
@@ -15,7 +14,7 @@
 
 all: sni.o
 O_TARGET := sni.o
-O_OBJS	 := hw-access.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o
+O_OBJS	 := int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o
 
 int-handler.o: int-handler.S
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/hw-access.c linux.pre11.3/arch/mips/sni/hw-access.c
--- linux.vanilla/arch/mips/sni/hw-access.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/hw-access.c	Thu Jan  1 01:00:00 1970
@@ -1,70 +0,0 @@
-/* $Id: hw-access.c,v 1.8 1998/09/16 22:50:46 ralf Exp $
- *
- * Low-level hardware access stuff for SNI RM200 PCI
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/kbdcntrlr.h>
-#include <linux/kernel.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/dma.h>
-#include <asm/keyboard.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mc146818rtc.h>
-#include <asm/pgtable.h>
-#include <asm/sni.h>
-
-#define KBD_STAT_IBF		0x02	/* Keyboard input buffer full */
-
-static unsigned char sni_read_input(void)
-{
-	return inb(KBD_DATA_REG);
-}
-
-static void sni_write_output(unsigned char val)
-{
-	int status;
-
-	do {
-		status = inb(KBD_CNTL_REG);
-	} while (status & KBD_STAT_IBF);
-	outb(val, KBD_DATA_REG);
-}
-
-static void sni_write_command(unsigned char val)
-{
-	int status;
-
-	do {
-		status = inb(KBD_CNTL_REG);
-	} while (status & KBD_STAT_IBF);
-	outb(val, KBD_CNTL_REG);
-}
-
-static unsigned char sni_read_status(void)
-{
-	return inb(KBD_STATUS_REG);
-}
-
-__initfunc(void sni_rm200_keyboard_setup(void))
-{
-	kbd_read_input = sni_read_input;
-	kbd_write_output = sni_write_output;
-	kbd_write_command = sni_write_command;
-	kbd_read_status = sni_read_status;
-	request_irq(PCIMT_KEYBOARD_IRQ, keyboard_interrupt,
-	            0, "keyboard", NULL);
-	request_region(0x60, 16, "keyboard");
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/int-handler.S linux.pre11.3/arch/mips/sni/int-handler.S
--- linux.vanilla/arch/mips/sni/int-handler.S	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/int-handler.S	Mon Jul 19 23:28:46 1999
@@ -1,17 +1,22 @@
-/* $Id: int-handler.S,v 1.4 1998/05/07 14:17:47 ralf Exp $
+/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $
  *
  * SNI RM200 PCI specific interrupt handler code.
  *
  * Copyright (C) 1994 - 1997 by Ralf Baechle
  */
 #include <asm/asm.h>
-#include <linux/config.h>
 #include <asm/mipsconfig.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/sni.h>
 #include <asm/stackframe.h>
 
+/* The PCI ASIC has the nasty property that it may delay writes if it is busy.
+   As a consequence from writes that have not graduated when we exit from the
+   interrupt handler we might catch a spurious interrupt.  To avoid this we
+   force the PCI ASIC to graduate all writes by executing a read from the
+   PCI bus.  */
+
 		.set	noreorder
 		.set	noat
 		.align	5
@@ -20,34 +25,38 @@
 		CLI
 		.set	at
 
-		lb	t0,led_cache
-		addiu	t0,1
-		sb	t0,led_cache
-		sb	t0,PCIMT_CSLED
+		/* Blinken light ...  */
+		lb	t0, led_cache
+		addiu	t0, 1
+		sb	t0, led_cache
+		sb	t0, PCIMT_CSLED			# write only register
 		.data
 led_cache:	.byte	0
 		.text
 
-		mfc0	t0,CP0_STATUS
-		mfc0	t1,CP0_CAUSE
-		and	t0,t1
-
-		 andi	t1,t0,0x0800			# hardware interrupt 1
-		bnez	t1,hwint1
-		 andi	t1,t0,0x4000			# hardware interrupt 4
-		bnez	t1,eth_int
-
-		 andi	t1,t0,0x1000			# hardware interrupt 2
-		bnez	t1,hwint2
-		 andi	t1,t0,0x2000			# hardware interrupt 3
-		bnez	t1,hwint3
-		 andi	t1,t0,0x8000			# hardware interrupt 5
-		bnez	t1,hwint5
-		 andi	t1,t0,0x0400			# hardware interrupt 0
-		bnez	t1,hwint0
+		mfc0	t0, CP0_STATUS
+		mfc0	t1, CP0_CAUSE
+		and	t0, t1
+
+		/* The following interrupt dispatch tests for hwint 1 /
+		   EISA bridge first such that the timer interrupt get the
+		   highest priority.  */
+		 andi	t1, t0, 0x0800			# hardware interrupt 1
+		bnez	t1, hwint1
+		 andi	t1, t0, 0x4000			# hardware interrupt 4
+		bnez	t1, hwint4
+
+		 andi	t1, t0, 0x1000			# hardware interrupt 2
+		bnez	t1, hwint2
+		 andi	t1, t0, 0x2000			# hardware interrupt 3
+		bnez	t1, hwint3
+		 andi	t1, t0, 0x8000			# hardware interrupt 5
+		bnez	t1, hwint5
+		 andi	t1, t0, 0x0400			# hardware interrupt 0
+		bnez	t1, hwint0
 		 nop
 
-		j	spurious_interrupt		# Nothing up ...
+		j	return				# spurious interrupt
 		 nop
 
  ##############################################################################
@@ -57,146 +66,61 @@
 
  /* ------------------------------------------------------------------------ */
 
-hwint1:		lbu	t0,PCIMT_CSITPEND
-
-		 andi	t1,t0,0x20
-		bnez	t1,eisa_int
-
-#ifdef CONFIG_SCSI_NCR53C8XX
-		 andi	t1,t0,0x40
-		beqz	t1,scsi_int
-#endif
-		 nop
-
-		j	spurious_interrupt
-		 nop
-
- /* ------------------------------------------------------------------------ */
-
-hwint0:		lbu	t0,PCIMT_CSITPEND
-
-		 andi	t1,t0,0x01
-		beqz	t1,int2
+/* hwint1 deals with EISA and SCSI interrupts.  */
+hwint1:		lbu	s0, PCIMT_CSITPEND
 
-go_spurious:	j	spurious_interrupt		# we got fooled
+		andi	t1, s0, 0x20
+		beqz	t1, 1f
+		 andi	s1, s0, 0x40
+		lbu	a0, PCIMT_INT_ACKNOWLEDGE	# IACK cycle
+		xori	t0, a0, 0xff
+		beqz	t0, 1f				# spurious interrupt?
 		 nop
+		jal	i8259_do_irq			# call real handler
+		 move	a1, sp
 
-eisa_int:	lui	s0,%hi(SNI_PORT_BASE)
-		li	a0,0x0f
-		sb	a0,%lo(SNI_PORT_BASE+0x20)(s0)	# poll command
-		lb	a0,%lo(SNI_PORT_BASE+0x20)(s0)	# read result
-		bgtz	a0,poll_second
-		 andi	a0,7
-		beq	a0,2,poll_second		# cascade?
-		 li	s1,1
-		/*
-		 * Acknowledge first pic
-		 */
-		lb	t2,%lo(SNI_PORT_BASE+0x21)(s0)
-		lui	s4,%hi(cache_21)
-		lb	t0,%lo(cache_21)(s4)
-		sllv	s1,s1,a0
-		or	t0,s1
-		sb	t0,%lo(cache_21)(s4)
-		sb	t0,%lo(SNI_PORT_BASE+0x21)(s0)
-		li	t2,0x20
-		sb	t2,%lo(SNI_PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
+1:		bnez	s1, 1f
+		 li	a0, PCIMT_IRQ_SCSI
 		jal	do_IRQ
-		 move	a1,sp
-		/*
-		 * Unblock first pic
-		 */
-		lbu	t1,%lo(SNI_PORT_BASE+0x21)(s0)
-		lb	t1,%lo(cache_21)(s4)
-		nor	s1,zero,s1
-		and	t1,s1
-		sb	t1,%lo(cache_21)(s4)
-		j	ret_from_irq
-		 sb	t1,%lo(SNI_PORT_BASE+0x21)(s0)
+		 move	a1, sp
 
-		/*
-		 * Cascade interrupt from second PIC
-		 */
-		.align	5
-poll_second:	li	a0,0x0f
-		sb	a0,%lo(SNI_PORT_BASE+0xa0)(s0)	# poll command
-		lb	a0,%lo(SNI_PORT_BASE+0xa0)(s0)	# read result
-		bgtz	a0,go_spurious
-		 andi	a0,7
-		/*
-		 * Acknowledge second pic
-		 */
-		lbu	t2,%lo(SNI_PORT_BASE+0xa1)(s0)
-		lui	s4,%hi(cache_A1)
-		lb	t3,%lo(cache_A1)(s4)
-		sllv	s1,s1,a0
-		or	t3,s1
-		sb	t3,%lo(cache_A1)(s4)
-		sb	t3,%lo(SNI_PORT_BASE+0xa1)(s0)
-		li	t3,0x20
-		sb	t3,%lo(SNI_PORT_BASE+0xa0)(s0)
-		sb	t3,%lo(SNI_PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		addiu	a0,8
-		jal	do_IRQ
-		 move	a1,sp
-		/*
-		 * Unblock second pic
-		 */
-		lb	t1,%lo(SNI_PORT_BASE+0xa1)(s0)
-		lb	t1,%lo(cache_A1)(s4)
-		subu	t0,1
-		nor	s1,zero,s1
-		and	t1,t1,s1
-		sb	t1,%lo(cache_A1)(s4)
+1:		lui	t0, %hi(PCIMT_CSITPEND)
 		j	ret_from_irq
-		 sb	t1,%lo(SNI_PORT_BASE+0xa1)(s0)
-
-/*
- * ... check if we were interrupted by the Lance ...
- */
-eth_int:	mfc0	s0,CP0_STATUS
-		ori	t0,s0,0x4000
-		xori	t0,0x4000
-		mtc0	t0,CP0_STATUS
+		 lbu	zero, %lo(PCIMT_CSITPEND)(t0)
 
-		li	a0,PCIMT_IRQ_ETHERNET
-		jal	do_IRQ
-		 move	a1,sp
+ /* ------------------------------------------------------------------------ */
 
-		mtc0	s0,CP0_STATUS
+/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
+   button interrupts.  */
+hwint0:		PANIC("Received int0 but no handler yet ...\n")
+1:		j	1b
+		 nop
 
-		j	ret_from_irq
+go_spurious:	j	spurious_interrupt		# we got fooled
 		 nop
 
-#ifdef CONFIG_SCSI_NCR53C8XX
+/* hwint4 is used for only the onboard PCnet 32.  */
+hwint4:		mfc0	s0, CP0_STATUS
+		ori	t0, s0, 0x4000
+		xori	t0, 0x4000
+		mtc0	t0, CP0_STATUS
 
-/*
- * ... check if we were interrupted by the NCR ...
- */
-scsi_int:	li	a0,PCIMT_IRQ_SCSI
+		li	a0, PCIMT_IRQ_ETHERNET
 		jal	do_IRQ
-		 move	a1,sp
-		j	ret_from_irq
-		 nop
-
-#endif /* CONFIG_SCSI_NCR53C8XX */
+		 move	a1, sp
 
-pci_int:	PANIC("Received PCI interrupt but no handler yet ...\n")
-1:		j	1b
-		 nop
+		mtc0	s0, CP0_STATUS
 
-int2:		PANIC("Received int2 but no handler yet ...\n")
-1:		j	1b
+		j	ret_from_irq
 		 nop
 
+/* This interrupt was used for the com1 console on the first prototypes.  */
 hwint2:		PANIC("hwint2 and no handler yet")
+
+/* hwint3 should deal with the PCI A - D interrupts.  */
 hwint3:		PANIC("hwint3 and no handler yet")
+
+/* hwint5 is the r4k count / compare interrupt  */
 hwint5:		PANIC("hwint5 and no handler yet")
 
 		END(sni_rm200_pci_handle_int)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/io.c linux.pre11.3/arch/mips/sni/io.c
--- linux.vanilla/arch/mips/sni/io.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/io.c	Mon Jul 19 23:28:46 1999
@@ -1,11 +1,10 @@
-/*
+/* $Id: io.c,v 1.3 1999/01/04 16:03:58 ralf Exp $
+ *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Low level I/O functions for SNI.
- *
- * $Id: io.c,v 1.2 1998/03/27 08:53:50 ralf Exp $
  */
 #include <linux/string.h>
 #include <asm/mipsconfig.h>
@@ -14,46 +13,42 @@
 #include <asm/spinlock.h>
 #include <asm/sni.h>
 
-unsigned char sni_map_isa_cache;
-
-#define unused __attribute__((unused))
-
-/*
- * The PCIMT_CSMAPISA is shared by all processors; we need locking.
- *
- * XXX It's legal to use all the I/O memory access functions in interrupt
- * code, so we need to use the _irq locking stuff which may result in
- * significant IRQ latencies.
- */
-static spinlock_t csmapisa_lock unused = SPIN_LOCK_UNLOCKED;
-
 /*
  * Urgs...  We only can see a 16mb window of the 4gb EISA address space
  * at PCIMT_EISA_BASE.  Maladia segmentitis ...
  *
- * XXX Check out if accessing PCIMT_CSMAPISA really is slow.
- * For now assume so.
+ * To avoid locking and all the related headacke we implement this such
+ * that accessing the bus address space nests, so we're treating this
+ * correctly even for interrupts.  This is going to suck seriously for
+ * the SMP members of the RM family.
+ *
+ * Making things worse the PCIMT_CSMAPISA register resides on the X bus with
+ * it's unbeatable 1.4 mb/s transfer rate.
  */
-static inline void update_isa_cache(unsigned long address)
+
+static inline void eisa_map(unsigned long address)
 {
 	unsigned char upper;
 
 	upper = address >> 24;
-	if (sni_map_isa_cache != upper) {
-		sni_map_isa_cache = upper;
-		*(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
-	}
+	*(volatile unsigned char *)PCIMT_CSMAPISA = ~upper;
 }
 
+#define save_eisa_map()							\
+	(*(volatile unsigned char *)PCIMT_CSMAPISA)
+#define restore_eisa_map(val)						\
+	do { (*(volatile unsigned char *)PCIMT_CSMAPISA) = val; } while(0)
+
 static unsigned char sni_readb(unsigned long addr)
 {
 	unsigned char res;
+	unsigned int save_map;
 
-	spin_lock_irq(&csmapisa_lock);
-	update_isa_cache(addr);
+	save_map = save_eisa_map();
+	eisa_map(addr);
 	addr &= 0xffffff;
 	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 
 	return res;
 }
@@ -61,12 +56,13 @@
 static unsigned short sni_readw(unsigned long addr)
 {
 	unsigned short res;
+	unsigned int save_map;
 
-	spin_lock_irq(&csmapisa_lock);
-	update_isa_cache(addr);
+	save_map = save_eisa_map();
+	eisa_map(addr);
 	addr &= 0xffffff;
 	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 
 	return res;
 }
@@ -74,101 +70,111 @@
 static unsigned int sni_readl(unsigned long addr)
 {
 	unsigned int res;
+	unsigned int save_map;
 
-	spin_lock_irq(&csmapisa_lock);
-	update_isa_cache(addr);
+	save_map = save_eisa_map();
+	eisa_map(addr);
 	addr &= 0xffffff;
 	res = *(volatile unsigned char *) (PCIMT_EISA_BASE + addr);
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 
 	return res;
 }
 
 static void sni_writeb(unsigned char val, unsigned long addr)
 {
-	spin_lock_irq(&csmapisa_lock);
-	update_isa_cache(addr);
+	unsigned int save_map;
+
+	save_map = save_eisa_map();
+	eisa_map(addr);
 	addr &= 0xffffff;
 	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 }
 
 static void sni_writew(unsigned short val, unsigned long addr)
 {
-	spin_lock_irq(&csmapisa_lock);
-	update_isa_cache(addr);
+	unsigned int save_map;
+
+	save_map = save_eisa_map();
+	eisa_map(addr);
 	addr &= 0xffffff;
 	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 }
 
 static void sni_writel(unsigned int val, unsigned long addr)
 {
-	spin_lock_irq(&csmapisa_lock);
-	update_isa_cache(addr);
+	unsigned int save_map;
+
+	save_map = save_eisa_map();
+	eisa_map(addr);
 	addr &= 0xffffff;
 	*(volatile unsigned char *) (PCIMT_EISA_BASE + addr) = val;
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 }
 
 static void sni_memset_io(unsigned long addr, int val, unsigned long len)
 {
 	unsigned long waddr;
+	unsigned int save_map;
 
+	save_map = save_eisa_map();
 	waddr = PCIMT_EISA_BASE | (addr & 0xffffff);
-	spin_lock_irq(&csmapisa_lock);
 	while(len) {
 		unsigned long fraglen;
 
 		fraglen = (~addr + 1) & 0xffffff;
 		fraglen = (fraglen < len) ? fraglen : len;
-		update_isa_cache(addr);
+		eisa_map(addr);
 		memset((char *)waddr, val, fraglen);
 		addr += fraglen;
 		waddr = waddr + fraglen - 0x1000000;
 		len -= fraglen;
 	}
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 }
 
 static void sni_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
 {
 	unsigned long waddr;
+	unsigned int save_map;
 
+	save_map = save_eisa_map();
 	waddr = PCIMT_EISA_BASE | (from & 0xffffff);
-	spin_lock_irq(&csmapisa_lock);
 	while(len) {
 		unsigned long fraglen;
 
 		fraglen = (~from + 1) & 0xffffff;
 		fraglen = (fraglen < len) ? fraglen : len;
-		update_isa_cache(from);
+		eisa_map(from);
 		memcpy((void *)to, (void *)waddr, fraglen);
 		to += fraglen;
 		from += fraglen;
 		waddr = waddr + fraglen - 0x1000000;
 		len -= fraglen;
 	}
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 }
 
 static void sni_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
 {
 	unsigned long waddr;
+	unsigned int save_map;
 
+	save_map = save_eisa_map();
 	waddr = PCIMT_EISA_BASE | (to & 0xffffff);
-	spin_lock_irq(&csmapisa_lock);
 	while(len) {
 		unsigned long fraglen;
 
 		fraglen = (~to + 1) & 0xffffff;
 		fraglen = (fraglen < len) ? fraglen : len;
-		update_isa_cache(to);
+		eisa_map(to);
 		memcpy((char *)to + PCIMT_EISA_BASE, (void *)from, fraglen);
 		to += fraglen;
 		from += fraglen;
 		waddr = waddr + fraglen - 0x1000000;
 		len -= fraglen;
 	}
-	spin_unlock_irq(&csmapisa_lock);
+	restore_eisa_map(save_map);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/pci.c linux.pre11.3/arch/mips/sni/pci.c
--- linux.vanilla/arch/mips/sni/pci.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/pci.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.6 1998/05/07 14:17:48 ralf Exp $
+/* $Id: pci.c,v 1.7 1999/01/04 16:03:58 ralf Exp $
  *
  * 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
@@ -9,6 +9,7 @@
  * Copyright (C) 1997, 1998 Ralf Baechle
  */
 #include <linux/config.h>
+#include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
@@ -28,13 +29,37 @@
 
 static void sni_rm200_pcibios_fixup (void)
 {
-	/*
-	 * TODO: Fix PCI_INTERRUPT_LINE register for onboard cards.
-	 * Take care of RM300 revision D boards for where the network
-	 * slot became an ordinary PCI slot.
-	 */
-	pcibios_write_config_byte(0, PCI_DEVFN(1, 0), PCI_INTERRUPT_LINE,
-	                          PCIMT_IRQ_SCSI);
+	struct pci_dev *dev;
+
+	for (dev=pci_devices; dev; dev=dev->next) {
+		/*
+		 * TODO: Take care of RM300 revision D boards for where the
+		 * network slot became an ordinary PCI slot.
+		 */
+		if (dev->devfn == PCI_DEVFN(1, 0)) {
+			/* Evil hack ...  */
+			set_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NO_WA);
+			dev->irq = PCIMT_IRQ_SCSI;
+			continue;
+		}
+		if (dev->devfn == PCI_DEVFN(2, 0)) {
+			dev->irq = PCIMT_IRQ_ETHERNET;
+			continue;
+		}
+
+		switch(dev->irq) {
+		case 1 ... 4:
+			dev->irq += PCIMT_IRQ_INTA - 1;
+			break;
+		case 0:
+			break;
+		default:
+			printk("PCI device on bus %d, dev %d, function %d "
+			       "impossible interrupt configured.\n",
+			       dev->bus->number, PCI_SLOT(dev->devfn),
+			       PCI_SLOT(dev->devfn));
+		}
+	}
 }
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/pcimt_scache.c linux.pre11.3/arch/mips/sni/pcimt_scache.c
--- linux.vanilla/arch/mips/sni/pcimt_scache.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/pcimt_scache.c	Mon Jul 19 23:28:46 1999
@@ -1,35 +1,38 @@
-/*
+/* $Id: pcimt_scache.c,v 1.4 1999/01/04 16:03:59 ralf Exp $
+ *
  * arch/mips/sni/pcimt_scache.c
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) 1997 by Ralf Baechle
- *
- * $Id: pcimt_scache.c,v 1.2 1998/05/28 03:18:02 ralf Exp $
+ * Copyright (c) 1997, 1998 by Ralf Baechle
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <asm/bcache.h>
 #include <asm/sni.h>
 
+#define cacheconf (*(volatile unsigned int *)PCIMT_CACHECONF)
+#define invspace (*(volatile unsigned int *)PCIMT_INVSPACE)
+
 __initfunc(void sni_pcimt_sc_init(void))
 {
-	unsigned int cacheconf, sc_size;
+	unsigned int scsiz, sc_size;
 
-	cacheconf = *(volatile unsigned int *)PCIMT_CACHECONF;
-	if ((cacheconf & 7) == 0) {
-		printk("No second level cache detected\n");
-		printk("WARNING: not activating second level cache, "
-		       "tell ralf@gnu.org\n");
+	scsiz = cacheconf & 7;
+	if (scsiz == 0) {
+		printk("Second level cache is deactived.\n");
 		return;
 	}
-	if ((cacheconf & 7) >= 6) {
-		printk("Invalid second level cache size detected\n");
+	if (scsiz >= 6) {
+		printk("Invalid second level cache size configured, "
+		       "deactivating second level cache.\n");
+		cacheconf = 0;
 		return;
 	}
-	
-	sc_size = 128 << (cacheconf & 7);
-	printk("%dkb second level cache detected.\n", sc_size);
+
+	sc_size = 128 << scsiz;
+	printk("%dkb second level cache detected, deactivating.\n", sc_size);
+	cacheconf = 0;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/sni/setup.c linux.pre11.3/arch/mips/sni/setup.c
--- linux.vanilla/arch/mips/sni/setup.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/sni/setup.c	Mon Jul 19 23:28:46 1999
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.13 1998/08/17 13:57:45 ralf Exp $
+/* $Id: setup.c,v 1.10 1999/01/04 16:03:59 ralf Exp $
  *
  * Setup pointers to hardware-dependent routines.
  *
@@ -17,6 +17,11 @@
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/pci.h>
+#include <linux/mc146818rtc.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/pc_keyb.h>
+
 #include <asm/bcache.h>
 #include <asm/bootinfo.h>
 #include <asm/keyboard.h>
@@ -39,7 +44,6 @@
 static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
 
 extern asmlinkage void sni_rm200_pci_handle_int(void);
-extern void sni_rm200_keyboard_setup(void);
 
 extern void sni_machine_restart(char *command);
 extern void sni_machine_halt(void);
@@ -47,19 +51,20 @@
 
 extern struct ide_ops std_ide_ops;
 extern struct rtc_ops std_rtc_ops;
+extern struct kbd_ops std_kbd_ops;
 
 __initfunc(static void sni_irq_setup(void))
 {
 	set_except_vector(0, sni_rm200_pci_handle_int);
 	request_region(0x20,0x20, "pic1");
 	request_region(0xa0,0x20, "pic2");	
-	setup_x86_irq(2, &irq2);
+	i8259_setup_irq(2, &irq2);
 	/*
 	 * IRQ0 seems to be the irq for PC style stuff.
 	 * I don't know how to handle the debug button interrupt, so
 	 * don't use this button yet or bad things happen ...
 	 */
-	set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ4);
+	set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ3 | IE_IRQ4);
 }
 
 void (*board_time_init)(struct irqaction *irq);
@@ -70,7 +75,7 @@
 	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
 	outb_p(LATCH & 0xff , 0x40);	/* LSB */
 	outb(LATCH >> 8 , 0x40);	/* MSB */
-	setup_x86_irq(0, irq);
+	i8259_setup_irq(0, irq);
 }
 
 unsigned char aux_device_present;
@@ -132,7 +137,6 @@
 
 	irq_setup = sni_irq_setup;
 	mips_io_port_base = SNI_PORT_BASE;
-	keyboard_setup = sni_rm200_keyboard_setup;
 
 	/*
 	 * Setup (E)ISA I/O memory access stuff
@@ -165,6 +169,10 @@
 #ifdef CONFIG_BLK_DEV_IDE
 	ide_ops = &std_ide_ops;
 #endif
-
+	conswitchp = &vga_con;
 	rtc_ops = &std_rtc_ops;
+	kbd_ops = &std_kbd_ops;
+#ifdef CONFIG_PSMOUSE
+	aux_device_present = 0xaa;
+#endif
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/tools/Makefile linux.pre11.3/arch/mips/tools/Makefile
--- linux.vanilla/arch/mips/tools/Makefile	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/tools/Makefile	Mon Jul 19 23:28:47 1999
@@ -3,7 +3,7 @@
 # Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
 # Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu)
 #
-# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $
+# $Id: Makefile,v 1.2 1997/12/01 17:57:41 ralf Exp $
 #
 TARGET	:= $(TOPDIR)/include/asm-$(ARCH)/offset.h
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/mips/tools/offset.c linux.pre11.3/arch/mips/tools/offset.c
--- linux.vanilla/arch/mips/tools/offset.c	Sun Nov  8 15:08:32 1998
+++ linux.pre11.3/arch/mips/tools/offset.c	Mon Jul 19 23:28:47 1999
@@ -1,4 +1,4 @@
-/* $Id: offset.c,v 1.10 1998/08/19 21:53:53 ralf Exp $
+/* $Id: offset.c,v 1.9 1998/08/25 09:14:52 ralf Exp $
  *
  * offset.c: Calculate pt_regs and task_struct offsets.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/amiga/amiints.c linux.pre11.3/arch/ppc/amiga/amiints.c
--- linux.vanilla/arch/ppc/amiga/amiints.c	Sat Jan  9 21:50:36 1999
+++ linux.pre11.3/arch/ppc/amiga/amiints.c	Mon Jul 19 23:28:50 1999
@@ -108,7 +108,7 @@
 	custom.intreq = 0x7fff;
 
 #ifdef CONFIG_APUS
-	/* Clear any inter-CPU interupt requests. Circumvents bug in
+	/* Clear any inter-CPU interrupt requests. Circumvents bug in
            Blizzard IPL emulation HW (or so it appears). */
 	APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK);
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/amiga/config.c linux.pre11.3/arch/ppc/amiga/config.c
--- linux.vanilla/arch/ppc/amiga/config.c	Tue Dec 22 23:19:31 1998
+++ linux.pre11.3/arch/ppc/amiga/config.c	Mon Jul 19 23:53:55 1999
@@ -30,7 +30,6 @@
 #include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
-#include <linux/init.h>
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/irq.c linux.pre11.3/arch/ppc/kernel/irq.c
--- linux.vanilla/arch/ppc/kernel/irq.c	Tue Jun 15 16:49:46 1999
+++ linux.pre11.3/arch/ppc/kernel/irq.c	Mon Jul 19 23:53:55 1999
@@ -50,7 +50,6 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
-#include <asm/bitops.h>
 #include <asm/gg2.h>
 #include <asm/cache.h>
 #include <asm/prom.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/pci.c linux.pre11.3/arch/ppc/kernel/pci.c
--- linux.vanilla/arch/ppc/kernel/pci.c	Thu May 27 22:11:50 1999
+++ linux.pre11.3/arch/ppc/kernel/pci.c	Mon Jul 19 23:53:55 1999
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/config.h>
-#include <linux/pci.h>
 #include <linux/openpic.h>
 
 #include <asm/processor.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/pmac_setup.c linux.pre11.3/arch/ppc/kernel/pmac_setup.c
--- linux.vanilla/arch/ppc/kernel/pmac_setup.c	Thu May 27 22:11:50 1999
+++ linux.pre11.3/arch/ppc/kernel/pmac_setup.c	Mon Jul 19 23:28:48 1999
@@ -48,6 +48,7 @@
 #include <asm/io.h>
 #include <asm/pci-bridge.h>
 #include <asm/adb.h>
+#include <asm/dma.h>
 #include <asm/cuda.h>
 #include <asm/pmu.h>
 #include <asm/ohare.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/ppc-stub.c linux.pre11.3/arch/ppc/kernel/ppc-stub.c
--- linux.vanilla/arch/ppc/kernel/ppc-stub.c	Sun Nov  8 15:08:33 1998
+++ linux.pre11.3/arch/ppc/kernel/ppc-stub.c	Mon Jul 19 23:53:55 1999
@@ -107,7 +107,6 @@
 
 #include <asm/system.h>
 #include <asm/signal.h>
-#include <asm/system.h>
 #include <asm/kgdb.h>
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/process.c linux.pre11.3/arch/ppc/kernel/process.c
--- linux.vanilla/arch/ppc/kernel/process.c	Thu May 27 22:11:50 1999
+++ linux.pre11.3/arch/ppc/kernel/process.c	Mon Jul 19 23:53:55 1999
@@ -31,7 +31,6 @@
 #include <linux/malloc.h>
 #include <linux/user.h>
 #include <linux/elf.h>
-#include <linux/elf.h>
 #include <linux/init.h>
 
 #include <asm/pgtable.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/setup.c linux.pre11.3/arch/ppc/kernel/setup.c
--- linux.vanilla/arch/ppc/kernel/setup.c	Tue Jun 15 16:49:47 1999
+++ linux.pre11.3/arch/ppc/kernel/setup.c	Mon Jul 19 23:53:55 1999
@@ -31,7 +31,6 @@
 #endif
 #include <asm/bootx.h>
 #include <asm/machdep.h>
-#include <asm/ide.h>
 
 extern void pmac_init(unsigned long r3,
                       unsigned long r4,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/ppc/kernel/syscalls.c linux.pre11.3/arch/ppc/kernel/syscalls.c
--- linux.vanilla/arch/ppc/kernel/syscalls.c	Tue Jun 15 16:49:47 1999
+++ linux.pre11.3/arch/ppc/kernel/syscalls.c	Mon Jul 19 23:53:55 1999
@@ -30,6 +30,7 @@
 #include <linux/shm.h>
 #include <linux/stat.h>
 #include <linux/mman.h>
+#include <linux/file.h>
 #include <linux/sys.h>
 #include <linux/ipc.h>
 #include <linux/utsname.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/ap1000/aplib.c linux.pre11.3/arch/sparc/ap1000/aplib.c
--- linux.vanilla/arch/sparc/ap1000/aplib.c	Sun Nov  8 15:08:28 1998
+++ linux.pre11.3/arch/sparc/ap1000/aplib.c	Mon Jul 19 23:53:56 1999
@@ -27,7 +27,6 @@
 #include <asm/segment.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
-#include <asm/segment.h>
 #include <asm/uaccess.h>
 
  #include <asm/ap1000/pgtapmmu.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/defconfig linux.pre11.3/arch/sparc/defconfig
--- linux.vanilla/arch/sparc/defconfig	Tue Jun 15 16:49:47 1999
+++ linux.pre11.3/arch/sparc/defconfig	Mon Jul 19 23:28:34 1999
@@ -254,7 +254,6 @@
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
-CONFIG_SMB_WIN95=y
 CONFIG_NCP_FS=m
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/pcic.c linux.pre11.3/arch/sparc/kernel/pcic.c
--- linux.vanilla/arch/sparc/kernel/pcic.c	Wed Mar 24 10:55:12 1999
+++ linux.pre11.3/arch/sparc/kernel/pcic.c	Mon Jul 19 23:53:56 1999
@@ -35,7 +35,6 @@
 #include <linux/timex.h>
 #include <linux/interrupt.h>
 
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/oplib.h>
 #include <asm/pcic.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/process.c linux.pre11.3/arch/sparc/kernel/process.c
--- linux.vanilla/arch/sparc/kernel/process.c	Thu May 27 22:11:51 1999
+++ linux.pre11.3/arch/sparc/kernel/process.c	Mon Jul 19 23:53:56 1999
@@ -37,7 +37,6 @@
 #include <asm/delay.h>
 #include <asm/processor.h>
 #include <asm/psr.h>
-#include <asm/system.h>
 #include <asm/elf.h>
 
 extern void fpsave(unsigned long *, unsigned long *, void *, unsigned long *);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/sparc-stub.c linux.pre11.3/arch/sparc/kernel/sparc-stub.c
--- linux.vanilla/arch/sparc/kernel/sparc-stub.c	Sun Nov  8 15:08:26 1998
+++ linux.pre11.3/arch/sparc/kernel/sparc-stub.c	Mon Jul 19 23:53:56 1999
@@ -105,7 +105,6 @@
 #include <asm/oplib.h>
 #include <asm/head.h>
 #include <asm/traps.h>
-#include <asm/system.h>
 #include <asm/vac-ops.h>
 #include <asm/kgdb.h>
 #include <asm/pgtable.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/sparc_ksyms.c linux.pre11.3/arch/sparc/kernel/sparc_ksyms.c
--- linux.vanilla/arch/sparc/kernel/sparc_ksyms.c	Wed Mar 24 10:55:12 1999
+++ linux.pre11.3/arch/sparc/kernel/sparc_ksyms.c	Mon Jul 19 23:54:04 1999
@@ -40,7 +40,6 @@
 #include <asm/dma.h>
 #endif
 #include <asm/a.out.h>
-#include <asm/spinlock.h>
 #include <asm/io-unit.h>
 
 struct poll {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/kernel/sys_sunos.c linux.pre11.3/arch/sparc/kernel/sys_sunos.c
--- linux.vanilla/arch/sparc/kernel/sys_sunos.c	Tue Jun 15 16:49:47 1999
+++ linux.pre11.3/arch/sparc/kernel/sys_sunos.c	Mon Jul 19 23:54:04 1999
@@ -26,7 +26,6 @@
 #include <linux/signal.h>
 #include <linux/uio.h>
 #include <linux/utsname.h>
-#include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/stat.h>
 #include <linux/malloc.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/mm/fault.c linux.pre11.3/arch/sparc/mm/fault.c
--- linux.vanilla/arch/sparc/mm/fault.c	Wed Mar 24 10:55:12 1999
+++ linux.pre11.3/arch/sparc/mm/fault.c	Mon Jul 19 23:54:04 1999
@@ -17,7 +17,6 @@
 #include <linux/smp.h>
 #include <linux/signal.h>
 #include <linux/mm.h>
-#include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc/mm/init.c linux.pre11.3/arch/sparc/mm/init.c
--- linux.vanilla/arch/sparc/mm/init.c	Wed Apr 28 19:14:25 1999
+++ linux.pre11.3/arch/sparc/mm/init.c	Mon Jul 19 23:28:35 1999
@@ -245,7 +245,7 @@
 	struct page *page, *end;
 
 	/* Saves us work later. */
-	memset((void *) ZERO_PAGE, 0, PAGE_SIZE);
+	memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE);
 
 	end_mem &= PAGE_MASK;
 	max_mapnr = MAP_NR(end_mem);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/config.in linux.pre11.3/arch/sparc64/config.in
--- linux.vanilla/arch/sparc64/config.in	Wed Apr 28 19:14:25 1999
+++ linux.pre11.3/arch/sparc64/config.in	Mon Jul 19 23:28:53 1999
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.66 1999/03/29 05:08:42 davem Exp $
+# $Id: config.in,v 1.67 1999/05/01 09:17:37 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -235,6 +235,16 @@
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
 	int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Video For Linux'
+tristate 'Video For Linux' CONFIG_VIDEO_DEV
+if [ "$CONFIG_VIDEO_DEV" != "n" ]; then
+  if [ "$CONFIG_PCI" != "n" ]; then
+    dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+  fi
 fi
 endmenu
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/defconfig linux.pre11.3/arch/sparc64/defconfig
--- linux.vanilla/arch/sparc64/defconfig	Tue Jun 15 16:49:47 1999
+++ linux.pre11.3/arch/sparc64/defconfig	Mon Jul 19 23:28:53 1999
@@ -257,6 +257,12 @@
 CONFIG_UNIX98_PTY_COUNT=256
 
 #
+# Video For Linux
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_BT848=y
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
@@ -292,7 +298,6 @@
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
-CONFIG_SMB_WIN95=y
 CONFIG_NCP_FS=m
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/binfmt_aout32.c linux.pre11.3/arch/sparc64/kernel/binfmt_aout32.c
--- linux.vanilla/arch/sparc64/kernel/binfmt_aout32.c	Wed Mar 24 10:55:13 1999
+++ linux.pre11.3/arch/sparc64/kernel/binfmt_aout32.c	Mon Jul 19 23:28:53 1999
@@ -57,8 +57,19 @@
  * These are the only things you should do on a core-file: use only these
  * macros to write out all the necessary info.
  */
-#define DUMP_WRITE(addr,nr) \
-while (file->f_op->write(file,(char *)(addr),(nr),&file->f_pos) != (nr)) goto close_coredump
+
+static int dump_write(struct file *file, const void *addr, int nr)
+{
+	int r;
+	down(&file->f_dentry->d_inode->i_sem);
+	r = file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+	up(&file->f_dentry->d_inode->i_sem);
+	return r;
+}
+
+#define DUMP_WRITE(addr, nr)	\
+	if (!dump_write(file, (void *)(addr), (nr))) \
+		goto close_coredump;
 
 #define DUMP_SEEK(offset) \
 if (file->f_op->llseek) { \
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/psycho.c linux.pre11.3/arch/sparc64/kernel/psycho.c
--- linux.vanilla/arch/sparc64/kernel/psycho.c	Wed Apr 28 19:14:25 1999
+++ linux.pre11.3/arch/sparc64/kernel/psycho.c	Mon Jul 19 23:28:53 1999
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.85 1999/04/02 14:54:28 davem Exp $
+/* $Id: psycho.c,v 1.85.2.1 1999/07/01 10:41:16 davem Exp $
  * psycho.c: Ultra/AX U2P PCI controller support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -757,13 +757,15 @@
 	unsigned short stmp;
 	unsigned int itmp;
 
+#if 0
 	for(pdev = pci_devices; pdev; pdev = pdev->next) {
 		if(pdev->vendor == PCI_VENDOR_ID_SUN &&
 		   pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 			break;
 		}
 	}
+#endif
 	for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
 		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -795,13 +797,14 @@
 			pci_read_config_dword(pdev, APB_PCI_CONTROL_LOW, &itmp);
 			itmp = APB_PCI_CTL_LOW_ERRINT_EN | 0x0f;
 			pci_write_config_dword(pdev, APB_PCI_CONTROL_LOW, itmp);
-
+#if 0
 			/* Don't mess with the retry limit and PIO/DMA latency
 			 * timer settings.  But do set primary and secondary
 			 * latency timers.
 			 */
-			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
-			pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 128);
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+			pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, 64);
+#endif
 		}
 	}
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/sparc64_ksyms.c linux.pre11.3/arch/sparc64/kernel/sparc64_ksyms.c
--- linux.vanilla/arch/sparc64/kernel/sparc64_ksyms.c	Thu May 27 22:11:51 1999
+++ linux.pre11.3/arch/sparc64/kernel/sparc64_ksyms.c	Mon Jul 19 23:28:53 1999
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.58 1999/05/08 03:00:31 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.58.2.1 1999/06/28 11:27:57 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -206,6 +206,7 @@
 
 /* Kernel thread creation. */
 EXPORT_SYMBOL(kernel_thread);
+EXPORT_SYMBOL(init_mm);
 
 /* prom symbols */
 EXPORT_SYMBOL(idprom);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/kernel/sys_sunos32.c linux.pre11.3/arch/sparc64/kernel/sys_sunos32.c
--- linux.vanilla/arch/sparc64/kernel/sys_sunos32.c	Tue Jun 15 16:49:47 1999
+++ linux.pre11.3/arch/sparc64/kernel/sys_sunos32.c	Mon Jul 19 23:54:30 1999
@@ -25,7 +25,6 @@
 #include <linux/signal.h>
 #include <linux/uio.h>
 #include <linux/utsname.h>
-#include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/stat.h>
 #include <linux/malloc.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/mm/init.c linux.pre11.3/arch/sparc64/mm/init.c
--- linux.vanilla/arch/sparc64/mm/init.c	Thu May 27 22:11:51 1999
+++ linux.pre11.3/arch/sparc64/mm/init.c	Mon Jul 19 23:28:55 1999
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.127 1999/05/08 03:00:38 davem Exp $
+/*  $Id: init.c,v 1.127.2.1 1999/06/25 10:42:10 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -418,10 +418,12 @@
 	}
 
 	if (iommu->strbuf_enabled) {
+		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
 		spin_lock_irqsave(&iommu->iommu_lock, flags);
 		iommu->flushflag = 0;
 		while(start < end) {
-			sregs->sbuf_pflush = start;
+			*sbuf_pflush = start;
 			start += PAGE_SIZE;
 		}
 		sregs->sbuf_fsync = __pa(&(iommu->flushflag));
@@ -446,6 +448,8 @@
 	start &= PAGE_MASK;
 
 	if (iommu->strbuf_enabled) {
+		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
 		spin_lock_irqsave(&iommu->iommu_lock, flags);
 
 		/* 1) Clear the flush flag word */
@@ -455,7 +459,7 @@
 		 *    we want flushed.
 		 */
 		while(start < end) {
-			sregs->sbuf_pflush = start;
+			*sbuf_pflush = start;
 			start += PAGE_SIZE;
 		}
 
@@ -483,6 +487,8 @@
 	volatile u64 *sbctrl = (volatile u64 *) &sregs->sbus_control;
 
 	if (iommu->strbuf_enabled) {
+		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
 		spin_lock_irqsave(&iommu->iommu_lock, flags);
 		iommu->flushflag = 0;
 
@@ -499,7 +505,7 @@
 			sg[sz--].dvma_addr = sbus_dvma_addr(start);
 			start &= PAGE_MASK;
 			while(start < end) {
-				sregs->sbuf_pflush = start;
+				*sbuf_pflush = start;
 				start += PAGE_SIZE;
 			}
 		}
@@ -534,6 +540,8 @@
 	unsigned long flags, tmp;
 
 	if (iommu->strbuf_enabled) {
+		volatile u64 *sbuf_pflush = (volatile u64 *) &sregs->sbuf_pflush;
+
 		spin_lock_irqsave(&iommu->iommu_lock, flags);
 
 		/* 1) Clear the flush flag word */
@@ -548,7 +556,7 @@
 
 			start &= PAGE_MASK;
 			while(start < end) {
-				sregs->sbuf_pflush = start;
+				*sbuf_pflush = start;
 				start += PAGE_SIZE;
 			}
 			sz--;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/arch/sparc64/solaris/socksys.c linux.pre11.3/arch/sparc64/solaris/socksys.c
--- linux.vanilla/arch/sparc64/solaris/socksys.c	Sun Nov  8 15:08:42 1998
+++ linux.pre11.3/arch/sparc64/solaris/socksys.c	Mon Jul 19 23:54:30 1999
@@ -16,7 +16,6 @@
 #include <linux/file.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/file.h>
 #include <linux/malloc.h>
 
 #include <asm/uaccess.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/Makefile linux.pre11.3/drivers/Makefile
--- linux.vanilla/drivers/Makefile	Thu May 27 22:11:52 1999
+++ linux.pre11.3/drivers/Makefile	Mon Jul 19 23:54:40 1999
@@ -9,8 +9,8 @@
 
 SUB_DIRS     := block char net misc sound
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus cdrom isdn pnp \
-				 macintosh video dio zorro fc4 usb
+ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp \
+				macintosh video dio zorro fc4 usb
 
 ifdef CONFIG_DIO
 SUB_DIRS += dio
@@ -34,6 +34,10 @@
 SUB_DIRS += nubus
 endif
 
+ifdef CONFIG_TC
+SUB_DIRS += tc
+endif
+
 ifdef CONFIG_VT
 SUB_DIRS += video
 MOD_SUB_DIRS += video
@@ -52,6 +56,11 @@
   MOD_SUB_DIRS += usb
   endif
 endif 
+
+ifdef CONFIG_SGI
+SUB_DIRS += sgi
+MOD_SUB_DIRS += sgi
+endif
 
 # If CONFIG_SCSI is set, the core of SCSI support will be added to the kernel,
 # but some of the low-level things may also be modules.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/ap1000/bif.c linux.pre11.3/drivers/ap1000/bif.c
--- linux.vanilla/drivers/ap1000/bif.c	Sun Nov  8 15:08:12 1998
+++ linux.pre11.3/drivers/ap1000/bif.c	Mon Jul 19 23:54:46 1999
@@ -30,7 +30,6 @@
 #include <asm/io.h>
 
 #include <linux/inet.h>
-#include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/Config.in linux.pre11.3/drivers/block/Config.in
--- linux.vanilla/drivers/block/Config.in	Thu May 27 22:11:52 1999
+++ linux.pre11.3/drivers/block/Config.in	Tue Jul 20 00:27:46 1999
@@ -114,6 +114,9 @@
   bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
 fi
 tristate 'XT hard disk support' CONFIG_BLK_DEV_XD
+if [ "$CONFIG_PCI" = "y" ]; then
+  tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960
+fi
 
 # PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
 # PARIDE must also be a module.  The bogus CONFIG_PARIDE_PARPORT option
@@ -128,6 +131,7 @@
 if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   source drivers/block/paride/Config.in
 fi
+tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA
 
 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
   define_bool CONFIG_BLK_DEV_HD y
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/DAC960.c linux.pre11.3/drivers/block/DAC960.c
--- linux.vanilla/drivers/block/DAC960.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/DAC960.c	Tue Jul 20 00:27:58 1999
@@ -0,0 +1,3320 @@
+/*
+
+  Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
+
+  Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+  This program is free software; you may redistribute and/or modify it under
+  the terms of the GNU General Public License Version 2 as published by the
+  Free Software Foundation.
+
+  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 complete details.
+
+  The author respectfully requests that any modifications to this software be
+  sent directly to him for evaluation and testing.
+
+*/
+
+
+#define DAC960_DriverVersion			"2.2.2"
+#define DAC960_DriverDate			"3 July 1999"
+
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/blk.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/locks.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+#include <linux/reboot.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/spinlock.h>
+#include <asm/uaccess.h>
+#include "DAC960.h"
+
+
+/*
+  DAC960_ControllerCount is the number of DAC960 Controllers detected.
+*/
+
+static int
+  DAC960_ControllerCount =			0;
+
+
+/*
+  DAC960_ActiveControllerCount is the number of Active DAC960 Controllers
+  detected.
+*/
+
+static int
+  DAC960_ActiveControllerCount =		0;
+
+
+/*
+  DAC960_Controllers is an array of pointers to the DAC960 Controller
+  structures.
+*/
+
+static DAC960_Controller_T
+  *DAC960_Controllers[DAC960_MaxControllers] =	{ NULL };
+
+
+/*
+  DAC960_FileOperations is the File Operations structure for DAC960 Logical
+  Disk Devices.
+*/
+
+static FileOperations_T
+  DAC960_FileOperations =
+    { llseek:		    NULL,
+      read:		    block_read,
+      write:		    block_write,
+      readdir:		    NULL,
+      poll:		    NULL,
+      ioctl:		    DAC960_IOCTL,
+      mmap:		    NULL,
+      open:		    DAC960_Open,
+      release:		    DAC960_Release,
+      fsync:		    block_fsync,
+      fasync:		    NULL,
+      check_media_change:   NULL,
+      revalidate:	    NULL };
+
+
+/*
+  DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.
+*/
+
+static PROC_DirectoryEntry_T
+  DAC960_ProcDirectoryEntry;
+
+
+/*
+  DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver.
+*/
+
+static NotifierBlock_T
+  DAC960_NotifierBlock =    { DAC960_Finalize, NULL, 0 };
+
+
+/*
+  DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
+  Copyright Notice, and Electronic Mail Address.
+*/
+
+static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller)
+{
+  DAC960_Announce("***** DAC960 RAID Driver Version "
+		  DAC960_DriverVersion " of "
+		  DAC960_DriverDate " *****\n", Controller);
+  DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
+		  "<lnz@dandelion.com>\n", Controller);
+}
+
+
+/*
+  DAC960_Failure prints a standardized error message, and then returns false.
+*/
+
+static boolean DAC960_Failure(DAC960_Controller_T *Controller,
+			      char *ErrorMessage)
+{
+  DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
+	       Controller);
+  if (Controller->IO_Address == 0)
+    DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
+		 "PCI Address 0x%X\n", Controller,
+		 Controller->Bus, Controller->Device,
+		 Controller->Function, Controller->PCI_Address);
+  else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+		    "0x%X PCI Address 0x%X\n", Controller,
+		    Controller->Bus, Controller->Device,
+		    Controller->Function, Controller->IO_Address,
+		    Controller->PCI_Address);
+  DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage);
+  return false;
+}
+
+
+/*
+  DAC960_ClearCommand clears critical fields of Command.
+*/
+
+static inline void DAC960_ClearCommand(DAC960_Command_T *Command)
+{
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  CommandMailbox->Words[0] = 0;
+  CommandMailbox->Words[1] = 0;
+  CommandMailbox->Words[2] = 0;
+  CommandMailbox->Words[3] = 0;
+  Command->CommandStatus = 0;
+}
+
+
+/*
+  DAC960_AllocateCommand allocates a Command structure from Controller's
+  free list.
+*/
+
+static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
+						       *Controller)
+{
+  DAC960_Command_T *Command = Controller->FreeCommands;
+  if (Command == NULL) return NULL;
+  Controller->FreeCommands = Command->Next;
+  Command->Next = NULL;
+  return Command;
+}
+
+
+/*
+  DAC960_DeallocateCommand deallocates Command, returning it to Controller's
+  free list.
+*/
+
+static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  Command->Next = Controller->FreeCommands;
+  Controller->FreeCommands = Command;
+}
+
+
+/*
+  DAC960_QueueCommand queues Command.
+*/
+
+static void DAC960_QueueCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  DAC960_CommandMailbox_T *NextCommandMailbox;
+  CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands;
+  switch (Controller->ControllerType)
+    {
+    case DAC960_V5_Controller:
+      NextCommandMailbox = Controller->NextCommandMailbox;
+      DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+      if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
+	  Controller->PreviousCommandMailbox2->Words[0] == 0)
+	{
+	  if (Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress);
+	  else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
+	}
+      Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
+      Controller->PreviousCommandMailbox1 = NextCommandMailbox;
+      if (++NextCommandMailbox > Controller->LastCommandMailbox)
+	NextCommandMailbox = Controller->FirstCommandMailbox;
+      Controller->NextCommandMailbox = NextCommandMailbox;
+      break;
+    case DAC960_V4_Controller:
+      NextCommandMailbox = Controller->NextCommandMailbox;
+      DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+      if (Controller->PreviousCommandMailbox1->Words[0] == 0 ||
+	  Controller->PreviousCommandMailbox2->Words[0] == 0)
+	{
+	  if (Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress);
+	  else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
+	}
+      Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1;
+      Controller->PreviousCommandMailbox1 = NextCommandMailbox;
+      if (++NextCommandMailbox > Controller->LastCommandMailbox)
+	NextCommandMailbox = Controller->FirstCommandMailbox;
+      Controller->NextCommandMailbox = NextCommandMailbox;
+      break;
+    case DAC960_V3_Controller:
+      while (DAC960_V3_MailboxFullP(ControllerBaseAddress))
+	udelay(1);
+      DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox);
+      DAC960_V3_NewCommand(ControllerBaseAddress);
+      break;
+    }
+}
+
+
+/*
+  DAC960_ExecuteCommand executes Command and waits for completion.  It
+  returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  Semaphore_T Semaphore = MUTEX_LOCKED;
+  unsigned long ProcessorFlags;
+  Command->Semaphore = &Semaphore;
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  DAC960_QueueCommand(Command);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+  if (!in_interrupt())
+    down(&Semaphore);
+  return Command->CommandStatus == DAC960_NormalCompletion;
+}
+
+
+/*
+  DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for
+  completion.  It returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteType3(DAC960_Controller_T *Controller,
+				   DAC960_CommandOpcode_T CommandOpcode,
+				   void *DataPointer)
+{
+  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  boolean Result;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox->Type3.CommandOpcode = CommandOpcode;
+  CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer);
+  Result = DAC960_ExecuteCommand(Command);
+  DAC960_DeallocateCommand(Command);
+  return Result;
+}
+
+
+/*
+  DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for
+  completion.  It returns true on success and false on failure.
+*/
+
+static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller,
+				    DAC960_CommandOpcode_T CommandOpcode,
+				    unsigned char Channel,
+				    unsigned char TargetID,
+				    void *DataPointer)
+{
+  DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  boolean Result;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
+  CommandMailbox->Type3D.Channel = Channel;
+  CommandMailbox->Type3D.TargetID = TargetID;
+  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer);
+  Result = DAC960_ExecuteCommand(Command);
+  DAC960_DeallocateCommand(Command);
+  return Result;
+}
+
+
+/*
+  DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
+*/
+
+static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T
+						   *Controller)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_CommandMailbox_T *CommandMailboxesMemory;
+  DAC960_StatusMailbox_T *StatusMailboxesMemory;
+  DAC960_CommandMailbox_T CommandMailbox;
+  DAC960_CommandStatus_T CommandStatus;
+  void *SavedMemoryMailboxesAddress = NULL;
+  short NextCommandMailboxIndex = 0;
+  short NextStatusMailboxIndex = 0;
+  int TimeoutCounter = 1000000, i;
+  if (Controller->ControllerType == DAC960_V5_Controller)
+    DAC960_V5_RestoreMemoryMailboxInfo(Controller,
+				       &SavedMemoryMailboxesAddress,
+				       &NextCommandMailboxIndex,
+				       &NextStatusMailboxIndex);
+  else DAC960_V4_RestoreMemoryMailboxInfo(Controller,
+					  &SavedMemoryMailboxesAddress,
+					  &NextCommandMailboxIndex,
+					  &NextStatusMailboxIndex);
+  if (SavedMemoryMailboxesAddress == NULL)
+    CommandMailboxesMemory =
+      (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1);
+  else CommandMailboxesMemory = SavedMemoryMailboxesAddress;
+  memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1);
+  Controller->FirstCommandMailbox = CommandMailboxesMemory;
+  CommandMailboxesMemory += DAC960_CommandMailboxCount - 1;
+  Controller->LastCommandMailbox = CommandMailboxesMemory;
+  Controller->NextCommandMailbox =
+    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+  if (--NextCommandMailboxIndex < 0)
+    NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
+  Controller->PreviousCommandMailbox1 =
+    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+  if (--NextCommandMailboxIndex < 0)
+    NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1;
+  Controller->PreviousCommandMailbox2 =
+    &Controller->FirstCommandMailbox[NextCommandMailboxIndex];
+  StatusMailboxesMemory =
+    (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+  Controller->FirstStatusMailbox = StatusMailboxesMemory;
+  StatusMailboxesMemory += DAC960_StatusMailboxCount - 1;
+  Controller->LastStatusMailbox = StatusMailboxesMemory;
+  Controller->NextStatusMailbox =
+    &Controller->FirstStatusMailbox[NextStatusMailboxIndex];
+  if (SavedMemoryMailboxesAddress != NULL) return true;
+  /* Enable the Memory Mailbox Interface. */
+  Controller->DualModeMemoryMailboxInterface = true;
+  CommandMailbox.TypeX.CommandOpcode = 0x2B;
+  CommandMailbox.TypeX.CommandIdentifier = 0;
+  CommandMailbox.TypeX.CommandOpcode2 = 0x14;
+  CommandMailbox.TypeX.CommandMailboxesBusAddress =
+    Virtual_to_Bus(Controller->FirstCommandMailbox);
+  CommandMailbox.TypeX.StatusMailboxesBusAddress =
+    Virtual_to_Bus(Controller->FirstStatusMailbox);
+  for (i = 0; i < 2; i++)
+    switch (Controller->ControllerType)
+      {
+      case DAC960_V5_Controller:
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+	DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress);
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (DAC960_V5_HardwareMailboxStatusAvailableP(
+		  ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress);
+	DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+	DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+	if (CommandStatus == DAC960_NormalCompletion) return true;
+	Controller->DualModeMemoryMailboxInterface = false;
+	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
+	break;
+      case DAC960_V4_Controller:
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+	DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress);
+	while (--TimeoutCounter >= 0)
+	  {
+	    if (DAC960_V4_HardwareMailboxStatusAvailableP(
+		  ControllerBaseAddress))
+	      break;
+	    udelay(10);
+	  }
+	if (TimeoutCounter < 0) return false;
+	CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress);
+	DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+	DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+	if (CommandStatus == DAC960_NormalCompletion) return true;
+	Controller->DualModeMemoryMailboxInterface = false;
+	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
+	break;
+      default:
+	break;
+      }
+  return false;
+}
+
+
+/*
+  DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating
+  the PCI Configuration Space for Controller Type.
+*/
+
+static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType)
+{
+  unsigned short VendorID = 0, DeviceID = 0;
+  unsigned int MemoryWindowSize = 0;
+  PCI_Device_T *PCI_Device = NULL;
+  switch (ControllerType)
+    {
+    case DAC960_V5_Controller:
+      VendorID = PCI_VENDOR_ID_DEC;
+      DeviceID = PCI_DEVICE_ID_DEC_21285;
+      MemoryWindowSize = DAC960_V5_RegisterWindowSize;
+      break;
+    case DAC960_V4_Controller:
+      VendorID = PCI_VENDOR_ID_MYLEX;
+      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4;
+      MemoryWindowSize = DAC960_V4_RegisterWindowSize;
+      break;
+    case DAC960_V3_Controller:
+      VendorID = PCI_VENDOR_ID_MYLEX;
+      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3;
+      MemoryWindowSize = DAC960_V3_RegisterWindowSize;
+      break;
+    }
+  while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
+    {
+      DAC960_Controller_T *Controller = (DAC960_Controller_T *)
+	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+      DAC960_IO_Address_T IO_Address = 0;
+      DAC960_PCI_Address_T PCI_Address = 0;
+      unsigned char Bus = PCI_Device->bus->number;
+      unsigned char DeviceFunction = PCI_Device->devfn;
+      unsigned char Device = DeviceFunction >> 3;
+      unsigned char Function = DeviceFunction & 0x7;
+      unsigned int IRQ_Channel = PCI_Device->irq;
+      unsigned long BaseAddress0 = PCI_Device->base_address[0];
+      unsigned long BaseAddress1 = PCI_Device->base_address[1];
+      unsigned short SubsystemVendorID, SubsystemDeviceID;
+      pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
+			   &SubsystemVendorID);
+      pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID,
+			   &SubsystemDeviceID);
+      switch (ControllerType)
+	{
+	case DAC960_V5_Controller:
+	  if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX &&
+		SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5))
+	    goto Ignore;
+	  PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
+	  break;
+	case DAC960_V4_Controller:
+	  PCI_Address = BaseAddress0 & PCI_BASE_ADDRESS_MEM_MASK;
+	  break;
+	case DAC960_V3_Controller:
+	  IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
+	  PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
+	  break;
+	}
+      if (DAC960_ControllerCount == DAC960_MaxControllers)
+	{
+	  DAC960_Error("More than %d DAC960 Controllers detected - "
+		       "ignoring from Controller at\n",
+		       NULL, DAC960_MaxControllers);
+	  goto Ignore;
+	}
+      if (Controller == NULL)
+	{
+	  DAC960_Error("Unable to allocate Controller structure for "
+		       "Controller at\n", NULL);
+	  goto Ignore;
+	}
+      memset(Controller, 0, sizeof(DAC960_Controller_T));
+      Controller->ControllerNumber = DAC960_ControllerCount;
+      DAC960_Controllers[DAC960_ControllerCount++] = Controller;
+      DAC960_AnnounceDriver(Controller);
+      Controller->ControllerType = ControllerType;
+      Controller->IO_Address = IO_Address;
+      Controller->PCI_Address = PCI_Address;
+      Controller->Bus = Bus;
+      Controller->Device = Device;
+      Controller->Function = Function;
+      sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
+      /*
+	Acquire shared access to the IRQ Channel.
+      */
+      if (IRQ_Channel == 0)
+	{
+	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      strcpy(Controller->FullModelName, "DAC960");
+      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
+		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
+	{
+	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      Controller->IRQ_Channel = IRQ_Channel;
+      /*
+	Map the Controller Register Window.
+      */
+      if (MemoryWindowSize < PAGE_SIZE)
+	MemoryWindowSize = PAGE_SIZE;
+      Controller->MemoryMappedAddress =
+	ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
+      Controller->BaseAddress =
+	Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
+      if (Controller->MemoryMappedAddress == NULL)
+	{
+	  DAC960_Error("Unable to map Controller Register Window for "
+		       "Controller at\n", Controller);
+	  goto Failure;
+	}
+      switch (ControllerType)
+	{
+	case DAC960_V5_Controller:
+	  DAC960_V5_DisableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_V5_EnableInterrupts(Controller->BaseAddress);
+	  break;
+	case DAC960_V4_Controller:
+	  DAC960_V4_DisableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_V4_EnableInterrupts(Controller->BaseAddress);
+	  break;
+	case DAC960_V3_Controller:
+	  request_region(Controller->IO_Address, 0x80,
+			 Controller->FullModelName);
+	  DAC960_V3_EnableInterrupts(Controller->BaseAddress);
+	  break;
+	}
+      DAC960_ActiveControllerCount++;
+      Controller->Commands[0].Controller = Controller;
+      Controller->Commands[0].Next = NULL;
+      Controller->FreeCommands = &Controller->Commands[0];
+      continue;
+    Failure:
+      if (IO_Address == 0)
+	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
+		     "PCI Address 0x%X\n", Controller,
+		     Bus, Device, Function, PCI_Address);
+      else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+			"0x%X PCI Address 0x%X\n", Controller,
+			Bus, Device, Function, IO_Address, PCI_Address);
+      if (Controller == NULL) break;
+      if (Controller->IRQ_Channel > 0)
+	free_irq(IRQ_Channel, Controller);
+      if (Controller->MemoryMappedAddress != NULL)
+	iounmap(Controller->MemoryMappedAddress);
+      DAC960_Controllers[Controller->ControllerNumber] = NULL;
+    Ignore:
+      kfree(Controller);
+    }
+}
+
+
+/*
+  DAC960_ReadControllerConfiguration reads the Configuration Information
+  from Controller and initializes the Controller structure.
+*/
+
+static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T
+						  *Controller)
+{
+  DAC960_Enquiry2_T Enquiry2;
+  DAC960_Config2_T Config2;
+  int LogicalDriveNumber, Channel, TargetID;
+  if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry,
+			   &Controller->Enquiry[0]))
+    return DAC960_Failure(Controller, "ENQUIRY");
+  if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2))
+    return DAC960_Failure(Controller, "ENQUIRY2");
+  if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2))
+    return DAC960_Failure(Controller, "READ CONFIG2");
+  if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation,
+			   &Controller->LogicalDriveInformation[0]))
+    return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
+  for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
+    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+      if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState,
+				Channel, TargetID,
+				&Controller->DeviceState[0][Channel][TargetID]))
+	return DAC960_Failure(Controller, "GET DEVICE STATE");
+  /*
+    Initialize the Controller Model Name and Full Model Name fields.
+  */
+  switch (Enquiry2.HardwareID.SubModel)
+    {
+    case DAC960_P_PD_PU:
+      if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra)
+	strcpy(Controller->ModelName, "DAC960PU");
+      else strcpy(Controller->ModelName, "DAC960PD");
+      break;
+    case DAC960_PL:
+      strcpy(Controller->ModelName, "DAC960PL");
+      break;
+    case DAC960_PG:
+      strcpy(Controller->ModelName, "DAC960PG");
+      break;
+    case DAC960_PJ:
+      strcpy(Controller->ModelName, "DAC960PJ");
+      break;
+    case DAC960_PR:
+      strcpy(Controller->ModelName, "DAC960PR");
+      break;
+    case DAC960_PT:
+      strcpy(Controller->ModelName, "DAC960PT");
+      break;
+    case DAC960_PTL0:
+      strcpy(Controller->ModelName, "DAC960PTL0");
+      break;
+    case DAC960_PRL:
+      strcpy(Controller->ModelName, "DAC960PRL");
+      break;
+    case DAC960_PTL1:
+      strcpy(Controller->ModelName, "DAC960PTL1");
+      break;
+    case DAC1164_P:
+      strcpy(Controller->ModelName, "DAC1164P");
+      break;
+    default:
+      return DAC960_Failure(Controller, "MODEL VERIFICATION");
+    }
+  strcpy(Controller->FullModelName, "Mylex ");
+  strcat(Controller->FullModelName, Controller->ModelName);
+  /*
+    Initialize the Controller Firmware Version field and verify that it
+    is a supported firmware version.  The supported firmware versions are:
+
+    DAC1164P		    5.06 and above
+    DAC960PTL/PRL/PJ/PG	    4.06 and above
+    DAC960PU/PD/PL	    3.51 and above
+  */
+  sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
+	  Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
+	  Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
+  if (!((Controller->FirmwareVersion[0] == '5' &&
+	 strcmp(Controller->FirmwareVersion, "5.06") >= 0) ||
+	(Controller->FirmwareVersion[0] == '4' &&
+	 strcmp(Controller->FirmwareVersion, "4.06") >= 0) ||
+	(Controller->FirmwareVersion[0] == '3' &&
+	 strcmp(Controller->FirmwareVersion, "3.51") >= 0)))
+    {
+      DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
+      DAC960_Error("Firmware Version = '%s'\n", Controller,
+		   Controller->FirmwareVersion);
+      return false;
+    }
+  /*
+    Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure
+    Management Enabled fields.
+  */
+  Controller->Channels = Enquiry2.ActualChannels;
+  Controller->MemorySize = Enquiry2.MemorySize >> 20;
+  Controller->SAFTE_EnclosureManagementEnabled =
+    Enquiry2.FaultManagementType == DAC960_SAFTE;
+  /*
+    Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
+    Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments.
+    The Driver Queue Depth must be at most one less than the Controller Queue
+    Depth to allow for an automatic drive rebuild operation.
+  */
+  Controller->ControllerQueueDepth = Controller->Enquiry[0].MaxCommands;
+  Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1;
+  Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives;
+  Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
+  Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries;
+  /*
+    Initialize the Stripe Size, Segment Size, and Geometry Translation.
+  */
+  Controller->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
+			   >> (10 - DAC960_BlockSizeBits);
+  Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
+			    >> (10 - DAC960_BlockSizeBits);
+  switch (Config2.DriveGeometry)
+    {
+    case DAC960_Geometry_128_32:
+      Controller->GeometryTranslationHeads = 128;
+      Controller->GeometryTranslationSectors = 32;
+      break;
+    case DAC960_Geometry_255_63:
+      Controller->GeometryTranslationHeads = 255;
+      Controller->GeometryTranslationSectors = 63;
+      break;
+    default:
+      return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
+    }
+  /*
+    Initialize the Logical Drive Initial State.
+  */
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < Controller->LogicalDriveCount;
+       LogicalDriveNumber++)
+    Controller->LogicalDriveInitialState[LogicalDriveNumber] =
+      Controller->LogicalDriveInformation[0]
+		  [LogicalDriveNumber].LogicalDriveState;
+  Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress;
+  return true;
+}
+
+
+/*
+  DAC960_ReportControllerConfiguration reports the configuration of
+  Controller.
+*/
+
+static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
+						    *Controller)
+{
+  int LogicalDriveNumber, Channel, TargetID;
+  DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
+	      Controller, Controller->ModelName);
+  DAC960_Info("  Firmware Version: %s, Channels: %d, Memory Size: %dMB\n",
+	      Controller, Controller->FirmwareVersion,
+	      Controller->Channels, Controller->MemorySize);
+  DAC960_Info("  PCI Bus: %d, Device: %d, Function: %d, I/O Address: ",
+	      Controller, Controller->Bus,
+	      Controller->Device, Controller->Function);
+  if (Controller->IO_Address == 0)
+    DAC960_Info("Unassigned\n", Controller);
+  else DAC960_Info("0x%X\n", Controller, Controller->IO_Address);
+  DAC960_Info("  PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d\n",
+	      Controller, Controller->PCI_Address,
+	      (unsigned long) Controller->BaseAddress,
+	      Controller->IRQ_Channel);
+  DAC960_Info("  Controller Queue Depth: %d, "
+	      "Maximum Blocks per Command: %d\n",
+	      Controller, Controller->ControllerQueueDepth,
+	      Controller->MaxBlocksPerCommand);
+  DAC960_Info("  Driver Queue Depth: %d, "
+	      "Maximum Scatter/Gather Segments: %d\n",
+	      Controller, Controller->DriverQueueDepth,
+	      Controller->MaxScatterGatherSegments);
+  DAC960_Info("  Stripe Size: %dKB, Segment Size: %dKB, "
+	      "BIOS Geometry: %d/%d\n", Controller,
+	      Controller->StripeSize,
+	      Controller->SegmentSize,
+	      Controller->GeometryTranslationHeads,
+	      Controller->GeometryTranslationSectors);
+  if (Controller->SAFTE_EnclosureManagementEnabled)
+    DAC960_Info("  SAF-TE Enclosure Management Enabled\n", Controller);
+  DAC960_Info("  Physical Devices:\n", Controller);
+  for (Channel = 0; Channel < Controller->Channels; Channel++)
+    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+      {
+	DAC960_DeviceState_T *DeviceState =
+	  &Controller->DeviceState[Controller->DeviceStateIndex]
+				  [Channel][TargetID];
+	if (!DeviceState->Present) continue;
+	switch (DeviceState->DeviceType)
+	  {
+	  case DAC960_OtherType:
+	    DAC960_Info("    %d:%d - Other\n", Controller, Channel, TargetID);
+	    break;
+	  case DAC960_DiskType:
+	    DAC960_Info("    %d:%d - Disk: %s, %d blocks\n", Controller,
+			Channel, TargetID,
+			(DeviceState->DeviceState == DAC960_Device_Dead
+			 ? "Dead"
+			 : DeviceState->DeviceState == DAC960_Device_WriteOnly
+			   ? "Write-Only"
+			   : DeviceState->DeviceState == DAC960_Device_Online
+			     ? "Online" : "Standby"),
+			DeviceState->DiskSize);
+	    break;
+	  case DAC960_SequentialType:
+	    DAC960_Info("    %d:%d - Sequential\n", Controller,
+			Channel, TargetID);
+	    break;
+	  case DAC960_CDROM_or_WORM_Type:
+	    DAC960_Info("    %d:%d - CD-ROM or WORM\n", Controller,
+			Channel, TargetID);
+	    break;
+	  }
+
+      }
+  DAC960_Info("  Logical Drives:\n", Controller);
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < Controller->LogicalDriveCount;
+       LogicalDriveNumber++)
+    {
+      DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
+	&Controller->LogicalDriveInformation
+	   [Controller->LogicalDriveInformationIndex][LogicalDriveNumber];
+      DAC960_Info("    /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n",
+		  Controller, Controller->ControllerNumber, LogicalDriveNumber,
+		  LogicalDriveInformation->RAIDLevel,
+		  (LogicalDriveInformation->LogicalDriveState ==
+		     DAC960_LogicalDrive_Online
+		   ? "Online"
+		   : LogicalDriveInformation->LogicalDriveState ==
+		     DAC960_LogicalDrive_Critical
+		     ? "Critical" : "Offline"),
+		  LogicalDriveInformation->LogicalDriveSize,
+		  (LogicalDriveInformation->WriteBack
+		   ? "Write Back" : "Write Thru"));
+    }
+  return true;
+}
+
+
+/*
+  DAC960_RegisterBlockDevice registers the Block Device structures
+  associated with Controller.
+*/
+
+static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
+{
+  static void (*RequestFunctions[DAC960_MaxControllers])(void) =
+    { DAC960_RequestFunction0, DAC960_RequestFunction1,
+      DAC960_RequestFunction2, DAC960_RequestFunction3,
+      DAC960_RequestFunction4, DAC960_RequestFunction5,
+      DAC960_RequestFunction6, DAC960_RequestFunction7 };
+  int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
+  GenericDiskInfo_T *GenericDiskInfo;
+  int MinorNumber;
+  /*
+    Register the Block Device Major Number for this DAC960 Controller.
+  */
+  if (register_blkdev(MajorNumber, "rd", &DAC960_FileOperations) < 0)
+    {
+      DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
+		   Controller, MajorNumber);
+      return false;
+    }
+  /*
+    Initialize the I/O Request Function.
+  */
+  blk_dev[MajorNumber].request_fn =
+    RequestFunctions[Controller->ControllerNumber];
+  /*
+    Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
+    array, Max Sectors per Request array, and Max Segments per Request array.
+  */
+  for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
+    {
+      Controller->BlockSizes[MinorNumber] = BLOCK_SIZE;
+      Controller->MaxSectorsPerRequest[MinorNumber] =
+	Controller->MaxBlocksPerCommand;
+      Controller->MaxSegmentsPerRequest[MinorNumber] =
+	Controller->MaxScatterGatherSegments;
+    }
+  Controller->GenericDiskInfo.part = Controller->DiskPartitions;
+  Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
+  blksize_size[MajorNumber] = Controller->BlockSizes;
+  max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest;
+  max_segments[MajorNumber] = Controller->MaxSegmentsPerRequest;
+  /*
+    Initialize Read Ahead to 128 sectors.
+  */
+  read_ahead[MajorNumber] = 128;
+  /*
+    Complete initialization of the Generic Disk Information structure.
+  */
+  Controller->GenericDiskInfo.major = MajorNumber;
+  Controller->GenericDiskInfo.major_name = "rd";
+  Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
+  Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
+  Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives;
+  Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo;
+  Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
+  Controller->GenericDiskInfo.real_devices = Controller;
+  Controller->GenericDiskInfo.next = NULL;
+  /*
+    Install the Generic Disk Information structure at the end of the list.
+  */
+  if ((GenericDiskInfo = gendisk_head) != NULL)
+    {
+      while (GenericDiskInfo->next != NULL)
+	GenericDiskInfo = GenericDiskInfo->next;
+      GenericDiskInfo->next = &Controller->GenericDiskInfo;
+    }
+  else gendisk_head = &Controller->GenericDiskInfo;
+  /*
+    Indicate the Block Device Registration completed successfully,
+  */
+  return true;
+}
+
+
+/*
+  DAC960_UnregisterBlockDevice unregisters the Block Device structures
+  associated with Controller.
+*/
+
+static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
+{
+  int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
+  /*
+    Unregister the Block Device Major Number for this DAC960 Controller.
+  */
+  unregister_blkdev(MajorNumber, "rd");
+  /*
+    Remove the I/O Request Function.
+  */
+  blk_dev[MajorNumber].request_fn = NULL;
+  /*
+    Remove the Disk Partitions array, Partition Sizes array, Block Sizes
+    array, Max Sectors per Request array, and Max Segments per Request array.
+  */
+  Controller->GenericDiskInfo.part = NULL;
+  Controller->GenericDiskInfo.sizes = NULL;
+  blk_size[MajorNumber] = NULL;
+  blksize_size[MajorNumber] = NULL;
+  max_sectors[MajorNumber] = NULL;
+  max_segments[MajorNumber] = NULL;
+  /*
+    Remove the Generic Disk Information structure from the list.
+  */
+  if (gendisk_head != &Controller->GenericDiskInfo)
+    {
+      GenericDiskInfo_T *GenericDiskInfo = gendisk_head;
+      while (GenericDiskInfo != NULL &&
+	     GenericDiskInfo->next != &Controller->GenericDiskInfo)
+	GenericDiskInfo = GenericDiskInfo->next;
+      if (GenericDiskInfo != NULL)
+	GenericDiskInfo->next = GenericDiskInfo->next->next;
+    }
+  else gendisk_head = Controller->GenericDiskInfo.next;
+}
+
+
+/*
+  DAC960_InitializeController initializes Controller.
+*/
+
+static void DAC960_InitializeController(DAC960_Controller_T *Controller)
+{
+  if (DAC960_ReadControllerConfiguration(Controller) &&
+      DAC960_ReportControllerConfiguration(Controller) &&
+      DAC960_RegisterBlockDevice(Controller))
+    {
+      /*
+	Initialize the Command structures.
+      */
+      DAC960_Command_T *Commands = Controller->Commands;
+      int CommandIdentifier;
+      Controller->FreeCommands = NULL;
+      for (CommandIdentifier = 0;
+	   CommandIdentifier < Controller->DriverQueueDepth;
+	   CommandIdentifier++)
+	{
+	  Commands[CommandIdentifier].Controller = Controller;
+	  Commands[CommandIdentifier].Next = Controller->FreeCommands;
+	  Controller->FreeCommands = &Commands[CommandIdentifier];
+	}
+      /*
+	Initialize the Monitoring Timer.
+      */
+      init_timer(&Controller->MonitoringTimer);
+      Controller->MonitoringTimer.expires =
+	jiffies + DAC960_MonitoringTimerInterval;
+      Controller->MonitoringTimer.data = (unsigned long) Controller;
+      Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
+      add_timer(&Controller->MonitoringTimer);
+      Controller->ControllerInitialized = true;
+    }
+  else DAC960_FinalizeController(Controller);
+}
+
+
+/*
+  DAC960_FinalizeController finalizes Controller.
+*/
+
+static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
+{
+  if (Controller->ControllerInitialized)
+    {
+      del_timer(&Controller->MonitoringTimer);
+      DAC960_Notice("Flushing Cache...", Controller);
+      DAC960_ExecuteType3(Controller, DAC960_Flush, NULL);
+      DAC960_Notice("done\n", Controller);
+      switch (Controller->ControllerType)
+	{
+	case DAC960_V5_Controller:
+	  if (!Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V5_SaveMemoryMailboxInfo(Controller);
+	  break;
+	case DAC960_V4_Controller:
+	  if (!Controller->DualModeMemoryMailboxInterface)
+	    DAC960_V4_SaveMemoryMailboxInfo(Controller);
+	  break;
+	case DAC960_V3_Controller:
+	  break;
+	}
+    }
+  free_irq(Controller->IRQ_Channel, Controller);
+  iounmap(Controller->MemoryMappedAddress);
+  if (Controller->IO_Address > 0)
+    release_region(Controller->IO_Address, 0x80);
+  DAC960_UnregisterBlockDevice(Controller);
+  DAC960_Controllers[Controller->ControllerNumber] = NULL;
+  kfree(Controller);
+}
+
+
+/*
+  DAC960_Initialize initializes the DAC960 Driver.
+*/
+
+void DAC960_Initialize(void)
+{
+  int ControllerNumber;
+  DAC960_DetectControllers(DAC960_V5_Controller);
+  DAC960_DetectControllers(DAC960_V4_Controller);
+  DAC960_DetectControllers(DAC960_V3_Controller);
+  if (DAC960_ActiveControllerCount == 0) return;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    if (DAC960_Controllers[ControllerNumber] != NULL)
+      DAC960_InitializeController(DAC960_Controllers[ControllerNumber]);
+  DAC960_CreateProcEntries();
+  register_reboot_notifier(&DAC960_NotifierBlock);
+}
+
+
+/*
+  DAC960_Finalize finalizes the DAC960 Driver.
+*/
+
+static int DAC960_Finalize(NotifierBlock_T *NotifierBlock,
+			   unsigned long Event,
+			   void *Buffer)
+{
+  int ControllerNumber;
+  if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
+    return NOTIFY_DONE;
+  if (DAC960_ActiveControllerCount == 0) return NOTIFY_OK;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    if (DAC960_Controllers[ControllerNumber] != NULL)
+      DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
+  DAC960_DestroyProcEntries();
+  unregister_reboot_notifier(&DAC960_NotifierBlock);
+  return NOTIFY_OK;
+}
+
+
+/*
+  DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
+  I/O Request Queue and queues it to the Controller.  WaitForCommand is true if
+  this function should wait for a Command to become available if necessary.
+  This function returns true if an I/O Request was queued and false otherwise.
+*/
+
+static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
+				     boolean WaitForCommand)
+{
+  IO_Request_T **RequestQueuePointer =
+    &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].current_request;
+  IO_Request_T *Request;
+  DAC960_Command_T *Command;
+  char *RequestBuffer;
+  while (true)
+    {
+      Request = *RequestQueuePointer;
+      if (Request == NULL || Request->rq_status == RQ_INACTIVE) return false;
+      Command = DAC960_AllocateCommand(Controller);
+      if (Command != NULL) break;
+      if (!WaitForCommand) return false;
+      spin_unlock(&io_request_lock);
+      sleep_on(&Controller->CommandWaitQueue);
+      spin_lock_irq(&io_request_lock);
+    }
+  DAC960_ClearCommand(Command);
+  if (Request->cmd == READ)
+    Command->CommandType = DAC960_ReadCommand;
+  else Command->CommandType = DAC960_WriteCommand;
+  Command->Semaphore = Request->sem;
+  Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev);
+  Command->BlockNumber =
+    Request->sector
+    + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect;
+  Command->BlockCount = Request->nr_sectors;
+  Command->SegmentCount = Request->nr_segments;
+  Command->BufferHeader = Request->bh;
+  RequestBuffer = Request->buffer;
+  Request->rq_status = RQ_INACTIVE;
+  *RequestQueuePointer = Request->next;
+  wake_up(&wait_for_request);
+  if (Command->SegmentCount == 1)
+    {
+      DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+      if (Command->CommandType == DAC960_ReadCommand)
+	CommandMailbox->Type5.CommandOpcode = DAC960_Read;
+      else CommandMailbox->Type5.CommandOpcode = DAC960_Write;
+      CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+      CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
+      CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(RequestBuffer);
+    }
+  else
+    {
+      DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+      DAC960_ScatterGatherSegment_T
+	*ScatterGatherList = Command->ScatterGatherList;
+      BufferHeader_T *BufferHeader = Command->BufferHeader;
+      char *LastDataEndPointer = NULL;
+      int SegmentNumber = 0;
+      if (Command->CommandType == DAC960_ReadCommand)
+	CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather;
+      else
+	CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather;
+      CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+      CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
+      CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList);
+      CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
+      while (BufferHeader != NULL)
+	{
+	  if (BufferHeader->b_data == LastDataEndPointer)
+	    {
+	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
+		BufferHeader->b_size;
+	      LastDataEndPointer += BufferHeader->b_size;
+	    }
+	  else
+	    {
+	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
+		Virtual_to_Bus(BufferHeader->b_data);
+	      ScatterGatherList[SegmentNumber].SegmentByteCount =
+		BufferHeader->b_size;
+	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
+	      if (SegmentNumber++ > Controller->MaxScatterGatherSegments)
+		panic("DAC960: Scatter/Gather Segment Overflow\n");
+	    }
+	  BufferHeader = BufferHeader->b_reqnext;
+	}
+      if (SegmentNumber != Command->SegmentCount)
+	panic("DAC960: SegmentNumber != SegmentCount\n");
+    }
+  DAC960_QueueCommand(Command);
+  return true;
+}
+
+
+/*
+  DAC960_ProcessRequests attempts to remove as many I/O Requests as possible
+  from Controller's I/O Request Queue and queue them to the Controller.
+*/
+
+static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller)
+{
+  int Counter = 0;
+  while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ;
+}
+
+
+/*
+  DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0.
+*/
+
+static void DAC960_RequestFunction0(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[0];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1.
+*/
+
+static void DAC960_RequestFunction1(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[1];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2.
+*/
+
+static void DAC960_RequestFunction2(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[2];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3.
+*/
+
+static void DAC960_RequestFunction3(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[3];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4.
+*/
+
+static void DAC960_RequestFunction4(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[4];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5.
+*/
+
+static void DAC960_RequestFunction5(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[5];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6.
+*/
+
+static void DAC960_RequestFunction6(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[6];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7.
+*/
+
+static void DAC960_RequestFunction7(void)
+{
+  DAC960_Controller_T *Controller = DAC960_Controllers[7];
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags);
+  /*
+    Process I/O Requests for Controller.
+  */
+  DAC960_ProcessRequests(Controller);
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_ReadWriteError prints an appropriate error message for Command when
+  an error occurs on a Read or Write operation.
+*/
+
+static void DAC960_ReadWriteError(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  char *CommandName = "UNKNOWN";
+  switch (Command->CommandType)
+    {
+    case DAC960_ReadCommand:
+    case DAC960_ReadRetryCommand:
+      CommandName = "READ";
+      break;
+    case DAC960_WriteCommand:
+    case DAC960_WriteRetryCommand:
+      CommandName = "WRITE";
+      break;
+    case DAC960_MonitoringCommand:
+    case DAC960_ImmediateCommand:
+    case DAC960_QueuedCommand:
+      break;
+    }
+  switch (Command->CommandStatus)
+    {
+    case DAC960_IrrecoverableDataError:
+      DAC960_Error("Irrecoverable Data Error on %s:\n",
+		   Controller, CommandName);
+      break;
+    case DAC960_LogicalDriveNonexistentOrOffline:
+      DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n",
+		   Controller, CommandName);
+      break;
+    case DAC960_AccessBeyondEndOfLogicalDrive:
+      DAC960_Error("Attempt to Access Beyond End of Logical Drive "
+		   "on %s:\n", Controller, CommandName);
+      break;
+    case DAC960_BadDataEncountered:
+      DAC960_Error("Bad Data Encountered on %s:\n", Controller, CommandName);
+      break;
+    default:
+      DAC960_Error("Unexpected Error Status %04X on %s:\n",
+		   Controller, Command->CommandStatus, CommandName);
+      break;
+    }
+  DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %d..%d\n",
+	       Controller, Controller->ControllerNumber,
+	       Command->LogicalDriveNumber, Command->BlockNumber,
+	       Command->BlockNumber + Command->BlockCount - 1);
+  if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
+    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %d..%d\n",
+		 Controller, Controller->ControllerNumber,
+		 Command->LogicalDriveNumber,
+		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
+		 Command->BufferHeader->b_rsector,
+		 Command->BufferHeader->b_rsector + Command->BlockCount - 1);
+}
+
+
+/*
+  DAC960_ProcessCompletedBuffer performs completion processing for an
+  individual Buffer.
+*/
+
+static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
+						 boolean SuccessfulIO)
+{
+  BufferHeader->b_end_io(BufferHeader, SuccessfulIO);
+}
+
+
+/*
+  DAC960_ProcessCompletedCommand performs completion processing for Command.
+*/
+
+static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  DAC960_CommandType_T CommandType = Command->CommandType;
+  DAC960_CommandOpcode_T CommandOpcode =
+    Command->CommandMailbox.Common.CommandOpcode;
+  DAC960_CommandStatus_T CommandStatus = Command->CommandStatus;
+  BufferHeader_T *BufferHeader = Command->BufferHeader;
+  if (CommandType == DAC960_ReadCommand ||
+      CommandType == DAC960_WriteCommand)
+    {
+      if (CommandStatus == DAC960_NormalCompletion)
+	{
+	  /*
+	    Perform completion processing for all buffers in this I/O Request.
+	  */
+	  while (BufferHeader != NULL)
+	    {
+	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+	      BufferHeader->b_reqnext = NULL;
+	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
+	      BufferHeader = NextBufferHeader;
+	    }
+	  /*
+	    Wake up requestor for swap file paging requests.
+	  */
+	  if (Command->Semaphore != NULL)
+	    {
+	      up(Command->Semaphore);
+	      Command->Semaphore = NULL;
+	    }
+	  add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber);
+	}
+      else if ((CommandStatus == DAC960_IrrecoverableDataError ||
+		CommandStatus == DAC960_BadDataEncountered) &&
+	       BufferHeader != NULL &&
+	       BufferHeader->b_reqnext != NULL)
+	{
+	  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+	  if (CommandType == DAC960_ReadCommand)
+	    {
+	      Command->CommandType = DAC960_ReadRetryCommand;
+	      CommandMailbox->Type5.CommandOpcode = DAC960_Read;
+	    }
+	  else
+	    {
+	      Command->CommandType = DAC960_WriteRetryCommand;
+	      CommandMailbox->Type5.CommandOpcode = DAC960_Write;
+	    }
+	  Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
+	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+	  CommandMailbox->Type5.BusAddress =
+	    Virtual_to_Bus(BufferHeader->b_data);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      else
+	{
+	  if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
+	    DAC960_ReadWriteError(Command);
+	  /*
+	    Perform completion processing for all buffers in this I/O Request.
+	  */
+	  while (BufferHeader != NULL)
+	    {
+	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+	      BufferHeader->b_reqnext = NULL;
+	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
+	      BufferHeader = NextBufferHeader;
+	    }
+	  /*
+	    Wake up requestor for swap file paging requests.
+	  */
+	  if (Command->Semaphore != NULL)
+	    {
+	      up(Command->Semaphore);
+	      Command->Semaphore = NULL;
+	    }
+	}
+    }
+  else if (CommandType == DAC960_ReadRetryCommand ||
+	   CommandType == DAC960_WriteRetryCommand)
+    {
+      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
+      BufferHeader->b_reqnext = NULL;
+      /*
+	Perform completion processing for this single buffer.
+      */
+      if (CommandStatus == DAC960_NormalCompletion)
+	DAC960_ProcessCompletedBuffer(BufferHeader, true);
+      else
+	{
+	  if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline)
+	    DAC960_ReadWriteError(Command);
+	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
+	}
+      if (NextBufferHeader != NULL)
+	{
+	  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+	  Command->BlockNumber +=
+	    BufferHeader->b_size >> DAC960_BlockSizeBits;
+	  Command->BlockCount =
+	    NextBufferHeader->b_size >> DAC960_BlockSizeBits;
+	  Command->BufferHeader = NextBufferHeader;
+	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
+	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
+	  CommandMailbox->Type5.BusAddress =
+	    Virtual_to_Bus(NextBufferHeader->b_data);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+    }
+  else if (CommandType == DAC960_MonitoringCommand ||
+	   CommandOpcode == DAC960_Enquiry ||
+	   CommandOpcode == DAC960_GetRebuildProgress)
+    {
+      if (CommandType != DAC960_MonitoringCommand)
+	{
+	  if (CommandOpcode == DAC960_Enquiry)
+	    memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1],
+		   Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress),
+		   sizeof(DAC960_Enquiry_T));
+	  else if (CommandOpcode == DAC960_GetRebuildProgress)
+	    memcpy(&Controller->RebuildProgress,
+		   Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress),
+		   sizeof(DAC960_RebuildProgress_T));
+	}
+      if (CommandOpcode == DAC960_Enquiry)
+	{
+	  DAC960_Enquiry_T *OldEnquiry =
+	    &Controller->Enquiry[Controller->EnquiryIndex];
+	  DAC960_Enquiry_T *NewEnquiry =
+	    &Controller->Enquiry[Controller->EnquiryIndex ^= 1];
+	  unsigned int OldCriticalLogicalDriveCount =
+	    OldEnquiry->CriticalLogicalDriveCount;
+	  unsigned int NewCriticalLogicalDriveCount =
+	    NewEnquiry->CriticalLogicalDriveCount;
+	  if (NewEnquiry->StatusFlags.DeferredWriteError !=
+	      OldEnquiry->StatusFlags.DeferredWriteError)
+	    DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
+			    (NewEnquiry->StatusFlags.DeferredWriteError
+			     ? "TRUE" : "FALSE"));
+	  if ((NewCriticalLogicalDriveCount > 0 ||
+	       NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) ||
+	      (NewEnquiry->OfflineLogicalDriveCount > 0 ||
+	       NewEnquiry->OfflineLogicalDriveCount !=
+	       OldEnquiry->OfflineLogicalDriveCount) ||
+	      (NewEnquiry->DeadDriveCount > 0 ||
+	       NewEnquiry->DeadDriveCount !=
+	       OldEnquiry->DeadDriveCount) ||
+	      (NewEnquiry->EventLogSequenceNumber !=
+	       OldEnquiry->EventLogSequenceNumber) ||
+	      Controller->MonitoringTimerCount == 0 ||
+	      (jiffies - Controller->SecondaryMonitoringTime
+	       >= DAC960_SecondaryMonitoringInterval))
+	    {
+	      Controller->NeedLogicalDriveInformation = true;
+	      Controller->NewEventLogSequenceNumber =
+		NewEnquiry->EventLogSequenceNumber;
+	      Controller->NeedErrorTableInformation = true;
+	      Controller->NeedDeviceStateInformation = true;
+	      Controller->DeviceStateChannel = 0;
+	      Controller->DeviceStateTargetID = 0;
+	      Controller->SecondaryMonitoringTime = jiffies;
+	    }
+	  if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
+	      NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress ||
+	      OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress ||
+	      OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress)
+	    Controller->NeedRebuildProgress = true;
+	  if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
+	    switch (NewEnquiry->RebuildFlag)
+	      {
+	      case DAC960_NoStandbyRebuildOrCheckInProgress:
+		DAC960_Progress("Consistency Check Completed Successfully\n",
+				Controller);
+		break;
+	      case DAC960_StandbyRebuildInProgress:
+	      case DAC960_BackgroundRebuildInProgress:
+		break;
+	      case DAC960_BackgroundCheckInProgress:
+		Controller->NeedConsistencyCheckProgress = true;
+		break;
+	      case DAC960_StandbyRebuildCompletedWithError:
+		DAC960_Progress("Consistency Check Completed with Error\n",
+				Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed:
+		DAC960_Progress("Consistency Check Failed - "
+				"Physical Drive Failed\n", Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed:
+		DAC960_Progress("Consistency Check Failed - "
+				"Logical Drive Failed\n", Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses:
+		DAC960_Progress("Consistency Check Failed - Other Causes\n",
+				Controller);
+		break;
+	      case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated:
+		DAC960_Progress("Consistency Check Successfully Terminated\n",
+				Controller);
+		break;
+	      }
+	  else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
+	    Controller->NeedConsistencyCheckProgress = true;
+	}
+      else if (CommandOpcode == DAC960_PerformEventLogOperation)
+	{
+	  static char
+	    *DAC960_EventMessages[] =
+	       { "killed because write recovery failed",
+		 "killed because of SCSI bus reset failure",
+		 "killed because of double check condition",
+		 "killed because it was removed",
+		 "killed because of gross error on SCSI chip",
+		 "killed because of bad tag returned from drive",
+		 "killed because of timeout on SCSI command",
+		 "killed because of reset SCSI command issued from system",
+		 "killed because busy or parity error count exceeded limit",
+		 "killed because of 'kill drive' command from system",
+		 "killed because of selection timeout",
+		 "killed due to SCSI phase sequence error",
+		 "killed due to unknown status" };
+	  DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry;
+	  if (EventLogEntry->SequenceNumber ==
+	      Controller->OldEventLogSequenceNumber)
+	    {
+	      unsigned char SenseKey = EventLogEntry->SenseKey;
+	      unsigned char AdditionalSenseCode =
+		EventLogEntry->AdditionalSenseCode;
+	      unsigned char AdditionalSenseCodeQualifier =
+		EventLogEntry->AdditionalSenseCodeQualifier;
+	      if (SenseKey == 9 &&
+		  AdditionalSenseCode == 0x80 &&
+		  AdditionalSenseCodeQualifier <
+		  sizeof(DAC960_EventMessages) / sizeof(char *))
+		DAC960_Critical("Physical Drive %d:%d %s\n", Controller,
+				EventLogEntry->Channel,
+				EventLogEntry->TargetID,
+				DAC960_EventMessages[
+				  AdditionalSenseCodeQualifier]);
+	      else if (!(SenseKey == 0 ||
+			 (SenseKey == 2 &&
+			  AdditionalSenseCode == 0x04 &&
+			  (AdditionalSenseCodeQualifier == 0x01 ||
+			   AdditionalSenseCodeQualifier == 0x02)) ||
+			 (SenseKey == 6 && AdditionalSenseCode == 0x29 &&
+			  Controller->MonitoringTimerCount == 0)))
+		{
+		  DAC960_Critical("Physical Drive %d:%d Error Log: "
+				  "Sense Key = %d, ASC = %02X, ASCQ = %02X\n",
+				  Controller,
+				  EventLogEntry->Channel,
+				  EventLogEntry->TargetID,
+				  SenseKey,
+				  AdditionalSenseCode,
+				  AdditionalSenseCodeQualifier);
+		  DAC960_Critical("Physical Drive %d:%d Error Log: "
+				  "Information = %02X%02X%02X%02X "
+				  "%02X%02X%02X%02X\n",
+				  Controller,
+				  EventLogEntry->Channel,
+				  EventLogEntry->TargetID,
+				  EventLogEntry->Information[0],
+				  EventLogEntry->Information[1],
+				  EventLogEntry->Information[2],
+				  EventLogEntry->Information[3],
+				  EventLogEntry->CommandSpecificInformation[0],
+				  EventLogEntry->CommandSpecificInformation[1],
+				  EventLogEntry->CommandSpecificInformation[2],
+				  EventLogEntry->CommandSpecificInformation[3]);
+		}
+	    }
+	  Controller->OldEventLogSequenceNumber++;
+	}
+      else if (CommandOpcode == DAC960_GetErrorTable)
+	{
+	  DAC960_ErrorTable_T *OldErrorTable =
+	    &Controller->ErrorTable[Controller->ErrorTableIndex];
+	  DAC960_ErrorTable_T *NewErrorTable =
+	    &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1];
+	  int Channel, TargetID;
+	  for (Channel = 0; Channel < Controller->Channels; Channel++)
+	    for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++)
+	      {
+		DAC960_ErrorTableEntry_T *NewErrorEntry =
+		  &NewErrorTable->ErrorTableEntries[Channel][TargetID];
+		DAC960_ErrorTableEntry_T *OldErrorEntry =
+		  &OldErrorTable->ErrorTableEntries[Channel][TargetID];
+		if ((NewErrorEntry->ParityErrorCount !=
+		     OldErrorEntry->ParityErrorCount) ||
+		    (NewErrorEntry->SoftErrorCount !=
+		     OldErrorEntry->SoftErrorCount) ||
+		    (NewErrorEntry->HardErrorCount !=
+		     OldErrorEntry->HardErrorCount) ||
+		    (NewErrorEntry->MiscErrorCount !=
+		     OldErrorEntry->MiscErrorCount))
+		  DAC960_Critical("Physical Drive %d:%d Errors: "
+				  "Parity = %d, Soft = %d, "
+				  "Hard = %d, Misc = %d\n",
+				  Controller, Channel, TargetID,
+				  NewErrorEntry->ParityErrorCount,
+				  NewErrorEntry->SoftErrorCount,
+				  NewErrorEntry->HardErrorCount,
+				  NewErrorEntry->MiscErrorCount);
+	      }
+	}
+      else if (CommandOpcode == DAC960_GetDeviceState)
+	{
+	  DAC960_DeviceState_T *OldDeviceState =
+	    &Controller->DeviceState[Controller->DeviceStateIndex]
+				    [Controller->DeviceStateChannel]
+				    [Controller->DeviceStateTargetID];
+	  DAC960_DeviceState_T *NewDeviceState =
+	    &Controller->DeviceState[Controller->DeviceStateIndex ^ 1]
+				    [Controller->DeviceStateChannel]
+				    [Controller->DeviceStateTargetID];
+	  if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
+	    DAC960_Critical("Physical Drive %d:%d is now %s\n", Controller,
+			    Controller->DeviceStateChannel,
+			    Controller->DeviceStateTargetID,
+			    (NewDeviceState->DeviceState == DAC960_Device_Dead
+			     ? "DEAD"
+			     : NewDeviceState->DeviceState
+			       == DAC960_Device_WriteOnly
+			       ? "WRITE-ONLY"
+			       : NewDeviceState->DeviceState
+				 == DAC960_Device_Online
+				 ? "ONLINE" : "STANDBY"));
+	  if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
+	    {
+	      Controller->DeviceStateChannel++;
+	      Controller->DeviceStateTargetID = 0;
+	    }
+	}
+      else if (CommandOpcode == DAC960_GetLogicalDriveInformation)
+	{
+	  int LogicalDriveNumber;
+	  for (LogicalDriveNumber = 0;
+	       LogicalDriveNumber < Controller->LogicalDriveCount;
+	       LogicalDriveNumber++)
+	    {
+	      DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation =
+		&Controller->LogicalDriveInformation
+			     [Controller->LogicalDriveInformationIndex]
+			     [LogicalDriveNumber];
+	      DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation =
+		&Controller->LogicalDriveInformation
+			     [Controller->LogicalDriveInformationIndex ^ 1]
+			     [LogicalDriveNumber];
+	      if (NewLogicalDriveInformation->LogicalDriveState !=
+		  OldLogicalDriveInformation->LogicalDriveState)
+		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+				"is now %s\n", Controller,
+				LogicalDriveNumber,
+				Controller->ControllerNumber,
+				LogicalDriveNumber,
+				(NewLogicalDriveInformation->LogicalDriveState
+				 == DAC960_LogicalDrive_Online
+				 ? "ONLINE"
+				 : NewLogicalDriveInformation->LogicalDriveState
+				 == DAC960_LogicalDrive_Critical
+				 ? "CRITICAL" : "OFFLINE"));
+	      if (NewLogicalDriveInformation->WriteBack !=
+		  OldLogicalDriveInformation->WriteBack)
+		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+				"is now %s\n", Controller,
+				LogicalDriveNumber,
+				Controller->ControllerNumber,
+				LogicalDriveNumber,
+				(NewLogicalDriveInformation->WriteBack
+				 ? "WRITE BACK" : "WRITE THRU"));
+	    }
+	  Controller->LogicalDriveInformationIndex ^= 1;
+	}
+      else if (CommandOpcode == DAC960_GetRebuildProgress)
+	{
+	  unsigned int LogicalDriveNumber =
+	    Controller->RebuildProgress.LogicalDriveNumber;
+	  unsigned int LogicalDriveSize =
+	    Controller->RebuildProgress.LogicalDriveSize;
+	  unsigned int BlocksCompleted =
+	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  switch (CommandStatus)
+	    {
+	    case DAC960_NormalCompletion:
+	      Controller->EphemeralProgressMessage = true;
+	      DAC960_Progress("Rebuild in Progress: "
+			      "Logical Drive %d (/dev/rd/c%dd%d) "
+			      "%d%% completed\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber,
+			      (100 * (BlocksCompleted >> 7))
+			      / (LogicalDriveSize >> 7));
+	      Controller->EphemeralProgressMessage = false;
+	      break;
+	    case DAC960_RebuildFailed_LogicalDriveFailure:
+	      DAC960_Progress("Rebuild Failed due to "
+			      "Logical Drive Failure\n", Controller);
+	      break;
+	    case DAC960_RebuildFailed_BadBlocksOnOther:
+	      DAC960_Progress("Rebuild Failed due to "
+			      "Bad Blocks on Other Drives\n", Controller);
+	      break;
+	    case DAC960_RebuildFailed_NewDriveFailed:
+	      DAC960_Progress("Rebuild Failed due to "
+			      "Failure of Drive Being Rebuilt\n", Controller);
+	      break;
+	    case DAC960_NoRebuildOrCheckInProgress:
+	      if (Controller->LastRebuildStatus != DAC960_NormalCompletion)
+		break;
+	    case DAC960_RebuildSuccessful:
+	      DAC960_Progress("Rebuild Completed Successfully\n", Controller);
+	      break;
+	    }
+	  Controller->LastRebuildStatus = CommandStatus;
+	}
+      else if (CommandOpcode == DAC960_RebuildStat)
+	{
+	  unsigned int LogicalDriveNumber =
+	    Controller->RebuildProgress.LogicalDriveNumber;
+	  unsigned int LogicalDriveSize =
+	    Controller->RebuildProgress.LogicalDriveSize;
+	  unsigned int BlocksCompleted =
+	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  if (CommandStatus == DAC960_NormalCompletion)
+	    {
+	      Controller->EphemeralProgressMessage = true;
+	      DAC960_Progress("Consistency Check in Progress: "
+			      "Logical Drive %d (/dev/rd/c%dd%d) "
+			      "%d%% completed\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber,
+			      (100 * (BlocksCompleted >> 7))
+			      / (LogicalDriveSize >> 7));
+	      Controller->EphemeralProgressMessage = false;
+	    }
+	}
+    }
+  if (CommandType == DAC960_MonitoringCommand)
+    {
+      if (Controller->NewEventLogSequenceNumber
+	  - Controller->OldEventLogSequenceNumber > 0)
+	{
+	  Command->CommandMailbox.Type3E.CommandOpcode =
+	    DAC960_PerformEventLogOperation;
+	  Command->CommandMailbox.Type3E.OperationType =
+	    DAC960_GetEventLogEntry;
+	  Command->CommandMailbox.Type3E.OperationQualifier = 1;
+	  Command->CommandMailbox.Type3E.SequenceNumber =
+	    Controller->OldEventLogSequenceNumber;
+	  Command->CommandMailbox.Type3E.BusAddress =
+	    Virtual_to_Bus(&Controller->EventLogEntry);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedErrorTableInformation)
+	{
+	  Controller->NeedErrorTableInformation = false;
+	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(
+	      &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedRebuildProgress && 
+	  Controller->Enquiry[Controller->EnquiryIndex]
+		      .CriticalLogicalDriveCount <
+	  Controller->Enquiry[Controller->EnquiryIndex ^ 1]
+		      .CriticalLogicalDriveCount)
+	{
+	  Controller->NeedRebuildProgress = false;
+	  Command->CommandMailbox.Type3.CommandOpcode =
+	    DAC960_GetRebuildProgress;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(&Controller->RebuildProgress);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedDeviceStateInformation)
+	{
+	  while (Controller->DeviceStateChannel < Controller->Channels)
+	    {
+	      DAC960_DeviceState_T *OldDeviceState =
+		&Controller->DeviceState[Controller->DeviceStateIndex]
+					[Controller->DeviceStateChannel]
+					[Controller->DeviceStateTargetID];
+	      if (OldDeviceState->Present &&
+		  OldDeviceState->DeviceType == DAC960_DiskType)
+		{
+		  Command->CommandMailbox.Type3D.CommandOpcode =
+		    DAC960_GetDeviceState;
+		  Command->CommandMailbox.Type3D.Channel =
+		    Controller->DeviceStateChannel;
+		  Command->CommandMailbox.Type3D.TargetID =
+		    Controller->DeviceStateTargetID;
+		  Command->CommandMailbox.Type3D.BusAddress =
+		    Virtual_to_Bus(&Controller->DeviceState
+				      [Controller->DeviceStateIndex ^ 1]
+				      [Controller->DeviceStateChannel]
+				      [Controller->DeviceStateTargetID]);
+		  DAC960_QueueCommand(Command);
+		  return;
+		}
+	      if (++Controller->DeviceStateTargetID == DAC960_MaxTargets)
+		{
+		  Controller->DeviceStateChannel++;
+		  Controller->DeviceStateTargetID = 0;
+		}
+	    }
+	  Controller->NeedDeviceStateInformation = false;
+	  Controller->DeviceStateIndex ^= 1;
+	}
+      if (Controller->NeedLogicalDriveInformation)
+	{
+	  Controller->NeedLogicalDriveInformation = false;
+	  Command->CommandMailbox.Type3.CommandOpcode =
+	    DAC960_GetLogicalDriveInformation;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(
+	      &Controller->LogicalDriveInformation
+			   [Controller->LogicalDriveInformationIndex ^ 1]);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedRebuildProgress)
+	{
+	  Controller->NeedRebuildProgress = false;
+	  Command->CommandMailbox.Type3.CommandOpcode =
+	    DAC960_GetRebuildProgress;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(&Controller->RebuildProgress);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      if (Controller->NeedConsistencyCheckProgress)
+	{
+	  Controller->NeedConsistencyCheckProgress = false;
+	  Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat;
+	  Command->CommandMailbox.Type3.BusAddress =
+	    Virtual_to_Bus(&Controller->RebuildProgress);
+	  DAC960_QueueCommand(Command);
+	  return;
+	}
+      Controller->MonitoringTimerCount++;
+      Controller->MonitoringTimer.expires =
+	jiffies + DAC960_MonitoringTimerInterval;
+      add_timer(&Controller->MonitoringTimer);
+    }
+  if (CommandType == DAC960_ImmediateCommand)
+    {
+      up(Command->Semaphore);
+      Command->Semaphore = NULL;
+      return;
+    }
+  if (CommandType == DAC960_QueuedCommand)
+    {
+      DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand;
+      KernelCommand->CommandStatus = CommandStatus;
+      Command->KernelCommand = NULL;
+      if (CommandOpcode == DAC960_DCDB)
+	Controller->DirectCommandActive[KernelCommand->DCDB->Channel]
+				       [KernelCommand->DCDB->TargetID] = false;
+      DAC960_DeallocateCommand(Command);
+      KernelCommand->CompletionFunction(KernelCommand);
+      return;
+    }
+  /*
+    Queue a Status Monitoring Command to the Controller using the just
+    completed Command if one was deferred previously due to lack of a
+    free Command when the Monitoring Timer Function was called.
+  */
+  if (Controller->MonitoringCommandDeferred)
+    {
+      Controller->MonitoringCommandDeferred = false;
+      DAC960_QueueMonitoringCommand(Command);
+      return;
+    }
+  /*
+    Deallocate the Command, and wake up any processes waiting on a free Command.
+  */
+  DAC960_DeallocateCommand(Command);
+  wake_up(&Controller->CommandWaitQueue);
+}
+
+
+/*
+  DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers.
+*/
+
+static void DAC960_InterruptHandler(int IRQ_Channel,
+				    void *DeviceIdentifier,
+				    Registers_T *InterruptRegisters)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_StatusMailbox_T *NextStatusMailbox;
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags);
+  /*
+    Process Hardware Interrupts for Controller.
+  */
+  switch (Controller->ControllerType)
+    {
+    case DAC960_V5_Controller:
+      DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress);
+      NextStatusMailbox = Controller->NextStatusMailbox;
+      while (NextStatusMailbox->Fields.Valid)
+	{
+	  DAC960_CommandIdentifier_T CommandIdentifier =
+	    NextStatusMailbox->Fields.CommandIdentifier;
+	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+	  Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+	  NextStatusMailbox->Word = 0;
+	  if (++NextStatusMailbox > Controller->LastStatusMailbox)
+	    NextStatusMailbox = Controller->FirstStatusMailbox;
+	  DAC960_ProcessCompletedCommand(Command);
+	}
+      Controller->NextStatusMailbox = NextStatusMailbox;
+      break;
+    case DAC960_V4_Controller:
+      DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress);
+      NextStatusMailbox = Controller->NextStatusMailbox;
+      while (NextStatusMailbox->Fields.Valid)
+	{
+	  DAC960_CommandIdentifier_T CommandIdentifier =
+	    NextStatusMailbox->Fields.CommandIdentifier;
+	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+	  Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+	  NextStatusMailbox->Word = 0;
+	  if (++NextStatusMailbox > Controller->LastStatusMailbox)
+	    NextStatusMailbox = Controller->FirstStatusMailbox;
+	  DAC960_ProcessCompletedCommand(Command);
+	}
+      Controller->NextStatusMailbox = NextStatusMailbox;
+      break;
+    case DAC960_V3_Controller:
+      while (DAC960_V3_StatusAvailableP(ControllerBaseAddress))
+	{
+	  DAC960_CommandIdentifier_T CommandIdentifier =
+	    DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress);
+	  DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier];
+	  Command->CommandStatus =
+	    DAC960_V3_ReadStatusRegister(ControllerBaseAddress);
+	  DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress);
+	  DAC960_V3_AcknowledgeStatus(ControllerBaseAddress);
+	  DAC960_ProcessCompletedCommand(Command);
+	}
+      break;
+    }
+  /*
+    Attempt to remove additional I/O Requests from the Controller's
+    I/O Request Queue and queue them to the Controller.
+  */
+  while (DAC960_ProcessRequest(Controller, false)) ;
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller.
+*/
+
+static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_MonitoringCommand;
+  CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry;
+  CommandMailbox->Type3.BusAddress =
+    Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]);
+  DAC960_QueueCommand(Command);
+}
+
+
+/*
+  DAC960_MonitoringTimerFunction is the timer function for monitoring
+  the status of DAC960 Controllers.
+*/
+
+static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData;
+  DAC960_Command_T *Command;
+  ProcessorFlags_T ProcessorFlags;
+  /*
+    Acquire exclusive access to Controller.
+  */
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  /*
+    Queue a Status Monitoring Command to Controller.
+  */
+  Command = DAC960_AllocateCommand(Controller);
+  if (Command != NULL)
+    DAC960_QueueMonitoringCommand(Command);
+  else Controller->MonitoringCommandDeferred = true;
+  /*
+    Release exclusive access to Controller.
+  */
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+}
+
+
+/*
+  DAC960_Open is the Device Open Function for the DAC960 Driver.
+*/
+
+static int DAC960_Open(Inode_T *Inode, File_T *File)
+{
+  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+  DAC960_Controller_T *Controller;
+  if (ControllerNumber == 0 && LogicalDriveNumber == 0 &&
+      (File->f_flags & O_NONBLOCK))
+    goto ModuleOnly;
+  if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
+    return -ENXIO;
+  Controller = DAC960_Controllers[ControllerNumber];
+  if (Controller == NULL ||
+      LogicalDriveNumber > Controller->LogicalDriveCount - 1)
+    return -ENXIO;
+  if (Controller->LogicalDriveInformation
+		  [Controller->LogicalDriveInformationIndex]
+		  [LogicalDriveNumber].LogicalDriveState
+      == DAC960_LogicalDrive_Offline)
+    return -ENXIO;
+  if (Controller->LogicalDriveInitialState[LogicalDriveNumber]
+      == DAC960_LogicalDrive_Offline)
+    {
+      Controller->LogicalDriveInitialState[LogicalDriveNumber] =
+	DAC960_LogicalDrive_Online;
+      DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
+      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+    }
+  if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
+    return -ENXIO;
+  /*
+    Increment Controller and Logical Drive Usage Counts.
+  */
+  Controller->ControllerUsageCount++;
+  Controller->LogicalDriveUsageCount[LogicalDriveNumber]++;
+ ModuleOnly:
+  MOD_INC_USE_COUNT;
+  return 0;
+}
+
+
+/*
+  DAC960_Release is the Device Release Function for the DAC960 Driver.
+*/
+
+static int DAC960_Release(Inode_T *Inode, File_T *File)
+{
+  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+  DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+  if (ControllerNumber == 0 && LogicalDriveNumber == 0 &&
+      File != NULL && (File->f_flags & O_NONBLOCK))
+    goto ModuleOnly;
+  /*
+    Force any buffered data to be written.
+  */
+  fsync_dev(Inode->i_rdev);
+  /*
+    Decrement the Logical Drive and Controller Usage Counts.
+  */
+  Controller->LogicalDriveUsageCount[LogicalDriveNumber]--;
+  Controller->ControllerUsageCount--;
+ ModuleOnly:
+  MOD_DEC_USE_COUNT;
+  return 0;
+}
+
+
+/*
+  DAC960_IOCTL is the Device IOCTL Function for the DAC960 Driver.
+*/
+
+static int DAC960_IOCTL(Inode_T *Inode, File_T *File,
+			unsigned int Request, unsigned long Argument)
+{
+  int ControllerNumber = DAC960_ControllerNumber(Inode->i_rdev);
+  int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
+  DiskGeometry_T Geometry, *UserGeometry;
+  DAC960_Controller_T *Controller;
+  int PartitionNumber;
+  if (File->f_flags & O_NONBLOCK)
+    return DAC960_UserIOCTL(Inode, File, Request, Argument);
+  if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
+    return -ENXIO;
+  Controller = DAC960_Controllers[ControllerNumber];
+  if (Controller == NULL ||
+      LogicalDriveNumber > Controller->LogicalDriveCount - 1)
+    return -ENXIO;
+  switch (Request)
+    {
+    case HDIO_GETGEO:
+      /* Get BIOS Disk Geometry. */
+      UserGeometry = (DiskGeometry_T *) Argument;
+      if (UserGeometry == NULL) return -EINVAL;
+      Geometry.heads = Controller->GeometryTranslationHeads;
+      Geometry.sectors = Controller->GeometryTranslationSectors;
+      Geometry.cylinders =
+	Controller->LogicalDriveInformation
+		    [Controller->LogicalDriveInformationIndex]
+		    [LogicalDriveNumber].LogicalDriveSize
+	/ (Controller->GeometryTranslationHeads *
+	   Controller->GeometryTranslationSectors);
+      Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
+						  .start_sect;
+      return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T));
+    case BLKGETSIZE:
+      /* Get Device Size. */
+      if ((long *) Argument == NULL) return -EINVAL;
+      return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
+						 .nr_sects,
+		      (long *) Argument);
+    case BLKRAGET:
+      /* Get Read-Ahead. */
+      if ((int *) Argument == NULL) return -EINVAL;
+      return put_user(read_ahead[MAJOR(Inode->i_rdev)], (int *) Argument);
+    case BLKRASET:
+      /* Set Read-Ahead. */
+      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+      if (Argument > 256) return -EINVAL;
+      read_ahead[MAJOR(Inode->i_rdev)] = Argument;
+      return 0;
+    case BLKFLSBUF:
+      /* Flush Buffers. */
+      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+      fsync_dev(Inode->i_rdev);
+      invalidate_buffers(Inode->i_rdev);
+      return 0;
+    case BLKRRPART:
+      /* Re-Read Partition Table. */
+      if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+      if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1)
+	return -EBUSY;
+      for (PartitionNumber = 0;
+	   PartitionNumber < DAC960_MaxPartitions;
+	   PartitionNumber++)
+	{
+	  KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber,
+						      LogicalDriveNumber,
+						      PartitionNumber);
+	  int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
+					       PartitionNumber);
+	  SuperBlock_T *SuperBlock = get_super(Device);
+	  if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
+	    continue;
+	  /*
+	    Flush all changes and invalidate buffered state.
+	  */
+	  sync_dev(Device);
+	  if (SuperBlock != NULL)
+	    invalidate_inodes(SuperBlock);
+	  invalidate_buffers(Device);
+	  /*
+	    Clear existing partition sizes.
+	  */
+	  if (PartitionNumber > 0)
+	    {
+	      Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0;
+	      Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0;
+	    }
+	  /*
+	    Reset the Block Size so that the partition table can be read.
+	  */
+	  set_blocksize(Device, BLOCK_SIZE);
+	}
+      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+      return 0;
+    }
+  return -EINVAL;
+}
+
+
+/*
+  DAC960_UserIOCTL is the User IOCTL Function for the DAC960 Driver.
+*/
+
+static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
+			    unsigned int Request, unsigned long Argument)
+{
+  int ErrorCode;
+  if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+  switch (Request)
+    {
+    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+      return DAC960_ControllerCount;
+    case DAC960_IOCTL_GET_CONTROLLER_INFO:
+      {
+	DAC960_ControllerInfo_T *UserSpaceControllerInfo =
+	  (DAC960_ControllerInfo_T *) Argument;
+	DAC960_ControllerInfo_T ControllerInfo;
+	DAC960_Controller_T *Controller;
+	int ControllerNumber;
+	if (UserSpaceControllerInfo == NULL) return -EINVAL;
+	ErrorCode = get_user(ControllerNumber,
+			     &UserSpaceControllerInfo->ControllerNumber);
+	if (ErrorCode != 0) return ErrorCode;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	memset(&ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
+	ControllerInfo.ControllerNumber = ControllerNumber;
+	ControllerInfo.PCI_Bus = Controller->Bus;
+	ControllerInfo.PCI_Device = Controller->Device;
+	ControllerInfo.PCI_Function = Controller->Function;
+	ControllerInfo.IRQ_Channel = Controller->IRQ_Channel;
+	ControllerInfo.Channels = Controller->Channels;
+	ControllerInfo.PCI_Address = Controller->PCI_Address;
+	strcpy(ControllerInfo.ModelName, Controller->ModelName);
+	strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion);
+	return copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
+			    sizeof(DAC960_ControllerInfo_T));
+      }
+    case DAC960_IOCTL_EXECUTE_COMMAND:
+      {
+	DAC960_UserCommand_T *UserSpaceUserCommand =
+	  (DAC960_UserCommand_T *) Argument;
+	DAC960_UserCommand_T UserCommand;
+	DAC960_Controller_T *Controller;
+	DAC960_Command_T *Command = NULL;
+	DAC960_CommandOpcode_T CommandOpcode;
+	DAC960_CommandStatus_T CommandStatus;
+	DAC960_DCDB_T DCDB;
+	ProcessorFlags_T ProcessorFlags;
+	int ControllerNumber, DataTransferLength;
+	unsigned char *DataTransferBuffer = NULL;
+	if (UserSpaceUserCommand == NULL) return -EINVAL;
+	ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand,
+				   sizeof(DAC960_UserCommand_T));
+	if (ErrorCode != 0) goto Failure;
+	ControllerNumber = UserCommand.ControllerNumber;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode;
+	DataTransferLength = UserCommand.DataTransferLength;
+	if (CommandOpcode & 0x80) return -EINVAL;
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    ErrorCode =
+	      copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T));
+	    if (ErrorCode != 0) goto Failure;
+	    if (!((DataTransferLength == 0 &&
+		   DCDB.Direction == DAC960_DCDB_NoDataTransfer) ||
+		  (DataTransferLength > 0 &&
+		   DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) ||
+		  (DataTransferLength < 0 &&
+		   DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice)))
+	      return -EINVAL;
+	    if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
+		!= abs(DataTransferLength))
+	      return -EINVAL;
+	  }
+	if (DataTransferLength > 0)
+	  {
+	    DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
+	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    memset(DataTransferBuffer, 0, DataTransferLength);
+	  }
+	else if (DataTransferLength < 0)
+	  {
+	    DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
+	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    ErrorCode = copy_from_user(DataTransferBuffer,
+				       UserCommand.DataTransferBuffer,
+				       -DataTransferLength);
+	    if (ErrorCode != 0) goto Failure;
+	  }
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    while (true)
+	      {
+		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+		if (!Controller->DirectCommandActive[DCDB.Channel]
+						    [DCDB.TargetID])
+		  Command = DAC960_AllocateCommand(Controller);
+		if (Command != NULL)
+		  Controller->DirectCommandActive[DCDB.Channel]
+						 [DCDB.TargetID] = true;
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		if (Command != NULL) break;
+		sleep_on(&Controller->CommandWaitQueue);
+	      }
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_ImmediateCommand;
+	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB);
+	    DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer);
+	  }
+	else
+	  {
+	    while (true)
+	      {
+		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+		Command = DAC960_AllocateCommand(Controller);
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		if (Command != NULL) break;
+		sleep_on(&Controller->CommandWaitQueue);
+	      }
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_ImmediateCommand;
+	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    if (DataTransferBuffer != NULL)
+	      Command->CommandMailbox.Type3.BusAddress =
+		Virtual_to_Bus(DataTransferBuffer);
+	  }
+	DAC960_ExecuteCommand(Command);
+	CommandStatus = Command->CommandStatus;
+	DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	DAC960_DeallocateCommand(Command);
+	DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	if (CommandStatus == DAC960_NormalCompletion &&
+	    DataTransferLength > 0)
+	  {
+	    ErrorCode = copy_to_user(UserCommand.DataTransferBuffer,
+				     DataTransferBuffer, DataTransferLength);
+	    if (ErrorCode != 0) goto Failure;
+	  }
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    Controller->DirectCommandActive[DCDB.Channel]
+					   [DCDB.TargetID] = false;
+	    ErrorCode =
+	      copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T));
+	    if (ErrorCode != 0) goto Failure;
+	  }
+	ErrorCode = CommandStatus;
+      Failure:
+	if (DataTransferBuffer != NULL)
+	  kfree(DataTransferBuffer);
+	return ErrorCode;
+      }
+    }
+  return -EINVAL;
+}
+
+
+/*
+  DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver.
+*/
+
+int DAC960_KernelIOCTL(unsigned int Request, void *Argument)
+{
+  switch (Request)
+    {
+    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+      return DAC960_ControllerCount;
+    case DAC960_IOCTL_GET_CONTROLLER_INFO:
+      {
+	DAC960_ControllerInfo_T *ControllerInfo =
+	  (DAC960_ControllerInfo_T *) Argument;
+	DAC960_Controller_T *Controller;
+	int ControllerNumber;
+	if (ControllerInfo == NULL) return -EINVAL;
+	ControllerNumber = ControllerInfo->ControllerNumber;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
+	ControllerInfo->ControllerNumber = ControllerNumber;
+	ControllerInfo->PCI_Bus = Controller->Bus;
+	ControllerInfo->PCI_Device = Controller->Device;
+	ControllerInfo->PCI_Function = Controller->Function;
+	ControllerInfo->IRQ_Channel = Controller->IRQ_Channel;
+	ControllerInfo->Channels = Controller->Channels;
+	ControllerInfo->PCI_Address = Controller->PCI_Address;
+	strcpy(ControllerInfo->ModelName, Controller->ModelName);
+	strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion);
+	return 0;
+      }
+    case DAC960_IOCTL_EXECUTE_COMMAND:
+      {
+	DAC960_KernelCommand_T *KernelCommand =
+	  (DAC960_KernelCommand_T *) Argument;
+	DAC960_Controller_T *Controller;
+	DAC960_Command_T *Command = NULL;
+	DAC960_CommandOpcode_T CommandOpcode;
+	DAC960_DCDB_T *DCDB = NULL;
+	ProcessorFlags_T ProcessorFlags;
+	int ControllerNumber, DataTransferLength;
+	unsigned char *DataTransferBuffer = NULL;
+	if (KernelCommand == NULL) return -EINVAL;
+	ControllerNumber = KernelCommand->ControllerNumber;
+	if (ControllerNumber < 0 ||
+	    ControllerNumber > DAC960_ControllerCount - 1)
+	  return -ENXIO;
+	Controller = DAC960_Controllers[ControllerNumber];
+	if (Controller == NULL)
+	  return -ENXIO;
+	CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode;
+	DataTransferLength = KernelCommand->DataTransferLength;
+	DataTransferBuffer = KernelCommand->DataTransferBuffer;
+	if (CommandOpcode & 0x80) return -EINVAL;
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    DCDB = KernelCommand->DCDB;
+	    if (!((DataTransferLength == 0 &&
+		   DCDB->Direction == DAC960_DCDB_NoDataTransfer) ||
+		  (DataTransferLength > 0 &&
+		   DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) ||
+		  (DataTransferLength < 0 &&
+		   DCDB->Direction == DAC960_DCDB_DataTransferSystemToDevice)))
+	      return -EINVAL;
+	    if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength)
+		!= abs(DataTransferLength))
+	      return -EINVAL;
+	  }
+	if (DataTransferLength != 0 && DataTransferBuffer == NULL)
+	  return -EINVAL;
+	if (DataTransferLength > 0)
+	  memset(DataTransferBuffer, 0, DataTransferLength);
+	if (CommandOpcode == DAC960_DCDB)
+	  {
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    if (!Controller->DirectCommandActive[DCDB->Channel]
+						[DCDB->TargetID])
+	      Command = DAC960_AllocateCommand(Controller);
+	    if (Command == NULL)
+	      {
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		return -EBUSY;
+	      }
+	    else Controller->DirectCommandActive[DCDB->Channel]
+						[DCDB->TargetID] = true;
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_QueuedCommand;
+	    memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+	    Command->KernelCommand = KernelCommand;
+	    DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer);
+	    DAC960_QueueCommand(Command);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	  }
+	else
+	  {
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    Command = DAC960_AllocateCommand(Controller);
+	    if (Command == NULL)
+	      {
+		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+		return -EBUSY;
+	      }
+	    DAC960_ClearCommand(Command);
+	    Command->CommandType = DAC960_QueuedCommand;
+	    memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox,
+		   sizeof(DAC960_CommandMailbox_T));
+	    if (DataTransferBuffer != NULL)
+	      Command->CommandMailbox.Type3.BusAddress =
+		Virtual_to_Bus(DataTransferBuffer);
+	    Command->KernelCommand = KernelCommand;
+	    DAC960_QueueCommand(Command);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+	  }
+	return 0;
+      }
+    }
+  return -EINVAL;
+}
+
+
+/*
+  DAC960_GenericDiskInit is the Generic Disk Information Initialization
+  Function for the DAC960 Driver.
+*/
+
+static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo)
+{
+  DAC960_Controller_T *Controller =
+    (DAC960_Controller_T *) GenericDiskInfo->real_devices;
+  DAC960_LogicalDriveInformation_T *LogicalDriveInformation =
+    Controller->LogicalDriveInformation
+		[Controller->LogicalDriveInformationIndex];
+  int LogicalDriveNumber;
+  for (LogicalDriveNumber = 0;
+       LogicalDriveNumber < Controller->LogicalDriveCount;
+       LogicalDriveNumber++)
+    GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects =
+      LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize;
+}
+
+
+/*
+  DAC960_Message prints Driver Messages.
+*/
+
+static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
+			   char *Format,
+			   DAC960_Controller_T *Controller,
+			   ...)
+{
+  static char Buffer[DAC960_LineBufferSize];
+  static boolean BeginningOfLine = true;
+  va_list Arguments;
+  int Length = 0;
+  va_start(Arguments, Controller);
+  Length = vsprintf(Buffer, Format, Arguments);
+  va_end(Arguments);
+  if (Controller == NULL)
+    printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+	   DAC960_ControllerCount, Buffer);
+  else if (MessageLevel == DAC960_AnnounceLevel ||
+	   MessageLevel == DAC960_InfoLevel)
+    {
+      if (!Controller->ControllerInitialized)
+	{
+	  strcpy(&Controller->InitialStatusBuffer[
+		    Controller->InitialStatusLength], Buffer);
+	  Controller->InitialStatusLength += Length;
+	  if (MessageLevel == DAC960_AnnounceLevel)
+	    {
+	      static int AnnouncementLines = 0;
+	      if (++AnnouncementLines <= 2)
+		printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
+		       Buffer);
+	    }
+	  else
+	    {
+	      if (BeginningOfLine)
+		{
+		  if (Buffer[0] != '\n' || Length > 1)
+		    printk("%sDAC960#%d: %s",
+			   DAC960_MessageLevelMap[MessageLevel],
+			   Controller->ControllerNumber, Buffer);
+		}
+	      else printk("%s", Buffer);
+	    }
+	}
+      else
+	{
+	  strcpy(&Controller->CurrentStatusBuffer[
+		    Controller->CurrentStatusLength], Buffer);
+	  Controller->CurrentStatusLength += Length;
+	}
+    }
+  else if (MessageLevel == DAC960_ProgressLevel)
+    {
+      strcpy(Controller->RebuildProgressBuffer, Buffer);
+      Controller->RebuildProgressLength = Length;
+      if (Controller->EphemeralProgressMessage)
+	{
+	  if (jiffies - Controller->LastProgressReportTime
+	      >= DAC960_ProgressReportingInterval)
+	    {
+	      printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+		     Controller->ControllerNumber, Buffer);
+	      Controller->LastProgressReportTime = jiffies;
+	    }
+	}
+      else printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+		  Controller->ControllerNumber, Buffer);
+    }
+  else if (MessageLevel == DAC960_UserCriticalLevel)
+    {
+      strcpy(&Controller->UserStatusBuffer[Controller->UserStatusLength],
+	     Buffer);
+      Controller->UserStatusLength += Length;
+      if (Buffer[0] != '\n' || Length > 1)
+	printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+	       Controller->ControllerNumber, Buffer);
+    }
+  else
+    {
+      if (BeginningOfLine)
+	printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+	       Controller->ControllerNumber, Buffer);
+      else printk("%s", Buffer);
+    }
+  BeginningOfLine = (Buffer[Length-1] == '\n');
+}
+
+
+/*
+  DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive
+  Channel:TargetID specification from a User Command string.  It updates
+  Channel and TargetID and returns true on success and returns false otherwise.
+*/
+
+static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller,
+					 char *UserCommandString,
+					 unsigned char *Channel,
+					 unsigned char *TargetID)
+{
+  char *NewUserCommandString = UserCommandString;
+  unsigned long XChannel, XTargetID;
+  while (*UserCommandString == ' ') UserCommandString++;
+  if (UserCommandString == NewUserCommandString)
+    return false;
+  XChannel = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+  if (NewUserCommandString == UserCommandString ||
+      *NewUserCommandString != ':' ||
+      XChannel >= Controller->Channels)
+    return false;
+  UserCommandString = ++NewUserCommandString;
+  XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+  if (NewUserCommandString == UserCommandString ||
+      *NewUserCommandString != '\0' ||
+      XTargetID >= DAC960_MaxTargets)
+    return false;
+  *Channel = XChannel;
+  *TargetID = XTargetID;
+  return true;
+}
+
+
+/*
+  DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number
+  specification from a User Command string.  It updates LogicalDriveNumber and
+  returns true on success and returns false otherwise.
+*/
+
+static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
+					char *UserCommandString,
+					unsigned char *LogicalDriveNumber)
+{
+  char *NewUserCommandString = UserCommandString;
+  unsigned long XLogicalDriveNumber;
+  while (*UserCommandString == ' ') UserCommandString++;
+  if (UserCommandString == NewUserCommandString)
+    return false;
+  XLogicalDriveNumber =
+    simple_strtoul(UserCommandString, &NewUserCommandString, 10);
+  if (NewUserCommandString == UserCommandString ||
+      *NewUserCommandString != '\0' ||
+      XLogicalDriveNumber >= Controller->LogicalDriveCount)
+    return false;
+  *LogicalDriveNumber = XLogicalDriveNumber;
+  return true;
+}
+
+
+/*
+  DAC960_SetDeviceState sets the Device State for a Physical Drive.
+*/
+
+static void DAC960_SetDeviceState(DAC960_Controller_T *Controller,
+				  DAC960_Command_T *Command,
+				  unsigned char Channel,
+				  unsigned char TargetID,
+				  DAC960_PhysicalDeviceState_T DeviceState,
+				  const char *DeviceStateString)
+{
+  DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox;
+  CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice;
+  CommandMailbox->Type3D.Channel = Channel;
+  CommandMailbox->Type3D.TargetID = TargetID;
+  CommandMailbox->Type3D.DeviceState = DeviceState;
+  CommandMailbox->Type3D.Modifier = 0;
+  DAC960_ExecuteCommand(Command);
+  switch (Command->CommandStatus)
+    {
+    case DAC960_NormalCompletion:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_UnableToStartDevice:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Unable to Start Device\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_NoDeviceAtAddress:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "No Device at Address\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_InvalidChannelOrTargetOrModifier:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Invalid Channel or Target or Modifier\n",
+			  Controller, DeviceStateString, Channel, TargetID);
+      break;
+    case DAC960_ChannelBusy:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Channel Busy\n", Controller,
+			  DeviceStateString, Channel, TargetID);
+      break;
+    default:
+      DAC960_UserCritical("%s of Physical Drive %d:%d Failed - "
+			  "Unexpected Status %04X\n", Controller,
+			  DeviceStateString, Channel, TargetID,
+			  Command->CommandStatus);
+      break;
+    }
+}
+
+
+/*
+  DAC960_ExecuteUserCommand executes a User Command.
+*/
+
+static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller,
+					 char *UserCommand)
+{
+  DAC960_Command_T *Command;
+  DAC960_CommandMailbox_T *CommandMailbox;
+  ProcessorFlags_T ProcessorFlags;
+  unsigned char Channel, TargetID, LogicalDriveNumber;
+  while (true)
+    {
+      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+      Command = DAC960_AllocateCommand(Controller);
+      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+      if (Command != NULL) break;
+      sleep_on(&Controller->CommandWaitQueue);
+    }
+  Controller->UserStatusLength = 0;
+  DAC960_ClearCommand(Command);
+  Command->CommandType = DAC960_ImmediateCommand;
+  CommandMailbox = &Command->CommandMailbox;
+  if (strcmp(UserCommand, "flush-cache") == 0)
+    {
+      CommandMailbox->Type3.CommandOpcode = DAC960_Flush;
+      DAC960_ExecuteCommand(Command);
+      DAC960_UserCritical("Cache Flush Completed\n", Controller);
+    }
+  else if (strncmp(UserCommand, "kill", 4) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[4],
+				     &Channel, &TargetID))
+    {
+      DAC960_DeviceState_T *DeviceState =
+	&Controller->DeviceState[Controller->DeviceStateIndex]
+				[Channel][TargetID];
+      if (DeviceState->Present &&
+	  DeviceState->DeviceType == DAC960_DiskType &&
+	  DeviceState->DeviceState != DAC960_Device_Dead)
+	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+			      DAC960_Device_Dead, "Kill");
+      else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n",
+			       Controller, Channel, TargetID);
+    }
+  else if (strncmp(UserCommand, "make-online", 11) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[11],
+				     &Channel, &TargetID))
+    {
+      DAC960_DeviceState_T *DeviceState =
+	&Controller->DeviceState[Controller->DeviceStateIndex]
+				[Channel][TargetID];
+      if (DeviceState->Present &&
+	  DeviceState->DeviceType == DAC960_DiskType &&
+	  DeviceState->DeviceState == DAC960_Device_Dead)
+	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+			      DAC960_Device_Online, "Make Online");
+      else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n",
+			       Controller, Channel, TargetID);
+
+    }
+  else if (strncmp(UserCommand, "make-standby", 12) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[12],
+				     &Channel, &TargetID))
+    {
+      DAC960_DeviceState_T *DeviceState =
+	&Controller->DeviceState[Controller->DeviceStateIndex]
+				[Channel][TargetID];
+      if (DeviceState->Present &&
+	  DeviceState->DeviceType == DAC960_DiskType &&
+	  DeviceState->DeviceState == DAC960_Device_Dead)
+	DAC960_SetDeviceState(Controller, Command, Channel, TargetID,
+			      DAC960_Device_Standby, "Make Standby");
+      else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n",
+			       Controller, Channel, TargetID);
+    }
+  else if (strncmp(UserCommand, "rebuild", 7) == 0 &&
+	   DAC960_ParsePhysicalDrive(Controller, &UserCommand[7],
+				     &Channel, &TargetID))
+    {
+      CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync;
+      CommandMailbox->Type3D.Channel = Channel;
+      CommandMailbox->Type3D.TargetID = TargetID;
+      DAC960_ExecuteCommand(Command);
+      switch (Command->CommandStatus)
+	{
+	case DAC960_NormalCompletion:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_AttemptToRebuildOnlineDrive:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Attempt to Rebuild Online or "
+			      "Unresponsive Drive\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_NewDiskFailedDuringRebuild:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "New Disk Failed During Rebuild\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_InvalidDeviceAddress:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Invalid Device Address\n",
+			      Controller, Channel, TargetID);
+	  break;
+	case DAC960_RebuildOrCheckAlreadyInProgress:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Rebuild or Consistency Check Already "
+			      "in Progress\n", Controller, Channel, TargetID);
+	  break;
+	default:
+	  DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - "
+			      "Unexpected Status %04X\n", Controller,
+			      Channel, TargetID, Command->CommandStatus);
+	  break;
+	}
+    }
+  else if (strncmp(UserCommand, "check-consistency", 17) == 0 &&
+	   DAC960_ParseLogicalDrive(Controller, &UserCommand[17],
+				    &LogicalDriveNumber))
+    {
+      CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync;
+      CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber;
+      CommandMailbox->Type3C.AutoRestore = true;
+      DAC960_ExecuteCommand(Command);
+      switch (Command->CommandStatus)
+	{
+	case DAC960_NormalCompletion:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Initiated\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	case DAC960_DependentDiskIsDead:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - "
+			      "Dependent Physical Drive is DEAD\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	case DAC960_InvalidOrNonredundantLogicalDrive:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - "
+			      "Invalid or Nonredundant Logical Drive\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	case DAC960_RebuildOrCheckAlreadyInProgress:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - Rebuild or "
+			      "Consistency Check Already in Progress\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	  break;
+	default:
+	  DAC960_UserCritical("Consistency Check of Logical Drive %d "
+			      "(/dev/rd/c%dd%d) Failed - "
+			      "Unexpected Status %04X\n",
+			      Controller, LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber, Command->CommandStatus);
+	  break;
+	}
+    }
+  else if (strcmp(UserCommand, "cancel-rebuild") == 0 ||
+	   strcmp(UserCommand, "cancel-consistency-check") == 0)
+    {
+      unsigned char OldRebuildRateConstant;
+      CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl;
+      CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
+      CommandMailbox->Type3R.BusAddress =
+	Virtual_to_Bus(&OldRebuildRateConstant);
+      DAC960_ExecuteCommand(Command);
+      switch (Command->CommandStatus)
+	{
+	case DAC960_NormalCompletion:
+	  DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n",
+			      Controller);
+	  break;
+	default:
+	  DAC960_UserCritical("Cancellation of Rebuild or "
+			      "Consistency Check Failed - "
+			      "Unexpected Status %04X\n",
+			      Controller, Command->CommandStatus);
+	  break;
+	}
+    }
+  else DAC960_UserCritical("Illegal User Command: '%s'\n",
+			   Controller, UserCommand);
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  DAC960_DeallocateCommand(Command);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+  return true;
+}
+
+
+/*
+  DAC960_ProcReadStatus implements reading /proc/rd/status.
+*/
+
+static ssize_t DAC960_ProcReadStatus(char *Page, char **Start,
+				     off_t Offset, int Count,
+				     int *EOF, void *Data)
+{
+  char *StatusMessage = "OK\n";
+  int ControllerNumber, BytesAvailable;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      DAC960_Enquiry_T *Enquiry;
+      if (Controller == NULL) continue;
+      Enquiry = &Controller->Enquiry[Controller->EnquiryIndex];
+      if (Enquiry->CriticalLogicalDriveCount > 0 ||
+	  Enquiry->OfflineLogicalDriveCount > 0 ||
+	  Enquiry->DeadDriveCount > 0)
+	{
+	  StatusMessage = "ALERT\n";
+	  break;
+	}
+    }
+  BytesAvailable = strlen(StatusMessage) - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  memcpy(Page, &StatusMessage[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status.
+*/
+
+static ssize_t DAC960_ProcReadInitialStatus(char *Page, char **Start,
+					    off_t Offset, int Count,
+					    int *EOF, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  int BytesAvailable = Controller->InitialStatusLength - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status.
+*/
+
+static ssize_t DAC960_ProcReadCurrentStatus(char *Page, char **Start,
+					    off_t Offset, int Count,
+					    int *EOF, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  int BytesAvailable;
+  Controller->CurrentStatusLength = 0;
+  DAC960_AnnounceDriver(Controller);
+  DAC960_ReportControllerConfiguration(Controller);
+  Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+  Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+  if (Controller->RebuildProgressLength > 0)
+    {
+      strcpy(&Controller->CurrentStatusBuffer[Controller->CurrentStatusLength],
+	     Controller->RebuildProgressBuffer);
+      Controller->CurrentStatusLength += Controller->RebuildProgressLength;
+    }
+  else
+    {
+      char *StatusMessage = "No Rebuild or Consistency Check in Progress\n";
+      strcpy(&Controller->CurrentStatusBuffer[Controller->CurrentStatusLength],
+	     StatusMessage);
+      Controller->CurrentStatusLength += strlen(StatusMessage);
+    }
+  BytesAvailable = Controller->CurrentStatusLength - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  memcpy(Page, &Controller->CurrentStatusBuffer[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command.
+*/
+
+static ssize_t DAC960_ProcReadUserCommand(char *Page, char **Start,
+					  off_t Offset, int Count,
+					  int *EOF, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  int BytesAvailable = Controller->UserStatusLength - Offset;
+  if (Count >= BytesAvailable)
+    {
+      Count = BytesAvailable;
+      *EOF = true;
+    }
+  if (Count <= 0) return 0;
+  memcpy(Page, &Controller->UserStatusBuffer[Offset], Count);
+  return Count;
+}
+
+
+/*
+  DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command.
+*/
+
+static ssize_t DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer,
+					   unsigned long Count, void *Data)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
+  char CommandBuffer[80];
+  int Length;
+  if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
+  copy_from_user(CommandBuffer, Buffer, Count);
+  CommandBuffer[Count] = '\0';
+  Length = strlen(CommandBuffer);
+  if (CommandBuffer[Length-1] == '\n')
+    CommandBuffer[--Length] = '\0';
+  return (DAC960_ExecuteUserCommand(Controller, CommandBuffer)
+	  ? Count : -EBUSY);
+}
+
+
+/*
+  DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960
+  Driver.
+*/
+
+static void DAC960_CreateProcEntries(void)
+{
+  static PROC_DirectoryEntry_T StatusProcEntry;
+  int ControllerNumber;
+  DAC960_ProcDirectoryEntry.name = "rd";
+  DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name);
+  DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO;
+  proc_register(&proc_root, &DAC960_ProcDirectoryEntry);
+  StatusProcEntry.name = "status";
+  StatusProcEntry.namelen = strlen(StatusProcEntry.name);
+  StatusProcEntry.mode = S_IFREG | S_IRUGO;
+  StatusProcEntry.read_proc = DAC960_ProcReadStatus;
+  proc_register(&DAC960_ProcDirectoryEntry, &StatusProcEntry);
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      PROC_DirectoryEntry_T *ControllerProcEntry, *InitialStatusProcEntry;
+      PROC_DirectoryEntry_T *CurrentStatusProcEntry, *UserCommandProcEntry;
+      if (Controller == NULL) continue;
+      ControllerProcEntry = &Controller->ControllerProcEntry;
+      ControllerProcEntry->name = Controller->ControllerName;
+      ControllerProcEntry->namelen = strlen(ControllerProcEntry->name);
+      ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+      proc_register(&DAC960_ProcDirectoryEntry, ControllerProcEntry);
+      InitialStatusProcEntry = &Controller->InitialStatusProcEntry;
+      InitialStatusProcEntry->name = "initial_status";
+      InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name);
+      InitialStatusProcEntry->mode = S_IFREG | S_IRUGO;
+      InitialStatusProcEntry->data = Controller;
+      InitialStatusProcEntry->read_proc = DAC960_ProcReadInitialStatus;
+      proc_register(ControllerProcEntry, InitialStatusProcEntry);
+      CurrentStatusProcEntry = &Controller->CurrentStatusProcEntry;
+      CurrentStatusProcEntry->name = "current_status";
+      CurrentStatusProcEntry->namelen = strlen(CurrentStatusProcEntry->name);
+      CurrentStatusProcEntry->mode = S_IFREG | S_IRUGO;
+      CurrentStatusProcEntry->data = Controller;
+      CurrentStatusProcEntry->read_proc = DAC960_ProcReadCurrentStatus;
+      proc_register(ControllerProcEntry, CurrentStatusProcEntry);
+      UserCommandProcEntry = &Controller->UserCommandProcEntry;
+      UserCommandProcEntry->name = "user_command";
+      UserCommandProcEntry->namelen = strlen(UserCommandProcEntry->name);
+      UserCommandProcEntry->mode = S_IFREG | S_IWUSR | S_IRUSR;
+      UserCommandProcEntry->data = Controller;
+      UserCommandProcEntry->read_proc = DAC960_ProcReadUserCommand;
+      UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
+      proc_register(ControllerProcEntry, UserCommandProcEntry);
+    }
+}
+
+
+/*
+  DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the DAC960
+  Driver.
+*/
+
+static void DAC960_DestroyProcEntries(void)
+{
+  proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino);
+}
+
+
+/*
+  Include Module support if requested.
+*/
+
+#ifdef MODULE
+
+
+int init_module(void)
+{
+  int ControllerNumber, LogicalDriveNumber;
+  DAC960_Initialize();
+  if (DAC960_ActiveControllerCount == 0) return -1;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      if (Controller == NULL) continue;
+      DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
+      for (LogicalDriveNumber = 0;
+	   LogicalDriveNumber < Controller->LogicalDriveCount;
+	   LogicalDriveNumber++)
+	resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+    }
+  return 0;
+}
+
+
+void cleanup_module(void)
+{
+  DAC960_Finalize(&DAC960_NotifierBlock, SYS_RESTART, NULL);
+}
+
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/DAC960.h linux.pre11.3/drivers/block/DAC960.h
--- linux.vanilla/drivers/block/DAC960.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/DAC960.h	Tue Jul 20 00:27:58 1999
@@ -0,0 +1,2184 @@
+/*
+
+  Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers
+
+  Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+
+  This program is free software; you may redistribute and/or modify it under
+  the terms of the GNU General Public License Version 2 as published by the
+  Free Software Foundation.
+
+  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 complete details.
+
+  The author respectfully requests that any modifications to this software be
+  sent directly to him for evaluation and testing.
+
+*/
+
+
+/*
+  Define the maximum number of DAC960 Controllers supported by this driver.
+*/
+
+#define DAC960_MaxControllers			8
+
+
+/*
+  Define the maximum number of Controller Channels supported by this driver.
+*/
+
+#define DAC960_MaxChannels			3
+
+
+/*
+  Define the maximum number of Targets per Channel supported by this driver.
+*/
+
+#define DAC960_MaxTargets			16
+
+
+/*
+  Define the maximum number of Logical Drives supported by any DAC960 model.
+*/
+
+#define DAC960_MaxLogicalDrives			32
+
+
+/*
+  Define a Boolean data type.
+*/
+
+typedef enum { false, true } __attribute__ ((packed)) boolean;
+
+
+/*
+  Define a 32 bit I/O Address data type.
+*/
+
+typedef unsigned int DAC960_IO_Address_T;
+
+
+/*
+  Define a 32 bit PCI Bus Address data type.
+*/
+
+typedef unsigned int DAC960_PCI_Address_T;
+
+
+/*
+  Define a 32 bit Bus Address data type.
+*/
+
+typedef unsigned int DAC960_BusAddress_T;
+
+
+/*
+  Define a 32 bit Byte Count data type.
+*/
+
+typedef unsigned int DAC960_ByteCount_T;
+
+
+/*
+  Define the DAC960 Command Opcodes.
+*/
+
+typedef enum
+{
+  /* I/O Commands */
+  DAC960_ReadExtended =				0x33,
+  DAC960_WriteExtended =			0x34,
+  DAC960_ReadAheadExtended =			0x35,
+  DAC960_ReadExtendedWithScatterGather =	0xB3,
+  DAC960_WriteExtendedWithScatterGather =	0xB4,
+  DAC960_Read =					0x36,
+  DAC960_ReadWithOldScatterGather =		0xB6,
+  DAC960_Write =				0x37,
+  DAC960_WriteWithOldScatterGather =		0xB7,
+  DAC960_DCDB =					0x04,
+  DAC960_DCDBWithScatterGather =		0x84,
+  DAC960_Flush =				0x0A,
+  /* Controller Status Related Commands */
+  DAC960_Enquiry =				0x53,
+  DAC960_Enquiry2 =				0x1C,
+  DAC960_GetLogicalDriveElement =		0x55,
+  DAC960_GetLogicalDriveInformation =		0x19,
+  DAC960_IOPortRead =				0x39,
+  DAC960_IOPortWrite =				0x3A,
+  DAC960_GetSDStats =				0x3E,
+  DAC960_GetPDStats =				0x3F,
+  DAC960_PerformEventLogOperation =		0x72,
+  /* Device Related Commands */
+  DAC960_StartDevice =				0x10,
+  DAC960_GetDeviceState =			0x50,
+  DAC960_StopChannel =				0x13,
+  DAC960_StartChannel =				0x12,
+  DAC960_ResetChannel =				0x1A,
+  /* Commands Associated with Data Consistency and Errors */
+  DAC960_Rebuild =				0x09,
+  DAC960_RebuildAsync =				0x16,
+  DAC960_CheckConsistency =			0x0F,
+  DAC960_CheckConsistencyAsync =		0x1E,
+  DAC960_RebuildStat =				0x0C,
+  DAC960_GetRebuildProgress =			0x27,
+  DAC960_RebuildControl =			0x1F,
+  DAC960_ReadBadBlockTable =			0x0B,
+  DAC960_ReadBadDataTable =			0x25,
+  DAC960_ClearBadDataTable =			0x26,
+  DAC960_GetErrorTable =			0x17,
+  DAC960_AddCapacityAsync =			0x2A,
+  /* Configuration Related Commands */
+  DAC960_ReadConfig2 =				0x3D,
+  DAC960_WriteConfig2 =				0x3C,
+  DAC960_ReadConfigurationOnDisk =		0x4A,
+  DAC960_WriteConfigurationOnDisk =		0x4B,
+  DAC960_ReadConfiguration =			0x4E,
+  DAC960_ReadBackupConfiguration =		0x4D,
+  DAC960_WriteConfiguration =			0x4F,
+  DAC960_AddConfiguration =			0x4C,
+  DAC960_ReadConfigurationLabel =		0x48,
+  DAC960_WriteConfigurationLabel =		0x49,
+  /* Firmware Upgrade Related Commands */
+  DAC960_LoadImage =				0x20,
+  DAC960_StoreImage =				0x21,
+  DAC960_ProgramImage =				0x22,
+  /* Diagnostic Commands */
+  DAC960_SetDiagnosticMode =			0x31,
+  DAC960_RunDiagnostic =			0x32,
+  /* Subsystem Service Commands */
+  DAC960_GetSubsystemData =			0x70,
+  DAC960_SetSubsystemParameters =		0x71
+}
+__attribute__ ((packed))
+DAC960_CommandOpcode_T;
+
+
+/*
+  Define the DAC960 Command Identifier type.
+*/
+
+typedef unsigned char DAC960_CommandIdentifier_T;
+
+
+/*
+  Define the DAC960 Command Status Codes.
+*/
+
+#define DAC960_NormalCompletion			0x0000	/* Common */
+#define DAC960_CheckConditionReceived		0x0002	/* Common */
+#define DAC960_NoDeviceAtAddress		0x0102	/* Common */
+#define DAC960_InvalidDeviceAddress		0x0105	/* Common */
+#define DAC960_InvalidParameter			0x0105	/* Common */
+#define DAC960_IrrecoverableDataError		0x0001	/* I/O */
+#define DAC960_LogicalDriveNonexistentOrOffline	0x0002	/* I/O */
+#define DAC960_AccessBeyondEndOfLogicalDrive	0x0105	/* I/O */
+#define DAC960_BadDataEncountered		0x010C	/* I/O */
+#define DAC960_DeviceBusy			0x0008	/* DCDB */
+#define DAC960_DeviceNonresponsive		0x000E	/* DCDB */
+#define DAC960_CommandTerminatedAbnormally	0x000F	/* DCDB */
+#define DAC960_UnableToStartDevice		0x0002	/* Device */
+#define DAC960_InvalidChannelOrTargetOrModifier	0x0105	/* Device */
+#define DAC960_ChannelBusy			0x0106	/* Device */
+#define DAC960_ChannelNotStopped		0x0002	/* Device */
+#define DAC960_AttemptToRebuildOnlineDrive	0x0002	/* Consistency */
+#define DAC960_RebuildBadBlocksEncountered	0x0003	/* Consistency */
+#define DAC960_NewDiskFailedDuringRebuild	0x0004	/* Consistency */
+#define DAC960_RebuildOrCheckAlreadyInProgress	0x0106	/* Consistency */
+#define DAC960_DependentDiskIsDead		0x0002	/* Consistency */
+#define DAC960_InconsistentBlocksFound		0x0003	/* Consistency */
+#define DAC960_InvalidOrNonredundantLogicalDrive 0x0105	/* Consistency */
+#define DAC960_NoRebuildOrCheckInProgress	0x0105	/* Consistency */
+#define DAC960_RebuildInProgress_DataValid	0x0000	/* Consistency */
+#define DAC960_RebuildFailed_LogicalDriveFailure 0x0002	/* Consistency */
+#define DAC960_RebuildFailed_BadBlocksOnOther	0x0003	/* Consistency */
+#define DAC960_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
+#define DAC960_RebuildSuccessful		0x0100	/* Consistency */
+#define DAC960_AddCapacityInProgress		0x0004	/* Consistency */
+#define DAC960_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
+#define DAC960_Config2ChecksumError		0x0002	/* Configuration */
+#define DAC960_ConfigurationSuspended		0x0106	/* Configuration */
+#define DAC960_FailedToConfigureNVRAM		0x0105	/* Configuration */
+#define DAC960_ConfigurationNotSavedStateChange	0x0106	/* Configuration */
+#define DAC960_SubsystemNotInstalled		0x0001	/* Subsystem */
+#define DAC960_SubsystemFailed			0x0002	/* Subsystem */
+#define DAC960_SubsystemBusy			0x0106	/* Subsystem */
+
+typedef unsigned short DAC960_CommandStatus_T;
+
+
+/*
+  Define the Enquiry reply structure.
+*/
+
+typedef struct DAC960_Enquiry
+{
+  unsigned char NumberOfLogicalDrives;			/* Byte 0 */
+  unsigned int :24;					/* Bytes 1-3 */
+  unsigned int LogicalDriveSizes[32];			/* Bytes 4-131 */
+  unsigned short FlashAge;				/* Bytes 132-133 */
+  struct {
+    boolean DeferredWriteError:1;			/* Byte 134 Bit 0 */
+    boolean BatteryLow:1;				/* Byte 134 Bit 1 */
+    unsigned char :6;					/* Byte 134 Bits 2-7 */
+  } StatusFlags;
+  unsigned char :8;					/* Byte 135 */
+  unsigned char MinorFirmwareVersion;			/* Byte 136 */
+  unsigned char MajorFirmwareVersion;			/* Byte 137 */
+  enum {
+    DAC960_NoStandbyRebuildOrCheckInProgress =			0x00,
+    DAC960_StandbyRebuildInProgress =				0x01,
+    DAC960_BackgroundRebuildInProgress =			0x02,
+    DAC960_BackgroundCheckInProgress =				0x03,
+    DAC960_StandbyRebuildCompletedWithError =			0xFF,
+    DAC960_BackgroundRebuildOrCheckFailed_DriveFailed =		0xF0,
+    DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed =	0xF1,
+    DAC960_BackgroundRebuildOrCheckFailed_OtherCauses =		0xF2,
+    DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated =	0xF3
+  } __attribute__ ((packed)) RebuildFlag;		/* Byte 138 */
+  unsigned char MaxCommands;				/* Byte 139 */
+  unsigned char OfflineLogicalDriveCount;		/* Byte 140 */
+  unsigned char :8;					/* Byte 141 */
+  unsigned short EventLogSequenceNumber;		/* Bytes 142-143 */
+  unsigned char CriticalLogicalDriveCount;		/* Byte 144 */
+  unsigned int :24;					/* Bytes 145-147 */
+  unsigned char DeadDriveCount;				/* Byte 148 */
+  unsigned char :8;					/* Byte 149 */
+  unsigned char RebuildCount;				/* Byte 150 */
+  struct {
+    unsigned char :3;					/* Byte 151 Bits 0-2 */
+    boolean BatteryBackupUnitPresent:1;			/* Byte 151 Bit 3 */
+    unsigned char :3;					/* Byte 151 Bits 4-6 */
+    unsigned char :1;					/* Byte 151 Bit 7 */
+  } MiscFlags;
+  struct {
+    unsigned char TargetID;
+    unsigned char Channel;
+  } DeadDrives[21];					/* Bytes 152-194 */
+  unsigned char Reserved[62];				/* Bytes 195-255 */
+}
+__attribute__ ((packed))
+DAC960_Enquiry_T;
+
+
+/*
+  Define the Enquiry2 reply structure.
+*/
+
+typedef struct DAC960_Enquiry2
+{
+  struct {
+    enum {
+      DAC960_P_PD_PU =				0x01,
+      DAC960_PL =				0x02,
+      DAC960_PG =				0x10,
+      DAC960_PJ =				0x11,
+      DAC960_PR =				0x12,
+      DAC960_PT =				0x13,
+      DAC960_PTL0 =				0x14,
+      DAC960_PRL =				0x15,
+      DAC960_PTL1 =				0x16,
+      DAC1164_P =				0x20
+    } __attribute__ ((packed)) SubModel;		/* Byte 0 */
+    unsigned char ActualChannels;			/* Byte 1 */
+    enum {
+      DAC960_FiveChannelBoard =			0x01,
+      DAC960_ThreeChannelBoard =		0x02,
+      DAC960_TwoChannelBoard =			0x03,
+      DAC960_ThreeChannelASIC_DAC =		0x04
+    } __attribute__ ((packed)) Model;			/* Byte 2 */
+    enum {
+      DAC960_EISA_Controller =			0x01,
+      DAC960_MicroChannel_Controller =		0x02,
+      DAC960_PCI_Controller =			0x03,
+      DAC960_SCSItoSCSI_Controller =		0x08
+    } __attribute__ ((packed)) ProductFamily;		/* Byte 3 */
+  } HardwareID;						/* Bytes 0-3 */
+  /* MajorVersion.MinorVersion-FirmwareType-TurnID */
+  struct {
+    unsigned char MajorVersion;				/* Byte 4 */
+    unsigned char MinorVersion;				/* Byte 5 */
+    unsigned char TurnID;				/* Byte 6 */
+    char FirmwareType;					/* Byte 7 */
+  } FirmwareID;						/* Bytes 4-7 */
+  unsigned char :8;					/* Byte 8 */
+  unsigned int :24;					/* Bytes 9-11 */
+  unsigned char ConfiguredChannels;			/* Byte 12 */
+  unsigned char ActualChannels;				/* Byte 13 */
+  unsigned char MaxTargets;				/* Byte 14 */
+  unsigned char MaxTags;				/* Byte 15 */
+  unsigned char MaxLogicalDrives;			/* Byte 16 */
+  unsigned char MaxArms;				/* Byte 17 */
+  unsigned char MaxSpans;				/* Byte 18 */
+  unsigned char :8;					/* Byte 19 */
+  unsigned int :32;					/* Bytes 20-23 */
+  unsigned int MemorySize;				/* Bytes 24-27 */
+  unsigned int CacheSize;				/* Bytes 28-31 */
+  unsigned int FlashMemorySize;				/* Bytes 32-35 */
+  unsigned int NonVolatileMemorySize;			/* Bytes 36-39 */
+  struct {
+    enum {
+      DAC960_DRAM =				0x00,
+      DAC960_EDO =				0x01,
+      DAC960_SDRAM =				0x02
+    } __attribute__ ((packed)) RamType:3;		/* Byte 40 Bits 0-2 */
+    enum {
+      DAC960_None =				0x00,
+      DAC960_Parity =				0x01,
+      DAC960_ECC =				0x02
+    } __attribute__ ((packed)) ErrorCorrection:3;	/* Byte 40 Bits 3-5 */
+    boolean FastPageMode:1;				/* Byte 40 Bit 6 */
+    boolean LowPowerMemory:1;				/* Byte 40 Bit 7 */
+    unsigned char :8;					/* Bytes 41 */
+  } MemoryType;
+  unsigned short ClockSpeed;				/* Bytes 42-43 */
+  unsigned short MemorySpeed;				/* Bytes 44-45 */
+  unsigned short HardwareSpeed;				/* Bytes 46-47 */
+  unsigned int :32;					/* Bytes 48-51 */
+  unsigned int :32;					/* Bytes 52-55 */
+  unsigned char :8;					/* Byte 56 */
+  unsigned char :8;					/* Byte 57 */
+  unsigned short :16;					/* Bytes 58-59 */
+  unsigned short MaxCommands;				/* Bytes 60-61 */
+  unsigned short MaxScatterGatherEntries;		/* Bytes 62-63 */
+  unsigned short MaxDriveCommands;			/* Bytes 64-65 */
+  unsigned short MaxIODescriptors;			/* Bytes 66-67 */
+  unsigned short MaxCombinedSectors;			/* Bytes 68-69 */
+  unsigned char Latency;				/* Byte 70 */
+  unsigned char :8;					/* Byte 71 */
+  unsigned char SCSITimeout;				/* Byte 72 */
+  unsigned char :8;					/* Byte 73 */
+  unsigned short MinFreeLines;				/* Bytes 74-75 */
+  unsigned int :32;					/* Bytes 76-79 */
+  unsigned int :32;					/* Bytes 80-83 */
+  unsigned char RebuildRateConstant;			/* Byte 84 */
+  unsigned char :8;					/* Byte 85 */
+  unsigned char :8;					/* Byte 86 */
+  unsigned char :8;					/* Byte 87 */
+  unsigned int :32;					/* Bytes 88-91 */
+  unsigned int :32;					/* Bytes 92-95 */
+  unsigned short PhysicalDriveBlockSize;		/* Bytes 96-97 */
+  unsigned short LogicalDriveBlockSize;			/* Bytes 98-99 */
+  unsigned short MaxBlocksPerCommand;			/* Bytes 100-101 */
+  unsigned short BlockFactor;				/* Bytes 102-103 */
+  unsigned short CacheLineSize;				/* Bytes 104-105 */
+  struct {
+    enum {
+      DAC960_Narrow_8bit =			0x00,
+      DAC960_Wide_16bit =			0x01,
+      DAC960_Wide_32bit =			0x02
+    } __attribute__ ((packed)) BusWidth:2;		/* Byte 106 Bits 0-1 */
+    enum {
+      DAC960_Fast =				0x00,
+      DAC960_Ultra =				0x01,
+      DAC960_Ultra2 =				0x02
+    } __attribute__ ((packed)) BusSpeed:2;		/* Byte 106 Bits 2-3 */
+    boolean Differential:1;				/* Byte 106 Bit 4 */
+    unsigned char :3;					/* Byte 106 Bits 5-7 */
+  } SCSICapability;
+  unsigned char :8;					/* Byte 107 */
+  unsigned int :32;					/* Bytes 108-111 */
+  unsigned short FirmwareBuildNumber;			/* Bytes 112-113 */
+  enum {
+    DAC960_AEMI =				0x01,
+    DAC960_OEM1 =				0x02,
+    DAC960_OEM2 =				0x04,
+    DAC960_OEM3 =				0x08,
+    DAC960_Conner =				0x10,
+    DAC960_SAFTE =				0x20
+  } __attribute__ ((packed)) FaultManagementType;	/* Byte 114 */
+  unsigned char :8;					/* Byte 115 */
+  struct {
+    boolean Clustering:1;				/* Byte 116 Bit 0 */
+    boolean MylexOnlineRAIDExpansion:1;			/* Byte 116 Bit 1 */
+    unsigned int :30;					/* Bytes 116-119 */
+  } FirmwareFeatures;
+  unsigned int :32;					/* Bytes 120-123 */
+  unsigned int :32;					/* Bytes 124-127 */
+}
+DAC960_Enquiry2_T;
+
+
+/*
+  Define the Logical Drive State type.
+*/
+
+typedef enum
+{
+    DAC960_LogicalDrive_Online =		0x03,
+    DAC960_LogicalDrive_Critical =		0x04,
+    DAC960_LogicalDrive_Offline =		0xFF
+}
+__attribute__ ((packed))
+DAC960_LogicalDriveState_T;
+
+
+/*
+  Define the Get Logical Drive Information reply structure.
+*/
+
+typedef struct DAC960_LogicalDriveInformation
+{
+  unsigned int LogicalDriveSize;			/* Bytes 0-3 */
+  DAC960_LogicalDriveState_T LogicalDriveState;		/* Byte 4 */
+  unsigned char RAIDLevel:7;				/* Byte 5 Bits 0-6 */
+  boolean WriteBack:1;					/* Byte 5 Bit 7 */
+  unsigned int :16;					/* Bytes 6-7 */
+}
+DAC960_LogicalDriveInformation_T;
+
+
+/*
+  Define the Perform Event Log Operation Types.
+*/
+
+typedef enum
+{
+  DAC960_GetEventLogEntry =			0x00
+}
+__attribute__ ((packed))
+DAC960_PerformEventLogOpType_T;
+
+
+/*
+  Define the Get Event Log Entry reply structure.
+*/
+
+typedef struct DAC960_EventLogEntry
+{
+  unsigned char MessageType;				/* Byte 0 */
+  unsigned char MessageLength;				/* Byte 1 */
+  unsigned char TargetID:5;				/* Byte 2 Bits 0-4 */
+  unsigned char Channel:3;				/* Byte 2 Bits 5-7 */
+  unsigned char LogicalUnit:6;				/* Byte 3 Bits 0-5 */
+  unsigned char :2;					/* Byte 3 Bits 6-7 */
+  unsigned short SequenceNumber;			/* Bytes 4-5 */
+  unsigned char ErrorCode:7;				/* Byte 6 Bits 0-6 */
+  boolean Valid:1;					/* Byte 6 Bit 7 */
+  unsigned char SegmentNumber;				/* Byte 7 */
+  unsigned char SenseKey:4;				/* Byte 8 Bits 0-3 */
+  unsigned char :1;					/* Byte 8 Bit 4 */
+  boolean ILI:1;					/* Byte 8 Bit 5 */
+  boolean EOM:1;					/* Byte 8 Bit 6 */
+  boolean Filemark:1;					/* Byte 8 Bit 7 */
+  unsigned char Information[4];				/* Bytes 9-12 */
+  unsigned char AdditionalSenseLength;			/* Byte 13 */
+  unsigned char CommandSpecificInformation[4];		/* Bytes 14-17 */
+  unsigned char AdditionalSenseCode;			/* Byte 18 */
+  unsigned char AdditionalSenseCodeQualifier;		/* Byte 19 */
+  unsigned char Dummy[12];				/* Bytes 20-31 */
+}
+DAC960_EventLogEntry_T;
+
+
+/*
+  Define the Physical Device State type.
+*/
+
+typedef enum
+{
+    DAC960_Device_Dead =			0x00,
+    DAC960_Device_WriteOnly =			0x02,
+    DAC960_Device_Online =			0x03,
+    DAC960_Device_Standby =			0x10
+}
+__attribute__ ((packed))
+DAC960_PhysicalDeviceState_T;
+
+
+/*
+  Define the Get Device State reply structure.
+*/
+
+typedef struct DAC960_DeviceState
+{
+  boolean Present:1;					/* Byte 0 Bit 0 */
+  unsigned char :7;					/* Byte 0 Bits 1-7 */
+  enum {
+    DAC960_OtherType =				0x00,
+    DAC960_DiskType =				0x01,
+    DAC960_SequentialType =			0x02,
+    DAC960_CDROM_or_WORM_Type =			0x03
+    } __attribute__ ((packed)) DeviceType:2;		/* Byte 1 Bits 0-1 */
+  boolean :1;						/* Byte 1 Bit 2 */
+  boolean Fast20:1;					/* Byte 1 Bit 3 */
+  boolean Sync:1;					/* Byte 1 Bit 4 */
+  boolean Fast:1;					/* Byte 1 Bit 5 */
+  boolean Wide:1;					/* Byte 1 Bit 6 */
+  boolean TaggedQueuingSupported:1;			/* Byte 1 Bit 7 */
+  DAC960_PhysicalDeviceState_T DeviceState;		/* Byte 2 */
+  unsigned char :8;					/* Byte 3 */
+  unsigned char SynchronousMultiplier;			/* Byte 4 */
+  unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
+  unsigned char :3;					/* Byte 5 Bits 5-7 */
+  unsigned long DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
+}
+DAC960_DeviceState_T;
+
+
+/*
+  Define the Get Rebuild Progress reply structure.
+*/
+
+typedef struct DAC960_RebuildProgress
+{
+  unsigned int LogicalDriveNumber;			/* Bytes 0-3 */
+  unsigned int LogicalDriveSize;			/* Bytes 4-7 */
+  unsigned int RemainingBlocks;				/* Bytes 8-11 */
+}
+DAC960_RebuildProgress_T;
+
+
+/*
+  Define the Error Table Entry and Get Error Table reply structure.
+*/
+
+typedef struct DAC960_ErrorTableEntry
+{
+  unsigned char ParityErrorCount;			/* Byte 0 */
+  unsigned char SoftErrorCount;				/* Byte 1 */
+  unsigned char HardErrorCount;				/* Byte 2 */
+  unsigned char MiscErrorCount;				/* Byte 3 */
+}
+DAC960_ErrorTableEntry_T;
+
+
+/*
+  Define the Get Error Table reply structure.
+*/
+
+typedef struct DAC960_ErrorTable
+{
+  DAC960_ErrorTableEntry_T
+    ErrorTableEntries[DAC960_MaxChannels][DAC960_MaxTargets];
+}
+DAC960_ErrorTable_T;
+
+
+/*
+  Define the Config2 reply structure.
+*/
+
+typedef struct DAC960_Config2
+{
+  unsigned char :1;					/* Byte 0 Bit 0 */
+  boolean ActiveNegationEnabled:1;			/* Byte 0 Bit 1 */
+  unsigned char :5;					/* Byte 0 Bits 2-6 */
+  boolean NoRescanIfResetReceivedDuringScan:1;		/* Byte 0 Bit 7 */
+  boolean StorageWorksSupportEnabled:1;			/* Byte 1 Bit 0 */
+  boolean HewlettPackardSupportEnabled:1;		/* Byte 1 Bit 1 */
+  boolean NoDisconnectOnFirstCommand:1;			/* Byte 1 Bit 2 */
+  unsigned char :2;					/* Byte 1 Bits 3-4 */
+  boolean AEMI_ARM:1;					/* Byte 1 Bit 5 */
+  boolean AEMI_OFM:1;					/* Byte 1 Bit 6 */
+  unsigned char :1;					/* Byte 1 Bit 7 */
+  enum {
+    DAC960_OEMID_Mylex =			0x00,
+    DAC960_OEMID_IBM =				0x08,
+    DAC960_OEMID_HP =				0x0A,
+    DAC960_OEMID_DEC =				0x0C,
+    DAC960_OEMID_Siemens =			0x10,
+    DAC960_OEMID_Intel =			0x12
+  } __attribute__ ((packed)) OEMID;			/* Byte 2 */
+  unsigned char OEMModelNumber;				/* Byte 3 */
+  unsigned char PhysicalSector;				/* Byte 4 */
+  unsigned char LogicalSector;				/* Byte 5 */
+  unsigned char BlockFactor;				/* Byte 6 */
+  boolean ReadAheadEnabled:1;				/* Byte 7 Bit 0 */
+  boolean LowBIOSDelay:1;				/* Byte 7 Bit 1 */
+  unsigned char :2;					/* Byte 7 Bits 2-3 */
+  boolean ReassignRestrictedToOneSector:1;		/* Byte 7 Bit 4 */
+  unsigned char :1;					/* Byte 7 Bit 5 */
+  boolean ForceUnitAccessDuringWriteRecovery:1;		/* Byte 7 Bit 6 */
+  boolean EnableLeftSymmetricRAID5Algorithm:1;		/* Byte 7 Bit 7 */
+  unsigned char DefaultRebuildRate;			/* Byte 8 */
+  unsigned char :8;					/* Byte 9 */
+  unsigned char BlocksPerCacheLine;			/* Byte 10 */
+  unsigned char BlocksPerStripe;			/* Byte 11 */
+  struct {
+    enum {
+      DAC960_Async =				0x00,
+      DAC960_Sync_8MHz =			0x01,
+      DAC960_Sync_5MHz =			0x02,
+      DAC960_Sync_10or20MHz =			0x03	/* Bits 0-1 */
+    } __attribute__ ((packed)) Speed:2;
+    boolean Force8Bit:1;				/* Bit 2 */
+    boolean DisableFast20:1;				/* Bit 3 */
+    unsigned char :3;					/* Bits 4-6 */
+    boolean EnableTaggedQueuing:1;			/* Bit 7 */
+  } __attribute__ ((packed)) ChannelParameters[6];	/* Bytes 12-17 */
+  unsigned char SCSIInitiatorID;			/* Byte 18 */
+  unsigned char :8;					/* Byte 19 */
+  enum {
+    DAC960_StartupMode_ControllerSpinUp =	0x00,
+    DAC960_StartupMode_PowerOnSpinUp =		0x01
+  } __attribute__ ((packed)) StartupMode;		/* Byte 20 */
+  unsigned char SimultaneousDeviceSpinUpCount;		/* Byte 21 */
+  unsigned char SecondsDelayBetweenSpinUps;		/* Byte 22 */
+  unsigned char Reserved1[29];				/* Bytes 23-51 */
+  boolean BIOSDisabled:1;				/* Byte 52 Bit 0 */
+  boolean CDROMBootEnabled:1;				/* Byte 52 Bit 1 */
+  unsigned char :3;					/* Byte 52 Bits 2-4 */
+  enum {
+    DAC960_Geometry_128_32 =			0x00,
+    DAC960_Geometry_255_63 =			0x01,
+    DAC960_Geometry_Reserved1 =			0x02,
+    DAC960_Geometry_Reserved2 =			0x03
+  } __attribute__ ((packed)) DriveGeometry:2;		/* Byte 52 Bits 5-6 */
+  unsigned char :1;					/* Byte 52 Bit 7 */
+  unsigned char Reserved2[9];				/* Bytes 53-61 */
+  unsigned short Checksum;				/* Bytes 62-63 */
+}
+DAC960_Config2_T;
+
+
+/*
+  Define the DCDB request structure.
+*/
+
+typedef struct DAC960_DCDB
+{
+  unsigned char TargetID:4;				 /* Byte 0 Bits 0-3 */
+  unsigned char Channel:4;				 /* Byte 0 Bits 4-7 */
+  enum {
+    DAC960_DCDB_NoDataTransfer = 0,
+    DAC960_DCDB_DataTransferDeviceToSystem = 1,
+    DAC960_DCDB_DataTransferSystemToDevice = 2,
+    DAC960_DCDB_IllegalDataTransfer = 3
+  } __attribute__ ((packed)) Direction:2;		 /* Byte 1 Bits 0-1 */
+  boolean EarlyStatus:1;				 /* Byte 1 Bit 2 */
+  unsigned char :1;					 /* Byte 1 Bit 3 */
+  enum {
+    DAC960_DCDB_Timeout_24_hours = 0,
+    DAC960_DCDB_Timeout_10_seconds = 1,
+    DAC960_DCDB_Timeout_60_seconds = 2,
+    DAC960_DCDB_Timeout_10_minutes = 3
+  } __attribute__ ((packed)) Timeout:2;			 /* Byte 1 Bits 4-5 */
+  boolean NoAutomaticRequestSense:1;			 /* Byte 1 Bit 6 */
+  boolean DisconnectPermitted:1;			 /* Byte 1 Bit 7 */
+  unsigned short TransferLength;			 /* Bytes 2-3 */
+  DAC960_BusAddress_T BusAddress;			 /* Bytes 4-7 */
+  unsigned char CDBLength:4;				 /* Byte 8 Bits 0-3 */
+  unsigned char TransferLengthHigh4:4;			 /* Byte 8 Bits 4-7 */
+  unsigned char SenseLength;				 /* Byte 9 */
+  unsigned char CDB[12];				 /* Bytes 10-21 */
+  unsigned char SenseData[64];				 /* Bytes 22-85 */
+  unsigned char Status;					 /* Byte 86 */
+  unsigned char :8;					 /* Byte 87 */
+}
+DAC960_DCDB_T;
+
+
+/*
+  Define the Scatter/Gather List Type 1 32 Bit Address 32 Bit Byte Count
+  structure.
+*/
+
+typedef struct DAC960_ScatterGatherSegment
+{
+  DAC960_BusAddress_T SegmentDataPointer;		/* Bytes 0-3 */
+  DAC960_ByteCount_T SegmentByteCount;			/* Bytes 4-7 */
+}
+DAC960_ScatterGatherSegment_T;
+
+
+/*
+  Define the 13 Byte DAC960 Command Mailbox structure.  Bytes 13-15 are
+  not used.  The Command Mailbox structure is padded to 16 bytes for
+  efficient access.
+*/
+
+typedef union DAC960_CommandMailbox
+{
+  unsigned int Words[4];				/* Words 0-3 */
+  unsigned char Bytes[16];				/* Bytes 0-15 */
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy[14];				/* Bytes 2-15 */
+  } __attribute__ ((packed)) Common;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy1[6];				/* Bytes 2-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy1[5];				/* Bytes 2-6 */
+    unsigned char LogicalDriveNumber:6;			/* Byte 7 Bits 0-6 */
+    boolean AutoRestore:1;				/* Byte 7 Bit 7 */
+    unsigned char Dummy2[8];				/* Bytes 8-15 */
+  } __attribute__ ((packed)) Type3C;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Channel;				/* Byte 2 */
+    unsigned char TargetID;				/* Byte 3 */
+    DAC960_PhysicalDeviceState_T DeviceState:5;		/* Byte 4 Bits 0-4 */
+    unsigned char Modifier:3;				/* Byte 4 Bits 5-7 */
+    unsigned char Dummy1[3];				/* Bytes 5-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3D;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    DAC960_PerformEventLogOpType_T OperationType;	/* Byte 2 */
+    unsigned char OperationQualifier;			/* Byte 3 */
+    unsigned short SequenceNumber;			/* Bytes 4-5 */
+    unsigned char Dummy1[2];				/* Bytes 6-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy2[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3E;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char Dummy1[2];				/* Bytes 2-3 */
+    unsigned char RebuildRateConstant;			/* Byte 4 */
+    unsigned char Dummy2[3];				/* Bytes 5-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char Dummy3[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) Type3R;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned short TransferLength;			/* Bytes 2-3 */
+    unsigned int LogicalBlockAddress;			/* Bytes 4-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char LogicalDriveNumber;			/* Byte 12 */
+    unsigned char Dummy[3];				/* Bytes 13-15 */
+  } __attribute__ ((packed)) Type4;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    struct {
+      unsigned short TransferLength:11;			/* Bytes 2-3 */
+      unsigned char LogicalDriveNumber:5;		/* Byte 3 Bits 3-7 */
+    } __attribute__ ((packed)) LD;
+    unsigned int LogicalBlockAddress;			/* Bytes 4-7 */
+    DAC960_BusAddress_T BusAddress;			/* Bytes 8-11 */
+    unsigned char ScatterGatherCount:6;			/* Byte 12 Bits 0-5 */
+    enum {
+      DAC960_ScatterGather_32BitAddress_32BitByteCount =	0x0,
+      DAC960_ScatterGather_32BitAddress_16BitByteCount =	0x1,
+      DAC960_ScatterGather_32BitByteCount_32BitAddress =	0x2,
+      DAC960_ScatterGather_16BitByteCount_32BitAddress =	0x3
+    } __attribute__ ((packed)) ScatterGatherType:2;	/* Byte 12 Bits 6-7 */
+    unsigned char Dummy[3];				/* Bytes 13-15 */
+  } __attribute__ ((packed)) Type5;
+  struct {
+    DAC960_CommandOpcode_T CommandOpcode;		/* Byte 0 */
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 1 */
+    unsigned char CommandOpcode2;			/* Byte 2 */
+    unsigned char :8;					/* Byte 3 */
+    DAC960_BusAddress_T CommandMailboxesBusAddress;	/* Bytes 4-7 */
+    DAC960_BusAddress_T StatusMailboxesBusAddress;	/* Bytes 8-11 */
+    unsigned char Dummy[4];				/* Bytes 12-15 */
+  } __attribute__ ((packed)) TypeX;
+}
+DAC960_CommandMailbox_T;
+
+
+/*
+  Define the DAC960 Driver IOCTL requests.
+*/
+
+#define DAC960_IOCTL_GET_CONTROLLER_COUNT	0xDAC001
+#define DAC960_IOCTL_GET_CONTROLLER_INFO	0xDAC002
+#define DAC960_IOCTL_EXECUTE_COMMAND		0xDAC003
+
+
+/*
+  Define the DAC960_IOCTL_GET_CONTROLLER_INFO reply structure.
+*/
+
+typedef struct DAC960_ControllerInfo
+{
+  unsigned char ControllerNumber;
+  unsigned char PCI_Bus;
+  unsigned char PCI_Device;
+  unsigned char PCI_Function;
+  unsigned char IRQ_Channel;
+  unsigned char Channels;
+  DAC960_PCI_Address_T PCI_Address;
+  unsigned char ModelName[16];
+  unsigned char FirmwareVersion[16];
+}
+DAC960_ControllerInfo_T;
+
+
+/*
+  Define the User Mode DAC960_IOCTL_EXECUTE_COMMAND request structure.
+*/
+
+typedef struct DAC960_UserCommand
+{
+  unsigned char ControllerNumber;
+  DAC960_CommandMailbox_T CommandMailbox;
+  int DataTransferLength;
+  void *DataTransferBuffer;
+  DAC960_DCDB_T *DCDB;
+}
+DAC960_UserCommand_T;
+
+
+/*
+  Define the Kernel Mode DAC960_IOCTL_EXECUTE_COMMAND request structure.
+*/
+
+typedef struct DAC960_KernelCommand
+{
+  unsigned char ControllerNumber;
+  DAC960_CommandMailbox_T CommandMailbox;
+  int DataTransferLength;
+  void *DataTransferBuffer;
+  DAC960_DCDB_T *DCDB;
+  DAC960_CommandStatus_T CommandStatus;
+  void (*CompletionFunction)(struct DAC960_KernelCommand *);
+  void *CompletionData;
+}
+DAC960_KernelCommand_T;
+
+
+/*
+  Import the Kernel Mode IOCTL interface.
+*/
+
+extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument);
+
+
+/*
+  Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses.
+*/
+
+static inline DAC960_BusAddress_T Virtual_to_Bus(void *VirtualAddress)
+{
+  return (DAC960_BusAddress_T) virt_to_bus(VirtualAddress);
+}
+
+
+/*
+  Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses.
+*/
+
+static inline void *Bus_to_Virtual(DAC960_BusAddress_T BusAddress)
+{
+  return (void *) bus_to_virt(BusAddress);
+}
+
+
+/*
+  DAC960_DriverVersion protects the private portion of this file.
+*/
+
+#ifdef DAC960_DriverVersion
+
+
+/*
+  Define the maximum Driver Queue Depth and Controller Queue Depth supported
+  by any DAC960 model.
+*/
+
+#define DAC960_MaxDriverQueueDepth		127
+#define DAC960_MaxControllerQueueDepth		128
+
+
+/*
+  Define the maximum number of Scatter/Gather Segments supported by any
+  DAC960 model.
+*/
+
+#define DAC960_MaxScatterGatherSegments		33
+
+
+/*
+  Define the number of Command Mailboxes and Status Mailboxes used by the
+  Memory Mailbox Interface.
+*/
+
+#define DAC960_CommandMailboxCount		256
+#define DAC960_StatusMailboxCount		1024
+
+
+/*
+  Define the DAC960 Controller Monitoring Timer Interval.
+*/
+
+#define DAC960_MonitoringTimerInterval		(10 * HZ)
+
+
+/*
+  Define the DAC960 Controller Secondary Monitoring Interval.
+*/
+
+#define DAC960_SecondaryMonitoringInterval	(60 * HZ)
+
+
+/*
+  Define the DAC960 Controller Progress Reporting Interval.
+*/
+
+#define DAC960_ProgressReportingInterval	(60 * HZ)
+
+
+/*
+  Define the maximum number of Partitions allowed for each Logical Drive.
+*/
+
+#define DAC960_MaxPartitions			8
+#define DAC960_MaxPartitionsBits		3
+
+
+/*
+  Define macros to extract the Controller Number, Logical Drive Number, and
+  Partition Number from a Kernel Device, and to construct a Major Number, Minor
+  Number, and Kernel Device from the Controller Number, Logical Drive Number,
+  and Partition Number.  There is one Major Number assigned to each Controller.
+  The associated Minor Number is divided into the Logical Drive Number and
+  Partition Number.
+*/
+
+#define DAC960_ControllerNumber(Device) \
+  (MAJOR(Device) - DAC960_MAJOR)
+
+#define DAC960_LogicalDriveNumber(Device) \
+  (MINOR(Device) >> DAC960_MaxPartitionsBits)
+
+#define DAC960_PartitionNumber(Device) \
+  (MINOR(Device) & (DAC960_MaxPartitions - 1))
+
+#define DAC960_MajorNumber(ControllerNumber) \
+  (DAC960_MAJOR + (ControllerNumber))
+
+#define DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber) \
+   (((LogicalDriveNumber) << DAC960_MaxPartitionsBits) | (PartitionNumber))
+
+#define DAC960_MinorCount			(DAC960_MaxLogicalDrives \
+						 * DAC960_MaxPartitions)
+
+#define DAC960_KernelDevice(ControllerNumber,				       \
+			    LogicalDriveNumber,				       \
+			    PartitionNumber)				       \
+   MKDEV(DAC960_MajorNumber(ControllerNumber),				       \
+	 DAC960_MinorNumber(LogicalDriveNumber, PartitionNumber))
+
+
+/*
+  Define the DAC960 Controller fixed Block Size and Block Size Bits.
+*/
+
+#define DAC960_BlockSize			512
+#define DAC960_BlockSizeBits			9
+
+
+/*
+  Define the Controller Line, Status Buffer, Rebuild Progress, and
+  User Message Sizes.
+*/
+
+#define DAC960_LineBufferSize			100
+#define DAC960_StatusBufferSize			5000
+#define DAC960_RebuildProgressSize		200
+#define DAC960_UserMessageSize			200
+
+
+/*
+  Define the types of DAC960 Controllers that are supported.
+*/
+
+typedef enum
+{
+  DAC960_V5_Controller =			1,	/* DAC1164P */
+  DAC960_V4_Controller =			2,	/* DAC960PTL/PJ/PG */
+  DAC960_V3_Controller =			3	/* DAC960PU/PD/PL */
+}
+DAC960_ControllerType_T;
+
+
+/*
+  Define the Driver Message Levels.
+*/
+
+typedef enum DAC960_MessageLevel
+{
+  DAC960_AnnounceLevel =			0,
+  DAC960_InfoLevel =				1,
+  DAC960_NoticeLevel =				2,
+  DAC960_WarningLevel =				3,
+  DAC960_ErrorLevel =				4,
+  DAC960_ProgressLevel =			5,
+  DAC960_CriticalLevel =			6,
+  DAC960_UserCriticalLevel =			7
+}
+DAC960_MessageLevel_T;
+
+static char
+  *DAC960_MessageLevelMap[] =
+    { KERN_NOTICE, KERN_NOTICE, KERN_NOTICE, KERN_WARNING,
+      KERN_ERR, KERN_CRIT, KERN_CRIT, KERN_CRIT };
+
+
+/*
+  Define Driver Message macros.
+*/
+
+#define DAC960_Announce(Format, Arguments...) \
+  DAC960_Message(DAC960_AnnounceLevel, Format, ##Arguments)
+
+#define DAC960_Info(Format, Arguments...) \
+  DAC960_Message(DAC960_InfoLevel, Format, ##Arguments)
+
+#define DAC960_Notice(Format, Arguments...) \
+  DAC960_Message(DAC960_NoticeLevel, Format, ##Arguments)
+
+#define DAC960_Warning(Format, Arguments...) \
+  DAC960_Message(DAC960_WarningLevel, Format, ##Arguments)
+
+#define DAC960_Error(Format, Arguments...) \
+  DAC960_Message(DAC960_ErrorLevel, Format, ##Arguments)
+
+#define DAC960_Progress(Format, Arguments...) \
+  DAC960_Message(DAC960_ProgressLevel, Format, ##Arguments)
+
+#define DAC960_Critical(Format, Arguments...) \
+  DAC960_Message(DAC960_CriticalLevel, Format, ##Arguments)
+
+#define DAC960_UserCritical(Format, Arguments...) \
+  DAC960_Message(DAC960_UserCriticalLevel, Format, ##Arguments)
+
+
+/*
+  Define types for some of the structures that interface with the rest
+  of the Linux Kernel and I/O Subsystem.
+*/
+
+typedef struct buffer_head BufferHeader_T;
+typedef struct file File_T;
+typedef struct file_operations FileOperations_T;
+typedef struct gendisk GenericDiskInfo_T;
+typedef struct hd_geometry DiskGeometry_T;
+typedef struct hd_struct DiskPartition_T;
+typedef struct inode Inode_T;
+typedef struct inode_operations InodeOperations_T;
+typedef kdev_t KernelDevice_T;
+typedef struct notifier_block NotifierBlock_T;
+typedef struct pci_dev PCI_Device_T;
+typedef struct proc_dir_entry PROC_DirectoryEntry_T;
+typedef unsigned long ProcessorFlags_T;
+typedef struct pt_regs Registers_T;
+typedef struct request IO_Request_T;
+typedef struct semaphore Semaphore_T;
+typedef struct super_block SuperBlock_T;
+typedef struct timer_list Timer_T;
+typedef struct wait_queue WaitQueue_T;
+
+
+/*
+  Define the DAC960 Controller Status Mailbox structure.
+*/
+
+typedef union DAC960_StatusMailbox
+{
+  unsigned int Word;					/* Bytes 0-3 */
+  struct {
+    DAC960_CommandIdentifier_T CommandIdentifier;	/* Byte 0 */
+    unsigned char :7;					/* Byte 1 Bits 0-6 */
+    boolean Valid:1;					/* Byte 1 Bit 7 */
+    DAC960_CommandStatus_T CommandStatus;		/* Bytes 2-3 */
+  } Fields;
+}
+DAC960_StatusMailbox_T;
+
+
+/*
+  Define the DAC960 Driver Command Types.
+*/
+
+typedef enum
+{
+  DAC960_ReadCommand =				1,
+  DAC960_WriteCommand =				2,
+  DAC960_ReadRetryCommand =			3,
+  DAC960_WriteRetryCommand =			4,
+  DAC960_MonitoringCommand =			5,
+  DAC960_ImmediateCommand =			6,
+  DAC960_QueuedCommand =			7
+}
+DAC960_CommandType_T;
+
+
+/*
+  Define the DAC960 Driver Command structure.
+*/
+
+typedef struct DAC960_Command
+{
+  DAC960_CommandType_T CommandType;
+  DAC960_CommandMailbox_T CommandMailbox;
+  DAC960_CommandStatus_T CommandStatus;
+  struct DAC960_Controller *Controller;
+  struct DAC960_Command *Next;
+  Semaphore_T *Semaphore;
+  unsigned int LogicalDriveNumber;
+  unsigned int BlockNumber;
+  unsigned int BlockCount;
+  unsigned int SegmentCount;
+  BufferHeader_T *BufferHeader;
+  DAC960_KernelCommand_T *KernelCommand;
+  DAC960_ScatterGatherSegment_T
+    ScatterGatherList[DAC960_MaxScatterGatherSegments];
+}
+DAC960_Command_T;
+
+
+/*
+  Define the DAC960 Driver Controller structure.
+*/
+
+typedef struct DAC960_Controller
+{
+  void *BaseAddress;
+  void *MemoryMappedAddress;
+  DAC960_ControllerType_T ControllerType;
+  DAC960_IO_Address_T IO_Address;
+  DAC960_PCI_Address_T PCI_Address;
+  unsigned char ControllerNumber;
+  unsigned char ControllerName[4];
+  unsigned char ModelName[12];
+  unsigned char FullModelName[18];
+  unsigned char FirmwareVersion[14];
+  unsigned char Bus;
+  unsigned char Device;
+  unsigned char Function;
+  unsigned char IRQ_Channel;
+  unsigned char Channels;
+  unsigned char MemorySize;
+  unsigned char LogicalDriveCount;
+  unsigned char GeometryTranslationHeads;
+  unsigned char GeometryTranslationSectors;
+  unsigned short ControllerQueueDepth;
+  unsigned short DriverQueueDepth;
+  unsigned short MaxBlocksPerCommand;
+  unsigned short MaxScatterGatherSegments;
+  unsigned short StripeSize;
+  unsigned short SegmentSize;
+  unsigned short NewEventLogSequenceNumber;
+  unsigned short OldEventLogSequenceNumber;
+  unsigned short InitialStatusLength;
+  unsigned short CurrentStatusLength;
+  unsigned short UserStatusLength;
+  unsigned short RebuildProgressLength;
+  unsigned int ControllerUsageCount;
+  unsigned int EnquiryIndex;
+  unsigned int LogicalDriveInformationIndex;
+  unsigned int ErrorTableIndex;
+  unsigned int DeviceStateIndex;
+  unsigned int DeviceStateChannel;
+  unsigned int DeviceStateTargetID;
+  unsigned long MonitoringTimerCount;
+  unsigned long SecondaryMonitoringTime;
+  unsigned long LastProgressReportTime;
+  boolean DualModeMemoryMailboxInterface;
+  boolean SAFTE_EnclosureManagementEnabled;
+  boolean ControllerInitialized;
+  boolean MonitoringCommandDeferred;
+  boolean NeedLogicalDriveInformation;
+  boolean NeedErrorTableInformation;
+  boolean NeedDeviceStateInformation;
+  boolean NeedRebuildProgress;
+  boolean NeedConsistencyCheckProgress;
+  boolean EphemeralProgressMessage;
+  Timer_T MonitoringTimer;
+  GenericDiskInfo_T GenericDiskInfo;
+  DAC960_Command_T *FreeCommands;
+  DAC960_CommandMailbox_T *FirstCommandMailbox;
+  DAC960_CommandMailbox_T *LastCommandMailbox;
+  DAC960_CommandMailbox_T *NextCommandMailbox;
+  DAC960_CommandMailbox_T *PreviousCommandMailbox1;
+  DAC960_CommandMailbox_T *PreviousCommandMailbox2;
+  DAC960_StatusMailbox_T *FirstStatusMailbox;
+  DAC960_StatusMailbox_T *LastStatusMailbox;
+  DAC960_StatusMailbox_T *NextStatusMailbox;
+  PROC_DirectoryEntry_T ControllerProcEntry;
+  PROC_DirectoryEntry_T InitialStatusProcEntry;
+  PROC_DirectoryEntry_T CurrentStatusProcEntry;
+  PROC_DirectoryEntry_T UserCommandProcEntry;
+  WaitQueue_T *CommandWaitQueue;
+  DAC960_Enquiry_T Enquiry[2];
+  DAC960_ErrorTable_T ErrorTable[2];
+  DAC960_EventLogEntry_T EventLogEntry;
+  DAC960_RebuildProgress_T RebuildProgress;
+  DAC960_CommandStatus_T LastRebuildStatus;
+  DAC960_LogicalDriveInformation_T
+    LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
+  DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
+  DAC960_DeviceState_T DeviceState[2][DAC960_MaxChannels][DAC960_MaxTargets];
+  DAC960_Command_T Commands[DAC960_MaxDriverQueueDepth];
+  DiskPartition_T DiskPartitions[DAC960_MinorCount];
+  int LogicalDriveUsageCount[DAC960_MaxLogicalDrives];
+  int PartitionSizes[DAC960_MinorCount];
+  int BlockSizes[DAC960_MinorCount];
+  int MaxSectorsPerRequest[DAC960_MinorCount];
+  int MaxSegmentsPerRequest[DAC960_MinorCount];
+  boolean DirectCommandActive[DAC960_MaxChannels][DAC960_MaxTargets];
+  char InitialStatusBuffer[DAC960_StatusBufferSize];
+  char CurrentStatusBuffer[DAC960_StatusBufferSize];
+  char UserStatusBuffer[DAC960_UserMessageSize];
+  char RebuildProgressBuffer[DAC960_RebuildProgressSize];
+}
+DAC960_Controller_T;
+
+
+/*
+  DAC960_AcquireControllerLock acquires exclusive access to Controller.
+*/
+
+static inline
+void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
+				  ProcessorFlags_T *ProcessorFlags)
+{
+  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  DAC960_ReleaseControllerLock releases exclusive access to Controller.
+*/
+
+static inline
+void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
+				  ProcessorFlags_T *ProcessorFlags)
+{
+  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  DAC960_AcquireControllerLockRF acquires exclusive access to Controller,
+  but is only called from the request function with the io_request_lock held.
+*/
+
+static inline
+void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+}
+
+
+/*
+  DAC960_ReleaseControllerLockRF releases exclusive access to Controller,
+  but is only called from the request function with the io_request_lock held.
+*/
+
+static inline
+void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+}
+
+
+/*
+  DAC960_AcquireControllerLockIH acquires exclusive access to Controller,
+  but is only called from the interrupt handler.
+*/
+
+static inline
+void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  DAC960_ReleaseControllerLockIH releases exclusive access to Controller,
+  but is only called from the interrupt handler.
+*/
+
+static inline
+void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
+				    ProcessorFlags_T *ProcessorFlags)
+{
+  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+}
+
+
+/*
+  Define the DAC960 V5 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V5_RegisterWindowSize		0x80
+
+typedef enum
+{
+  DAC960_V5_InboundDoorBellRegisterOffset =	0x60,
+  DAC960_V5_OutboundDoorBellRegisterOffset =	0x61,
+  DAC960_V5_InterruptMaskRegisterOffset =	0x34,
+  DAC960_V5_CommandOpcodeRegisterOffset =	0x50,
+  DAC960_V5_CommandIdentifierRegisterOffset =	0x51,
+  DAC960_V5_MailboxRegister2Offset =		0x52,
+  DAC960_V5_MailboxRegister3Offset =		0x53,
+  DAC960_V5_MailboxRegister4Offset =		0x54,
+  DAC960_V5_MailboxRegister5Offset =		0x55,
+  DAC960_V5_MailboxRegister6Offset =		0x56,
+  DAC960_V5_MailboxRegister7Offset =		0x57,
+  DAC960_V5_MailboxRegister8Offset =		0x58,
+  DAC960_V5_MailboxRegister9Offset =		0x59,
+  DAC960_V5_MailboxRegister10Offset =		0x5A,
+  DAC960_V5_MailboxRegister11Offset =		0x5B,
+  DAC960_V5_MailboxRegister12Offset =		0x5C,
+  DAC960_V5_StatusCommandIdentifierRegOffset =	0x5D,
+  DAC960_V5_StatusRegisterOffset =		0x5E
+}
+DAC960_V5_RegisterOffsets_T;
+
+
+/*
+  Define the structure of the DAC960 V5 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V5_InboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
+    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    boolean GenerateInterrupt:1;			/* Bit 2 */
+    boolean ControllerReset:1;				/* Bit 3 */
+    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    unsigned char :3;					/* Bits 5-7 */
+  } Write;
+  struct {
+    boolean HardwareMailboxEmpty:1;			/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Read;
+}
+DAC960_V5_InboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V5 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V5_OutboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
+    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
+  } Write;
+  struct {
+    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
+  } Read;
+}
+DAC960_V5_OutboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V5 Interrupt Mask Register.
+*/
+
+typedef union DAC960_V5_InterruptMaskRegister
+{
+  unsigned char All;
+  struct {
+    unsigned char :2;					/* Bits 0-1 */
+    boolean DisableInterrupts:1;			/* Bit 2 */
+    unsigned char :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V5_InterruptMaskRegister_T;
+
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 V5 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V5_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_GenerateInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_ControllerReset(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+}
+
+static inline
+void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V5_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_V5_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.DisableInterrupts = false;
+  writeb(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+}
+
+static inline
+void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.DisableInterrupts = true;
+  writeb(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+}
+
+static inline
+boolean DAC960_V5_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
+  return !InterruptMaskRegister.Bits.DisableInterrupts;
+}
+
+static inline
+void DAC960_V5_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
+				   DAC960_CommandMailbox_T *CommandMailbox)
+{
+  NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
+  NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
+  NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+}
+
+static inline
+void DAC960_V5_WriteHardwareMailbox(void *ControllerBaseAddress,
+				    DAC960_CommandMailbox_T *CommandMailbox)
+{
+  writel(CommandMailbox->Words[0],
+	 ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  writel(CommandMailbox->Words[1],
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+  writel(CommandMailbox->Words[2],
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+  writeb(CommandMailbox->Bytes[12],
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V5_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+  return readb(ControllerBaseAddress
+	       + DAC960_V5_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V5_ReadStatusRegister(void *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
+}
+
+static inline
+void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  writel(0x743C485E,
+	 ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  writel((unsigned long) Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+  writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+  writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
+	 ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
+}
+
+static inline
+void DAC960_V5_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
+					void **MemoryMailboxAddress,
+					short *NextCommandMailboxIndex,
+					short *NextStatusMailboxIndex)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  if (readl(ControllerBaseAddress
+	    + DAC960_V5_CommandOpcodeRegisterOffset) != 0x743C485E)
+    return;
+  *MemoryMailboxAddress =
+    (void *) readl(ControllerBaseAddress + DAC960_V5_MailboxRegister4Offset);
+  *NextCommandMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V5_MailboxRegister8Offset);
+  *NextStatusMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V5_MailboxRegister10Offset);
+}
+
+
+/*
+  Define the DAC960 V4 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V4_RegisterWindowSize		0x2000
+
+typedef enum
+{
+  DAC960_V4_InboundDoorBellRegisterOffset =	0x0020,
+  DAC960_V4_OutboundDoorBellRegisterOffset =	0x002C,
+  DAC960_V4_InterruptMaskRegisterOffset =	0x0034,
+  DAC960_V4_CommandOpcodeRegisterOffset =	0x1000,
+  DAC960_V4_CommandIdentifierRegisterOffset =	0x1001,
+  DAC960_V4_MailboxRegister2Offset =		0x1002,
+  DAC960_V4_MailboxRegister3Offset =		0x1003,
+  DAC960_V4_MailboxRegister4Offset =		0x1004,
+  DAC960_V4_MailboxRegister5Offset =		0x1005,
+  DAC960_V4_MailboxRegister6Offset =		0x1006,
+  DAC960_V4_MailboxRegister7Offset =		0x1007,
+  DAC960_V4_MailboxRegister8Offset =		0x1008,
+  DAC960_V4_MailboxRegister9Offset =		0x1009,
+  DAC960_V4_MailboxRegister10Offset =		0x100A,
+  DAC960_V4_MailboxRegister11Offset =		0x100B,
+  DAC960_V4_MailboxRegister12Offset =		0x100C,
+  DAC960_V4_StatusCommandIdentifierRegOffset =	0x1018,
+  DAC960_V4_StatusRegisterOffset =		0x101A
+}
+DAC960_V4_RegisterOffsets_T;
+
+
+/*
+  Define the structure of the DAC960 V4 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V4_InboundDoorBellRegister
+{
+  unsigned int All;
+  struct {
+    boolean HardwareMailboxNewCommand:1;		/* Bit 0 */
+    boolean AcknowledgeHardwareMailboxStatus:1;		/* Bit 1 */
+    boolean GenerateInterrupt:1;			/* Bit 2 */
+    boolean ControllerReset:1;				/* Bit 3 */
+    boolean MemoryMailboxNewCommand:1;			/* Bit 4 */
+    unsigned int :27;					/* Bits 5-31 */
+  } Write;
+  struct {
+    boolean HardwareMailboxFull:1;			/* Bit 0 */
+    unsigned int :31;					/* Bits 1-31 */
+  } Read;
+}
+DAC960_V4_InboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V4 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V4_OutboundDoorBellRegister
+{
+  unsigned int All;
+  struct {
+    boolean AcknowledgeHardwareMailboxInterrupt:1;	/* Bit 0 */
+    boolean AcknowledgeMemoryMailboxInterrupt:1;	/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
+  } Write;
+  struct {
+    boolean HardwareMailboxStatusAvailable:1;		/* Bit 0 */
+    boolean MemoryMailboxStatusAvailable:1;		/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
+  } Read;
+}
+DAC960_V4_OutboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V4 Interrupt Mask Register.
+*/
+
+typedef union DAC960_V4_InterruptMaskRegister
+{
+  unsigned int All;
+  struct {
+    unsigned int MessageUnitInterruptMask1:2;		/* Bits 0-1 */
+    boolean DisableInterrupts:1;			/* Bit 2 */
+    unsigned int MessageUnitInterruptMask2:5;		/* Bits 3-7 */
+    unsigned int Reserved0:24;				/* Bits 8-31 */
+  } Bits;
+}
+DAC960_V4_InterruptMaskRegister_T;
+
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 V4 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V4_HardwareMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.HardwareMailboxNewCommand = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeHardwareMailboxStatus(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeHardwareMailboxStatus = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_GenerateInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_ControllerReset(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_MemoryMailboxNewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.MemoryMailboxNewCommand = true;
+  writel(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_HardwareMailboxFullP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.HardwareMailboxFull;
+}
+
+static inline
+void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeMemoryMailboxInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V4_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeHardwareMailboxInterrupt = true;
+  OutboundDoorBellRegister.Write.AcknowledgeMemoryMailboxInterrupt = true;
+  writel(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_HardwareMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.HardwareMailboxStatusAvailable;
+}
+
+static inline
+boolean DAC960_V4_MemoryMailboxStatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.MemoryMailboxStatusAvailable;
+}
+
+static inline
+void DAC960_V4_EnableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
+  InterruptMaskRegister.Bits.DisableInterrupts = false;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
+  writel(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+}
+
+static inline
+void DAC960_V4_DisableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask1 = 0x3;
+  InterruptMaskRegister.Bits.DisableInterrupts = true;
+  InterruptMaskRegister.Bits.MessageUnitInterruptMask2 = 0x1F;
+  writel(InterruptMaskRegister.All,
+	 ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+}
+
+static inline
+boolean DAC960_V4_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InterruptMaskRegister_T InterruptMaskRegister;
+  InterruptMaskRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InterruptMaskRegisterOffset);
+  return !InterruptMaskRegister.Bits.DisableInterrupts;
+}
+
+static inline
+void DAC960_V4_WriteCommandMailbox(DAC960_CommandMailbox_T *NextCommandMailbox,
+				   DAC960_CommandMailbox_T *CommandMailbox)
+{
+  NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
+  NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
+  NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+}
+
+static inline
+void DAC960_V4_WriteHardwareMailbox(void *ControllerBaseAddress,
+				    DAC960_CommandMailbox_T *CommandMailbox)
+{
+  writel(CommandMailbox->Words[0],
+	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  writel(CommandMailbox->Words[1],
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+  writel(CommandMailbox->Words[2],
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+  writeb(CommandMailbox->Bytes[12],
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V4_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+  return readb(ControllerBaseAddress
+	       + DAC960_V4_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V4_ReadStatusRegister(void *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
+}
+
+static inline
+void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  writel(0xAABBFFFF,
+	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  writel((unsigned long) Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+  writew(Controller->NextCommandMailbox - Controller->FirstCommandMailbox,
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+  writew(Controller->NextStatusMailbox - Controller->FirstStatusMailbox,
+	 ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
+}
+
+static inline
+void DAC960_V4_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
+					void **MemoryMailboxAddress,
+					short *NextCommandMailboxIndex,
+					short *NextStatusMailboxIndex)
+{
+  void *ControllerBaseAddress = Controller->BaseAddress;
+  if (readl(ControllerBaseAddress
+	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
+    return;
+  *MemoryMailboxAddress =
+    (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
+  *NextCommandMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V4_MailboxRegister8Offset);
+  *NextStatusMailboxIndex =
+    readw(ControllerBaseAddress + DAC960_V4_MailboxRegister10Offset);
+}
+
+
+/*
+  Define the DAC960 V3 Controller Interface Register Offsets.
+*/
+
+#define DAC960_V3_RegisterWindowSize		0x80
+
+typedef enum
+{
+  DAC960_V3_CommandOpcodeRegisterOffset =	0x00,
+  DAC960_V3_CommandIdentifierRegisterOffset =	0x01,
+  DAC960_V3_MailboxRegister2Offset =		0x02,
+  DAC960_V3_MailboxRegister3Offset =		0x03,
+  DAC960_V3_MailboxRegister4Offset =		0x04,
+  DAC960_V3_MailboxRegister5Offset =		0x05,
+  DAC960_V3_MailboxRegister6Offset =		0x06,
+  DAC960_V3_MailboxRegister7Offset =		0x07,
+  DAC960_V3_MailboxRegister8Offset =		0x08,
+  DAC960_V3_MailboxRegister9Offset =		0x09,
+  DAC960_V3_MailboxRegister10Offset =		0x0A,
+  DAC960_V3_MailboxRegister11Offset =		0x0B,
+  DAC960_V3_MailboxRegister12Offset =		0x0C,
+  DAC960_V3_StatusCommandIdentifierRegOffset =	0x0D,
+  DAC960_V3_StatusRegisterOffset =		0x0E,
+  DAC960_V3_InboundDoorBellRegisterOffset =	0x40,
+  DAC960_V3_OutboundDoorBellRegisterOffset =	0x41,
+  DAC960_V3_InterruptEnableRegisterOffset =	0x43
+}
+DAC960_V3_RegisterOffsets_T;
+
+
+/*
+  Define the structure of the DAC960 V3 Inbound Door Bell Register.
+*/
+
+typedef union DAC960_V3_InboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean NewCommand:1;				/* Bit 0 */
+    boolean AcknowledgeStatus:1;			/* Bit 1 */
+    boolean GenerateInterrupt:1;			/* Bit 2 */
+    boolean ControllerReset:1;				/* Bit 3 */
+    unsigned char :4;					/* Bits 4-7 */
+  } Write;
+  struct {
+    boolean MailboxFull:1;				/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Read;
+}
+DAC960_V3_InboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V3 Outbound Door Bell Register.
+*/
+
+typedef union DAC960_V3_OutboundDoorBellRegister
+{
+  unsigned char All;
+  struct {
+    boolean AcknowledgeInterrupt:1;			/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Write;
+  struct {
+    boolean StatusAvailable:1;				/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Read;
+}
+DAC960_V3_OutboundDoorBellRegister_T;
+
+
+/*
+  Define the structure of the DAC960 V3 Interrupt Enable Register.
+*/
+
+typedef union DAC960_V3_InterruptEnableRegister
+{
+  unsigned char All;
+  struct {
+    boolean EnableInterrupts:1;				/* Bit 0 */
+    unsigned char :7;					/* Bits 1-7 */
+  } Bits;
+}
+DAC960_V3_InterruptEnableRegister_T;
+
+
+/*
+  Define inline functions to provide an abstraction for reading and writing the
+  DAC960 V3 Controller Interface Registers.
+*/
+
+static inline
+void DAC960_V3_NewCommand(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.NewCommand = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_AcknowledgeStatus(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.AcknowledgeStatus = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_GenerateInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.GenerateInterrupt = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+void DAC960_V3_ControllerReset(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All = 0;
+  InboundDoorBellRegister.Write.ControllerReset = true;
+  writeb(InboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_MailboxFullP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.MailboxFull;
+}
+
+static inline
+void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
+{
+  DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All = 0;
+  OutboundDoorBellRegister.Write.AcknowledgeInterrupt = true;
+  writeb(OutboundDoorBellRegister.All,
+	 ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_StatusAvailableP(void *ControllerBaseAddress)
+{
+  DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
+  OutboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_OutboundDoorBellRegisterOffset);
+  return OutboundDoorBellRegister.Read.StatusAvailable;
+}
+
+static inline
+void DAC960_V3_EnableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+  InterruptEnableRegister.All = 0;
+  InterruptEnableRegister.Bits.EnableInterrupts = true;
+  writeb(InterruptEnableRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+}
+
+static inline
+void DAC960_V3_DisableInterrupts(void *ControllerBaseAddress)
+{
+  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+  InterruptEnableRegister.All = 0;
+  InterruptEnableRegister.Bits.EnableInterrupts = false;
+  writeb(InterruptEnableRegister.All,
+	 ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+}
+
+static inline
+boolean DAC960_V3_InterruptsEnabledP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InterruptEnableRegister_T InterruptEnableRegister;
+  InterruptEnableRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InterruptEnableRegisterOffset);
+  return InterruptEnableRegister.Bits.EnableInterrupts;
+}
+
+static inline
+void DAC960_V3_WriteCommandMailbox(void *ControllerBaseAddress,
+				   DAC960_CommandMailbox_T *CommandMailbox)
+{
+  writel(CommandMailbox->Words[0],
+	 ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
+  writel(CommandMailbox->Words[1],
+	 ControllerBaseAddress + DAC960_V3_MailboxRegister4Offset);
+  writel(CommandMailbox->Words[2],
+	 ControllerBaseAddress + DAC960_V3_MailboxRegister8Offset);
+  writeb(CommandMailbox->Bytes[12],
+	 ControllerBaseAddress + DAC960_V3_MailboxRegister12Offset);
+}
+
+static inline DAC960_CommandIdentifier_T
+DAC960_V3_ReadStatusCommandIdentifier(void *ControllerBaseAddress)
+{
+  return readb(ControllerBaseAddress
+	       + DAC960_V3_StatusCommandIdentifierRegOffset);
+}
+
+static inline DAC960_CommandStatus_T
+DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
+{
+  return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
+}
+
+
+/*
+  Define compatibility macros between Linux 2.0 and Linux 2.1.
+*/
+
+#if LINUX_VERSION_CODE < 0x20100
+
+#define MODULE_PARM(Variable, Type)
+#define ioremap_nocache(Offset, Size)	vremap(Offset, Size)
+#define iounmap(Address)		vfree(Address)
+
+#endif
+
+
+/*
+  Define prototypes for the forward referenced DAC960 Driver Internal Functions.
+*/
+
+static void DAC960_FinalizeController(DAC960_Controller_T *);
+static int DAC960_Finalize(NotifierBlock_T *, unsigned long, void *);
+static void DAC960_RequestFunction0(void);
+static void DAC960_RequestFunction1(void);
+static void DAC960_RequestFunction2(void);
+static void DAC960_RequestFunction3(void);
+static void DAC960_RequestFunction4(void);
+static void DAC960_RequestFunction5(void);
+static void DAC960_RequestFunction6(void);
+static void DAC960_RequestFunction7(void);
+static void DAC960_InterruptHandler(int, void *, Registers_T *);
+static void DAC960_QueueMonitoringCommand(DAC960_Command_T *);
+static void DAC960_MonitoringTimerFunction(unsigned long);
+static int DAC960_Open(Inode_T *, File_T *);
+static int DAC960_Release(Inode_T *, File_T *);
+static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
+static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
+static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *);
+static void DAC960_Message(DAC960_MessageLevel_T, char *,
+			   DAC960_Controller_T *, ...);
+static void DAC960_CreateProcEntries(void);
+static void DAC960_DestroyProcEntries(void);
+
+
+/*
+  Export the Kernel Mode IOCTL interface.
+*/
+
+EXPORT_SYMBOL(DAC960_KernelIOCTL);
+
+
+#endif /* DAC960_DriverVersion */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/Makefile linux.pre11.3/drivers/block/Makefile
--- linux.vanilla/drivers/block/Makefile	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/drivers/block/Makefile	Tue Jul 20 00:28:19 1999
@@ -234,6 +234,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_BLK_CPQ_DA),y)
+L_OBJS += cpqarray.o
+else
+  ifeq ($(CONFIG_BLK_CPQ_DA),m)
+  M_OBJS += cpqarray.o
+  endif
+endif
+
+ifeq ($(CONFIG_BLK_DEV_DAC960),y)
+LX_OBJS += DAC960.o
+else
+  ifeq ($(CONFIG_BLK_DEV_DAC960),m)
+  MX_OBJS += DAC960.o
+  endif
+endif
+
 ifeq ($(CONFIG_BLK_DEV_MD),y)
 LX_OBJS += md.o
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/cpqarray.c linux.pre11.3/drivers/block/cpqarray.c
--- linux.vanilla/drivers/block/cpqarray.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/cpqarray.c	Mon Jul 19 23:55:17 1999
@@ -0,0 +1,1791 @@
+/*
+ *    Disk Array driver for Compaq SMART2 Controllers
+ *    Copyright 1998 Compaq Computer Corporation
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to arrays@compaq.com
+ *
+ *    If you want to make changes, improve or add functionality to this
+ *    driver, you'll probably need the Compaq Array Controller Interface
+ *    Specificiation (Document number ECG086/1198)
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <linux/fs.h>
+#include <linux/timer.h>
+#include <linux/proc_fs.h>
+#include <linux/hdreg.h>
+#include <asm/uaccess.h>
+#include <asm/spinlock.h>
+#include <asm/io.h>
+
+
+#define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
+
+#define DRIVER_NAME "Compaq SMART2 Driver (v 1.0.5)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(1,0,5)
+#define MAJOR_NR COMPAQ_SMART2_MAJOR
+#include <linux/blk.h>
+#include <linux/blkdev.h>
+#include <linux/genhd.h>
+
+#include "cpqarray.h"
+#include "ida_cmd.h"
+#include "smart1,2.h"
+#include "ida_ioctl.h"
+
+#define READ_AHEAD	128
+#define NR_CMDS		128 /* This could probably go as high as ~400 */
+
+#define MAX_CTLR	8
+#define CTLR_SHIFT	8
+
+static int nr_ctlr = 0;
+static ctlr_info_t *hba[MAX_CTLR] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+static int eisa[8] = { 0, 0 ,0 ,0, 0, 0 ,0 ,0 };
+
+#define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type))
+
+/*  board_id = Subsystem Device ID & Vendor ID
+ *  product = Marketing Name for the board
+ *  access = Address of the struct of function pointers 
+ */
+struct board_type products[] = {
+	{ 0x0040110E, "IDA",			&smart1_access },
+	{ 0x0140110E, "IDA-2",			&smart1_access },
+	{ 0x1040110E, "IAES",			&smart1_access },
+	{ 0x2040110E, "SMART",			&smart1_access },
+	{ 0x3040110E, "SMART-2/E",		&smart2e_access },
+	{ 0x40300E11, "SMART-2/P",		&smart2_access },
+	{ 0x40310E11, "SMART-2SL",		&smart2_access },
+	{ 0x40320E11, "Smart Array 3200",	&smart2_access },
+	{ 0x40330E11, "Smart Array 3100ES",	&smart2_access },
+	{ 0x40340E11, "Smart Array 221",	&smart2_access },
+	{ 0x40400E11, "Integrated Array",	&smart4_access },
+	{ 0x40500E11, "Smart Array 4200",	&smart4_access },
+	{ 0x40510E11, "Smart Array 4250ES",	&smart4_access },
+};
+
+static struct hd_struct * ida;
+static int * ida_sizes;
+static int * ida_blocksizes;
+static int * ida_hardsizes;
+static struct gendisk ida_gendisk[MAX_CTLR];
+
+struct proc_dir_entry *proc_array = NULL;
+
+/* Debug... */
+#define DBG(s)	do { s } while(0)
+/* Debug (general info)... */
+#define DBGINFO(s) do { } while(0)
+/* Debug Paranoid... */
+#define DBGP(s)  do { } while(0)
+/* Debug Extra Paranoid... */
+#define DBGPX(s) do { } while(0)
+
+int cpqarray_init(void);
+static int cpqarray_pci_detect(void);
+static int cpqarray_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn);
+static ulong remap_pci_mem(ulong base, ulong size);
+static int cpqarray_eisa_detect(void);
+static int pollcomplete(int ctlr);
+static void getgeometry(int ctlr);
+static void start_fwbk(int ctlr);
+
+static cmdlist_t * cmd_alloc(ctlr_info_t *h);
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c);
+
+static int sendcmd(
+	__u8	cmd,
+	int	ctlr,
+	void	*buff,
+	size_t	size,
+	unsigned int blk,
+	unsigned int blkcnt,
+	unsigned int log_unit );
+
+static int ida_open(struct inode *inode, struct file *filep);
+static int ida_release(struct inode *inode, struct file *filep);
+static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);
+static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io);
+
+static void do_ida_request(int i);
+/*
+ * This is a hack.  This driver eats a major number for each controller, and
+ * sets blkdev[xxx].request_fn to each one of these so the real request
+ * function knows what controller its working with.
+ */
+#define DO_IDA_REQUEST(x) { do_ida_request(x); }
+
+static void do_ida_request0(void) DO_IDA_REQUEST(0);
+static void do_ida_request1(void) DO_IDA_REQUEST(1);
+static void do_ida_request2(void) DO_IDA_REQUEST(2);
+static void do_ida_request3(void) DO_IDA_REQUEST(3);
+static void do_ida_request4(void) DO_IDA_REQUEST(4);
+static void do_ida_request5(void) DO_IDA_REQUEST(5);
+static void do_ida_request6(void) DO_IDA_REQUEST(6);
+static void do_ida_request7(void) DO_IDA_REQUEST(7);
+
+static void start_io(ctlr_info_t *h);
+
+static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
+static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
+static inline void complete_buffers(struct buffer_head *bh, int ok);
+static inline void complete_command(cmdlist_t *cmd, int timeout);
+
+static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
+static void ida_timer(unsigned long tdata);
+static int frevalidate_logvol(kdev_t dev);
+static int revalidate_logvol(kdev_t dev, int maxusage);
+static int revalidate_allvol(kdev_t dev);
+
+static void ida_procinit(int i);
+static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+
+static void ida_geninit(struct gendisk *g)
+{
+	int ctlr = g-ida_gendisk;
+	int i,j;
+	drv_info_t *drv;
+
+	for(i=0; i<NWD; i++) {
+		drv = &hba[ctlr]->drv[i];
+		if (!drv->nr_blks)
+			continue;
+		ida[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)].nr_sects =
+		ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)] =
+				drv->nr_blks;
+
+		for(j=0; j<16; j++) {
+			ida_blocksizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)+j] =
+				1024;
+			ida_hardsizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)+j] =
+				drv->blk_size;
+		}
+		ida_gendisk[ctlr].nr_real++;
+	}
+
+}
+
+struct file_operations ida_fops  = {
+	NULL,                        /* lseek - default */
+	block_read,                  /* read - general block-dev read */
+	block_write,                 /* write - general block-dev write */
+	NULL,                        /* readdir - bad */
+	NULL,                        /* select */
+	ida_ioctl,                  /* ioctl */
+	NULL,                        /* mmap */
+	ida_open,                     /* open code */
+	NULL,
+	ida_release,                  /* release */
+	block_fsync,	              /* fsync */
+	NULL,                        /* fasync */
+	NULL,			/* Disk change */
+	frevalidate_logvol,	/* revalidate */
+};
+
+
+/*
+ * Get us a file in /proc/array that says something about each controller.
+ * Create /proc/array if it doesn't exist yet.
+ */
+static void ida_procinit(int i)
+{
+	struct proc_dir_entry *pd;
+
+	if (proc_array == NULL) {
+		proc_array = create_proc_entry("array", S_IFDIR|S_IRUGO|S_IXUGO,
+								&proc_root);
+		if (!proc_array) return;
+	}
+
+	pd = create_proc_entry(hba[i]->devname, S_IFREG|S_IRUGO, proc_array);
+	if (!pd) return;
+	pd->read_proc = ida_proc_get_info;
+	pd->data = hba[i];
+}
+
+/*
+ * Report information about this controller.
+ */
+static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+	off_t pos = 0;
+	off_t len = 0;
+	int size, i, ctlr;
+	ctlr_info_t *h = (ctlr_info_t*)data;
+	drv_info_t *drv;
+#ifdef CPQ_PROC_PRINT_QUEUES
+	cmdlist_t *c;
+#endif
+
+	ctlr = h->ctlr;
+	size = sprintf(buffer, "%s:  Compaq %s Controller\n"
+		"       Board ID: %08lx\n"
+		"       Firmware Revision: %c%c%c%c\n"
+		"       Controller Sig: %08lx\n"
+		"       Memory Address: %08lx\n"
+		"       I/O Port: %04x\n"
+		"       IRQ: %x\n"
+		"       Logical drives: %d\n"
+		"       Physical drives: %d\n\n"
+		"       Current Q depth: %d\n"
+		"       Max Q depth since init: %d\n\n",
+		h->devname, 
+		h->product_name,
+		(unsigned long)h->board_id,
+		h->firm_rev[0], h->firm_rev[1], h->firm_rev[2], h->firm_rev[3],
+		(unsigned long)h->ctlr_sig, (unsigned long)h->vaddr,
+		(unsigned int) h->ioaddr, (unsigned int)h->intr,
+		h->log_drives, h->phys_drives,
+		h->Qdepth, h->maxQsinceinit);
+
+	pos += size; len += size;
+	
+	size = sprintf(buffer+len, "Logical Drive Info:\n");
+	pos += size; len += size;
+
+	for(i=0; i<h->log_drives; i++) {
+		drv = &h->drv[i];
+		size = sprintf(buffer+len, "ida/c%dd%d: blksz=%d nr_blks=%d\n",
+				ctlr, i, drv->blk_size, drv->nr_blks);
+		pos += size; len += size;
+	}
+
+#ifdef CPQ_PROC_PRINT_QUEUES
+	size = sprintf(buffer+len, "\nCurrent Queues:\n");
+	pos += size; len += size;
+
+	c = h->reqQ;
+	size = sprintf(buffer+len, "reqQ = %p", c); pos += size; len += size;
+	if (c) c=c->next;
+	while(c && c != h->reqQ) {
+		size = sprintf(buffer+len, "->%p", c);
+		pos += size; len += size;
+		c=c->next;
+	}
+
+	c = h->cmpQ;
+	size = sprintf(buffer+len, "\ncmpQ = %p", c); pos += size; len += size;
+	if (c) c=c->next;
+	while(c && c != h->cmpQ) {
+		size = sprintf(buffer+len, "->%p", c);
+		pos += size; len += size;
+		c=c->next;
+	}
+
+	size = sprintf(buffer+len, "\n"); pos += size; len += size;
+#endif
+	size = sprintf(buffer+len, "nr_allocs = %d\nnr_frees = %d\n",
+			h->nr_allocs, h->nr_frees);
+	pos += size; len += size;
+
+	*eof = 1;
+	*start = buffer+offset;
+	len -= offset;
+	if (len>length)
+		len = length;
+	return len;
+}
+
+#ifdef MODULE
+
+MODULE_PARM(eisa, "1-8i");
+EXPORT_NO_SYMBOLS;
+
+/* This is a bit of a hack... */
+int init_module(void)
+{
+	int i, j;
+	if (cpqarray_init() == 0) /* all the block dev numbers already used */
+		return -EIO;	  /* or no controllers were found */
+
+	for(i=0; i<nr_ctlr; i++) {
+		ida_geninit(&ida_gendisk[i]); 
+		for(j=0; j<NWD; j++)	
+			if (ida_sizes[(i<<CTLR_SHIFT) + (j<<NWD_SHIFT)])
+				resetup_one_dev(&ida_gendisk[i], j);
+	}
+	return 0;
+}
+void cleanup_module(void)
+{
+	int i;
+	struct gendisk *g;
+
+	for(i=0; i<nr_ctlr; i++) {
+		hba[i]->access.set_intr_mask(hba[i], 0);
+		free_irq(hba[i]->intr, hba[i]);
+		iounmap((void*)hba[i]->vaddr);
+		unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+		del_timer(&hba[i]->timer);
+		remove_proc_entry(hba[i]->devname, proc_array);
+		kfree(hba[i]->cmd_pool);
+		kfree(hba[i]->cmd_pool_bits);
+
+		if (gendisk_head == &ida_gendisk[i]) {
+			gendisk_head = ida_gendisk[i].next;
+		} else {
+			for(g=gendisk_head; g; g=g->next) {
+				if (g->next == &ida_gendisk[i]) {
+					g->next = ida_gendisk[i].next;
+					break;
+				}
+			}
+		}
+	}
+	remove_proc_entry("array", &proc_root);
+	kfree(ida);
+	kfree(ida_sizes);
+	kfree(ida_hardsizes);
+	kfree(ida_blocksizes);
+
+
+}
+#endif /* MODULE */
+
+/*
+ *  This is it.  Find all the controllers and register them.  I really hate
+ *  stealing all these major device numbers.
+ *  returns the number of block devices registered.
+ */
+int cpqarray_init(void)
+{
+	void (*request_fns[MAX_CTLR])(void) = {
+		do_ida_request0, do_ida_request1,
+		do_ida_request2, do_ida_request3,
+		do_ida_request4, do_ida_request5,
+		do_ida_request6, do_ida_request7,
+	};
+	int i;
+	int num_cntlrs_reg = 0;
+
+	/* detect controllers */
+	cpqarray_pci_detect();
+	cpqarray_eisa_detect();
+	
+	if (nr_ctlr == 0)
+		return(num_cntlrs_reg);
+
+	printk(DRIVER_NAME "\n");
+	printk("Found %d controller(s)\n", nr_ctlr);
+
+	/* allocate space for disk structs */
+	ida = kmalloc(sizeof(struct hd_struct)*nr_ctlr*NWD*16, GFP_KERNEL);
+	
+	if(ida==NULL)
+	{
+		printk( KERN_ERR "cpqarray: out of memory");
+		return(num_cntlrs_reg);
+	}
+	ida_sizes =      kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
+	if(ida_sizes==NULL)
+	{
+		kfree(ida); 
+                printk( KERN_ERR "cpqarray: out of memory");
+                return(num_cntlrs_reg);
+        }
+
+	ida_blocksizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
+	if(ida_blocksizes==NULL)
+	{
+		kfree(ida);
+		kfree(ida_sizes); 
+                printk( KERN_ERR "cpqarray: out of memory");
+                return(num_cntlrs_reg);
+        }
+
+	ida_hardsizes =  kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
+	if(ida_hardsizes==NULL)
+	{
+		kfree(ida);
+                kfree(ida_sizes); 
+		kfree(ida_blocksizes);
+                printk( KERN_ERR "cpqarray: out of memory");
+                return(num_cntlrs_reg);
+        }
+
+	memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16);
+	memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16);
+	memset(ida_blocksizes, 0, sizeof(int)*nr_ctlr*NWD*16);
+	memset(ida_hardsizes, 0, sizeof(int)*nr_ctlr*NWD*16);
+	memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR);
+
+	/* 
+	 * register block devices
+	 * Find disks and fill in structs
+	 * Get an interrupt, set the Q depth and get into /proc
+	 */
+	for(i=0; i< nr_ctlr; i++) {
+	  	/* If this successful it should insure that we are the only */
+		/* instance of the driver */	
+		if (register_blkdev(MAJOR_NR+i, hba[i]->devname, &ida_fops)) {
+                        printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n",
+                                MAJOR_NR+i);
+                        continue;
+                }
+
+		hba[i]->access.set_intr_mask(hba[i], 0);
+		if (request_irq(hba[i]->intr, do_ida_intr,
+			SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) {
+
+			printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n", 
+				hba[i]->intr, hba[i]->devname);
+			unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+			continue;
+		}
+		num_cntlrs_reg++;
+		hba[i]->cmd_pool = (cmdlist_t *)kmalloc(
+				NR_CMDS * sizeof(cmdlist_t), GFP_KERNEL);
+		hba[i]->cmd_pool_bits = (__u32*)kmalloc(
+				((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);
+		
+		if(hba[i]->cmd_pool_bits == NULL || hba[i]->cmd_pool == NULL)
+		{
+			nr_ctlr = i; 
+			if(hba[i]->cmd_pool_bits)
+				kfree(hba[i]->cmd_pool_bits);
+			if(hba[i]->cmd_pool)
+				kfree(hba[i]->cmd_pool);
+			free_irq(hba[i]->intr, hba[i]);
+			unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
+			num_cntlrs_reg--;
+                	printk( KERN_ERR "cpqarray: out of memory");
+
+			/* If num_cntlrs_reg == 0, no controllers worked. 
+			 *	init_module will fail, so clean up global 
+			 *	memory that clean_module would do.
+			*/	
+			if (num_cntlrs_reg == 0) 
+			{
+				kfree(ida);
+				kfree(ida_sizes);
+				kfree(ida_hardsizes);
+				kfree(ida_blocksizes);
+			}
+                	return(num_cntlrs_reg);
+	
+		}
+		memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));
+		memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));
+		printk(KERN_INFO "cpqarray: Finding drives on %s", 
+			hba[i]->devname);
+		getgeometry(i);
+		start_fwbk(i); 
+
+		hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
+
+		ida_procinit(i);
+		ida_gendisk[i].major = MAJOR_NR + i;
+		ida_gendisk[i].major_name = "ida";
+		ida_gendisk[i].minor_shift = NWD_SHIFT;
+		ida_gendisk[i].max_p = 16;
+		ida_gendisk[i].max_nr = 16;
+		ida_gendisk[i].init = ida_geninit;
+		ida_gendisk[i].part = ida + (i*256);
+		ida_gendisk[i].sizes = ida_sizes + (i*256);
+		/* ida_gendisk[i].nr_real is handled by getgeometry */
+	
+		blk_dev[MAJOR_NR+i].request_fn = request_fns[i];
+		blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
+		hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
+		read_ahead[MAJOR_NR+i] = READ_AHEAD;
+
+		/* Get on the disk list */
+		ida_gendisk[i].next = gendisk_head;
+		gendisk_head = &ida_gendisk[i];
+
+		init_timer(&hba[i]->timer);
+		hba[i]->timer.expires = jiffies + IDA_TIMER;
+		hba[i]->timer.data = (unsigned long)hba[i];
+		hba[i]->timer.function = ida_timer;
+		add_timer(&hba[i]->timer);
+
+	}
+	/* done ! */
+	return(num_cntlrs_reg);
+}
+
+/*
+ * Find the controller and initialize it
+ *  Cannot use the class code to search, because older array controllers use
+ *    0x018000 and new ones use 0x010400.  So I might as well search for each
+ *    each device IDs, being there are only going to be three of them. 
+ */
+static int cpqarray_pci_detect(void)
+{
+	int index;
+	unchar bus=0, dev_fn=0;
+
+#define IDA_BOARD_TYPES 3
+	static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC, 
+		PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ };
+	static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX,
+		PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P };
+	int brdtype;
+	
+	/* search for all PCI board types that could be for this driver */
+	for(brdtype=0; brdtype<IDA_BOARD_TYPES; brdtype++)
+	{
+		for(index=0; ; index++) {
+			if (pcibios_find_device(ida_vendor_id[brdtype],
+			 	ida_device_id[brdtype], index, &bus, &dev_fn))
+				break;
+			printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",
+				ida_vendor_id[brdtype], bus, dev_fn);
+			if (index == 1000000) break;
+			if (nr_ctlr == 8) {
+				printk(KERN_WARNING "cpqarray: This driver"
+				" supports a maximum of 8 controllers.\n");
+				break;
+			}
+
+			/* if it is a PCI_DEVICE_ID_NCR_53C1510, make sure it's 
+				the Compaq version of the chip */ 
+
+			if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510)
+			{	
+				unsigned short subvendor=0;
+				if(pcibios_read_config_word(bus, dev_fn, 
+                        		PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
+                		{
+                        		printk(KERN_DEBUG "cpqarray: failed to read subvendor\n");
+                        		continue;
+                		}
+				if(subvendor !=  PCI_VENDOR_ID_COMPAQ)
+				{
+					printk(KERN_DEBUG 
+						"cpqarray: not a Compaq integrated array controller\n");
+					continue;
+				}
+			}
+			hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+			if(hba[nr_ctlr]==NULL)
+			{
+				printk(KERN_ERR "cpqarray: out of memory.\n");
+				continue;
+			}
+			memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
+			if (cpqarray_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)
+			{
+				kfree(hba[nr_ctlr]);
+				continue;
+			}
+			sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
+			hba[nr_ctlr]->ctlr = nr_ctlr;
+			nr_ctlr++;
+
+		}
+	}
+
+	return nr_ctlr;
+}
+/*
+ * Find the IO address of the controller, its IRQ and so forth.  Fill
+ * in some basic stuff into the ctlr_info_t structure.
+ */
+static int cpqarray_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
+{
+	ushort vendor_id, device_id, command;
+	unchar cache_line_size, latency_timer;
+	unchar irq, revision;
+	uint addr[6];
+	__u32 board_id;
+	struct pci_dev *pdev;
+
+	int i;
+
+	pdev = pci_find_slot(bus, device_fn);
+	vendor_id = pdev->vendor;
+	device_id = pdev->device;
+	irq = pdev->irq;
+
+	for(i=0; i<6; i++)
+		addr[i] = pdev->base_address[i];
+
+	(void) pcibios_read_config_word(bus, device_fn,
+					PCI_COMMAND,&command);
+	(void) pcibios_read_config_byte(bus, device_fn,
+					PCI_CLASS_REVISION,&revision);
+	(void) pcibios_read_config_byte(bus, device_fn,
+					PCI_CACHE_LINE_SIZE, &cache_line_size);
+	(void) pcibios_read_config_byte(bus, device_fn,
+					PCI_LATENCY_TIMER, &latency_timer);
+
+	(void) pcibios_read_config_dword(bus, device_fn, 0x2c, &board_id);
+
+DBGINFO(
+	printk("vendor_id = %x\n", vendor_id);
+	printk("device_id = %x\n", device_id);
+	printk("command = %x\n", command);
+	for(i=0; i<6; i++)
+		printk("addr[%d] = %x\n", i, addr[i]);
+	printk("revision = %x\n", revision);
+	printk("irq = %x\n", irq);
+	printk("cache_line_size = %x\n", cache_line_size);
+	printk("latency_timer = %x\n", latency_timer);
+	printk("board_id = %x\n", board_id);
+);
+
+	c->intr = irq;
+	c->ioaddr = addr[0] & ~0x1;
+
+	/*
+	 * Memory base addr is first addr with the first bit _not_ set
+	 */
+	for(i=0; i<6; i++)
+		if (!(addr[i] & 0x1)) {
+			c->paddr = addr[i];
+			break;
+		}
+	c->vaddr = remap_pci_mem(c->paddr, 128);
+	c->board_id = board_id;
+
+	for(i=0; i<NR_PRODUCTS; i++) {
+		if (board_id == products[i].board_id) {
+			c->product_name = products[i].product_name;
+			c->access = *(products[i].access);
+			break;
+		}
+	}
+	if (i == NR_PRODUCTS) {
+		printk(KERN_WARNING "cpqarray: Sorry, I don't know how"
+			" to access the SMART Array controller %08lx\n", 
+				(unsigned long)board_id);
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Map (physical) PCI mem into (virtual) kernel space
+ */
+static ulong remap_pci_mem(ulong base, ulong size)
+{
+        ulong page_base        = ((ulong) base) & PAGE_MASK;
+        ulong page_offs        = ((ulong) base) - page_base;
+        ulong page_remapped    = (ulong) ioremap(page_base, page_offs+size);
+
+        return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
+}
+
+/*
+ * Copy the contents of the ints[] array passed to us by init.
+ */
+void cpqarray_setup(char *str, int *ints)
+{
+	int i;
+	for(i=0; i<ints[0] && i<8; i++)
+		eisa[i] = ints[i+1];
+}
+
+/*
+ * Find an EISA controller's signature.  Set up an hba if we find it.
+ */
+static int cpqarray_eisa_detect(void)
+{
+	int i=0, j;
+	__u32 board_id;
+	int intr;
+
+	while(i<8 && eisa[i]) {
+		if (nr_ctlr == 8) {
+			printk(KERN_WARNING "cpqarray: This driver supports"
+				" a maximum of 8 controllers.\n");
+			break;
+		}
+		board_id = inl(eisa[i]+0xC80);
+		for(j=0; j < NR_PRODUCTS; j++)
+			if (board_id == products[j].board_id) 
+				break;
+
+		if (j == NR_PRODUCTS) {
+			printk(KERN_WARNING "cpqarray: Sorry, I don't know how"
+				" to access the SMART Array controller %08lx\n",
+				 (unsigned long)board_id);
+			continue;
+		}
+		hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);
+		if(hba[nr_ctlr]==NULL)
+		{
+			printk(KERN_ERR "cpqarray: out of memory.\n");
+			continue;
+		}
+		memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));
+		hba[nr_ctlr]->ioaddr = eisa[i];
+
+		/*
+		 * Read the config register to find our interrupt
+		 */
+		intr = inb(eisa[i]+0xCC0) >> 4;
+		if (intr & 1) intr = 11;
+		else if (intr & 2) intr = 10;
+		else if (intr & 4) intr = 14;
+		else if (intr & 8) intr = 15;
+		
+		hba[nr_ctlr]->intr = intr;
+		sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);
+		hba[nr_ctlr]->product_name = products[j].product_name;
+		hba[nr_ctlr]->access = *(products[j].access);
+		hba[nr_ctlr]->ctlr = nr_ctlr;
+		hba[nr_ctlr]->board_id = board_id;
+
+DBGINFO(
+	printk("i = %d, j = %d\n", i, j);
+	printk("irq = %x\n", intr);
+	printk("product name = %s\n", products[j].product_name);
+	printk("board_id = %x\n", board_id);
+);
+
+		nr_ctlr++;
+		i++;
+	}
+
+	return nr_ctlr;
+}
+
+
+/*
+ * Open.  Make sure the device is really there.
+ */
+static int ida_open(struct inode *inode, struct file *filep)
+{
+	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
+	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+
+	DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
+	if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
+		return -ENXIO;
+
+	if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) +
+						MINOR(inode->i_rdev)] == 0)
+		return -ENXIO;
+
+	/*
+	 * Root is allowed to open raw volume zero even if its not configured
+	 * so array config can still work.  I don't think I really like this,
+	 * but I'm already using way to many device nodes to claim another one
+	 * for "raw controller".
+	 */
+	if (suser()
+		&& ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0 
+		&& MINOR(inode->i_rdev) != 0)
+		return -ENXIO;
+
+	hba[ctlr]->drv[dsk].usage_count++;
+	hba[ctlr]->usage_count++;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+/*
+ * Close.  Sync first.
+ */
+static int ida_release(struct inode *inode, struct file *filep)
+{
+	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
+	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+
+	DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );
+	fsync_dev(inode->i_rdev);
+
+	hba[ctlr]->drv[dsk].usage_count--;
+	hba[ctlr]->usage_count--;
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*
+ * Enqueuing and dequeuing functions for cmdlists.
+ */
+static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c)
+{
+	if (*Qptr == NULL) {
+		*Qptr = c;
+		c->next = c->prev = c;
+	} else {
+		c->prev = (*Qptr)->prev;
+		c->next = (*Qptr);
+		(*Qptr)->prev->next = c;
+		(*Qptr)->prev = c;
+	}
+}
+
+static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c)
+{
+	if (c && c->next != c) {
+		if (*Qptr == c) *Qptr = c->next;
+		c->prev->next = c->next;
+		c->next->prev = c->prev;
+	} else {
+		*Qptr = NULL;
+	}
+	return c;
+}
+
+/*
+ * Get a request and submit it to the controller.
+ * This routine needs to grab all the requests it possibly can from the
+ * req Q and submit them.  Interrupts are off (and need to be off) when you
+ * are in here (either via the dummy do_ida_request functions or by being
+ * called from the interrupt handler
+ */
+static void do_ida_request(int ctlr)
+{
+	ctlr_info_t *h = hba[ctlr];
+	cmdlist_t *c;
+	int seg, sect;
+	char *lastdataend;
+	struct buffer_head *bh;
+	struct request *creq;
+
+	creq = blk_dev[MAJOR_NR+ctlr].current_request;
+	if (creq == NULL || creq->rq_status == RQ_INACTIVE)
+	{
+		start_io(h);
+		return;
+	}
+
+	if (ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ||
+		ctlr > nr_ctlr || h == NULL) {
+		printk("cpqarray: doreq cmd for %d, %x at %p\n",
+				ctlr, creq->rq_dev, creq);
+		complete_buffers(creq->bh, 0);
+	 	start_io(h);	
+		return;
+	}
+
+	if ((c = cmd_alloc(h)) == NULL)
+	{
+		start_io(h);
+		return;
+	}
+
+	bh = creq->bh;
+
+	c->ctlr = ctlr;
+	c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
+	c->hdr.size = sizeof(rblk_t) >> 2;
+	c->size += sizeof(rblk_t);
+
+	c->req.hdr.blk = ida[(ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
+	c->bh = bh;
+DBGPX(
+	if (bh == NULL)
+		panic("bh == NULL?");
+	
+	printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
+);
+	seg = 0; lastdataend = NULL;
+	sect = 0;
+	while(bh) {
+		sect += bh->b_size/512;
+DBGPX(
+		if (bh->b_size % 512) {
+			printk("Oh damn.  %d+%d, size = %d\n", creq->sector, sect, bh->b_size);
+			panic("b_size %% 512 != 0");
+		}
+);
+		if (bh->b_data == lastdataend) {
+			c->req.sg[seg-1].size += bh->b_size;
+			lastdataend += bh->b_size;
+		} else {
+			c->req.sg[seg].size = bh->b_size;
+			c->req.sg[seg].addr = (__u32)virt_to_bus(bh->b_data);
+			lastdataend = bh->b_data + bh->b_size;
+			if (++seg == SG_MAX)
+				break;
+		}
+		bh = bh->b_reqnext;
+	}
+DBGPX(	printk("Submitting %d sectors in %d segments\n", sect, seg); );
+	c->req.hdr.sg_cnt = seg;
+	c->req.hdr.blk_cnt = sect;
+
+	creq->sector += sect;
+	creq->nr_sectors -= sect;
+
+	/* Ready the next request:
+	 * Fix up creq if we still have more buffers in the buffer chain, or
+	 * mark this request as done and ready the next one.
+         */
+	if (creq->nr_sectors) {
+DBGPX(
+		if (bh==NULL) {
+			printk("sector=%d, nr_sectors=%d, sect=%d, seg=%d\n",
+				creq->sector, creq->nr_sectors, sect, seg);
+			panic("mother...");
+		}
+);
+		creq->bh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+DBGPX(		printk("More to do on same request %p\n", creq); );
+	} else {
+DBGPX(		printk("Done with %p, queueing %p\n", creq, creq->next); );
+		creq->rq_status = RQ_INACTIVE;
+		blk_dev[MAJOR_NR+ctlr].current_request = creq->next;
+		wake_up(&wait_for_request);
+	}
+
+	c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE;
+	c->type = CMD_RWREQ;
+
+	/* Put the request on the tail of the request queue */
+	addQ(&h->reqQ, c);
+	h->Qdepth++;
+	if (h->Qdepth > h->maxQsinceinit) 
+		h->maxQsinceinit = h->Qdepth;
+
+	start_io(h);
+}
+
+/* 
+ * start_io submits everything on a controller's request queue
+ * and moves it to the completion queue.
+ *
+ * Interrupts had better be off if you're in here
+ */
+static void start_io(ctlr_info_t *h)
+{
+	cmdlist_t *c;
+
+	while((c = h->reqQ) != NULL) {
+		/* Can't do anything if we're busy */
+		if (h->access.fifo_full(h) == 0)
+			return;
+
+		/* Get the first entry from the request Q */
+		removeQ(&h->reqQ, c);
+		h->Qdepth--;
+	
+		/* Tell the controller to do our bidding */
+		h->access.submit_command(h, c);
+
+		/* Get onto the completion Q */
+		addQ(&h->cmpQ, c);
+	}
+}
+
+static inline void complete_buffers(struct buffer_head *bh, int ok)
+{
+	struct buffer_head *xbh;
+	while(bh) {
+		xbh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+		
+		bh->b_end_io(bh, ok);
+
+		bh = xbh;
+	}
+}
+/*
+ * Mark all buffers that cmd was responsible for
+ */
+static inline void complete_command(cmdlist_t *cmd, int timeout)
+{
+	char buf[80];
+	int ok=1;
+
+	if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
+	   (hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
+		sprintf(buf, "Non Fatal error on ida/c%dd%d\n",
+				cmd->ctlr, cmd->hdr.unit);
+		console_print(buf);
+		hba[cmd->ctlr]->misc_tflags |= MISC_NONFATAL_WARN;
+	}
+	if (cmd->req.hdr.rcode & RCODE_FATAL) {
+		sprintf(buf, "Fatal error on ida/c%dd%d\n",
+				cmd->ctlr, cmd->hdr.unit);
+		console_print(buf);
+		ok = 0;
+	}
+	if (cmd->req.hdr.rcode & RCODE_INVREQ) {
+				sprintf(buf, "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
+				cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
+				cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
+				cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
+		console_print(buf);
+		ok = 0;	
+	}
+	if (timeout) ok = 0;
+	complete_buffers(cmd->bh, ok);
+}
+
+/*
+ *  The controller will interrupt us upon completion of commands.
+ *  Find the command on the completion queue, remove it, tell the OS and
+ *  try to queue up more IO
+ */
+static void do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ctlr_info_t *h = dev_id;
+	cmdlist_t *c;
+	unsigned long istat;
+	unsigned long flags;
+	__u32 a,a1;
+
+
+	istat = h->access.intr_pending(h);
+	/* Is this interrupt for us? */
+	if (istat == 0)
+		return;
+
+	/*
+	 * If there are completed commands in the completion queue,
+	 * we had better do something about it.
+	 */
+	spin_lock_irqsave(&io_request_lock, flags);
+	if (istat & FIFO_NOT_EMPTY) {
+		while((a = h->access.command_completed(h))) {
+			a1 = a; a &= ~3;
+			if ((c = h->cmpQ) == NULL)
+			{  
+				printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1);
+				continue;	
+			} 
+			while(c->busaddr != a) {
+				c = c->next;
+				if (c == h->cmpQ) 
+					break;
+			}
+			/*
+			 * If we've found the command, take it off the
+			 * completion Q and free it
+			 */
+			if (c->busaddr == a) {
+				removeQ(&h->cmpQ, c);
+				if (c->type == CMD_RWREQ) {
+					complete_command(c, 0);
+					cmd_free(h, c);
+				} else if (c->type == CMD_IOCTL_PEND) {
+					c->type = CMD_IOCTL_DONE;
+				}
+				continue;
+			}
+		}
+	}
+
+	/*
+	 * See if we can queue up some more IO
+	 */
+	do_ida_request(h->ctlr);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
+/*
+ * This timer was for timing out requests that haven't happened after
+ * IDA_TIMEOUT.  That wasn't such a good idea.  This timer is used to
+ * reset a flags structure so we don't flood the user with
+ * "Non-Fatal error" messages.
+ */
+static void ida_timer(unsigned long tdata)
+{
+	ctlr_info_t *h = (ctlr_info_t*)tdata;
+
+	h->timer.expires = jiffies + IDA_TIMER;
+	add_timer(&h->timer);
+	h->misc_tflags = 0;
+}
+
+/*
+ *  ida_ioctl does some miscellaneous stuff like reporting drive geometry,
+ *  setting readahead and submitting commands from userspace to the controller.
+ */
+static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
+{
+	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
+	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
+	int error;
+	int diskinfo[4];
+	struct hd_geometry *geo = (struct hd_geometry *)arg;
+	ida_ioctl_t *io = (ida_ioctl_t*)arg;
+	ida_ioctl_t my_io;
+
+	switch(cmd) {
+	case HDIO_GETGEO:
+		if (hba[ctlr]->drv[dsk].cylinders) {
+			diskinfo[0] = hba[ctlr]->drv[dsk].heads;
+			diskinfo[1] = hba[ctlr]->drv[dsk].sectors;
+			diskinfo[2] = hba[ctlr]->drv[dsk].cylinders;
+		} else {
+			diskinfo[0] = 0xff;
+			diskinfo[1] = 0x3f;
+			diskinfo[2] = hba[ctlr]->drv[dsk].nr_blks / (0xff*0x3f);
+		}
+		put_user(diskinfo[0], &geo->heads);
+		put_user(diskinfo[1], &geo->sectors);
+		put_user(diskinfo[2], &geo->cylinders);
+		put_user(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].start_sect, &geo->start);
+		return 0;
+	case IDAGETDRVINFO:
+		return copy_to_user(&io->c.drv,&hba[ctlr]->drv[dsk],sizeof(drv_info_t));
+	case BLKGETSIZE:
+		if (!arg) return -EINVAL;
+		put_user(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].nr_sects, (long*)arg);
+		return 0;
+	case BLKRASET:
+		if (!suser()) return -EACCES;
+		if (!(inode->i_rdev)) return -EINVAL;
+		if (arg>0xff) return -EINVAL;
+		read_ahead[MAJOR(inode->i_rdev)] = arg;
+		return 0;
+	case BLKRAGET:
+		if (!arg) return -EINVAL;
+		put_user(read_ahead[MAJOR(inode->i_rdev)], (int*)arg);
+		return 0;
+	case BLKRRPART:
+		return revalidate_logvol(inode->i_rdev, 1);
+	case IDAPASSTHRU:
+		if (!suser()) return -EPERM;
+		error = copy_from_user(&my_io, io, sizeof(my_io));
+		if (error) return error;
+		error = ida_ctlr_ioctl(ctlr, dsk, &my_io);
+		if (error) return error;
+		error = copy_to_user(io, &my_io, sizeof(my_io));
+		return error;
+	case IDAGETCTLRSIG:
+		if (!arg) return -EINVAL;
+		put_user(hba[ctlr]->ctlr_sig, (int*)arg);
+		return 0;
+	case IDAREVALIDATEVOLS:
+		return revalidate_allvol(inode->i_rdev);
+	case IDADRIVERVERSION:
+		if (!arg) return -EINVAL;
+		put_user(DRIVER_VERSION, (unsigned long*)arg);
+		return 0;
+
+	RO_IOCTLS(inode->i_rdev, arg);
+
+	default:
+		return -EBADRQC;
+	}
+		
+}
+/*
+ * ida_ctlr_ioctl is for passing commands to the controller from userspace.
+ * The command block (io) has already been copied to kernel space for us,
+ * however, any elements in the sglist need to be copied to kernel space
+ * or copied back to userspace.
+ *
+ * Only root may perform a controller passthru command, however I'm not doing
+ * any serious sanity checking on the arguments.  Doing an IDA_WRITE_MEDIA and
+ * putting a 64M buffer in the sglist is probably a *bad* idea.
+ */
+static int ida_ctlr_ioctl(int ctlr, int dsk, ida_ioctl_t *io)
+{
+	ctlr_info_t *h = hba[ctlr];
+	cmdlist_t *c;
+	void *p = NULL;
+	unsigned long flags;
+	int error;
+
+	if ((c = cmd_alloc(NULL)) == NULL)
+		return -ENOMEM;
+	c->ctlr = ctlr;
+	c->hdr.unit = (io->unit & UNITVALID) ? (io->unit & ~UNITVALID) : dsk;
+	c->hdr.size = sizeof(rblk_t) >> 2;
+	c->size += sizeof(rblk_t);
+
+	c->req.hdr.cmd = io->cmd;
+	c->req.hdr.blk = io->blk;
+	c->req.hdr.blk_cnt = io->blk_cnt;
+	c->type = CMD_IOCTL_PEND;
+
+	/* Pre submit processing */
+	switch(io->cmd) {
+	case PASSTHRU_A:
+		p = kmalloc(io->sg[0].size, GFP_KERNEL);
+		if (!p) 
+		{ 
+			error = -ENOMEM; 
+			cmd_free(NULL, c); 
+			return(error);
+		}
+		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
+		c->req.bp = virt_to_bus(&(io->c));
+		c->req.sg[0].size = io->sg[0].size;
+		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.hdr.sg_cnt = 1;
+		break;
+	case IDA_READ:
+		p = kmalloc(io->sg[0].size, GFP_KERNEL);
+		if (!p) 
+		{ 
+                        error = -ENOMEM; 
+                        cmd_free(NULL, c);
+                        return(error);
+                }
+
+		c->req.sg[0].size = io->sg[0].size;
+		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.hdr.sg_cnt = 1;
+		break;
+	case IDA_WRITE:
+	case IDA_WRITE_MEDIA:
+	case DIAG_PASS_THRU:
+		p = kmalloc(io->sg[0].size, GFP_KERNEL);
+		if (!p) 
+ 		{ 
+                        error = -ENOMEM; 
+                        cmd_free(NULL, c);
+                        return(error);
+                }
+		copy_from_user(p, (void*)io->sg[0].addr, io->sg[0].size);
+		c->req.sg[0].size = io->sg[0].size;
+		c->req.sg[0].addr = virt_to_bus(p);
+		c->req.hdr.sg_cnt = 1;
+		break;
+	default:
+		c->req.sg[0].size = sizeof(io->c);
+		c->req.sg[0].addr = virt_to_bus(&io->c);
+		c->req.hdr.sg_cnt = 1;
+	}
+
+	/* Put the request on the tail of the request queue */
+	spin_lock_irqsave(&io_request_lock, flags);
+	addQ(&h->reqQ, c);
+	h->Qdepth++;
+	start_io(h);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	/* Wait for completion */
+	while(c->type != CMD_IOCTL_DONE)
+		schedule();
+
+	/* Post submit processing */
+	switch(io->cmd) {
+	case PASSTHRU_A:
+	case IDA_READ:
+	case DIAG_PASS_THRU:
+		copy_to_user((void*)io->sg[0].addr, p, io->sg[0].size);
+		/* fall through and free p */
+	case IDA_WRITE:
+	case IDA_WRITE_MEDIA:
+		kfree(p);
+		break;
+	default:
+		/* Nothing to do */
+	}
+
+	io->rcode = c->req.hdr.rcode;
+	cmd_free(NULL, c);
+	return(0);
+}
+
+/*
+ * Commands are pre-allocated in a large block.  Here we use a simple bitmap
+ * scheme to suballocte them to the driver.  Operations that are not time
+ * critical (and can wait for kmalloc and possibly sleep) can pass in NULL
+ * as the first argument to get a new command.
+ */
+static cmdlist_t * cmd_alloc(ctlr_info_t *h)
+{
+	cmdlist_t * c;
+	int i;
+
+	if (h == NULL) {
+		c = (cmdlist_t*)kmalloc(sizeof(cmdlist_t), GFP_KERNEL);
+		if(c==NULL)
+			return NULL;
+	} else {
+		do {
+			i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
+			if (i == NR_CMDS)
+				return NULL;
+		} while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
+		c = h->cmd_pool + i;
+		h->nr_allocs++;
+	}
+
+	memset(c, 0, sizeof(cmdlist_t));
+	c->busaddr = virt_to_bus(c);
+	return c;
+}
+
+static void cmd_free(ctlr_info_t *h, cmdlist_t *c)
+{
+	int i;
+
+	if (h == NULL) {
+		kfree(c);
+	} else {
+		i = c - h->cmd_pool;
+		clear_bit(i%32, h->cmd_pool_bits+(i/32));
+		h->nr_frees++;
+	}
+}
+
+/***********************************************************************
+    name:        sendcmd
+    Send a command to an IDA using the memory mapped FIFO interface
+    and wait for it to complete.  
+    This routine should only be called at init time.
+***********************************************************************/
+static int sendcmd(
+	__u8	cmd,
+	int	ctlr,
+	void	*buff,
+	size_t	size,
+	unsigned int blk,
+	unsigned int blkcnt,
+	unsigned int log_unit )
+{
+	cmdlist_t *c;
+	int complete;
+	unsigned long temp;
+	unsigned long i;
+	ctlr_info_t *info_p = hba[ctlr];
+
+	c = cmd_alloc(info_p);
+	c->ctlr = ctlr;
+	c->hdr.unit = log_unit;
+	c->hdr.prio = 0;
+	c->hdr.size = sizeof(rblk_t) >> 2;
+	c->size += sizeof(rblk_t);
+
+	/* The request information. */
+	c->req.hdr.next = 0;
+	c->req.hdr.rcode = 0;
+	c->req.bp = 0;
+	c->req.hdr.sg_cnt = 1;
+	c->req.hdr.reserved = 0;
+	
+	if (size == 0)
+		c->req.sg[0].size = 512;
+	else
+		c->req.sg[0].size = size;
+
+	c->req.hdr.blk = blk;
+	c->req.hdr.blk_cnt = blkcnt;
+	c->req.hdr.cmd = (unsigned char) cmd;
+	c->req.sg[0].addr = (__u32) virt_to_bus(buff);
+	/*
+	 * Disable interrupt
+	 */
+	info_p->access.set_intr_mask(info_p, 0);
+	/* Make sure there is room in the command FIFO */
+	/* Actually it should be completely empty at this time. */
+	for (i = 200000; i > 0; i--) {
+		temp = info_p->access.fifo_full(info_p);
+		if (temp != 0) {
+			break;
+		}
+		udelay(10);
+DBG(
+		printk(KERN_WARNING "cpqarray ida%d: idaSendPciCmd FIFO full,"
+			" waiting!\n", ctlr);
+);
+	} 
+	/*
+	 * Send the cmd
+	 */
+	info_p->access.submit_command(info_p, c);
+	complete = pollcomplete(ctlr);
+	if (complete != 1) {
+		if (complete != c->busaddr) {
+			printk( KERN_WARNING
+			"cpqarray ida%d: idaSendPciCmd "
+		      "Invalid command list address returned! (%08lx)\n",
+				ctlr, (unsigned long)complete);
+			cmd_free(info_p, c);
+			return (IO_ERROR);
+		}
+	} else {
+		printk( KERN_WARNING
+			"cpqarray ida%d: idaSendPciCmd Timeout out, "
+			"No command list address returned!\n",
+			ctlr);
+		cmd_free(info_p, c);
+		return (IO_ERROR);
+	}
+
+	if (c->req.hdr.rcode & 0x00FE) {
+		if (!(c->req.hdr.rcode & BIG_PROBLEM)) {
+			printk( KERN_WARNING
+			"cpqarray ida%d: idaSendPciCmd, error: "
+				"Controller failed at init time "
+				"cmd: 0x%x, return code = 0x%x\n",
+				ctlr, c->req.hdr.cmd, c->req.hdr.rcode);
+
+			cmd_free(info_p, c);
+			return (IO_ERROR);
+		}
+	}
+	cmd_free(info_p, c);
+	return (IO_OK);
+}
+
+static int frevalidate_logvol(kdev_t dev)
+{
+	return revalidate_logvol(dev, 0);
+}
+
+/*
+ * revalidate_allvol is for online array config utilities.  After a
+ * utility reconfigures the drives in the array, it can use this function
+ * (through an ioctl) to make the driver zap any previous disk structs for
+ * that controller and get new ones.
+ *
+ * Right now I'm using the getgeometry() function to do this, but this
+ * function should probably be finer grained and allow you to revalidate one
+ * particualar logical volume (instead of all of them on a particular
+ * controller).
+ */
+static int revalidate_allvol(kdev_t dev)
+{
+	int ctlr, i;
+	unsigned long flags;
+
+	ctlr = MAJOR(dev) - MAJOR_NR;
+	if (MINOR(dev) != 0)
+		return -ENXIO;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	if (hba[ctlr]->usage_count > 1) {
+		spin_unlock_irqrestore(&io_request_lock, flags);
+		printk(KERN_WARNING "cpqarray: Device busy for volume"
+			" revalidation (usage=%d)\n", hba[ctlr]->usage_count);
+		return -EBUSY;
+	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	hba[ctlr]->usage_count++;
+
+	/*
+	 * Set the partition and block size structures for all volumes
+	 * on this controller to zero.  We will reread all of this data
+	 */
+	memset(ida+(ctlr*256),            0, sizeof(struct hd_struct)*NWD*16);
+	memset(ida_sizes+(ctlr*256),      0, sizeof(int)*NWD*16);
+	memset(ida_blocksizes+(ctlr*256), 0, sizeof(int)*NWD*16);
+	memset(ida_hardsizes+(ctlr*256),  0, sizeof(int)*NWD*16);
+	memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
+	ida_gendisk[ctlr].nr_real = 0;
+
+	/*
+	 * Tell the array controller not to give us any interupts while
+	 * we check the new geometry.  Then turn interrupts back on when
+	 * we're done.
+	 */
+	hba[ctlr]->access.set_intr_mask(hba[ctlr], 0);
+	getgeometry(ctlr);
+	hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
+
+	ida_geninit(&ida_gendisk[ctlr]);
+	for(i=0; i<NWD; i++)
+		if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
+			revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
+
+	hba[ctlr]->usage_count--;
+	return 0;
+}
+
+/* Borrowed and adapted from sd.c */
+static int revalidate_logvol(kdev_t dev, int maxusage)
+{
+	int ctlr, target;
+	struct gendisk *gdev;
+	unsigned long flags;
+	int max_p;
+	int start;
+	int i;
+
+	target = DEVICE_NR(dev);
+	ctlr = MAJOR(dev) - MAJOR_NR;
+	gdev = &ida_gendisk[ctlr];
+	
+	spin_lock_irqsave(&io_request_lock, flags);
+	if (hba[ctlr]->drv[target].usage_count > maxusage) {
+		spin_unlock_irqrestore(&io_request_lock, flags);
+		printk(KERN_WARNING "cpqarray: Device busy for "
+			"revalidation (usage=%d)\n",
+			hba[ctlr]->drv[target].usage_count);
+		return -EBUSY;
+	}
+
+	hba[ctlr]->drv[target].usage_count++;
+	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	max_p = gdev->max_p;
+	start = target << gdev->minor_shift;
+
+	for(i=max_p; i>=0; i--) {
+		int minor = start+i;
+		kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);
+		struct super_block *sb = get_super(devi);
+		sync_dev(devi);
+		if (sb) invalidate_inodes(sb);
+		invalidate_buffers(devi);
+		gdev->part[minor].start_sect = 0;	
+		gdev->part[minor].nr_sects = 0;	
+
+		/* reset the blocksize so we can read the partition table */
+		blksize_size[MAJOR_NR+ctlr][minor] = 1024;
+	}
+
+	gdev->part[start].nr_sects =  hba[ctlr]->drv[target].nr_blks;
+	resetup_one_dev(gdev, target);
+	hba[ctlr]->drv[target].usage_count--;
+	return 0;
+}
+
+
+/********************************************************************
+    name: pollcomplete
+    Wait polling for a command to complete.
+    The memory mapped FIFO is polled for the completion.
+    Used only at init time, interrupts disabled.
+ ********************************************************************/
+static int pollcomplete(int ctlr)
+{
+	int done;
+	int i;
+
+	/* Wait (up to 2 seconds) for a command to complete */
+
+	for (i = 200000; i > 0; i--) {
+		done = hba[ctlr]->access.command_completed(hba[ctlr]);
+		if (done == 0) {
+			udelay(10);	/* a short fixed delay */
+		} else
+			return (done);
+	}
+	/* Invalid address to tell caller we ran out of time */
+	return 1;
+}
+/*****************************************************************
+    start_fwbk
+    Starts controller firmwares background processing. 
+    Currently only the Integrated Raid controller needs this done.
+    If the PCI mem address registers are written to after this, 
+	 data corruption may occur
+*****************************************************************/
+static void start_fwbk(int ctlr)
+{
+		id_ctlr_t *id_ctlr_buf; 
+	int ret_code;
+
+	if(	hba[ctlr]->board_id != 0x40400E11)
+	/* Not a Integrated Raid, so there is nothing for us to do */
+		return;
+	printk(KERN_DEBUG "cpqarray: Starting firmware's background"
+		" processing\n");
+	/* Command does not return anything, but idasend command needs a 
+		buffer */
+	id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+	if(id_ctlr_buf==NULL)
+	{
+		printk(KERN_WARNING "cpqarray: Out of memory. "
+			"Unable to start background processing.\n");
+		return;
+	}		
+	ret_code = sendcmd(RESUME_BACKGROUND_ACTIVITY, ctlr, 
+		id_ctlr_buf, 0, 0, 0, 0);
+	if(ret_code != IO_OK)
+		printk(KERN_WARNING "cpqarray: Unable to start"
+			" background processing\n");
+	kfree(id_ctlr_buf);
+}
+/*****************************************************************
+    getgeometry
+    Get ida logical volume geometry from the controller 
+    This is a large bit of code which once existed in two flavors,
+    It is used only at init time.
+*****************************************************************/
+static void getgeometry(int ctlr)
+{				
+	id_log_drv_t *id_ldrive;
+	id_ctlr_t *id_ctlr_buf;
+	sense_log_drv_stat_t *id_lstatus_buf;
+	config_t *sense_config_buf;
+	unsigned int log_unit, log_index;
+	int ret_code, size;
+	drv_info_t *drv;
+	ctlr_info_t *info_p = hba[ctlr];
+
+	info_p->log_drv_map = 0;	
+	
+	id_ldrive = (id_log_drv_t *)kmalloc(sizeof(id_log_drv_t), GFP_KERNEL);
+	if(id_ldrive == NULL)
+	{
+		printk( KERN_ERR "cpqarray:  out of memory.\n");
+		return;
+	}
+	id_ctlr_buf = (id_ctlr_t *)kmalloc(sizeof(id_ctlr_t), GFP_KERNEL);
+	if(id_ctlr_buf == NULL)
+	{
+		kfree(id_ldrive);
+		printk( KERN_ERR "cpqarray:  out of memory.\n");
+                return;
+        }
+
+	id_lstatus_buf = (sense_log_drv_stat_t *)kmalloc(sizeof(sense_log_drv_stat_t), GFP_KERNEL);
+	if(id_lstatus_buf == NULL)
+	{
+		kfree(id_ctlr_buf);
+                kfree(id_ldrive);
+                printk( KERN_ERR "cpqarray:  out of memory.\n");
+                return;
+        }
+
+	sense_config_buf = (config_t *)kmalloc(sizeof(config_t), GFP_KERNEL);
+	if(sense_config_buf == NULL)
+	{
+		kfree(id_lstatus_buf);
+                kfree(id_ctlr_buf);
+                kfree(id_ldrive);
+                printk( KERN_ERR "cpqarray:  out of memory.\n");
+                return;
+        }
+
+	memset(id_ldrive, 0, sizeof(id_log_drv_t));
+	memset(id_ctlr_buf, 0, sizeof(id_ctlr_t));
+	memset(id_lstatus_buf, 0, sizeof(sense_log_drv_stat_t));
+	memset(sense_config_buf, 0, sizeof(config_t));
+
+	info_p->phys_drives = 0;
+	info_p->log_drv_map = 0;
+	info_p->drv_assign_map = 0;
+	info_p->drv_spare_map = 0;
+	info_p->mp_failed_drv_map = 0;	/* only initialized here */
+	/* Get controllers info for this logical drive */
+	ret_code = sendcmd(ID_CTLR, ctlr, id_ctlr_buf, 0, 0, 0, 0);
+	if (ret_code == IO_ERROR) {
+		/*
+		 * If can't get controller info, set the logical drive map to 0,
+		 * so the idastubopen will fail on all logical drives
+		 * on the controller.
+		 */
+		 /* Free all the buffers and return */ 
+		printk(KERN_ERR "cpqarray: error sending ID controller\n");
+		kfree(sense_config_buf);
+                kfree(id_lstatus_buf);
+                kfree(id_ctlr_buf);
+                kfree(id_ldrive);
+                return;
+        }
+
+	info_p->log_drives = id_ctlr_buf->nr_drvs;;
+	*(__u32*)(info_p->firm_rev) = *(__u32*)(id_ctlr_buf->firm_rev);
+	info_p->ctlr_sig = id_ctlr_buf->cfg_sig;
+
+	printk(" (%s)\n", info_p->product_name);
+	/*
+	 * Initialize logical drive map to zero
+	 */
+	log_index = 0;
+	/*
+	 * Get drive geometry for all logical drives
+	 */
+	if (id_ctlr_buf->nr_drvs > 16)
+		printk(KERN_WARNING "cpqarray ida%d:  This driver supports "
+			"16 logical drives per controller.\n.  "
+			" Additional drives will not be "
+			"detected\n", ctlr);
+
+	for (log_unit = 0;
+	     (log_index < id_ctlr_buf->nr_drvs)
+	     && (log_unit < NWD);
+	     log_unit++) {
+
+		size = sizeof(sense_log_drv_stat_t);
+
+		/*
+		   Send "Identify logical drive status" cmd
+		 */
+		ret_code = sendcmd(SENSE_LOG_DRV_STAT,
+			     ctlr, id_lstatus_buf, size, 0, 0, log_unit);
+		if (ret_code == IO_ERROR) {
+			/*
+			   If can't get logical drive status, set
+			   the logical drive map to 0, so the
+			   idastubopen will fail for all logical drives
+			   on the controller. 
+			 */
+			info_p->log_drv_map = 0;	
+			printk( KERN_WARNING
+			     "cpqarray ida%d: idaGetGeometry - Controller"
+				" failed to report status of logical drive %d\n"
+			 "Access to this controller has been disabled\n",
+				ctlr, log_unit);
+			/* Free all the buffers and return */
+                	kfree(sense_config_buf);
+                	kfree(id_lstatus_buf);
+                	kfree(id_ctlr_buf);
+                	kfree(id_ldrive);
+                	return;
+		}
+		/*
+		   Make sure the logical drive is configured
+		 */
+		if (id_lstatus_buf->status != LOG_NOT_CONF) {
+			ret_code = sendcmd(ID_LOG_DRV, ctlr, id_ldrive,
+			       sizeof(id_log_drv_t), 0, 0, log_unit);
+			/*
+			   If error, the bit for this
+			   logical drive won't be set and
+			   idastubopen will return error. 
+			 */
+			if (ret_code != IO_ERROR) {
+				drv = &info_p->drv[log_unit];
+				drv->blk_size = id_ldrive->blk_size;
+				drv->nr_blks = id_ldrive->nr_blks;
+				drv->cylinders = id_ldrive->drv.cyl;
+				drv->heads = id_ldrive->drv.heads;
+				drv->sectors = id_ldrive->drv.sect_per_track;
+				info_p->log_drv_map |=	(1 << log_unit);
+
+	printk(KERN_INFO "cpqarray ida/c%dd%d: blksz=%d nr_blks=%d\n",
+		ctlr, log_unit, drv->blk_size, drv->nr_blks);
+				ret_code = sendcmd(SENSE_CONFIG,
+						  ctlr, sense_config_buf,
+				 sizeof(config_t), 0, 0, log_unit);
+				if (ret_code == IO_ERROR) {
+					info_p->log_drv_map = 0;
+					/* Free all the buffers and return */
+                			printk(KERN_ERR "cpqarray: error sending sense config\n");
+                			kfree(sense_config_buf);
+                			kfree(id_lstatus_buf);
+                			kfree(id_ctlr_buf);
+                			kfree(id_ldrive);
+                			return;
+
+				}
+				info_p->phys_drives =
+				    sense_config_buf->ctlr_phys_drv;
+				info_p->drv_assign_map
+				    |= sense_config_buf->drv_asgn_map;
+				info_p->drv_assign_map
+				    |= sense_config_buf->spare_asgn_map;
+				info_p->drv_spare_map
+				    |= sense_config_buf->spare_asgn_map;
+			}	/* end of if no error on id_ldrive */
+			log_index = log_index + 1;
+		}		/* end of if logical drive configured */
+	}			/* end of for log_unit */
+	kfree(sense_config_buf);
+	kfree(id_ldrive);
+	kfree(id_lstatus_buf);
+	kfree(id_ctlr_buf);
+	return;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/cpqarray.h linux.pre11.3/drivers/block/cpqarray.h
--- linux.vanilla/drivers/block/cpqarray.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/cpqarray.h	Tue Jul 20 01:53:07 1999
@@ -0,0 +1,120 @@
+/*
+ *    Disk Array driver for Compaq SMART2 Controllers
+ *    Copyright 1998 Compaq Computer Corporation
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to arrays@compaq.com
+ *
+ *    If you want to make changes, improve or add functionality to this
+ *    driver, you'll probably need the Compaq Array Controller Interface
+ *    Specificiation (Document number ECG086/1198)
+ */
+#ifndef CPQARRAY_H
+#define CPQARRAY_H
+
+#ifdef __KERNEL__
+#include <linux/blkdev.h>
+#include <linux/locks.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+#include <linux/md.h>
+#include <linux/timer.h>
+#endif
+
+#include "ida_cmd.h"
+
+#define IO_OK		0
+#define IO_ERROR	1
+#define NWD		16
+#define NWD_SHIFT	4
+
+#define IDA_TIMER	(5*HZ)
+#define IDA_TIMEOUT	(10*HZ)
+
+#define MISC_NONFATAL_WARN	0x01
+
+typedef struct {
+	unsigned blk_size;
+	unsigned nr_blks;
+	unsigned cylinders;
+	unsigned heads;
+	unsigned sectors;
+	int usage_count;
+} drv_info_t;
+
+#ifdef __KERNEL__
+
+struct ctlr_info;
+typedef struct ctlr_info ctlr_info_t;
+
+struct access_method {
+	void (*submit_command)(ctlr_info_t *h, cmdlist_t *c);
+	void (*set_intr_mask)(ctlr_info_t *h, unsigned long val);
+	unsigned long (*fifo_full)(ctlr_info_t *h);
+	unsigned long (*intr_pending)(ctlr_info_t *h);
+	unsigned long (*command_completed)(ctlr_info_t *h);
+};
+
+struct board_type {
+	__u32	board_id;
+	char	*product_name;
+	struct access_method *access;
+};
+
+struct ctlr_info {
+	int	ctlr;
+	char	devname[8];
+	__u32	log_drv_map;
+	__u32	drv_assign_map;
+	__u32	drv_spare_map;
+	__u32	mp_failed_drv_map;
+
+	char	firm_rev[4];
+	int	ctlr_sig;
+
+	int	log_drives;
+	int	phys_drives;
+
+	__u32	board_id;
+	char	*product_name;	
+
+	__u32	vaddr;
+	__u32	paddr;
+	__u32	ioaddr;
+	int	intr;
+	int	usage_count;
+	drv_info_t	drv[NWD];
+	struct proc_dir_entry *proc;
+
+	struct access_method access;
+
+	cmdlist_t *reqQ;
+	cmdlist_t *cmpQ;
+	cmdlist_t *cmd_pool;
+	__u32	*cmd_pool_bits;
+
+	unsigned int Qdepth;
+	unsigned int maxQsinceinit;
+
+	unsigned int nr_requests;
+	unsigned int nr_allocs;
+	unsigned int nr_frees;
+	struct timer_list timer;
+	unsigned int misc_tflags;
+};
+#endif
+
+#endif /* CPQARRAY_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/genhd.c linux.pre11.3/drivers/block/genhd.c
--- linux.vanilla/drivers/block/genhd.c	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/drivers/block/genhd.c	Tue Jul 20 01:39:05 1999
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 
 #include <asm/system.h>
+#include <asm/byteorder.h>
 
 /*
  * Many architectures don't like unaligned accesses, which is
@@ -58,6 +59,9 @@
 
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
+#ifdef CONFIG_BLK_DEV_DAC960
+extern void DAC960_Initialize(void);
+#endif
 extern int scsi_dev_init(void);
 extern int net_dev_init(void);
 
@@ -65,6 +69,20 @@
 extern void note_bootable_part(kdev_t dev, int part);
 #endif
 
+static char *raid_name (struct gendisk *hd, int minor, int major_base,
+                        char *buf)
+{
+        int ctlr = hd->major - major_base;
+        int disk = minor >> hd->minor_shift;
+        int part = minor & (( 1 << hd->minor_shift) - 1);
+        if (part == 0)
+                sprintf(buf, "%s/c%dd%d", hd->major_name, ctlr, disk);
+        else
+                sprintf(buf, "%s/c%dd%dp%d", hd->major_name, ctlr, disk,
+                        part);
+        return buf;
+}
+
 /*
  * disk_name() is used by genhd.c and md.c.
  * It formats the devicename of the indicated disk
@@ -81,6 +99,8 @@
 	 * IDE devices use multiple major numbers, but the drives
 	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
 	 * This requires special handling here.
+	 *
+	 * MD devices are named md0, md1, ... md15, fix it up here.
 	 */
 	switch (hd->major) {
 		case IDE5_MAJOR:
@@ -96,6 +116,8 @@
 		case IDE0_MAJOR:
 			maj = "hd";
 			break;
+		case MD_MAJOR:
+			unit -= 'a'-'0';
 	}
 	part = minor & ((1 << hd->minor_shift) - 1);
 	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
@@ -108,6 +130,13 @@
 			return buf;
 		}
 	}
+	if (hd->major >= COMPAQ_SMART2_MAJOR && hd->major <=
+            COMPAQ_SMART2_MAJOR+7) {
+          return raid_name (hd, minor, COMPAQ_SMART2_MAJOR, buf);
+ 	}
+	if (hd->major >= DAC960_MAJOR && hd->major <= DAC960_MAJOR+7) {
+          return raid_name (hd, minor, DAC960_MAJOR, buf);
+ 	}
 	if (part)
 		sprintf(buf, "%s%c%d", maj, unit, part);
 	else
@@ -115,11 +144,16 @@
 	return buf;
 }
 
-static void add_partition (struct gendisk *hd, int minor, int start, int size)
+static void add_partition (struct gendisk *hd, int minor,
+					int start, int size, int type)
 {
-	char buf[8];
-	hd->part[minor].start_sect = start;
-	hd->part[minor].nr_sects   = size;
+	char buf[MAX_DISKNAME_LEN];
+	struct hd_struct *p = hd->part+minor;
+
+	p->start_sect = start;
+	p->nr_sects = size;
+	p->type = type;
+
 	printk(" %s", disk_name(hd, minor, buf));
 }
 
@@ -140,49 +174,49 @@
 
 static unsigned int get_ptable_blocksize(kdev_t dev)
 {
-  int ret = 1024;
+	int ret = 1024;
 
-  /*
-   * See whether the low-level driver has given us a minumum blocksize.
-   * If so, check to see whether it is larger than the default of 1024.
-   */
-  if (!blksize_size[MAJOR(dev)])
-    {
-      return ret;
-    }
+	/*
+	 * See whether the low-level driver has given us a minumum blocksize.
+	 * If so, check to see whether it is larger than the default of 1024.
+	 */
+	if (!blksize_size[MAJOR(dev)])
+		return ret;
 
-  /*
-   * Check for certain special power of two sizes that we allow.
-   * With anything larger than 1024, we must force the blocksize up to
-   * the natural blocksize for the device so that we don't have to try
-   * and read partial sectors.  Anything smaller should be just fine.
-   */
+	/*
+	 * Check for certain special power of two sizes that we allow.
+	 * With anything larger than 1024, we must force the blocksize up to
+	 * the natural blocksize for the device so that we don't have to try
+	 * and read partial sectors.  Anything smaller should be just fine.
+	 */
 
-  switch( blksize_size[MAJOR(dev)][MINOR(dev)] )
-    {
-    case 2048:
-      ret = 2048;
-      break;
-    case 4096:
-      ret = 4096;
-      break;
-    case 8192:
-      ret = 8192;
-      break;
-    case 1024:
-    case 512:
-    case 256:
-    case 0:
-      /*
-       * These are all OK.
-       */
-      break;
-    default:
-      panic("Strange blocksize for partition table\n");
-    }
+	switch( blksize_size[MAJOR(dev)][MINOR(dev)] ) {
+	case 2048:
+		ret = 2048;
+		break;
+
+	case 4096:
+		ret = 4096;
+		break;
+
+	case 8192:
+		ret = 8192;
+		break;
+
+	case 1024:
+	case 512:
+	case 256:
+	case 0:
+		/*
+		 * These are all OK.
+		 */
+		break;
 
-  return ret;
+	default:
+		panic("Strange blocksize for partition table\n");
+	}
 
+	return ret;
 }
 
 #ifdef CONFIG_MSDOS_PARTITION
@@ -255,7 +289,8 @@
 				     first_sector + first_size))
 				continue;
 
-			add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+			add_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size, 
+				      NR_SECTS(p)*sector_size, ptype(SYS_IND(p)));
 			current_minor++;
 			if ((current_minor & mask) == 0)
 				goto done;
@@ -319,7 +354,8 @@
 		 * one but add_partition starts relative to sector
 		 * zero of the disk.  Therefore, must add the offset
 		 * of the current partition */
-		add_partition(hd, current_minor, s->s_start+offset, s->s_size);
+		add_partition(hd, current_minor,
+					s->s_start+offset, s->s_size, 0);
 		current_minor++;
 	}
 	brelse(bh);
@@ -365,7 +401,7 @@
 	} /* if the bsd partition is not currently known to linux, we end
 	   * up here 
 	   */
-	add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
+	add_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size, 0);
 	current_minor++;
 }
 /* 
@@ -432,7 +468,7 @@
 			break;
 
 		if (p->s_label != UNIXWARE_FS_UNUSED) {
-			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p), 0);
 			current_minor++;
 		}
 		p++;
@@ -552,7 +588,8 @@
 	for (i=1 ; i<=4 ; minor++,i++,p++) {
 		if (!NR_SECTS(p))
 			continue;
-               add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+               add_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, 
+               		     ptype(SYS_IND(p)));
 		if (is_extended_partition(p)) {
 			printk(" <");
 			/*
@@ -619,7 +656,8 @@
 				break;
 			if (!(START_SECT(p) && NR_SECTS(p)))
 				continue;
-			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+			add_partition(hd, current_minor, START_SECT(p),
+					NR_SECTS(p), 0);
 		}
 	}
 	printk("\n");
@@ -677,12 +715,10 @@
 	label = (struct disklabel *) (bh->b_data+64);
 	partition = label->d_partitions;
 	if (label->d_magic != DISKLABELMAGIC) {
-		printk("magic: %08x\n", label->d_magic);
 		brelse(bh);
 		return 0;
 	}
 	if (label->d_magic2 != DISKLABELMAGIC) {
-		printk("magic2: %08x\n", label->d_magic2);
 		brelse(bh);
 		return 0;
 	}
@@ -692,7 +728,7 @@
 		if (partition->p_size)
 			add_partition(hd, current_minor,
 				first_sector+partition->p_offset,
-				partition->p_size);
+				partition->p_size, 0);
 		current_minor++;
 	}
 	printk("\n");
@@ -711,7 +747,14 @@
 	struct buffer_head *bh;
 	struct sun_disklabel {
 		unsigned char info[128];   /* Informative text string */
-		unsigned char spare[292];  /* Boot information etc. */
+		unsigned char spare0[14];
+		struct sun_disklabelinfo {
+			unsigned char spare1;
+			unsigned char id;
+			unsigned char spare2;
+			unsigned char flags;
+		} infos[8];
+		unsigned char spare1[246];  /* Boot information etc. */
 		unsigned short rspeed;     /* Disk rotational speed */
 		unsigned short pcylcount;  /* Physical cylinder count */
 		unsigned short sparecyl;   /* extra sects per cylinder */
@@ -765,7 +808,8 @@
 		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
 		num_sectors = be32_to_cpu(p->num_sectors);
 		if (num_sectors)
-			add_partition(hd, current_minor, st_sector, num_sectors);
+			add_partition(hd, current_minor, st_sector,
+					num_sectors, ptype(label->infos[i].id));
 		current_minor++;
 	}
 	printk("\n");
@@ -776,14 +820,11 @@
 #endif /* CONFIG_SUN_PARTITION */
 
 #ifdef CONFIG_SGI_PARTITION
-#include <asm/byteorder.h>
 
 static int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
 {
-	int i, csum;
-	unsigned int *ui;
-	unsigned int start, blocks, cs;
-	int magic;
+	int i, csum, magic;
+	unsigned int *ui, start, blocks, cs;
 	struct buffer_head *bh;
 	struct sgi_disklabel {
 		int magic_mushroom;         /* Big fat spliff... */
@@ -841,7 +882,7 @@
 		start  = be32_to_cpu(p->first_block);
 		if(!blocks)
 			continue;
-		add_partition(hd, current_minor, start, blocks);
+		add_partition(hd, current_minor, start, blocks, 0);
 		current_minor++;
 	}
 	printk("\n");
@@ -852,7 +893,6 @@
 #endif
 
 #ifdef CONFIG_AMIGA_PARTITION
-#include <asm/byteorder.h>
 #include <linux/affs_hardblocks.h>
 
 static __inline__ u32
@@ -923,27 +963,30 @@
 				blk = htonl(pb->pb_Next);
 				if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
 				    (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
-					
+
 					/* Tell Kernel about it */
 
 					if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
 							  htonl(pb->pb_Environment[9])) *
 							 htonl(pb->pb_Environment[3]) *
 							 htonl(pb->pb_Environment[5]))) {
+						brelse(bh);
 						continue;
 					}
 					start_sect = htonl(pb->pb_Environment[9]) *
 						     htonl(pb->pb_Environment[3]) *
 						     htonl(pb->pb_Environment[5]);
-					add_partition(hd,current_minor,start_sect,nr_sects);
+					add_partition(hd,current_minor,
+							start_sect,nr_sects,0);
 					current_minor++;
 					res = 1;
 				}
 				brelse(bh);
 			}
 			printk("\n");
-			break;
 		}
+		else
+			brelse(bh);
 	}
 
 rdb_done:
@@ -1056,7 +1099,7 @@
 		blocks_in_map = be32_to_cpu(part->map_count);
 		add_partition(hd, current_minor,
 			fsec + be32_to_cpu(part->start_block) * (secsize/512),
-			be32_to_cpu(part->block_count) * (secsize/512));
+			be32_to_cpu(part->block_count) * (secsize/512), 0);
 
 #ifdef CONFIG_PPC
 		/*
@@ -1147,7 +1190,7 @@
 		  }
 
 		  add_partition(hd, minor, partsect + xrs->part[0].st,
-				xrs->part[0].siz);
+				xrs->part[0].siz, 0);
 
 		  if (!(xrs->part[1].flg & 1)) {
 		    /* end of linked partition list */
@@ -1173,7 +1216,7 @@
 	  else
 	    {
 	      /* we don't care about other id's */
-	      add_partition (hd, minor, pi->st, pi->siz);
+	      add_partition (hd, minor, pi->st, pi->siz, 0);
 	    }
 	}
     }
@@ -1200,7 +1243,7 @@
              memcmp (pi->id, "RAW", 3) == 0) )
         {
           part_fmt = 2;
-	  add_partition (hd, minor, pi->st, pi->siz);
+	  add_partition (hd, minor, pi->st, pi->siz, 0);
         }
       }
       printk(" >");
@@ -1215,11 +1258,59 @@
 }
 #endif /* CONFIG_ATARI_PARTITION */
 
+#ifdef CONFIG_ULTRIX_PARTITION
+
+static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+	int i, minor = current_minor;
+	struct buffer_head *bh;
+	struct ultrix_disklabel {
+		long	pt_magic;	/* magic no. indicating part. info exits */
+		int	pt_valid;	/* set by driver if pt is current */
+		struct  pt_info {
+			int		pi_nblocks; /* no. of sectors */
+			unsigned long	pi_blkoff;  /* block offset for start */
+		} pt_part[8];
+	} *label;
+
+#define PT_MAGIC	0x032957	/* Partition magic number */
+#define PT_VALID	1		/* Indicates if struct is valid */
+
+#define	SBLOCK	((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
+                  /get_ptable_blocksize(dev)))
+
+	bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
+	if (!bh) {
+		printk (" unable to read block 0x%lx\n", SBLOCK);
+		return -1;
+	}
+	
+	label = (struct ultrix_disklabel *)(bh->b_data
+                                            + get_ptable_blocksize(dev)
+                                            - sizeof(struct ultrix_disklabel));
+
+	if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
+		for (i=0; i<8; i++, minor++)
+			if (label->pt_part[i].pi_nblocks)
+				add_partition(hd, minor, 
+					      label->pt_part[i].pi_blkoff,
+					      label->pt_part[i].pi_nblocks);
+		brelse(bh);
+		printk ("\n");
+		return 1;
+	} else {
+		brelse(bh);
+		return 0;
+	}
+}
+
+#endif /* CONFIG_ULTRIX_PARTITION */
+
 static void check_partition(struct gendisk *hd, kdev_t dev)
 {
 	static int first_time = 1;
 	unsigned long first_sector;
-	char buf[8];
+	char buf[MAX_DISKNAME_LEN];
 
 	if (first_time)
 		printk("Partition check:\n");
@@ -1264,6 +1355,10 @@
 	if(sgi_partition(hd, dev, first_sector))
 		return;
 #endif
+#ifdef CONFIG_ULTRIX_PARTITION
+	if(ultrix_partition(hd, dev, first_sector))
+		return;
+#endif
 	printk(" unknown partition table\n");
 }
 
@@ -1323,6 +1418,7 @@
 __initfunc(void device_setup(void))
 {
 	extern void console_map_init(void);
+	extern void cpqarray_init(void);
 #ifdef CONFIG_PARPORT
 	extern int parport_init(void);
 #endif
@@ -1340,6 +1436,9 @@
 	chr_dev_init();
 	blk_dev_init();
 	sti();
+#ifdef CONFIG_BLK_DEV_DAC960
+	DAC960_Initialize();
+#endif
 #ifdef CONFIG_FC4_SOC
 	/* This has to be done before scsi_dev_init */
 	soc_probe();
@@ -1347,6 +1446,9 @@
 #ifdef CONFIG_SCSI
 	scsi_dev_init();
 #endif
+#ifdef CONFIG_BLK_CPQ_DA
+	cpqarray_init();
+#endif
 #ifdef CONFIG_INET
 	net_dev_init();
 #endif
@@ -1373,7 +1475,7 @@
 int get_partition_list(char * page)
 {
 	struct gendisk *p;
-	char buf[32];
+	char buf[MAX_DISKNAME_LEN];
 	int n, len;
 
 	len = sprintf(page, "major minor  #blocks  name\n\n");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ida_cmd.h linux.pre11.3/drivers/block/ida_cmd.h
--- linux.vanilla/drivers/block/ida_cmd.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/ida_cmd.h	Tue Jul 20 01:53:07 1999
@@ -0,0 +1,347 @@
+/*
+ *    Disk Array driver for Compaq SMART2 Controllers
+ *    Copyright 1998 Compaq Computer Corporation
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to arrays@compaq.com
+ *
+ *    If you want to make changes, improve or add functionality to this
+ *    driver, you'll probably need the Compaq Array Controller Interface
+ *    Specificiation (Document number ECG086/1198)
+ */
+#ifndef ARRAYCMD_H
+#define ARRAYCMD_H
+
+#include <asm/types.h>
+#if 0
+#include <linux/blkdev.h>
+#endif
+
+/* for the Smart Array 42XX cards */
+#define S42XX_REQUEST_PORT_OFFSET	0x40
+#define S42XX_REPLY_INTR_MASK_OFFSET	0x34
+#define S42XX_REPLY_PORT_OFFSET		0x44
+#define S42XX_INTR_STATUS		0x30
+
+#define S42XX_INTR_OFF		0x08
+#define S42XX_INTR_PENDING	0x08
+
+#define COMMAND_FIFO		0x04
+#define COMMAND_COMPLETE_FIFO	0x08
+#define INTR_MASK		0x0C
+#define INTR_STATUS		0x10
+#define INTR_PENDING		0x14
+
+#define FIFO_NOT_EMPTY		0x01
+#define FIFO_NOT_FULL		0x02
+
+#define BIG_PROBLEM		0x40
+#define LOG_NOT_CONF		2
+
+#pragma pack(1)
+typedef struct {
+	__u32	size;
+	__u32	addr;
+} sg_t;
+
+#define RCODE_NONFATAL	0x02
+#define RCODE_FATAL	0x04
+#define RCODE_INVREQ	0x10
+typedef struct {
+	__u16	next;
+	__u8	cmd;
+	__u8	rcode;
+	__u32	blk;
+	__u16	blk_cnt;
+	__u8	sg_cnt;
+	__u8	reserved;
+} rhdr_t;
+
+#define SG_MAX			32
+typedef struct {
+	rhdr_t	hdr;
+	sg_t	sg[SG_MAX];
+	__u32	bp;
+} rblk_t;
+
+typedef struct {
+	__u8	unit;
+	__u8	prio;
+	__u16	size;
+} chdr_t;
+
+#define CMD_RWREQ	0x00
+#define CMD_IOCTL_PEND	0x01
+#define CMD_IOCTL_DONE	0x02
+
+typedef struct cmdlist {
+	chdr_t	hdr;
+	rblk_t	req;
+	__u32	size;
+	int	retry_cnt;
+	__u32	busaddr;
+	int	ctlr;
+	struct cmdlist *prev;
+	struct cmdlist *next;
+	struct buffer_head *bh;
+	int type;
+} cmdlist_t;
+	
+#define ID_CTLR		0x11
+typedef struct {
+	__u8	nr_drvs;
+	__u32	cfg_sig;
+	__u8	firm_rev[4];
+	__u8	rom_rev[4];
+	__u8	hw_rev;
+	__u32	bb_rev;
+	__u32	drv_present_map;
+	__u32	ext_drv_map;
+	__u32	board_id;
+	__u8	cfg_error;
+	__u32	non_disk_bits;
+	__u8	bad_ram_addr;
+	__u8	cpu_rev;
+	__u8	pdpi_rev;
+	__u8	epic_rev;
+	__u8	wcxc_rev;
+	__u8	marketing_rev;
+	__u8	ctlr_flags;
+	__u8	host_flags;
+	__u8	expand_dis;
+	__u8	scsi_chips;
+	__u32	max_req_blocks;
+	__u32	ctlr_clock;
+	__u8	drvs_per_bus;
+	__u16	big_drv_present_map[8];
+	__u16	big_ext_drv_map[8];
+	__u16	big_non_disk_map[8];
+	__u16	task_flags;
+	__u8	icl_bus;
+	__u8	red_modes;
+	__u8	cur_red_mode;
+	__u8	red_ctlr_stat;
+	__u8	red_fail_reason;
+	__u8	reserved[403];
+} id_ctlr_t;
+
+typedef struct {
+	__u16	cyl;
+	__u8	heads;
+	__u8	xsig;
+	__u8	psectors;
+	__u16	wpre;
+	__u8	maxecc;
+	__u8	drv_ctrl;
+	__u16	pcyls;
+	__u8	pheads;
+	__u16	landz;
+	__u8	sect_per_track;
+	__u8	cksum;
+} drv_param_t;
+
+#define ID_LOG_DRV	0x10
+typedef struct {
+	__u16	blk_size;
+	__u32	nr_blks;
+	drv_param_t drv;
+	__u8	fault_tol;
+	__u8	reserved;
+	__u8	bios_disable;
+} id_log_drv_t;
+
+#define ID_LOG_DRV_EXT	0x18
+typedef struct {
+	__u32	log_drv_id;
+	__u8	log_drv_label[64];
+	__u8	reserved[418];
+} id_log_drv_ext_t;
+
+#define SENSE_LOG_DRV_STAT	0x12
+typedef struct {
+	__u8	status;
+	__u32	fail_map;
+	__u16	read_err[32];
+	__u16	write_err[32];
+	__u8	drv_err_data[256];
+	__u8	drq_timeout[32];
+	__u32	blks_to_recover;
+	__u8	drv_recovering;
+	__u16	remap_cnt[32];
+	__u32	replace_drv_map;
+	__u32	act_spare_map;
+	__u8	spare_stat;
+	__u8	spare_repl_map[32];
+	__u32	repl_ok_map;
+	__u8	media_exch;
+	__u8	cache_fail;
+	__u8	expn_fail;
+	__u8	unit_flags;
+	__u16	big_fail_map[8];
+	__u16	big_remap_map[8];
+	__u16	big_repl_map[8];
+	__u16	big_act_spare_map[8];
+	__u8	big_spar_repl_map[128];
+	__u16	big_repl_ok_map[8];
+	__u8	big_drv_rebuild;
+	__u8	reserved[36];
+} sense_log_drv_stat_t;
+
+#define START_RECOVER		0x13
+
+#define ID_PHYS_DRV		0x15
+typedef struct {
+	__u8	scsi_bus;
+	__u8	scsi_id;
+	__u16	blk_size;
+	__u32	nr_blks;
+	__u32	rsvd_blks;
+	__u8	drv_model[40];
+	__u8	drv_sn[40];
+	__u8	drv_fw[8];
+	__u8	scsi_iq_bits;
+	__u8	compaq_drv_stmp;
+	__u8	last_fail;
+	__u8	phys_drv_flags;
+	__u8	phys_drv_flags1;
+	__u8	scsi_lun;
+	__u8	phys_drv_flags2;
+	__u8	reserved;
+	__u32	spi_speed_rules;
+	__u8	phys_connector[2];
+	__u8	phys_box_on_bus;
+	__u8	phys_bay_in_box;
+} id_phys_drv_t;
+
+#define BLINK_DRV_LEDS		0x16
+typedef struct {
+	__u32	blink_duration;
+	__u32	reserved;
+	__u8	blink[256];
+	__u8	reserved1[248];
+} blink_drv_leds_t;
+
+#define SENSE_BLINK_LEDS	0x17
+typedef struct {
+	__u32	blink_duration;
+	__u32	btime_elap;
+	__u8	blink[256];
+	__u8	reserved1[248];
+} sense_blink_leds_t;
+
+#define IDA_READ		0x20
+#define IDA_WRITE		0x30
+#define IDA_WRITE_MEDIA		0x31
+#define RESET_TO_DIAG		0x40
+#define DIAG_PASS_THRU		0x41
+
+#define SENSE_CONFIG		0x50
+#define SET_CONFIG		0x51
+typedef struct {
+	__u32	cfg_sig;
+	__u16	compat_port;
+	__u8	data_dist_mode;
+	__u8	surf_an_ctrl;
+	__u16	ctlr_phys_drv;
+	__u16	log_unit_phys_drv;
+	__u16	fault_tol_mode;
+	__u8	phys_drv_param[16];
+	drv_param_t drv;
+	__u32	drv_asgn_map;
+	__u16	dist_factor;
+	__u32	spare_asgn_map;
+	__u8	reserved[6];
+	__u16	os;
+	__u8	ctlr_order;
+	__u8	extra_info;
+	__u32	data_offs;
+	__u8	parity_backedout_write_drvs;
+	__u8	parity_dist_mode;
+	__u8	parity_shift_fact;
+	__u8	bios_disable_flag;
+	__u32	blks_on_vol;
+	__u32	blks_per_drv;
+	__u8	scratch[16];
+	__u16	big_drv_map[8];
+	__u16	big_spare_map[8];
+	__u8	ss_source_vol;
+	__u8	mix_drv_cap_range;
+	struct {
+		__u16	big_drv_map[8];
+		__u32	blks_per_drv;
+		__u16	fault_tol_mode;
+		__u16	dist_factor;
+	} MDC_range[4];
+	__u8	reserved1[248];
+} config_t;
+
+#define BYPASS_VOL_STATE	0x52
+#define SS_CREATE_VOL		0x53
+#define CHANGE_CONFIG		0x54
+#define SENSE_ORIG_CONF		0x55
+#define REORDER_LOG_DRV		0x56
+typedef struct {
+	__u8	old_units[32];
+} reorder_log_drv_t;
+
+#define LABEL_LOG_DRV		0x57
+typedef struct {
+	__u8	log_drv_label[64];
+} label_log_drv_t;
+
+#define SS_TO_VOL		0x58
+	
+#define SET_SURF_DELAY		0x60
+typedef struct {
+	__u16	delay;
+	__u8	reserved[510];
+} surf_delay_t;
+
+#define SET_OVERHEAT_DELAY	0x61
+typedef struct {
+	__u16	delay;
+} overhead_delay_t;
+ 
+#define SET_MP_DELAY
+typedef struct {
+	__u16	delay;
+	__u8	reserved[510];
+} mp_delay_t;
+
+#define PASSTHRU_A	0x91
+typedef struct {
+	__u8	target;
+	__u8	bus;
+	__u8	lun;
+	__u32	timeout;
+	__u32	flags;
+	__u8	status;
+	__u8	error;
+	__u8	cdb_len;
+	__u8	sense_error;
+	__u8	sense_key;
+	__u32	sense_info;
+	__u8	sense_code;
+	__u8	sense_qual;
+	__u8	residual;
+	__u8	reserved[4];
+	__u8	cdb[12];	
+} scsi_param_t;
+
+#define RESUME_BACKGROUND_ACTIVITY	0x99
+#pragma pack()	
+
+#endif /* ARRAYCMD_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ida_ioctl.h linux.pre11.3/drivers/block/ida_ioctl.h
--- linux.vanilla/drivers/block/ida_ioctl.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/ida_ioctl.h	Tue Jul 20 01:53:07 1999
@@ -0,0 +1,83 @@
+/*
+ *    Disk Array driver for Compaq SMART2 Controllers
+ *    Copyright 1998 Compaq Computer Corporation
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to arrays@compaq.com
+ *
+ *    If you want to make changes, improve or add functionality to this
+ *    driver, you'll probably need the Compaq Array Controller Interface
+ *    Specificiation (Document number ECG086/1198)
+ */
+#ifndef IDA_IOCTL_H
+#define IDA_IOCTL_H
+
+#include "ida_cmd.h"
+#include "cpqarray.h"
+
+#define IDAGETDRVINFO		0x27272828
+#define IDAPASSTHRU		0x28282929
+#define IDAGETCTLRSIG		0x29293030
+#define IDAREVALIDATEVOLS	0x30303131
+#define IDADRIVERVERSION	0x31313232
+
+/*
+ * Normally, the ioctl determines the logical unit for this command by
+ * the major,minor number of the fd passed to ioctl.  If you need to send
+ * a command to a different/nonexistant unit (such as during config), you
+ * can override the normal behavior by setting the unit valid bit. (Normally,
+ * it should be zero) The controller the command is sent to is still
+ * determined by the major number of the open device.
+ */
+
+#define UNITVALID	0x80
+typedef struct {
+	__u8	cmd;
+	__u8	rcode;
+	__u8	unit;
+	__u32	blk;
+	__u16	blk_cnt;
+
+/* currently, sg_cnt is assumed to be 1: only the 0th element of sg is used */
+	struct {
+		void	*addr;
+		size_t	size;
+	} sg[SG_MAX];
+	int	sg_cnt;
+
+	union ctlr_cmds {
+		drv_info_t		drv;
+		unsigned char		buf[512];
+
+		id_ctlr_t		id_ctlr;
+		drv_param_t		drv_param;
+		id_log_drv_t		id_log_drv;
+		id_log_drv_ext_t	id_log_drv_ext;
+		sense_log_drv_stat_t	sense_log_drv_stat;
+		id_phys_drv_t		id_phys_drv;
+		blink_drv_leds_t	blink_drv_leds;
+		sense_blink_leds_t	sense_blink_leds;
+		config_t		config;
+		reorder_log_drv_t	reorder_log_drv;
+		label_log_drv_t		label_log_drv;
+		surf_delay_t		surf_delay;
+		overhead_delay_t	overhead_delay;
+		mp_delay_t		mp_delay;
+		scsi_param_t		scsi_param;
+	} c;
+} ida_ioctl_t;
+
+#endif /* IDA_IOCTL_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-cd.c linux.pre11.3/drivers/block/ide-cd.c
--- linux.vanilla/drivers/block/ide-cd.c	Fri Apr 16 22:10:51 1999
+++ linux.pre11.3/drivers/block/ide-cd.c	Mon Jul 19 23:55:59 1999
@@ -2121,20 +2121,23 @@
 				 msf.cdmsf_frame0);
 
 		/* Make sure the TOC is up to date. */
-		stat = cdrom_read_toc (drive, NULL);
-		if (stat) return stat;
+		if (cmd != CDROMREADRAW) {
+			stat = cdrom_read_toc (drive, NULL);
+			if (stat) 
+				return stat;
 
-		toc = info->toc;
+			toc = info->toc;
 
-		if (lba < 0 || lba >= toc->capacity)
-			return -EINVAL;
+			if (lba < 0 || lba >= toc->capacity)
+				return -EINVAL;
+		}
 
 		buf = (char *) kmalloc (blocksize, GFP_KERNEL);
 		if (buf == NULL)
 			return -ENOMEM;
 
-		stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize,
-					 NULL);
+		stat = cdrom_read_block (drive, format, lba, 1, buf,
+					 blocksize, NULL);
 
 		if (stat == 0) {
 			if (cmd == CDROMREADMODE2) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-floppy.c linux.pre11.3/drivers/block/ide-floppy.c
--- linux.vanilla/drivers/block/ide-floppy.c	Mon Dec 28 23:09:41 1998
+++ linux.pre11.3/drivers/block/ide-floppy.c	Mon Jul 19 23:55:59 1999
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/block/ide-floppy.c	Version 0.8		Dec   7, 1997
+ * linux/drivers/block/ide-floppy.c	Version 0.9		Jul   4, 1999
  *
- * Copyright (C) 1996, 1997 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
  */
 
 /*
@@ -26,9 +26,12 @@
  *                       Issue START command only if TEST UNIT READY fails.
  *                       Add work-around for IOMEGA ZIP revision 21.D.
  *                       Remove idefloppy_get_capabilities().
+ * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
+ *                        bytes requested on each interrupt to be zero.
+ *                        Thanks to <shanos@es.co.nz> for pointing this out.
  */
 
-#define IDEFLOPPY_VERSION "0.8"
+#define IDEFLOPPY_VERSION "0.9"
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -1001,7 +1004,7 @@
 	pc->retries++;
 	pc->actually_transferred=0;					/* We haven't transferred any data yet */
 	pc->current_position=pc->buffer;
-	bcount.all=pc->request_transfer;				/* Request to transfer the entire buffer at once */
+	bcount.all = IDE_MIN(pc->request_transfer, 63 * 1024);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) {
@@ -1524,9 +1527,19 @@
 	floppy->pc = floppy->pc_stack;
 	if (gcw.drq_type == 1)
 		set_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
-	if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0 &&
-	    ((strcmp(drive->id->fw_rev, "21.D") == 0) ||
-	     (strcmp(drive->id->fw_rev, "23.D") == 0))) {
+	/*
+	 *	We used to check revisions here. At this point however
+	 *	I'm giving up. Just assume they are all broken, its easier.
+	 *
+	 *	The actual reason for the workarounds was likely
+	 *	a driver bug after all rather than a firmware bug,
+	 *	and the workaround below used to hide it. It should
+	 *	be fixed as of version 1.9, but to be on the safe side
+	 *	we'll leave the limitation below for the 2.2.x tree.
+	 */
+
+	if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0)
+	{
 		for (i = 0; i < 1 << PARTN_BITS; i++)
 			max_sectors[major][minor + i] = 64;
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide-tape.c linux.pre11.3/drivers/block/ide-tape.c
--- linux.vanilla/drivers/block/ide-tape.c	Sat Jan  9 21:50:36 1999
+++ linux.pre11.3/drivers/block/ide-tape.c	Mon Jul 19 23:55:59 1999
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/block/ide-tape.c	Version 1.14		Dec  30, 1998
+ * linux/drivers/block/ide-tape.c	Version 1.15		Jul   4, 1999
  *
- * Copyright (C) 1995 - 1998 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
  *
  * This driver was constructed as a student project in the software laboratory
  * of the faculty of electrical engineering in the Technion - Israel's
@@ -214,6 +214,9 @@
  * Ver 1.13  Jan  2 98   Add "speed == 0" work-around for HP COLORADO 5GB
  * Ver 1.14  Dec 30 98   Partial fixes for the Sony/AIWA tape drives.
  *                       Replace cli()/sti() with hwgroup spinlocks.
+ * Ver 1.15  Mar 25 99   Fix SMP race condition by replacing hwgroup
+ *                        spinlock with private per-tape spinlock.
+ *                       Fix use of freed memory.
  *
  * Here are some words from the first releases of hd.c, which are quoted
  * in ide.c and apply here as well:
@@ -693,6 +696,7 @@
 	int excess_bh_size;			/* Wasted space in each stage */
 
 	unsigned int flags;			/* Status/Action flags */
+	spinlock_t spinlock;			/* protects the ide-tape queue */
 } idetape_tape_t;
 
 /*
@@ -1439,7 +1443,7 @@
 #if IDETAPE_DEBUG_LOG
 	printk (KERN_INFO "Reached idetape_add_stage_tail\n");
 #endif /* IDETAPE_DEBUG_LOG */
-	spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+	spin_lock_irqsave(&tape->spinlock, flags);
 	stage->next=NULL;
 	if (tape->last_stage != NULL)
 		tape->last_stage->next=stage;
@@ -1450,7 +1454,7 @@
 		tape->next_stage=tape->last_stage;
 	tape->nr_stages++;
 	tape->nr_pending_stages++;
-	spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+	spin_unlock_irqrestore(&tape->spinlock, flags);
 }
 
 /*
@@ -1552,7 +1556,9 @@
 	ide_drive_t *drive = hwgroup->drive;
 	struct request *rq = hwgroup->rq;
 	idetape_tape_t *tape = drive->driver_data;
+	unsigned long flags;
 	int error;
+	int remove_stage = 0;
 
 #if IDETAPE_DEBUG_LOG
 	printk (KERN_INFO "Reached idetape_end_request\n");
@@ -1567,6 +1573,7 @@
 	if (error)
 		tape->failed_pc = NULL;
 
+	spin_lock_irqsave(&tape->spinlock, flags);
 	if (tape->active_data_request == rq) {		/* The request was a pipelined data transfer request */
 		tape->active_stage = NULL;
 		tape->active_data_request = NULL;
@@ -1577,7 +1584,7 @@
 				if (error == IDETAPE_ERROR_EOD)
 					idetape_abort_pipeline (drive);
 			}
-			idetape_remove_stage_head (drive);
+			remove_stage = 1;
 		}
 		if (tape->next_stage != NULL) {
 			idetape_active_next_stage (drive);
@@ -1595,6 +1602,9 @@
 			idetape_increase_max_pipeline_stages (drive);
 	}
 	ide_end_drive_cmd (drive, 0, 0);
+	if (remove_stage)
+		idetape_remove_stage_head (drive);
+	spin_unlock_irqrestore(&tape->spinlock, flags);
 }
 
 /*
@@ -2335,6 +2345,7 @@
 static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
 {
 	struct semaphore sem = MUTEX_LOCKED;
+	idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_BUGS
 	if (rq == NULL || !IDETAPE_RQ_CMD (rq->cmd)) {
@@ -2343,9 +2354,9 @@
 	}
 #endif /* IDETAPE_DEBUG_BUGS */
 	rq->sem = &sem;
-	spin_unlock(&HWGROUP(drive)->spinlock);
+	spin_unlock(&tape->spinlock);
 	down(&sem);
-	spin_lock_irq(&HWGROUP(drive)->spinlock);
+	spin_lock_irq(&tape->spinlock);
 }
 
 /*
@@ -2419,10 +2430,10 @@
 		 */
 		return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh));
 	}
-	spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+	spin_lock_irqsave(&tape->spinlock, flags);
 	if (tape->active_stage == tape->first_stage)
 		idetape_wait_for_request(drive, tape->active_data_request);
-	spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+	spin_unlock_irqrestore(&tape->spinlock, flags);
 
 	rq_ptr = &tape->first_stage->rq;
 	bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
@@ -2471,12 +2482,12 @@
 	 *	Pay special attention to possible race conditions.
 	 */
 	while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
-		spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+		spin_lock_irqsave(&tape->spinlock, flags);
 		if (idetape_pipeline_active (tape)) {
 			idetape_wait_for_request(drive, tape->active_data_request);
-			spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+			spin_unlock_irqrestore(&tape->spinlock, flags);
 		} else {
-			spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+			spin_unlock_irqrestore(&tape->spinlock, flags);
 			idetape_insert_pipeline_into_queue (drive);
 			if (idetape_pipeline_active (tape))
 				continue;
@@ -2533,11 +2544,11 @@
 	if (tape->first_stage == NULL)
 		return;
 
-	spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+	spin_lock_irqsave(&tape->spinlock, flags);
 	tape->next_stage = NULL;
 	if (idetape_pipeline_active (tape))
 		idetape_wait_for_request(drive, tape->active_data_request);
-	spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+	spin_unlock_irqrestore(&tape->spinlock, flags);
 
 	while (tape->first_stage != NULL)
 		idetape_remove_stage_head (drive);
@@ -2557,7 +2568,7 @@
 	if (!idetape_pipeline_active (tape))
 		idetape_insert_pipeline_into_queue (drive);
 
-	spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+	spin_lock_irqsave(&tape->spinlock, flags);
 	if (!idetape_pipeline_active (tape))
 		goto abort;
 #if IDETAPE_DEBUG_BUGS
@@ -2567,7 +2578,7 @@
 #endif /* IDETAPE_DEBUG_BUGS */
 	idetape_wait_for_request(drive, &tape->last_stage->rq);
 abort:
-	spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+	spin_unlock_irqrestore(&tape->spinlock, flags);
 }
 
 static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
@@ -2812,10 +2823,10 @@
 			 *	Wait until the first read-ahead request
 			 *	is serviced.
 			 */
-			spin_lock_irqsave(&HWGROUP(drive)->spinlock, flags);
+			spin_lock_irqsave(&tape->spinlock, flags);
 			if (tape->active_stage == tape->first_stage)
 				idetape_wait_for_request(drive, tape->active_data_request);
-			spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
+			spin_unlock_irqrestore(&tape->spinlock, flags);
 
 			if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
 				count++;
@@ -3559,6 +3570,8 @@
 	u16 speed;
 	struct idetape_id_gcw gcw;
 
+	memset (tape, 0, sizeof (idetape_tape_t));
+	tape->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED;
 	drive->driver_data = tape;
 	drive->ready_stat = 0;			/* An ATAPI device ignores DRDY */
 	drive->dsc_overlap = 1;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ide.c linux.pre11.3/drivers/block/ide.c
--- linux.vanilla/drivers/block/ide.c	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/block/ide.c	Mon Jul 19 23:55:59 1999
@@ -1416,6 +1416,17 @@
 	hwgroup->handler = NULL;
 	(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
 	del_timer(&(hwgroup->timer));
+	{
+		struct request *rq;
+		unsigned long block, sectors;
+
+		if ((rq = hwgroup->rq) != NULL) {
+			block = rq->sector;
+			block += drive->part[MINOR(rq->rq_dev)&PARTN_MASK].start_sect + drive->sect0;
+			sectors = drive->using_dma ? rq->nr_sectors : drive->mult_count ? drive->mult_count : 1;
+		}
+	}
+
 	spin_unlock_irqrestore(&hwgroup->spinlock, flags);
 	if (drive->unmask)
 		ide__sti();	/* local CPU only */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/ll_rw_blk.c linux.pre11.3/drivers/block/ll_rw_blk.c
--- linux.vanilla/drivers/block/ll_rw_blk.c	Wed Mar 24 10:55:15 1999
+++ linux.pre11.3/drivers/block/ll_rw_blk.c	Tue Jul 20 00:35:18 1999
@@ -108,6 +108,11 @@
  */
 int * max_sectors[MAX_BLKDEV] = { NULL, NULL, };
 
+/*
+ * Max number of segments per request
+ */
+int * max_segments[MAX_BLKDEV] = { NULL, NULL, };
+
 static inline int get_max_sectors(kdev_t dev)
 {
 	if (!max_sectors[MAJOR(dev)])
@@ -115,6 +120,13 @@
 	return max_sectors[MAJOR(dev)][MINOR(dev)];
 }
 
+static inline int get_max_segments(kdev_t dev)
+{
+	if (!max_segments[MAJOR(dev)])
+		return MAX_SEGMENTS;
+	return max_segments[MAJOR(dev)][MINOR(dev)];
+}
+
 /*
  * Is called with the request spinlock aquired.
  * NOTE: the device-specific queue() functions
@@ -266,7 +278,7 @@
 }
 
 static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
-                                   short disk_index)
+				   short disk_index)
 {
 	kstat.dk_drive[disk_index]++;
 	if (cmd == READ) {
@@ -291,24 +303,31 @@
 
 void add_request(struct blk_dev_struct * dev, struct request * req)
 {
+	int major = MAJOR(req->rq_dev);
+	int minor = MINOR(req->rq_dev);
 	struct request * tmp, **current_request;
 	short		 disk_index;
 	unsigned long flags;
 	int queue_new_request = 0;
 
-	switch (MAJOR(req->rq_dev)) {
+	switch (major) {
+		case DAC960_MAJOR+0:
+			disk_index = (minor & 0x00f8) >> 3;
+			if (disk_index < 4)
+				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
+			break;
 		case SCSI_DISK0_MAJOR:
-			disk_index = (MINOR(req->rq_dev) & 0x00f0) >> 4;
+			disk_index = (minor & 0x00f0) >> 4;
 			if (disk_index < 4)
 				drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 			break;
 		case IDE0_MAJOR:	/* same as HD_MAJOR */
 		case XT_DISK_MAJOR:
-			disk_index = (MINOR(req->rq_dev) & 0x0040) >> 6;
+			disk_index = (minor & 0x0040) >> 6;
 			drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 			break;
 		case IDE1_MAJOR:
-			disk_index = ((MINOR(req->rq_dev) & 0x0040) >> 6) + 2;
+			disk_index = ((minor & 0x0040) >> 6) + 2;
 			drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
 		default:
 			break;
@@ -346,8 +365,12 @@
 	tmp->next = req;
 
 /* for SCSI devices, call request_fn unconditionally */
-	if (scsi_blk_major(MAJOR(req->rq_dev)))
+	if (scsi_blk_major(major) ||
+            (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7) ||
+            (major >= COMPAQ_SMART2_MAJOR+0 &&
+             major <= COMPAQ_SMART2_MAJOR+7))
 		queue_new_request = 1;
+
 out:
 	if (queue_new_request)
 		(dev->request_fn)();
@@ -357,29 +380,39 @@
 /*
  * Has to be called with the request spinlock aquired
  */
-static inline void attempt_merge (struct request *req, int max_sectors)
+static inline void attempt_merge (struct request *req,
+				  int max_sectors,
+				  int max_segments)
 {
 	struct request *next = req->next;
+	int total_segments;
 
 	if (!next)
 		return;
 	if (req->sector + req->nr_sectors != next->sector)
 		return;
-	if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors)
+	if (next->sem || req->cmd != next->cmd || req->rq_dev != next->rq_dev ||
+	    req->nr_sectors + next->nr_sectors > max_sectors)
+		return;
+	total_segments = req->nr_segments + next->nr_segments;
+	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
+		total_segments--;
+	if (total_segments > max_segments)
 		return;
 	req->bhtail->b_reqnext = next->bh;
 	req->bhtail = next->bhtail;
 	req->nr_sectors += next->nr_sectors;
+	req->nr_segments = total_segments;
 	next->rq_status = RQ_INACTIVE;
 	req->next = next->next;
 	wake_up (&wait_for_request);
 }
 
-void make_request(int major,int rw, struct buffer_head * bh)
+void make_request(int major, int rw, struct buffer_head * bh)
 {
 	unsigned int sector, count;
 	struct request * req;
-	int rw_ahead, max_req, max_sectors;
+	int rw_ahead, max_req, max_sectors, max_segments;
 	unsigned long flags;
 
 	count = bh->b_size >> 9;
@@ -397,15 +430,20 @@
 
 		if (maxsector < count || maxsector - count < sector) {
 			bh->b_state &= (1 << BH_Lock);
-                        /* This may well happen - the kernel calls bread()
-                           without checking the size of the device, e.g.,
-                           when mounting a device. */
+			/* This may well happen - the kernel calls bread()
+			   without checking the size of the device, e.g.,
+			   when mounting a device. */
 			printk(KERN_INFO
-                               "attempt to access beyond end of device\n");
+			       "attempt to access beyond end of device\n");
 			printk(KERN_INFO "%s: rw=%d, want=%d, limit=%d\n",
-                               kdevname(bh->b_rdev), rw,
-                               (sector + count)>>1,
-                               blk_size[major][MINOR(bh->b_rdev)]);
+			       kdevname(bh->b_rdev), rw,
+			       (sector + count)>>1,
+			       blk_size[major][MINOR(bh->b_rdev)]);
+			printk(KERN_INFO "dev %s blksize=%d blocknr=%ld sector=%ld size=%ld count=%d\n",
+				kdevname(bh->b_dev),
+				blksize_size[major][MINOR(bh->b_dev)],
+				bh->b_blocknr, bh->b_rsector, bh->b_size, bh->b_count);
+							
 			goto end_io;
 		}
 	}
@@ -437,13 +475,13 @@
 			break;
 		default:
 			printk(KERN_ERR "make_request: bad block dev cmd,"
-                               " must be R/W/RA/WA\n");
+			       " must be R/W/RA/WA\n");
 			goto end_io;
 	}
 
 /* look for a free request. */
        /* Loop uses two requests, 1 for loop and 1 for the real device.
-        * Cut max_req in half to avoid running out and deadlocking. */
+	* Cut max_req in half to avoid running out and deadlocking. */
 	 if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
 	     max_req >>= 1;
 
@@ -451,6 +489,7 @@
 	 * Try to coalesce the new request with old requests
 	 */
 	max_sectors = get_max_sectors(bh->b_rdev);
+	max_segments = get_max_segments(bh->b_rdev);
 
 	/*
 	 * Now we acquire the request spinlock, we have to be mega careful
@@ -497,6 +536,22 @@
 	     case SCSI_DISK6_MAJOR:
 	     case SCSI_DISK7_MAJOR:
 	     case SCSI_CDROM_MAJOR:
+	     case DAC960_MAJOR+0:
+	     case DAC960_MAJOR+1:
+	     case DAC960_MAJOR+2:
+	     case DAC960_MAJOR+3:
+	     case DAC960_MAJOR+4:
+	     case DAC960_MAJOR+5:
+	     case DAC960_MAJOR+6:
+	     case DAC960_MAJOR+7:
+	     case COMPAQ_SMART2_MAJOR+0:
+	     case COMPAQ_SMART2_MAJOR+1:
+	     case COMPAQ_SMART2_MAJOR+2:
+	     case COMPAQ_SMART2_MAJOR+3:
+	     case COMPAQ_SMART2_MAJOR+4:
+	     case COMPAQ_SMART2_MAJOR+5:
+	     case COMPAQ_SMART2_MAJOR+6:
+	     case COMPAQ_SMART2_MAJOR+7:
 
 		do {
 			if (req->sem)
@@ -509,13 +564,25 @@
 				continue;
 			/* Can we add it to the end of this request? */
 			if (req->sector + req->nr_sectors == sector) {
+				if (req->bhtail->b_data + req->bhtail->b_size
+				    != bh->b_data) {
+					if (req->nr_segments < max_segments)
+						req->nr_segments++;
+					else continue;
+				}
 				req->bhtail->b_reqnext = bh;
 				req->bhtail = bh;
 			    	req->nr_sectors += count;
 				/* Can we now merge this req with the next? */
-				attempt_merge(req, max_sectors);
+				attempt_merge(req, max_sectors, max_segments);
 			/* or to the beginning? */
 			} else if (req->sector - count == sector) {
+				if (bh->b_data + bh->b_size
+				    != req->bh->b_data) {
+					if (req->nr_segments < max_segments)
+						req->nr_segments++;
+					else continue;
+				}
 			    	bh->b_reqnext = req->bh;
 			    	req->bh = bh;
 			    	req->buffer = bh->b_data;
@@ -549,6 +616,7 @@
 	req->errors = 0;
 	req->sector = sector;
 	req->nr_sectors = count;
+	req->nr_segments = 1;
 	req->current_nr_sectors = count;
 	req->buffer = bh->b_data;
 	req->sem = NULL;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/loop.c linux.pre11.3/drivers/block/loop.c
--- linux.vanilla/drivers/block/loop.c	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/block/loop.c	Mon Jul 19 23:56:58 1999
@@ -27,7 +27,13 @@
  * - Should use an own CAP_* category instead of CAP_SYS_ADMIN 
  * - Should use the underlying filesystems/devices read function if possible
  *   to support read ahead (and for write)
- */
+ *
+ * WARNING/FIXME:
+ * - The block number as IV passing to low level transfer functions is broken:
+ *   it passes the underlying device's block number instead of the
+ *   offset. This makes it change for a given block when the file is 
+ *   moved/restored/copied and also doesn't work over NFS. 
+ */ 
 
 #include <linux/module.h>
 
@@ -107,7 +113,7 @@
 
 static int xor_status(struct loop_device *lo, struct loop_info *info)
 {
-	if (info->lo_encrypt_key_size < 0)
+	if (info->lo_encrypt_key_size <= 0)
 		return -EINVAL;
 	return 0;
 }
@@ -369,6 +375,10 @@
 		   a file structure */
 		lo->lo_backing_file = NULL;
 	} else if (S_ISREG(inode->i_mode)) {
+		if (!inode->i_op->bmap) { 
+			printk(KERN_ERR "loop: device has no block access/not implemented\n");
+			goto out_putf;
+		}
 
 		/* Backed by a regular file - we need to hold onto
 		   a file structure for this file.  We'll use it to
@@ -504,8 +514,6 @@
 	if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE)
 		return -EINVAL;
 	type = info.lo_encrypt_type; 
-	if (info.lo_encrypt_key_size == 0 && type == LO_CRYPT_XOR)
-		return -EINVAL;
 	if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL)
 		return -EINVAL;
 	err = loop_release_xfer(lo);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/nbd.c linux.pre11.3/drivers/block/nbd.c
--- linux.vanilla/drivers/block/nbd.c	Wed Mar 24 10:55:15 1999
+++ linux.pre11.3/drivers/block/nbd.c	Mon Jul 19 23:27:39 1999
@@ -401,7 +401,7 @@
 		return 0;
 	case NBD_SET_SIZE_BLOCKS:
 		nbd_sizes[dev] = arg;
-		nbd_bytesizes[dev] = arg << nbd_blksize_bits[dev];
+		nbd_bytesizes[dev] = ((u64) arg) << nbd_blksize_bits[dev];
 		return 0;
 	case NBD_DO_IT:
 		if (!lo->file)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/rd.c linux.pre11.3/drivers/block/rd.c
--- linux.vanilla/drivers/block/rd.c	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/block/rd.c	Mon Jul 19 23:57:15 1999
@@ -517,7 +517,7 @@
 	}
 
 	if (nblocks > (rd_length[unit] >> RDBLK_SIZE_BITS)) {
-		printk("RAMDISK: image too big! (%d/%d blocks)\n",
+		printk("RAMDISK: image too big! (%d/%ld blocks)\n",
 		       nblocks, rd_length[unit] >> RDBLK_SIZE_BITS);
 		goto done;
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/block/smart1,2.h linux.pre11.3/drivers/block/smart1,2.h
--- linux.vanilla/drivers/block/smart1,2.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/block/smart1,2.h	Mon Jul 19 23:57:15 1999
@@ -0,0 +1,274 @@
+/*
+ *    Disk Array driver for Compaq SMART2 Controllers
+ *    Copyright 1998 Compaq Computer Corporation
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the 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, GOOD TITLE or
+ *    NON INFRINGEMENT.  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.
+ *
+ *    Questions/Comments/Bugfixes to arrays@compaq.com
+ *
+ *    If you want to make changes, improve or add functionality to this
+ *    driver, you'll probably need the Compaq Array Controller Interface
+ *    Specificiation (Document number ECG086/1198)
+ */
+
+/*
+ * This file contains the controller communication implementation for
+ * Compaq SMART-1 and SMART-2 controllers.  To the best of my knowledge,
+ * this should support:
+ *
+ *  PCI:
+ *  SMART-2/P, SMART-2DH, SMART-2SL, SMART-221, SMART-3100ES, SMART-3200
+ *  Integerated SMART Array Controller, SMART-4200, SMART-4250ES
+ *
+ *  EISA:
+ *  SMART-2/E, SMART, IAES, IDA-2, IDA
+ */
+
+/*
+ * Memory mapped FIFO interface (SMART 42xx cards)
+ */
+static void smart4_submit_command(ctlr_info_t *h, cmdlist_t *c)
+{
+        writel(c->busaddr, h->vaddr + S42XX_REQUEST_PORT_OFFSET);
+}
+
+/*  
+ *  This card is the oposite of the other cards.  
+ *   0 turns interrupts on... 
+ *   0x08 turns them off... 
+ */
+static void smart4_intr_mask(ctlr_info_t *h, unsigned long val)
+{
+	if (val) 
+	{ /* Turn interrupts on */
+		writel(0, h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
+	} else /* Turn them off */
+	{
+        	writel( S42XX_INTR_OFF, 
+			h->vaddr + S42XX_REPLY_INTR_MASK_OFFSET);
+	}
+}
+
+/*
+ *  For this card fifo is full if reading this port returns 0! 
+ * 
+ */ 
+static unsigned long smart4_fifo_full(ctlr_info_t *h)
+{
+	
+        return (~readl(h->vaddr + S42XX_REQUEST_PORT_OFFSET));
+}
+
+/* This type of controller returns -1 if the fifo is empty, 
+ *    Not 0 like the others.
+ *    And we need to let it know we read a value out 
+ */ 
+static unsigned long smart4_completed(ctlr_info_t *h)
+{
+	long register_value 
+		= readl(h->vaddr + S42XX_REPLY_PORT_OFFSET);
+
+	/* Fifo is empty */
+	if( register_value == -1)
+		return 0; 	
+
+	/* Need to let it know we got the reply */
+	/* We do this by writing a 0 to the port we just read from */
+	writel(0, h->vaddr + S42XX_REPLY_PORT_OFFSET);
+
+	return ((unsigned long) register_value); 
+}
+
+ /*
+ *  This hardware returns interrupt pending at a different place and 
+ *  it does not tell us if the fifo is empty, we will have check  
+ *  that by getting a 0 back from the comamnd_completed call. 
+ */
+static unsigned long smart4_intr_pending(ctlr_info_t *h)
+{
+	unsigned long register_value  = 
+		readl(h->vaddr + S42XX_INTR_STATUS);
+
+	if( register_value &  S42XX_INTR_PENDING) 
+		return  FIFO_NOT_EMPTY;	
+	return 0 ;
+}
+
+static struct access_method smart4_access = {
+	smart4_submit_command,
+	smart4_intr_mask,
+	smart4_fifo_full,
+	smart4_intr_pending,
+	smart4_completed,
+};
+
+/*
+ * Memory mapped FIFO interface (PCI SMART2 and SMART 3xxx cards)
+ */
+static void smart2_submit_command(ctlr_info_t *h, cmdlist_t *c)
+{
+	writel(c->busaddr, h->vaddr + COMMAND_FIFO);
+}
+
+static void smart2_intr_mask(ctlr_info_t *h, unsigned long val)
+{
+	writel(val, h->vaddr + INTR_MASK);
+}
+
+static unsigned long smart2_fifo_full(ctlr_info_t *h)
+{
+	return readl(h->vaddr + COMMAND_FIFO);
+}
+
+static unsigned long smart2_completed(ctlr_info_t *h)
+{
+	return readl(h->vaddr + COMMAND_COMPLETE_FIFO);
+}
+
+static unsigned long smart2_intr_pending(ctlr_info_t *h)
+{
+	return readl(h->vaddr + INTR_PENDING);
+}
+
+static struct access_method smart2_access = {
+	smart2_submit_command,
+	smart2_intr_mask,
+	smart2_fifo_full,
+	smart2_intr_pending,
+	smart2_completed,
+};
+
+/*
+ *  IO access for SMART-2/E cards
+ */
+static void smart2e_submit_command(ctlr_info_t *h, cmdlist_t *c)
+{
+	outl(c->busaddr, h->ioaddr + COMMAND_FIFO);
+}
+
+static void smart2e_intr_mask(ctlr_info_t *h, unsigned long val)
+{
+	outl(val, h->ioaddr + INTR_MASK);
+}
+
+static unsigned long smart2e_fifo_full(ctlr_info_t *h)
+{
+	return inl(h->ioaddr + COMMAND_FIFO);
+}
+
+static unsigned long smart2e_completed(ctlr_info_t *h)
+{
+	return inl(h->ioaddr + COMMAND_COMPLETE_FIFO);
+}
+
+static unsigned long smart2e_intr_pending(ctlr_info_t *h)
+{
+	return inl(h->ioaddr + INTR_PENDING);
+}
+
+static struct access_method smart2e_access = {
+	smart2e_submit_command,
+	smart2e_intr_mask,
+	smart2e_fifo_full,
+	smart2e_intr_pending,
+	smart2e_completed,
+};
+
+/*
+ *  IO access for older SMART-1 type cards
+ */
+#define SMART1_SYSTEM_MASK		0xC8E
+#define SMART1_SYSTEM_DOORBELL		0xC8F
+#define SMART1_LOCAL_MASK		0xC8C
+#define SMART1_LOCAL_DOORBELL		0xC8D
+#define SMART1_INTR_MASK		0xC89
+#define SMART1_LISTADDR			0xC90
+#define SMART1_LISTLEN			0xC94
+#define SMART1_TAG			0xC97
+#define SMART1_COMPLETE_ADDR		0xC98
+#define SMART1_LISTSTATUS		0xC9E
+
+#define CHANNEL_BUSY			0x01
+#define CHANNEL_CLEAR			0x02
+
+static void smart1_submit_command(ctlr_info_t *h, cmdlist_t *c)
+{
+	/*
+	 * This __u16 is actually a bunch of control flags on SMART
+	 * and below.  We want them all to be zero.
+	 */
+	c->hdr.size = 0;
+
+	outb(CHANNEL_CLEAR, h->ioaddr + SMART1_SYSTEM_DOORBELL);
+
+	outl(c->busaddr, h->ioaddr + SMART1_LISTADDR);
+	outw(c->size, h->ioaddr + SMART1_LISTLEN);
+
+	outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
+}
+
+static void smart1_intr_mask(ctlr_info_t *h, unsigned long val)
+{
+	if (val == 1) {
+		outb(0xFD, h->ioaddr + SMART1_SYSTEM_DOORBELL);
+		outb(CHANNEL_BUSY, h->ioaddr + SMART1_LOCAL_DOORBELL);
+		outb(0x01, h->ioaddr + SMART1_INTR_MASK);
+		outb(0x01, h->ioaddr + SMART1_SYSTEM_MASK);
+	} else {
+		outb(0, h->ioaddr + 0xC8E);
+	}
+}
+
+static unsigned long smart1_fifo_full(ctlr_info_t *h)
+{
+	unsigned char chan;
+	chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_CLEAR;
+	return chan;
+}
+
+static unsigned long smart1_completed(ctlr_info_t *h)
+{
+	unsigned char status;
+	unsigned long cmd;
+
+	if (inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY) {
+		outb(CHANNEL_BUSY, h->ioaddr + SMART1_SYSTEM_DOORBELL);
+
+		cmd = inl(h->ioaddr + SMART1_COMPLETE_ADDR);
+		status = inb(h->ioaddr + SMART1_LISTSTATUS);
+
+		outb(CHANNEL_CLEAR, h->ioaddr + SMART1_LOCAL_DOORBELL);
+
+		if (cmd) ((cmdlist_t*)bus_to_virt(cmd))->req.hdr.rcode = status;
+	} else {
+		cmd = 0;
+	}
+	return cmd;
+}
+
+static unsigned long smart1_intr_pending(ctlr_info_t *h)
+{
+	unsigned char chan;
+	chan = inb(h->ioaddr + SMART1_SYSTEM_DOORBELL) & CHANNEL_BUSY;
+	return chan;
+}
+
+static struct access_method smart1_access = {
+	smart1_submit_command,
+	smart1_intr_mask,
+	smart1_fifo_full,
+	smart1_intr_pending,
+	smart1_completed,
+};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/cdrom/cdrom.c linux.pre11.3/drivers/cdrom/cdrom.c
--- linux.vanilla/drivers/cdrom/cdrom.c	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/cdrom/cdrom.c	Mon Jul 19 23:57:24 1999
@@ -1145,8 +1145,10 @@
 		   ((cdi->ops->capability & ~cdi->mask & CDC_PLAY_AUDIO)!=0));
 
         strcpy(cdrom_drive_info+pos,"\n\n");
-	*lenp=pos+3;
-
+	pos += 3;
+	if (*lenp > pos)
+		*lenp = pos;
+		
         return proc_dostring(ctl, write, filp, buffer, lenp);
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Config.in linux.pre11.3/drivers/char/Config.in
--- linux.vanilla/drivers/char/Config.in	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/char/Config.in	Mon Jul 19 23:27:49 1999
@@ -28,6 +28,9 @@
       tristate 'Digiboard PC/Xx Support' CONFIG_DIGI
    fi
    tristate 'Cyclades async mux support' CONFIG_CYCLADES
+   if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then
+      bool '  Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
+   fi
    bool 'Stallion multiport serial support' CONFIG_STALDRV
    if [ "$CONFIG_STALDRV" = "y" ]; then
      tristate '  Stallion EasyIO or EC8/32 support' CONFIG_STALLION
@@ -144,6 +147,11 @@
   dep_tristate 'SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
   if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
     hex '  SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
+  fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    if [ "$CONFIG_SGI" = "y" ]; then
+      dep_tristate 'SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV
+    fi
   fi
   dep_tristate 'Typhoon Radio (a.k.a. EcoRadio)' CONFIG_RADIO_TYPHOON $CONFIG_VIDEO_DEV
   if [ "$CONFIG_PROC_FS" = "y" ]; then
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/Makefile linux.pre11.3/drivers/char/Makefile
--- linux.vanilla/drivers/char/Makefile	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/char/Makefile	Mon Jul 19 23:27:49 1999
@@ -30,16 +30,30 @@
 
 ifeq ($(CONFIG_SERIAL),y)
   ifeq ($(CONFIG_SUN_SERIAL),)
-  LX_OBJS += serial.o
+    ifeq ($(CONFIG_SGI_SERIAL),)
+      ifeq ($(CONFIG_DECSTATION),)
+	ifeq ($(CONFIG_BAGET_MIPS),)
+      LX_OBJS += serial.o
+    endif
+  endif
+    endif
   endif
 else
   ifeq ($(CONFIG_SERIAL),m)
     ifeq ($(CONFIG_SUN_SERIAL),)
-    MX_OBJS += serial.o
+      ifeq ($(CONFIG_SGI_SERIAL),)
+        ifeq ($(CONFIG_DECSTATION),)
+          ifeq ($(CONFIG_BAGET_MIPS),)
+      MX_OBJS += serial.o
+      endif
+    endif
+  endif
     endif
   endif
 endif
 
+ifndef CONFIG_DECSTATION
+ifndef CONFIG_BAGET_MIPS
 ifndef CONFIG_SUN_KEYBOARD
 ifdef CONFIG_VT
 LX_OBJS += keyboard.o
@@ -57,6 +71,8 @@
 ifdef CONFIG_MAGIC_SYSRQ
 LX_OBJS += sysrq.o
 endif
+endif
+endif
 
 ifeq ($(CONFIG_ATARI_DSP56K),y)
 L_OBJS += dsp56k.o
@@ -362,6 +378,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_VIDEO_VINO),y)
+L_OBJS += vino.o
+else
+  ifeq ($(CONFIG_VIDEO_VINO),m)
+  M_OBJS += vino.o
+  endif
+endif
+
 ifeq ($(CONFIG_RADIO_AZTECH),y)
 L_OBJS += radio-aztech.o
 else
@@ -477,6 +501,10 @@
   MOD_SUB_DIRS += hfmodem
   endif
 
+endif
+
+ifeq ($(CONFIG_DZ),y)
+  L_OBJS += dz.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bttv.c linux.pre11.3/drivers/char/bttv.c
--- linux.vanilla/drivers/char/bttv.c	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/char/bttv.c	Mon Jul 19 23:57:53 1999
@@ -43,7 +43,6 @@
 #include <linux/types.h>
 #include <linux/wrapper.h>
 #include <linux/interrupt.h>
-#include <linux/version.h>
 
 #if LINUX_VERSION_CODE >= 0x020100
 #include <asm/uaccess.h>
@@ -81,8 +80,8 @@
 #include "bttv.h"
 #include "tuner.h"
 
-#define DEBUG(x) 		/* Debug driver */	
-#define IDEBUG(x) 		/* Debug interrupt handler */
+#define DEBUG(x)		/* Debug driver */	
+#define IDEBUG(x)		/* Debug interrupt handler */
 
 #if LINUX_VERSION_CODE >= 0x020117
 MODULE_PARM(vidmem,"i");
@@ -110,7 +109,7 @@
 #define CARD_DEFAULT 0
 #endif
 
-static unsigned int remap[BTTV_MAX];    /* remap Bt848 */
+static unsigned long remap[BTTV_MAX];    /* remap Bt848 */
 static unsigned int radio[BTTV_MAX];
 static unsigned int card[BTTV_MAX] = { CARD_DEFAULT, CARD_DEFAULT, 
                                        CARD_DEFAULT, CARD_DEFAULT };
@@ -129,51 +128,80 @@
 #define EEPROM_WRITE_DELAY    20000
 #define BURSTOFFSET 76
 
-
-
 /*******************************/
 /* Memory management functions */
 /*******************************/
 
-/* convert virtual user memory address to physical address */
-/* (virt_to_phys only works for kmalloced kernel memory) */
+#define MDEBUG(x)	do { } while(0)		/* Debug memory management */
+
+/* [DaveM] I've recoded most of this so that:
+ * 1) It's easier to tell what is happening
+ * 2) It's more portable, especially for translating things
+ *    out of vmalloc mapped areas in the kernel.
+ * 3) Less unnecessary translations happen.
+ *
+ * The code used to assume that the kernel vmalloc mappings
+ * existed in the page tables of every process, this is simply
+ * not guarenteed.  We now use pgd_offset_k which is the
+ * defined way to get at the kernel page tables.
+ */
 
-static inline unsigned long uvirt_to_phys(unsigned long adr)
+/* Given PGD from the address space's page table, return the kernel
+ * virtual mapping of the physical memory mapped at ADR.
+ */
+static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
 {
-	pgd_t *pgd;
+        unsigned long ret = 0UL;
 	pmd_t *pmd;
 	pte_t *ptep, pte;
   
-	pgd = pgd_offset(current->mm, adr);
-	if (pgd_none(*pgd))
-		return 0;
-	pmd = pmd_offset(pgd, adr);
-	if (pmd_none(*pmd))
-		return 0;
-	ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);
-	pte = *ptep;
-	if(pte_present(pte))
-		return 
-		  virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));
-	return 0;
+	if (!pgd_none(*pgd)) {
+                pmd = pmd_offset(pgd, adr);
+                if (!pmd_none(*pmd)) {
+                        ptep = pte_offset(pmd, adr);
+                        pte = *ptep;
+                        if(pte_present(pte))
+                                ret = (pte_page(pte)|(adr&(PAGE_SIZE-1)));
+                }
+        }
+        MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
+	return ret;
 }
 
 static inline unsigned long uvirt_to_bus(unsigned long adr) 
 {
-	return virt_to_bus(phys_to_virt(uvirt_to_phys(adr)));
-}
+        unsigned long kva, ret;
 
-/* convert virtual kernel memory address to physical address */
-/* (virt_to_phys only works for kmalloced kernel memory) */
+        kva = uvirt_to_kva(pgd_offset(current->mm, adr), adr);
+	ret = virt_to_bus((void *)kva);
+        MDEBUG(printk("uv2b(%lx-->%lx)", adr, ret));
+        return ret;
+}
 
-static inline unsigned long kvirt_to_phys(unsigned long adr) 
+static inline unsigned long kvirt_to_bus(unsigned long adr) 
 {
-	return uvirt_to_phys(VMALLOC_VMADDR(adr));
+        unsigned long va, kva, ret;
+
+        va = VMALLOC_VMADDR(adr);
+        kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = virt_to_bus((void *)kva);
+        MDEBUG(printk("kv2b(%lx-->%lx)", adr, ret));
+        return ret;
 }
 
-static inline unsigned long kvirt_to_bus(unsigned long adr) 
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
 {
-	return uvirt_to_bus(VMALLOC_VMADDR(adr));
+        unsigned long va, kva, ret;
+
+        va = VMALLOC_VMADDR(adr);
+        kva = uvirt_to_kva(pgd_offset_k(va), va);
+	ret = __pa(kva);
+        MDEBUG(printk("kv2pa(%lx-->%lx)", adr, ret));
+        return ret;
 }
 
 static void * rvmalloc(unsigned long size)
@@ -188,8 +216,8 @@
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
-	                page = kvirt_to_phys(adr);
-			mem_map_reserve(MAP_NR(phys_to_virt(page)));
+	                page = kvirt_to_pa(adr);
+			mem_map_reserve(MAP_NR(__va(page)));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -206,8 +234,8 @@
 	        adr=(unsigned long) mem;
 		while (size > 0) 
                 {
-	                page = kvirt_to_phys(adr);
-			mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+	                page = kvirt_to_pa(adr);
+			mem_map_unreserve(MAP_NR(__va(page)));
 			adr+=PAGE_SIZE;
 			size-=PAGE_SIZE;
 		}
@@ -541,13 +569,15 @@
         /* Aimslab VHX */
         { 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4}},
         /* Zoltrix TV-Max */
-        { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
+        { 3, 1, 0, 2, 0x00000f, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0x8}},
         /* Pixelview PlayTV (bt878) */
         { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }},
         /* "Leadtek WinView 601", */
         { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}},
         /* AVEC Intercapture */
         { 3, 1, 9, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}},
+       /* LifeView FlyKit w/o Tuner */
+       { 3, 1, -1, 2, 0xc00, { 0, 3, 1, 1}}
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -823,30 +853,30 @@
 	unsigned int *po=(unsigned int *) btv->vbi_odd;
 	unsigned int *pe=(unsigned int *) btv->vbi_even;
   
-	DEBUG(printk(KERN_DEBUG "vbiodd: 0x%08x\n",(int)btv->vbi_odd));
-	DEBUG(printk(KERN_DEBUG "vbievn: 0x%08x\n",(int)btv->vbi_even));
-	DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));
-	DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));
+	DEBUG(printk(KERN_DEBUG "vbiodd: 0x%lx\n",(long)btv->vbi_odd));
+	DEBUG(printk(KERN_DEBUG "vbievn: 0x%lx\n",(long)btv->vbi_even));
+	DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po));
+	DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe));
         
-	*(po++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(po++)=0;
+	*(po++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(po++)=0;
 	for (i=0; i<16; i++) 
 	{
-		*(po++)=VBI_RISC;
-		*(po++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048);
+		*(po++)=cpu_to_le32(VBI_RISC);
+		*(po++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));
 	}
-	*(po++)=BT848_RISC_JUMP;
-	*(po++)=virt_to_bus(btv->risc_jmp+4);
+	*(po++)=cpu_to_le32(BT848_RISC_JUMP);
+	*(po++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));
 
-	*(pe++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(pe++)=0;
+	*(pe++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(pe++)=0;
 	for (i=16; i<32; i++) 
 	{
-		*(pe++)=VBI_RISC;
-		*(pe++)=kvirt_to_bus((unsigned long)btv->vbibuf+i*2048);
+		*(pe++)=cpu_to_le32(VBI_RISC);
+		*(pe++)=cpu_to_le32(kvirt_to_bus((unsigned long)btv->vbibuf+i*2048));
 	}
-	*(pe++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16);
-	*(pe++)=virt_to_bus(btv->risc_jmp+10);
-	DEBUG(printk(KERN_DEBUG "po: 0x%08x\n",(int)po));
-	DEBUG(printk(KERN_DEBUG "pe: 0x%08x\n",(int)pe));
+	*(pe++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(0x01<<16));
+	*(pe++)=cpu_to_le32(virt_to_bus(btv->risc_jmp+10));
+	DEBUG(printk(KERN_DEBUG "po: 0x%lx\n",(long)po));
+	DEBUG(printk(KERN_DEBUG "pe: 0x%lx\n",(long)pe));
 }
 
 int fmtbppx2[16] = {
@@ -881,8 +911,8 @@
 	unsigned long bpl=1024;		/* bytes per line */
 	unsigned long vadr=(unsigned long) vbuf;
 
-	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
-	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
+	*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0;
+	*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0;
   
         /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY
            is 2 and without separate VBI grabbing.
@@ -890,17 +920,17 @@
 
 	for (line=0; line < 640; line++)
 	{
-                *(ro++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL;
-                *(ro++)=kvirt_to_bus(vadr);
-                *(re++)=BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL;
-                *(re++)=kvirt_to_bus(vadr+BTTV_MAX_FBUF/2);
+                *(ro++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);
+                *(ro++)=cpu_to_le32(kvirt_to_bus(vadr));
+                *(re++)=cpu_to_le32(BT848_RISC_WRITE|bpl|BT848_RISC_SOL|BT848_RISC_EOL);
+                *(re++)=cpu_to_le32(kvirt_to_bus(vadr+BTTV_MAX_FBUF/2));
                 vadr+=bpl;
 	}
 	
-	*(ro++)=BT848_RISC_JUMP;
-	*(ro++)=btv->bus_vbi_even;
-	*(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
-	*(re++)=btv->bus_vbi_odd;
+	*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
+	*(ro++)=cpu_to_le32(btv->bus_vbi_even);
+	*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
+	*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 	
 	return 0;
 }
@@ -954,8 +984,8 @@
 	cradr=cbadr+csize;
 	inter = (height>btv->win.cropheight/2) ? 1 : 0;
 	
-	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(ro++)=0;
-	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3; *(re++)=0;
+	*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(ro++)=0;
+	*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM3); *(re++)=0;
   
 	for (line=0; line < (height<<(1^inter)); line++)
 	{
@@ -991,15 +1021,15 @@
 		 todo-=bl;
 		 if(!todo) rcmd|=BT848_RISC_EOL; /* if this is the last EOL */
 		 
-		 *((*rp)++)=rcmd|bl;
-		 *((*rp)++)=blcb|(blcr<<16);
-		 *((*rp)++)=kvirt_to_bus(vadr);
+		 *((*rp)++)=cpu_to_le32(rcmd|bl);
+		 *((*rp)++)=cpu_to_le32(blcb|(blcr<<16));
+		 *((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));
 		 vadr+=bl;
 		 if((rcmd&(15<<28))==BT848_RISC_WRITE123)
 		 {
-		 	*((*rp)++)=kvirt_to_bus(cbadr);
+		 	*((*rp)++)=cpu_to_le32(kvirt_to_bus(cbadr));
 		 	cbadr+=blcb;
-		 	*((*rp)++)=kvirt_to_bus(cradr);
+		 	*((*rp)++)=cpu_to_le32(kvirt_to_bus(cradr));
 		 	cradr+=blcr;
 		 }
 		 
@@ -1007,10 +1037,10 @@
 		}
 	}
 	
-	*(ro++)=BT848_RISC_JUMP;
-	*(ro++)=btv->bus_vbi_even;
-	*(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
-	*(re++)=btv->bus_vbi_odd;
+	*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
+	*(ro++)=cpu_to_le32(btv->bus_vbi_even);
+	*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
+	*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 	
 	return 0;
 }
@@ -1037,8 +1067,8 @@
 	inter = (height>btv->win.cropheight/2) ? 1 : 0;
 	bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2;
 	
-	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
-	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
+	*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0;
+	*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0;
   
 	for (line=0; line < (height<<(1^inter)); line++)
 	{
@@ -1050,35 +1080,35 @@
 		bl=PAGE_SIZE-((PAGE_SIZE-1)&vadr);
 		if (bpl<=bl)
                 {
-		        *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_SOL|
-			        BT848_RISC_EOL|bpl; 
-			*((*rp)++)=kvirt_to_bus(vadr);
+		        *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|
+                                               BT848_RISC_EOL|bpl);
+			*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));
 			vadr+=bpl;
 		}
 		else
 		{
 		        todo=bpl;
-		        *((*rp)++)=BT848_RISC_WRITE|BT848_RISC_SOL|bl;
-			*((*rp)++)=kvirt_to_bus(vadr);
+		        *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|bl);
+			*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));
 			vadr+=bl;
 			todo-=bl;
 			while (todo>PAGE_SIZE)
 			{
-			        *((*rp)++)=BT848_RISC_WRITE|PAGE_SIZE;
-				*((*rp)++)=kvirt_to_bus(vadr);
+			        *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE);
+				*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));
 				vadr+=PAGE_SIZE;
 				todo-=PAGE_SIZE;
 			}
-			*((*rp)++)=BT848_RISC_WRITE|BT848_RISC_EOL|todo;
-			*((*rp)++)=kvirt_to_bus(vadr);
+			*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo);
+			*((*rp)++)=cpu_to_le32(kvirt_to_bus(vadr));
 			vadr+=todo;
 		}
 	}
 	
-	*(ro++)=BT848_RISC_JUMP;
-	*(ro++)=btv->bus_vbi_even;
-	*(re++)=BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16);
-	*(re++)=btv->bus_vbi_odd;
+	*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
+	*(ro++)=cpu_to_le32(btv->bus_vbi_even);
+	*(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16));
+	*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 	
 	return 0;
 }
@@ -1162,10 +1192,10 @@
 	adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
 	if ((clipmap=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) {
 		/* can't clip, don't generate any risc code */
-		*(ro++)=BT848_RISC_JUMP;
-		*(ro++)=btv->bus_vbi_even;
-		*(re++)=BT848_RISC_JUMP;
-		*(re++)=btv->bus_vbi_odd;
+		*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
+		*(ro++)=cpu_to_le32(btv->bus_vbi_even);
+		*(re++)=cpu_to_le32(BT848_RISC_JUMP);
+		*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 	}
 	if (ncr < 0) {	/* bitmap was pased */
 		memcpy(clipmap, (unsigned char *)cr, VIDEO_CLIPMAP_SIZE);
@@ -1187,8 +1217,8 @@
 	if (btv->win.y<0)
 		clip_draw_rectangle(clipmap, 0, 0, 1024, -(btv->win.y));
 	
-	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
-	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
+	*(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(ro++)=0;
+	*(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); *(re++)=0;
 	
 	/* translate bitmap to risc code */
         for (line=outofmem=0; line < (height<<inter) && !outofmem; line++)
@@ -1206,10 +1236,10 @@
 				flags |= ((!sx) ? BT848_RISC_SOL : 0);
 				flags |= ((sx + dx == width) ? BT848_RISC_EOL : 0);
 				if (!lastbit) {
-					*((*rp)++)=BT848_RISC_WRITE|flags|len;
-					*((*rp)++)=adr + bpp * sx;
+					*((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|flags|len);
+					*((*rp)++)=cpu_to_le32(adr + bpp * sx);
 				} else
-					*((*rp)++)=BT848_RISC_SKIP|flags|len;
+					*((*rp)++)=cpu_to_le32(BT848_RISC_SKIP|flags|len);
 				lastbit=cbit;
 				sx += dx;
 				dx = 1;
@@ -1224,10 +1254,10 @@
 	}
 	vfree(clipmap);
 	/* outofmem flag relies on the following code to discard extra data */
-	*(ro++)=BT848_RISC_JUMP;
-	*(ro++)=btv->bus_vbi_even;
-	*(re++)=BT848_RISC_JUMP;
-	*(re++)=btv->bus_vbi_odd;
+	*(ro++)=cpu_to_le32(BT848_RISC_JUMP);
+	*(ro++)=cpu_to_le32(btv->bus_vbi_even);
+	*(re++)=cpu_to_le32(BT848_RISC_JUMP);
+	*(re++)=cpu_to_le32(btv->bus_vbi_odd);
 }
 
 /* set geometry for even/odd frames 
@@ -1297,6 +1327,23 @@
         set_pll(btv);
 
 	btwrite(fmt, BT848_COLOR_FMT);
+#ifdef __sparc__
+        if(fmt == BT848_COLOR_FMT_RGB32 ||
+           fmt == BT848_COLOR_FMT_RGB24) {
+                btwrite((BT848_COLOR_CTL_GAMMA		|
+                         BT848_COLOR_CTL_WSWAP_ODD	|
+                         BT848_COLOR_CTL_WSWAP_EVEN	|
+                         BT848_COLOR_CTL_BSWAP_ODD	|
+                         BT848_COLOR_CTL_BSWAP_EVEN),
+                        BT848_COLOR_CTL);
+        } else if(fmt == BT848_COLOR_FMT_RGB16 ||
+           fmt == BT848_COLOR_FMT_RGB15) {
+                btwrite((BT848_COLOR_CTL_GAMMA		|
+                         BT848_COLOR_CTL_BSWAP_ODD	|
+                         BT848_COLOR_CTL_BSWAP_EVEN),
+                        BT848_COLOR_CTL);
+        }
+#endif
 	hactive=width;
 
         vtc=0;
@@ -1474,7 +1521,7 @@
 			btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI);
 			btor(BT848_VSCALE_COMB, BT848_O_VSCALE_HI);
 		}
-		btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
+		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
         }
 	btor(3, BT848_CAP_CTL);
 	btor(3, BT848_GPIO_DMA_CTL);
@@ -1661,12 +1708,13 @@
 			struct video_capability b;
 			strcpy(b.name,btv->video_dev.name);
 			b.type = VID_TYPE_CAPTURE|
-			 	VID_TYPE_TUNER|
 				VID_TYPE_TELETEXT|
 				VID_TYPE_OVERLAY|
 				VID_TYPE_CLIPPING|
 				VID_TYPE_FRAMERAM|
-				VID_TYPE_SCALES;
+				VID_TYPE_SCALES|
+				((tvcards[btv->type].tuner != -1)
+					? VID_TYPE_TUNER : 0);
 			b.channels = tvcards[btv->type].video_inputs;
 			b.audios = tvcards[btv->type].audio_inputs;
 			b.maxwidth = tvnorms[btv->win.norm].swidth;
@@ -2268,7 +2316,7 @@
 	pos=(unsigned long) btv->fbuffer;
 	while (size > 0) 
 	{
-	        page = kvirt_to_phys(pos);
+	        page = kvirt_to_pa(pos);
 		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
 		        return -EAGAIN;
 		start+=PAGE_SIZE;
@@ -3110,44 +3158,44 @@
 	int flags=btv->cap;
 
 	/* Sync to start of odd field */
-	btv->risc_jmp[0]=BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRE;
+	btv->risc_jmp[0]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRE);
 	btv->risc_jmp[1]=0;
 
 	/* Jump to odd vbi sub */
-	btv->risc_jmp[2]=BT848_RISC_JUMP|(0x5<<20);
+	btv->risc_jmp[2]=cpu_to_le32(BT848_RISC_JUMP|(0x5<<20));
 	if (flags&8)
-		btv->risc_jmp[3]=virt_to_bus(btv->vbi_odd);
+		btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->vbi_odd));
 	else
-		btv->risc_jmp[3]=virt_to_bus(btv->risc_jmp+4);
+		btv->risc_jmp[3]=cpu_to_le32(virt_to_bus(btv->risc_jmp+4));
 
         /* Jump to odd sub */
-	btv->risc_jmp[4]=BT848_RISC_JUMP|(0x6<<20);
+	btv->risc_jmp[4]=cpu_to_le32(BT848_RISC_JUMP|(0x6<<20));
 	if (flags&2)
-		btv->risc_jmp[5]=virt_to_bus(btv->risc_odd);
+		btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_odd));
 	else
-		btv->risc_jmp[5]=virt_to_bus(btv->risc_jmp+6);
+		btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_jmp+6));
 
 
 	/* Sync to start of even field */
-	btv->risc_jmp[6]=BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRO;
+	btv->risc_jmp[6]=cpu_to_le32(BT848_RISC_SYNC|BT848_RISC_RESYNC|BT848_FIFO_STATUS_VRO);
 	btv->risc_jmp[7]=0;
 
 	/* Jump to even vbi sub */
-	btv->risc_jmp[8]=BT848_RISC_JUMP;
+	btv->risc_jmp[8]=cpu_to_le32(BT848_RISC_JUMP);
 	if (flags&4)
-		btv->risc_jmp[9]=virt_to_bus(btv->vbi_even);
+		btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->vbi_even));
 	else
-		btv->risc_jmp[9]=virt_to_bus(btv->risc_jmp+10);
+		btv->risc_jmp[9]=cpu_to_le32(virt_to_bus(btv->risc_jmp+10));
 
 	/* Jump to even sub */
-	btv->risc_jmp[10]=BT848_RISC_JUMP|(8<<20);
+	btv->risc_jmp[10]=cpu_to_le32(BT848_RISC_JUMP|(8<<20));
 	if (flags&1)
-		btv->risc_jmp[11]=virt_to_bus(btv->risc_even);
+		btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_even));
 	else
-		btv->risc_jmp[11]=virt_to_bus(btv->risc_jmp+12);
+		btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12));
 
-	btv->risc_jmp[12]=BT848_RISC_JUMP;
-	btv->risc_jmp[13]=virt_to_bus(btv->risc_jmp);
+	btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
+	btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp));
 
 	/* enable capturing */
 	btaor(flags, ~0x0f, BT848_CAP_CTL);
@@ -3165,7 +3213,7 @@
 
 	/* reset the bt848 */
 	btwrite(0, BT848_SRESET);
-	DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem));
+	DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n",i,(unsigned long) btv->bt848_mem));
 
 	/* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
 	btv->win.norm=0; /* change this to 1 for NTSC, 2 for SECAM */
@@ -3330,8 +3378,7 @@
 		if (!astat)
 			return;
 		btwrite(astat,BT848_INT_STAT);
-		IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat));
-		IDEBUG(printk ("bttv%d:  stat %08x\n", btv->nr, stat));
+		IDEBUG(printk ("bttv%d: astat %08x stat %08x\n", btv->nr, astat, stat));
 
 		/* get device status bits */
 		dstat=btread(BT848_DSTATUS);
@@ -3387,8 +3434,8 @@
 					btv->gro = btv->gro_next;
 					btv->gre = btv->gre_next;
 					btv->grf = btv->grf_next;
-                                        btv->risc_jmp[5]=btv->gro;
-					btv->risc_jmp[11]=btv->gre;
+                                        btv->risc_jmp[5]=cpu_to_le32(btv->gro);
+					btv->risc_jmp[11]=cpu_to_le32(btv->gre);
 					bt848_set_geo(btv, btv->gwidth,
 						      btv->gheight,
 						      btv->gfmt);
@@ -3405,9 +3452,9 @@
 			}
 			if (stat&(8<<28)) 
 			{
-			        btv->risc_jmp[5]=btv->gro;
-				btv->risc_jmp[11]=btv->gre;
-				btv->risc_jmp[12]=BT848_RISC_JUMP;
+			        btv->risc_jmp[5]=cpu_to_le32(btv->gro);
+				btv->risc_jmp[11]=cpu_to_le32(btv->gre);
+				btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
 				bt848_set_geo(btv, btv->gwidth, btv->gheight,
 					      btv->gfmt);
 			}
@@ -3502,14 +3549,16 @@
 
         if (remap[bttv_num])
         {
+                unsigned int dw = btv->bt848_adr;
+
                 if (remap[bttv_num] < 0x1000)
                         remap[bttv_num]<<=20;
                 remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK;
-                printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n",
+                printk(KERN_INFO "bttv%d: remapping to : 0x%lx.\n",
                        bttv_num,remap[bttv_num]);
                 remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
                 pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, remap[bttv_num]);
-                pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr);
+                pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dw);
                 btv->dev->base_address[0] = btv->bt848_adr;
         }					
         btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
@@ -3518,7 +3567,7 @@
                bttv_num,btv->id, btv->revision);
         printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn);
         printk("irq: %d, ",btv->irq);
-        printk("memory: 0x%08x.\n", btv->bt848_adr);
+        printk("memory: 0x%lx.\n", btv->bt848_adr);
 
         btv->pll.pll_crystal = 0;
         btv->pll.pll_ifreq   = 0;
@@ -3542,7 +3591,11 @@
                 }
         }
         
+#ifdef __sparc__
+        btv->bt848_mem=(unsigned char *)btv->bt848_adr;
+#else
         btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
+#endif
         
         /* clear interrupt mask */
 	btwrite(0, BT848_INT_MASK);
@@ -3817,17 +3870,17 @@
 		if (btv->risc_even)
 			kfree((void *) btv->risc_even);
 
-		DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%08x.\n", btv->risc_jmp));
+		DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp));
 		if (btv->risc_jmp)
 			kfree((void *) btv->risc_jmp);
 
-		DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%08x.\n", btv->vbibuf));
+		DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf));
 		if (btv->vbibuf)
 			vfree((void *) btv->vbibuf);
 
 
 		free_irq(btv->irq,btv);
-		DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%08x.\n", btv->bt848_mem));
+		DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem));
 		if (btv->bt848_mem)
 			iounmap(btv->bt848_mem);
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bttv.h linux.pre11.3/drivers/char/bttv.h
--- linux.vanilla/drivers/char/bttv.h	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/char/bttv.h	Tue Jul 20 01:56:13 1999
@@ -102,9 +102,9 @@
 #else
 	struct pci_dev *dev;
 #endif
-	unsigned char irq;          /* IRQ used by Bt848 card */
+	unsigned int irq;           /* IRQ used by Bt848 card */
 	unsigned char revision;
-	unsigned int bt848_adr;      /* bus address of IO mem returned by PCI BIOS */
+	unsigned long bt848_adr;    /* bus address of IO mem returned by PCI BIOS */
 	unsigned char *bt848_mem;   /* pointer to mapped IO memory */
 	unsigned long busriscmem; 
 	u32 *riscmem;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/bw-qcam.c linux.pre11.3/drivers/char/bw-qcam.c
--- linux.vanilla/drivers/char/bw-qcam.c	Mon Mar 29 10:25:55 1999
+++ linux.pre11.3/drivers/char/bw-qcam.c	Mon Jul 19 23:58:05 1999
@@ -159,6 +159,8 @@
 	struct qcam_device *q;
 	
 	q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
+	if(q==NULL)
+		return NULL;
 
 	q->pport = port;
 	q->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/c-qcam.c linux.pre11.3/drivers/char/c-qcam.c
--- linux.vanilla/drivers/char/c-qcam.c	Tue Dec 22 23:19:37 1998
+++ linux.pre11.3/drivers/char/c-qcam.c	Mon Jul 19 23:58:05 1999
@@ -641,6 +641,8 @@
 	struct qcam_device *q;
 	
 	q = kmalloc(sizeof(struct qcam_device), GFP_KERNEL);
+	if(q==NULL)
+		return NULL;
 
 	q->pport = port;
 	q->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/cyclades.c linux.pre11.3/drivers/char/cyclades.c
--- linux.vanilla/drivers/char/cyclades.c	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/char/cyclades.c	Mon Jul 19 23:27:49 1999
@@ -1,7 +1,7 @@
 #define BLOCKMOVE
 #define	Z_WAKE
 static char rcsid[] =
-"$Revision: 2.2.2.2 $$Date: 1999/05/21 17:18:15 $";
+"$Revision: 2.2.2.3 $$Date: 1999/06/28 11:13:29 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -31,6 +31,16 @@
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.2.2.3   1999/06/28 11:13:29 ivan
+ * Added support for interrupt mode operation for the Z cards;
+ * Removed the driver inactivity control for the Z;
+ * Added a missing MOD_DEC_USE_COUNT in the cy_open function for when 
+ * the Z firmware is not loaded yet;
+ * Replaced the "manual" Z Tx flush buffer by a call to a FW command of 
+ * same functionality;
+ * Implemented workaround for IRQ setting loss on the PCI configuration 
+ * registers after a PCI bridge EEPROM reload (affects PLX9060 only);
+ *
  * Revision 2.2.2.2  1999/05/14 17:18:15 ivan
  * /proc entry location changed to /proc/tty/driver/cyclades;
  * Added support to shared IRQ's (only for PCI boards);
@@ -528,7 +538,7 @@
    constant in the definition below. No other change is necessary to
    support more boards/ports. */
 
-#define NR_PORTS        128
+#define NR_PORTS        256
 
 #define ZE_V1_NPORTS	64
 #define ZO_V1	0
@@ -810,13 +820,15 @@
 #ifndef CONFIG_COBALT_27
 static void cy_probe(int, void *, struct pt_regs *);
 #endif /* CONFIG_COBALT_27 */
-static void cyz_poll(unsigned long);
 #ifdef CYCLOM_SHOW_STATUS
 static void show_status(int);
 #endif
 
 static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *);
 
+#ifndef CONFIG_CYZ_INTR
+static void cyz_poll(unsigned long);
+
 /* The Cyclades-Z polling cycle is defined by this variable */
 static long cyz_polling_cycle = CZ_DEF_POLL;
 
@@ -825,6 +837,7 @@
 cyz_timerlist = {
     NULL, NULL, 0, 0, cyz_poll
 };
+#endif /* CONFIG_CYZ_INTR */
 
 /**************************************************
 error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
@@ -1197,7 +1210,7 @@
 
     if((cinfo = (struct cyclades_card *)dev_id) == 0){
 #ifdef CY_DEBUG_INTERRUPTS
-	printk("cy_interrupt: spurious interrupt %d\n\r", irq);
+	printk("cyy_interrupt: spurious interrupt %d\n\r", irq);
 #endif
         return; /* spurious interrupt */
     }
@@ -1229,7 +1242,7 @@
                 }
                 if (status & CySRReceive) { /* reception interrupt */
 #ifdef CY_DEBUG_INTERRUPTS
-		    printk("cy_interrupt: rcvd intr, chip %d\n\r", chip);
+		    printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip);
 #endif
                     /* determine the channel & change to that context */
                     save_xir = (u_char) cy_readb(base_addr+(CyRIR<<index));
@@ -1287,7 +1300,7 @@
 							    TTY_OVERRUN;
                                         *tty->flip.char_buf_ptr++ = 0;
                                         /* If the flip buffer itself is
-                                           overflowing, we still loose
+                                           overflowing, we still lose
                                            the next incoming character.
                                          */
                                         if(tty->flip.count
@@ -1356,7 +1369,7 @@
                        is empty, we know we can always stuff a dozen
                        characters. */
 #ifdef CY_DEBUG_INTERRUPTS
-		    printk("cy_interrupt: xmit intr, chip %d\n\r", chip);
+		    printk("cyy_interrupt: xmit intr, chip %d\n\r", chip);
 #endif
 
                     /* determine the channel & change to that context */
@@ -1636,12 +1649,285 @@
 } /* cyz_update_channel */
 #endif
 
-
+#ifdef CONFIG_CYZ_INTR
 static void
 cyz_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+  struct tty_struct *tty;
+  struct cyclades_card *cinfo;
+  struct cyclades_port *info;
+  static volatile struct FIRM_ID *firm_id;
+  static volatile struct ZFW_CTRL *zfw_ctrl;
+  static volatile struct BOARD_CTRL *board_ctrl;
+  static volatile struct CH_CTRL *ch_ctrl;
+  static volatile struct BUF_CTRL *buf_ctrl;
+  uclong channel;
+  ucchar cmd;
+  uclong param;
+  uclong hw_ver, fw_ver;
+  char data;
+  volatile int char_count, special_count;
+#ifdef BLOCKMOVE
+  int small_count;
+#endif
+  volatile uclong tx_put, tx_get, tx_bufsize;
+  volatile uclong rx_put, rx_get, rx_bufsize;
+
+    if((cinfo = (struct cyclades_card *)dev_id) == 0){
+#ifdef CY_DEBUG_INTERRUPTS
+	printk("cyz_interrupt: spurious interrupt %d\n\r", irq);
+#endif
+        return; /* spurious interrupt */
+    }
+
+	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+        if (!ISZLOADED(*cinfo)) {
+#ifdef CY_DEBUG_INTERRUPTS
+	    printk("cyz_interrupt: board not yet loaded (INT %d).\n\r", irq);
+#endif
+	    return;
+	}
+
+	zfw_ctrl = (struct ZFW_CTRL *)
+	           (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
+	board_ctrl = &(zfw_ctrl->board_ctrl);
+	fw_ver = cy_readl(&board_ctrl->fw_version);
+	hw_ver = cy_readl(&((struct RUNTIME_9060 *)
+                            (cinfo->ctl_addr))->mail_box_0);
+
+	while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
+	    special_count = 0;
+	    info = &cy_port[channel + cinfo->first_line];
+            if((tty = info->tty) == 0) continue;
+	    ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
+	    buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
+
+	    switch(cmd){
+	    case C_CM_PR_ERROR:
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+		*tty->flip.char_buf_ptr++ = 0;
+		special_count++;
+	        break;
+	    case C_CM_FR_ERROR:
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+		*tty->flip.char_buf_ptr++ = 0;
+		special_count++;
+	        break;
+	    case C_CM_RXBRK:
+		tty->flip.count++;
+		*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+		*tty->flip.char_buf_ptr++ = 0;
+		special_count++;
+	        break;
+	    case C_CM_MDCD:
+		if (info->flags & ASYNC_CHECK_CD){
+		    if ((fw_ver > 241 ? 
+                          ((u_long)param) : 
+                          cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
+			/* SP("Open Wakeup\n"); */
+			cy_sched_event(info,
+			    Cy_EVENT_OPEN_WAKEUP);
+		    }else if(!((info->flags
+				& ASYNC_CALLOUT_ACTIVE)
+			 &&(info->flags
+			    & ASYNC_CALLOUT_NOHUP))){
+			/* SP("Hangup\n"); */
+			cy_sched_event(info,
+			    Cy_EVENT_HANGUP);
+		    }
+		}
+	        break;
+	    case C_CM_MCTS:
+		if (info->flags & ASYNC_CTS_FLOW) {
+		    if(info->tty->hw_stopped){
+			if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){
+			    /* cy_start isn't used because... 
+			       HW flow is handled by the board */
+			    /* SP("Write Wakeup\n"); */
+			    cy_sched_event(info,
+				Cy_EVENT_WRITE_WAKEUP);
+			}
+		    }else{
+			if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){
+			    /* cy_stop isn't used because 
+			       HW flow is handled by the board */
+			    /* SP("Write stop\n"); */
+			}
+		    }
+		}
+	        break;
+	    case C_CM_MRI:
+	        break;
+	    case C_CM_MDSR:
+	        break;
+#ifdef Z_WAKE
+	    case C_CM_IOCTLW:
+		cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
+	        break;
+#endif
+	    case C_CM_RXHIWM:
+	    case C_CM_RXNNDT:
+		/* Reception Interrupt */
+#ifdef CY_DEBUG_INTERRUPTS
+	    printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", 
+		info->card, channel);
+#endif
+
+	    rx_get = cy_readl(&buf_ctrl->rx_get);
+	    rx_put = cy_readl(&buf_ctrl->rx_put);
+	    rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+	    if (rx_put >= rx_get)
+	    	char_count = rx_put - rx_get;
+	    else
+	    	char_count = rx_put - rx_get + rx_bufsize;
+
+	    if ( char_count ){
+
+#ifdef CY_ENABLE_MONITORING
+		info->mon.int_count++;
+		info->mon.char_count += char_count;
+		if (char_count > info->mon.char_max)
+		   info->mon.char_max = char_count;
+		info->mon.char_last = char_count;
+#endif
+		info->idle_stats.recv_bytes += char_count;
+		info->idle_stats.recv_idle   = jiffies;
+		if( tty == 0){
+		    /* flush received characters */
+		    rx_get = (rx_get + char_count) & (rx_bufsize - 1);
+		    /* SP("-"); */
+		    info->rflush_count++;
+		}else{
+#ifdef BLOCKMOVE
+		/* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+		   for performance, but because of buffer boundaries, there
+		   may be several steps to the operation */
+		    while(0 < (small_count
+			= cy_min((rx_bufsize - rx_get),
+			         cy_min((TTY_FLIPBUF_SIZE - tty->flip.count),
+				        char_count)))){
+
+			memcpy_fromio(tty->flip.char_buf_ptr,
+			              (char *)(cinfo->base_addr
+				       + cy_readl(&buf_ctrl->rx_bufaddr)
+				       + rx_get),
+			              small_count);
+
+			tty->flip.char_buf_ptr += small_count;
+			memset(tty->flip.flag_buf_ptr,
+			       TTY_NORMAL,
+			       small_count);
+			tty->flip.flag_buf_ptr += small_count;
+			rx_get = (rx_get + small_count) & (rx_bufsize - 1);
+			char_count -= small_count;
+			tty->flip.count += small_count;
+		    }
+#else
+		    while(char_count--){
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE){
+				break;
+			}
+			data = cy_readb(cinfo->base_addr +
+			           cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
+			rx_get = (rx_get + 1) & (rx_bufsize - 1);
+			tty->flip.count++;
+			*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+			*tty->flip.char_buf_ptr++ = data;
+		    }
+#endif
+		    queue_task(&tty->flip.tqueue, &tq_timer);
+		}
+		/* Update rx_get */
+		cy_writel(&buf_ctrl->rx_get, rx_get);
+	    }
+		break;
+	    case C_CM_TXBEMPTY:
+	    case C_CM_TXLOWWM:
+	    case C_CM_INTBACK:
+		/* Transmission Interrupt */
+#ifdef CY_DEBUG_INTERRUPTS
+	    printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", 
+		info->card, channel);
+#endif
+
+	    tx_get = cy_readl(&buf_ctrl->tx_get);
+	    tx_put = cy_readl(&buf_ctrl->tx_put);
+	    tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+	    if (tx_put >= tx_get)
+	    	char_count = tx_get - tx_put - 1 + tx_bufsize;
+	    else
+	    	char_count = tx_get - tx_put - 1;
+
+	    if ( char_count ){
+
+		if( tty == 0 ){
+		    goto ztxdone;
+		}
+
+		if(info->x_char) { /* send special char */
+		    data = info->x_char;
+
+		    cy_writeb((cinfo->base_addr +
+		              cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
+		    tx_put = (tx_put + 1) & (tx_bufsize - 1);
+		    info->x_char = 0;
+		    char_count--;
+		}
+#ifdef BLOCKMOVE
+		while(0 < (small_count
+		    = cy_min((tx_bufsize - tx_put),
+			     cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
+			             cy_min(info->xmit_cnt, char_count))))){
+
+		    memcpy_toio((char *)(cinfo->base_addr
+			         + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
+			        &info->xmit_buf[info->xmit_tail],
+			        small_count);
+
+		    tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+		    char_count -= small_count;
+		    info->xmit_cnt -= small_count;
+		    info->xmit_tail =
+		       (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1);
+		}
+#else
+		while (info->xmit_cnt && char_count){
+		    data = info->xmit_buf[info->xmit_tail];
+		    info->xmit_cnt--;
+		    info->xmit_tail =
+			(info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+
+		    cy_writeb(cinfo->base_addr +
+		              cy_readl(&buf_ctrl->tx_bufaddr) + tx_put, 
+			      data);
+		    tx_put = (tx_put + 1) & (tx_bufsize - 1);
+		    char_count--;
+		}
+
+#endif
+	    ztxdone:
+		if (info->xmit_cnt < WAKEUP_CHARS) {
+		    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
+		}
+		/* Update tx_put */
+		cy_writel(&buf_ctrl->tx_put, tx_put);
+	    }
+		break;
+	    case C_CM_FATAL:
+		/* should do something with this !!! */
+	        break;
+	    }
+	    if(special_count){
+		queue_task(&tty->flip.tqueue, &tq_timer);
+	    }
+	}
+
+    return;
 } /* cyz_interrupt */
 
+#else /* CONFIG_CYZ_INTR */
 
 static void
 cyz_poll(unsigned long arg)
@@ -1675,7 +1961,6 @@
 
 	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
         if (!ISZLOADED(*cinfo)) {
-	    cinfo->inact_ctrl = 0;
 	    continue;
 	}
 
@@ -1686,12 +1971,6 @@
 	hw_ver = cy_readl(&((struct RUNTIME_9060 *)
                             (cinfo->ctl_addr))->mail_box_0);
 
-	/* Enables the firmware inactivity control */
-	if ((fw_ver > 0x00000310L) && (!cinfo->inact_ctrl)) {
-	    param = cyz_issue_cmd( &cy_card[card], 0L, C_CM_TINACT, 0L);
-	    cinfo->inact_ctrl = 1;
-	}
-
 	while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1){
 	    char_count = 0;
 	    info = &cy_port[ channel + cinfo->first_line ];
@@ -1922,17 +2201,13 @@
 	}
 	/* poll every 40 ms */
 	cyz_timerlist.expires = jiffies + cyz_polling_cycle;
-
-	/* refresh inactivity counter */
-	if (cinfo->inact_ctrl) {
-		cy_writel(&board_ctrl->inactivity, (uclong) ZF_TINACT);
-	}
     }
     add_timer(&cyz_timerlist);
 
     return;
 } /* cyz_poll */
 
+#endif /* CONFIG_CYZ_INTR */
 
 /********** End of block of Cyclades-Z specific code *********/
 /***********************************************************/
@@ -2053,12 +2328,27 @@
 
 	cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE);
 #ifdef Z_WAKE
+#ifdef CONFIG_CYZ_INTR
 	cy_writel(&ch_ctrl[channel].intr_enable, 
-		  C_IN_MDCD|C_IN_MCTS|C_IN_IOCTLW);
+		  C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
+		  C_IN_IOCTLW|
+		  C_IN_MDCD|C_IN_MCTS);
 #else
 	cy_writel(&ch_ctrl[channel].intr_enable, 
+		  C_IN_IOCTLW|
 		  C_IN_MDCD|C_IN_MCTS);
-#endif
+#endif /* CONFIG_CYZ_INTR */
+#else
+#ifdef CONFIG_CYZ_INTR
+	cy_writel(&ch_ctrl[channel].intr_enable, 
+		  C_IN_TXBEMPTY|C_IN_TXLOWWM|C_IN_RXHIWM|C_IN_RXNNDT|
+		  C_IN_MDCD|C_IN_MCTS);
+#else
+	cy_writel(&ch_ctrl[channel].intr_enable, 
+		  C_IN_MDCD|C_IN_MCTS);
+#endif /* CONFIG_CYZ_INTR */
+#endif /* Z_WAKE */
+
 	retval = cyz_issue_cmd( &cy_card[card],
 	    channel, C_CM_IOCTL, 0L);	/* was C_CM_RESET */
 	if (retval != 0){
@@ -2126,11 +2416,21 @@
                cy_readb(base_addr+(CySRER<<index)) | CyTxMpty);
 	restore_flags(flags);
     } else {
+#ifdef CONFIG_CYZ_INTR
+      int retval;
+
+	save_flags(flags); cli();
+	    retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L);
+	    if (retval != 0){
+		printk("cyc:start_xmit retval was %x\n", retval);
+	    }
+	restore_flags(flags);
+#else /* CONFIG_CYZ_INTR */
 	/* Don't have to do anything at this time */
+#endif /* CONFIG_CYZ_INTR */
     }
 } /* start_xmit */
 
-
 /*
  * This routine shuts down a serial port; interrupts are disabled,
  * and DTR is dropped if the hangup on close termio flag is on.
@@ -2504,8 +2804,24 @@
 	    } else {
 		printk("cyc:Cyclades-Z firmware not yet loaded\n");
 	    }
+	    MOD_DEC_USE_COUNT;
 	    return -ENODEV;
 	}
+#ifdef CONFIG_CYZ_INTR
+	else {
+	    /* In case this Z board is operating in interrupt mode, its 
+	       interrupts should be enabled as soon as the first open happens 
+	       to one of its ports. */
+	    if (!cy_card[info->card].intr_enabled) {
+		retval = cyz_issue_cmd(&cy_card[info->card], 
+					0, C_CM_IRQ_ENBL, 0L);
+		if (retval != 0){
+		    printk("cyc:IRQ enable retval was %x\n", retval);
+		}
+		cy_card[info->card].intr_enabled = 1;
+	    }
+	}
+#endif /* CONFIG_CYZ_INTR */
     }
 #ifdef CY_DEBUG_OTHER
     printk("cyc:cy_open ttyC%d\n", info->line); /* */
@@ -3798,14 +4114,14 @@
 	if (break_state == -1) {
 	    if (!info->breakon) {
 		info->breakon = 1;
-		if (!info->xmit_cnt ) {
+		if (!info->xmit_cnt) {
 		    start_xmit(info);
 		}
 	    }
 	} else {
 	    if (!info->breakoff) {
 		info->breakoff = 1;
-		if (!info->xmit_cnt ) {
+		if (!info->xmit_cnt) {
 		    start_xmit(info);
 		}
 	    }
@@ -4053,6 +4369,7 @@
 	case CYGETCD1400VER:
 	    ret_val = info->chip_rev;
 	    break;
+#ifndef CONFIG_CYZ_INTR
 	case CYZSETPOLLCYCLE:
             cyz_polling_cycle = (arg * HZ) / 1000;
 	    ret_val = 0;
@@ -4060,6 +4377,7 @@
 	case CYZGETPOLLCYCLE:
             ret_val = (cyz_polling_cycle * 1000) / HZ;
 	    break;
+#endif /* CONFIG_CYZ_INTR */
 	case CYSETWAIT:
     	    info->closing_wait = (unsigned short)arg * HZ/100;
 	    ret_val = 0;
@@ -4333,7 +4651,7 @@
 cy_flush_buffer(struct tty_struct *tty)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
-  int card, channel;
+  int card, channel, retval;
   unsigned long flags;
                                 
 #ifdef CY_DEBUG_IO
@@ -4351,19 +4669,10 @@
 
     if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board 
 				      buffers as well */
-	static volatile struct FIRM_ID *firm_id;
-	static volatile struct ZFW_CTRL *zfw_ctrl;
-	static volatile struct CH_CTRL *ch_ctrl;
-	static volatile struct BUF_CTRL *buf_ctrl;
-
-	firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *) (cy_card[card].base_addr +
-				cy_readl(&firm_id->zfwctrl_addr));
-	ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]);
-	buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]);
-
-	while (cy_readl(&buf_ctrl->tx_get) != cy_readl(&buf_ctrl->tx_put))
-		cy_writel(&buf_ctrl->tx_put, cy_readl(&buf_ctrl->tx_get));
+	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
+	if (retval != 0) {
+	    printk("cyc: flush_buffer retval was %x\n", retval);
+	}
     }
     wake_up_interruptible(&tty->write_wait);
     if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
@@ -4872,10 +5181,11 @@
 		    return(i);
                 }
 
+#ifdef CONFIG_CYZ_INTR
                 /* allocate IRQ only if board has an IRQ */
-		if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) {
-		    if(request_irq(cy_pci_irq,cyz_interrupt,
-			SA_SHIRQ,"Cyclades-Z",&cy_card[j]))
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
+		    if(request_irq(cy_pci_irq, cyz_interrupt,
+			SA_SHIRQ, "Cyclades-Z", &cy_card[j]))
 		    {
 			printk("Could not allocate IRQ%d ",
 			    cy_pci_irq);
@@ -4884,6 +5194,7 @@
 			return(i);
 		    }
 		}
+#endif /* CONFIG_CYZ_INTR */
 
 
                 /* set cy_card */
@@ -4896,7 +5207,7 @@
 
                 /* print message */
 		/* don't report IRQ if board is no IRQ */
-		if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) {
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
 		    printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
 			j+1,(ulong)cy_pci_addr2,
 			(ulong)(cy_pci_addr2 + CyPCI_Zwin - 1),
@@ -4908,6 +5219,11 @@
 		}
                 printk("%d channels starting from port %d.\n",
 		    cy_pci_nchan,cy_next_channel);
+#ifdef CONFIG_CYZ_INTR
+		/* Enable interrupts on the PLX chip */
+		cy_writew(cy_pci_addr0+0x68,
+			cy_readw(cy_pci_addr0+0x68)|0x0900);
+#endif /* CONFIG_CYZ_INTR */
                 cy_next_channel += cy_pci_nchan;
     }
         }
@@ -4927,10 +5243,6 @@
                 (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
 	    printk("Cyclades-Z/PCI: New Cyclades-Z board.  FPGA not loaded\n");
 #endif
-	    /* The following clears the firmware id word.  This ensures
-	       that the driver will not attempt to talk to the board
-	       until it has been properly initialized.
-	     */
 		PAUSE
                 /* This must be the new Cyclades-Ze/PCI. */
                 cy_pci_nchan = ZE_V1_NPORTS;
@@ -4955,10 +5267,11 @@
 		    return(i);
                 }
 
+#ifdef CONFIG_CYZ_INTR
                 /* allocate IRQ only if board has an IRQ */
-		if( (1 < cy_pci_irq) && (cy_pci_irq < 15) ) {
-		    if(request_irq(cy_pci_irq,cyz_interrupt,
-			SA_SHIRQ,"Cyclades-Z",&cy_card[j]))
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
+		    if(request_irq(cy_pci_irq, cyz_interrupt,
+			SA_SHIRQ, "Cyclades-Z", &cy_card[j]))
 		    {
 			printk("Could not allocate IRQ%d ",
 			    cy_pci_irq);
@@ -4967,6 +5280,7 @@
 			return(i);
 		    }
 		}
+#endif /* CONFIG_CYZ_INTR */
 
                 /* set cy_card */
                 cy_card[j].base_addr = cy_pci_addr2;
@@ -4978,7 +5292,7 @@
 
                 /* print message */
 		/* don't report IRQ if board is no IRQ */
-		if( (cy_pci_irq < 15) && (cy_pci_irq > 1) ) {
+		if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) {
 		    printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
 			j+1,(ulong)cy_pci_addr2,
 			(ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1),
@@ -4990,6 +5304,11 @@
 		}
                 printk("%d channels starting from port %d.\n",
 		    cy_pci_nchan,cy_next_channel);
+#ifdef CONFIG_CYZ_INTR
+		/* Enable interrupts on the PLX chip */
+		cy_writew(cy_pci_addr0+0x68,
+			cy_readw(cy_pci_addr0+0x68)|0x0900);
+#endif /* CONFIG_CYZ_INTR */
                 cy_next_channel += cy_pci_nchan;
         }
 	if (ZeIndex != 0) {
@@ -5219,6 +5538,7 @@
 		mailbox = cy_readl(&((struct RUNTIME_9060 *)
 			     cy_card[board].ctl_addr)->mail_box_0);
 		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
+		cinfo->intr_enabled = 0;
                 for (port = cinfo->first_line ;
                      port < cinfo->first_line + nports;
                      port++)
@@ -5342,15 +5662,17 @@
                 }
             }
     }
-    
-    if ( number_z_boards && !cyz_timeron){
-        cyz_timeron++;
+
+#ifndef CONFIG_CYZ_INTR
+    if (number_z_boards && !cyz_timeron){
+	cyz_timeron++;
 	cyz_timerlist.expires = jiffies + 1;
 	add_timer(&cyz_timerlist);
 #ifdef CY_PCI_DEBUG
 	printk("Cyclades-Z polling initialized\n");
 #endif
     }
+#endif /* CONFIG_CYZ_INTR */
 
 #ifdef CY_PROC
         ent = create_proc_entry("cyclades", S_IFREG | S_IRUGO, 0);
@@ -5377,10 +5699,12 @@
     int e1, e2;
     unsigned long flags;
 
+#ifndef CONFIG_CYZ_INTR
     if (cyz_timeron){
 	cyz_timeron = 0;
 	del_timer(&cyz_timerlist);
     }
+#endif /* CONFIG_CYZ_INTR */
 
     save_flags(flags); cli();
     remove_bh(CYCLADES_BH);
@@ -5396,6 +5720,9 @@
 
     for (i = 0; i < NR_CARDS; i++) {
         if (cy_card[i].base_addr != 0
+#ifndef CONFIG_CYZ_INTR
+	    && cy_card[i].num_chips != -1 /* not a Z card */
+#endif /* CONFIG_CYZ_INTR */
 	    && cy_card[i].irq)
         {
             free_irq(cy_card[i].irq, &cy_card[i]);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/dz.c linux.pre11.3/drivers/char/dz.c
--- linux.vanilla/drivers/char/dz.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/char/dz.c	Mon Jul 19 23:27:55 1999
@@ -0,0 +1,1601 @@
+/*
+ * dz.c: Serial port driver for DECStations equiped 
+ *       with the DZ chipset.
+ *
+ * Copyright (C) 1998 Olivier A. D. Lebaillif 
+ *             
+ * Email: olivier.lebaillif@ifrsys.com
+ *
+ * [31-AUG-98] triemer
+ * Changed IRQ to use Harald's dec internals interrupts.h
+ * removed base_addr code - moving address assignment to setup.c
+ * Changed name of dz_init to rs_init to be consistent with tc code
+ * [13-NOV-98] triemer fixed code to receive characters
+ *    after patches by harald to irq code.  
+ * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
+ *            field from "current" - somewhere between 2.1.121 and 2.1.131
+ */
+
+#ifdef MODULE
+#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/init.h> 
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/major.h>
+#include <linux/param.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <asm-mips/wbflush.h>
+/* for definition of SERIAL */
+#include <asm/dec/interrupts.h>
+
+/* for definition of struct console */
+#ifdef CONFIG_SERIAL_CONSOLE
+#define CONSOLE_LINE (3)
+#include <linux/console.h>
+#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/kn01.h>
+#include <asm/dec/kn02.h>
+
+#define DEBUG_DZ 1
+#ifdef DEBUG_DZ
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+#include <asm/bootinfo.h>
+
+extern int (*prom_printf) (char *,...);
+#endif
+
+
+
+#include "dz.h"
+
+#define DZ_INTR_DEBUG 1
+
+DECLARE_TASK_QUEUE(tq_serial);
+
+extern struct wait_queue *keypress_wait;
+static struct dz_serial *lines[4];
+static unsigned char tmp_buffer[256];
+
+
+
+#ifdef DEBUG_DZ
+/*
+ * debugging code to send out chars via prom 
+ */
+static void debug_console( const char *s,int count)
+{
+    unsigned i;
+
+    for (i = 0; i < count; i++) {
+       if (*s == 10)
+           prom_printf("%c", 13);
+       prom_printf("%c", *s++);
+    }
+}
+#endif
+
+/*
+ * ------------------------------------------------------------
+ * dz_in () and dz_out ()
+ *
+ * These routines are used to access the registers of the DZ 
+ * chip, hiding relocation differences between implementation.
+ * ------------------------------------------------------------
+ */
+
+static inline unsigned short dz_in (struct dz_serial *info, unsigned offset)
+{
+  volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
+  return *addr;
+}
+
+static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value)
+{
+
+    volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
+  *addr = value;
+
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop () and rs_start ()
+ *
+ * These routines are called before setting or resetting 
+ * tty->stopped. They enable or disable transmitter interrupts, 
+ * as necessary.
+ * ------------------------------------------------------------
+ */
+
+static void dz_stop (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  unsigned short mask, tmp;
+
+         
+  mask = 1 << info->line;
+  tmp = dz_in (info, DZ_TCR);       /* read the TX flag */
+
+    tmp &= ~mask;                   /* clear the TX flag */
+    dz_out (info, DZ_TCR, tmp);
+}  
+
+static void dz_start (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  unsigned short mask, tmp;
+
+  mask = 1 << info->line;
+  tmp = dz_in (info, DZ_TCR);      /* read the TX flag */
+
+    tmp |= mask;                   /* set the TX flag */
+    dz_out (info, DZ_TCR, tmp);
+
+}  
+
+/*
+ * ------------------------------------------------------------
+ * Here starts the interrupt handling routines.  All of the 
+ * following subroutines are declared as inline and are folded 
+ * into dz_interrupt.  They were separated out for readability's 
+ * sake. 
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * ------------------------------------------------------------
+ */
+
+/*
+ * ------------------------------------------------------------
+ * dz_sched_event ()
+ *
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ * ------------------------------------------------------------
+ */
+static inline void dz_sched_event (struct dz_serial *info, int event)
+{
+  info->event |= 1 << event;
+  queue_task (&info->tqueue, &tq_serial);
+  mark_bh (SERIAL_BH);
+}
+
+/*
+ * ------------------------------------------------------------
+ * receive_char ()
+ *
+ * This routine deals with inputs from any lines.
+ * ------------------------------------------------------------
+ */
+static inline void receive_chars (struct dz_serial *info_in)
+{
+
+  struct dz_serial *info;
+  struct tty_struct *tty = 0;
+  struct async_icount *icount;
+  int ignore = 0;
+  unsigned short status, tmp;
+  unsigned char ch;
+
+  /* this code is going to be a problem...
+     the call to tty_flip_buffer is going to need
+     to be rethought...
+   */
+  do
+    {
+      status = dz_in (info_in, DZ_RBUF);
+      info = lines[LINE(status)];
+
+      /* punt so we don't get duplicate characters */
+      if (!(status & DZ_DVAL))
+        goto ignore_char;
+
+
+    ch = UCHAR(status);                /* grab the char */
+
+#ifdef 0
+    if (info->is_console) {
+      if (ch == 0) return;            /* it's a break ... */
+
+      wake_up (&keypress_wait);       /* It is a 'keyboard interrupt' ;-) */
+    }
+#endif
+
+    tty = info->tty;                  /* now tty points to the proper dev */
+    icount = &info->icount;
+
+    if (!tty) break;
+    if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
+
+    *tty->flip.char_buf_ptr = ch;
+    *tty->flip.flag_buf_ptr = 0;
+    icount->rx++;
+
+    /* keep track of the statistics */
+    if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
+      if (status & DZ_PERR)                /* parity error */
+        icount->parity++;
+      else if (status & DZ_FERR)           /* frame error */
+        icount->frame++;
+      if (status & DZ_OERR)                /* overrun error */
+        icount->overrun++;
+
+      /*  check to see if we should ignore the character
+	 and mask off conditions that should be ignored
+      */
+
+      if (status & info->ignore_status_mask) {
+        if (++ignore > 100 ) break;
+        goto ignore_char;
+      }
+
+      /* mask off the error conditions we want to ignore */
+      tmp = status & info->read_status_mask;
+
+      if (tmp & DZ_PERR)
+	{
+        *tty->flip.flag_buf_ptr = TTY_PARITY;
+	  debug_console("PERR\n",5);
+	}
+      else if (tmp & DZ_FERR)
+	{
+        *tty->flip.flag_buf_ptr = TTY_FRAME;
+	  debug_console("FERR\n",5);
+	}
+      if (tmp & DZ_OERR) 
+	{ 
+	  debug_console("OERR\n",5);
+	if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+          tty->flip.count++;
+          tty->flip.flag_buf_ptr++;
+          tty->flip.char_buf_ptr++;
+          *tty->flip.flag_buf_ptr = TTY_OVERRUN;
+        }
+      }
+    }
+    tty->flip.flag_buf_ptr++;
+    tty->flip.char_buf_ptr++;
+    tty->flip.count++;
+  ignore_char:
+  } while (status & DZ_DVAL);
+
+  if (tty)
+    tty_flip_buffer_push(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * transmit_char ()
+ *
+ * This routine deals with outputs to any lines.
+ * ------------------------------------------------------------
+ */
+static inline void transmit_chars (struct dz_serial *info)
+{
+  unsigned char tmp;
+
+
+
+  if (info->x_char) {           /* XON/XOFF chars */
+    dz_out (info, DZ_TDR, info->x_char);
+    info->icount.tx++;
+    info->x_char = 0;
+    return;
+  }
+
+  /* if nothing to do or stopped or hardware stopped */
+  if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
+    dz_stop (info->tty);
+    return;
+  }
+
+  /* if something to do ... (rember the dz has no output fifo so we go one char at a time :-< */
+  tmp = (unsigned short)info->xmit_buf[info->xmit_tail++];
+  dz_out (info, DZ_TDR, tmp);
+  info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1);
+  info->icount.tx++;
+
+  if (--info->xmit_cnt < WAKEUP_CHARS)
+    dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP);
+
+
+  /* Are we done */
+  if (info->xmit_cnt <= 0) dz_stop (info->tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * check_modem_status ()
+ *
+ * Only valid for the MODEM line duh !
+ * ------------------------------------------------------------
+ */
+static inline void check_modem_status (struct dz_serial *info)
+{
+  unsigned short status;
+
+  /* if not ne modem line just return */
+  if (info->line != DZ_MODEM) return;
+
+  status = dz_in (info, DZ_MSR);
+  
+  /* it's easy, since DSR2 is the only bit in the register */
+  if (status) info->icount.dsr++;
+}
+
+/*
+ * ------------------------------------------------------------
+ * dz_interrupt ()
+ *
+ * this is the main interrupt routine for the DZ chip.
+ * It deals with the multiple ports.
+ * ------------------------------------------------------------
+ */
+static void dz_interrupt (int irq, void *dev, struct pt_regs *regs)
+{
+  struct dz_serial *info;
+  unsigned short status;
+
+  status = dz_in ((struct dz_serial *)dev, DZ_CSR); /* get the reason why we just got an irq */
+  info = lines[LINE(status)];     /* re-arrange info the proper port */
+
+  if (status & DZ_RDONE) 
+      receive_chars (info);          /* the receive function */
+
+  if (status & DZ_TRDY) 
+    transmit_chars (info);
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the DZ interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh (void)
+{
+        run_task_queue (&tq_serial);
+}
+
+static void do_softint (void *private_data)
+{
+  struct dz_serial *info = (struct dz_serial *)private_data;
+  struct tty_struct *tty = info->tty;
+
+  if (!tty) return;
+
+  if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) {
+    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+      (tty->ldisc.write_wakeup) (tty);
+    wake_up_interruptible (&tty->write_wait);
+  }
+}
+
+/*
+ * -------------------------------------------------------------------
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred.  The path of
+ * hangup processing is:
+ *
+ *      serial interrupt routine -> (scheduler tqueue) ->
+ *      do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ * ------------------------------------------------------------------- 
+ */
+static void do_serial_hangup (void *private_data)
+{
+  struct dz_serial *info = (struct dz_serial *)private_data;
+  struct tty_struct *tty = info->tty;;
+        
+  if (!tty) return;
+
+  tty_hangup (tty);
+}
+
+/*
+ * -------------------------------------------------------------------
+ * startup ()
+ *
+ * various initialization tasks
+ * ------------------------------------------------------------------- 
+ */
+static int startup (struct dz_serial *info)
+{
+  unsigned long page, flags;
+  unsigned short tmp;
+
+  if (info->is_initialized) return 0;
+  
+  save_flags (flags);
+  cli ();
+
+  if (!info->port) {
+    if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
+    restore_flags (flags);
+    return -ENODEV;
+  }
+
+  if (!info->xmit_buf) {
+    page = get_free_page (GFP_KERNEL);
+    if (!page) {
+      restore_flags (flags);
+      return -ENOMEM;
+    }
+    info->xmit_buf = (unsigned char *)page;
+  }
+
+  if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags);
+
+  /* enable the interrupt and the scanning */
+  tmp = dz_in (info, DZ_CSR);
+  tmp |= (DZ_RIE | DZ_TIE | DZ_MSE);
+  dz_out (info, DZ_CSR, tmp);
+
+  info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+  /* set up the speed */
+  change_speed (info);
+
+  /* clear the line transmitter buffer 
+     I can't figure out why I need to do this - but
+     its necessary - in order for the console portion
+     and the interrupt portion to live happily side by side.
+  */
+
+  /* clear the line transmitter buffer 
+     I can't figure out why I need to do this - but
+     its necessary - in order for the console portion
+     and the interrupt portion to live happily side by side.
+  */
+
+  info->is_initialized = 1;
+
+  restore_flags (flags);
+  return 0;
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * shutdown ()
+ *
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ * ------------------------------------------------------------------- 
+ */
+static void shutdown (struct dz_serial *info)
+{
+  unsigned long flags;
+  unsigned short tmp;
+
+  if (!info->is_initialized) return;
+
+  save_flags (flags);
+  cli ();
+
+  dz_stop (info->tty);
+
+
+
+  info->cflags &= ~DZ_CREAD;          /* turn off receive enable flag */
+  dz_out (info, DZ_LPR, info->cflags);
+
+  if (info->xmit_buf) {               /* free Tx buffer */
+    free_page ((unsigned long)info->xmit_buf);
+    info->xmit_buf = 0;
+  }
+
+  if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+    tmp = dz_in (info, DZ_TCR);
+    if (tmp & DZ_MODEM_DTR) {
+      tmp &= ~DZ_MODEM_DTR;
+      dz_out (info, DZ_TCR, tmp);
+    }
+  }
+
+  if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
+
+  info->is_initialized = 0;
+  restore_flags (flags);
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * change_speed ()
+ *
+ * set the baud rate.
+ * ------------------------------------------------------------------- 
+ */
+static void change_speed (struct dz_serial *info)
+{
+  unsigned long flags;
+  unsigned cflag;
+  int baud;
+
+  if (!info->tty || !info->tty->termios) return;
+  
+  save_flags (flags);
+  cli ();
+  
+  info->cflags = info->line;
+
+  cflag = info->tty->termios->c_cflag;
+
+  switch (cflag & CSIZE) {
+  case CS5: info->cflags |= DZ_CS5; break;
+  case CS6: info->cflags |= DZ_CS6; break;
+  case CS7: info->cflags |= DZ_CS7; break;
+  case CS8: 
+  default:  info->cflags |= DZ_CS8;
+  }
+
+  if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB;
+  if (cflag & PARENB) info->cflags |= DZ_PARENB;
+  if (cflag & PARODD) info->cflags |= DZ_PARODD;
+  
+  baud = tty_get_baud_rate (info->tty);
+  switch (baud) {
+  case 50  :  info->cflags |= DZ_B50;   break;
+  case 75  :  info->cflags |= DZ_B75;   break;
+  case 110 :  info->cflags |= DZ_B110;  break;
+  case 134 :  info->cflags |= DZ_B134;  break; 
+  case 150 :  info->cflags |= DZ_B150;  break;
+  case 300 :  info->cflags |= DZ_B300;  break; 
+  case 600 :  info->cflags |= DZ_B600;  break;
+  case 1200:  info->cflags |= DZ_B1200; break; 
+  case 1800:  info->cflags |= DZ_B1800; break;
+  case 2000:  info->cflags |= DZ_B2000; break;
+  case 2400:  info->cflags |= DZ_B2400; break;
+  case 3600:  info->cflags |= DZ_B3600; break; 
+  case 4800:  info->cflags |= DZ_B4800; break;
+  case 7200:  info->cflags |= DZ_B7200; break; 
+  case 9600: 
+  default  :  info->cflags |= DZ_B9600; 
+  }
+
+  info->cflags |= DZ_RXENAB;
+  dz_out (info, DZ_LPR, info->cflags);
+
+  /* setup accept flag */
+  info->read_status_mask = DZ_OERR;
+  if (I_INPCK(info->tty))
+   info->read_status_mask |= (DZ_FERR | DZ_PERR); 
+  
+  /* characters to ignore */
+  info->ignore_status_mask = 0;
+  if (I_IGNPAR(info->tty))
+    info->ignore_status_mask |= (DZ_FERR | DZ_PERR);
+
+  restore_flags (flags);
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * dz_flush_char ()
+ *
+ * Flush the buffer.
+ * ------------------------------------------------------------------- 
+ */
+static void dz_flush_chars (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  unsigned long flags;
+
+ if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)
+    return;
+
+ save_flags (flags);
+ cli ();  
+
+ dz_start (info->tty);
+
+ restore_flags (flags);
+}
+
+
+/* 
+ * -------------------------------------------------------------------
+ * dz_write ()
+ *
+ * main output routine.
+ * ------------------------------------------------------------------- 
+ */
+static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  unsigned long flags;
+  int c, ret = 0;
+
+  if (!tty ) return ret;
+  if (!info->xmit_buf) return ret;
+  if (!tmp_buf) tmp_buf = tmp_buffer;
+
+
+
+  if (from_user) {
+
+    down (&tmp_buf_sem);
+    while (1) {
+      c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
+      if (c <= 0) break;
+
+      c -= copy_from_user (tmp_buf, buf, c);
+      if (!c) {
+        if (!ret) ret = -EFAULT;
+        break;
+      }
+
+      save_flags (flags);
+      cli ();
+
+      c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
+      memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+      info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
+      info->xmit_cnt += c;
+
+      restore_flags(flags);
+
+      buf += c;
+      count -= c;
+      ret += c;
+    }
+    
+    up (&tmp_buf_sem);
+  } else {
+
+
+    while (1) {
+      save_flags (flags);
+      cli ();     
+
+      c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
+      if (c <= 0) {
+        restore_flags (flags);
+        break;
+      }
+      memcpy (info->xmit_buf + info->xmit_head, buf, c);
+      info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
+      info->xmit_cnt += c;
+
+      restore_flags (flags);
+
+      buf += c;
+      count -= c;
+      ret += c;
+    }
+  }
+
+
+  if (info->xmit_cnt)
+    {
+      if (!tty->stopped) 
+	{
+	  if (!tty->hw_stopped)
+	    {
+	      dz_start (info->tty);
+	    }
+	}
+    }
+  return ret;
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * dz_write_room ()
+ *
+ * compute the amount of space available for writing.
+ * ------------------------------------------------------------------- 
+ */
+static int dz_write_room (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  int ret;
+                                
+  ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;
+  if (ret < 0) ret = 0;
+  return ret;
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * dz_chars_in_buffer ()
+ *
+ * compute the amount of char left to be transmitted
+ * ------------------------------------------------------------------- 
+ */
+static int dz_chars_in_buffer (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  
+  return info->xmit_cnt;
+}
+
+/* 
+ * -------------------------------------------------------------------
+ * dz_flush_buffer ()
+ *
+ * Empty the output buffer
+ * ------------------------------------------------------------------- 
+ */
+static void dz_flush_buffer (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+                                
+  cli ();
+  info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+  sti ();
+
+  wake_up_interruptible (&tty->write_wait);
+
+  if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+    (tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * dz_throttle () and dz_unthrottle ()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled (or not).
+ * ------------------------------------------------------------
+ */
+static void dz_throttle (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  
+
+  if (I_IXOFF(tty))
+    info->x_char = STOP_CHAR(tty);
+}
+
+static void dz_unthrottle (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;  
+
+  if (I_IXOFF(tty)) {
+    if (info->x_char)
+      info->x_char = 0;
+    else
+      info->x_char = START_CHAR(tty);
+  }
+}
+
+static void dz_send_xchar (struct tty_struct *tty, char ch)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+
+  info->x_char = ch;
+
+  if (ch) dz_start (info->tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl () and friends
+ * ------------------------------------------------------------
+ */
+static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo)
+{
+  struct serial_struct tmp;
+  
+  if (!retinfo)
+    return -EFAULT;
+
+  memset (&tmp, 0, sizeof(tmp));
+
+  tmp.type = info->type;
+  tmp.line = info->line;
+  tmp.port = info->port;
+  tmp.irq = SERIAL;
+  tmp.flags = info->flags;
+  tmp.baud_base = info->baud_base;
+  tmp.close_delay = info->close_delay;
+  tmp.closing_wait = info->closing_wait;
+  
+  return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
+}
+
+static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info)
+{
+  struct serial_struct new_serial;
+  struct dz_serial old_info;
+  int retval = 0;
+
+  if (!new_info)
+    return -EFAULT;
+
+  copy_from_user (&new_serial, new_info, sizeof(new_serial));
+  old_info = *info;
+
+  if (!suser())
+    return -EPERM;
+
+  if (info->count > 1)
+    return -EBUSY;
+
+  /*
+   * OK, past this point, all the error checking has been done.
+   * At this point, we start making changes.....
+   */
+  
+  info->baud_base = new_serial.baud_base;
+  info->type = new_serial.type;
+  info->close_delay = new_serial.close_delay;
+  info->closing_wait = new_serial.closing_wait;
+
+  retval = startup (info);
+  return retval;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *          is emptied.  On bus types like RS485, the transmitter must
+ *          release the bus after transmitting. This must be done when
+ *          the transmit shift register is empty, not be done when the
+ *          transmit holding register is empty.  This functionality
+ *          allows an RS485 driver to be written in user space. 
+ */
+static int get_lsr_info (struct dz_serial *info, unsigned int *value)
+{
+  unsigned short status = dz_in (info, DZ_LPR);
+
+  return put_user (status, value);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void send_break (struct dz_serial *info, int duration)
+{
+  unsigned long flags;
+  unsigned short tmp, mask;
+
+  if (!info->port)
+    return;
+
+  mask = 1 << info->line;
+  tmp = dz_in (info, DZ_TCR);
+  tmp |= mask;
+
+  current->state = TASK_INTERRUPTIBLE;
+
+  save_flags (flags);
+  cli();
+  
+  dz_out (info, DZ_TCR, tmp);
+  
+  schedule_timeout(jiffies + duration);
+  
+  tmp &= ~mask;
+  dz_out (info, DZ_TCR, tmp);
+  
+  restore_flags (flags);
+}
+
+static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
+{
+  int error;
+  struct dz_serial * info = (struct dz_serial *)tty->driver_data;
+  int retval;
+
+  if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+      (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
+      (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+    if (tty->flags & (1 << TTY_IO_ERROR))
+      return -EIO;
+  }
+
+  switch (cmd) {
+  case TCSBRK:    /* SVID version: non-zero arg --> no break */
+    retval = tty_check_change (tty);
+    if (retval)
+      return retval;
+    tty_wait_until_sent (tty, 0);
+    if (!arg)
+      send_break (info, HZ/4); /* 1/4 second */
+    return 0;
+
+  case TCSBRKP:   /* support for POSIX tcsendbreak() */
+    retval = tty_check_change (tty);
+    if (retval)
+      return retval;
+    tty_wait_until_sent (tty, 0);
+    send_break (info, arg ? arg*(HZ/10) : HZ/4);
+    return 0;
+
+  case TIOCGSOFTCAR:
+    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long));
+    if (error)
+      return error;
+    put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
+    return 0;
+
+  case TIOCSSOFTCAR:
+    error = get_user (arg, (unsigned long *)arg);
+    if (error)
+      return error;
+    tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
+    return 0;
+
+  case TIOCGSERIAL:
+    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
+    if (error)
+      return error;
+    return get_serial_info (info, (struct serial_struct *)arg);
+
+  case TIOCSSERIAL:
+    return set_serial_info (info, (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 (info, (unsigned int *)arg);
+
+  case TIOCSERGSTRUCT:
+    error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial));
+    if (error)
+      return error;
+    copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial));
+    return 0;
+    
+  default:
+    return -ENOIOCTLCMD;
+  }
+
+  return 0;
+}
+
+static void dz_set_termios (struct tty_struct *tty,
+			    struct termios *old_termios)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+
+  if (tty->termios->c_cflag == old_termios->c_cflag)
+    return;
+
+  change_speed (info);
+
+  if ((old_termios->c_cflag & CRTSCTS) &&
+      !(tty->termios->c_cflag & CRTSCTS)) {
+    tty->hw_stopped = 0;
+    dz_start (tty);
+  }
+}
+
+/*
+ * ------------------------------------------------------------
+ * dz_close()
+ * 
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we turn off
+ * the transmit enable and receive enable flags.
+ * ------------------------------------------------------------
+ */
+static void dz_close (struct tty_struct *tty, struct file *filp)
+{
+  struct dz_serial * info = (struct dz_serial *)tty->driver_data;
+  unsigned long flags;
+
+  if (!info) return;
+        
+  save_flags (flags); 
+  cli();
+        
+  if (tty_hung_up_p (filp)) {
+    restore_flags (flags);
+    return;
+  }
+
+  if ((tty->count == 1) && (info->count != 1)) {
+    /*
+     * Uh, oh.  tty->count is 1, which means that the tty
+     * structure will be freed.  Info->count should always
+     * be one in these conditions.  If it's greater than
+     * one, we've got real problems, since it means the
+     * serial port won't be shutdown.
+     */
+    printk("dz_close: bad serial port count; tty->count is 1, "
+                       "info->count is %d\n", info->count);
+                info->count = 1;
+  }
+
+  if (--info->count < 0) {
+    printk("rs_close: bad serial port count for ttys%d: %d\n",
+	   info->line, info->count);
+    info->count = 0;
+  }
+
+  if (info->count) {
+    restore_flags (flags);
+    return;
+  }
+  info->flags |= DZ_CLOSING;
+  /*
+   * Save the termios structure, since this port may have
+   * separate termios for callout and dialin.
+   */
+  if (info->flags & DZ_NORMAL_ACTIVE)
+    info->normal_termios = *tty->termios;
+  if (info->flags & DZ_CALLOUT_ACTIVE)
+    info->callout_termios = *tty->termios;
+  /*
+   * Now we wait for the transmit buffer to clear; and we notify 
+   * the line discipline to only process XON/XOFF characters.
+   */
+  tty->closing = 1;
+
+  if (info->closing_wait != DZ_CLOSING_WAIT_NONE)
+    tty_wait_until_sent (tty, info->closing_wait);
+
+  /*
+   * At this point we stop accepting input.  To do this, we
+   * disable the receive line status interrupts.
+   */
+
+  shutdown (info);
+
+  if (tty->driver.flush_buffer)
+    tty->driver.flush_buffer (tty);
+  if (tty->ldisc.flush_buffer)
+    tty->ldisc.flush_buffer (tty);
+  tty->closing = 0;
+  info->event = 0;
+  info->tty = 0;
+
+  if (tty->ldisc.num != ldiscs[N_TTY].num) {
+    if (tty->ldisc.close)
+      (tty->ldisc.close)(tty);
+    tty->ldisc = ldiscs[N_TTY];
+    tty->termios->c_line = N_TTY;
+    if (tty->ldisc.open)
+      (tty->ldisc.open)(tty);
+  }
+  if (info->blocked_open) {
+    if (info->close_delay) {
+      current->state = TASK_INTERRUPTIBLE;
+      schedule_timeout(jiffies + info->close_delay);
+    }
+    wake_up_interruptible (&info->open_wait);
+  }
+
+  info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);
+  wake_up_interruptible (&info->close_wait);
+
+  restore_flags (flags);
+}
+
+/*
+ * dz_hangup () --- called by tty_hangup() when a hangup is signaled.
+ */
+static void dz_hangup (struct tty_struct *tty)
+{
+  struct dz_serial *info = (struct dz_serial *)tty->driver_data;
+  
+  dz_flush_buffer (tty);
+  shutdown (info);
+  info->event = 0;
+  info->count = 0;
+  info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE);
+  info->tty = 0;
+  wake_up_interruptible (&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info)
+{
+  struct wait_queue wait = { current, NULL };
+  int retval;
+  int do_clocal = 0;
+
+  /*
+   * If the device is in the middle of being closed, then block
+   * until it's done, and then try again.
+   */
+  if (info->flags & DZ_CLOSING) {
+    interruptible_sleep_on (&info->close_wait);
+    return -EAGAIN;
+  }
+
+  /*
+   * If this is a callout device, then just make sure the normal
+   * device isn't being used.
+   */
+  if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+    if (info->flags & DZ_NORMAL_ACTIVE)
+      return -EBUSY;
+    
+    if ((info->flags & DZ_CALLOUT_ACTIVE) &&
+	(info->flags & DZ_SESSION_LOCKOUT) &&
+	(info->session != current->session))
+      return -EBUSY;
+    
+    if ((info->flags & DZ_CALLOUT_ACTIVE) &&
+	(info->flags & DZ_PGRP_LOCKOUT) &&
+	(info->pgrp != current->pgrp))
+      return -EBUSY;
+    info->flags |= DZ_CALLOUT_ACTIVE;
+    return 0;
+  }
+
+  /*
+   * If non-blocking mode is set, or the port is not enabled,
+   * then make the check up front and then exit.
+   */
+  if ((filp->f_flags & O_NONBLOCK) ||
+      (tty->flags & (1 << TTY_IO_ERROR))) {
+    if (info->flags & DZ_CALLOUT_ACTIVE)
+      return -EBUSY;
+    info->flags |= DZ_NORMAL_ACTIVE;
+    return 0;
+  }
+
+  if (info->flags & DZ_CALLOUT_ACTIVE) {
+    if (info->normal_termios.c_cflag & CLOCAL)
+      do_clocal = 1;
+  } else {
+    if (tty->termios->c_cflag & CLOCAL)
+      do_clocal = 1;
+  }
+
+  /*
+   * Block waiting for the carrier detect and the line to become
+   * free (i.e., not in use by the callout).  While we are in
+   * this loop, info->count is dropped by one, so that
+   * dz_close() knows when to free things.  We restore it upon
+   * exit, either normal or abnormal.
+   */
+  retval = 0;
+  add_wait_queue (&info->open_wait, &wait);
+
+  info->count--;
+  info->blocked_open++;
+  while (1) {
+    current->state = TASK_INTERRUPTIBLE;
+    if (tty_hung_up_p (filp) || !(info->is_initialized)) {
+      retval = -EAGAIN;
+      break;
+    }
+    if (!(info->flags & DZ_CALLOUT_ACTIVE) &&
+	!(info->flags & DZ_CLOSING) && do_clocal)
+      break;
+    if (signal_pending (current)) {
+      retval = -ERESTARTSYS;
+      break;
+    }
+    schedule();
+  }
+		
+  current->state = TASK_RUNNING;
+  remove_wait_queue (&info->open_wait, &wait);
+  if (!tty_hung_up_p(filp))
+    info->count++;
+  info->blocked_open--;
+
+  if (retval)
+    return retval;
+  info->flags |= DZ_NORMAL_ACTIVE;
+  return 0;
+}       
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port. It also performs the 
+ * serial-specific initialization for the tty structure.
+ */
+static int dz_open (struct tty_struct *tty, struct file *filp)
+{
+  struct dz_serial *info;
+  int retval, line;
+
+  line = MINOR(tty->device) - tty->driver.minor_start;
+
+  /* The dz lines for the mouse/keyboard must be
+   * opened using their respective drivers.
+   */
+  if ((line < 0) || (line >= DZ_NB_PORT))
+    return -ENODEV;
+
+  if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))
+    return -ENODEV;
+
+  info = lines[line];
+  info->count++;
+
+  tty->driver_data = info;
+  info->tty = tty;
+
+  /*
+   * Start up serial port
+   */
+  retval = startup (info);
+  if (retval)
+    return retval;
+
+
+
+  retval = block_til_ready (tty, filp, info);
+  if (retval)
+    return retval;
+
+  if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
+    if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+      *tty->termios = info->normal_termios;
+    else 
+      *tty->termios = info->callout_termios;
+    change_speed (info);
+
+  }
+
+  info->session = current->session;
+  info->pgrp = current->pgrp;
+  return 0;
+}
+
+static void show_serial_version (void)
+{
+  printk("%s%s\n", dz_name, dz_version);
+}
+
+
+__initfunc(int dz_init(void))
+{
+  int i, flags;
+  struct dz_serial *info;
+
+  /* Setup base handler, and timer table. */
+  init_bh (SERIAL_BH, do_serial_bh);
+
+  show_serial_version ();
+
+  memset(&serial_driver, 0, sizeof(struct tty_driver));
+  serial_driver.magic = TTY_DRIVER_MAGIC;
+  serial_driver.name = "ttyS";
+  serial_driver.major = TTY_MAJOR;
+  serial_driver.minor_start = 64;
+  serial_driver.num = DZ_NB_PORT;
+  serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+  serial_driver.subtype = SERIAL_TYPE_NORMAL;
+  serial_driver.init_termios = tty_std_termios;
+
+  serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+  serial_driver.flags = TTY_DRIVER_REAL_RAW;
+  serial_driver.refcount = &serial_refcount;
+  serial_driver.table = serial_table;
+  serial_driver.termios = serial_termios;
+  serial_driver.termios_locked = serial_termios_locked;
+
+  serial_driver.open = dz_open;
+  serial_driver.close = dz_close;
+  serial_driver.write = dz_write;
+  serial_driver.flush_chars = dz_flush_chars;
+  serial_driver.write_room = dz_write_room;
+  serial_driver.chars_in_buffer = dz_chars_in_buffer;
+  serial_driver.flush_buffer = dz_flush_buffer;
+  serial_driver.ioctl = dz_ioctl;
+  serial_driver.throttle = dz_throttle;
+  serial_driver.unthrottle = dz_unthrottle;
+  serial_driver.send_xchar = dz_send_xchar;
+  serial_driver.set_termios = dz_set_termios;
+  serial_driver.stop = dz_stop;
+  serial_driver.start = dz_start;
+  serial_driver.hangup = dz_hangup;
+
+  /*
+   * The callout device is just like normal device except for
+   * major number and the subtype code.
+   */
+  callout_driver = serial_driver;
+  callout_driver.name = "cua";
+  callout_driver.major = TTYAUX_MAJOR;
+  callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+  if (tty_register_driver (&serial_driver))
+    panic("Couldn't register serial driver\n");
+  if (tty_register_driver (&callout_driver))
+    panic("Couldn't register callout driver\n");
+  save_flags(flags); cli();
+ 
+  i = 0;
+  for (info = &multi[i]; i < DZ_NB_PORT;  i++) 
+    {
+      lines[i] = info;
+    info->magic = SERIAL_MAGIC;
+
+      if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) 
+      info->port = (unsigned long) KN01_DZ11_BASE;
+      else 
+      info->port = (unsigned long) KN02_DZ11_BASE;
+
+    info->line = i;
+    info->tty = 0;
+    info->close_delay = 50;
+    info->closing_wait = 3000;
+    info->x_char = 0;
+    info->event = 0;
+    info->count = 0;
+    info->blocked_open = 0;
+    info->tqueue.routine = do_softint;
+    info->tqueue.data = info;
+    info->tqueue_hangup.routine = do_serial_hangup;
+    info->tqueue_hangup.data = info;
+    info->callout_termios = callout_driver.init_termios;
+    info->normal_termios = serial_driver.init_termios;
+    info->open_wait = 0;
+    info->close_wait = 0;
+
+    /* If we are pointing to address zero then punt - not correctly
+       set up in setup.c to handle this. */
+    if (! info->port)
+      return 0;
+
+    printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL);
+  }
+
+  /* reset the chip */
+#ifndef CONFIG_SERIAL_CONSOLE
+  dz_out(info, DZ_CSR, DZ_CLR);
+  while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ;
+  wbflush();
+  
+  /* enable scanning */
+   dz_out(info, DZ_CSR, DZ_MSE); 
+#endif
+  
+  /* order matters here... the trick is that flags
+     is updated... in request_irq - to immediatedly obliterate
+     it is unwise. */
+  restore_flags(flags);
+ 
+
+  if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))
+    panic ("Unable to register DZ interrupt\n");
+ 
+  return 0;
+}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+static void dz_console_put_char (unsigned char ch)
+{
+  long flags;
+  int  loops = 2500;
+  unsigned short tmp = ch;
+  /* this code sends stuff out to serial device - spinning its
+      wheels and waiting. */
+
+  /* force the issue - point it at lines[3]*/
+  dz_console=&multi[CONSOLE_LINE];
+
+  save_flags(flags);
+  cli();
+  
+
+  /* spin our wheels */
+  while (((dz_in(dz_console,DZ_TCR) & DZ_TRDY) != DZ_TRDY) &&  loops--)
+    ;
+  
+  /* Actually transmit the character. */
+  dz_out (dz_console, DZ_TDR, tmp);
+
+  restore_flags(flags); 
+}
+/* 
+ * -------------------------------------------------------------------
+ * dz_console_print ()
+ *
+ * dz_console_print is registered for printk.
+ * ------------------------------------------------------------------- 
+ */
+static void dz_console_print (struct console *cons, 
+			      const char *str, 
+			      unsigned int count)
+{
+#ifdef DEBUG_DZ
+  prom_printf((char *)str);
+#endif
+  while (count--) 
+    {
+    if (*str == '\n')
+	dz_console_put_char ('\r');
+      dz_console_put_char (*str++);
+  }
+}
+
+static int dz_console_wait_key(struct console *co)
+{
+    return 0;
+}
+
+static kdev_t dz_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+__initfunc(static int dz_console_setup(struct console *co, char *options))
+{
+  	int	baud = 9600;
+	int	bits = 8;
+	int	parity = 'n';
+	int	cflag = CREAD | HUPCL | CLOCAL;
+	char	*s;
+	unsigned short mask,tmp;
+
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while(*s >= '0' && *s <= '9')
+			s++;
+		if (*s)
+			parity = *s++;
+		if (*s)
+			bits   = *s - '0';
+	}
+
+	/*
+	 *	Now construct a cflag setting.
+	 */
+	switch(baud) {
+	case 1200:
+		cflag |= DZ_B1200;
+		break;
+	case 2400:
+		cflag |= DZ_B2400;
+		break;
+	case 4800:
+		cflag |= DZ_B4800;
+		break;
+	case 9600:
+	default:
+		cflag |= DZ_B9600;
+		break;
+	}
+	switch(bits) {
+	case 7:
+		cflag |= DZ_CS7;
+		break;
+	default:
+	case 8:
+		cflag |= DZ_CS8;
+		break;
+	}
+	switch(parity) {
+	case 'o': case 'O':
+		cflag |= DZ_PARODD;
+		break;
+	case 'e': case 'E':
+		cflag |= DZ_PARENB;
+		break;
+	}
+	co->cflag = cflag;
+
+	/* TOFIX: force to console line */
+	dz_console = &multi[CONSOLE_LINE];
+    	if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) 
+	dz_console->port = KN01_DZ11_BASE;
+       	else 
+       		dz_console->port = KN02_DZ11_BASE; 
+	dz_console->line = CONSOLE_LINE;
+
+	dz_out(dz_console, DZ_CSR, DZ_CLR);
+	while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR)
+	  ;
+
+	/* enable scanning */
+	dz_out(dz_console, DZ_CSR, DZ_MSE); 
+
+        /*  Set up flags... */
+	dz_console->cflags = 0;
+	dz_console->cflags |= DZ_B9600;
+	dz_console->cflags |= DZ_CS8;
+	dz_console->cflags |= DZ_PARENB;
+	dz_out (dz_console, DZ_LPR, dz_console->cflags);
+
+
+	mask = 1 << dz_console->line;
+	tmp = dz_in (dz_console, DZ_TCR);       /* read the TX flag */
+	if (!(tmp & mask)) {
+	  tmp |= mask;                   /* set the TX flag */
+	  dz_out (dz_console, DZ_TCR, tmp); 
+	}
+	
+
+	/* TOFIX: force to console line */
+	dz_console = &multi[CONSOLE_LINE];
+    	if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) 
+	dz_console->port = KN01_DZ11_BASE;
+       	else 
+       		dz_console->port = KN02_DZ11_BASE; 
+	dz_console->line = CONSOLE_LINE;
+
+	dz_out(dz_console, DZ_CSR, DZ_CLR);
+	while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR)
+	  ;
+
+	/* enable scanning */
+	dz_out(dz_console, DZ_CSR, DZ_MSE); 
+
+        /*  Set up flags... */
+	dz_console->cflags = 0;
+	dz_console->cflags |= DZ_B9600;
+	dz_console->cflags |= DZ_CS8;
+	dz_console->cflags |= DZ_PARENB;
+	dz_out (dz_console, DZ_LPR, dz_console->cflags);
+
+
+	mask = 1 << dz_console->line;
+	tmp = dz_in (dz_console, DZ_TCR);       /* read the TX flag */
+	if (!(tmp & mask)) {
+	  tmp |= mask;                   /* set the TX flag */
+	  dz_out (dz_console, DZ_TCR, tmp); 
+	}
+	
+
+	return 0;
+}
+
+static struct console dz_sercons = {
+	"ttyS",
+	dz_console_print,
+	NULL,
+	dz_console_device,
+	dz_console_wait_key,
+	NULL,
+	dz_console_setup,
+	CON_CONSDEV | CON_PRINTBUFFER,
+	CONSOLE_LINE,
+	0,
+	NULL
+};
+
+__initfunc (long dz_serial_console_init(long kmem_start, long kmem_end))
+{
+	register_console(&dz_sercons);
+
+	return kmem_start;
+}
+
+#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/dz.h linux.pre11.3/drivers/char/dz.h
--- linux.vanilla/drivers/char/dz.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/char/dz.h	Mon Jul 19 23:27:55 1999
@@ -0,0 +1,242 @@
+/*
+ * dz.h: Serial port driver for DECStations equiped 
+ *       with the DZ chipset.
+ *
+ * Copyright (C) 1998 Olivier A. D. Lebaillif 
+ *             
+ * Email: olivier.lebaillif@ifrsys.com
+ *
+ */
+#ifndef DZ_SERIAL_H
+#define DZ_SERIAL_H
+
+/*
+ * Definitions for the Control and Status Received.
+ */
+#define DZ_TRDY        0x8000                 /* Transmitter empty */
+#define DZ_TIE         0x4000                 /* Transmitter Interrupt Enable */
+#define DZ_RDONE       0x0080                 /* Receiver data ready */
+#define DZ_RIE         0x0040                 /* Receive Interrupt Enable */
+#define DZ_MSE         0x0020                 /* Master Scan Enable */
+#define DZ_CLR         0x0010                 /* Master reset */
+#define DZ_MAINT       0x0008                 /* Loop Back Mode */
+
+/*
+ * Definitions for the Received buffer. 
+ */
+#define DZ_RBUF_MASK   0x00FF                 /* Data Mask in the Receive Buffer */
+#define DZ_LINE_MASK   0x0300                 /* Line Mask in the Receive Buffer */
+#define DZ_DVAL        0x8000                 /* Valid Data indicator */
+#define DZ_OERR        0x4000                 /* Overrun error indicator */
+#define DZ_FERR        0x2000                 /* Frame error indicator */
+#define DZ_PERR        0x1000                 /* Parity error indicator */
+
+#define LINE(x) (x & DZ_LINE_MASK) >> 8       /* Get the line number from the input buffer */
+#define UCHAR(x) (unsigned char)(x & DZ_RBUF_MASK)
+
+/*
+ * Definitions for the Transmit Register.
+ */
+#define DZ_LINE_KEYBOARD 0x0001
+#define DZ_LINE_MOUSE    0x0002
+#define DZ_LINE_MODEM    0x0004
+#define DZ_LINE_PRINTER  0x0008
+
+#define DZ_MODEM_DTR     0x0400               /* DTR for the modem line (2) */
+
+/*
+ * Definitions for the Modem Status Register.
+ */
+#define DZ_MODEM_DSR     0x0200               /* DSR for the modem line (2) */
+
+/*
+ * Definitions for the Transmit Data Register.
+ */
+#define DZ_BRK0          0x0100               /* Break assertion for line 0 */
+#define DZ_BRK1          0x0200               /* Break assertion for line 1 */
+#define DZ_BRK2          0x0400               /* Break assertion for line 2 */
+#define DZ_BRK3          0x0800               /* Break assertion for line 3 */
+
+/*
+ * Definitions for the Line Parameter Register.
+ */
+#define DZ_KEYBOARD      0x0000               /* line 0 = keyboard */
+#define DZ_MOUSE         0x0001               /* line 1 = mouse */
+#define DZ_MODEM         0x0002               /* line 2 = modem */
+#define DZ_PRINTER       0x0003               /* line 3 = printer */
+
+#define DZ_CSIZE         0x0018               /* Number of bits per byte (mask) */
+#define DZ_CS5           0x0000               /* 5 bits per byte */
+#define DZ_CS6           0x0008               /* 6 bits per byte */
+#define DZ_CS7           0x0010               /* 7 bits per byte */
+#define DZ_CS8           0x0018               /* 8 bits per byte */
+
+#define DZ_CSTOPB        0x0020               /* 2 stop bits instead of one */ 
+
+#define DZ_PARENB        0x0040               /* Parity enable */
+#define DZ_PARODD        0x0080               /* Odd parity instead of even */
+
+#define DZ_CBAUD         0x0E00               /* Baud Rate (mask) */
+#define DZ_B50           0x0000
+#define DZ_B75           0x0100
+#define DZ_B110          0x0200
+#define DZ_B134          0x0300
+#define DZ_B150          0x0400
+#define DZ_B300          0x0500
+#define DZ_B600          0x0600
+#define DZ_B1200         0x0700 
+#define DZ_B1800         0x0800
+#define DZ_B2000         0x0900
+#define DZ_B2400         0x0A00
+#define DZ_B3600         0x0B00
+#define DZ_B4800         0x0C00
+#define DZ_B7200         0x0D00
+#define DZ_B9600         0x0E00
+
+#define DZ_CREAD         0x1000               /* Enable receiver */
+#define DZ_RXENAB        0x1000               /* enable receive char */
+/*
+ * Addresses for the DZ registers
+ */
+#define DZ_CSR       0x00            /* Control and Status Register */
+#define DZ_RBUF      0x08            /* Receive Buffer */
+#define DZ_LPR       0x08            /* Line Parameters Register */
+#define DZ_TCR       0x10            /* Transmitter Control Register */
+#define DZ_MSR       0x18            /* Modem Status Register */
+#define DZ_TDR       0x18            /* Transmit Data Register */
+
+
+#define DZ_NB_PORT 4
+
+#define DZ_XMIT_SIZE   4096                 /* buffer size */
+#define WAKEUP_CHARS   DZ_XMIT_SIZE/4
+
+#define DZ_EVENT_WRITE_WAKEUP   0
+
+#ifndef MIN
+#define MIN(a,b)        ((a) < (b) ? (a) : (b))
+
+#define DZ_INITIALIZED       0x80000000 /* Serial port was initialized */
+#define DZ_CALLOUT_ACTIVE    0x40000000 /* Call out device is active */
+#define DZ_NORMAL_ACTIVE     0x20000000 /* Normal device is active */
+#define DZ_BOOT_AUTOCONF     0x10000000 /* Autoconfigure port on bootup */
+#define DZ_CLOSING           0x08000000 /* Serial port is closing */
+#define DZ_CTS_FLOW          0x04000000 /* Do CTS flow control */
+#define DZ_CHECK_CD          0x02000000 /* i.e., CLOCAL */
+
+#define DZ_CLOSING_WAIT_INF  0
+#define DZ_CLOSING_WAIT_NONE 65535
+
+#define DZ_SPLIT_TERMIOS   0x0008 /* Separate termios for dialin/callout */
+#define DZ_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define DZ_PGRP_LOCKOUT    0x0200 /* Lock out cua opens based on pgrp */
+
+struct dz_serial {
+  unsigned                port;                /* base address for the port */
+  int                     type;
+  int                     flags; 
+  int                     baud_base;
+  int                     blocked_open;
+  unsigned short          close_delay;
+  unsigned short          closing_wait;
+  unsigned short          line;                /* port/line number */
+  unsigned short          cflags;              /* line configuration flag */
+  unsigned short          x_char;              /* xon/xoff character */
+  unsigned short          read_status_mask;    /* mask for read condition */
+  unsigned short          ignore_status_mask;  /* mask for ignore condition */
+  unsigned long           event;               /* mask used in BH */
+  unsigned char           *xmit_buf;           /* Transmit buffer */
+  int                     xmit_head;           /* Position of the head */
+  int                     xmit_tail;           /* Position of the tail */
+  int                     xmit_cnt;            /* Count of the chars in the buffer */
+  int                     count;               /* indicates how many times it has been opened */
+  int                     magic;
+
+  struct async_icount     icount;              /* keep track of things ... */
+  struct tty_struct       *tty;                /* tty associated */
+  struct tq_struct        tqueue;              /* Queue for BH */
+  struct tq_struct        tqueue_hangup;
+  struct termios          normal_termios;
+  struct termios          callout_termios;
+  struct wait_queue       *open_wait;
+  struct wait_queue       *close_wait;
+
+  long                    session;             /* Session of opening process */
+  long                    pgrp;                /* pgrp of opening process */
+
+  unsigned char           is_console;          /* flag indicating a serial console */
+  unsigned char           is_initialized;
+};
+
+static struct dz_serial multi[DZ_NB_PORT];    /* Four serial lines in the DZ chip */
+static struct dz_serial *dz_console;
+static struct tty_driver serial_driver, callout_driver;
+
+static struct tty_struct *serial_table[DZ_NB_PORT];
+static struct termios *serial_termios[DZ_NB_PORT];
+static struct termios *serial_termios_locked[DZ_NB_PORT];
+
+static int serial_refcount;
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write.  We need to
+ * lock it in case the copy_from_user 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;
+static struct semaphore tmp_buf_sem = MUTEX;
+
+static char *dz_name = "DECstation DZ serial driver version ";
+static char *dz_version = "1.02";
+
+static inline unsigned short dz_in (struct dz_serial *, unsigned);
+static inline void dz_out (struct dz_serial *, unsigned, unsigned short);
+
+static inline void dz_sched_event (struct dz_serial *, int);
+static inline void receive_chars (struct dz_serial *);
+static inline void transmit_chars (struct dz_serial *);
+static inline void check_modem_status (struct dz_serial *);
+
+static void dz_stop (struct tty_struct *);
+static void dz_start (struct tty_struct *);
+static void dz_interrupt (int, void *, struct pt_regs *);
+static void do_serial_bh (void);
+static void do_softint (void *);
+static void do_serial_hangup (void *);
+static void change_speed (struct dz_serial *);
+static void dz_flush_chars (struct tty_struct *);
+static void dz_console_print (struct console *, const char *, unsigned int);
+static void dz_flush_buffer (struct tty_struct *);
+static void dz_throttle (struct tty_struct *);
+static void dz_unthrottle (struct tty_struct *);
+static void dz_send_xchar (struct tty_struct *, char);
+static void shutdown (struct dz_serial *);
+static void send_break (struct dz_serial *, int);
+static void dz_set_termios (struct tty_struct *, struct termios *);
+static void dz_close (struct tty_struct *, struct file *);
+static void dz_hangup (struct tty_struct *);
+static void show_serial_version (void);
+
+static int dz_write (struct tty_struct *, int, const unsigned char *, int);
+static int dz_write_room (struct tty_struct *);
+static int dz_chars_in_buffer (struct tty_struct *);
+static int startup (struct dz_serial *);
+static int get_serial_info (struct dz_serial *, struct serial_struct *);
+static int set_serial_info (struct dz_serial *, struct serial_struct *);
+static int get_lsr_info (struct dz_serial *, unsigned int *);
+static int dz_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long);
+static int block_til_ready (struct tty_struct *, struct file *, struct dz_serial *);
+static int dz_open (struct tty_struct *, struct file *);
+
+#ifdef MODULE
+int init_module (void)
+void cleanup_module (void)
+#endif
+
+#endif
+
+#endif /* DZ_SERIAL_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/isicom.c linux.pre11.3/drivers/char/isicom.c
--- linux.vanilla/drivers/char/isicom.c	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/char/isicom.c	Mon Jul 19 23:58:42 1999
@@ -14,7 +14,8 @@
  *					Printk clean up
  *	9/12/98	alan@redhat.com		Rough port to 2.1.x
  *
- *
+ *	10/6/99 sameer			Merged the ISA and PCI drivers to
+ *					a new unified driver.
  *	***********************************************************
  *
  *	To use this driver you also need the support package. You 
@@ -51,8 +52,21 @@
 #include <asm/io.h>
 #include <asm/system.h>
 
+#include <linux/pci.h>
+
 #include <linux/isicom.h>
 
+static int device_id[] = {      0x2028,
+				0x2051,
+				0x2052,
+				0x2053,
+				0x2054,
+				0x2055,
+				0x2056,
+				0x2057,
+				0x2058
+			};
+
 static int isicom_refcount = 0;
 static int prev_card = 3;	/*	start servicing isi_card[0]	*/
 static struct isi_board * irq_to_board[16] = { NULL, };
@@ -147,7 +161,7 @@
 static int ISILoad_ioctl(struct inode *inode, struct file *filp,
 		         unsigned int cmd, unsigned long arg)
 {
-	unsigned int card, i, j, signature, status;
+	unsigned int card, i, j, signature, status, portcount = 0;
 	unsigned short word_count, base;
 	bin_frame frame;
 	/* exec_record exec_rec; */
@@ -180,19 +194,38 @@
 				printk(".");
 			}	
 			signature=(inw(base+0x4)) & 0xff;	
-				
-			if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
+			if (isi_card[card].isa) {
+					
+				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));
+					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;					
-			}
-				
+					printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+					return -EIO;					
+				}
+			}	
+			else {
+				portcount = inw(base+0x2);
+				if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {	
+#ifdef ISICOM_DEBUG
+					printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
+#endif
+					printk("\nISILoad:PCI 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;
+			case	0xdd:	
+					if (isi_card[card].isa) 
+						isi_card[card].port_count = 8;
+					else {
+						if (portcount == 4)
+							isi_card[card].port_count = 4;
+						else
+							isi_card[card].port_count = 8;
+					}	
 				     	isi_card[card].shift_count = 12;
 				     	break;
 				        
@@ -310,7 +343,8 @@
 			outw(0x0, base);
 			outw(0x0, base);
 			InterruptTheCard(base);
-			
+			outw(0x0, base+0x4);    /* for ISI4608 cards */
+							
 			isi_card[card].status |= FIRMWARE_LOADED;
 			return 0;	
 			
@@ -455,28 +489,7 @@
 				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;
@@ -531,12 +544,34 @@
 	unsigned char channel;
 	short byte_count;
 	
-	card = irq_to_board[irq];
+	/*
+	 *      find the source of interrupt
+	 */
+	 
+	for(count = 0; count < BOARD_COUNT; count++) { 
+		card = &isi_card[count];
+		if (card->base != 0) {
+			if (((card->isa == YES) && (card->irq == irq)) || 
+				((card->isa == NO) && (card->irq == irq) && (inw(card->base+0x0e) & 0x02)))
+				break;
+		}
+		card = NULL;
+	}
+
 	if (!card || !(card->status & FIRMWARE_LOADED)) {
-		printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);
+/*		printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);*/
 		return;
 	}
+	
 	base = card->base;
+	if (card->isa == NO) {
+	/*
+	 *      disable any interrupts from the PCI card and lower the
+	 *      interrupt line
+	 */
+		outw(0x8000, base+0x04);
+		ClearInterrupt(base);
+	}
 	
 	inw(base);		/* get the dummy word out */
 	header = inw(base);
@@ -548,12 +583,18 @@
 	if ((channel+1) > card->port_count) {
 		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
 				base, channel+1);
-		ClearInterrupt(base);		
+		if (card->isa)
+			ClearInterrupt(base);
+		else
+			outw(0x0000, base+0x04); /* enable interrupts */		
 		return;			
 	}
 	port = card->ports + channel;
 	if (!(port->flags & ASYNC_INITIALIZED)) {
-		ClearInterrupt(base);
+		if (card->isa)
+			ClearInterrupt(base);
+		else
+			outw(0x0000, base+0x04); /* enable interrupts */
 		return;
 	}	
 		
@@ -681,7 +722,10 @@
 		}
 		queue_task(&tty->flip.tqueue, &tq_timer);
 	}
-	ClearInterrupt(base);
+	if (card->isa == YES)
+		ClearInterrupt(base);
+	else
+		outw(0x0000, base+0x04); /* enable interrupts */	
 	return;
 } 
 
@@ -1023,12 +1067,11 @@
 		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;
-		}	
+	/*  open on a port greater than the port count for the card !!! */
+	if (line > ((board * 16) + card->port_count - 1)) {
+		printk(KERN_ERR "ISICOM: Open on a port which exceeds the port_count of the card!\n");
+		return -ENODEV;
+	}	
 	port = &isi_ports[line];	
 	if (isicom_paranoia_check(port, tty->device, "isicom_open"))
 		return -ENODEV;
@@ -1764,21 +1807,42 @@
 
 static int register_isr(void)
 {
-	int count, done=0;
+	int count, done=0, card;
+	unsigned char request;
 	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);
+		/*
+		 * verify if the required irq has already been requested for
+		 * another ISI Card, if so we already have it, else request it
+		 */
+			request = YES;
+			for(card = 0; card < count; card++)
+			if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
+				request = NO;
+				if ((isi_card[count].isa == NO) && (isi_card[card].isa == NO))
+					break;
+				/*
+				 * ISA cards cannot share interrupts with other
+				 * PCI or ISA devices hence disable this card.
+				 */
 				release_region(isi_card[count].base,16);
-				isi_card[count].base=0;
+				isi_card[count].base = 0;
+				break;
 			}
-			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++;
+			if (request == YES) { 
+				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++;
+				}
 			}
 		}	
 	}
@@ -1787,14 +1851,24 @@
 
 static void unregister_isr(void)
 {
-	int count;
-	for (count=0; count < BOARD_COUNT; count++ ) 
+	int count, card;
+	unsigned char freeirq;
+	for (count=0; count < BOARD_COUNT; count++ ) {
 		if (isi_card[count].base) {
-			free_irq(isi_card[count].irq, NULL);
+			freeirq = YES;
+			for(card = 0; card < count; card++)
+				if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
+					freeirq = NO;
+					break;
+				}
+			if (freeirq == YES) {
+				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			
+				printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);
+#endif	
+			}		
 		}
+	}
 }
 
 static int isicom_init(void)
@@ -1882,28 +1956,74 @@
 
 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))) {
+	struct pci_dev *dev = NULL;
+	int retval, card, idx, count;
+	unsigned char pciirq;
+	unsigned int ioaddr;
+	                
+	card = 0;
+	for(idx=0; idx < BOARD_COUNT; idx++) {	
+		if (io[idx]) {
+			isi_card[idx].base=io[idx];
+			isi_card[idx].irq=irq[idx];
+			isi_card[idx].isa=YES;
+			card++;
+		}
+		else {
+			isi_card[idx].base = 0;
+			isi_card[idx].irq = 0;
+		}
+	}
+	
+	for (idx=0 ;idx < card; idx++) {
+		if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
+		    (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
+		    (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
+		    (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
+		    (isi_card[idx].irq==15))) {
 			
-			if (isi_card[card].base) {
+			if (isi_card[idx].base) {
 				printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
-					isi_card[card].irq, card+1);
-				isi_card[card].base=0;
+					isi_card[idx].irq, idx+1);
+				isi_card[idx].base=0;
+				card--;
 			}	
 		}
 	}	
+	
+	if (pci_present() && (card < BOARD_COUNT)) {
+		for (idx=0; idx < DEVID_COUNT; idx++) {
+			dev = NULL;
+			for (;;){
+				if (!(dev = pci_find_device(VENDOR_ID, device_id[idx], dev)))
+					break;
+				if (card >= BOARD_COUNT)
+					break;
+					
+				/* found a PCI ISI card! */
+				ioaddr = dev->base_address[3]; /* i.e at offset 0x1c in the
+								* PCI configuration register
+								* space.
+								*/
+				ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
+				pciirq = dev->irq;
+				printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", device_id[idx]);
+				/*
+				 * allot the first empty slot in the array
+				 */				
+				for (count=0; count < BOARD_COUNT; count++) {				
+					if (isi_card[count].base == 0) {
+						isi_card[count].base = ioaddr;
+						isi_card[count].irq = pciirq;
+						isi_card[count].isa = NO;
+						card++;
+						break;
+					}
+				}
+			}				
+			if (card >= BOARD_COUNT) break;
+		}
+	}
 	
 	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"); 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/keyboard.c linux.pre11.3/drivers/char/keyboard.c
--- linux.vanilla/drivers/char/keyboard.c	Wed Apr 28 19:14:26 1999
+++ linux.pre11.3/drivers/char/keyboard.c	Mon Jul 19 23:27:49 1999
@@ -32,6 +32,7 @@
 #include <linux/string.h>
 #include <linux/random.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
@@ -155,6 +156,7 @@
 
 #ifdef CONFIG_MAGIC_SYSRQ
 static int sysrq_pressed;
+int sysrq_enabled = 1;
 #endif
 
 /*
@@ -247,7 +249,7 @@
 		sysrq_pressed = !up_flag;
 		return;
 	} else if (sysrq_pressed) {
-		if (!up_flag)
+		if (!up_flag && sysrq_enabled)
 			handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs, kbd, tty);
 		return;
 	}
@@ -321,15 +323,31 @@
 	}
 }
 
+#ifdef CONFIG_FORWARD_KEYBOARD
+extern int forward_chars;
 
 void put_queue(int ch)
 {
+	if (forward_chars == fg_console+1){
+		kbd_forward_char (ch);
+	} else {
+		wake_up(&keypress_wait);
+		if (tty) {
+			tty_insert_flip_char(tty, ch, 0);
+			con_schedule_flip(tty);
+		}
+	}
+}
+#else
+void put_queue(int ch)
+{
 	wake_up(&keypress_wait);
 	if (tty) {
 		tty_insert_flip_char(tty, ch, 0);
 		con_schedule_flip(tty);
 	}
 }
+#endif
 
 static void puts_queue(char *cp)
 {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/misc.c linux.pre11.3/drivers/char/misc.c
--- linux.vanilla/drivers/char/misc.c	Mon Mar 29 10:25:55 1999
+++ linux.pre11.3/drivers/char/misc.c	Mon Jul 19 23:27:49 1999
@@ -268,6 +268,12 @@
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_device_init();
 #endif
+#ifdef CONFIG_SGI_NEWPORT_GFX
+	gfx_register ();
+#endif
+#ifdef CONFIG_SGI
+	streamable_init ();
+#endif
 	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
 		printk("unable to get major %d for misc devices\n",
 		       MISC_MAJOR);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/pc_keyb.c linux.pre11.3/drivers/char/pc_keyb.c
--- linux.vanilla/drivers/char/pc_keyb.c	Wed Apr 28 19:14:26 1999
+++ linux.pre11.3/drivers/char/pc_keyb.c	Mon Jul 19 23:27:52 1999
@@ -23,7 +23,6 @@
 #include <linux/tty.h>
 #include <linux/mm.h>
 #include <linux/signal.h>
-#include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/kbd_ll.h>
 #include <linux/delay.h>
@@ -34,15 +33,13 @@
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/system.h>
-#include <asm/irq.h>
 
 /* Some configuration switches are present in the include file... */
 
-#include "pc_keyb.h"
+#include <linux/pc_keyb.h>
 
 /* Simple translation table for the SysRq keys */
 
@@ -57,10 +54,11 @@
 	"\r\000/";					/* 0x60 - 0x6f */
 #endif
 
-static void kbd_write(int address, int data);
-static unsigned char handle_kbd_event(void);
+static void kbd_write_command_w(int data);
+static void kbd_write_output_w(int data);
 
 spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
 
 /* used only by send_data - set by keyboard_interrupt */
 static volatile unsigned char reply_expected = 0;
@@ -84,11 +82,6 @@
 #define AUX_INTS_ON  (KBD_MODE_KCC | KBD_MODE_SYS | KBD_MODE_MOUSE_INT | KBD_MODE_KBD_INT)
 
 #define MAX_RETRIES	60		/* some aux operations take long time*/
-
-#ifndef AUX_IRQ
-# define AUX_IRQ	12
-#endif
-
 #endif /* CONFIG_PSMOUSE */
 
 /*
@@ -426,13 +419,13 @@
  */
 static unsigned char handle_kbd_event(void)
 {
-	unsigned char status = inb(KBD_STATUS_REG);
+	unsigned char status = kbd_read_status();
+	unsigned int work = 10000;
 
 	while (status & KBD_STAT_OBF) {
 		unsigned char scancode;
 
-		scancode = inb(KBD_DATA_REG);
-
+		scancode = kbd_read_input();
 		if (status & KBD_STAT_MOUSE_OBF) {
 			handle_mouse_event(scancode);
 		} else {
@@ -441,7 +434,14 @@
 			mark_bh(KEYBOARD_BH);
 		}
 
-		status = inb(KBD_STATUS_REG);
+		status = kbd_read_status();
+		
+		if(!work--)
+		{
+			printk(KERN_ERR "pc_keyb: controller jammed (0x%02X).\n",
+				status);
+			break;
+		}
 	}
 
 	return status;
@@ -476,7 +476,7 @@
 		acknowledge = 0; /* Set by interrupt routine on receipt of ACK. */
 		resend = 0;
 		reply_expected = 1;
-		kbd_write(KBD_DATA_REG, data);
+		kbd_write_output_w(data);
 		for (;;) {
 			if (acknowledge)
 				return 1;
@@ -527,14 +527,14 @@
 #define KBD_NO_DATA	(-1)	/* No data */
 #define KBD_BAD_DATA	(-2)	/* Parity or other error */
 
-static int __init kbd_read_input(void)
+static int __init kbd_read_data(void)
 {
 	int retval = KBD_NO_DATA;
 	unsigned char status;
 
-	status = inb(KBD_STATUS_REG);
+	status = kbd_read_status();
 	if (status & KBD_STAT_OBF) {
-		unsigned char data = inb(KBD_DATA_REG);
+		unsigned char data = kbd_read_input();
 
 		retval = data;
 		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
@@ -548,7 +548,7 @@
 	int maxread = 100;	/* Random number */
 
 	do {
-		if (kbd_read_input() == KBD_NO_DATA)
+		if (kbd_read_data() == KBD_NO_DATA)
 			break;
 	} while (--maxread);
 }
@@ -558,7 +558,7 @@
 	long timeout = KBD_INIT_TIMEOUT;
 
 	do {
-		int retval = kbd_read_input();
+		int retval = kbd_read_data();
 		if (retval >= 0)
 			return retval;
 		mdelay(1);
@@ -566,13 +566,23 @@
 	return -1;
 }
 
-static void kbd_write(int address, int data)
+static void kbd_write_command_w(int data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	kb_wait();
+	kbd_write_command(data);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+}
+
+static void kbd_write_output_w(int data)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 	kb_wait();
-	outb(data, address);
+	kbd_write_output(data);
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
@@ -583,9 +593,9 @@
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 	kb_wait();
-	outb(KBD_CCMD_WRITE_MODE, KBD_CNTL_REG);
+	kbd_write_command(KBD_CCMD_WRITE_MODE);
 	kb_wait();
-	outb(cmd, KBD_DATA_REG);
+	kbd_write_output(cmd);
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 #endif /* CONFIG_PSMOUSE */
@@ -599,7 +609,7 @@
 	 * This seems to be the only way to get it going.
 	 * If the test is successful a x55 is placed in the input buffer.
 	 */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_SELF_TEST);
+	kbd_write_command_w(KBD_CCMD_SELF_TEST);
 	if (kbd_wait_for_input() != 0x55)
 		return "Keyboard failed self test";
 
@@ -608,14 +618,14 @@
 	 * to test the keyboard clock and data lines.  The results of the
 	 * test are placed in the input buffer.
 	 */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_TEST);
+	kbd_write_command_w(KBD_CCMD_KBD_TEST);
 	if (kbd_wait_for_input() != 0x00)
 		return "Keyboard interface failed self test";
 
 	/*
 	 * Enable the keyboard by allowing the keyboard clock to run.
 	 */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_KBD_ENABLE);
+	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
 
 	/*
 	 * Reset keyboard. If the read times out
@@ -626,7 +636,7 @@
 	 * Set up to try again if the keyboard asks for RESEND.
 	 */
 	do {
-		kbd_write(KBD_DATA_REG, KBD_CMD_RESET);
+		kbd_write_output_w(KBD_CMD_RESET);
 		status = kbd_wait_for_input();
 		if (status == KBD_REPLY_ACK)
 			break;
@@ -644,7 +654,7 @@
 	 * Set up to try again if the keyboard asks for RESEND.
 	 */
 	do {
-		kbd_write(KBD_DATA_REG, KBD_CMD_DISABLE);
+		kbd_write_output_w(KBD_CMD_DISABLE);
 		status = kbd_wait_for_input();
 		if (status == KBD_REPLY_ACK)
 			break;
@@ -652,37 +662,37 @@
 			return "Disable keyboard: no ACK";
 	} while (1);
 
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_WRITE_MODE);
-	kbd_write(KBD_DATA_REG, KBD_MODE_KBD_INT
+	kbd_write_command_w(KBD_CCMD_WRITE_MODE);
+	kbd_write_output_w(KBD_MODE_KBD_INT
 			      | KBD_MODE_SYS
 			      | KBD_MODE_DISABLE_MOUSE
 			      | KBD_MODE_KCC);
 
 	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_READ_MODE);
+	kbd_write_command_w(KBD_CCMD_READ_MODE);
 	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
 		/*
 		 * If the controller does not support conversion,
 		 * Set the keyboard to scan-code set 1.
 		 */
-		kbd_write(KBD_DATA_REG, 0xF0);
+		kbd_write_output_w(0xF0);
 		kbd_wait_for_input();
-		kbd_write(KBD_DATA_REG, 0x01);
+		kbd_write_output_w(0x01);
 		kbd_wait_for_input();
 	}
 
 	
-	kbd_write(KBD_DATA_REG, KBD_CMD_ENABLE);
+	kbd_write_output_w(KBD_CMD_ENABLE);
 	if (kbd_wait_for_input() != KBD_REPLY_ACK)
 		return "Enable keyboard: no ACK";
 
 	/*
 	 * Finally, set the typematic rate to maximum.
 	 */
-	kbd_write(KBD_DATA_REG, KBD_CMD_SET_RATE);
+	kbd_write_output_w(KBD_CMD_SET_RATE);
 	if (kbd_wait_for_input() != KBD_REPLY_ACK)
 		return "Set rate: no ACK";
-	kbd_write(KBD_DATA_REG, 0x00);
+	kbd_write_output_w(0x00);
 	if (kbd_wait_for_input() != KBD_REPLY_ACK)
 		return "Set rate: no ACK";
 
@@ -691,8 +701,7 @@
 
 void __init pckbd_init_hw(void)
 {
-	/* Get the keyboard controller registers (incomplete decode) */
-	request_region(0x60, 16, "keyboard");
+	kbd_request_region();
 
 	/* Flush any pending input. */
 	kbd_clear_input();
@@ -708,7 +717,7 @@
 #endif
 
 	/* Ok, finally allocate the IRQ, and off we go.. */
-	request_irq(KEYBOARD_IRQ, keyboard_interrupt, 0, "keyboard", NULL);
+	kbd_request_irq(keyboard_interrupt);
 }
 
 #if defined CONFIG_PSMOUSE
@@ -732,16 +741,16 @@
 	 * controller has an Auxiliary Port (a.k.a. Mouse Port).
 	 */
 	kb_wait();
-	outb(KBD_CCMD_WRITE_AUX_OBUF, KBD_CNTL_REG);
+	kbd_write_command(KBD_CCMD_WRITE_AUX_OBUF);
 
 	kb_wait();
-	outb(0x5a, KBD_DATA_REG); /* 0x5a is a random dummy value. */
+	kbd_write_output(0x5a); /* 0x5a is a random dummy value. */
 
 	do {
-		unsigned char status = inb(KBD_STATUS_REG);
+		unsigned char status = kbd_read_status();
 
 		if (status & KBD_STAT_OBF) {
-			(void) inb(KBD_DATA_REG);
+			(void) kbd_read_input();
 			if (status & KBD_STAT_MOUSE_OBF) {
 				printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
 				retval = 1;
@@ -764,9 +773,9 @@
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 	kb_wait();
-	outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
+	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
 	kb_wait();
-	outb(val, KBD_DATA_REG);
+	kbd_write_output(val);
 	spin_unlock_irqrestore(&kbd_controller_lock, flags);
 }
 
@@ -779,9 +788,9 @@
 
 	spin_lock_irqsave(&kbd_controller_lock, flags);
 	kb_wait();
-	outb(KBD_CCMD_WRITE_MOUSE, KBD_CNTL_REG);
+	kbd_write_command(KBD_CCMD_WRITE_MOUSE);
 	kb_wait();
-	outb(val, KBD_DATA_REG);
+	kbd_write_output(val);
 	/* we expect an ACK in response. */
 	mouse_reply_expected++;
 	kb_wait();
@@ -828,8 +837,8 @@
 	if (--aux_count)
 		return 0;
 	kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE);
-	free_irq(AUX_IRQ, AUX_DEV);
+	kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
+	aux_free_irq(AUX_DEV);
 	return 0;
 }
 
@@ -844,11 +853,11 @@
 		return 0;
 	}
 	queue->head = queue->tail = 0;		/* Flush input queue */
-	if (request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {
+	if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
 		aux_count--;
 		return -EBUSY;
 	}
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable the
+	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
 							   auxiliary port on
 							   controller. */
 	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
@@ -967,14 +976,14 @@
 	queue->proc_list = NULL;
 
 #ifdef INITIALIZE_MOUSE
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable Aux. */
+	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE); /* Enable Aux. */
 	aux_write_ack(AUX_SET_SAMPLE);
 	aux_write_ack(100);			/* 100 samples/sec */
 	aux_write_ack(AUX_SET_RES);
 	aux_write_ack(3);			/* 8 counts per mm */
 	aux_write_ack(AUX_SET_SCALE21);		/* 2:1 scaling */
 #endif /* INITIALIZE_MOUSE */
-	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
+	kbd_write_command(KBD_CCMD_MOUSE_DISABLE); /* Disable aux device. */
 	kbd_write_cmd(AUX_INTS_OFF); /* Disable controller ints. */
 
 	return 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/pc_keyb.h linux.pre11.3/drivers/char/pc_keyb.h
--- linux.vanilla/drivers/char/pc_keyb.h	Tue Feb 23 14:21:33 1999
+++ linux.pre11.3/drivers/char/pc_keyb.h	Thu Jan  1 01:00:00 1970
@@ -1,130 +0,0 @@
-/*
- *	linux/drivers/char/pc_keyb.h
- *
- *	PC Keyboard And Keyboard Controller
- *
- *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
- */
-
-/*
- *	Configuration Switches
- */
-
-#undef KBD_REPORT_ERR			/* Report keyboard errors */
-#define KBD_REPORT_UNKN			/* Report unknown scan codes */
-#define KBD_REPORT_TIMEOUTS		/* Report keyboard timeouts */
-#undef KBD_IS_FOCUS_9000		/* We have the brain-damaged FOCUS-9000 keyboard */
-#undef INITIALIZE_MOUSE			/* Define if your PS/2 mouse needs initialization. */
-
-
-
-#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
-#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
-#define KBD_TIMEOUT 1000		/* Timeout in ms for keyboard command acknowledge */
-
-/*
- *	Internal variables of the driver
- */
-
-extern unsigned char pckbd_read_mask;
-extern unsigned char aux_device_present;
-
-/*
- *	Keyboard Controller Registers
- */
-
-#define KBD_STATUS_REG		0x64	/* Status register (R) */
-#define KBD_CNTL_REG		0x64	/* Controller command register (W) */
-#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
-
-/*
- *	Keyboard Controller Commands
- */
-
-#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */
-#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */
-#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */
-#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
-#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */
-#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */
-#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */
-#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */
-#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */
-#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */
-#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
-					   initiated by the auxiliary device */
-#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */
-
-/*
- *	Keyboard Commands
- */
-
-#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
-#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
-#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
-#define KBD_CMD_DISABLE		0xF5	/* Disable scanning */
-#define KBD_CMD_RESET		0xFF	/* Reset */
-
-/*
- *	Keyboard Replies
- */
-
-#define KBD_REPLY_POR		0xAA	/* Power on reset */
-#define KBD_REPLY_ACK		0xFA	/* Command ACK */
-#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
-
-/*
- *	Status Register Bits
- */
-
-#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
-#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */
-#define KBD_STAT_SELFTEST	0x04	/* Self test successful */
-#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */
-#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */
-#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
-#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */
-#define KBD_STAT_PERR 		0x80	/* Parity error */
-
-#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
-
-/*
- *	Controller Mode Register Bits
- */
-
-#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */
-#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */
-#define KBD_MODE_SYS 		0x04	/* The system flag (?) */
-#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */
-#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */
-#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
-#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */
-#define KBD_MODE_RFU		0x80
-
-/*
- *	Mouse Commands
- */
-
-#define AUX_SET_RES		0xE8	/* Set resolution */
-#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
-#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
-#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
-#define AUX_SET_STREAM		0xEA	/* Set stream mode */
-#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
-#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
-#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
-#define AUX_RESET		0xFF	/* Reset aux device */
-#define AUX_ACK			0xFA	/* Command byte ACK. */
-
-#define AUX_BUF_SIZE		2048	/* This might be better divisible by
-					   three to make overruns stay in sync
-					   but then the read function would need
-					   a lock etc - ick */
-
-struct aux_queue {
-	unsigned long head;
-	unsigned long tail;
-	struct wait_queue *proc_list;
-	struct fasync_struct *fasync;
-	unsigned char buf[AUX_BUF_SIZE];
-};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/qpmouse.c linux.pre11.3/drivers/char/qpmouse.c
--- linux.vanilla/drivers/char/qpmouse.c	Sun Nov  8 15:10:12 1998
+++ linux.pre11.3/drivers/char/qpmouse.c	Mon Jul 19 23:27:52 1999
@@ -42,7 +42,7 @@
 #include <asm/system.h>
 #include <asm/semaphore.h>
 
-#include "pc_keyb.h"		/* mouse enable command.. */
+#include <linux/pc_keyb.h>		/* mouse enable command.. */
 
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-cadet.c linux.pre11.3/drivers/char/radio-cadet.c
--- linux.vanilla/drivers/char/radio-cadet.c	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/char/radio-cadet.c	Mon Jul 19 23:27:55 1999
@@ -1,7 +1,7 @@
-/* cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card 
+/* radio-cadet.c - A video4linux driver for the ADS Cadet AM/FM Radio Card 
  *
  * by Fred Gleason <fredg@wava.com>
- * Version 0.3.2
+ * Version 0.3.3
  *
  * (Loosely) based on code for the Aztech radio card by
  *
@@ -346,17 +346,13 @@
 static long cadet_read(struct video_device *v,char *buf,unsigned long count,
 		       int nonblock)
 {
-        int i=0,c;
+        int i=0;
 	unsigned char readbuf[RDS_BUFFER];
 
         if(rdsstat==0) {
 	        cadet_lock++;
 	        rdsstat=1;
 		outb(0x80,io);        /* Select RDS fifo */
-		c=3*(inb(io)&0x03);
-		for(i=0;i<c;i++) {    /* Flush the fifo */
-		        inb(io+1);
-		}
 		cadet_lock--;
 		init_timer(&readtimer);
 		readtimer.function=cadet_handler;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/radio-gemtek.c linux.pre11.3/drivers/char/radio-gemtek.c
--- linux.vanilla/drivers/char/radio-gemtek.c	Fri Apr 16 22:10:52 1999
+++ linux.pre11.3/drivers/char/radio-gemtek.c	Mon Jul 19 23:27:55 1999
@@ -282,7 +282,7 @@
 MODULE_AUTHOR("Jonas Munsin");
 MODULE_DESCRIPTION("A driver for the GemTek Radio Card");
 MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c)");
+MODULE_PARM_DESC(io, "I/O address of the GemTek card (0x20c, 0x30c, 0x24c or 0x34c (or 0x248 for the combined sound/radiocard))");
 
 EXPORT_NO_SYMBOLS;
 
@@ -290,7 +290,7 @@
 {
 	if(io==-1)
 	{
-		printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c\n");
+		printk(KERN_ERR "You must set an I/O address with io=0x20c, io=0x30c, io=0x24c or io=0x34c (or io=0x248 for the combined sound/radiocard)\n");
 		return -EINVAL;
 	}
 	return gemtek_init(NULL);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/serial.c linux.pre11.3/drivers/char/serial.c
--- linux.vanilla/drivers/char/serial.c	Wed Mar 24 10:55:16 1999
+++ linux.pre11.3/drivers/char/serial.c	Mon Jul 19 23:27:49 1999
@@ -103,7 +103,8 @@
 #define RS_STROBE_TIME (10*HZ)
 #define RS_ISR_PASS_LIMIT 256
 
-#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+#define IRQ_T(state) \
+ ((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
 #define SERIAL_INLINE
   
@@ -1003,7 +1004,7 @@
 		} else 
 			handler = rs_interrupt_single;
 
-		retval = request_irq(state->irq, handler, IRQ_T(info),
+		retval = request_irq(state->irq, handler, IRQ_T(state),
 				     "serial", NULL);
 		if (retval) {
 			if (capable(CAP_SYS_ADMIN)) {
@@ -1168,7 +1169,7 @@
 		if (IRQ_ports[state->irq]) {
 			free_irq(state->irq, NULL);
 			retval = request_irq(state->irq, rs_interrupt_single,
-					     IRQ_T(info), "serial", NULL);
+					     IRQ_T(state), "serial", NULL);
 			
 			if (retval)
 				printk("serial shutdown: request_irq: error %d"
@@ -2017,7 +2018,7 @@
 		else
 			handler = rs_interrupt;
 
-		retval = request_irq(state->irq, handler, IRQ_T(info),
+		retval = request_irq(state->irq, handler, IRQ_T(state),
 				     "serial", NULL);
 		if (retval) {
 			printk("Couldn't reallocate serial interrupt "
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/videodev.c linux.pre11.3/drivers/char/videodev.c
--- linux.vanilla/drivers/char/videodev.c	Tue Jun 15 16:49:48 1999
+++ linux.pre11.3/drivers/char/videodev.c	Mon Jul 19 23:27:52 1999
@@ -63,6 +63,9 @@
 #ifdef CONFIG_RADIO_RTRACK
 extern int rtrack_init(struct video_init *);
 #endif
+#ifdef CONFIG_RADIO_RTRACK2
+extern int rtrack2_init(struct video_init *);
+#endif
 #ifdef CONFIG_RADIO_SF16FMI
 extern int fmi_init(struct video_init *);
 #endif
@@ -81,6 +84,9 @@
 #ifdef CONFIG_VIDEO_PMS
 extern int init_pms_cards(struct video_init *);
 #endif
+#ifdef CONFIG_VIDEO_ZORAN
+extern int init_zoran_cards(struct video_init *);
+#endif
 
 static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
@@ -108,6 +114,9 @@
 #ifdef CONFIG_RADIO_RTRACK
 	{"RTrack", rtrack_init}, 
 #endif 
+#ifdef CONFIG_RADIO_RTRACK2
+	{"RTrack2", rtrack2_init}, 
+#endif
 #ifdef CONFIG_RADIO_SF16FMI
 	{"SF16FMI", fmi_init}, 
 #endif	
@@ -123,6 +132,9 @@
 #ifdef CONFIG_RADIO_TYPHOON
 	{"radio-typhoon", typhoon_init},
 #endif
+#ifdef CONFIG_VIDEO_ZORAN
+	{"zoran", init_zoran_cards},
+#endif	
 	{"end", NULL}
 };
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/vino.c linux.pre11.3/drivers/char/vino.c
--- linux.vanilla/drivers/char/vino.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/char/vino.c	Mon Jul 19 23:27:54 1999
@@ -0,0 +1,276 @@
+/* $Id: vino.c,v 1.4 1999/02/09 23:59:36 ulfc Exp $
+ * drivers/char/vino.c
+ *
+ * (incomplete) Driver for the Vino Video input system found in SGI Indys.
+ *
+ * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
+ *
+ * This isn't complete yet, please don't expect any video until I've written
+ * some more code.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/videodev.h>
+
+#include <asm/addrspace.h>
+#include <asm/system.h>
+
+#include "vino.h"
+
+struct vino_device {
+	struct video_device vdev;
+
+	unsigned long chan;
+#define VINO_CHAN_A		0
+#define VINO_CHAN_B		1
+
+	unsigned long flags;
+#define VINO_DMA_ACTIVE		(1<<0)
+};
+
+/* We can actually receive TV and IndyCam input at the same time. Believe it or
+ * not..
+ */
+static struct vino_device vino[2];
+
+/* Those registers have to be accessed by either *one* 64 bit write or *one* 64
+ * bit read. We need some asm to fix this. We can't use mips3 as standard
+ * because we just save 32 bits at context switch.
+ */
+
+static __inline__ unsigned long long vino_reg_read(unsigned long addr)
+{
+	unsigned long long ret __attribute__ ((aligned (64)));
+	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+	unsigned long flags;
+
+	save_and_cli(flags);
+	__asm__ __volatile__(
+		".set\tmips3\n\t"
+		".set\tnoat\n\t"
+		"ld\t$1,(%0)\n\t"
+		"sd\t$1,(%1)\n\t"
+		".set\tat\n\t"
+		".set\tmips0"
+		:
+		:"r" (virt_addr),
+		 "r" (&ret)
+		:"$1");
+	restore_flags(flags);
+
+	return ret;
+}
+
+static __inline__ void vino_reg_write(unsigned long long value,
+				      unsigned long addr)
+{
+	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+	unsigned long flags;
+
+	/* we might lose the upper parts of the registers which are not saved
+	 * if there comes an interrupt in our way, play safe */
+
+	save_and_cli(flags);
+	__asm__ __volatile__(
+		".set\tmips3\n\t"
+		".set\tnoat\n\t"
+		"ld\t$1,(%0)\n\t"
+		"sd\t$1,(%1)\n\t"
+		".set\tat\n\t"
+		".set\tmips0"
+		:
+		:"r" (&value),
+		 "r" (virt_addr)
+		:"$1");
+	restore_flags(flags);
+}
+
+static __inline__ void vino_reg_and(unsigned long long value,
+				    unsigned long addr)
+{
+	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+	unsigned long flags;
+
+	save_and_cli(flags);
+	__asm__ __volatile__(
+		".set\tmips3\n\t"
+		".set\tnoat\n\t"
+		"ld\t$1,(%0)\n\t"
+		"ld\t$2,(%1)\n\t"
+		"and\t$1,$1,$2\n\t"
+		"sd\t$1,(%0)\n\t"
+		".set\tat\n\t"
+		".set\tmips0"
+		:
+		:"r" (virt_addr),
+		 "r" (&value)
+		:"$1","$2");
+	restore_flags(flags);
+}
+
+static __inline__ void vino_reg_or(unsigned long long value,
+				   unsigned long addr)
+{
+	unsigned long virt_addr = KSEG1ADDR(addr + VINO_BASE);
+	unsigned long flags;
+
+	save_and_cli(flags);
+	__asm__ __volatile__(
+		".set\tmips3\n\t"
+		".set\tnoat\n\t"
+		"ld\t$1,(%0)\n\t"
+		"ld\t$2,(%1)\n\t"
+		"or\t$1,$1,$2\n\t"
+		"sd\t$1,(%0)\n\t"
+		".set\tat\n\t"
+		".set\tmips0"
+		:
+		:"r" (virt_addr),
+		 "r" (&value)
+		:"$1","$2");
+	restore_flags(flags);
+}
+
+static int vino_dma_setup(void)
+{
+	return 0;
+}
+
+static void vino_dma_stop(void)
+{
+
+}
+
+static int vino_init(void)
+{
+	unsigned long ret;
+	unsigned short rev, id;
+	unsigned long long foo;
+	unsigned long *bar;
+
+	bar = (unsigned long *) &foo;
+
+	ret = vino_reg_read(VINO_REVID);
+
+	rev = (ret & VINO_REVID_REV_MASK);
+	id = (ret & VINO_REVID_ID_MASK) >> 4;
+
+	printk("Vino: ID:%02hx Rev:%02hx\n", id, rev);
+
+	foo = vino_reg_read(VINO_A_DESC_DATA0);
+	printk("0x%lx", bar[0]);
+	printk("%lx ", bar[1]);
+	foo = vino_reg_read(VINO_A_DESC_DATA1);
+	printk("0x%lx", bar[0]);
+	printk("%lx ", bar[1]);
+	foo = vino_reg_read(VINO_A_DESC_DATA2);
+	printk("0x%lx", bar[0]);
+	printk("%lx ", bar[1]);
+	foo = vino_reg_read(VINO_A_DESC_DATA3);
+	printk("0x%lx", bar[0]);
+	printk("%lx\n", bar[1]);
+	foo = vino_reg_read(VINO_B_DESC_DATA0);
+	printk("0x%lx", bar[0]);
+	printk("%lx ", bar[1]);
+	foo = vino_reg_read(VINO_B_DESC_DATA1);
+	printk("0x%lx", bar[0]);
+	printk("%lx ", bar[1]);
+	foo = vino_reg_read(VINO_B_DESC_DATA2);
+	printk("0x%lx", bar[0]);
+	printk("%lx ", bar[1]);
+	foo = vino_reg_read(VINO_B_DESC_DATA3);
+	printk("0x%lx", bar[0]);
+	printk("%lx\n", bar[1]);
+
+	return 0;
+}
+
+static void vino_dma_go(struct vino_device *v)
+{
+	
+}
+
+/* Reset the vino back to default state */
+
+static void vino_setup(struct vino_device *v)
+{
+	
+}
+
+static int vino_open(struct video_device *dev, int flags)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void vino_close(struct video_device *dev)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+static int vino_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	return 0;
+}
+
+static int vino_mmap(struct video_device *dev, const char *adr,
+		     unsigned long size)
+{
+	return 0;
+}
+
+static struct video_device vino_dev = {
+	"Vino IndyCam/TV",
+	VID_TYPE_CAPTURE,
+	VID_HARDWARE_VINO,
+	vino_open,
+	vino_close,
+	NULL,		/* vino_read */
+	NULL,		/* vino_write */
+	NULL,		/* vino_poll */
+	vino_ioctl,
+	vino_mmap,
+	NULL,		/* vino_init */
+	NULL,
+	0,
+	0
+};
+
+__initfunc(int init_vino(struct video_device *dev))
+{
+	int err;
+
+	err = vino_init();
+	if (err)
+		return err;
+
+#if 0
+	if (video_register_device(&vinodev, VFL_TYPE_GRABBER) == -1) {
+		return -ENODEV;
+	}
+#endif
+
+	return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	int err;
+
+	err = vino_init();
+	if (err)
+		return err;
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/vino.h linux.pre11.3/drivers/char/vino.h
--- linux.vanilla/drivers/char/vino.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/char/vino.h	Mon Jul 19 23:27:55 1999
@@ -0,0 +1,118 @@
+/* $Id: vino.h,v 1.2 1999/02/09 23:03:53 ulfc Exp $
+ * drivers/sgi/vino.h
+ *
+ * Copyright (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
+ */
+
+#define VINO_BASE		0x0008000
+
+#define VINO_REVID		0x0000
+#define VINO_CTRL		0x0008
+#define VINO_INTSTAT		0x0010	/* Interrupt status */
+#define VINO_I2C_CTRL		0x0018
+#define VINO_I2C_DATA		0x0020
+#define VINO_A_ALPHA		0x0028	/* Channel A ... */
+#define VINO_A_CLIPS		0x0030	/* Clipping start */
+#define VINO_A_CLIPE		0x0038	/* Clipping end */
+#define VINO_A_FRAMERT		0x0040	/* Framerate */
+#define VINO_A_FLDCNT		0x0048	/* Field counter */
+#define VINO_A_LNSZ		0x0050
+#define VINO_A_LNCNT		0x0058
+#define VINO_A_PGIX		0x0060	/* Page index */
+#define VINO_A_DESC_PTR		0x0068	/* Ptr to next four descriptors */
+#define VINO_A_DESC_TLB_PTR	0x0070	/* Ptr to start of descriptor table */
+#define VINO_A_DESC_DATA0	0x0078	/* Descriptor data 0 */
+#define VINO_A_DESC_DATA1	0x0080	/* ... */
+#define VINO_A_DESC_DATA2	0x0088
+#define VINO_A_DESC_DATA3	0x0090
+#define VINO_A_FIFO_THRESHOLD	0x0098	/* FIFO threshold */
+#define VINO_A_FIFO_RP		0x00a0
+#define VINO_A_FIFO_WP		0x00a8
+#define VINO_B_ALPHA		0x00b0	/* Channel B ... */
+#define VINO_B_CLIPS		0x00b8
+#define VINO_B_CLIPE		0x00c0
+#define VINO_B_FRAMERT		0x00c8
+#define VINO_B_FLDCNT		0x00d0
+#define VINO_B_LNSZ		0x00d8
+#define VINO_B_LNCNT		0x00e0
+#define VINO_B_PGIX		0x00e8
+#define VINO_B_DESC_PTR		0x00f0
+#define VINO_B_DESC_TLB_PTR	0x00f8
+#define VINO_B_DESC_DATA0	0x0100
+#define VINO_B_DESC_DATA1	0x0108
+#define VINO_B_DESC_DATA2	0x0110
+#define VINO_B_DESC_DATA3	0x0118
+#define VINO_B_FIFO_THRESHOLD	0x0120
+#define VINO_B_FIFO_RP		0x0128
+#define VINO_B_FIFO_WP		0x0130
+
+/* Bits in the VINO_REVID register */
+
+#define VINO_REVID_REV_MASK		0x000f	/* bits 0:3 */
+#define VINO_REVID_ID_MASK		0x00f0	/* bits 4:7 */
+
+/* Bits in the VINO_CTRL register */
+
+#define VINO_CTRL_LITTLE_ENDIAN		(1<<0)
+#define VINO_CTRL_A_FIELD_TRANS_INT	(1<<1)	/* Field transferred int */
+#define VINO_CTRL_A_FIFO_OF_INT		(1<<2)	/* FIFO overflow int */
+#define VINO_CTRL_A_END_DESC_TBL_INT	(1<<3)	/* End of desc table int */
+#define VINO_CTRL_B_FIELD_TRANS_INT	(1<<4)	/* Field transferred int */
+#define VINO_CTRL_B_FIFO_OF_INT		(1<<5)	/* FIFO overflow int */
+#define VINO_CTRL_B_END_DESC_TLB_INT	(1<<6)	/* End of desc table int */
+#define VINO_CTRL_A_DMA_ENBL		(1<<7)
+#define VINO_CTRL_A_INTERLEAVE_ENBL	(1<<8)
+#define VINO_CTRL_A_SYNC_ENBL		(1<<9)
+#define VINO_CTRL_A_SELECT		(1<<10)	/* 1=D1 0=Philips */
+#define VINO_CTRL_A_RGB			(1<<11)	/* 1=RGB 0=YUV */
+#define VINO_CTRL_A_LUMA_ONLY		(1<<12)
+#define VINO_CTRL_A_DEC_ENBL		(1<<13)	/* Decimation */
+#define VINO_CTRL_A_DEC_SCALE_MASK	0x1c000	/* bits 14:17 */
+#define VINO_CTRL_A_DEC_HOR_ONLY	(1<<17)	/* Horizontal only */
+#define VINO_CTRL_A_DITHER		(1<<18)	/* 24 -> 8 bit dither */
+#define VINO_CTRL_B_DMA_ENBL		(1<<19)
+#define VINO_CTRL_B_INTERLEAVE_ENBL	(1<<20)
+#define VINO_CTRL_B_SYNC_ENBL		(1<<21)
+#define VINO_CTRL_B_SELECT		(1<<22)	/* 1=D1 0=Philips */
+#define VINO_CTRL_B_RGB			(1<<22)	/* 1=RGB 0=YUV */
+#define VINO_CTRL_B_LUMA_ONLY		(1<<23)
+#define VINO_CTRL_B_DEC_ENBL		(1<<24)	/* Decimation */
+#define VINO_CTRL_B_DEC_SCALE_MASK	0x1c000000	/* bits 25:28 */
+#define VINO_CTRL_B_DEC_HOR_ONLY	(1<<29)	/* Decimation horizontal only */
+#define VINO_CTRL_B_DITHER		(1<<30)	/* ChanB 24 -> 8 bit dither */
+
+/* Bits in the Interrupt and Status register */
+
+#define VINO_INTSTAT_A_FIELD_TRANS	(1<<0)	/* Field transferred int */
+#define VINO_INTSTAT_A_FIFO_OF		(1<<1)	/* FIFO overflow int */
+#define VINO_INTSTAT_A_END_DESC_TBL	(1<<2)	/* End of desc table int */
+#define VINO_INTSTAT_B_FIELD_TRANS	(1<<3)	/* Field transferred int */
+#define VINO_INTSTAT_B_FIFO_OF		(1<<4)	/* FIFO overflow int */
+#define VINO_INTSTAT_B_END_DESC_TBL	(1<<5)	/* End of desc table int */
+
+/* Bits in the Clipping Start register */
+
+#define VINO_CLIPS_START		0x3ff		/* bits 0:9 */
+#define VINO_CLIPS_ODD_MASK		0x7fc00		/* bits 10:18 */
+#define VINO_CLIPS_EVEN_MASK		0xff80000	/* bits 19:27 */
+
+/* Bits in the Clipping End register */
+
+#define VINO_CLIPE_END			0x3ff		/* bits 0:9 */
+#define VINO_CLIPE_ODD_MASK		0x7fc00		/* bits 10:18 */
+#define VINO_CLIPE_EVEN_MASK		0xff80000	/* bits 19:27 */
+
+/* Bits in the Frame Rate register */
+
+#define VINO_FRAMERT_PAL		(1<<0)	/* 0=NTSC 1=PAL */
+#define VINO_FRAMERT_RT_MASK		0x1ffe		/* bits 1:12 */
+
+/* Bits in the VINO_I2C_CTRL */
+
+#define VINO_CTRL_I2C_IDLE		(1<<0)	/* write: 0=force idle
+						 * read: 0=idle 1=not idle */
+#define VINO_CTRL_I2C_DIR		(1<<1)	/* 0=read 1=write */
+#define VINO_CTRL_I2C_MORE_BYTES	(1<<2)	/* 0=last byte 1=more bytes */
+#define VINO_CTRL_I2C_TRANS_BUSY	(1<<4)	/* 0=trans done 1=trans busy */
+#define VINO_CTRL_I2C_ACK		(1<<5)	/* 0=ack received 1=ack not */
+#define VINO_CTRL_I2C_BUS_ERROR		(1<<7)	/* 0=no bus err 1=bus err */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/char/vt.c linux.pre11.3/drivers/char/vt.c
--- linux.vanilla/drivers/char/vt.c	Tue Feb 23 14:21:33 1999
+++ linux.pre11.3/drivers/char/vt.c	Mon Jul 19 23:27:49 1999
@@ -88,7 +88,8 @@
  * comments - KDMKTONE doesn't put the process to sleep.
  */
 
-#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) || defined(__mips__)
+#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
+    || (defined(__mips__) && !defined(CONFIG_SGI))
 
 static void
 kd_nosound(unsigned long ignored)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/Config.in linux.pre11.3/drivers/isdn/Config.in
--- linux.vanilla/drivers/isdn/Config.in	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/Config.in	Mon Jul 19 23:59:32 1999
@@ -9,6 +9,7 @@
   fi
 fi
 bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO
+bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
 if [ "$CONFIG_X25" != "n" ]; then
   bool 'X.25 PLP on top of ISDN (EXPERIMENTAL)' CONFIG_ISDN_X25
 fi
@@ -19,37 +20,53 @@
 if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
     bool 'HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
     if [ "$CONFIG_HISAX_EURO" != "n" ]; then
-	    bool 'Support for german tarifinfo' CONFIG_DE_AOC
-	    bool 'Support for australian Microlink service (not for std. EURO)' CONFIG_HISAX_ML
+	    bool 'Support for german chargeinfo' CONFIG_DE_AOC
+	    bool 'Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE
+	    bool 'Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC
     fi
     bool 'HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
     bool 'HiSax Support for Teles 16.0/8.0' CONFIG_HISAX_16_0
     bool 'HiSax Support for Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
-    bool 'HiSax Support for Teles 16.3c' CONFIG_HISAX_TELES3C 
+    bool 'HiSax Support for Teles PCI' CONFIG_HISAX_TELESPCI 
+    bool 'HiSax Support for Teles S0Box' CONFIG_HISAX_S0BOX 
     bool 'HiSax Support for AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+    bool 'HiSax Support for AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+    bool 'HiSax Support for AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
     bool 'HiSax Support for Elsa cards' CONFIG_HISAX_ELSA
     bool 'HiSax Support for ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
     bool 'HiSax Support for Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
     bool 'HiSax Support for ASUSCOM cards' CONFIG_HISAX_ASUSCOM
     bool 'HiSax Support for TELEINT cards' CONFIG_HISAX_TELEINT
-    bool 'HiSax Support for Sedlbauer speed card/win/star' CONFIG_HISAX_SEDLBAUER
+    bool 'HiSax Support for HFC-S based cards' CONFIG_HISAX_HFCS
+    bool 'HiSax Support for Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
     bool 'HiSax Support for USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
     bool 'HiSax Support for MIC card' CONFIG_HISAX_MIC
     bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
     bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
+    bool 'HiSax Support for Siemens I-Surf card' CONFIG_HISAX_ISURF
+    bool 'HiSax Support for HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+    bool 'HiSax Support for Telekom A4T card' CONFIG_HISAX_BKM_A4T
+    bool 'HiSax Support for Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+    bool 'HiSax Support for Gazel cards' CONFIG_HISAX_GAZEL
     if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-      if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
-        bool 'HiSax Support for SPARC Am7930' CONFIG_HISAX_AMD7930
-        bool 'HiSax Support for SPARC DBRI' CONFIG_HISAX_DBRI
-      fi
+	bool 'HiSax Support for HFC PCI-Bus cards (EXPERIMENTAL)' CONFIG_HISAX_HFC_PCI
+#	bool 'HiSax Support for TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+	if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+		bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+	fi
     fi
 fi
 if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
 	dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
 	dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
 fi
-dep_tristate 'AVM-B1 with CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
+dep_tristate 'Eicon.Diehl active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN
+dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
 if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
+    bool 'AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
+    bool 'AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
+    bool 'AVM T1/T1B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
+    bool 'AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
     bool 'Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
 fi
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/Makefile linux.pre11.3/drivers/isdn/Makefile
--- linux.vanilla/drivers/isdn/Makefile	Sun Nov  8 15:08:07 1998
+++ linux.pre11.3/drivers/isdn/Makefile	Mon Jul 19 23:59:32 1999
@@ -1,6 +1,6 @@
 SUB_DIRS     :=
 MOD_SUB_DIRS :=
-ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000
+ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert
 
 L_OBJS :=
 LX_OBJS :=
@@ -33,6 +33,7 @@
     OX_OBJS += isdn_common.o
     ifdef CONFIG_ISDN_PPP
       O_OBJS += isdn_ppp.o
+      M_OBJS += isdn_bsdcomp.o
     endif
     ifdef CONFIG_ISDN_X25
       O_OBJS += isdn_x25iface.o
@@ -44,6 +45,12 @@
   endif
 endif
 
+ifeq ($(CONFIG_ISDN_DIVERSION),y)
+ ifeq ($(CONFIG_MODULES),y)
+    MOD_SUB_DIRS += divert
+ endif
+endif
+
 ifeq ($(CONFIG_ISDN_DRV_HISAX),y)
   L_OBJS += hisax/hisax.o
   SUB_DIRS += hisax
@@ -111,6 +118,16 @@
 else
   ifeq ($(CONFIG_ISDN_DRV_ACT2000),m)
     MOD_SUB_DIRS += act2000
+  endif
+endif
+
+ifeq ($(CONFIG_ISDN_DRV_EICON),y)
+  L_OBJS += eicon/eicon.o
+  SUB_DIRS += eicon
+  MOD_SUB_DIRS += eicon
+else
+  ifeq ($(CONFIG_ISDN_DRV_EICON),m)
+    MOD_SUB_DIRS += eicon
   endif
 endif
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/act2000.h linux.pre11.3/drivers/isdn/act2000/act2000.h
--- linux.vanilla/drivers/isdn/act2000/act2000.h	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/isdn/act2000/act2000.h	Mon Jul 19 23:59:32 1999
@@ -1,8 +1,8 @@
-/* $Id: act2000.h,v 1.5 1997/10/09 22:22:59 fritz Exp $
+/* $Id: act2000.h,v 1.7 1999/04/12 13:13:54 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
  * Thanks to Friedemann Baitinger and IBM Germany
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: act2000.h,v $
+ * Revision 1.7  1999/04/12 13:13:54  fritz
+ * Made cards pointer static to avoid name-clash.
+ *
+ * Revision 1.6  1998/11/05 22:12:38  fritz
+ * Changed mail-address.
+ *
  * Revision 1.5  1997/10/09 22:22:59  fritz
  * New HL<->LL interface:
  *   New BSENT callback with nr. of bytes included.
@@ -212,8 +218,6 @@
         isdn_if interface;               /* Interface to upper layer         */
         char regname[35];                /* Name used for request_region     */
 } act2000_card;
-
-extern act2000_card *actcards;
 
 extern __inline__ void act2000_schedule_tx(act2000_card *card)
 {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/act2000_isa.c linux.pre11.3/drivers/isdn/act2000/act2000_isa.c
--- linux.vanilla/drivers/isdn/act2000/act2000_isa.c	Sun Nov  8 15:10:14 1998
+++ linux.pre11.3/drivers/isdn/act2000/act2000_isa.c	Mon Jul 19 23:59:32 1999
@@ -1,8 +1,8 @@
-/* $Id: act2000_isa.c,v 1.5 1998/02/12 23:06:47 keil Exp $
+/* $Id: act2000_isa.c,v 1.8 1999/01/05 18:29:25 he Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
  * Thanks to Friedemann Baitinger and IBM Germany
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,17 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: act2000_isa.c,v $
+ * Revision 1.8  1999/01/05 18:29:25  he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.7  1998/11/05 22:12:41  fritz
+ * Changed mail-address.
+ *
+ * Revision 1.6  1998/06/17 19:51:09  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
  * Revision 1.5  1998/02/12 23:06:47  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/act2000_isa.h linux.pre11.3/drivers/isdn/act2000/act2000_isa.h
--- linux.vanilla/drivers/isdn/act2000/act2000_isa.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/act2000/act2000_isa.h	Mon Jul 19 23:59:32 1999
@@ -1,8 +1,8 @@
-/* $Id: act2000_isa.h,v 1.1 1997/09/23 18:00:07 fritz Exp $
+/* $Id: act2000_isa.h,v 1.2 1998/11/05 22:12:43 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
  * Thanks to Friedemann Baitinger and IBM Germany
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: act2000_isa.h,v $
+ * Revision 1.2  1998/11/05 22:12:43  fritz
+ * Changed mail-address.
+ *
  * Revision 1.1  1997/09/23 18:00:07  fritz
  * New driver for IBM Active 2000.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/capi.c linux.pre11.3/drivers/isdn/act2000/capi.c
--- linux.vanilla/drivers/isdn/act2000/capi.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/act2000/capi.c	Mon Jul 19 23:59:32 1999
@@ -1,9 +1,9 @@
-/* $Id: capi.c,v 1.7 1998/02/23 23:35:41 fritz Exp $
+/* $Id: capi.c,v 1.8 1998/11/05 22:12:46 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *        CAPI encoder/decoder
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
  * Thanks to Friedemann Baitinger and IBM Germany
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: capi.c,v $
+ * Revision 1.8  1998/11/05 22:12:46  fritz
+ * Changed mail-address.
+ *
  * Revision 1.7  1998/02/23 23:35:41  fritz
  * Eliminated some compiler warnings.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/capi.h linux.pre11.3/drivers/isdn/act2000/capi.h
--- linux.vanilla/drivers/isdn/act2000/capi.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/act2000/capi.h	Mon Jul 19 23:59:32 1999
@@ -1,8 +1,8 @@
-/* $Id: capi.h,v 1.4 1997/10/01 09:21:04 fritz Exp $
+/* $Id: capi.h,v 1.5 1998/11/05 22:12:48 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
  * Thanks to Friedemann Baitinger and IBM Germany
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: capi.h,v $
+ * Revision 1.5  1998/11/05 22:12:48  fritz
+ * Changed mail-address.
+ *
  * Revision 1.4  1997/10/01 09:21:04  fritz
  * Removed old compatibility stuff for 2.0.X kernels.
  * From now on, this code is for 2.1.X ONLY!
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/act2000/module.c linux.pre11.3/drivers/isdn/act2000/module.c
--- linux.vanilla/drivers/isdn/act2000/module.c	Thu May 27 22:11:53 1999
+++ linux.pre11.3/drivers/isdn/act2000/module.c	Mon Jul 19 23:59:32 1999
@@ -1,8 +1,8 @@
-/* $Id: module.c,v 1.7 1998/02/12 23:06:52 keil Exp $
+/* $Id: module.c,v 1.9 1999/04/12 13:13:56 fritz Exp $
  *
  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
  *
- * Copyright 1997 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
  * Thanks to Friedemann Baitinger and IBM Germany
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: module.c,v $
+ * Revision 1.9  1999/04/12 13:13:56  fritz
+ * Made cards pointer static to avoid name-clash.
+ *
+ * Revision 1.8  1998/11/05 22:12:51  fritz
+ * Changed mail-address.
+ *
  * Revision 1.7  1998/02/12 23:06:52  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -57,7 +63,7 @@
 };
 #define ISA_NRPORTS (sizeof(isa_ports)/sizeof(unsigned short))
 
-act2000_card *actcards = (act2000_card *) NULL;
+static act2000_card *cards = (act2000_card *) NULL;
 
 /* Parameters to be set by insmod */
 static int   act_bus  =  0;
@@ -589,7 +595,7 @@
 static inline act2000_card *
 act2000_findcard(int driverid)
 {
-        act2000_card *p = actcards;
+        act2000_card *p = cards;
 
         while (p) {
                 if (p->myid == driverid)
@@ -714,8 +720,8 @@
         card->bus = bus;
         card->port = port;
         card->irq = irq;
-        card->next = actcards;
-        actcards = card;
+        card->next = cards;
+        cards = card;
 }
 
 /*
@@ -805,9 +811,9 @@
 				       bus);
 		}
 	}
-	if (!actcards)
+	if (!cards)
 		return 1;
-        p = actcards;
+        p = cards;
         while (p) {
 		initialized = 0;
 		if (!p->interface.statcallb) {
@@ -870,9 +876,9 @@
                                 kfree(p);
                                 p = q->next;
                         } else {
-                                actcards = p->next;
+                                cards = p->next;
                                 kfree(p);
-                                p = actcards;
+                                p = cards;
                         }
 			failed++;
                 }
@@ -890,9 +896,9 @@
 act2000_init(void)
 {
         printk(KERN_INFO "%s\n", DRIVERNAME);
-        if (!actcards)
+        if (!cards)
 		act2000_addcard(act_bus, act_port, act_irq, act_id);
-        if (!actcards)
+        if (!cards)
                 printk(KERN_INFO "act2000: No cards defined yet\n");
         /* No symbols to export, hide all symbols */
         EXPORT_NO_SYMBOLS;
@@ -903,14 +909,14 @@
 void
 cleanup_module(void)
 {
-        act2000_card *card = actcards;
+        act2000_card *card = cards;
         act2000_card *last;
         while (card) {
                 unregister_card(card);
 		del_timer(&card->ptimer);
                 card = card->next;
         }
-        card = actcards;
+        card = cards;
         while (card) {
                 last = card;
                 card = card->next;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/Makefile linux.pre11.3/drivers/isdn/avmb1/Makefile
--- linux.vanilla/drivers/isdn/avmb1/Makefile	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/Makefile	Mon Jul 19 23:59:32 1999
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile,v 1.4 1997/03/30 17:10:40 calle Exp $
+# $Id: Makefile,v 1.5 1999/07/01 15:26:20 calle Exp $
 #
 # Makefile for the CAPI and AVM-B1 device drivers.
 #
@@ -11,6 +11,22 @@
 # parent makes..
 #
 # $Log: Makefile,v $
+# Revision 1.5  1999/07/01 15:26:20  calle
+# complete new version (I love it):
+# + new hardware independed "capi_driver" interface that will make it easy to:
+#   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+#   - write a CAPI-2.0 for the passive cards
+#   - support serial link CAPI-2.0 boxes.
+# + wrote "capi_driver" for all supported cards.
+# + "capi_driver" (supported cards) now have to be configured with
+#   make menuconfig, in the past all supported cards where included
+#   at once.
+# + new and better informations in /proc/capi/
+# + new ioctl to switch trace of capi messages per controller
+#   using "avmcapictrl trace [contr] on|off|...."
+# + complete testcircle with all supported cards and also the
+#   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+#
 # Revision 1.4  1997/03/30 17:10:40  calle
 # added support for AVM-B1-PCI card.
 #
@@ -56,20 +72,38 @@
 
 ifeq ($(CONFIG_ISDN_DRV_AVMB1),y)
   O_TARGET += avmb1.o
-  O_OBJS   += capi.o b1lli.o
-  OX_OBJS  += capiutil.o b1capi.o capidrv.o
-  ifdef CONFIG_PCI
-  OX_OBJS  += b1pci.o
+  OX_OBJS  += kcapi.o
+  O_OBJS   += capi.o kernelcapi.o
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+  O_OBJS   += b1isa.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+  O_OBJS  += b1pci.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
+  O_OBJS   += t1isa.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+  OX_OBJS   += b1pcmcia.o
   endif
+  OX_OBJS  += capiutil.o capidrv.o b1.o
 else
   ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
   O_TARGET += kernelcapi.o
-  O_OBJS   += b1lli.o
-  OX_OBJS  += b1capi.o
+  OX_OBJS  += kcapi.o
   M_OBJS   += capi.o kernelcapi.o
-  MX_OBJS  += capiutil.o capidrv.o
-  ifdef CONFIG_PCI
-  MX_OBJS  += b1pci.o
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA
+  M_OBJS   += b1isa.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI
+  M_OBJS  += b1pci.o
+  endif
+  ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA
+  M_OBJS   += t1isa.o
+  endif
+  MX_OBJS  += capiutil.o capidrv.o b1.o
+  ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
+  MX_OBJS  += b1pcmcia.o
   endif
   endif
 endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/avmcard.h linux.pre11.3/drivers/isdn/avmb1/avmcard.h
--- linux.vanilla/drivers/isdn/avmb1/avmcard.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/avmcard.h	Mon Jul 19 23:59:32 1999
@@ -0,0 +1,535 @@
+/*
+ * $Id: avmcard.h,v 1.2 1999/07/05 15:09:45 calle Exp $
+ *
+ * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: avmcard.h,v $
+ * Revision 1.2  1999/07/05 15:09:45  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:22  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+
+#ifndef _AVMCARD_H_
+#define _AVMCARD_H_
+
+#define	AVMB1_PORTLEN		0x1f
+#define AVM_MAXVERSION		8
+#define AVM_NAPPS		30
+#define AVM_NCCI_PER_CHANNEL	4
+
+/*
+ * Versions
+ */
+
+#define	VER_DRIVER	0
+#define	VER_CARDTYPE	1
+#define	VER_HWID	2
+#define	VER_SERIAL	3
+#define	VER_OPTION	4
+#define	VER_PROTO	5
+#define	VER_PROFILE	6
+#define	VER_CAPI	7
+
+enum avmcardtype {
+	avm_b1isa,
+	avm_b1pci,
+	avm_b1pcmcia,
+	avm_m1,
+	avm_m2,
+	avm_t1isa,
+	avm_t1pci
+};
+
+typedef struct avmcard {
+	char name[32];
+	unsigned int port;
+	unsigned irq;
+	enum avmcardtype cardtype;
+	int cardnr; /* for t1isa */
+
+	int versionlen;
+	char versionbuf[1024];
+	char *version[AVM_MAXVERSION];
+
+	char cardname[32];
+
+	char infobuf[128];	/* for function procinfo */
+	char msgbuf[128];	/* capimsg msg part */
+	char databuf[2048];	/* capimsg data part */
+
+	int interrupt;
+
+	struct capi_ctr *ctrl;
+} avmcard;
+
+extern int b1_irq_table[16];
+
+/*
+ * LLI Messages to the ISDN-ControllerISDN Controller 
+ */
+
+#define	SEND_POLL		0x72	/*
+					   * after load <- RECEIVE_POLL 
+					 */
+#define SEND_INIT		0x11	/*
+					   * first message <- RECEIVE_INIT
+					   * int32 NumApplications  int32
+					   * NumNCCIs int32 BoardNumber 
+					 */
+#define SEND_REGISTER		0x12	/*
+					   * register an application int32
+					   * ApplIDId int32 NumMessages
+					   * int32 NumB3Connections int32
+					   * NumB3Blocks int32 B3Size
+					   * 
+					   * AnzB3Connection != 0 &&
+					   * AnzB3Blocks >= 1 && B3Size >= 1 
+					 */
+#define SEND_RELEASE		0x14	/*
+					   * deregister an application int32 
+					   * ApplID 
+					 */
+#define SEND_MESSAGE		0x15	/*
+					   * send capi-message int32 length
+					   * capi-data ... 
+					 */
+#define SEND_DATA_B3_REQ	0x13	/*
+					   * send capi-data-message int32
+					   * MsgLength capi-data ... int32
+					   * B3Length data .... 
+					 */
+
+#define SEND_CONFIG		0x21    /*
+                                         */
+
+#define SEND_POLLACK		0x73    /* T1 Watchdog */
+
+/*
+ * LLI Messages from the ISDN-ControllerISDN Controller 
+ */
+
+#define RECEIVE_POLL		0x32	/*
+					   * <- after SEND_POLL 
+					 */
+#define RECEIVE_INIT		0x27	/*
+					   * <- after SEND_INIT int32 length
+					   * byte total length b1struct board 
+					   * driver revision b1struct card
+					   * type b1struct reserved b1struct
+					   * serial number b1struct driver
+					   * capability b1struct d-channel
+					   * protocol b1struct CAPI-2.0
+					   * profile b1struct capi version 
+					 */
+#define RECEIVE_MESSAGE		0x21	/*
+					   * <- after SEND_MESSAGE int32
+					   * AppllID int32 Length capi-data
+					   * .... 
+					 */
+#define RECEIVE_DATA_B3_IND	0x22	/*
+					   * received data int32 AppllID
+					   * int32 Length capi-data ...
+					   * int32 B3Length data ... 
+					 */
+#define RECEIVE_START		0x23	/*
+					   * Handshake 
+					 */
+#define RECEIVE_STOP		0x24	/*
+					   * Handshake 
+					 */
+#define RECEIVE_NEW_NCCI	0x25	/*
+					   * int32 AppllID int32 NCCI int32
+					   * WindowSize 
+					 */
+#define RECEIVE_FREE_NCCI	0x26	/*
+					   * int32 AppllID int32 NCCI 
+					 */
+#define RECEIVE_RELEASE		0x26	/*
+					   * int32 AppllID int32 0xffffffff 
+					 */
+#define RECEIVE_TASK_READY	0x31	/*
+					   * int32 tasknr
+					   * int32 Length Taskname ...
+					 */
+#define RECEIVE_DEBUGMSG	0x71	/*
+					   * int32 Length message
+					   * 
+					 */
+
+#define WRITE_REGISTER		0x00
+#define READ_REGISTER		0x01
+
+/*
+ * port offsets
+ */
+
+#define B1_READ			0x00
+#define B1_WRITE		0x01
+#define B1_INSTAT		0x02
+#define B1_OUTSTAT		0x03
+#define B1_RESET		0x10
+#define B1_ANALYSE		0x04
+
+
+#define B1_STAT0(cardtype)  ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l)
+#define B1_STAT1(cardtype)  (0x80E00000l)
+
+/* ---------------------------------------------------------------- */
+
+static inline unsigned char b1outp(unsigned int base,
+				   unsigned short offset,
+				   unsigned char value)
+{
+	outb(value, base + offset);
+	return inb(base + B1_ANALYSE);
+}
+
+
+static inline int b1_rx_full(unsigned int base)
+{
+	return inb(base + B1_INSTAT) & 0x1;
+}
+
+static inline unsigned char b1_get_byte(unsigned int base)
+{
+	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
+	while (!b1_rx_full(base) && time_before(jiffies, stop));
+	if (b1_rx_full(base))
+		return inb(base + B1_READ);
+	printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base);
+	return 0;
+}
+
+static inline unsigned int b1_get_word(unsigned int base)
+{
+	unsigned int val = 0;
+	val |= b1_get_byte(base);
+	val |= (b1_get_byte(base) << 8);
+	val |= (b1_get_byte(base) << 16);
+	val |= (b1_get_byte(base) << 24);
+	return val;
+}
+
+static inline int b1_tx_empty(unsigned int base)
+{
+	return inb(base + B1_OUTSTAT) & 0x1;
+}
+
+static inline void b1_put_byte(unsigned int base, unsigned char val)
+{
+	while (!b1_tx_empty(base));
+	b1outp(base, B1_WRITE, val);
+}
+
+static inline int b1_save_put_byte(unsigned int base, unsigned char val)
+{
+	unsigned long stop = jiffies + 2 * HZ;
+	while (!b1_tx_empty(base) && time_before(jiffies,stop));
+	if (!b1_tx_empty(base)) return -1;
+	b1outp(base, B1_WRITE, val);
+	return 0;
+}
+
+static inline void b1_put_word(unsigned int base, unsigned int val)
+{
+	b1_put_byte(base, val & 0xff);
+	b1_put_byte(base, (val >> 8) & 0xff);
+	b1_put_byte(base, (val >> 16) & 0xff);
+	b1_put_byte(base, (val >> 24) & 0xff);
+}
+
+static inline unsigned int b1_get_slice(unsigned int base,
+					unsigned char *dp)
+{
+	unsigned int len, i;
+
+	len = i = b1_get_word(base);
+	while (i-- > 0) *dp++ = b1_get_byte(base);
+	return len;
+}
+
+static inline void b1_put_slice(unsigned int base,
+				unsigned char *dp, unsigned int len)
+{
+	unsigned i = len;
+	b1_put_word(base, i);
+	while (i-- > 0)
+		b1_put_byte(base, *dp++);
+}
+
+static void b1_wr_reg(unsigned int base,
+                      unsigned int reg,
+		      unsigned int value)
+{
+	b1_put_byte(base, WRITE_REGISTER);
+        b1_put_word(base, reg);
+        b1_put_word(base, value);
+}
+
+static inline unsigned int b1_rd_reg(unsigned int base,
+                                     unsigned int reg)
+{
+	b1_put_byte(base, READ_REGISTER);
+        b1_put_word(base, reg);
+        return b1_get_word(base);
+	
+}
+
+static inline void b1_reset(unsigned int base)
+{
+	b1outp(base, B1_RESET, 0);
+	udelay(55 * 2 * 1000);	/* 2 TIC's */
+
+	b1outp(base, B1_RESET, 1);
+	udelay(55 * 2 * 1000);	/* 2 TIC's */
+
+	b1outp(base, B1_RESET, 0);
+	udelay(55 * 2 * 1000);	/* 2 TIC's */
+}
+
+static inline unsigned char b1_disable_irq(unsigned int base)
+{
+	return b1outp(base, B1_INSTAT, 0x00);
+}
+
+/* ---------------------------------------------------------------- */
+
+static inline void b1_set_test_bit(unsigned int base,
+				   enum avmcardtype cardtype,
+				   int onoff)
+{
+    b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
+}
+
+static inline int b1_get_test_bit(unsigned int base,
+                                  enum avmcardtype cardtype)
+{
+    return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
+}
+
+/* ---------------------------------------------------------------- */
+
+#define T1_FASTLINK		0x00
+#define T1_SLOWLINK		0x08
+
+#define T1_READ			B1_READ
+#define T1_WRITE		B1_WRITE
+#define T1_INSTAT		B1_INSTAT
+#define T1_OUTSTAT		B1_OUTSTAT
+#define T1_IRQENABLE		0x05
+#define T1_FIFOSTAT		0x06
+#define T1_RESETLINK		0x10
+#define T1_ANALYSE		0x11
+#define T1_IRQMASTER		0x12
+#define T1_IDENT		0x17
+#define T1_RESETBOARD		0x1f
+
+#define	T1F_IREADY		0x01
+#define	T1F_IHALF		0x02
+#define	T1F_IFULL		0x04
+#define	T1F_IEMPTY		0x08
+#define	T1F_IFLAGS		0xF0
+
+#define	T1F_OREADY		0x10
+#define	T1F_OHALF		0x20
+#define	T1F_OEMPTY		0x40
+#define	T1F_OFULL		0x80
+#define	T1F_OFLAGS		0xF0
+
+/* there are HEMA cards with 1k and 4k FIFO out */
+#define FIFO_OUTBSIZE		256
+#define FIFO_INPBSIZE		512
+
+#define HEMA_VERSION_ID		0
+#define HEMA_PAL_ID		0
+
+static inline void t1outp(unsigned int base,
+			  unsigned short offset,
+			  unsigned char value)
+{
+	outb(value, base + offset);
+}
+
+static inline unsigned char t1inp(unsigned int base,
+			          unsigned short offset)
+{
+	return inb(base + offset);
+}
+
+static inline int t1_isfastlink(unsigned int base)
+{
+	return (inb(base + T1_IDENT) & ~0x82) == 1;
+}
+
+static inline unsigned char t1_fifostatus(unsigned int base)
+{
+	return inb(base + T1_FIFOSTAT);
+}
+
+static inline unsigned int t1_get_slice(unsigned int base,
+					unsigned char *dp)
+{
+	unsigned int len, i;
+#ifdef FASTLINK_DEBUG
+	unsigned wcnt = 0, bcnt = 0;
+#endif
+
+	len = i = b1_get_word(base);
+        if (t1_isfastlink(base)) {
+		int status;
+		while (i > 0) {
+			status = t1_fifostatus(base) & (T1F_IREADY|T1F_IHALF);
+			if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
+
+			switch (status) {
+				case T1F_IREADY|T1F_IHALF|T1F_IFULL:
+					insb(base+B1_READ, dp, FIFO_INPBSIZE);
+					dp += FIFO_INPBSIZE;
+					i -= FIFO_INPBSIZE;
+#ifdef FASTLINK_DEBUG
+					wcnt += FIFO_INPBSIZE;
+#endif
+					break;
+				case T1F_IREADY|T1F_IHALF: 
+					insb(base+B1_READ,dp, i);
+#ifdef FASTLINK_DEBUG
+					wcnt += i;
+#endif
+					dp += i;
+					i = 0;
+					if (i == 0)
+						break;
+					/* fall through */
+				default:
+					*dp++ = b1_get_byte(base);
+					i--;
+#ifdef FASTLINK_DEBUG
+					bcnt++;
+#endif
+					break;
+			}
+	    }
+#ifdef FASTLINK_DEBUG
+	    if (wcnt)
+	    printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n",
+				base, len, wcnt, bcnt);
+#endif
+	} else {
+		while (i-- > 0)
+			*dp++ = b1_get_byte(base);
+	}
+	return len;
+}
+
+static inline void t1_put_slice(unsigned int base,
+				unsigned char *dp, unsigned int len)
+{
+	unsigned i = len;
+	b1_put_word(base, i);
+        if (t1_isfastlink(base)) {
+		int status;
+		while (i > 0) {
+			status = t1_fifostatus(base) & (T1F_OREADY|T1F_OHALF);
+			if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY;
+			switch (status) {
+				case T1F_OREADY|T1F_OHALF|T1F_OEMPTY: 
+					outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE);
+					dp += FIFO_OUTBSIZE;
+					i -= FIFO_OUTBSIZE;
+					break;
+				case T1F_OREADY|T1F_OHALF: 
+					outsb(base+B1_WRITE, dp, i);
+					dp += i;
+					i = 0;
+				        break;
+				default:
+					b1_put_byte(base, *dp++);
+					i--;
+					break;
+			}
+		}
+	} else {
+		while (i-- > 0)
+			b1_put_byte(base, *dp++);
+	}
+}
+
+static inline void t1_disable_irq(unsigned int base)
+{
+      t1outp(base, T1_IRQMASTER, 0x00);
+}
+
+static inline void t1_reset(unsigned int base)
+{
+        /* reset T1 Controller */
+        b1_reset(base);
+        /* disable irq on HEMA */
+        t1outp(base, B1_INSTAT, 0x00);
+        t1outp(base, B1_OUTSTAT, 0x00);
+        t1outp(base, T1_IRQMASTER, 0x00);
+        /* reset HEMA board configuration */
+	t1outp(base, T1_RESETBOARD, 0xf);
+}
+
+static inline void b1_setinterrupt(unsigned int base, unsigned irq,
+				   enum avmcardtype cardtype)
+{
+	switch (cardtype) {
+	   case avm_t1isa:
+              t1outp(base, B1_INSTAT, 0x00);
+              t1outp(base, B1_INSTAT, 0x02);
+	      t1outp(base, T1_IRQMASTER, 0x08);
+	      break;
+	   case avm_b1isa:
+	      b1outp(base, B1_INSTAT, 0x00);
+	      b1outp(base, B1_RESET, b1_irq_table[irq]);
+	      b1outp(base, B1_INSTAT, 0x02);
+	      break;
+	   default:
+	   case avm_m1:
+	   case avm_m2:
+	   case avm_b1pci:
+	      b1outp(base, B1_INSTAT, 0x00);
+	      b1outp(base, B1_RESET, 0xf0);
+	      b1outp(base, B1_INSTAT, 0x02);
+	      break;
+	 }
+}
+
+int b1_detect(unsigned int base, enum avmcardtype cardtype);
+int b1_load_t4file(unsigned int base, capiloaddatapart * t4file);
+int b1_load_config(unsigned int base, capiloaddatapart * config);
+int b1_loaded(unsigned int base);
+int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
+void b1_reset_ctr(struct capi_ctr *ctrl);
+void b1_register_appl(struct capi_ctr *ctrl, __u16 appl,
+				capi_register_params *rp);
+void b1_release_appl(struct capi_ctr *ctrl, __u16 appl);
+void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+void b1_parse_version(avmcard *card);
+void b1_handle_interrupt(avmcard * card);
+
+int b1ctl_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl);
+
+
+#endif /* _AVMCARD_H_ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1.c linux.pre11.3/drivers/isdn/avmb1/b1.c
--- linux.vanilla/drivers/isdn/avmb1/b1.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/b1.c	Mon Jul 19 23:59:32 1999
@@ -0,0 +1,679 @@
+/*
+ * $Id: b1.c,v 1.4 1999/07/09 15:05:38 keil Exp $
+ * 
+ * Common module for AVM B1 cards.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: b1.c,v $
+ * Revision 1.4  1999/07/09 15:05:38  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.3  1999/07/06 07:41:59  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.2  1999/07/05 15:09:47  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:23  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capilli.h"
+#include "avmcard.h"
+#include "capicmd.h"
+#include "capiutil.h"
+
+static char *revision = "$Revision: 1.4 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+int b1_irq_table[16] =
+{0,
+ 0,
+ 0,
+ 192,				/* irq 3 */
+ 32,				/* irq 4 */
+ 160,				/* irq 5 */
+ 96,				/* irq 6 */
+ 224,				/* irq 7 */
+ 0,
+ 64,				/* irq 9 */
+ 80,				/* irq 10 */
+ 208,				/* irq 11 */
+ 48,				/* irq 12 */
+ 0,
+ 0,
+ 112,				/* irq 15 */
+};
+
+/* ------------------------------------------------------------- */
+
+int b1_detect(unsigned int base, enum avmcardtype cardtype)
+{
+	int onoff, i;
+
+	/*
+	 * Statusregister 0000 00xx 
+	 */
+	if ((inb(base + B1_INSTAT) & 0xfc)
+	    || (inb(base + B1_OUTSTAT) & 0xfc))
+		return 1;
+	/*
+	 * Statusregister 0000 001x 
+	 */
+	b1outp(base, B1_INSTAT, 0x2);	/* enable irq */
+	/* b1outp(base, B1_OUTSTAT, 0x2); */
+	if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
+	    /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
+		return 2;
+	/*
+	 * Statusregister 0000 000x 
+	 */
+	b1outp(base, B1_INSTAT, 0x0);	/* disable irq */
+	b1outp(base, B1_OUTSTAT, 0x0);
+	if ((inb(base + B1_INSTAT) & 0xfe)
+	    || (inb(base + B1_OUTSTAT) & 0xfe))
+		return 3;
+        
+	for (onoff = !0, i= 0; i < 10 ; i++) {
+		b1_set_test_bit(base, cardtype, onoff);
+		if (b1_get_test_bit(base, cardtype) != onoff)
+		   return 4;
+		onoff = !onoff;
+	}
+
+	if (cardtype == avm_m1)
+	   return 0;
+
+        if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
+	   return 5;
+
+	return 0;
+}
+
+int b1_load_t4file(unsigned int base, capiloaddatapart * t4file)
+{
+	unsigned char buf[256];
+	unsigned char *dp;
+	int i, left, retval;
+
+	dp = t4file->data;
+	left = t4file->len;
+	while (left > sizeof(buf)) {
+		if (t4file->user) {
+			retval = copy_from_user(buf, dp, sizeof(buf));
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, sizeof(buf));
+		}
+		for (i = 0; i < sizeof(buf); i++)
+			if (b1_save_put_byte(base, buf[i]) < 0) {
+				printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n");
+				return -EIO;
+			}
+		left -= sizeof(buf);
+		dp += sizeof(buf);
+	}
+	if (left) {
+		if (t4file->user) {
+			retval = copy_from_user(buf, dp, left);
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, left);
+		}
+		for (i = 0; i < left; i++)
+			if (b1_save_put_byte(base, buf[i]) < 0) {
+				printk(KERN_ERR "b1_load_t4file: corrupted t4 file ?\n");
+				return -EIO;
+			}
+	}
+	return 0;
+}
+
+int b1_load_config(unsigned int base, capiloaddatapart * config)
+{
+	unsigned char buf[256];
+	unsigned char *dp;
+	int i, j, left, retval;
+
+	dp = config->data;
+	left = config->len;
+	if (left) {
+		b1_put_byte(base, SEND_CONFIG);
+        	b1_put_word(base, 1);
+		b1_put_byte(base, SEND_CONFIG);
+        	b1_put_word(base, left);
+	}
+	while (left > sizeof(buf)) {
+		if (config->user) {
+			retval = copy_from_user(buf, dp, sizeof(buf));
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, sizeof(buf));
+		}
+		for (i = 0; i < sizeof(buf); ) {
+			b1_put_byte(base, SEND_CONFIG);
+			for (j=0; j < 4; j++) {
+				b1_put_byte(base, buf[i++]);
+			}
+		}
+		left -= sizeof(buf);
+		dp += sizeof(buf);
+	}
+	if (left) {
+		if (config->user) {
+			retval = copy_from_user(buf, dp, left);
+			if (retval)
+				return -EFAULT;
+		} else {
+			memcpy(buf, dp, left);
+		}
+		for (i = 0; i < left; ) {
+			b1_put_byte(base, SEND_CONFIG);
+			for (j=0; j < 4; j++) {
+				if (i < left)
+					b1_put_byte(base, buf[i++]);
+				else
+					b1_put_byte(base, 0);
+			}
+		}
+	}
+	return 0;
+}
+
+int b1_loaded(unsigned int base)
+{
+	unsigned long stop;
+	unsigned char ans;
+	unsigned long tout = 2;
+
+	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+		if (b1_tx_empty(base))
+			break;
+	}
+	if (!b1_tx_empty(base)) {
+		printk(KERN_ERR "b1_loaded: tx err, corrupted t4 file ?\n");
+		return 0;
+	}
+	b1_put_byte(base, SEND_POLL);
+	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+		if (b1_rx_full(base)) {
+			if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
+				return 1;
+			}
+			printk(KERN_ERR "b1_loaded: got 0x%x, firmware not running\n", ans);
+			return 0;
+		}
+	}
+	printk(KERN_ERR "b1_loaded: firmware not running\n");
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	int retval;
+
+	b1_reset(port);
+
+	if ((retval = b1_load_t4file(port, &data->firmware))) {
+		b1_reset(port);
+		printk(KERN_ERR "%s: failed to load t4file!!\n",
+					card->name);
+		return retval;
+	}
+
+	b1_disable_irq(port);
+
+	if (data->configuration.len > 0 && data->configuration.data) {
+		if ((retval = b1_load_config(port, &data->configuration))) {
+			b1_reset(port);
+			printk(KERN_ERR "%s: failed to load config!!\n",
+					card->name);
+			return retval;
+		}
+	}
+
+	if (!b1_loaded(port)) {
+		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
+		return -EIO;
+	}
+
+	save_flags(flags);
+	cli();
+	b1_setinterrupt(port, card->irq, card->cardtype);
+	b1_put_byte(port, SEND_INIT);
+	b1_put_word(port, AVM_NAPPS);
+	b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
+	b1_put_word(port, ctrl->cnr - 1);
+	restore_flags(flags);
+
+	return 0;
+}
+
+void b1_reset_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	memset(card->version, 0, sizeof(card->version));
+	ctrl->reseted(ctrl);
+}
+
+void b1_register_appl(struct capi_ctr *ctrl,
+				__u16 appl,
+				capi_register_params *rp)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	int nconn, want = rp->level3cnt;
+
+	if (want > 0) nconn = want;
+	else nconn = ctrl->profile.nbchannel * -want;
+	if (nconn == 0) nconn = ctrl->profile.nbchannel;
+
+	save_flags(flags);
+	cli();
+	b1_put_byte(port, SEND_REGISTER);
+	b1_put_word(port, appl);
+	b1_put_word(port, 1024 * (nconn+1));
+	b1_put_word(port, nconn);
+	b1_put_word(port, rp->datablkcnt);
+	b1_put_word(port, rp->datablklen);
+	restore_flags(flags);
+
+	ctrl->appl_registered(ctrl, appl);
+}
+
+void b1_release_appl(struct capi_ctr *ctrl, __u16 appl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	b1_put_byte(port, SEND_RELEASE);
+	b1_put_word(port, appl);
+	restore_flags(flags);
+}
+
+void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	__u16 len = CAPIMSG_LEN(skb->data);
+	__u8 cmd = CAPIMSG_COMMAND(skb->data);
+	__u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+	save_flags(flags);
+	cli();
+	if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+		__u16 dlen = CAPIMSG_DATALEN(skb->data);
+		b1_put_byte(port, SEND_DATA_B3_REQ);
+		b1_put_slice(port, skb->data, len);
+		b1_put_slice(port, skb->data + len, dlen);
+	} else {
+		b1_put_byte(port, SEND_MESSAGE);
+		b1_put_slice(port, skb->data, len);
+	}
+	restore_flags(flags);
+	dev_kfree_skb(skb);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1_parse_version(avmcard *card)
+{
+	struct capi_ctr *ctrl = card->ctrl;
+	capi_profile *profp;
+	__u8 *dversion;
+	__u8 flag;
+	int i, j;
+
+	for (j = 0; j < AVM_MAXVERSION; j++)
+		card->version[j] = "\0\0" + 1;
+	for (i = 0, j = 0;
+	     j < AVM_MAXVERSION && i < card->versionlen;
+	     j++, i += card->versionbuf[i] + 1)
+		card->version[j] = &card->versionbuf[i + 1];
+
+	strncpy(ctrl->serial, card->version[VER_SERIAL], CAPI_SERIAL_LEN);
+	memcpy(&ctrl->profile, card->version[VER_PROFILE],sizeof(capi_profile));
+	strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN);
+	dversion = card->version[VER_DRIVER];
+	ctrl->version.majorversion = 2;
+	ctrl->version.minorversion = 0;
+	ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
+	ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf);
+	ctrl->version.minormanuversion = (dversion[3] - '0') << 4;
+	ctrl->version.minormanuversion |=
+			(dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
+
+	profp = &ctrl->profile;
+
+	flag = ((__u8 *)(profp->manu))[1];
+	switch (flag) {
+	case 0: strcpy(card->cardname, "B1"); break;
+	case 3: strcpy(card->cardname,"PCMCIA B"); break;
+	case 4: strcpy(card->cardname,"PCMCIA M1"); break;
+	case 5: strcpy(card->cardname,"PCMCIA M2"); break;
+	case 6: strcpy(card->cardname,"B1 V3.0"); break;
+	case 7: strcpy(card->cardname,"B1 PCI"); break;
+	default: sprintf(card->cardname, "AVM?%u", (unsigned int)flag); break;
+        }
+        printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n",
+				card->name, ctrl->cnr, card->cardname);
+
+        flag = ((__u8 *)(profp->manu))[3];
+        if (flag)
+		printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
+			ctrl->cnr,
+			(flag & 0x01) ? " DSS1" : "",
+			(flag & 0x02) ? " CT1" : "",
+			(flag & 0x04) ? " VN3" : "",
+			(flag & 0x08) ? " NI1" : "",
+			(flag & 0x10) ? " AUSTEL" : "",
+			(flag & 0x20) ? " ESS" : "",
+			(flag & 0x40) ? " 1TR6" : ""
+			);
+
+        flag = ((__u8 *)(profp->manu))[5];
+	if (flag)
+		printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n",
+			card->name,
+			ctrl->cnr,
+			(flag & 0x01) ? " point to point" : "",
+			(flag & 0x02) ? " point to multipoint" : "",
+			(flag & 0x08) ? " leased line without D-channel" : "",
+			(flag & 0x04) ? " leased line with D-channel" : ""
+			);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1_handle_interrupt(avmcard * card)
+{
+	struct capi_ctr *ctrl = card->ctrl;
+	unsigned char b1cmd;
+	struct sk_buff *skb;
+
+	unsigned ApplId;
+	unsigned MsgLen;
+	unsigned DataB3Len;
+	unsigned NCCI;
+	unsigned WindowSize;
+
+	if (!b1_rx_full(card->port))
+	   return;
+
+	b1cmd = b1_get_byte(card->port);
+
+	switch (b1cmd) {
+
+	case RECEIVE_DATA_B3_IND:
+
+		ApplId = (unsigned) b1_get_word(card->port);
+		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		DataB3Len = b1_get_slice(card->port, card->databuf);
+
+		if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) {
+			printk(KERN_ERR "%s: incoming packet dropped\n",
+					card->name);
+		} else {
+			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+			memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
+			CAPIMSG_SETDATA(skb->data, skb->data + MsgLen);
+			ctrl->handle_capimsg(ctrl, ApplId, skb);
+		}
+		break;
+
+	case RECEIVE_MESSAGE:
+
+		ApplId = (unsigned) b1_get_word(card->port);
+		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+			printk(KERN_ERR "%s: incoming packet dropped\n",
+					card->name);
+		} else {
+			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+			ctrl->handle_capimsg(ctrl, ApplId, skb);
+		}
+		break;
+
+	case RECEIVE_NEW_NCCI:
+
+		ApplId = b1_get_word(card->port);
+		NCCI = b1_get_word(card->port);
+		WindowSize = b1_get_word(card->port);
+
+		ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+		break;
+
+	case RECEIVE_FREE_NCCI:
+
+		ApplId = b1_get_word(card->port);
+		NCCI = b1_get_word(card->port);
+
+		if (NCCI != 0xffffffff)
+			ctrl->free_ncci(ctrl, ApplId, NCCI);
+		else ctrl->appl_released(ctrl, ApplId);
+		break;
+
+	case RECEIVE_START:
+	   	/* b1_put_byte(card->port, SEND_POLLACK); */
+		ctrl->resume_output(ctrl);
+		break;
+
+	case RECEIVE_STOP:
+		ctrl->suspend_output(ctrl);
+		break;
+
+	case RECEIVE_INIT:
+
+		card->versionlen = b1_get_slice(card->port, card->versionbuf);
+		b1_parse_version(card);
+		printk(KERN_INFO "%s: %s-card (%s) now active\n",
+		       card->name,
+		       card->version[VER_CARDTYPE],
+		       card->version[VER_DRIVER]);
+		ctrl->ready(ctrl);
+		break;
+
+        case RECEIVE_TASK_READY:
+		ApplId = (unsigned) b1_get_word(card->port);
+		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		card->msgbuf[MsgLen--] = 0;
+		while (    MsgLen >= 0
+		       && (   card->msgbuf[MsgLen] == '\n'
+			   || card->msgbuf[MsgLen] == '\r'))
+			card->msgbuf[MsgLen--] = 0;
+		printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
+				card->name, ApplId, card->msgbuf);
+		break;
+
+        case RECEIVE_DEBUGMSG:
+		MsgLen = b1_get_slice(card->port, card->msgbuf);
+		card->msgbuf[MsgLen--] = 0;
+		while (    MsgLen >= 0
+		       && (   card->msgbuf[MsgLen] == '\n'
+			   || card->msgbuf[MsgLen] == '\r'))
+			card->msgbuf[MsgLen--] = 0;
+		printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
+		break;
+
+	case 0xff:
+		printk(KERN_ERR "%s: card removed ?\n", card->name);
+		return;
+	default:
+		printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
+				card->name, b1cmd);
+		return;
+	}
+}
+
+/* ------------------------------------------------------------- */
+int b1ctl_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	__u8 flag;
+	int len = 0;
+	char *s;
+
+	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
+	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
+	len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
+	switch (card->cardtype) {
+	case avm_b1isa: s = "B1 ISA"; break;
+	case avm_b1pci: s = "B1 PCI"; break;
+	case avm_b1pcmcia: s = "B1 PCMCIA"; break;
+	case avm_m1: s = "M1"; break;
+	case avm_m2: s = "M2"; break;
+	case avm_t1isa: s = "T1 ISA (HEMA)"; break;
+	case avm_t1pci: s = "T1 PCI"; break;
+	default: s = "???"; break;
+	}
+	len += sprintf(page+len, "%-16s %s\n", "type", s);
+	if (card->cardtype == avm_t1isa)
+	   len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr);
+	if ((s = card->version[VER_DRIVER]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+	if ((s = card->version[VER_CARDTYPE]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+	if ((s = card->version[VER_SERIAL]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+	if (card->cardtype != avm_m1) {
+        	flag = ((__u8 *)(ctrl->profile.manu))[3];
+        	if (flag)
+			len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
+			"protocol",
+			(flag & 0x01) ? " DSS1" : "",
+			(flag & 0x02) ? " CT1" : "",
+			(flag & 0x04) ? " VN3" : "",
+			(flag & 0x08) ? " NI1" : "",
+			(flag & 0x10) ? " AUSTEL" : "",
+			(flag & 0x20) ? " ESS" : "",
+			(flag & 0x40) ? " 1TR6" : ""
+			);
+	}
+	if (card->cardtype != avm_m1) {
+        	flag = ((__u8 *)(ctrl->profile.manu))[5];
+		if (flag)
+			len += sprintf(page+len, "%-16s%s%s%s%s\n",
+			"linetype",
+			(flag & 0x01) ? " point to point" : "",
+			(flag & 0x02) ? " point to multipoint" : "",
+			(flag & 0x08) ? " leased line without D-channel" : "",
+			(flag & 0x04) ? " leased line with D-channel" : ""
+			);
+	}
+	len += sprintf(page+len, "%-16s %s\n", "cardname", card->cardname);
+
+	if (len < off) 
+           return 0;
+	*eof = 1;
+	*start = page - off;
+	return ((count < len-off) ? count : len-off);
+	if (len < off) 
+           return 0;
+	*eof = 1;
+	*start = page - off;
+	return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+EXPORT_SYMBOL(b1_irq_table);
+
+EXPORT_SYMBOL(b1_detect);
+EXPORT_SYMBOL(b1_load_t4file);
+EXPORT_SYMBOL(b1_load_config);
+EXPORT_SYMBOL(b1_loaded);
+EXPORT_SYMBOL(b1_load_firmware);
+EXPORT_SYMBOL(b1_reset_ctr);
+EXPORT_SYMBOL(b1_register_appl);
+EXPORT_SYMBOL(b1_release_appl);
+EXPORT_SYMBOL(b1_send_message);
+
+EXPORT_SYMBOL(b1_parse_version);
+EXPORT_SYMBOL(b1_handle_interrupt);
+
+EXPORT_SYMBOL(b1ctl_read_proc);
+
+#ifdef MODULE
+#define b1_init init_module
+void cleanup_module(void);
+#endif
+
+int b1_init(void)
+{
+	char *p;
+	char rev[10];
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(rev, p + 1, sizeof(rev));
+		p = strchr(rev, '$');
+		*p = 0;
+	} else
+		strcpy(rev, "1.0");
+
+	printk(KERN_INFO "b1: revision %s\n", rev);
+
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1capi.c linux.pre11.3/drivers/isdn/avmb1/b1capi.c
--- linux.vanilla/drivers/isdn/avmb1/b1capi.c	Sun Nov  8 15:10:14 1998
+++ linux.pre11.3/drivers/isdn/avmb1/b1capi.c	Mon Jul 19 23:59:32 1999
@@ -1,1141 +0,0 @@
-/*
- * $Id: b1capi.c,v 1.10 1998/02/13 07:09:10 calle Exp $
- * 
- * CAPI 2.0 Module for AVM B1-card.
- * 
- * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
- * 
- * $Log: b1capi.c,v $
- * Revision 1.10  1998/02/13 07:09:10  calle
- * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
- *
- * Revision 1.9  1998/01/31 11:14:39  calle
- * merged changes to 2.0 tree, prepare 2.1.82 to work.
- *
- * Revision 1.8  1997/12/10 20:00:46  calle
- * get changes from 2.0 version
- *
- * Revision 1.4.2.5  1997/12/07 19:59:54  calle
- * more changes for M1/T1/B1 + config
- *
- * Revision 1.4.2.4  1997/11/26 16:57:20  calle
- * more changes for B1/M1/T1.
- *
- * Revision 1.7  1997/10/19 14:45:40  calle
- * fixed capi_get_version.
- *
- * Revision 1.6  1997/10/01 09:21:09  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.5  1997/07/12 08:22:26  calle
- * Correct bug in CARD_NR macro, so now more than one card will work.
- * Allow card reset, even if card is in running state.
- *
- *
- * Revision 1.4  1997/05/27 15:17:45  fritz
- * Added changes for recent 2.1.x kernels:
- *   changed return type of isdn_close
- *   queue_task_* -> queue_task
- *   clear/set_bit -> test_and_... where apropriate.
- *   changed type of hard_header_cache parameter.
- *
- * Revision 1.3  1997/05/18 09:24:09  calle
- * added verbose disconnect reason reporting to avmb1.
- * some fixes in capi20 interface.
- * changed info messages for B1-PCI
- *
- * Revision 1.2  1997/03/05 21:20:41  fritz
- * Removed include of config.h (mkdep stated this is unneded).
- *
- * Revision 1.1  1997/03/04 21:50:27  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
- *
- * 
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <asm/segment.h>
-#include <linux/skbuff.h>
-#include <linux/tqueue.h>
-#include <linux/capi.h>
-#include <linux/b1lli.h>
-#include <linux/kernelcapi.h>
-#include "compat.h"
-#include "capicmd.h"
-#include "capiutil.h"
-
-static char *revision = "$Revision: 1.10 $";
-
-/* ------------------------------------------------------------- */
-
-int showcapimsgs = 0;		/* used in lli.c */
-int loaddebug = 0;
-
-MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
-MODULE_PARM(showcapimsgs, "0-3i");
-MODULE_PARM(loaddebug, "0-1i");
-
-/* ------------------------------------------------------------- */
-
-struct msgidqueue {
-	struct msgidqueue *next;
-	__u16 msgid;
-};
-
-typedef struct avmb1_ncci {
-	struct avmb1_ncci *next;
-	__u16 applid;
-	__u32 ncci;
-	__u32 winsize;
-	struct msgidqueue *msgidqueue;
-	struct msgidqueue *msgidlast;
-	struct msgidqueue *msgidfree;
-	struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
-} avmb1_ncci;
-
-typedef struct avmb1_appl {
-	__u16 applid;
-	capi_register_params rparam;
-	int releasing;
-	__u32 param;
-	void (*signal) (__u16 applid, __u32 param);
-	struct sk_buff_head recv_queue;
-	struct avmb1_ncci *nccilist;
-} avmb1_appl;
-
-/* ------------------------------------------------------------- */
-
-static struct capi_version driver_version = {2, 0, 1, 1<<4};
-static char driver_serial[CAPI_SERIAL_LEN] = "4711";
-static char capi_manufakturer[64] = "AVM Berlin";
-
-#define APPL(a)		   (&applications[(a)-1])
-#define	VALID_APPLID(a)	   ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
-#define APPL_IS_FREE(a)    (APPL(a)->applid == 0)
-#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
-#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
-
-#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
-
-#define VALID_CARD(c)	   ((c) > 0 && (c) <= CAPI_MAXCONTR)
-#define CARD(c)		   (&cards[(c)-1])
-#define CARDNR(cp)	   (((cp)-cards)+1)
-
-static avmb1_appl applications[CAPI_MAXAPPL];
-static avmb1_card cards[CAPI_MAXCONTR];
-static int ncards = 0;
-static struct sk_buff_head recv_queue;
-static struct capi_interface_user *capi_users = 0;
-static long notify_up_set = 0;
-static long notify_down_set = 0;
-
-static struct tq_struct tq_state_notify;
-static struct tq_struct tq_recv_notify;
-
-/* -------- util functions ------------------------------------ */
-
-static char *cardtype2str(int cardtype)
-{
-	switch (cardtype) {
-		default:
-		case AVM_CARDTYPE_B1: return "B1";
-		case AVM_CARDTYPE_M1: return "M1";
-		case AVM_CARDTYPE_M2: return "M2";
-		case AVM_CARDTYPE_T1: return "T1";
-	}
-}
-
-static inline int capi_cmd_valid(__u8 cmd)
-{
-	switch (cmd) {
-	case CAPI_ALERT:
-	case CAPI_CONNECT:
-	case CAPI_CONNECT_ACTIVE:
-	case CAPI_CONNECT_B3_ACTIVE:
-	case CAPI_CONNECT_B3:
-	case CAPI_CONNECT_B3_T90_ACTIVE:
-	case CAPI_DATA_B3:
-	case CAPI_DISCONNECT_B3:
-	case CAPI_DISCONNECT:
-	case CAPI_FACILITY:
-	case CAPI_INFO:
-	case CAPI_LISTEN:
-	case CAPI_MANUFACTURER:
-	case CAPI_RESET_B3:
-	case CAPI_SELECT_B_PROTOCOL:
-		return 1;
-	}
-	return 0;
-}
-
-static inline int capi_subcmd_valid(__u8 subcmd)
-{
-	switch (subcmd) {
-	case CAPI_REQ:
-	case CAPI_CONF:
-	case CAPI_IND:
-	case CAPI_RESP:
-		return 1;
-	}
-	return 0;
-}
-
-/* -------- NCCI Handling ------------------------------------- */
-
-static inline void mq_init(avmb1_ncci * np)
-{
-	int i;
-	np->msgidqueue = 0;
-	np->msgidlast = 0;
-	memset(np->msgidpool, 0, sizeof(np->msgidpool));
-	np->msgidfree = &np->msgidpool[0];
-	for (i = 1; i < np->winsize; i++) {
-		np->msgidpool[i].next = np->msgidfree;
-		np->msgidfree = &np->msgidpool[i];
-	}
-}
-
-static inline int mq_enqueue(avmb1_ncci * np, __u16 msgid)
-{
-	struct msgidqueue *mq;
-	if ((mq = np->msgidfree) == 0)
-		return 0;
-	np->msgidfree = mq->next;
-	mq->msgid = msgid;
-	mq->next = 0;
-	if (np->msgidlast)
-		np->msgidlast->next = mq;
-	np->msgidlast = mq;
-	if (!np->msgidqueue)
-		np->msgidqueue = mq;
-	return 1;
-}
-
-static inline int mq_dequeue(avmb1_ncci * np, __u16 msgid)
-{
-	struct msgidqueue **pp;
-	for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
-		if ((*pp)->msgid == msgid) {
-			struct msgidqueue *mq = *pp;
-			*pp = mq->next;
-			if (mq == np->msgidlast)
-				np->msgidlast = 0;
-			mq->next = np->msgidfree;
-			np->msgidfree = mq;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-void avmb1_handle_new_ncci(avmb1_card * card,
-			   __u16 appl, __u32 ncci, __u32 winsize)
-{
-	avmb1_ncci *np;
-	if (!VALID_APPLID(appl)) {
-		printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
-		return;
-	}
-	if ((np = (avmb1_ncci *) kmalloc(sizeof(avmb1_ncci), GFP_ATOMIC)) == 0) {
-		printk(KERN_ERR "avmb1_handle_new_ncci: alloc failed ncci 0x%x\n", ncci);
-		return;
-	}
-	if (winsize > CAPI_MAXDATAWINDOW) {
-		printk(KERN_ERR "avmb1_handle_new_ncci: winsize %d too big, set to %d\n",
-		       winsize, CAPI_MAXDATAWINDOW);
-		winsize = CAPI_MAXDATAWINDOW;
-	}
-	np->applid = appl;
-	np->ncci = ncci;
-	np->winsize = winsize;
-	mq_init(np);
-	np->next = APPL(appl)->nccilist;
-	APPL(appl)->nccilist = np;
-	printk(KERN_INFO "b1capi: appl %d ncci 0x%x up\n", appl, ncci);
-
-}
-
-void avmb1_handle_free_ncci(avmb1_card * card,
-			    __u16 appl, __u32 ncci)
-{
-	if (!VALID_APPLID(appl)) {
-		printk(KERN_ERR "avmb1_handle_free_ncci: illegal appl %d\n", appl);
-		return;
-	}
-	if (ncci != 0xffffffff) {
-		avmb1_ncci **pp;
-		for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
-			if ((*pp)->ncci == ncci) {
-				avmb1_ncci *np = *pp;
-				*pp = np->next;
-				kfree(np);
-				printk(KERN_INFO "b1capi: appl %d ncci 0x%x down\n", appl, ncci);
-				return;
-			}
-		}
-		printk(KERN_ERR "avmb1_handle_free_ncci: ncci 0x%x not found\n", ncci);
-	} else {
-		avmb1_ncci **pp, **nextpp;
-		for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
-			if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
-				avmb1_ncci *np = *pp;
-				*pp = np->next;
-				printk(KERN_INFO "b1capi: appl %d ncci 0x%x down!\n", appl, np->ncci);
-				kfree(np);
-				nextpp = pp;
-			} else {
-				nextpp = &(*pp)->next;
-			}
-		}
-		APPL(appl)->releasing--;
-		if (APPL(appl)->releasing == 0) {
-	                APPL(appl)->signal = 0;
-			APPL_MARK_FREE(appl);
-			printk(KERN_INFO "b1capi: appl %d down\n", appl);
-		}
-	}
-}
-
-static avmb1_ncci *find_ncci(avmb1_appl * app, __u32 ncci)
-{
-	avmb1_ncci *np;
-	for (np = app->nccilist; np; np = np->next) {
-		if (np->ncci == ncci)
-			return np;
-	}
-	return 0;
-}
-
-
-
-/* -------- Receiver ------------------------------------------ */
-
-
-static void recv_handler(void *dummy)
-{
-	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&recv_queue)) != 0) {
-		__u16 appl = CAPIMSG_APPID(skb->data);
-		struct avmb1_ncci *np;
-		if (!VALID_APPLID(appl)) {
-			printk(KERN_ERR "b1capi: recv_handler: applid %d ? (%s)\n",
-			       appl, capi_message2str(skb->data));
-			kfree_skb(skb);
-			continue;
-		}
-		if (APPL(appl)->signal == 0) {
-			printk(KERN_ERR "b1capi: recv_handler: applid %d has no signal function\n",
-			       appl);
-			kfree_skb(skb);
-			continue;
-		}
-		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
-		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
-	            && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
-		    && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
-			printk(KERN_ERR "b1capi: msgid %hu ncci 0x%x not on queue\n",
-				CAPIMSG_MSGID(skb->data), np->ncci);
-		}
-		skb_queue_tail(&APPL(appl)->recv_queue, skb);
-		(APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
-	}
-}
-
-
-void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb)
-{
-	if (card->cardstate != CARD_RUNNING) {
-		printk(KERN_INFO "b1capi: controller %d not active, got: %s",
-		       card->cnr, capi_message2str(skb->data));
-		goto error;
-		return;
-	}
-	skb_queue_tail(&recv_queue, skb);
-	queue_task(&tq_recv_notify, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-	return;
-
-      error:
-	kfree_skb(skb);
-}
-
-void avmb1_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
-{
-	avmb1_card *card;
-
-	card = (avmb1_card *) devptr;
-
-	if (!card) {
-		printk(KERN_WARNING "avmb1_interrupt: wrong device\n");
-		return;
-	}
-	if (card->interrupt) {
-		printk(KERN_ERR "avmb1_interrupt: reentering interrupt hander\n");
-		return;
-	}
-
-	card->interrupt = 1;
-
-	B1_handle_interrupt(card);
-
-	card->interrupt = 0;
-}
-
-/* -------- Notifier ------------------------------------------ */
-
-static void notify_up(__u16 contr)
-{
-	struct capi_interface_user *p;
-
-        printk(KERN_NOTICE "b1capi: notify up contr %d\n", contr);
-	for (p = capi_users; p; p = p->next) {
-		if (p->callback)
-			(*p->callback) (KCI_CONTRUP, contr,
-				(capi_profile *)
-					CARD(contr)->version[VER_PROFILE]);
-	}
-}
-
-static void notify_down(__u16 contr)
-{
-	struct capi_interface_user *p;
-        printk(KERN_NOTICE "b1capi: notify down contr %d\n", contr);
-	for (p = capi_users; p; p = p->next) {
-		if (p->callback)
-			(*p->callback) (KCI_CONTRDOWN, contr, 0);
-	}
-}
-
-static void notify_handler(void *dummy)
-{
-	__u16 contr;
-
-	for (contr=1; VALID_CARD(contr); contr++)
-		 if (test_and_clear_bit(contr, &notify_up_set))
-			 notify_up(contr);
-	for (contr=1; VALID_CARD(contr); contr++)
-		 if (test_and_clear_bit(contr, &notify_down_set))
-			 notify_down(contr);
-}
-
-/* -------- card ready callback ------------------------------- */
-
-void avmb1_card_ready(avmb1_card * card)
-{
-        struct capi_profile *profp =
-			(struct capi_profile *)card->version[VER_PROFILE];
-	char *dversion = card->version[VER_DRIVER];
-	__u16 appl;
-	char *cardname, cname[20];
-	__u32 flag;
-
-	card->cversion.majorversion = 2;
-	card->cversion.minorversion = 0;
-	card->cversion.majormanuversion = (((dversion[0] - '0') & 0xf) << 4);
-	card->cversion.majormanuversion |= ((dversion[2] - '0') & 0xf);
-	card->cversion.minormanuversion = (dversion[3] - '0') << 4;
-	card->cversion.minormanuversion |=
-		(dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf);
-	card->cardstate = CARD_RUNNING;
-
-	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
-		if (VALID_APPLID(appl) && !APPL(appl)->releasing) {
-			B1_send_register(card->port, appl,
-				1024 * (APPL(appl)->rparam.level3cnt+1),
-				APPL(appl)->rparam.level3cnt,
-				APPL(appl)->rparam.datablkcnt,
-				APPL(appl)->rparam.datablklen);
-		}
-	}
-
-        set_bit(CARDNR(card), &notify_up_set);
-        queue_task(&tq_state_notify, &tq_scheduler);
-
-        flag = ((__u8 *)(profp->manu))[1];
-        switch (flag) {
-	case 0: cardname = cardtype2str(card->cardtype); break;
-	case 3: cardname = "PCMCIA B"; break;
-	case 4: cardname = "PCMCIA M1"; break;
-	case 5: cardname = "PCMCIA M2"; break;
-	case 6: cardname = "B1 V3.0"; break;
-	case 7: cardname = "B1 PCI"; break;
-	default: cardname = cname; break;
-                 sprintf(cname, "AVM?%u", (unsigned int)flag);
-                 break;
-        }
-        printk(KERN_NOTICE "b1capi: card %d \"%s\" ready.\n",
-		CARDNR(card), cardname);
-        flag = ((__u8 *)(profp->manu))[3];
-        if (flag)
-		printk(KERN_NOTICE "b1capi: card %d Protocol:%s%s%s%s%s%s%s\n",
-			CARDNR(card),
-			(flag & 0x01) ? " DSS1" : "",
-			(flag & 0x02) ? " CT1" : "",
-			(flag & 0x04) ? " VN3" : "",
-			(flag & 0x08) ? " NI1" : "",
-			(flag & 0x10) ? " AUSTEL" : "",
-			(flag & 0x20) ? " ESS" : "",
-			(flag & 0x40) ? " 1TR6" : ""
-			);
-        flag = ((__u8 *)(profp->manu))[5];
-	if (flag)
-		printk(KERN_NOTICE "b1capi: card %d Linetype:%s%s%s%s\n",
-			CARDNR(card),
-			(flag & 0x01) ? " point to point" : "",
-			(flag & 0x02) ? " point to multipoint" : "",
-			(flag & 0x08) ? " leased line without D-channel" : "",
-			(flag & 0x04) ? " leased line with D-channel" : ""
-			);
-}
-
-static void avmb1_card_down(avmb1_card * card, int notify)
-{
-	__u16 appl;
-
-        card->cardstate = CARD_DETECTED;
-
-	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
-		avmb1_ncci **pp, **nextpp;
-		for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
-			if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
-				avmb1_ncci *np = *pp;
-				*pp = np->next;
-				printk(KERN_INFO "b1capi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
-				kfree(np);
-				nextpp = pp;
-			} else {
-				nextpp = &(*pp)->next;
-			}
-		}
-	}
-	set_bit(CARDNR(card), &notify_down_set);
-	queue_task(&tq_state_notify, &tq_scheduler);
-	printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card));
-}
-
-/* ------------------------------------------------------------- */
-
-
-int avmb1_registercard(int port, int irq, int cardtype, int allocio)
-{
-	struct avmb1_card *card;
-	int irqval,i;
-
-
-	for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
-   
-	if (i == CAPI_MAXCONTR) {
-		printk(KERN_ERR "b1capi: out of controller slots\n");
-	   	return -ENFILE;
-	}
-
-	card = &cards[i];
-	memset(card, 0, sizeof(avmb1_card));
-	sprintf(card->name, "avmb1-%d", CARDNR(card));
-
-        if (allocio)
-		request_region(port, AVMB1_PORTLEN, card->name);
-
-	if ((irqval = request_irq(irq, avmb1_interrupt,
-				 SA_SHIRQ, card->name, card)) != 0) {
-		printk(KERN_ERR "b1capi: unable to get IRQ %d (irqval=%d).\n",
-		       irq, irqval);
-		release_region((unsigned short) port, AVMB1_PORTLEN);
-		return -EIO;
-	}
-
-	card->cardstate = CARD_DETECTED;
-	ncards++;
-	card->cnr = CARDNR(card);
-	card->port = port;
-	card->irq = irq;
-	card->cardtype = cardtype;
-	return card->cnr;
-}
-
-int avmb1_addcard(int port, int irq, int cardtype)
-{
-	return avmb1_registercard(port, irq, cardtype, 1);
-}
-
-int avmb1_detectcard(int port, int irq, int cardtype)
-{
-	int rc;
-
-	if (!B1_valid_irq(irq, cardtype)) {
-		printk(KERN_WARNING "b1capi: irq %d not valid for %s-card.\n",
-				irq, cardtype2str(cardtype));
-		return -EIO;
-	}
-	if ((rc = B1_detect(port, cardtype)) != 0) {
-		printk(KERN_NOTICE "b1capi: NO %s-card at 0x%x (%d)\n",
-					  cardtype2str(cardtype), port, rc);
-		return -EIO;
-	}
-	B1_reset(port);
-	switch (cardtype) {
-		default:
-	   	case AVM_CARDTYPE_M1:
-	   	case AVM_CARDTYPE_M2:
-	   	case AVM_CARDTYPE_B1:
-	    		printk(KERN_NOTICE "b1capi: AVM-%s-Controller detected at 0x%x\n", cardtype2str(cardtype), port);
-			break;
-	   	case AVM_CARDTYPE_T1:
-	    		printk(KERN_NOTICE "b1capi: AVM-%s-Controller may be at 0x%x\n", cardtype2str(cardtype), port);
-			break;
-	}
-
-	return 0;
-}
-
-int avmb1_probecard(int port, int irq, int cardtype)
-{
-	if (check_region((unsigned short) port, AVMB1_PORTLEN)) {
-		printk(KERN_WARNING
-		       "b1capi: ports 0x%03x-0x%03x in use.\n",
-		       port, port + AVMB1_PORTLEN);
-		return -EIO;
-	}
-        return avmb1_detectcard(port, irq, cardtype);
-}
-
-int avmb1_unregistercard(int cnr, int freeio)
-{
-	avmb1_card * card;
-   	if (!VALID_CARD(cnr)) 
-		return -ESRCH;
-	card = CARD(cnr);
-	if (card->cardstate == CARD_FREE)
-		return -ESRCH;
-	if (card->cardstate == CARD_RUNNING)
-		avmb1_card_down(card, freeio);
-
-	free_irq(card->irq, card);
-	if (freeio)
-		release_region(card->port, AVMB1_PORTLEN);
-	card->cardstate = CARD_FREE;
-	return 0;
-}
-
-int avmb1_resetcard(int cnr)
-{
-	avmb1_card * card;
-
-	if (!VALID_CARD(cnr))
-		return -ESRCH;
-	card = CARD(cnr);
-	if (card->cardstate == CARD_FREE)
-		return -ESRCH;
-
-	if (card->cardstate == CARD_RUNNING)
-		avmb1_card_down(card, 0);
-
-	B1_reset(card->port);
-	B1_reset(card->port);
-
-	card->cardstate = CARD_DETECTED;
-
-	return 0;
-}
-
-/* ------------------------------------------------------------- */
-/* -------- CAPI2.0 Interface ---------------------------------- */
-/* ------------------------------------------------------------- */
-
-static int capi_installed(void)
-{
-	int i;
-	for (i = 0; i < CAPI_MAXCONTR; i++) {
-		if (cards[i].cardstate == CARD_RUNNING)
-			return 1;
-	}
-	return 0;
-}
-
-static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
-{
-	int i;
-	int appl;
-
-	if (rparam->datablklen < 128)
-		return CAPI_LOGBLKSIZETOSMALL;
-
-	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
-		if (APPL_IS_FREE(appl))
-			break;
-	}
-	if (appl > CAPI_MAXAPPL)
-		return CAPI_TOOMANYAPPLS;
-
-	APPL_MARK_USED(appl);
-	skb_queue_head_init(&APPL(appl)->recv_queue);
-
-	memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
-
-	for (i = 0; i < CAPI_MAXCONTR; i++) {
-		if (cards[i].cardstate != CARD_RUNNING)
-			continue;
-		B1_send_register(cards[i].port, appl,
-			       1024 * (APPL(appl)->rparam.level3cnt + 1),
-				 APPL(appl)->rparam.level3cnt,
-				 APPL(appl)->rparam.datablkcnt,
-				 APPL(appl)->rparam.datablklen);
-	}
-	*applidp = appl;
-	printk(KERN_INFO "b1capi: appl %d up\n", appl);
-
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_release(__u16 applid)
-{
-	struct sk_buff *skb;
-	int i;
-
-	if (ncards == 0)
-		return CAPI_REGNOTINSTALLED;
-	if (!VALID_APPLID(applid) || APPL(applid)->releasing)
-		return CAPI_ILLAPPNR;
-	while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
-		kfree_skb(skb);
-	for (i = 0; i < CAPI_MAXCONTR; i++) {
-		if (cards[i].cardstate != CARD_RUNNING) {
-			continue;
-		}
-		APPL(applid)->releasing++;
-		B1_send_release(cards[i].port, applid);
-	}
-	if (APPL(applid)->releasing == 0) {
-	        APPL(applid)->signal = 0;
-		APPL_MARK_FREE(applid);
-		printk(KERN_INFO "b1capi: appl %d down\n", applid);
-	}
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
-{
-	avmb1_ncci *np;
-	int contr;
-	if (ncards == 0)
-		return CAPI_REGNOTINSTALLED;
-	if (!VALID_APPLID(applid))
-		return CAPI_ILLAPPNR;
-	if (skb->len < 12
-	    || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
-	    || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
-		return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
-	contr = CAPIMSG_CONTROLLER(skb->data);
-	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
-		contr = 1;
-	        if (CARD(contr)->cardstate != CARD_RUNNING) 
-			return CAPI_REGNOTINSTALLED;
-	}
-	if (CARD(contr)->blocked)
-		return CAPI_SENDQUEUEFULL;
-
-	if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
-	    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_REQ
-	    && (np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
-	    && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
-		return CAPI_SENDQUEUEFULL;
-
-	B1_send_message(CARD(contr)->port, skb);
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
-{
-	struct sk_buff *skb;
-
-	if (!VALID_APPLID(applid))
-		return CAPI_ILLAPPNR;
-	if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
-		return CAPI_RECEIVEQUEUEEMPTY;
-	*msgp = skb;
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_set_signal(__u16 applid,
-			     void (*signal) (__u16 applid, __u32 param),
-			     __u32 param)
-{
-	if (!VALID_APPLID(applid))
-		return CAPI_ILLAPPNR;
-	APPL(applid)->signal = signal;
-	APPL(applid)->param = param;
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
-{
-	if (contr == 0) {
-		strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
-		return CAPI_NOERROR;
-	}
-	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
-
-	strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_get_version(__u16 contr, struct capi_version *verp)
-{
-	if (contr == 0) {
-		*verp = driver_version;
-		return CAPI_NOERROR;
-	}
-	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
-
-	memcpy((void *) verp, &CARD(contr)->cversion,
-	       sizeof(capi_version));
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN])
-{
-	if (contr == 0) {
-		strncpy(serial, driver_serial, 8);
-		return CAPI_NOERROR;
-	}
-	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
-
-	memcpy((void *) serial, CARD(contr)->version[VER_SERIAL],
-	       CAPI_SERIAL_LEN);
-	serial[CAPI_SERIAL_LEN - 1] = 0;
-	return CAPI_NOERROR;
-}
-
-static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp)
-{
-	if (contr == 0) {
-		profp->ncontroller = ncards;
-		return CAPI_NOERROR;
-	}
-	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
-		return 0x2002;
-
-	memcpy((void *) profp, CARD(contr)->version[VER_PROFILE],
-	       sizeof(struct capi_profile));
-	return CAPI_NOERROR;
-}
-
-static int capi_manufacturer(unsigned int cmd, void *data)
-{
-	unsigned long flags;
-	avmb1_loadandconfigdef ldef;
-	avmb1_extcarddef cdef;
-	avmb1_resetdef rdef;
-	avmb1_getdef gdef;
-	avmb1_card *card;
-	int rc;
-
-	switch (cmd) {
-	case AVMB1_ADDCARD:
-	case AVMB1_ADDCARD_WITH_TYPE:
-		if (cmd == AVMB1_ADDCARD) {
-		   if ((rc = copy_from_user((void *) &cdef, data,
-					    sizeof(avmb1_carddef))))
-			   return rc;
-		   cdef.cardtype = AVM_CARDTYPE_B1;
-		} else {
-		   if ((rc = copy_from_user((void *) &cdef, data,
-					    sizeof(avmb1_extcarddef))))
-			   return rc;
-		}
-
-		if ((rc = avmb1_probecard(cdef.port, cdef.irq, cdef.cardtype)) != 0)
-			return rc;
-
-		return avmb1_addcard(cdef.port, cdef.irq, cdef.cardtype);
-
-	case AVMB1_LOAD:
-	case AVMB1_LOAD_AND_CONFIG:
-
-		if (cmd == AVMB1_LOAD) {
-			if ((rc = copy_from_user((void *) &ldef, data,
-						sizeof(avmb1_loaddef))))
-				return rc;
-			ldef.t4config.len = 0;
-			ldef.t4config.data = 0;
-		} else {
-			if ((rc = copy_from_user((void *) &ldef, data,
-					    	sizeof(avmb1_loadandconfigdef))))
-				return rc;
-		}
-		if (!VALID_CARD(ldef.contr))
-			return -ESRCH;
-
-		if (ldef.t4file.len <= 0) {
-			if (loaddebug)
-				printk(KERN_DEBUG "b1capi: load: invalid parameter length of t4file is %d ?\n", ldef.t4file.len);
-			return -EINVAL;
-		}
-
-		card = CARD(ldef.contr);
-		save_flags(flags);
-		cli();
-		if (card->cardstate != CARD_DETECTED) {
-			restore_flags(flags);
-			if (loaddebug)
-				printk(KERN_DEBUG "b1capi: load: contr=%d not in detect state\n", ldef.contr);
-			return -EBUSY;
-		}
-		card->cardstate = CARD_LOADING;
-		restore_flags(flags);
-
-		if (loaddebug) {
-			printk(KERN_DEBUG "b1capi: load: reseting contr %d\n",
-				ldef.contr);
-		}
-
-		B1_reset(card->port);
-		if ((rc = B1_load_t4file(card->port, &ldef.t4file))) {
-			B1_reset(card->port);
-			printk(KERN_ERR "b1capi: failed to load t4file!!\n");
-			card->cardstate = CARD_DETECTED;
-			return rc;
-		}
-		B1_disable_irq(card->port);
-
-		if (ldef.t4config.len > 0) { /* load config */
-		        if (loaddebug) {
-				printk(KERN_DEBUG "b1capi: loading config to contr %d\n",
-				   			ldef.contr);
-		   	}
-			if ((rc = B1_load_config(card->port, &ldef.t4config))) {
-				B1_reset(card->port);
-				printk(KERN_ERR "b1capi: failed to load config!!\n");
-				card->cardstate = CARD_DETECTED;
-				return rc;
-			}
-		}
-
-		if (loaddebug) {
-			printk(KERN_DEBUG "b1capi: load: ready contr %d: checking\n",
-				ldef.contr);
-		}
-
-		if (!B1_loaded(card->port)) {
-			card->cardstate = CARD_DETECTED;
-			printk(KERN_ERR "b1capi: failed to load t4file.\n");
-			return -EIO;
-		}
-		/*
-		 * enable interrupt
-		 */
-
-		card->cardstate = CARD_INITSTATE;
-		save_flags(flags);
-		cli();
-		B1_assign_irq(card->port, card->irq, card->cardtype);
-		B1_enable_irq(card->port);
-		restore_flags(flags);
-
-		if (loaddebug) {
-			printk(KERN_DEBUG "b1capi: load: irq enabled contr %d\n",
-				ldef.contr);
-		}
-
-		/*
-		 * init card
-		 */
-		B1_send_init(card->port, AVM_NAPPS, AVM_NNCCI, card->cnr - 1);
-
-		if (loaddebug) {
-			printk(KERN_DEBUG "b1capi: load: waiting for init reply contr %d\n",
-				ldef.contr);
-		}
-
-		while (card->cardstate != CARD_RUNNING) {
-
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(HZ/10);	/* 0.1 sec */
-
-			if (signal_pending(current))
-				return -EINTR;
-		}
-		return 0;
-
-	case AVMB1_RESETCARD:
-		if ((rc = copy_from_user((void *) &rdef, data,
-					 sizeof(avmb1_resetdef))))
-			return rc;
-
-		return avmb1_resetcard(rdef.contr);
-
-	case AVMB1_GET_CARDINFO:
-		if ((rc = copy_from_user((void *) &gdef, data,
-					 sizeof(avmb1_getdef))))
-			return rc;
-
-		if (!VALID_CARD(gdef.contr))
-			return -ESRCH;
-
-		card = CARD(gdef.contr);
-
-		gdef.cardstate = card->cardstate;
-		gdef.cardtype = card->cardtype;
-
-		if ((rc = copy_to_user(data, (void *) &gdef,
-					 sizeof(avmb1_getdef))))
-			return rc;
-
-		return 0;
-	}
-	return -EINVAL;
-}
-
-struct capi_interface avmb1_interface =
-{
-	capi_installed,
-	capi_register,
-	capi_release,
-	capi_put_message,
-	capi_get_message,
-	capi_set_signal,
-	capi_get_manufacturer,
-	capi_get_version,
-	capi_get_serial,
-	capi_get_profile,
-	capi_manufacturer
-};
-
-/* ------------------------------------------------------------- */
-/* -------- Exported Functions --------------------------------- */
-/* ------------------------------------------------------------- */
-
-struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
-{
-	struct capi_interface_user *p;
-
-	for (p = capi_users; p; p = p->next) {
-		if (p == userp) {
-			printk(KERN_ERR "b1capi: double attach from %s\n",
-			       userp->name);
-			return 0;
-		}
-	}
-	userp->next = capi_users;
-	capi_users = userp;
-	MOD_INC_USE_COUNT;
-
-	return &avmb1_interface;
-}
-
-int detach_capi_interface(struct capi_interface_user *userp)
-{
-	struct capi_interface_user **pp;
-
-	for (pp = &capi_users; *pp; pp = &(*pp)->next) {
-		if (*pp == userp) {
-			*pp = userp->next;
-			userp->next = 0;
-			MOD_DEC_USE_COUNT;
-			return 0;
-		}
-	}
-	printk(KERN_ERR "b1capi: double detach from %s\n", userp->name);
-	return -1;
-}
-
-/* ------------------------------------------------------------- */
-/* -------- Init & Cleanup ------------------------------------- */
-/* ------------------------------------------------------------- */
-
-EXPORT_SYMBOL(attach_capi_interface);
-EXPORT_SYMBOL(detach_capi_interface);
-EXPORT_SYMBOL(avmb1_addcard);
-EXPORT_SYMBOL(avmb1_probecard);
-EXPORT_SYMBOL(avmb1_registercard);
-EXPORT_SYMBOL(avmb1_unregistercard);
-EXPORT_SYMBOL(avmb1_resetcard);
-EXPORT_SYMBOL(avmb1_detectcard);
-
-
-/*
- * init / exit functions
- */
-
-#ifdef MODULE
-#define avmb1_init init_module
-#endif
-
-int avmb1_init(void)
-{
-	char *p;
-	char rev[10];
-
-	skb_queue_head_init(&recv_queue);
-	/* init_bh(CAPI_BH, do_capi_bh); */
-
-	tq_state_notify.routine = notify_handler;
-	tq_state_notify.data = 0;
-
-	tq_recv_notify.routine = recv_handler;
-	tq_recv_notify.data = 0;
-
-
-	if ((p = strchr(revision, ':'))) {
-		strcpy(rev, p + 1);
-		p = strchr(rev, '$');
-		*p = 0;
-	} else
-		strcpy(rev, " ??? ");
-
-#ifdef MODULE
-        printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: loaded\n", rev);
-#else
-	printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: started\n", rev);
-#endif
-	return 0;
-}
-
-#ifdef MODULE
-void cleanup_module(void)
-{
-	char rev[10];
-	char *p;
-	int i;
-
-	if ((p = strchr(revision, ':'))) {
-		strcpy(rev, p + 1);
-		p = strchr(rev, '$');
-		*p = 0;
-	} else {
-		strcpy(rev, " ??? ");
-	}
-
-	for (i = 0; i < CAPI_MAXCONTR; i++) {
-		if (cards[i].cardstate != CARD_FREE) {
-			/*
-			 * disable card
-			 */
-			B1_disable_irq(cards[i].port);
-			avmb1_resetcard(i+1);
-			/*
-			 * free kernel resources
-			 */
-			avmb1_unregistercard(i+1, 1);
-		}
-	}
-	schedule(); /* execute queued tasks .... */
-	printk(KERN_NOTICE "AVM-B1-CAPI-driver Rev%s: unloaded\n", rev);
-}
-#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1isa.c linux.pre11.3/drivers/isdn/avmb1/b1isa.c
--- linux.vanilla/drivers/isdn/avmb1/b1isa.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/b1isa.c	Mon Jul 19 23:59:32 1999
@@ -0,0 +1,238 @@
+/*
+ * $Id: b1isa.c,v 1.3 1999/07/09 15:05:40 keil Exp $
+ * 
+ * Module for AVM B1 ISA-card.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: b1isa.c,v $
+ * Revision 1.3  1999/07/09 15:05:40  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.2  1999/07/05 15:09:49  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:27  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.3 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static void b1isa_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	release_region(card->port, AVMB1_PORTLEN);
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "b1isa: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	sprintf(card->name, "b1isa-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->cardtype = avm_b1isa;
+
+	if (check_region(card->port, AVMB1_PORTLEN)) {
+		printk(KERN_WARNING
+		       "b1isa: ports 0x%03x-0x%03x in use.\n",
+		       card->port, card->port + AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+	if (b1_irq_table[card->irq & 0xf] == 0) {
+		printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq);
+		kfree(card);
+		return -EINVAL;
+	}
+	if (   card->port != 0x150 && card->port != 0x250
+	    && card->port != 0x300 && card->port != 0x340) {
+		printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port);
+		kfree(card);
+		return -EINVAL;
+	}
+	b1_reset(card->port);
+	if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
+		printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n",
+					card->port, retval);
+		kfree(card);
+		return -EIO;
+	}
+	b1_reset(card->port);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, b1isa_interrupt, 0, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "b1isa: attach controller failed.\n");
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static char *b1isa_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		return "";
+	sprintf(card->infobuf, "%s %s 0x%x %d",
+		card->cardname[0] ? card->cardname : "-",
+		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
+		card->port, card->irq
+		);
+	return card->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver b1isa_driver = {
+    "b1isa",
+    "0.0",
+    b1_load_firmware,
+    b1_reset_ctr,
+    b1isa_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    b1_send_message,
+
+    b1isa_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    b1isa_add_card,
+};
+
+#ifdef MODULE
+#define b1isa_init init_module
+void cleanup_module(void);
+#endif
+
+int b1isa_init(void)
+{
+	struct capi_driver *driver = &b1isa_driver;
+	char *p;
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
+		*p = 0;
+	} 
+
+	printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+        di = attach_capi_driver(driver);
+
+	if (!di) {
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driver->name);
+		return -EIO;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&b1isa_driver);
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1lli.c linux.pre11.3/drivers/isdn/avmb1/b1lli.c
--- linux.vanilla/drivers/isdn/avmb1/b1lli.c	Mon Dec 28 23:09:42 1998
+++ linux.pre11.3/drivers/isdn/avmb1/b1lli.c	Mon Jul 19 23:59:32 1999
@@ -1,749 +0,0 @@
-/*
- * $Id: b1lli.c,v 1.6 1998/02/13 07:09:11 calle Exp $
- * 
- * ISDN lowlevel-module for AVM B1-card.
- * 
- * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
- * 
- * $Log: b1lli.c,v $
- * Revision 1.6  1998/02/13 07:09:11  calle
- * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
- *
- * Revision 1.5  1998/01/31 11:14:41  calle
- * merged changes to 2.0 tree, prepare 2.1.82 to work.
- *
- * Revision 1.4  1997/12/10 20:00:48  calle
- * get changes from 2.0 version
- *
- * Revision 1.1.2.2  1997/11/26 10:46:55  calle
- * prepared for M1 (Mobile) and T1 (PMX) cards.
- * prepared to set configuration after load to support other D-channel
- * protocols, point-to-point and leased lines.
- *
- * Revision 1.3  1997/10/01 09:21:13  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.2  1997/07/13 12:22:42  calle
- * bug fix for more than one controller in connect_req.
- * debugoutput now with contrnr.
- *
- *
- * Revision 1.1  1997/03/04 21:50:28  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
- *
- * 
- */
-
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <linux/capi.h>
-#include <linux/b1lli.h>
-
-#include "compat.h"
-#include "capicmd.h"
-#include "capiutil.h"
-
-/*
- * LLI Messages to the ISDN-ControllerISDN Controller 
- */
-
-#define	SEND_POLL		0x72	/*
-					   * after load <- RECEIVE_POLL 
-					 */
-#define SEND_INIT		0x11	/*
-					   * first message <- RECEIVE_INIT
-					   * int32 NumApplications  int32
-					   * NumNCCIs int32 BoardNumber 
-					 */
-#define SEND_REGISTER		0x12	/*
-					   * register an application int32
-					   * ApplIDId int32 NumMessages
-					   * int32 NumB3Connections int32
-					   * NumB3Blocks int32 B3Size
-					   * 
-					   * AnzB3Connection != 0 &&
-					   * AnzB3Blocks >= 1 && B3Size >= 1 
-					 */
-#define SEND_RELEASE		0x14	/*
-					   * deregister an application int32 
-					   * ApplID 
-					 */
-#define SEND_MESSAGE		0x15	/*
-					   * send capi-message int32 length
-					   * capi-data ... 
-					 */
-#define SEND_DATA_B3_REQ	0x13	/*
-					   * send capi-data-message int32
-					   * MsgLength capi-data ... int32
-					   * B3Length data .... 
-					 */
-
-#define SEND_CONFIG		0x21    /*
-                                         */
-
-/*
- * LLI Messages from the ISDN-ControllerISDN Controller 
- */
-
-#define RECEIVE_POLL		0x32	/*
-					   * <- after SEND_POLL 
-					 */
-#define RECEIVE_INIT		0x27	/*
-					   * <- after SEND_INIT int32 length
-					   * byte total length b1struct board 
-					   * driver revision b1struct card
-					   * type b1struct reserved b1struct
-					   * serial number b1struct driver
-					   * capability b1struct d-channel
-					   * protocol b1struct CAPI-2.0
-					   * profile b1struct capi version 
-					 */
-#define RECEIVE_MESSAGE		0x21	/*
-					   * <- after SEND_MESSAGE int32
-					   * AppllID int32 Length capi-data
-					   * .... 
-					 */
-#define RECEIVE_DATA_B3_IND	0x22	/*
-					   * received data int32 AppllID
-					   * int32 Length capi-data ...
-					   * int32 B3Length data ... 
-					 */
-#define RECEIVE_START		0x23	/*
-					   * Handshake 
-					 */
-#define RECEIVE_STOP		0x24	/*
-					   * Handshake 
-					 */
-#define RECEIVE_NEW_NCCI	0x25	/*
-					   * int32 AppllID int32 NCCI int32
-					   * WindowSize 
-					 */
-#define RECEIVE_FREE_NCCI	0x26	/*
-					   * int32 AppllID int32 NCCI 
-					 */
-#define RECEIVE_RELEASE		0x26	/*
-					   * int32 AppllID int32 0xffffffff 
-					 */
-
-#define WRITE_REGISTER		0x00
-#define READ_REGISTER		0x01
-
-/*
- * port offsets
- */
-
-#define B1_READ			0x00
-#define B1_WRITE		0x01
-#define B1_INSTAT		0x02
-#define B1_OUTSTAT		0x03
-#define B1_RESET		0x10
-#define B1_ANALYSE		0x04
-#define B1_IDENT		0x17  /* Hema card T1 */
-#define B1_IRQ_MASTER		0x12  /* Hema card T1 */
-
-#define B1_STAT0(cardtype)  ((cardtype) == AVM_CARDTYPE_M1 ? 0x81200000l : 0x80A00000l)
-#define B1_STAT1(cardtype)  (0x80E00000l)
-
-
-static inline unsigned char b1outp(unsigned short base,
-				   unsigned short offset,
-				   unsigned char value)
-{
-	outb(value, base + offset);
-	return inb(base + B1_ANALYSE);
-}
-
-static inline int B1_rx_full(unsigned short base)
-{
-	return inb(base + B1_INSTAT) & 0x1;
-}
-
-static inline unsigned char B1_get_byte(unsigned short base)
-{
-	unsigned long i = jiffies + 5 * HZ;	/* maximum wait time 5 sec */
-	while (!B1_rx_full(base) && time_before(jiffies, i));
-	if (B1_rx_full(base))
-		return inb(base + B1_READ);
-	printk(KERN_CRIT "b1lli: rx not full after 5 second\n");
-	return 0;
-}
-
-static inline unsigned int B1_get_word(unsigned short base)
-{
-	unsigned int val = 0;
-	val |= B1_get_byte(base);
-	val |= (B1_get_byte(base) << 8);
-	val |= (B1_get_byte(base) << 16);
-	val |= (B1_get_byte(base) << 24);
-	return val;
-}
-
-static inline int B1_tx_empty(unsigned short base)
-{
-	return inb(base + B1_OUTSTAT) & 0x1;
-}
-
-static inline void B1_put_byte(unsigned short base, unsigned char val)
-{
-	while (!B1_tx_empty(base));
-	b1outp(base, B1_WRITE, val);
-}
-
-static inline void B1_put_word(unsigned short base, unsigned int val)
-{
-	B1_put_byte(base, val & 0xff);
-	B1_put_byte(base, (val >> 8) & 0xff);
-	B1_put_byte(base, (val >> 16) & 0xff);
-	B1_put_byte(base, (val >> 24) & 0xff);
-}
-
-static inline unsigned int B1_get_slice(unsigned short base,
-					unsigned char *dp)
-{
-	unsigned int len, i;
-
-	len = i = B1_get_word(base);
-	while (i-- > 0)
-		*dp++ = B1_get_byte(base);
-	return len;
-}
-
-static inline void B1_put_slice(unsigned short base,
-				unsigned char *dp, unsigned int len)
-{
-	B1_put_word(base, len);
-	while (len-- > 0)
-		B1_put_byte(base, *dp++);
-}
-
-static void b1_wr_reg(unsigned short base,
-                      unsigned int reg,
-		      unsigned int value)
-{
-	B1_put_byte(base, WRITE_REGISTER);
-        B1_put_word(base, reg);
-        B1_put_word(base, value);
-}
-
-static inline unsigned int b1_rd_reg(unsigned short base,
-                                     unsigned int reg)
-{
-	B1_put_byte(base, READ_REGISTER);
-        B1_put_word(base, reg);
-        return B1_get_word(base);
-	
-}
-
-static inline void b1_set_test_bit(unsigned short base,
-				   int cardtype,
-				   int onoff)
-{
-    b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
-}
-
-static inline int b1_get_test_bit(unsigned short base,
-                                  int cardtype)
-{
-    return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
-}
-
-static int irq_table[16] =
-{0,
- 0,
- 0,
- 192,				/* irq 3 */
- 32,				/* irq 4 */
- 160,				/* irq 5 */
- 96,				/* irq 6 */
- 224,				/* irq 7 */
- 0,
- 64,				/* irq 9 */
- 80,				/* irq 10 */
- 208,				/* irq 11 */
- 48,				/* irq 12 */
- 0,
- 0,
- 112,				/* irq 15 */
-};
-
-int B1_valid_irq(unsigned irq, int cardtype)
-{
-	switch (cardtype) {
-	   default:
-	   case AVM_CARDTYPE_M1:
-	   case AVM_CARDTYPE_M2:
-	   case AVM_CARDTYPE_B1:
-	   	return irq_table[irq] != 0;
-	   case AVM_CARDTYPE_T1:
-	   	return irq == 5;
-	}
-}
-
-unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype)
-{
-	switch (cardtype) {
-	   case AVM_CARDTYPE_T1:
-	      return b1outp(base, B1_IRQ_MASTER, 0x08);
-	   default:
-	   case AVM_CARDTYPE_M1:
-	   case AVM_CARDTYPE_M2:
-	   case AVM_CARDTYPE_B1:
-	      return b1outp(base, B1_RESET, irq_table[irq]);
-	 }
-}
-
-unsigned char B1_enable_irq(unsigned short base)
-{
-	return b1outp(base, B1_INSTAT, 0x02);
-}
-
-unsigned char B1_disable_irq(unsigned short base)
-{
-	return b1outp(base, B1_INSTAT, 0x00);
-}
-
-void B1_reset(unsigned short base)
-{
-	b1outp(base, B1_RESET, 0);
-	udelay(55 * 2 * 1000);	/* 2 TIC's */
-
-	b1outp(base, B1_RESET, 1);
-	udelay(55 * 2 * 1000);	/* 2 TIC's */
-
-	b1outp(base, B1_RESET, 0);
-	udelay(55 * 2 * 1000);	/* 2 TIC's */
-}
-
-int B1_detect(unsigned short base, int cardtype)
-{
-	int onoff, i;
-
-	if (cardtype == AVM_CARDTYPE_T1)
-	   return 0;
-
-	/*
-	 * Statusregister 0000 00xx 
-	 */
-	if ((inb(base + B1_INSTAT) & 0xfc)
-	    || (inb(base + B1_OUTSTAT) & 0xfc))
-		return 1;
-	/*
-	 * Statusregister 0000 001x 
-	 */
-	b1outp(base, B1_INSTAT, 0x2);	/* enable irq */
-	/* b1outp(base, B1_OUTSTAT, 0x2); */
-	if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
-	    /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
-		return 2;
-	/*
-	 * Statusregister 0000 000x 
-	 */
-	b1outp(base, B1_INSTAT, 0x0);	/* disable irq */
-	b1outp(base, B1_OUTSTAT, 0x0);
-	if ((inb(base + B1_INSTAT) & 0xfe)
-	    || (inb(base + B1_OUTSTAT) & 0xfe))
-		return 3;
-        
-	for (onoff = !0, i= 0; i < 10 ; i++) {
-		b1_set_test_bit(base, cardtype, onoff);
-		if (b1_get_test_bit(base, cardtype) != onoff)
-		   return 4;
-		onoff = !onoff;
-	}
-
-	if (cardtype == AVM_CARDTYPE_M1)
-	   return 0;
-
-        if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
-	   return 5;
-
-	return 0;
-}
-
-
-extern int loaddebug;
-
-int B1_load_t4file(unsigned short base, avmb1_t4file * t4file)
-{
-	/*
-	 * Data is in user space !!!
-	 */
-	unsigned char buf[256];
-	unsigned char *dp;
-	int i, left, retval;
-
-
-	dp = t4file->data;
-	left = t4file->len;
-	while (left > sizeof(buf)) {
-		retval = copy_from_user(buf, dp, sizeof(buf));
-		if (retval)
-			return -EFAULT;
-		if (loaddebug)
-			printk(KERN_DEBUG "b1capi: loading: %d bytes ..", sizeof(buf));
-		for (i = 0; i < sizeof(buf); i++)
-			B1_put_byte(base, buf[i]);
-		if (loaddebug)
-		   printk("ok\n");
-		left -= sizeof(buf);
-		dp += sizeof(buf);
-	}
-	if (left) {
-		retval = copy_from_user(buf, dp, left);
-		if (retval)
-			return -EFAULT;
-		if (loaddebug)
-			printk(KERN_DEBUG "b1capi: loading: %d bytes ..", left);
-		for (i = 0; i < left; i++)
-			B1_put_byte(base, buf[i]);
-		if (loaddebug)
-		   printk("ok\n");
-	}
-	return 0;
-}
-
-int B1_load_config(unsigned short base, avmb1_t4file * config)
-{
-	/*
-	 * Data is in user space !!!
-	 */
-	unsigned char buf[256];
-	unsigned char *dp;
-	int i, j, left, retval;
-
-
-	dp = config->data;
-	left = config->len;
-	if (left) {
-		B1_put_byte(base, SEND_CONFIG);
-        	B1_put_word(base, 1);
-		B1_put_byte(base, SEND_CONFIG);
-        	B1_put_word(base, left);
-	}
-	while (left > sizeof(buf)) {
-		retval = copy_from_user(buf, dp, sizeof(buf));
-		if (retval)
-			return -EFAULT;
-		if (loaddebug)
-			printk(KERN_DEBUG "b1capi: conf load: %d bytes ..", sizeof(buf));
-		for (i = 0; i < sizeof(buf); ) {
-			B1_put_byte(base, SEND_CONFIG);
-			for (j=0; j < 4; j++) {
-				B1_put_byte(base, buf[i++]);
-			}
-		}
-		if (loaddebug)
-		   printk("ok\n");
-		left -= sizeof(buf);
-		dp += sizeof(buf);
-	}
-	if (left) {
-		retval = copy_from_user(buf, dp, left);
-		if (retval)
-			return -EFAULT;
-		if (loaddebug)
-			printk(KERN_DEBUG "b1capi: conf load: %d bytes ..", left);
-		for (i = 0; i < left; ) {
-			B1_put_byte(base, SEND_CONFIG);
-			for (j=0; j < 4; j++) {
-				if (i < left)
-					B1_put_byte(base, buf[i++]);
-				else
-					B1_put_byte(base, 0);
-			}
-		}
-		if (loaddebug)
-		   printk("ok\n");
-	}
-	return 0;
-}
-
-int B1_loaded(unsigned short base)
-{
-	int i;
-	unsigned char ans;
-
-	if (loaddebug)
-		printk(KERN_DEBUG "b1capi: loaded: wait 1 ..\n");
-	for (i = jiffies + 10 * HZ; time_before(jiffies, i);) {
-		if (B1_tx_empty(base))
-			break;
-	}
-	if (!B1_tx_empty(base)) {
-		printk(KERN_ERR "b1lli: B1_loaded: timeout tx\n");
-		return 0;
-	}
-	B1_put_byte(base, SEND_POLL);
-	printk(KERN_DEBUG "b1capi: loaded: wait 2 ..\n");
-	for (i = jiffies + 10 * HZ; time_before(jiffies, i);) {
-		if (B1_rx_full(base)) {
-			if ((ans = B1_get_byte(base)) == RECEIVE_POLL) {
-				if (loaddebug)
-					printk(KERN_DEBUG "b1capi: loaded: ok\n");
-				return 1;
-			}
-			printk(KERN_ERR "b1lli: B1_loaded: got 0x%x ???\n", ans);
-			return 0;
-		}
-	}
-	printk(KERN_ERR "b1lli: B1_loaded: timeout rx\n");
-	return 0;
-}
-
-/*
- * ------------------------------------------------------------------- 
- */
-static inline void parse_version(avmb1_card * card)
-{
-	int i, j;
-	for (j = 0; j < AVM_MAXVERSION; j++)
-		card->version[j] = "\0\0" + 1;
-	for (i = 0, j = 0;
-	     j < AVM_MAXVERSION && i < card->versionlen;
-	     j++, i += card->versionbuf[i] + 1)
-		card->version[j] = &card->versionbuf[i + 1];
-}
-/*
- * ------------------------------------------------------------------- 
- */
-
-void B1_send_init(unsigned short port,
-	     unsigned int napps, unsigned int nncci, unsigned int cardnr)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	B1_put_byte(port, SEND_INIT);
-	B1_put_word(port, napps);
-	B1_put_word(port, nncci);
-	B1_put_word(port, cardnr);
-	restore_flags(flags);
-}
-
-void B1_send_register(unsigned short port,
-		      __u16 appid, __u32 nmsg,
-		      __u32 nb3conn, __u32 nb3blocks, __u32 b3bsize)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	B1_put_byte(port, SEND_REGISTER);
-	B1_put_word(port, appid);
-	B1_put_word(port, nmsg);
-	B1_put_word(port, nb3conn);
-	B1_put_word(port, nb3blocks);
-	B1_put_word(port, b3bsize);
-	restore_flags(flags);
-}
-
-void B1_send_release(unsigned short port,
-		     __u16 appid)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	B1_put_byte(port, SEND_RELEASE);
-	B1_put_word(port, appid);
-	restore_flags(flags);
-}
-
-extern int showcapimsgs;
-
-void B1_send_message(unsigned short port, struct sk_buff *skb)
-{
-	unsigned long flags;
-	__u16 len = CAPIMSG_LEN(skb->data);
-	__u8 cmd = CAPIMSG_COMMAND(skb->data);
-	__u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
-	__u32 contr = CAPIMSG_CONTROL(skb->data);
-
-	if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
-		__u16 dlen = CAPIMSG_DATALEN(skb->data);
-
-		if (showcapimsgs > 2) {
-			if (showcapimsgs & 1) {
-				printk(KERN_DEBUG "b1lli: Put [0x%lx] id#%d %s len=%u\n",
-				       (unsigned long) contr,
-				       CAPIMSG_APPID(skb->data),
-				       capi_cmd2str(cmd, subcmd), len);
-			} else {
-				printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n",
-						(unsigned long) contr,
-						capi_message2str(skb->data));
-			}
-
-		}
-		save_flags(flags);
-		cli();
-		B1_put_byte(port, SEND_DATA_B3_REQ);
-		B1_put_slice(port, skb->data, len);
-		B1_put_slice(port, skb->data + len, dlen);
-		restore_flags(flags);
-	} else {
-		if (showcapimsgs) {
-
-			if (showcapimsgs & 1) {
-				printk(KERN_DEBUG "b1lli: Put [0x%lx] id#%d %s len=%u\n",
-				       (unsigned long) contr,
-				       CAPIMSG_APPID(skb->data),
-				       capi_cmd2str(cmd, subcmd), len);
-			} else {
-				printk(KERN_DEBUG "b1lli: Put [0x%lx] %s\n", (unsigned long)contr, capi_message2str(skb->data));
-			}
-		}
-		save_flags(flags);
-		cli();
-		B1_put_byte(port, SEND_MESSAGE);
-		B1_put_slice(port, skb->data, len);
-		restore_flags(flags);
-	}
-	dev_kfree_skb(skb);
-}
-
-/*
- * ------------------------------------------------------------------- 
- */
-
-void B1_handle_interrupt(avmb1_card * card)
-{
-	unsigned char b1cmd;
-	struct sk_buff *skb;
-
-	unsigned ApplId;
-	unsigned MsgLen;
-	unsigned DataB3Len;
-	unsigned NCCI;
-	unsigned WindowSize;
-
-	if (!B1_rx_full(card->port))
-		return;
-
-	b1cmd = B1_get_byte(card->port);
-
-	switch (b1cmd) {
-
-	case RECEIVE_DATA_B3_IND:
-
-		ApplId = (unsigned) B1_get_word(card->port);
-		MsgLen = B1_get_slice(card->port, card->msgbuf);
-		DataB3Len = B1_get_slice(card->port, card->databuf);
-
-		if (showcapimsgs > 2) {
-			__u8 cmd = CAPIMSG_COMMAND(card->msgbuf);
-			__u8 subcmd = CAPIMSG_SUBCOMMAND(card->msgbuf);
-			__u32 contr = CAPIMSG_CONTROL(card->msgbuf);
-			CAPIMSG_SETDATA(card->msgbuf, card->databuf);
-			if (showcapimsgs & 1) {
-				printk(KERN_DEBUG "b1lli: Got [0x%lx] id#%d %s len=%u/%u\n",
-				       (unsigned long) contr,
-				       CAPIMSG_APPID(card->msgbuf),
-				       capi_cmd2str(cmd, subcmd),
-				       MsgLen, DataB3Len);
-			} else {
-				printk(KERN_DEBUG "b1lli: Got [0x%lx] %s\n", (unsigned long)contr, capi_message2str(card->msgbuf));
-			}
-		}
-		if (!(skb = dev_alloc_skb(DataB3Len + MsgLen))) {
-			printk(KERN_ERR "b1lli: incoming packet dropped\n");
-		} else {
-			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
-			memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
-			CAPIMSG_SETDATA(skb->data, skb->data + MsgLen);
-			avmb1_handle_capimsg(card, ApplId, skb);
-		}
-		break;
-
-	case RECEIVE_MESSAGE:
-
-		ApplId = (unsigned) B1_get_word(card->port);
-		MsgLen = B1_get_slice(card->port, card->msgbuf);
-		if (showcapimsgs) {
-			__u8 cmd = CAPIMSG_COMMAND(card->msgbuf);
-			__u8 subcmd = CAPIMSG_SUBCOMMAND(card->msgbuf);
-			__u32 contr = CAPIMSG_CONTROL(card->msgbuf);
-			if (showcapimsgs & 1) {
-				printk(KERN_DEBUG "b1lli: Got [0x%lx] id#%d %s len=%u\n",
-				       (unsigned long) contr,
-				       CAPIMSG_APPID(card->msgbuf),
-				       capi_cmd2str(cmd, subcmd),
-				       MsgLen);
-			} else {
-				printk(KERN_DEBUG "b1lli: Got [0x%lx] %s\n",
-						(unsigned long) contr,
-						capi_message2str(card->msgbuf));
-			}
-
-		}
-		if (!(skb = dev_alloc_skb(MsgLen))) {
-			printk(KERN_ERR "b1lli: incoming packet dropped\n");
-		} else {
-			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
-			avmb1_handle_capimsg(card, ApplId, skb);
-		}
-		break;
-
-	case RECEIVE_NEW_NCCI:
-
-		ApplId = B1_get_word(card->port);
-		NCCI = B1_get_word(card->port);
-		WindowSize = B1_get_word(card->port);
-
-		if (showcapimsgs)
-			printk(KERN_DEBUG "b1lli: NEW_NCCI app %u ncci 0x%x\n", ApplId, NCCI);
-
-		avmb1_handle_new_ncci(card, ApplId, NCCI, WindowSize);
-
-		break;
-
-	case RECEIVE_FREE_NCCI:
-
-		ApplId = B1_get_word(card->port);
-		NCCI = B1_get_word(card->port);
-
-		if (showcapimsgs)
-			printk(KERN_DEBUG "b1lli: FREE_NCCI app %u ncci 0x%x\n", ApplId, NCCI);
-
-		avmb1_handle_free_ncci(card, ApplId, NCCI);
-		break;
-
-	case RECEIVE_START:
-		if (card->blocked)
-			printk(KERN_DEBUG "b1lli: RESTART\n");
-		card->blocked = 0;
-		break;
-
-	case RECEIVE_STOP:
-		printk(KERN_DEBUG "b1lli: STOP\n");
-		card->blocked = 1;
-		break;
-
-	case RECEIVE_INIT:
-
-		card->versionlen = B1_get_slice(card->port, card->versionbuf);
-		card->cardstate = CARD_ACTIVE;
-		parse_version(card);
-		printk(KERN_INFO "b1lli: %s-card (%s) now active\n",
-		       card->version[VER_CARDTYPE],
-		       card->version[VER_DRIVER]);
-		avmb1_card_ready(card);
-		break;
-	default:
-		printk(KERN_ERR "b1lli: B1_handle_interrupt: 0x%x ???\n", b1cmd);
-		break;
-	}
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1pci.c linux.pre11.3/drivers/isdn/avmb1/b1pci.c
--- linux.vanilla/drivers/isdn/avmb1/b1pci.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/b1pci.c	Mon Jul 19 23:59:32 1999
@@ -1,40 +1,59 @@
 /*
- * $Id: b1pci.c,v 1.5 1998/01/31 11:14:43 calle Exp $
+ * $Id: b1pci.c,v 1.14 1999/07/09 15:05:41 keil Exp $
  * 
  * Module for AVM B1 PCI-card.
  * 
- * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1pci.c,v $
- * Revision 1.5  1998/01/31 11:14:43  calle
- * merged changes to 2.0 tree, prepare 2.1.82 to work.
+ * Revision 1.14  1999/07/09 15:05:41  keil
+ * compat.h is now isdn_compat.h
  *
- * Revision 1.4  1997/12/10 20:00:50  calle
- * get changes from 2.0 version
+ * Revision 1.13  1999/07/05 15:09:50  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
  *
- * Revision 1.3  1997/10/01 09:21:14  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
+ * Revision 1.12  1999/07/01 15:26:29  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
  *
- * Revision 1.2  1997/05/18 09:24:13  calle
- * added verbose disconnect reason reporting to avmb1.
- * some fixes in capi20 interface.
- * changed info messages for B1-PCI
- *
- * Revision 1.1  1997/03/30 17:10:42  calle
- * added support for AVM-B1-PCI card.
  *
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/pci.h>
 #include <linux/skbuff.h>
-#include "compat.h"
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
 #include <linux/capi.h>
-#include <linux/b1lli.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.14 $";
+
+/* ------------------------------------------------------------- */
 
 #ifndef PCI_VENDOR_ID_AVM
 #define PCI_VENDOR_ID_AVM	0x1244
@@ -44,65 +63,213 @@
 #define PCI_DEVICE_ID_AVM_B1	0x700
 #endif
 
-static char *revision = "$Revision: 1.5 $";
-
 /* ------------------------------------------------------------- */
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
 
 /* ------------------------------------------------------------- */
 
+static struct capi_driver_interface *di;
+
 /* ------------------------------------------------------------- */
-/* -------- Init & Cleanup ------------------------------------- */
+
+static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
 /* ------------------------------------------------------------- */
 
-/*
- * init / exit functions
- */
+static void b1pci_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	release_region(card->port, AVMB1_PORTLEN);
+	ctrl->driverdata = 0;
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static char *b1pci_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		return "";
+	sprintf(card->infobuf, "%s %s 0x%x %d",
+		card->cardname[0] ? card->cardname : "-",
+		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
+		card->port, card->irq
+		);
+	return card->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "b1pci: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	sprintf(card->name, "b1pci-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->cardtype = avm_b1pci;
+
+	if (check_region(card->port, AVMB1_PORTLEN)) {
+		printk(KERN_WARNING
+		       "b1pci: ports 0x%03x-0x%03x in use.\n",
+		       card->port, card->port + AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+	b1_reset(card->port);
+	if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
+		printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
+					card->port, retval);
+		kfree(card);
+		return -EIO;
+	}
+	b1_reset(card->port);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, b1pci_interrupt, 0, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "b1pci: attach controller failed.\n");
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver b1pci_driver = {
+    "b1pci",
+    "0.0",
+    b1_load_firmware,
+    b1_reset_ctr,
+    b1pci_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    b1_send_message,
+
+    b1pci_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0, /* no add_card function */
+};
 
 #ifdef MODULE
 #define b1pci_init init_module
+void cleanup_module(void);
 #endif
 
+static int ncards = 0;
+
 int b1pci_init(void)
 {
-	char *p;
-	char rev[10];
-	int rc;
+	struct capi_driver *driver = &b1pci_driver;
 	struct pci_dev *dev = NULL;
+	char *p;
+	int retval;
 
 	if ((p = strchr(revision, ':'))) {
-		strcpy(rev, p + 1);
-		p = strchr(rev, '$');
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
 		*p = 0;
-	} else
-		strcpy(rev, " ??? ");
+	}
+
+	printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+        di = attach_capi_driver(driver);
 
+	if (!di) {
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driver->name);
+		return -EIO;
+	}
 
 #ifdef CONFIG_PCI
 	if (!pci_present()) {
-		printk(KERN_ERR "b1pci: no PCI bus present\n");
+		printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
+    		detach_capi_driver(driver);
 		return -EIO;
 	}
 
-	printk(KERN_INFO "b1pci: revision %s\n", rev);
-
 	while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) {
-		unsigned int ioaddr = dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
-		unsigned int irq = dev->irq;
+		struct capicardparams param;
+
+		param.port = dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+		param.irq = dev->irq;
 		printk(KERN_INFO
-			"b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
-			ioaddr, irq);
-		if ((rc = avmb1_probecard(ioaddr, irq, AVM_CARDTYPE_B1)) != 0) {
+			"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
+			driver->name, param.port, param.irq);
+		retval = b1pci_add_card(driver, &param);
+		if (retval != 0) {
 		        printk(KERN_ERR
-			"b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
-			ioaddr, irq);
-			return rc;
+			"%s: no AVM-B1 at i/o %#x, irq %d detected\n",
+			driver->name, param.port, param.irq);
+#ifdef MODULE
+			cleanup_module();
+#endif
+			return retval;
 		}
-		if ((rc = avmb1_addcard(ioaddr, irq, AVM_CARDTYPE_B1)) < 0)
-			return rc;
+		ncards++;
 	}
-	return 0;
+	if (ncards) {
+		printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n",
+				driver->name, ncards);
+		return 0;
+	}
+	printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name);
+	return -ESRCH;
 #else
 	printk(KERN_ERR "b1pci: kernel not compiled with PCI.\n");
 	return -EIO;
@@ -112,5 +279,6 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
+    detach_capi_driver(&b1pci_driver);
 }
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/b1pcmcia.c linux.pre11.3/drivers/isdn/avmb1/b1pcmcia.c
--- linux.vanilla/drivers/isdn/avmb1/b1pcmcia.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/b1pcmcia.c	Mon Jul 19 23:59:32 1999
@@ -0,0 +1,267 @@
+/*
+ * $Id: b1pcmcia.c,v 1.3 1999/07/09 15:05:41 keil Exp $
+ * 
+ * Module for AVM B1/M1/M2 PCMCIA-card.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: b1pcmcia.c,v $
+ * Revision 1.3  1999/07/09 15:05:41  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.2  1999/07/05 15:09:51  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:30  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <linux/capi.h>
+#include <linux/b1pcmcia.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.3 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	b1_reset(port);
+	b1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	/* io addrsses managent by CardServices 
+	 * release_region(card->port, AVMB1_PORTLEN);
+	 */
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1pcmcia_add_card(struct capi_driver *driver,
+				unsigned int port,
+				unsigned irq,
+				enum avmcardtype cardtype)
+{
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "b1pcmcia: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	switch (cardtype) {
+		case avm_m1: sprintf(card->name, "m1-%x", port); break;
+		case avm_m2: sprintf(card->name, "m2-%x", port); break;
+		default: sprintf(card->name, "b1pcmcia-%x", port); break;
+	}
+	card->port = port;
+	card->irq = irq;
+	card->cardtype = cardtype;
+
+	b1_reset(card->port);
+	if ((retval = b1_detect(card->port, card->cardtype)) != 0) {
+		printk(KERN_NOTICE "b1pcmcia: NO card at 0x%x (%d)\n",
+					card->port, retval);
+		kfree(card);
+		return -EIO;
+	}
+	b1_reset(card->port);
+
+	retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "b1pcmcia: unable to get IRQ %d.\n", card->irq);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "b1pcmcia: attach controller failed.\n");
+		free_irq(card->irq, card);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+	return card->ctrl->cnr;
+}
+
+/* ------------------------------------------------------------- */
+
+static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		return "";
+	sprintf(card->infobuf, "%s %s 0x%x %d",
+		card->cardname[0] ? card->cardname : "-",
+		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
+		card->port, card->irq
+		);
+	return card->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver b1pcmcia_driver = {
+    "b1pcmcia",
+    "0.0",
+    b1_load_firmware,
+    b1_reset_ctr,
+    b1pcmcia_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    b1_send_message,
+
+    b1pcmcia_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0,
+};
+
+/* ------------------------------------------------------------- */
+
+int b1pcmcia_addcard_b1(unsigned int port, unsigned irq)
+{
+	return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_b1pcmcia);
+}
+
+int b1pcmcia_addcard_m1(unsigned int port, unsigned irq)
+{
+	return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m1);
+}
+
+int b1pcmcia_addcard_m2(unsigned int port, unsigned irq)
+{
+	return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m2);
+}
+
+int b1pcmcia_delcard(unsigned int port, unsigned irq)
+{
+	struct capi_ctr *ctrl;
+	avmcard *card;
+
+	for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) {
+		card = (avmcard *)(ctrl->driverdata);
+		if (card->port == port && card->irq == irq) {
+			b1pcmcia_remove_ctr(ctrl);
+			return 0;
+		}
+	}
+	return -ESRCH;
+}
+
+EXPORT_SYMBOL(b1pcmcia_addcard_b1);
+EXPORT_SYMBOL(b1pcmcia_addcard_m1);
+EXPORT_SYMBOL(b1pcmcia_addcard_m2);
+EXPORT_SYMBOL(b1pcmcia_delcard);
+
+/* ------------------------------------------------------------- */
+
+#ifdef MODULE
+#define b1pcmcia_init init_module
+void cleanup_module(void);
+#endif
+
+int b1pcmcia_init(void)
+{
+	struct capi_driver *driver = &b1pcmcia_driver;
+	char *p;
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
+		*p = 0;
+	}
+
+	printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+        di = attach_capi_driver(driver);
+
+	if (!di) {
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driver->name);
+		return -EIO;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&b1pcmcia_driver);
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capi.c linux.pre11.3/drivers/isdn/avmb1/capi.c
--- linux.vanilla/drivers/isdn/avmb1/capi.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/capi.c	Mon Jul 19 23:59:32 1999
@@ -1,11 +1,55 @@
 /*
- * $Id: capi.c,v 1.10 1998/02/13 07:09:13 calle Exp $
+ * $Id: capi.c,v 1.19 1999/07/09 15:05:42 keil Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capi.c,v $
+ * Revision 1.19  1999/07/09 15:05:42  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.18  1999/07/06 07:42:01  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.17  1999/07/01 15:26:30  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.16  1999/07/01 08:22:57  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.15  1999/06/21 15:24:11  calle
+ * extend information in /proc.
+ *
+ * Revision 1.14  1999/06/10 16:51:03  calle
+ * Bugfix: open/release of control device was not handled correct.
+ *
+ * Revision 1.13  1998/08/28 04:32:25  calle
+ * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1
+ * driver running with 2.1.118.
+ *
+ * Revision 1.12  1998/05/26 22:39:34  he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.11  1998/03/09 17:46:37  he
+ * merged in 2.1.89 changes
+ *
  * Revision 1.10  1998/02/13 07:09:13  calle
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -68,11 +112,12 @@
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/skbuff.h>
+#include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidev.h"
@@ -166,7 +211,10 @@
 	}
 	copied = skb->len;
 
-
+	if (CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+	    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND)
+		cdev->nrecvdatapkt++;
+        else cdev->nrecvctlpkt++;
 	kfree_skb(skb);
 
 	return copied;
@@ -195,7 +243,7 @@
 	skb = alloc_skb(count, GFP_USER);
 
 	if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return retval;
 	}
 	cmd = CAPIMSG_COMMAND(skb->data);
@@ -204,11 +252,11 @@
 	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ) {
 		__u16 dlen = CAPIMSG_DATALEN(skb->data);
 		if (mlen + dlen != count) {
-			dev_kfree_skb(skb);
+			kfree_skb(skb);
 			return -EINVAL;
 		}
 	} else if (mlen != count) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return -EINVAL;
 	}
 	CAPIMSG_SETAPPID(skb->data, cdev->applid);
@@ -216,9 +264,12 @@
 	cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb);
 
 	if (cdev->errcode) {
-		dev_kfree_skb(skb);
+		kfree_skb(skb);
 		return -EIO;
 	}
+	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_REQ)
+		cdev->nsentdatapkt++;
+	else cdev->nsentctlpkt++;
 	return count;
 }
 
@@ -237,6 +288,9 @@
 		return POLLERR;
 
 	cdev = &capidevs[minor];
+#if (LINUX_VERSION_CODE < 0x020159) /* 2.1.89 */
+#define poll_wait(f,wq,w) poll_wait((wq),(w))
+#endif
 	poll_wait(file, &(cdev->recv_wait), wait);
 	mask = POLLOUT | POLLWRNORM;
 	if (!skb_queue_empty(&cdev->recv_queue))
@@ -411,16 +465,13 @@
 		capidevs[minor].is_open = 1;
 		skb_queue_head_init(&capidevs[minor].recv_queue);
 		MOD_INC_USE_COUNT;
+		capidevs[minor].nopen++;
 
 	} else {
-
-		if (!capidevs[minor].is_open) {
-			capidevs[minor].is_open = 1;
-			MOD_INC_USE_COUNT;
-		}
+		capidevs[minor].is_open++;
+		MOD_INC_USE_COUNT;
 	}
 
-
 	return 0;
 }
 
@@ -445,10 +496,13 @@
 		cdev->is_registered = 0;
 		cdev->applid = 0;
 
-		while ((skb = skb_dequeue(&cdev->recv_queue)) != 0)
+		while ((skb = skb_dequeue(&cdev->recv_queue)) != 0) {
 			kfree_skb(skb);
+		}
+		cdev->is_open = 0;
+	} else {
+		cdev->is_open--;
 	}
-	cdev->is_open = 0;
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -464,13 +518,90 @@
 	capi_ioctl,
 	NULL,			/* capi_mmap */
 	capi_open,
-	NULL,			/* flush */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118)
+        NULL,                   /* capi_flush */
+#endif
 	capi_release,
 	NULL,			/* capi_fsync */
 	NULL,			/* capi_fasync */
 };
 
+/* -------- /proc functions ----------------------------------- */
 
+/*
+ * /proc/capi/capi20:
+ *  minor opencount nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
+ */
+static int proc_capidev_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+        struct capidev *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXMINOR; i++) {
+		cp = &capidevs[i+1];
+		if (cp->nopen == 0) continue;
+		len += sprintf(page+len, "%d %lu %lu %lu %lu %lu\n",
+			i+1,
+			cp->nopen,
+			cp->nrecvctlpkt,
+			cp->nrecvdatapkt,
+			cp->nsentctlpkt,
+			cp->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXMINOR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   /* { "capi",		  S_IFDIR, 0 }, */
+   { "capi/capi20", 	  0	 , proc_capidev_read_proc },
+};
+
+static void proc_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
 /* -------- init function and module interface ---------------------- */
 
 #ifdef MODULE
@@ -484,7 +615,16 @@
 
 int capi_init(void)
 {
+#ifdef COMPAT_HAS_NEW_WAITQ
+	int j;
+#endif
+	
 	memset(capidevs, 0, sizeof(capidevs));
+#ifdef COMPAT_HAS_NEW_WAITQ
+	for ( j = 0; j < CAPI_MAXMINOR+1; j++ ) {
+		init_waitqueue_head(&capidevs[j].recv_wait);
+	}
+#endif
 
 	if (register_chrdev(capi_major, "capi20", &capi_fops)) {
 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
@@ -496,12 +636,14 @@
 		unregister_chrdev(capi_major, "capi20");
 		return -EIO;
 	}
+	(void)proc_init();
 	return 0;
 }
 
 #ifdef MODULE
 void cleanup_module(void)
 {
+	(void)proc_exit();
 	unregister_chrdev(capi_major, "capi20");
 	(void) detach_capi_interface(&cuser);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidev.h linux.pre11.3/drivers/isdn/avmb1/capidev.h
--- linux.vanilla/drivers/isdn/avmb1/capidev.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/capidev.h	Mon Jul 19 23:59:32 1999
@@ -1,11 +1,33 @@
 /*
- * $Id: capidev.h,v 1.1 1997/03/04 21:50:30 calle Exp $
+ * $Id: capidev.h,v 1.4 1999/07/01 15:26:32 calle Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capidev.h,v $
+ * Revision 1.4  1999/07/01 15:26:32  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.3  1999/07/01 08:22:58  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.2  1999/06/21 15:24:13  calle
+ * extend information in /proc.
+ *
  * Revision 1.1  1997/03/04 21:50:30  calle
  * Frirst version in isdn4linux
  *
@@ -22,8 +44,18 @@
 	int is_registered;
 	__u16 applid;
 	struct sk_buff_head recv_queue;
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t recv_wait;
+#else
 	struct wait_queue *recv_wait;
+#endif
 	__u16 errcode;
+	/* Statistic */
+	unsigned long nopen;
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
 };
 
 #define CAPI_MAXMINOR	CAPI_MAXAPPL
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidrv.c linux.pre11.3/drivers/isdn/avmb1/capidrv.c
--- linux.vanilla/drivers/isdn/avmb1/capidrv.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/capidrv.c	Mon Jul 19 23:59:32 1999
@@ -1,11 +1,83 @@
 /*
- * $Id: capidrv.c,v 1.11 1998/02/13 07:09:15 calle Exp $
+ * $Id: capidrv.c,v 1.23 1999/07/09 15:05:44 keil Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capidrv.c,v $
+ * Revision 1.23  1999/07/09 15:05:44  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.22  1999/07/06 07:24:14  calle
+ * Bugfix: call to kfree_skb in capidrv_signal was too early,
+ *         thanks to Lars Heete <hel@admin.de>.
+ *
+ * Revision 1.21  1999/07/01 15:26:34  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.20  1999/07/01 08:22:59  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
+ * Revision 1.19  1999/06/29 16:16:54  calle
+ * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
+ * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
+ * isdnlog should check returncode of read(2) calls.
+ *
+ * Revision 1.18  1999/06/21 15:24:15  calle
+ * extend information in /proc.
+ *
+ * Revision 1.17  1999/06/10 16:53:55  calle
+ * Removing of module b1pci will now remove card from lower level.
+ *
+ * Revision 1.16  1999/05/31 11:50:33  calle
+ * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed
+ *         on failure, result in data block with DATA_B3 header transmitted
+ *
+ * Revision 1.15  1999/05/25 21:26:16  calle
+ * Include CAPI-Channelallocation (leased lines) from the 2.0 tree.
+ *
+ * Revision 1.14  1999/05/22 07:55:06  calle
+ * Added *V110* to AVM B1 driver.
+ *
+ * Revision 1.13  1998/06/26 15:12:55  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.12  1998/03/29 16:06:03  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.3.2.10  1998/03/20 14:38:24  calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
+ * Revision 1.3.2.9  1998/03/20 09:01:12  calle
+ * Changes capi_register handling to get full support for 30 bchannels.
+ *
+ * Revision 1.3.2.8  1998/03/18 17:51:28  calle
+ * added controller number to error messages
+ *
+ * Revision 1.3.2.7  1998/02/27 15:40:47  calle
+ * T1 running with slow link. bugfix in capi_release.
+ *
  * Revision 1.11  1998/02/13 07:09:15  calle
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -71,15 +143,18 @@
 #include <linux/skbuff.h>
 #include <linux/isdn.h>
 #include <linux/isdnif.h>
+#include <linux/proc_fs.h>
 #include <linux/capi.h>
 #include <linux/kernelcapi.h>
+#include <linux/ctype.h>
+#include <asm/segment.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 #include "capicmd.h"
 #include "capidrv.h"
 
-static char *revision = "$Revision: 1.11 $";
+static char *revision = "$Revision: 1.23 $";
 int debugmode = 0;
 
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
@@ -135,6 +210,7 @@
 			__u16 msgid;	/* to identfy CONNECT_CONF */
 			int chan;
 			int state;
+			int leasedline;
 			struct capidrv_ncci {
 				struct capidrv_ncci *next;
 				struct capidrv_plci *plcip;
@@ -169,6 +245,12 @@
 	__u16 appid;
 	int ncontr;
 	struct capidrv_contr *contr_list;
+
+        /* statistic */
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
 };
 
 typedef struct capidrv_plci capidrv_plci;
@@ -199,6 +281,10 @@
 		return 0;
 	case ISDN_PROTO_L2_TRANS:
 		return 1;
+        case ISDN_PROTO_L2_V11096:
+        case ISDN_PROTO_L2_V11019:
+        case ISDN_PROTO_L2_V11038:
+		return 2;
 	}
 }
 
@@ -212,6 +298,9 @@
 		return 0;
 	case ISDN_PROTO_L2_HDLC:
 	case ISDN_PROTO_L2_TRANS:
+        case ISDN_PROTO_L2_V11096:
+        case ISDN_PROTO_L2_V11019:
+        case ISDN_PROTO_L2_V11038:
 		return 1;
 	}
 }
@@ -224,8 +313,43 @@
 	case ISDN_PROTO_L2_X75BUI:
 	case ISDN_PROTO_L2_HDLC:
 	case ISDN_PROTO_L2_TRANS:
+        case ISDN_PROTO_L2_V11096:
+        case ISDN_PROTO_L2_V11019:
+        case ISDN_PROTO_L2_V11038:
+	default:
+		return 0;
+	}
+}
+
+static _cstruct b1config_sync_v110(__u16 rate)
+{
+	/* CAPI-Spec "B1 Configuration" */
+	static unsigned char buf[9];
+	buf[0] = 8; /* len */
+	/* maximum bitrate */
+	buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
+	buf[3] = buf[4] = 0; /* reserved, bits per character */
+	buf[5] = buf[6] = 0; /* reserved, parity */
+	buf[7] = buf[9] = 0; /* reserved, stop bits */
+	return buf;
+}
+
+static _cstruct b1config(int l2, int l3)
+{
+	switch (l2) {
+	case ISDN_PROTO_L2_X75I:
+	case ISDN_PROTO_L2_X75UI:
+	case ISDN_PROTO_L2_X75BUI:
+	case ISDN_PROTO_L2_HDLC:
+	case ISDN_PROTO_L2_TRANS:
 	default:
 		return 0;
+        case ISDN_PROTO_L2_V11096:
+	    return b1config_sync_v110(9600);
+        case ISDN_PROTO_L2_V11019:
+	    return b1config_sync_v110(19200);
+        case ISDN_PROTO_L2_V11038:
+	    return b1config_sync_v110(38400);
 	}
 }
 
@@ -378,8 +502,8 @@
 			return;
 		}
 	}
-	printk(KERN_ERR "capidrv: free_plci %p (0x%x) not found, Huh?\n",
-	       plcip, plcip->plci);
+	printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
+	       card->contrnr, plcip, plcip->plci);
 }
 
 /* -------- ncci management ------------------------------------------ */
@@ -497,9 +621,10 @@
 	size_t len;
 	capi_cmsg2message(cmsg, cmsg->buf);
 	len = CAPIMSG_LEN(cmsg->buf);
-	skb = dev_alloc_skb(len);
+	skb = alloc_skb(len, GFP_ATOMIC);
 	memcpy(skb_put(skb, len), cmsg->buf, len);
 	(*capifuncs->capi_put_message) (global.appid, skb);
+	global.nsentctlpkt++;
 }
 
 /* -------- state machine -------------------------------------------- */
@@ -512,15 +637,15 @@
 
 static struct listenstatechange listentable[] =
 {
-	{ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
-	{ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
-	{ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
-    {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
-	{ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
-      {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
-	{ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
-	{ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
-	{},
+  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
+  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
+  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
+  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
+  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
+  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
+  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
+  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
+  {},
 };
 
 static void listen_change_state(capidrv_contr * card, int event)
@@ -529,15 +654,15 @@
 	while (p->event) {
 		if (card->state == p->actstate && p->event == event) {
 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: listen_change_state %d -> %d\n",
-				       card->state, p->nextstate);
+				printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
+				       card->contrnr, card->state, p->nextstate);
 			card->state = p->nextstate;
 			return;
 		}
 		p++;
 	}
-	printk(KERN_ERR "capidrv: listen_change_state state=%d event=%d ????\n",
-	       card->state, event);
+	printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
+	       card->contrnr, card->state, event);
 
 }
 
@@ -567,46 +692,57 @@
 static struct plcistatechange plcitable[] =
 {
   /* P-0 */
-	{ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
-	{ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
-	{ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
+  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0},
+  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0},
+  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0},
+  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0},
   /* P-0.1 */
-	{ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
-	{ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
-    {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
+  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0},
+  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_OUTGOING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
   /* P-1 */
-      {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-   {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-{ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-    {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
   /* P-ACT */
-      {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-   {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-	{ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0},
+  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0},
   /* P-2 */
-    {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
-    {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
-	{ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
-    {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
- {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-     {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0},
   /* P-3 */
-{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
-{ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-	{ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
- {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
   /* P-4 */
-      {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
-   {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
-{ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
-    {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0},
+  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
   /* P-5 */
-{ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
+  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0},
   /* P-6 */
-	{ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
-	{},
+  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
+  /* P-0.Res */
+  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
+  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0},
+  /* P-RES */
+  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0},
+  /* P-HELD */
+  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0},
+  {},
 };
 
 static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
@@ -615,8 +751,8 @@
 	while (p->event) {
 		if (plci->state == p->actstate && p->event == event) {
 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: plci_change_state:0x%x %d -> %d\n",
-				  plci->plci, plci->state, p->nextstate);
+				printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
+				  card->contrnr, plci->plci, plci->state, p->nextstate);
 			plci->state = p->nextstate;
 			if (p->changefunc)
 				p->changefunc(card, plci);
@@ -624,8 +760,8 @@
 		}
 		p++;
 	}
-	printk(KERN_ERR "capidrv: plci_change_state:0x%x state=%d event=%d ????\n",
-	       plci->plci, plci->state, event);
+	printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
+	       card->contrnr, plci->plci, plci->state, event);
 }
 
 /* ------------------------------------------------------------------ */
@@ -642,7 +778,7 @@
 				 ncci->plcip->plci,
 				 0,	/* BChannelinformation */
 				 0,	/* Keypadfacility */
-				 0,	/* Useruserdata */
+				 0,	/* Useruserdata */   /* $$$$ */
 				 0	/* Facilitydataarray */
 	);
 	send_message(card, &cmsg);
@@ -667,34 +803,35 @@
 static struct nccistatechange nccitable[] =
 {
   /* N-0 */
-	{ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
-	{ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
+  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0},
+  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0},
   /* N-0.1 */
-    {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
-      {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, 0},
+  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0},
+  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
   /* N-1 */
- {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
-	{ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
+  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0},
+  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0},
   {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
   /* N-2 */
-   {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
- {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-{ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0},
+  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
   /* N-ACT */
-	{ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
-    {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-   {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
   /* N-3 */
-	{ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
+  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0},
   {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
- {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
+  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0},
   /* N-4 */
-	{ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
-	{ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR, 0},
+  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0},
+  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0},
   /* N-5 */
-    {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
-	{},
+  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
+  {},
 };
 
 static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
@@ -703,8 +840,8 @@
 	while (p->event) {
 		if (ncci->state == p->actstate && p->event == event) {
 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: ncci_change_state:0x%x %d -> %d\n",
-				  ncci->ncci, ncci->state, p->nextstate);
+				printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
+				  card->contrnr, ncci->ncci, ncci->state, p->nextstate);
 			if (p->nextstate == ST_NCCI_PREVIOUS) {
 				ncci->state = ncci->oldstate;
 				ncci->oldstate = p->actstate;
@@ -718,8 +855,8 @@
 		}
 		p++;
 	}
-	printk(KERN_ERR "capidrv: ncci_change_state:0x%x state=%d event=%d ????\n",
-	       ncci->ncci, ncci->state, event);
+	printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
+	       card->contrnr, ncci->ncci, ncci->state, event);
 }
 
 /* ------------------------------------------------------------------- */
@@ -752,8 +889,8 @@
 
 	case CAPI_LISTEN_CONF:	/* Controller */
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
-			       cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
+			printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
+			       card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
 		if (cmsg->Info) {
 			listen_change_state(card, EV_LISTEN_CONF_ERROR);
 		} else if (card->cipmask == 0) {
@@ -789,7 +926,8 @@
 		      handle_dtrace_data(card, direction, 0, data, len);
 		      break;
 		   }
-	           printk(KERN_INFO "capidrv: %s from controller 0x%x layer 0x%x, ignored\n",
+	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
+                        card->contrnr, 
 			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			cmsg->adr.adrController, layer);
                    break;
@@ -805,7 +943,8 @@
 		      default: s = "unkown error"; break;
 		   }
 		   if (s)
-	           printk(KERN_INFO "capidrv: %s from controller 0x%x function %d: %s\n",
+	           printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
+			card->contrnr,
 			capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			cmsg->adr.adrController,
 			cmsg->Function, s);
@@ -822,14 +961,16 @@
 		goto ignored;
 
 	default:
-		printk(KERN_ERR "capidrv: got %s from controller 0x%x ???",
+		printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
+		       card->contrnr,
 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 		       cmsg->adr.adrController);
 	}
 	return;
 
       ignored:
-	printk(KERN_INFO "capidrv: %s from controller 0x%x ignored\n",
+	printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
+	       card->contrnr,
 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 	       cmsg->adr.adrController);
 }
@@ -842,12 +983,12 @@
 	int chan;
 
 	if ((chan = new_bchan(card)) == -1) {
-		printk(KERN_ERR "capidrv: incoming call on not existing bchan ?\n");
+		printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
 		return;
 	}
 	bchan = &card->bchans[chan];
 	if ((plcip = new_plci(card, chan)) == 0) {
-		printk(KERN_ERR "capidrv: incoming call: no memory, sorry.\n");
+		printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
 		return;
 	}
 	bchan->incoming = 1;
@@ -869,7 +1010,8 @@
 	cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
 	cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
 
-	printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s\n", 
+	printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", 
+			card->contrnr,
 			cmd.parm.setup.phone,
 			cmd.parm.setup.si1,
 			cmd.parm.setup.si2,
@@ -877,6 +1019,7 @@
 
 	switch (card->interface.statcallb(&cmd)) {
 	case 0:
+	case 3:
 		/* No device matching this call.
 		 * and isdn_common.c has send a HANGUP command
 		 * which is ignored in state ST_PLCI_INCOMING,
@@ -886,7 +1029,8 @@
 		cmsg->Reject = 1;	/* ignore */
 		send_message(card, cmsg);
 		plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
-		printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s ignored\n",
+		printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
+			card->contrnr,
 			cmd.parm.setup.phone,
 			cmd.parm.setup.si1,
 			cmd.parm.setup.si2,
@@ -903,7 +1047,8 @@
 		 * and CONNECT_RESP already sent.
 		 */
 		if (plcip->state == ST_PLCI_INCOMING) {
-			printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s tty alerting\n",
+			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
+				card->contrnr,
 				cmd.parm.setup.phone,
 				cmd.parm.setup.si1,
 				cmd.parm.setup.si2,
@@ -920,7 +1065,8 @@
 			plcip->msgid = cmsg->Messagenumber;
 			send_message(card, cmsg);
 		} else {
-			printk(KERN_INFO "capidrv: incoming call %s,%d,%d,%s on netdev\n",
+			printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
+				card->contrnr,
 				cmd.parm.setup.phone,
 				cmd.parm.setup.si1,
 				cmd.parm.setup.si2,
@@ -963,7 +1109,8 @@
 
 	case CAPI_DISCONNECT_IND:	/* plci */
 		if (cmsg->Reason) {
-			printk(KERN_INFO "capidrv: %s reason 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
 		}
@@ -981,7 +1128,8 @@
 
 	case CAPI_DISCONNECT_CONF:	/* plci */
 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->Info, capi_info2str(cmsg->Info), 
 			       cmsg->adr.adrPLCI);
@@ -994,7 +1142,8 @@
 
 	case CAPI_ALERT_CONF:	/* plci */
 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->Info, capi_info2str(cmsg->Info), 
 			       cmsg->adr.adrPLCI);
@@ -1007,7 +1156,8 @@
 
 	case CAPI_CONNECT_CONF:	/* plci */
 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for plci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->Info, capi_info2str(cmsg->Info), 
 			       cmsg->adr.adrPLCI);
@@ -1040,7 +1190,7 @@
 			nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
 
 			if (!nccip) {
-				printk(KERN_ERR "capidrv: no mem for ncci, sorry\n");
+				printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
 				break;	/* $$$$ */
 			}
 			capi_fill_CONNECT_B3_REQ(cmsg,
@@ -1080,7 +1230,8 @@
 				break;
 			}
 		}
-		printk(KERN_ERR "capidrv: %s\n", capi_cmsg2str(cmsg));
+		printk(KERN_ERR "capidrv-%d: %s\n",
+				card->contrnr, capi_cmsg2str(cmsg));
 		break;
 
 	case CAPI_CONNECT_ACTIVE_CONF:		/* plci */
@@ -1096,18 +1247,21 @@
 		goto ignored;
 
 	default:
-		printk(KERN_ERR "capidrv: got %s for plci 0x%x ???",
+		printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
+		       card->contrnr,
 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 		       cmsg->adr.adrPLCI);
 	}
 	return;
       ignored:
-	printk(KERN_INFO "capidrv: %s for plci 0x%x ignored\n",
+	printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
+	       card->contrnr,
 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 	       cmsg->adr.adrPLCI);
 	return;
       notfound:
-	printk(KERN_ERR "capidrv: %s: plci 0x%x not found\n",
+	printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
+	       card->contrnr,
 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 	       cmsg->adr.adrPLCI);
 	return;
@@ -1142,8 +1296,8 @@
 		cmd.arg = nccip->chan;
 		card->interface.statcallb(&cmd);
 
-		printk(KERN_INFO "capidrv: chan %d up with ncci 0x%x\n",
-		       nccip->chan, nccip->ncci);
+		printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
+		       card->contrnr, nccip->chan, nccip->ncci);
 		break;
 
 	case CAPI_CONNECT_B3_ACTIVE_CONF:	/* ncci */
@@ -1167,9 +1321,10 @@
 				ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
 				break;
 			}
-			printk(KERN_ERR "capidrv: no mem for ncci, sorry\n");
+			printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",							card->contrnr);
 		} else {
-			printk(KERN_ERR "capidrv: %s: plci for ncci 0x%x not found\n",
+			printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->adr.adrNCCI);
 		}
@@ -1192,7 +1347,8 @@
 
 		nccip->ncci = cmsg->adr.adrNCCI;
 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->Info, capi_info2str(cmsg->Info), 
 			       cmsg->adr.adrNCCI);
@@ -1242,7 +1398,8 @@
 		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
 			goto notfound;
 		if (cmsg->Info) {
-			printk(KERN_INFO "capidrv: %s info 0x%x (%s) for ncci 0x%x\n",
+			printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
+			   card->contrnr,
 			   capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 			       cmsg->Info, capi_info2str(cmsg->Info), 
 			       cmsg->adr.adrNCCI);
@@ -1251,6 +1408,9 @@
 		break;
 
 	case CAPI_RESET_B3_IND:	/* ncci */
+		if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
+			goto notfound;
+		ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
 		capi_cmsg_answer(cmsg);
 		send_message(card, cmsg);
 		break;
@@ -1264,18 +1424,21 @@
 		goto ignored;
 
 	default:
-		printk(KERN_ERR "capidrv: got %s for ncci 0x%x ???",
+		printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
+		       card->contrnr,
 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 		       cmsg->adr.adrNCCI);
 	}
 	return;
       ignored:
-	printk(KERN_INFO "capidrv: %s for ncci 0x%x ignored\n",
+	printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
+	       card->contrnr,
 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 	       cmsg->adr.adrNCCI);
 	return;
       notfound:
-	printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n",
+	printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
+	       card->contrnr,
 	       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 	       cmsg->adr.adrNCCI);
 }
@@ -1290,10 +1453,12 @@
 		printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 		       cmsg->adr.adrController & 0x7f);
+		kfree_skb(skb);
 		return;
 	}
 	if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
-		printk(KERN_ERR "capidrv: %s: ncci 0x%x not found\n",
+		printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
+		       card->contrnr,
 		       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 		       cmsg->adr.adrNCCI);
 		kfree_skb(skb);
@@ -1313,21 +1478,29 @@
 
 	while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) {
 		capi_message2cmsg(&s_cmsg, skb->data);
-		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv_signal: %s\n", capi_cmsg2str(&s_cmsg));
+		if (debugmode > 2)
+			printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n",
+					applid, capi_cmsg2str(&s_cmsg));
 
 		if (s_cmsg.Command == CAPI_DATA_B3
 		    && s_cmsg.Subcommand == CAPI_IND) {
 			handle_data(&s_cmsg, skb);
+			global.nrecvdatapkt++;
 			continue;
 		}
-		kfree_skb(skb);
 		if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
 			handle_controller(&s_cmsg);
 		else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
 			handle_plci(&s_cmsg);
 		else
 			handle_ncci(&s_cmsg);
+		/*
+		 * data of skb used in s_cmsg,
+		 * free data when s_cmsg is not used again
+		 * thanks to Lars Heete <hel@admin.de>
+		 */
+		kfree_skb(skb);
+		global.nrecvctlpkt++;
 	}
 }
 
@@ -1348,7 +1521,8 @@
     isdn_ctrl cmd;
 
     if (!len) {
-       printk(KERN_DEBUG "avmb1_q931_data: len == %d\n", len);
+       printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
+				card->contrnr, len);
        return;
     }
 
@@ -1392,18 +1566,116 @@
 static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
 {
 	switch (c->arg) {
+	case 1:
+		debugmode = (int)(*((unsigned int *)c->parm.num));
+		printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",
+				card->contrnr, debugmode);
+		return 0;
 	default:
-		printk(KERN_DEBUG "capidrv: capidrv_ioctl(%ld) called ??\n", c->arg);
+		printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
+				card->contrnr, c->arg);
 		return -EINVAL;
 	}
 	return -EINVAL;
 }
 
+/*
+ * Handle leased lines (CAPI-Bundling)
+ */
+
+struct internal_bchannelinfo {
+   unsigned short channelalloc;
+   unsigned short operation;
+   unsigned char  cmask[31];
+};
+
+static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
+{
+	unsigned long bmask = 0;
+	int active = !0;
+	char *s;
+	int i;
+
+	if (strncmp(teln, "FV:", 3) != 0)
+		return 1;
+	s = teln + 3;
+	while (*s && *s == ' ') s++;
+	if (!*s) return -2;
+	if (*s == 'p' || *s == 'P') {
+		active = 0;
+		s++;
+	}
+	if (*s == 'a' || *s == 'A') {
+		active = !0;
+		s++;
+	}
+	while (*s) {
+		int digit1 = 0;
+		int digit2 = 0;
+		if (!isdigit(*s)) return -3;
+		while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; }
+		if (digit1 <= 0 && digit1 > 30) return -4;
+		if (*s == 0 || *s == ',' || *s == ' ') {
+			bmask |= (1 << digit1);
+			digit1 = 0;
+			if (*s) s++;
+			continue;
+		}
+		if (*s != '-') return -5;
+		s++;
+		if (!isdigit(*s)) return -3;
+		while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; }
+		if (digit2 <= 0 && digit2 > 30) return -4;
+		if (*s == 0 || *s == ',' || *s == ' ') {
+			if (digit1 > digit2)
+				for (i = digit2; i <= digit1 ; i++)
+					bmask |= (1 << i);
+			else 
+				for (i = digit1; i <= digit2 ; i++)
+					bmask |= (1 << i);
+			digit1 = digit2 = 0;
+			if (*s) s++;
+			continue;
+		}
+		return -6;
+	}
+	if (activep) *activep = active;
+	if (bmaskp) *bmaskp = bmask;
+	return 0;
+}
+
+static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31])
+{
+	unsigned long bmask;
+	int active;
+	int rc, i;
+   
+	rc = decodeFVteln(teln, &bmask, &active);
+	if (rc) return rc;
+	/* Length */
+	AdditionalInfo[0] = 2+2+31;
+        /* Channel: 3 => use channel allocation */
+        AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
+	/* Operation: 0 => DTE mode, 1 => DCE mode */
+        if (active) {
+   		AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
+   	} else {
+   		AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
+	}
+	/* Channel mask array */
+	AdditionalInfo[5] = 0; /* no D-Channel */
+	for (i=1; i <= 30; i++)
+		AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
+	return 0;
+}
+
 static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
 {
 	isdn_ctrl cmd;
 	struct capidrv_bchan *bchan;
 	struct capidrv_plci *plcip;
+	__u8 AdditionalInfo[1+2+2+31];
+        int rc, isleasedline = 0;
 
 	if (c->command == ISDN_CMD_IOCTL)
 		return capidrv_ioctl(c, card);
@@ -1414,7 +1686,8 @@
 			__u8 called[ISDN_MSNLEN + 2];
 
 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
+				printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
+					card->contrnr,
 					c->arg,
 				        c->parm.setup.phone,
 				        c->parm.setup.si1,
@@ -1424,7 +1697,8 @@
 			bchan = &card->bchans[c->arg % card->nbchan];
 
 			if (bchan->plcip) {
-				printk(KERN_ERR "capidrv: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
+				printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
+					card->contrnr,
 			        	c->arg, 
 				        c->parm.setup.phone,
 				        c->parm.setup.si1,
@@ -1438,15 +1712,25 @@
 
 			strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
 			strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
-
-			calling[0] = strlen(bchan->mynum) + 2;
-			calling[1] = 0;
-			calling[2] = 0x80;
-			strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
-
-			called[0] = strlen(bchan->num) + 1;
-			called[1] = 0x80;
-			strncpy(called + 2, bchan->num, ISDN_MSNLEN);
+                        rc = FVteln2capi20(bchan->num, AdditionalInfo);
+			isleasedline = (rc == 0);
+			if (rc < 0)
+				printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
+
+			if (isleasedline) {
+				calling[0] = 0;
+				called[0] = 0;
+			        if (debugmode)
+					printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
+			} else {
+		        	calling[0] = strlen(bchan->mynum) + 2;
+		        	calling[1] = 0;
+		     		calling[2] = 0x80;
+			   	strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
+				called[0] = strlen(bchan->num) + 1;
+				called[1] = 0x80;
+				strncpy(called + 2, bchan->num, ISDN_MSNLEN);
+			}
 
 			capi_fill_CONNECT_REQ(&cmdcmsg,
 					      global.appid,
@@ -1460,13 +1744,14 @@
 					    b1prot(bchan->l2, bchan->l3),	/* B1protocol */
 					    b2prot(bchan->l2, bchan->l3),	/* B2protocol */
 					    b3prot(bchan->l2, bchan->l3),	/* B3protocol */
-					      0,	/* B1configuration */
+					    b1config(bchan->l2, bchan->l3),	/* B1configuration */
 					      0,	/* B2configuration */
 					      0,	/* B3configuration */
 					      0,	/* BC */
 					      0,	/* LLC */
 					      0,	/* HLC */
-					      0,	/* BChannelinformation */
+					      /* BChannelinformation */
+					      isleasedline ? AdditionalInfo : 0,
 					      0,	/* Keypadfacility */
 					      0,	/* Useruserdata */
 					      0		/* Facilitydataarray */
@@ -1479,6 +1764,7 @@
 				return -1;
 			}
 			plcip->msgid = cmdcmsg.Messagenumber;
+			plcip->leasedline = isleasedline;
 			plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
 			send_message(card, &cmdcmsg);
 			return 0;
@@ -1486,10 +1772,11 @@
 
 	case ISDN_CMD_ACCEPTD:
 
-		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTD(ch=%ld)\n",
-			       c->arg);
 		bchan = &card->bchans[c->arg % card->nbchan];
+		if (debugmode)
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
+			       card->contrnr,
+			       c->arg, bchan->l2, bchan->l3);
 
 		capi_fill_CONNECT_RESP(&cmdcmsg,
 				       global.appid,
@@ -1499,7 +1786,7 @@
 				       b1prot(bchan->l2, bchan->l3),	/* B1protocol */
 				       b2prot(bchan->l2, bchan->l3),	/* B2protocol */
 				       b3prot(bchan->l2, bchan->l3),	/* B3protocol */
-				       0,	/* B1configuration */
+				       b1config(bchan->l2, bchan->l3),	/* B1configuration */
 				       0,	/* B2configuration */
 				       0,	/* B3configuration */
 				       0,	/* ConnectedNumber */
@@ -1517,19 +1804,22 @@
 
 	case ISDN_CMD_ACCEPTB:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_ACCEPTB(ch=%ld)\n",
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
+			       card->contrnr,
 			       c->arg);
 		return -ENOSYS;
 
 	case ISDN_CMD_HANGUP:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_HANGUP(ch=%ld)\n",
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
+			       card->contrnr,
 			       c->arg);
 		bchan = &card->bchans[c->arg % card->nbchan];
 
 		if (bchan->disconnecting) {
 			if (debugmode)
-				printk(KERN_DEBUG "capidrv: chan %ld already disconnecting ...\n",
+				printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
+				       card->contrnr,
 				       c->arg);
 			return 0;
 		}
@@ -1568,23 +1858,26 @@
 
 	case ISDN_CMD_SETL2:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: set L2 on chan %ld to %ld\n",
+			printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
+			       card->contrnr,
 			       (c->arg & 0xff), (c->arg >> 8));
-		bchan = &card->bchans[c->arg % card->nbchan];
+		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
 		bchan->l2 = (c->arg >> 8);
 		return 0;
 
 	case ISDN_CMD_SETL3:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: set L3 on chan %ld to %ld\n",
+			printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
+			       card->contrnr,
 			       (c->arg & 0xff), (c->arg >> 8));
-		bchan = &card->bchans[c->arg % card->nbchan];
+		bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
 		bchan->l3 = (c->arg >> 8);
 		return 0;
 
 	case ISDN_CMD_SETEAZ:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: set EAZ \"%s\" on chan %ld\n",
+			printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
+			       card->contrnr,
 			       c->parm.num, c->arg);
 		bchan = &card->bchans[c->arg % card->nbchan];
 		strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
@@ -1592,46 +1885,54 @@
 
 	case ISDN_CMD_CLREAZ:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: clearing EAZ on chan %ld\n", c->arg);
+			printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
+					card->contrnr, c->arg);
 		bchan = &card->bchans[c->arg % card->nbchan];
 		bchan->msn[0] = 0;
 		return 0;
 
 	case ISDN_CMD_LOCK:
 		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_LOCK (%ld)\n", c->arg);
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg);
 		MOD_INC_USE_COUNT;
 		break;
 
 	case ISDN_CMD_UNLOCK:
 		if (debugmode > 1)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_UNLOCK (%ld)\n", c->arg);
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n",
+					card->contrnr, c->arg);
 		MOD_DEC_USE_COUNT;
 		break;
 
 /* never called */
 	case ISDN_CMD_GETL2:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL2\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n",
+					card->contrnr);
 		return -ENODEV;
 	case ISDN_CMD_GETL3:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETL3\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n",
+					card->contrnr);
 		return -ENODEV;
 	case ISDN_CMD_GETEAZ:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETEAZ\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n",
+					card->contrnr);
 		return -ENODEV;
 	case ISDN_CMD_SETSIL:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_SETSIL\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n",
+					card->contrnr);
 		return -ENODEV;
 	case ISDN_CMD_GETSIL:
 		if (debugmode)
-			printk(KERN_DEBUG "capidrv: ISDN_CMD_GETSIL\n");
+			printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n",
+					card->contrnr);
 		return -ENODEV;
 	default:
-		printk(KERN_ERR "capidrv: ISDN_CMD_%d, Huh?\n", c->command);
+		printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
+					card->contrnr, c->command);
 		return -EINVAL;
 	}
 	return 0;
@@ -1645,8 +1946,8 @@
 		return capidrv_command(c, card);
 
 	printk(KERN_ERR
-	     "capidrv: if_command %d called with invalid driverId %d!\n",
-	       c->command, c->driver);
+	     "capidrv-%d: if_command %d called with invalid driverId %d!\n",
+	       card->contrnr, c->command, c->driver);
 	return -ENODEV;
 }
 
@@ -1663,15 +1964,18 @@
 	__u16 datahandle;
 
 	if (!card) {
-		printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
-		       id);
+		printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
+		       card->contrnr, id);
 		return 0;
 	}
+	if (debugmode > 1)
+		printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
+					card->contrnr, len, skb, doack);
 	bchan = &card->bchans[channel % card->nbchan];
 	nccip = bchan->nccip;
 	if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
-		printk(KERN_ERR "capidrv: if_sendbuf: %s:%d: chan not up!\n",
-		       card->name, channel);
+		printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
+		       card->contrnr, card->name, channel);
 		return 0;
 	}
 	datahandle = nccip->datahandle;
@@ -1689,22 +1993,23 @@
 	capi_cmsg2message(&sendcmsg, sendcmsg.buf);
 	msglen = CAPIMSG_LEN(sendcmsg.buf);
 	if (skb_headroom(skb) < msglen) {
-		struct sk_buff *nskb = dev_alloc_skb(msglen + skb->len);
+		struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);
 		if (!nskb) {
-			printk(KERN_ERR "capidrv: if_sendbuf: no memory\n");
+			printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
+				card->contrnr);
 		        (void)capidrv_del_ack(nccip, datahandle);
 			return 0;
 		}
-#if 0
-		printk(KERN_DEBUG "capidrv: only %d bytes headroom\n",
-		       skb_headroom(skb));
+#if 1
+		printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
+		       card->contrnr, skb_headroom(skb), msglen);
 #endif
-		memcpy(skb_put(nskb, msglen), sendcmsg.buf, msglen);
-		memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
+		memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
 		errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
 		if (errcode == CAPI_NOERROR) {
 			dev_kfree_skb(skb);
 			nccip->datahandle++;
+			global.nsentdatapkt++;
 			return len;
 		}
 	        (void)capidrv_del_ack(nccip, datahandle);
@@ -1715,8 +2020,10 @@
 		errcode = (*capifuncs->capi_put_message) (global.appid, skb);
 		if (errcode == CAPI_NOERROR) {
 			nccip->datahandle++;
+			global.nsentdatapkt++;
 			return len;
 		}
+		skb_pull(skb, msglen);
 	        (void)capidrv_del_ack(nccip, datahandle);
 		return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
 	}
@@ -1729,8 +2036,8 @@
 	__u8 *p;
 
 	if (!card) {
-		printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
-		       id);
+		printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",
+		       card->contrnr, id);
 		return -ENODEV;
 	}
 
@@ -1761,8 +2068,8 @@
 	   return;
 	}
 	if (strstr(manufacturer, "AVM") == 0) {
-	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible\n",
-			card->name);
+	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
+			card->name, manufacturer);
 	   return;
 	}
         errcode = (*capifuncs->capi_get_version)(contr, &version);
@@ -1776,7 +2083,7 @@
 	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
 	avmversion[2] |= version.minormanuversion & 0x0f;
 
-        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
+        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) {
 		printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
 		capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
 					   card->msgid++,
@@ -1798,6 +2105,51 @@
 	send_message(card, &cmdcmsg);
 }
 
+static void disable_dchannel_trace(capidrv_contr *card)
+{
+        __u8 manufacturer[CAPI_MANUFACTURER_LEN];
+        capi_version version;
+	__u16 contr = card->contrnr;
+	__u16 errcode;
+	__u16 avmversion[3];
+
+        errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);
+        if (errcode != CAPI_NOERROR) {
+	   printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
+			card->name, errcode);
+	   return;
+	}
+	if (strstr(manufacturer, "AVM") == 0) {
+	   printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
+			card->name, manufacturer);
+	   return;
+	}
+        errcode = (*capifuncs->capi_get_version)(contr, &version);
+        if (errcode != CAPI_NOERROR) {
+	   printk(KERN_ERR "%s: can't get version (0x%x)\n",
+			card->name, errcode);
+	   return;
+	}
+	avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
+	avmversion[1] = (version.majormanuversion << 4) & 0xf0;
+	avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
+	avmversion[2] |= version.minormanuversion & 0x0f;
+
+        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 6)) {
+		printk(KERN_INFO "%s: D2 trace disabled\n", card->name);
+	} else {
+		printk(KERN_INFO "%s: D3 trace disabled\n", card->name);
+	}
+	capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
+				   card->msgid++,
+				   contr,
+				   0x214D5641,  /* ManuID */
+				   0,           /* Class */
+				   1,           /* Function */
+				   (_cstruct)"\004\000\000\000\000");
+	send_message(card, &cmdcmsg);
+}
+
 static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
 {
 	capidrv_contr *card;
@@ -1834,6 +2186,9 @@
 	    ISDN_FEATURE_L2_HDLC |
 	    ISDN_FEATURE_L2_TRANS |
 	    ISDN_FEATURE_L3_TRANS |
+	    ISDN_FEATURE_L2_V11096 |
+	    ISDN_FEATURE_L2_V11019 |
+	    ISDN_FEATURE_L2_V11038 |
 	    ISDN_FEATURE_P_UNKNOWN;
 	card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
 	strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
@@ -1878,7 +2233,7 @@
 	printk(KERN_INFO "%s: now up (%d B channels)\n",
 		card->name, card->nbchan);
 
-        enable_dchannel_trace(card);
+	enable_dchannel_trace(card);
 
 	return 0;
 }
@@ -1898,6 +2253,15 @@
 		return -1;
 	}
 	card = *pp;
+
+	if (debugmode)
+		printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
+					card->contrnr, card->myid);
+
+	cmd.command = ISDN_STAT_UNLOAD;
+	cmd.driver = card->myid;
+	card->interface.statcallb(&cmd);
+
 	*pp = (*pp)->next;
 	global.ncontr--;
 
@@ -1911,10 +2275,6 @@
 	}
 	kfree(card->bchans);
 
-	cmd.command = ISDN_STAT_UNLOAD;
-	cmd.driver = card->myid;
-	card->interface.statcallb(&cmd);
-
 	printk(KERN_INFO "%s: now down.\n", card->name);
 
 	kfree(card);
@@ -1925,16 +2285,77 @@
 
 static void lower_callback(unsigned int cmd, __u16 contr, void *data)
 {
+
 	switch (cmd) {
 	case KCI_CONTRUP:
+		printk(KERN_INFO "capidrv: controller %hu up\n", contr);
 		(void) capidrv_addcontr(contr, (capi_profile *) data);
 		break;
 	case KCI_CONTRDOWN:
+		printk(KERN_INFO "capidrv: controller %hu down\n", contr);
 		(void) capidrv_delcontr(contr);
 		break;
 	}
 }
 
+/*
+ * /proc/capi/capidrv:
+ * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
+ */
+static int proc_capidrv_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	int len = 0;
+
+	len += sprintf(page+len, "%lu %lu %lu %lu\n",
+			global.nrecvctlpkt,
+			global.nrecvdatapkt,
+			global.nsentctlpkt,
+			global.nsentdatapkt);
+	if (len < off) 
+           return 0;
+	*eof = 1;
+	*start = page -off;
+	return ((count < len-off) ? count : len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   /* { "capi",		  S_IFDIR, 0 }, */
+   { "capi/capidrv", 	  0	 , proc_capidrv_read_proc },
+};
+
+static void proc_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
+
 static struct capi_interface_user cuser = {
 	"capidrv",
 	lower_callback
@@ -1965,8 +2386,8 @@
 	} else
 		strcpy(rev, " ??? ");
 
-	rparam.level3cnt = 2;
-	rparam.datablkcnt = 8;
+	rparam.level3cnt = -2;  /* number of bchannels twice */
+	rparam.datablkcnt = 16;
 	rparam.datablklen = 2048;
 	errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
 	if (errcode) {
@@ -1990,6 +2411,7 @@
 			continue;
 		(void) capidrv_addcontr(contr, &profile);
 	}
+	proc_init();
 
 	return 0;
 }
@@ -2011,11 +2433,13 @@
 
 	for (card = global.contr_list; card; card = next) {
 		next = card->next;
+		disable_dchannel_trace(card);
 		capidrv_delcontr(card->contrnr);
 	}
 
 	(void) (*capifuncs->capi_release) (global.appid);
 	detach_capi_interface(&cuser);
+	proc_exit();
 
 	printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capidrv.h linux.pre11.3/drivers/isdn/avmb1/capidrv.h
--- linux.vanilla/drivers/isdn/avmb1/capidrv.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/capidrv.h	Mon Jul 19 23:59:32 1999
@@ -1,11 +1,22 @@
 /*
- * $Id: capidrv.h,v 1.1 1997/03/04 21:50:33 calle Exp $
+ * $Id: capidrv.h,v 1.2 1998/03/29 16:06:06 calle Exp $
  *
  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
  *
  * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capidrv.h,v $
+ * Revision 1.2  1998/03/29 16:06:06  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.1  1998/03/20 14:38:28  calle
+ * capidrv: prepared state machines for suspend/resume/hold
+ * capidrv: fix bug in state machine if B1/T1 is out of nccis
+ * b1capi: changed some errno returns.
+ * b1capi: detect if you try to add same T1 to different io address.
+ * b1capi: change number of nccis depending on number of channels.
+ * b1lli: cosmetics
+ *
  * Revision 1.1  1997/03/04 21:50:33  calle
  * Frirst version in isdn4linux
  *
@@ -49,34 +60,70 @@
 #define ST_PLCI_ACCEPTING		6	/* P-4 */
 #define ST_PLCI_DISCONNECTING		7	/* P-5 */
 #define ST_PLCI_DISCONNECTED		8	/* P-6 */
+#define ST_PLCI_RESUMEING		9	/* P-0.Res */
+#define ST_PLCI_RESUME			10	/* P-Res */
+#define ST_PLCI_HELD			11	/* P-HELD */
 
-#define EV_PLCI_CONNECT_REQ		1	/* P-0 -> P-0.1 */
-#define EV_PLCI_CONNECT_CONF_ERROR	2	/* P-0.1 -> P-0 */
-#define EV_PLCI_CONNECT_CONF_OK		3	/* P-0.1 -> P-1 */
-#define EV_PLCI_FACILITY_IND_UP		4	/* P-0 -> P-1 */
-#define EV_PLCI_CONNECT_IND		5	/* P-0 -> P-2 */
-#define EV_PLCI_CONNECT_ACTIVE_IND	6	/* P-1 -> P-ACT */
+#define EV_PLCI_CONNECT_REQ		1	/* P-0 -> P-0.1
+                                                 */
+#define EV_PLCI_CONNECT_CONF_ERROR	2	/* P-0.1 -> P-0
+                                                 */
+#define EV_PLCI_CONNECT_CONF_OK		3	/* P-0.1 -> P-1
+                                                 */
+#define EV_PLCI_FACILITY_IND_UP		4	/* P-0 -> P-1
+                                                 */
+#define EV_PLCI_CONNECT_IND		5	/* P-0 -> P-2
+                                                 */
+#define EV_PLCI_CONNECT_ACTIVE_IND	6	/* P-1 -> P-ACT
+                                                 */
 #define EV_PLCI_CONNECT_REJECT		7	/* P-2 -> P-5
-						   P-3 -> P-5 */
+						   P-3 -> P-5
+						 */
 #define EV_PLCI_DISCONNECT_REQ		8	/* P-1 -> P-5
 						   P-2 -> P-5
 						   P-3 -> P-5
 						   P-4 -> P-5
-						   P-ACT -> P-5 */
+						   P-ACT -> P-5
+						   P-Res -> P-5 (*)
+						   P-HELD -> P-5 (*)
+						   */
 #define EV_PLCI_DISCONNECT_IND		9	/* P-1 -> P-6
 						   P-2 -> P-6
 						   P-3 -> P-6
 						   P-4 -> P-6
 						   P-5 -> P-6
-						   P-ACT -> P-6 */
+						   P-ACT -> P-6
+						   P-Res -> P-6 (*)
+						   P-HELD -> P-6 (*)
+						   */
 #define EV_PLCI_FACILITY_IND_DOWN	10	/* P-0.1 -> P-5
 						   P-1 -> P-5
 						   P-ACT -> P-5
 						   P-2 -> P-5
 						   P-3 -> P-5
-						   P-4 -> P-5 */
-#define EV_PLCI_DISCONNECT_RESP		11	/* P-6 -> P-0 */
-#define EV_PLCI_CONNECT_RESP		12	/* P-6 -> P-0 */
+						   P-4 -> P-5
+						   */
+#define EV_PLCI_DISCONNECT_RESP		11	/* P-6 -> P-0
+                                                   */
+#define EV_PLCI_CONNECT_RESP		12	/* P-6 -> P-0
+                                                   */
+
+#define EV_PLCI_RESUME_REQ		13	/* P-0 -> P-0.Res
+                                                 */
+#define EV_PLCI_RESUME_CONF_OK		14	/* P-0.Res -> P-Res
+                                                 */
+#define EV_PLCI_RESUME_CONF_ERROR	15	/* P-0.Res -> P-0
+                                                 */
+#define EV_PLCI_RESUME_IND		16	/* P-Res -> P-ACT
+                                                 */
+#define EV_PLCI_HOLD_IND		17	/* P-ACT -> P-HELD
+                                                 */
+#define EV_PLCI_RETRIEVE_IND		18	/* P-HELD -> P-ACT
+                                                 */
+#define EV_PLCI_SUSPEND_IND		19	/* P-ACT -> P-5
+                                                 */
+#define EV_PLCI_CD_IND			20	/* P-2 -> P-5
+                                                 */
 
 /*
  * per ncci state machine
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capilli.h linux.pre11.3/drivers/isdn/avmb1/capilli.h
--- linux.vanilla/drivers/isdn/avmb1/capilli.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/capilli.h	Mon Jul 19 23:59:32 1999
@@ -0,0 +1,109 @@
+/*
+ * $Id: capilli.h,v 1.2 1999/07/05 15:09:52 calle Exp $
+ * 
+ * Kernel CAPI 2.0 Driver Interface for Linux
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ */
+#ifndef __CAPILLI_H__
+#define __CAPILLI_H__
+
+typedef struct capiloaddatapart {
+	int user;		/* data in userspace ? */
+	int len;
+	unsigned char *data;
+} capiloaddatapart;
+
+typedef struct capiloaddata {
+	capiloaddatapart firmware;
+	capiloaddatapart configuration;
+} capiloaddata;
+
+typedef struct capicardparams {
+	unsigned int port;
+	unsigned irq;
+	int cardtype;
+	int cardnr;
+} capicardparams;
+
+struct capi_driver;
+
+struct capi_ctr {
+        struct capi_ctr *next;			/* next ctr of same driver */
+        struct capi_driver *driver;
+	int cnr;				/* controller number */
+	char name[32];				/* name of controller */
+	volatile unsigned short cardstate;	/* controller state */
+	volatile int blocked;			/* output blocked */
+	int traceflag;				/* capi trace */
+
+	void *driverdata;			/* driver specific */
+
+	/* filled before calling ready callback */
+	__u8 manu[CAPI_MANUFACTURER_LEN];	/* CAPI_GET_MANUFACTURER */
+	capi_version version;			/* CAPI_GET_VERSION */
+	capi_profile profile;			/* CAPI_GET_PROFILE */
+	__u8 serial[CAPI_SERIAL_LEN];		/* CAPI_GET_SERIAL */
+
+	/* functions */
+        void (*ready)(struct capi_ctr * card);
+        void (*reseted)(struct capi_ctr * card);
+        void (*suspend_output)(struct capi_ctr * card);
+        void (*resume_output)(struct capi_ctr * card);
+        void (*handle_capimsg)(struct capi_ctr * card,
+			   	__u16 appl, struct sk_buff *skb);
+	void (*appl_registered)(struct capi_ctr * card, __u16 appl);
+	void (*appl_released)(struct capi_ctr * card, __u16 appl);
+
+        void (*new_ncci)(struct capi_ctr * card,
+			   	__u16 appl, __u32 ncci, __u32 winsize);
+        void (*free_ncci)(struct capi_ctr * card, __u16 appl, __u32 ncci);
+
+	/* management information for kcapi */
+
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
+
+	struct proc_dir_entry *procent;
+        char procfn[128];
+};
+
+struct capi_driver_interface {
+    struct capi_ctr *(*attach_ctr)(struct capi_driver *driver, char *name, void *data);
+    int (*detach_ctr)(struct capi_ctr *);
+};
+
+struct capi_driver {
+     char name[32];				/* driver name */
+     char revision[32];
+     int (*load_firmware)(struct capi_ctr *, capiloaddata *);
+     void (*reset_ctr)(struct capi_ctr *);
+     void (*remove_ctr)(struct capi_ctr *);
+     void (*register_appl)(struct capi_ctr *, __u16 appl,
+						capi_register_params *);
+     void (*release_appl)(struct capi_ctr *, __u16 appl);
+     void (*send_message)(struct capi_ctr *, struct sk_buff *skb);
+
+     char *(*procinfo)(struct capi_ctr *);
+     int (*ctr_read_proc)(char *page, char **start, off_t off,
+			       int count, int *eof, struct capi_ctr *card);
+     int (*driver_read_proc)(char *page, char **start, off_t off,
+		               int count, int *eof, struct capi_driver *driver);
+
+     int (*add_card)(struct capi_driver *driver, capicardparams *data);
+
+     /* intitialized by kcapi */
+     struct capi_ctr	*controller;		/* list of controllers */
+     struct capi_driver *next;
+     int ncontroller;
+     struct proc_dir_entry *procent;
+     char procfn[128];
+};
+
+struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver);
+void detach_capi_driver(struct capi_driver *driver);
+
+#endif				/* __CAPILLI_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/capiutil.c linux.pre11.3/drivers/isdn/avmb1/capiutil.c
--- linux.vanilla/drivers/isdn/avmb1/capiutil.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/capiutil.c	Mon Jul 19 23:59:32 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: capiutil.c,v 1.6 1997/11/04 06:12:12 calle Exp $
+ * $Id: capiutil.c,v 1.9 1999/07/09 15:05:46 keil Exp $
  *
  * CAPI 2.0 convert capi message to capi message struct
  *
@@ -7,6 +7,28 @@
  * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capiutil.c,v $
+ * Revision 1.9  1999/07/09 15:05:46  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.8  1999/07/01 15:26:37  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.7  1999/07/01 08:23:01  keil
+ * compatibility macros now in <linux/isdn_compat.h>
+ *
  * Revision 1.6  1997/11/04 06:12:12  calle
  * capi.c: new read/write in file_ops since 2.1.60
  * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
@@ -48,7 +70,7 @@
 #include <asm/segment.h>
 #include <linux/config.h>
 
-#include "compat.h"
+#include <linux/isdn_compat.h>
 #include "capiutil.h"
 
 /* from CAPI2.0 DDK AVM Berlin GmbH */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/compat.h linux.pre11.3/drivers/isdn/avmb1/compat.h
--- linux.vanilla/drivers/isdn/avmb1/compat.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/avmb1/compat.h	Mon Jul 19 23:59:32 1999
@@ -1,41 +0,0 @@
-/*
- * $Id: compat.h,v 1.3 1997/11/04 06:12:15 calle Exp $
- * 
- * Headerfile for Compartibility between different kernel versions
- * 
- * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
- * 
- * $Log: compat.h,v $
- * Revision 1.3  1997/11/04 06:12:15  calle
- * capi.c: new read/write in file_ops since 2.1.60
- * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware.
- * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON)
- * compat.h: added #define LinuxVersionCode
- *
- * Revision 1.2  1997/10/01 09:21:22  fritz
- * Removed old compatibility stuff for 2.0.X kernels.
- * From now on, this code is for 2.1.X ONLY!
- * Old stuff is still in the separate branch.
- *
- * Revision 1.1  1997/03/04 21:50:36  calle
- * Frirst version in isdn4linux
- *
- * Revision 2.2  1997/02/12 09:31:39  calle
- * new version
- *
- * Revision 1.1  1997/01/31 10:32:20  calle
- * Initial revision
- *
- * 
- */
-#ifndef __COMPAT_H__
-#define __COMPAT_H__
-
-#include <linux/version.h>
-#include <linux/isdnif.h>
-
-#ifndef LinuxVersionCode
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-#endif
-
-#endif				/* __COMPAT_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/kcapi.c linux.pre11.3/drivers/isdn/avmb1/kcapi.c
--- linux.vanilla/drivers/isdn/avmb1/kcapi.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/kcapi.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,1522 @@
+/*
+ * $Id: kcapi.c,v 1.5 1999/07/09 15:05:48 keil Exp $
+ * 
+ * Kernel CAPI 2.0 Module
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: kcapi.c,v $
+ * Revision 1.5  1999/07/09 15:05:48  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.4  1999/07/08 14:15:17  calle
+ * Forgot to count down ncards in drivercb_detach_ctr.
+ *
+ * Revision 1.3  1999/07/06 07:42:02  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.2  1999/07/05 15:09:52  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:42  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+#define CONFIG_AVMB1_COMPAT
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <asm/segment.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/tqueue.h>
+#include <linux/capi.h>
+#include <linux/kernelcapi.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#ifdef CONFIG_AVMB1_COMPAT
+#include <linux/b1lli.h>
+#endif
+
+static char *revision = "$Revision: 1.5 $";
+
+/* ------------------------------------------------------------- */
+
+#define CARD_FREE	0
+#define CARD_DETECTED	1
+#define CARD_LOADING	2
+#define CARD_RUNNING	3
+
+/* ------------------------------------------------------------- */
+
+int showcapimsgs = 0;
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+MODULE_PARM(showcapimsgs, "0-4i");
+
+/* ------------------------------------------------------------- */
+
+struct msgidqueue {
+	struct msgidqueue *next;
+	__u16 msgid;
+};
+
+struct capi_ncci {
+	struct capi_ncci *next;
+	__u16 applid;
+	__u32 ncci;
+	__u32 winsize;
+	int   nmsg;
+	struct msgidqueue *msgidqueue;
+	struct msgidqueue *msgidlast;
+	struct msgidqueue *msgidfree;
+	struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW];
+};
+
+struct capi_appl {
+	__u16 applid;
+	capi_register_params rparam;
+	int releasing;
+	__u32 param;
+	void (*signal) (__u16 applid, __u32 param);
+	struct sk_buff_head recv_queue;
+	int nncci;
+	struct capi_ncci *nccilist;
+
+	unsigned long nrecvctlpkt;
+	unsigned long nrecvdatapkt;
+	unsigned long nsentctlpkt;
+	unsigned long nsentdatapkt;
+};
+
+/* ------------------------------------------------------------- */
+
+static struct capi_version driver_version = {2, 0, 1, 1<<4};
+static char driver_serial[CAPI_SERIAL_LEN] = "4711";
+static char capi_manufakturer[64] = "AVM Berlin";
+
+#define APPL(a)		   (&applications[(a)-1])
+#define	VALID_APPLID(a)	   ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
+#define APPL_IS_FREE(a)    (APPL(a)->applid == 0)
+#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
+#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
+
+#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
+
+#define VALID_CARD(c)	   ((c) > 0 && (c) <= CAPI_MAXCONTR)
+#define CARD(c)		   (&cards[(c)-1])
+#define CARDNR(cp)	   (((cp)-cards)+1)
+
+static struct capi_appl applications[CAPI_MAXAPPL];
+static struct capi_ctr cards[CAPI_MAXCONTR];
+static int ncards = 0;
+static struct sk_buff_head recv_queue;
+static struct capi_interface_user *capi_users = 0;
+static struct capi_driver *drivers;
+#ifdef CONFIG_AVMB1_COMPAT
+static struct capi_driver *b1isa_driver;
+static struct capi_driver *t1isa_driver;
+#endif
+static long notify_up_set = 0;
+static long notify_down_set = 0;
+
+static struct tq_struct tq_state_notify;
+static struct tq_struct tq_recv_notify;
+
+/* -------- util functions ------------------------------------ */
+
+static char *cardstate2str(unsigned short cardstate)
+{
+	switch (cardstate) {
+        	default:
+		case CARD_FREE:		return "free";
+		case CARD_DETECTED:	return "detected";
+		case CARD_LOADING:	return "loading";
+		case CARD_RUNNING:	return "running";
+	}
+}
+
+static inline int capi_cmd_valid(__u8 cmd)
+{
+	switch (cmd) {
+	case CAPI_ALERT:
+	case CAPI_CONNECT:
+	case CAPI_CONNECT_ACTIVE:
+	case CAPI_CONNECT_B3_ACTIVE:
+	case CAPI_CONNECT_B3:
+	case CAPI_CONNECT_B3_T90_ACTIVE:
+	case CAPI_DATA_B3:
+	case CAPI_DISCONNECT_B3:
+	case CAPI_DISCONNECT:
+	case CAPI_FACILITY:
+	case CAPI_INFO:
+	case CAPI_LISTEN:
+	case CAPI_MANUFACTURER:
+	case CAPI_RESET_B3:
+	case CAPI_SELECT_B_PROTOCOL:
+		return 1;
+	}
+	return 0;
+}
+
+static inline int capi_subcmd_valid(__u8 subcmd)
+{
+	switch (subcmd) {
+	case CAPI_REQ:
+	case CAPI_CONF:
+	case CAPI_IND:
+	case CAPI_RESP:
+		return 1;
+	}
+	return 0;
+}
+
+/* -------- /proc functions ----------------------------------- */
+/*
+ * /proc/capi/applications:
+ *      applid l3cnt dblkcnt dblklen #ncci recvqueuelen
+ */
+static int proc_applications_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_appl *ap;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXAPPL; i++) {
+		ap = &applications[i];
+		if (ap->applid == 0) continue;
+		len += sprintf(page+len, "%u %d %d %d %d %d\n",
+			ap->applid,
+			ap->rparam.level3cnt,
+			ap->rparam.datablkcnt,
+			ap->rparam.datablklen,
+			ap->nncci,
+                        skb_queue_len(&ap->recv_queue));
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXAPPL)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/ncci:
+ *	applid ncci winsize nblk
+ */
+static int proc_ncci_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_appl *ap;
+	struct capi_ncci *np;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXAPPL; i++) {
+		ap = &applications[i];
+		if (ap->applid == 0) continue;
+		for (np = ap->nccilist; np; np = np->next) {
+			len += sprintf(page+len, "%d 0x%x %d %d\n",
+				np->applid,
+				np->ncci,
+				np->winsize,
+				np->nmsg);
+			if (len+begin > off+count)
+				goto endloop;
+			if (len+begin < off) {
+				begin += len;
+				len = 0;
+			}
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXAPPL)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/driver:
+ *	driver ncontroller
+ */
+static int proc_driver_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_driver *driver;
+	int len = 0;
+	off_t begin = 0;
+
+	for (driver = drivers; driver; driver = driver->next) {
+		len += sprintf(page+len, "%-32s %d %s\n",
+					driver->name,
+					driver->ncontroller,
+					driver->revision);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (!driver)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/users:
+ *	name
+ */
+static int proc_users_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+        struct capi_interface_user *cp;
+	int len = 0;
+	off_t begin = 0;
+
+        for (cp = capi_users; cp ; cp = cp->next) {
+		len += sprintf(page+len, "%s\n", cp->name);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (cp == 0)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/controller:
+ *	cnr driver cardstate name driverinfo
+ */
+static int proc_controller_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_ctr *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXCONTR; i++) {
+		cp = &cards[i];
+		if (cp->cardstate == CARD_FREE) continue;
+		len += sprintf(page+len, "%d %-10s %-8s %-16s %s\n",
+			cp->cnr, cp->driver->name, 
+			cardstate2str(cp->cardstate),
+			cp->name,
+			cp->driver->procinfo ?  cp->driver->procinfo(cp) : ""
+			);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXCONTR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/applstats:
+ *	applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
+ */
+static int proc_applstats_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_appl *ap;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXAPPL; i++) {
+		ap = &applications[i];
+		if (ap->applid == 0) continue;
+		len += sprintf(page+len, "%u %lu %lu %lu %lu\n",
+			ap->applid,
+			ap->nrecvctlpkt,
+			ap->nrecvdatapkt,
+			ap->nsentctlpkt,
+			ap->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXAPPL)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * /proc/capi/contrstats:
+ *	cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt
+ */
+static int proc_contrstats_read_proc(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data)
+{
+	struct capi_ctr *cp;
+	int i;
+	int len = 0;
+	off_t begin = 0;
+
+	for (i=0; i < CAPI_MAXCONTR; i++) {
+		cp = &cards[i];
+		if (cp->cardstate == CARD_FREE) continue;
+		len += sprintf(page+len, "%d %lu %lu %lu %lu\n",
+			cp->cnr, 
+			cp->nrecvctlpkt,
+			cp->nrecvdatapkt,
+			cp->nsentctlpkt,
+			cp->nsentdatapkt);
+		if (len+begin > off+count)
+			goto endloop;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+endloop:
+	if (i >= CAPI_MAXCONTR)
+		*eof = 1;
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+static struct procfsentries {
+  char *name;
+  mode_t mode;
+  int (*read_proc)(char *page, char **start, off_t off,
+                                       int count, int *eof, void *data);
+  struct proc_dir_entry *procent;
+} procfsentries[] = {
+   { "capi",		  S_IFDIR, 0 },
+   { "capi/applications", 0	 , proc_applications_read_proc },
+   { "capi/ncci", 	  0	 , proc_ncci_read_proc },
+   { "capi/driver",       0	 , proc_driver_read_proc },
+   { "capi/users", 	  0	 , proc_users_read_proc },
+   { "capi/controller",   0	 , proc_controller_read_proc },
+   { "capi/applstats",    0	 , proc_applstats_read_proc },
+   { "capi/contrstats",   0	 , proc_contrstats_read_proc },
+   { "capi/drivers",	  S_IFDIR, 0 },
+   { "capi/controllers",  S_IFDIR, 0 },
+};
+
+static void proc_capi_init(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=0; i < nelem; i++) {
+        struct procfsentries *p = procfsentries + i;
+	p->procent = create_proc_entry(p->name, p->mode, 0);
+	if (p->procent) p->procent->read_proc = p->read_proc;
+    }
+}
+
+static void proc_capi_exit(void)
+{
+    int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
+    int i;
+
+    for (i=nelem-1; i >= 0; i--) {
+        struct procfsentries *p = procfsentries + i;
+	if (p->procent) {
+	   remove_proc_entry(p->name, 0);
+	   p->procent = 0;
+	}
+    }
+}
+
+/* -------- NCCI Handling ------------------------------------- */
+
+static inline void mq_init(struct capi_ncci * np)
+{
+	int i;
+	np->msgidqueue = 0;
+	np->msgidlast = 0;
+	np->nmsg = 0;
+	memset(np->msgidpool, 0, sizeof(np->msgidpool));
+	np->msgidfree = &np->msgidpool[0];
+	for (i = 1; i < np->winsize; i++) {
+		np->msgidpool[i].next = np->msgidfree;
+		np->msgidfree = &np->msgidpool[i];
+	}
+}
+
+static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid)
+{
+	struct msgidqueue *mq;
+	if ((mq = np->msgidfree) == 0)
+		return 0;
+	np->msgidfree = mq->next;
+	mq->msgid = msgid;
+	mq->next = 0;
+	if (np->msgidlast)
+		np->msgidlast->next = mq;
+	np->msgidlast = mq;
+	if (!np->msgidqueue)
+		np->msgidqueue = mq;
+	np->nmsg++;
+	return 1;
+}
+
+static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid)
+{
+	struct msgidqueue **pp;
+	for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
+		if ((*pp)->msgid == msgid) {
+			struct msgidqueue *mq = *pp;
+			*pp = mq->next;
+			if (mq == np->msgidlast)
+				np->msgidlast = 0;
+			mq->next = np->msgidfree;
+			np->msgidfree = mq;
+			np->nmsg--;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl)
+{
+}
+
+static void controllercb_appl_released(struct capi_ctr * card, __u16 appl)
+{
+	struct capi_ncci **pp, **nextpp;
+	for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
+		if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
+			struct capi_ncci *np = *pp;
+			*pp = np->next;
+			printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", appl, np->ncci);
+			kfree(np);
+			APPL(appl)->nncci--;
+			nextpp = pp;
+		} else {
+			nextpp = &(*pp)->next;
+		}
+	}
+	APPL(appl)->releasing--;
+	if (APPL(appl)->releasing <= 0) {
+		APPL(appl)->signal = 0;
+		APPL_MARK_FREE(appl);
+		printk(KERN_INFO "kcapi: appl %d down\n", appl);
+	}
+}
+/*
+ * ncci managment
+ */
+
+static void controllercb_new_ncci(struct capi_ctr * card,
+					__u16 appl, __u32 ncci, __u32 winsize)
+{
+	struct capi_ncci *np;
+	if (!VALID_APPLID(appl)) {
+		printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl);
+		return;
+	}
+	if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) {
+		printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci);
+		return;
+	}
+	if (winsize > CAPI_MAXDATAWINDOW) {
+		printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n",
+		       winsize, CAPI_MAXDATAWINDOW);
+		winsize = CAPI_MAXDATAWINDOW;
+	}
+	np->applid = appl;
+	np->ncci = ncci;
+	np->winsize = winsize;
+	mq_init(np);
+	np->next = APPL(appl)->nccilist;
+	APPL(appl)->nccilist = np;
+	APPL(appl)->nncci++;
+	printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci);
+
+}
+
+static void controllercb_free_ncci(struct capi_ctr * card,
+				__u16 appl, __u32 ncci)
+{
+	struct capi_ncci **pp;
+	if (!VALID_APPLID(appl)) {
+		printk(KERN_ERR "free_ncci: illegal appl %d\n", appl);
+		return;
+	}
+	for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) {
+		if ((*pp)->ncci == ncci) {
+			struct capi_ncci *np = *pp;
+			*pp = np->next;
+			kfree(np);
+			APPL(appl)->nncci--;
+			printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci);
+			return;
+		}
+	}
+	printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci);
+}
+
+
+static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci)
+{
+	struct capi_ncci *np;
+	for (np = app->nccilist; np; np = np->next) {
+		if (np->ncci == ncci)
+			return np;
+	}
+	return 0;
+}
+
+/* -------- Receiver ------------------------------------------ */
+
+static void recv_handler(void *dummy)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&recv_queue)) != 0) {
+		__u16 appl = CAPIMSG_APPID(skb->data);
+		struct capi_ncci *np;
+		if (!VALID_APPLID(appl)) {
+			printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n",
+			       appl, capi_message2str(skb->data));
+			kfree_skb(skb);
+			continue;
+		}
+		if (APPL(appl)->signal == 0) {
+			printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n",
+			       appl);
+			kfree_skb(skb);
+			continue;
+		}
+		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF
+	            && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0
+		    && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) {
+			printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n",
+				CAPIMSG_MSGID(skb->data), np->ncci);
+		}
+		if (   CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3
+		    && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
+			APPL(appl)->nrecvdatapkt++;
+		} else {
+			APPL(appl)->nrecvctlpkt++;
+		}
+		skb_queue_tail(&APPL(appl)->recv_queue, skb);
+		(APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param);
+	}
+}
+
+static void controllercb_handle_capimsg(struct capi_ctr * card,
+				__u16 appl, struct sk_buff *skb)
+{
+	int showctl = 0;
+	__u8 cmd, subcmd;
+
+	if (card->cardstate != CARD_RUNNING) {
+		printk(KERN_INFO "kcapi: controller %d not active, got: %s",
+		       card->cnr, capi_message2str(skb->data));
+		goto error;
+	}
+	cmd = CAPIMSG_COMMAND(skb->data);
+        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+	if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
+		card->nrecvdatapkt++;
+	        if (card->traceflag > 2) showctl |= 2;
+	        if (card->traceflag) showctl |= 2;
+	} else {
+		card->nrecvctlpkt++;
+	}
+	showctl |= (card->traceflag & 1);
+	if (showctl & 2) {
+		if (showctl & 1) {
+			printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n",
+			       (unsigned long) card->cnr,
+			       CAPIMSG_APPID(skb->data),
+			       capi_cmd2str(cmd, subcmd),
+			       CAPIMSG_LEN(skb->data));
+		} else {
+			printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n",
+					(unsigned long) card->cnr,
+					capi_message2str(skb->data));
+		}
+
+	}
+	skb_queue_tail(&recv_queue, skb);
+	queue_task(&tq_recv_notify, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+	return;
+
+error:
+	kfree_skb(skb);
+}
+
+/* -------- Notifier ------------------------------------------ */
+
+static void notify_up(__u16 contr)
+{
+	struct capi_interface_user *p;
+
+        printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
+	for (p = capi_users; p; p = p->next) {
+		if (!p->callback) continue;
+		(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);
+	}
+}
+
+static void notify_down(__u16 contr)
+{
+	struct capi_interface_user *p;
+        printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
+	for (p = capi_users; p; p = p->next) {
+		if (!p->callback) continue;
+		(*p->callback) (KCI_CONTRDOWN, contr, 0);
+	}
+}
+
+static void notify_handler(void *dummy)
+{
+	__u16 contr;
+
+	for (contr=1; VALID_CARD(contr); contr++)
+		 if (test_and_clear_bit(contr, &notify_up_set))
+			 notify_up(contr);
+	for (contr=1; VALID_CARD(contr); contr++)
+		 if (test_and_clear_bit(contr, &notify_down_set))
+			 notify_down(contr);
+}
+
+
+static void controllercb_ready(struct capi_ctr * card)
+{
+	__u16 appl;
+
+	card->cardstate = CARD_RUNNING;
+
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		if (!VALID_APPLID(appl)) continue;
+		if (APPL(appl)->releasing) continue;
+		card->driver->register_appl(card, appl, &APPL(appl)->rparam);
+	}
+
+        set_bit(CARDNR(card), &notify_up_set);
+        queue_task(&tq_state_notify, &tq_scheduler);
+
+        printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
+		CARDNR(card), card->name);
+}
+
+static void controllercb_reseted(struct capi_ctr * card)
+{
+	__u16 appl;
+
+        if (card->cardstate == CARD_FREE)
+		return;
+        if (card->cardstate == CARD_DETECTED)
+		return;
+
+        card->cardstate = CARD_DETECTED;
+
+	memset(card->manu, 0, sizeof(card->manu));
+	memset(&card->version, 0, sizeof(card->version));
+	memset(&card->profile, 0, sizeof(card->profile));
+	memset(card->serial, 0, sizeof(card->serial));
+
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		struct capi_ncci **pp, **nextpp;
+		for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) {
+			if (NCCI2CTRL((*pp)->ncci) == card->cnr) {
+				struct capi_ncci *np = *pp;
+				*pp = np->next;
+				printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci);
+				kfree(np);
+				nextpp = pp;
+			} else {
+				nextpp = &(*pp)->next;
+			}
+		}
+	}
+	set_bit(CARDNR(card), &notify_down_set);
+	queue_task(&tq_state_notify, &tq_scheduler);
+	printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card));
+}
+
+static void controllercb_suspend_output(struct capi_ctr *card)
+{
+	if (!card->blocked) {
+		printk(KERN_DEBUG "kcapi: card %d suspend\n", CARDNR(card));
+		card->blocked = 1;
+	}
+}
+
+static void controllercb_resume_output(struct capi_ctr *card)
+{
+	if (card->blocked) {
+		printk(KERN_DEBUG "kcapi: card %d resume\n", CARDNR(card));
+		card->blocked = 0;
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+
+struct capi_ctr *
+drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata)
+{
+	struct capi_ctr *card, **pp;
+	int i;
+
+	for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ;
+   
+	if (i == CAPI_MAXCONTR) {
+		printk(KERN_ERR "kcapi: out of controller slots\n");
+	   	return 0;
+	}
+	card = &cards[i];
+	memset(card, 0, sizeof(struct capi_ctr));
+	card->driver = driver;
+	card->cnr = CARDNR(card);
+	strncpy(card->name, name, sizeof(card->name));
+	card->cardstate = CARD_DETECTED;
+	card->blocked = 0;
+	card->driverdata = driverdata;
+	card->traceflag = showcapimsgs;
+
+        card->ready = controllercb_ready; 
+        card->reseted = controllercb_reseted; 
+        card->suspend_output = controllercb_suspend_output;
+        card->resume_output = controllercb_resume_output;
+        card->handle_capimsg = controllercb_handle_capimsg;
+	card->appl_registered = controllercb_appl_registered;
+	card->appl_released = controllercb_appl_released;
+        card->new_ncci = controllercb_new_ncci;
+        card->free_ncci = controllercb_free_ncci;
+
+	for (pp = &driver->controller; *pp; pp = &(*pp)->next) ;
+	card->next = 0;
+	*pp = card;
+	driver->ncontroller++;
+	sprintf(card->procfn, "capi/controllers/%d", card->cnr);
+	card->procent = create_proc_entry(card->procfn, 0, 0);
+	if (card->procent) {
+	   card->procent->read_proc = 
+		(int (*)(char *,char **,off_t,int,int *,void *))
+			driver->ctr_read_proc;
+	   card->procent->data = card;
+	}
+
+	ncards++;
+	printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n",
+			card->cnr, card->name);
+	return card;
+}
+
+static int drivercb_detach_ctr(struct capi_ctr *card)
+{
+	struct capi_driver *driver = card->driver;
+	struct capi_ctr **pp;
+
+        if (card->cardstate == CARD_FREE)
+		return 0;
+        if (card->cardstate != CARD_DETECTED)
+		controllercb_reseted(card);
+	for (pp = &driver->controller; *pp ; pp = &(*pp)->next) {
+        	if (*pp == card) {
+	        	*pp = card->next;
+			driver->ncontroller--;
+			ncards--;
+	        	break;
+		}
+	}
+	if (card->procent) {
+	   remove_proc_entry(card->procfn, 0);
+	   card->procent = 0;
+	}
+	card->cardstate = CARD_FREE;
+	printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n",
+			card->cnr, card->name);
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+/* fallback if no driver read_proc function defined by driver */
+
+static int driver_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, void *data)
+{
+	struct capi_driver *driver = (struct capi_driver *)data;
+	int len = 0;
+
+	len += sprintf(page+len, "%-16s %s\n", "name", driver->name);
+	len += sprintf(page+len, "%-16s %s\n", "revision", driver->revision);
+
+	if (len < off) 
+           return 0;
+	*eof = 1;
+	*start = page - off;
+	return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface di = {
+    drivercb_attach_ctr,
+    drivercb_detach_ctr,
+};
+
+struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
+{
+	struct capi_driver **pp;
+
+	for (pp = &drivers; *pp; pp = &(*pp)->next) ;
+	driver->next = 0;
+	*pp = driver;
+	printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);
+#ifdef CONFIG_AVMB1_COMPAT
+        if (strcmp(driver->name, "b1isa") == 0 && driver->add_card)
+		b1isa_driver = driver;
+        if (strcmp(driver->name, "t1isa") == 0 && driver->add_card)
+		t1isa_driver = driver;
+#endif
+	sprintf(driver->procfn, "capi/drivers/%s", driver->name);
+	driver->procent = create_proc_entry(driver->procfn, 0, 0);
+	if (driver->procent) {
+	   if (driver->driver_read_proc) {
+		   driver->procent->read_proc = 
+	       		(int (*)(char *,char **,off_t,int,int *,void *))
+					driver->driver_read_proc;
+	   } else {
+		   driver->procent->read_proc = driver_read_proc;
+	   }
+	   driver->procent->data = driver;
+	}
+	return &di;
+}
+
+void detach_capi_driver(struct capi_driver *driver)
+{
+	struct capi_driver **pp;
+	for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
+	if (*pp) {
+		*pp = (*pp)->next;
+#ifdef CONFIG_AVMB1_COMPAT
+		if (driver == b1isa_driver) b1isa_driver = 0;
+		if (driver == t1isa_driver) t1isa_driver = 0;
+#endif
+		printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name);
+	} else {
+		printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);
+	}
+	if (driver->procent) {
+	   remove_proc_entry(driver->procfn, 0);
+	   driver->procent = 0;
+	}
+}
+
+/* ------------------------------------------------------------- */
+/* -------- CAPI2.0 Interface ---------------------------------- */
+/* ------------------------------------------------------------- */
+
+static int capi_installed(void)
+{
+	int i;
+	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		if (cards[i].cardstate == CARD_RUNNING)
+			return 1;
+	}
+	return 0;
+}
+
+static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
+{
+	int appl;
+	int i;
+
+	if (rparam->datablklen < 128)
+		return CAPI_LOGBLKSIZETOSMALL;
+
+	for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+		if (APPL_IS_FREE(appl))
+			break;
+	}
+	if (appl > CAPI_MAXAPPL)
+		return CAPI_TOOMANYAPPLS;
+
+	APPL_MARK_USED(appl);
+	skb_queue_head_init(&APPL(appl)->recv_queue);
+	APPL(appl)->nncci = 0;
+
+	memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params));
+
+	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		if (cards[i].cardstate != CARD_RUNNING)
+			continue;
+		cards[i].driver->register_appl(&cards[i], appl,
+						&APPL(appl)->rparam);
+	}
+	*applidp = appl;
+	printk(KERN_INFO "kcapi: appl %d up\n", appl);
+
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_release(__u16 applid)
+{
+	struct sk_buff *skb;
+	int i;
+
+	if (!VALID_APPLID(applid) || APPL(applid)->releasing)
+		return CAPI_ILLAPPNR;
+	while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
+		kfree_skb(skb);
+	for (i = 0; i < CAPI_MAXCONTR; i++) {
+		if (cards[i].cardstate != CARD_RUNNING)
+			continue;
+		APPL(applid)->releasing++;
+		cards[i].driver->release_appl(&cards[i], applid);
+	}
+	if (APPL(applid)->releasing <= 0) {
+	        APPL(applid)->signal = 0;
+		APPL_MARK_FREE(applid);
+		printk(KERN_INFO "kcapi: appl %d down\n", applid);
+	}
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_put_message(__u16 applid, struct sk_buff *skb)
+{
+	struct capi_ncci *np;
+	int contr;
+	int showctl = 0;
+	__u8 cmd, subcmd;
+
+	if (ncards == 0)
+		return CAPI_REGNOTINSTALLED;
+	if (!VALID_APPLID(applid))
+		return CAPI_ILLAPPNR;
+	if (skb->len < 12
+	    || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
+	    || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
+		return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
+	contr = CAPIMSG_CONTROLLER(skb->data);
+	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) {
+		contr = 1;
+	        if (CARD(contr)->cardstate != CARD_RUNNING) 
+			return CAPI_REGNOTINSTALLED;
+	}
+	if (CARD(contr)->blocked)
+		return CAPI_SENDQUEUEFULL;
+
+	cmd = CAPIMSG_COMMAND(skb->data);
+        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+	if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
+	    	if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0
+	            && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0)
+			return CAPI_SENDQUEUEFULL;
+		CARD(contr)->nsentdatapkt++;
+		APPL(applid)->nsentdatapkt++;
+	        if (CARD(contr)->traceflag > 2) showctl |= 2;
+	} else {
+		CARD(contr)->nsentctlpkt++;
+		APPL(applid)->nsentctlpkt++;
+	        if (CARD(contr)->traceflag) showctl |= 2;
+	}
+	showctl |= (CARD(contr)->traceflag & 1);
+	if (showctl & 2) {
+		if (showctl & 1) {
+			printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%u\n",
+			       (unsigned long) contr,
+			       CAPIMSG_APPID(skb->data),
+			       capi_cmd2str(cmd, subcmd),
+			       CAPIMSG_LEN(skb->data));
+		} else {
+			printk(KERN_DEBUG "kcapi: put [0x%lx] %s\n",
+					(unsigned long) contr,
+					capi_message2str(skb->data));
+		}
+
+	}
+	CARD(contr)->driver->send_message(CARD(contr), skb);
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
+{
+	struct sk_buff *skb;
+
+	if (!VALID_APPLID(applid))
+		return CAPI_ILLAPPNR;
+	if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0)
+		return CAPI_RECEIVEQUEUEEMPTY;
+	*msgp = skb;
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_set_signal(__u16 applid,
+			     void (*signal) (__u16 applid, __u32 param),
+			     __u32 param)
+{
+	if (!VALID_APPLID(applid))
+		return CAPI_ILLAPPNR;
+	APPL(applid)->signal = signal;
+	APPL(applid)->param = param;
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_manufacturer(__u16 contr, __u8 buf[CAPI_MANUFACTURER_LEN])
+{
+	if (contr == 0) {
+		strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
+		return CAPI_NOERROR;
+	}
+	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
+		return 0x2002;
+
+	strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN);
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_version(__u16 contr, struct capi_version *verp)
+{
+	if (contr == 0) {
+		*verp = driver_version;
+		return CAPI_NOERROR;
+	}
+	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
+		return 0x2002;
+
+	memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version));
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_serial(__u16 contr, __u8 serial[CAPI_SERIAL_LEN])
+{
+	if (contr == 0) {
+		strncpy(serial, driver_serial, CAPI_SERIAL_LEN);
+		return CAPI_NOERROR;
+	}
+	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
+		return 0x2002;
+
+	strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN);
+	return CAPI_NOERROR;
+}
+
+static __u16 capi_get_profile(__u16 contr, struct capi_profile *profp)
+{
+	if (contr == 0) {
+		profp->ncontroller = ncards;
+		return CAPI_NOERROR;
+	}
+	if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) 
+		return 0x2002;
+
+	memcpy((void *) profp, &CARD(contr)->profile,
+			sizeof(struct capi_profile));
+	return CAPI_NOERROR;
+}
+
+#ifdef CONFIG_AVMB1_COMPAT
+static int old_capi_manufacturer(unsigned int cmd, void *data)
+{
+	avmb1_loadandconfigdef ldef;
+	avmb1_extcarddef cdef;
+	avmb1_resetdef rdef;
+	avmb1_getdef gdef;
+	struct capi_driver *driver;
+	struct capi_ctr *card;
+	capicardparams cparams;
+	capiloaddata ldata;
+	int retval;
+
+	switch (cmd) {
+	case AVMB1_ADDCARD:
+	case AVMB1_ADDCARD_WITH_TYPE:
+		if (cmd == AVMB1_ADDCARD) {
+		   if ((retval = copy_from_user((void *) &cdef, data,
+					    sizeof(avmb1_carddef))))
+			   return retval;
+		   cdef.cardtype = AVM_CARDTYPE_B1;
+		} else {
+		   if ((retval = copy_from_user((void *) &cdef, data,
+					    sizeof(avmb1_extcarddef))))
+			   return retval;
+		}
+		cparams.port = cdef.port;
+		cparams.irq = cdef.irq;
+		cparams.cardnr = cdef.cardnr;
+
+                switch (cdef.cardtype) {
+			case AVM_CARDTYPE_B1: driver = b1isa_driver; break;
+			case AVM_CARDTYPE_T1: driver = t1isa_driver; break;
+			default: driver = 0;
+		}
+		if (!driver || !driver->add_card) {
+			return -EIO;
+		}
+
+		return driver->add_card(driver, &cparams);
+
+	case AVMB1_LOAD:
+	case AVMB1_LOAD_AND_CONFIG:
+
+		if (cmd == AVMB1_LOAD) {
+			if ((retval = copy_from_user((void *) &ldef, data,
+						sizeof(avmb1_loaddef))))
+				return retval;
+			ldef.t4config.len = 0;
+			ldef.t4config.data = 0;
+		} else {
+			if ((retval = copy_from_user((void *) &ldef, data,
+					    	sizeof(avmb1_loadandconfigdef))))
+				return retval;
+		}
+		if (!VALID_CARD(ldef.contr))
+			return -ESRCH;
+
+		card = CARD(ldef.contr);
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+
+		if (ldef.t4file.len <= 0) {
+			printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
+			return -EINVAL;
+		}
+		if (ldef.t4file.data == 0) {
+			printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
+			return -EINVAL;
+		}
+
+		ldata.firmware.user = 1;
+		ldata.firmware.data = ldef.t4file.data;
+		ldata.firmware.len = ldef.t4file.len;
+		ldata.configuration.user = 1;
+		ldata.configuration.data = ldef.t4config.data;
+		ldata.configuration.len = ldef.t4config.len;
+
+		if (card->cardstate != CARD_DETECTED) {
+			printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
+			return -EBUSY;
+		}
+		card->cardstate = CARD_LOADING;
+
+		retval = card->driver->load_firmware(card, &ldata);
+
+		if (retval) {
+			card->cardstate = CARD_DETECTED;
+			return retval;
+		}
+
+		while (card->cardstate != CARD_RUNNING) {
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/10);	/* 0.1 sec */
+
+			if (signal_pending(current))
+				return -EINTR;
+		}
+		return 0;
+
+	case AVMB1_RESETCARD:
+		if ((retval = copy_from_user((void *) &rdef, data,
+					 sizeof(avmb1_resetdef))))
+			return retval;
+		if (!VALID_CARD(rdef.contr))
+			return -ESRCH;
+		card = CARD(rdef.contr);
+
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+		if (card->cardstate == CARD_DETECTED)
+			return 0;
+
+		card->driver->reset_ctr(card);
+
+		while (card->cardstate > CARD_DETECTED) {
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/10);	/* 0.1 sec */
+
+			if (signal_pending(current))
+				return -EINTR;
+		}
+		return 0;
+
+	case AVMB1_GET_CARDINFO:
+		if ((retval = copy_from_user((void *) &gdef, data,
+					 sizeof(avmb1_getdef))))
+			return retval;
+
+		if (!VALID_CARD(gdef.contr))
+			return -ESRCH;
+
+		card = CARD(gdef.contr);
+
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+
+		gdef.cardstate = card->cardstate;
+		if (card->driver == b1isa_driver)
+			gdef.cardtype = AVM_CARDTYPE_B1;
+		else if (card->driver == t1isa_driver)
+			gdef.cardtype = AVM_CARDTYPE_T1;
+		else gdef.cardtype = AVM_CARDTYPE_B1;
+
+		if ((retval = copy_to_user(data, (void *) &gdef,
+					 sizeof(avmb1_getdef))))
+			return retval;
+
+		return 0;
+
+	case AVMB1_REMOVECARD:
+		if ((retval = copy_from_user((void *) &rdef, data,
+					 sizeof(avmb1_resetdef))))
+			return retval;
+
+		if (!VALID_CARD(rdef.contr))
+			return -ESRCH;
+		card = CARD(rdef.contr);
+
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+
+		if (card->cardstate != CARD_DETECTED)
+			return -EBUSY;
+
+		card->driver->remove_ctr(card);
+
+		while (card->cardstate != CARD_FREE) {
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(HZ/10);	/* 0.1 sec */
+
+			if (signal_pending(current))
+				return -EINTR;
+		}
+		return 0;
+	}
+	return -EINVAL;
+}
+#endif
+
+static int capi_manufacturer(unsigned int cmd, void *data)
+{
+        struct capi_ctr *card;
+	kcapi_flagdef fdef;
+	int retval;
+
+	switch (cmd) {
+#ifdef CONFIG_AVMB1_COMPAT
+	case AVMB1_ADDCARD:
+	case AVMB1_ADDCARD_WITH_TYPE:
+	case AVMB1_LOAD:
+	case AVMB1_LOAD_AND_CONFIG:
+	case AVMB1_RESETCARD:
+	case AVMB1_GET_CARDINFO:
+	case AVMB1_REMOVECARD:
+		return old_capi_manufacturer(cmd, data);
+#endif
+	case KCAPI_CMD_TRACE:
+		if ((retval = copy_from_user((void *) &fdef, data,
+					 sizeof(kcapi_flagdef))))
+			return retval;
+
+		if (!VALID_CARD(fdef.contr))
+			return -ESRCH;
+		card = CARD(fdef.contr);
+		if (card->cardstate == CARD_FREE)
+			return -ESRCH;
+		card->traceflag = fdef.flag;
+		printk(KERN_INFO "kcapi: contr %d set trace=%d\n",
+			card->cnr, card->traceflag);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct capi_interface avmb1_interface =
+{
+	capi_installed,
+	capi_register,
+	capi_release,
+	capi_put_message,
+	capi_get_message,
+	capi_set_signal,
+	capi_get_manufacturer,
+	capi_get_version,
+	capi_get_serial,
+	capi_get_profile,
+	capi_manufacturer
+};
+
+/* ------------------------------------------------------------- */
+/* -------- Exported Functions --------------------------------- */
+/* ------------------------------------------------------------- */
+
+struct capi_interface *attach_capi_interface(struct capi_interface_user *userp)
+{
+	struct capi_interface_user *p;
+
+	for (p = capi_users; p; p = p->next) {
+		if (p == userp) {
+			printk(KERN_ERR "kcapi: double attach from %s\n",
+			       userp->name);
+			return 0;
+		}
+	}
+	userp->next = capi_users;
+	capi_users = userp;
+	MOD_INC_USE_COUNT;
+	printk(KERN_NOTICE "kcapi: %s attached\n", userp->name);
+
+	return &avmb1_interface;
+}
+
+int detach_capi_interface(struct capi_interface_user *userp)
+{
+	struct capi_interface_user **pp;
+
+	for (pp = &capi_users; *pp; pp = &(*pp)->next) {
+		if (*pp == userp) {
+			*pp = userp->next;
+			userp->next = 0;
+			MOD_DEC_USE_COUNT;
+			printk(KERN_NOTICE "kcapi: %s detached\n", userp->name);
+			return 0;
+		}
+	}
+	printk(KERN_ERR "kcapi: double detach from %s\n", userp->name);
+	return -1;
+}
+
+/* ------------------------------------------------------------- */
+/* -------- Init & Cleanup ------------------------------------- */
+/* ------------------------------------------------------------- */
+
+EXPORT_SYMBOL(attach_capi_interface);
+EXPORT_SYMBOL(detach_capi_interface);
+EXPORT_SYMBOL(attach_capi_driver);
+EXPORT_SYMBOL(detach_capi_driver);
+
+/*
+ * init / exit functions
+ */
+
+#ifdef MODULE
+#define kcapi_init init_module
+#endif
+
+int kcapi_init(void)
+{
+	char *p;
+	char rev[10];
+
+	skb_queue_head_init(&recv_queue);
+	/* init_bh(CAPI_BH, do_capi_bh); */
+
+	tq_state_notify.routine = notify_handler;
+	tq_state_notify.data = 0;
+
+	tq_recv_notify.routine = recv_handler;
+	tq_recv_notify.data = 0;
+
+        proc_capi_init();
+
+	if ((p = strchr(revision, ':'))) {
+		strcpy(rev, p + 1);
+		p = strchr(rev, '$');
+		*p = 0;
+	} else
+		strcpy(rev, "1.0");
+
+#ifdef MODULE
+        printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev);
+#else
+	printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev);
+#endif
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	char rev[10];
+	char *p;
+
+	if ((p = strchr(revision, ':'))) {
+		strcpy(rev, p + 1);
+		p = strchr(rev, '$');
+		*p = 0;
+	} else {
+		strcpy(rev, "1.0");
+	}
+
+	schedule(); /* execute queued tasks .... */
+        proc_capi_exit();
+	printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/avmb1/t1isa.c linux.pre11.3/drivers/isdn/avmb1/t1isa.c
--- linux.vanilla/drivers/isdn/avmb1/t1isa.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/avmb1/t1isa.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,545 @@
+/*
+ * $Id: t1isa.c,v 1.4 1999/07/09 15:05:50 keil Exp $
+ * 
+ * Module for AVM T1 HEMA-card.
+ * 
+ * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: t1isa.c,v $
+ * Revision 1.4  1999/07/09 15:05:50  keil
+ * compat.h is now isdn_compat.h
+ *
+ * Revision 1.3  1999/07/06 07:42:04  calle
+ * - changes in /proc interface
+ * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb.
+ *
+ * Revision 1.2  1999/07/05 15:09:54  calle
+ * - renamed "appl_release" to "appl_released".
+ * - version und profile data now cleared on controller reset
+ * - extended /proc interface, to allow driver and controller specific
+ *   informations to include by driver hackers.
+ *
+ * Revision 1.1  1999/07/01 15:26:44  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <linux/isdn_compat.h>
+#include "capicmd.h"
+#include "capiutil.h"
+#include "capilli.h"
+#include "avmcard.h"
+
+static char *revision = "$Revision: 1.4 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
+static int hema_irq_table[16] =
+{0,
+ 0,
+ 0,
+ 0x80,				/* irq 3 */
+ 0,
+ 0x90,				/* irq 5 */
+ 0,
+ 0xA0,				/* irq 7 */
+ 0,
+ 0xB0,				/* irq 9 */
+ 0xC0,				/* irq 10 */
+ 0xD0,				/* irq 11 */
+ 0xE0,				/* irq 12 */
+ 0,
+ 0,
+ 0xF0,				/* irq 15 */
+};
+
+static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
+{
+	unsigned char cregs[8];
+	unsigned char reverse_cardnr;
+	unsigned long flags;
+	unsigned char dummy;
+	int i;
+
+	reverse_cardnr =   ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1)
+		         | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3);
+	cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf);
+	cregs[1] = 0x00; /* fast & slow link connected to CON1 */
+	cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */
+	cregs[3] = 0;
+	cregs[4] = 0x11; /* zero wait state */
+	cregs[5] = hema_irq_table[irq & 0xf];
+	cregs[6] = 0;
+	cregs[7] = 0;
+
+	save_flags(flags);
+	cli();
+	/* board reset */
+	t1outp(base, T1_RESETBOARD, 0xf);
+	udelay(100 * 1000);
+	dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
+
+	/* write config */
+	dummy = (base >> 4) & 0xff;
+	for (i=1;i<=0xf;i++) t1outp(base, i, dummy);
+	t1outp(base, HEMA_PAL_ID & 0xf, dummy);
+	t1outp(base, HEMA_PAL_ID >> 4, cregs[0]);
+	for(i=1;i<7;i++) t1outp(base, 0, cregs[i]);
+	t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
+	restore_flags(flags);
+
+	udelay(100 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+	udelay(10 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
+	udelay(100 * 1000);
+	t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
+	t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
+	udelay(10 * 1000);
+	t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
+	udelay(5 * 1000);
+	t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
+
+	if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+		return 1;
+	if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */
+		return 2;
+	if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0)
+		return 3;
+	if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70)
+		return 4;
+	if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0)
+		return 5;
+	if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1)
+		return 6;
+	if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */
+		return 7;
+	if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0)
+		return 8;
+	if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0)
+		return 9;
+        return 0;
+}
+
+static void t1_handle_interrupt(avmcard * card)
+{
+	struct capi_ctr *ctrl = card->ctrl;
+	unsigned char b1cmd;
+	struct sk_buff *skb;
+
+	unsigned ApplId;
+	unsigned MsgLen;
+	unsigned DataB3Len;
+	unsigned NCCI;
+	unsigned WindowSize;
+
+	while (b1_rx_full(card->port)) {
+
+		b1cmd = b1_get_byte(card->port);
+
+		switch (b1cmd) {
+
+		case RECEIVE_DATA_B3_IND:
+
+			ApplId = (unsigned) b1_get_word(card->port);
+			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			DataB3Len = t1_get_slice(card->port, card->databuf);
+
+			if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
+				printk(KERN_ERR "t1isa: incoming packet dropped\n");
+			} else {
+				memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+				memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
+				CAPIMSG_SETDATA(skb->data, skb->data + MsgLen);
+				ctrl->handle_capimsg(ctrl, ApplId, skb);
+			}
+			break;
+
+		case RECEIVE_MESSAGE:
+
+			ApplId = (unsigned) b1_get_word(card->port);
+			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+				printk(KERN_ERR "t1isa: incoming packet dropped\n");
+			} else {
+				memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+				ctrl->handle_capimsg(ctrl, ApplId, skb);
+			}
+			break;
+
+		case RECEIVE_NEW_NCCI:
+
+			ApplId = b1_get_word(card->port);
+			NCCI = b1_get_word(card->port);
+			WindowSize = b1_get_word(card->port);
+
+			ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+			break;
+
+		case RECEIVE_FREE_NCCI:
+
+			ApplId = b1_get_word(card->port);
+			NCCI = b1_get_word(card->port);
+
+			if (NCCI != 0xffffffff)
+				ctrl->free_ncci(ctrl, ApplId, NCCI);
+			else ctrl->appl_released(ctrl, ApplId);
+			break;
+
+		case RECEIVE_START:
+			b1_put_byte(card->port, SEND_POLLACK);
+			ctrl->resume_output(ctrl);
+			break;
+
+		case RECEIVE_STOP:
+			ctrl->suspend_output(ctrl);
+			break;
+
+		case RECEIVE_INIT:
+
+			card->versionlen = t1_get_slice(card->port, card->versionbuf);
+			b1_parse_version(card);
+			printk(KERN_INFO "%s: %s-card (%s) now active\n",
+			       card->name,
+			       card->version[VER_CARDTYPE],
+			       card->version[VER_DRIVER]);
+			ctrl->ready(ctrl);
+			break;
+
+		case RECEIVE_TASK_READY:
+			ApplId = (unsigned) b1_get_word(card->port);
+			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			card->msgbuf[MsgLen--] = 0;
+			while (    MsgLen >= 0
+			       && (   card->msgbuf[MsgLen] == '\n'
+				   || card->msgbuf[MsgLen] == '\r'))
+				card->msgbuf[MsgLen--] = 0;
+			printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
+					card->name, ApplId, card->msgbuf);
+			break;
+
+		case RECEIVE_DEBUGMSG:
+			MsgLen = t1_get_slice(card->port, card->msgbuf);
+			card->msgbuf[MsgLen--] = 0;
+			while (    MsgLen >= 0
+			       && (   card->msgbuf[MsgLen] == '\n'
+				   || card->msgbuf[MsgLen] == '\r'))
+				card->msgbuf[MsgLen--] = 0;
+			printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
+			break;
+
+		case 0xff:
+			printk(KERN_ERR "%s: card reseted ?\n", card->name);
+			return;
+		default:
+			printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n",
+					card->name, b1cmd);
+			return;
+		}
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "t1_interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "t1_interrupt: reentering interrupt hander (%s)\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	t1_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+/* ------------------------------------------------------------- */
+
+static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	int retval;
+
+	t1_disable_irq(port);
+	b1_reset(port);
+
+	if ((retval = b1_load_t4file(port, &data->firmware))) {
+		b1_reset(port);
+		printk(KERN_ERR "%s: failed to load t4file!!\n",
+					card->name);
+		return retval;
+	}
+
+	if (data->configuration.len > 0 && data->configuration.data) {
+		if ((retval = b1_load_config(port, &data->configuration))) {
+			b1_reset(port);
+			printk(KERN_ERR "%s: failed to load config!!\n",
+					card->name);
+			return retval;
+		}
+	}
+
+	if (!b1_loaded(port)) {
+		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
+		return -EIO;
+	}
+
+	save_flags(flags);
+	cli();
+	b1_setinterrupt(port, card->irq, card->cardtype);
+	b1_put_byte(port, SEND_INIT);
+	b1_put_word(port, AVM_NAPPS);
+	b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
+	b1_put_word(port, ctrl->cnr - 1);
+	restore_flags(flags);
+
+	return 0;
+}
+
+void t1isa_reset_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	t1_disable_irq(port);
+	b1_reset(port);
+	b1_reset(port);
+
+	memset(card->version, 0, sizeof(card->version));
+	ctrl->reseted(ctrl);
+}
+
+static void t1isa_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+
+	t1_disable_irq(port);
+	b1_reset(port);
+	b1_reset(port);
+	t1_reset(port);
+
+	di->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	release_region(card->port, AVMB1_PORTLEN);
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+/* ------------------------------------------------------------- */
+
+static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	struct capi_ctr *ctrl;
+	avmcard *card;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "t1isa: no memory.\n");
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	sprintf(card->name, "t1isa-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->cardtype = avm_t1isa;
+	card->cardnr = p->cardnr;
+
+	if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) {
+		printk(KERN_WARNING "t1isa: illegal port 0x%x.\n", card->port);
+		kfree(card);
+		return -EINVAL;
+        }
+
+	if (check_region(card->port, AVMB1_PORTLEN)) {
+		printk(KERN_WARNING
+		       "t1isa: ports 0x%03x-0x%03x in use.\n",
+		       card->port, card->port + AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+	if (hema_irq_table[card->irq & 0xf] == 0) {
+		printk(KERN_WARNING "t1isa: irq %d not valid.\n", card->irq);
+		kfree(card);
+		return -EINVAL;
+	}
+	for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
+		if (((avmcard *)(ctrl->driverdata))->cardnr == card->cardnr) {
+			printk(KERN_WARNING "t1isa: card with number %d already installed.\n", card->cardnr);
+			kfree(card);
+			return -EBUSY;
+		}
+	}
+        if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) {
+		printk(KERN_NOTICE "t1isa: NO card at 0x%x (%d)\n",
+					card->port, retval);
+		kfree(card);
+		return -EIO;
+	}
+	t1_disable_irq(card->port);
+	b1_reset(card->port);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "t1isa: unable to get IRQ %d.\n", card->irq);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	card->ctrl = di->attach_ctr(driver, card->name, card);
+	if (!card->ctrl) {
+		printk(KERN_ERR "t1isa: attach controller failed.\n");
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	unsigned int port = card->port;
+	unsigned long flags;
+	__u16 len = CAPIMSG_LEN(skb->data);
+	__u8 cmd = CAPIMSG_COMMAND(skb->data);
+	__u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+	save_flags(flags);
+	cli();
+	if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+		__u16 dlen = CAPIMSG_DATALEN(skb->data);
+		b1_put_byte(port, SEND_DATA_B3_REQ);
+		t1_put_slice(port, skb->data, len);
+		t1_put_slice(port, skb->data + len, dlen);
+	} else {
+		b1_put_byte(port, SEND_MESSAGE);
+		t1_put_slice(port, skb->data, len);
+	}
+	restore_flags(flags);
+	dev_kfree_skb(skb);
+}
+/* ------------------------------------------------------------- */
+
+static char *t1isa_procinfo(struct capi_ctr *ctrl)
+{
+	avmcard *card = (avmcard *)(ctrl->driverdata);
+	if (!card)
+		return "";
+	sprintf(card->infobuf, "%s %s 0x%x %d %d",
+		card->cardname[0] ? card->cardname : "-",
+		card->version[VER_DRIVER] ? card->version[VER_DRIVER] : "-",
+		card->port, card->irq, card->cardnr
+		);
+	return card->infobuf;
+}
+
+
+/* ------------------------------------------------------------- */
+
+static struct capi_driver t1isa_driver = {
+    "t1isa",
+    "0.0",
+    t1isa_load_firmware,
+    t1isa_reset_ctr,
+    t1isa_remove_ctr,
+    b1_register_appl,
+    b1_release_appl,
+    t1isa_send_message,
+
+    t1isa_procinfo,
+    b1ctl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    t1isa_add_card,
+};
+
+#ifdef MODULE
+#define t1isa_init init_module
+void cleanup_module(void);
+#endif
+
+int t1isa_init(void)
+{
+	struct capi_driver *driver = &t1isa_driver;
+	char *p;
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(driver->revision, p + 1, sizeof(driver->revision));
+		p = strchr(driver->revision, '$');
+		*p = 0;
+	}
+
+	printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
+
+        di = attach_capi_driver(driver);
+
+	if (!di) {
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driver->name);
+		return -EIO;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+    detach_capi_driver(&t1isa_driver);
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/Makefile linux.pre11.3/drivers/isdn/divert/Makefile
--- linux.vanilla/drivers/isdn/divert/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/divert/Makefile	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,21 @@
+L_OBJS :=
+LX_OBJS :=
+M_OBJS :=
+MX_OBJS :=
+O_OBJS :=
+OX_OBJS :=
+L_TARGET :=
+O_TARGET :=
+
+O_OBJS += isdn_divert.o divert_procfs.o
+O_TARGET := dss1_divert.o
+M_OBJS += dss1_divert.o
+OX_OBJS += divert_init.o
+
+include $(TOPDIR)/Rules.make
+
+
+
+
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/divert_init.c linux.pre11.3/drivers/isdn/divert/divert_init.c
--- linux.vanilla/drivers/isdn/divert/divert_init.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/divert/divert_init.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,105 @@
+/* 
+ * $Id: divert_init.c,v 1.3 1999/07/05 20:21:39 werner Exp $
+ *
+ * Module init for DSS1 diversion services for i4l.
+ *
+ * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: divert_init.c,v $
+ * Revision 1.3  1999/07/05 20:21:39  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2  1999/07/04 21:37:30  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include "isdn_divert.h"
+
+/********************/
+/* needed externals */
+/********************/
+extern int printk(const char *fmt,...);
+
+/****************************************/
+/* structure containing interface to hl */
+/****************************************/
+isdn_divert_if divert_if =
+  { DIVERT_IF_MAGIC,  /* magic value */
+    DIVERT_CMD_REG,   /* register cmd */
+    ll_callback,      /* callback routine from ll */
+    NULL,             /* command still not specified */
+    NULL,             /* drv_to_name */
+    NULL,             /* name_to_drv */
+  };
+
+/*************************/
+/* Module interface code */
+/* no cmd line parms     */
+/*************************/
+int init_module(void)
+{ int i;
+
+  if (divert_dev_init())
+   { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
+     return(-EIO);
+   }
+  if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
+   { divert_dev_deinit();
+     printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i);
+     return(-EIO);
+   } 
+#if (LINUX_VERSION_CODE < 0x020111)
+  register_symtab(0);
+#endif
+  printk(KERN_INFO "dss1_divert module successfully installed\n");
+  return(0);
+} /* init_module */
+
+/**********************/
+/* Module deinit code */
+/**********************/
+void cleanup_module(void)
+{ int flags;
+  int i;
+
+  save_flags(flags);
+  cli();
+  divert_if.cmd = DIVERT_CMD_REL; /* release */
+  if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR)
+   { printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i);
+     restore_flags(flags);
+     return;
+   } 
+  if (divert_dev_deinit()) 
+   { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
+     restore_flags(flags);
+     return;
+   }
+  restore_flags(flags);
+  deleterule(-1); /* delete all rules and free mem */
+  deleteprocs();
+  printk(KERN_INFO "dss1_divert module successfully removed \n");
+} /* cleanup_module */
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/divert_procfs.c linux.pre11.3/drivers/isdn/divert/divert_procfs.c
--- linux.vanilla/drivers/isdn/divert/divert_procfs.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/divert/divert_procfs.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,444 @@
+/* 
+ * $Id: divert_procfs.c,v 1.3 1999/07/05 20:21:41 werner Exp $
+ *
+ * Filesystem handling for the diversion supplementary services.
+ *
+ * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: divert_procfs.c,v $
+ * Revision 1.3  1999/07/05 20:21:41  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2  1999/07/04 21:37:31  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE >= 0x020117) 
+#include <linux/poll.h>
+#endif
+#ifdef CONFIG_PROC_FS
+  #include <linux/proc_fs.h>
+#else
+  #include <linux/fs.h>
+#endif
+#include <linux/isdnif.h>
+#include "isdn_divert.h"
+
+/*********************************/
+/* Variables for interface queue */
+/*********************************/
+ulong if_used = 0; /* number of interface users */
+static struct divert_info *divert_info_head = NULL; /* head of queue */
+static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
+static struct wait_queue *rd_queue = 0; /* Queue IO */
+
+/*********************************/
+/* put an info buffer into queue */
+/*********************************/
+void put_info_buffer(char *cp)
+{ struct divert_info *ib;
+  int flags; 
+  
+  if (if_used <= 0) return;
+  if (!cp) return;
+  if (!*cp) return; 
+  if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info)+strlen(cp), GFP_ATOMIC))) return; /* no memory */
+  strcpy(ib->info_start,cp); /* set output string */
+  ib->next = NULL;
+  save_flags(flags);
+  cli();
+  ib->usage_cnt = if_used; 
+  if (!divert_info_head) 
+    divert_info_head = ib; /* new head */
+  else
+    divert_info_tail->next = ib; /* follows existing messages */
+  divert_info_tail = ib; /* new tail */   
+  restore_flags(flags);
+
+  /* delete old entrys */
+  while (divert_info_head->next)
+   { if ((divert_info_head->usage_cnt <= 0) &&
+         (divert_info_head->next->usage_cnt <= 0))
+       { ib = divert_info_head;
+         divert_info_head = divert_info_head->next;
+         kfree(ib);
+       }
+     else break;
+   } /* divert_info_head->next */  
+  wake_up_interruptible(&(rd_queue));
+} /* put_info_buffer */
+
+/**********************************/
+/* deflection device read routine */
+/**********************************/
+#if (LINUX_VERSION_CODE < 0x020117)
+static int isdn_divert_read(struct inode *inode, struct file *file, char *buf, RWARG count)
+#else
+static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off)
+#endif
+{ struct divert_info *inf;
+  int len;
+	
+  if (!*((struct divert_info **)file->private_data))
+    { if (file->f_flags & O_NONBLOCK)
+	return -EAGAIN;
+      interruptible_sleep_on(&(rd_queue));
+    }
+  if (!(inf = *((struct divert_info **)file->private_data))) return(0);
+  
+  inf->usage_cnt--; /* new usage count */
+  (struct divert_info **)file->private_data = &inf->next; /* next structure */
+  if ((len = strlen(inf->info_start)) <= count) 
+    { if (copy_to_user(buf, inf->info_start, len))
+	return -EFAULT;
+      file->f_pos += len;
+      return(len);
+    }
+  return(0);
+} /* isdn_divert_read */
+
+/**********************************/
+/* deflection device write routine */
+/**********************************/
+#if (LINUX_VERSION_CODE < 0x020117)
+static int isdn_divert_write(struct inode *inode, struct file *file, const char *buf, RWARG count)
+#else
+static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off)
+#endif
+{
+  return(-ENODEV);
+} /* isdn_divert_write */
+
+
+/***************************************/
+/* select routines for various kernels */
+/***************************************/
+#if (LINUX_VERSION_CODE < 0x020117)
+static int isdn_divert_select(struct inode *inode, struct file *file, int type, select_table * st)
+{
+  if (*((struct divert_info **)file->private_data))
+    return 1;
+  else 
+    { if (st) select_wait(&(rd_queue), st);
+      return 0;
+    }
+} /* isdn_divert_select */
+#else
+static unsigned int isdn_divert_poll(struct file *file, poll_table * wait)
+{ unsigned int mask = 0;
+
+  poll_wait(file, &(rd_queue), wait);
+  /* mask = POLLOUT | POLLWRNORM; */
+  if (*((struct divert_info **)file->private_data)) 
+    { mask |= POLLIN | POLLRDNORM;
+    }
+  return mask;
+} /* isdn_divert_poll */
+#endif
+
+/****************/
+/* Open routine */
+/****************/
+static int isdn_divert_open(struct inode *ino, struct file *filep)
+{ int flags;
+
+  MOD_INC_USE_COUNT;
+  save_flags(flags);
+  cli();
+  if_used++;
+  if (divert_info_head)
+    (struct divert_info **)filep->private_data = &(divert_info_tail->next);
+   else
+    (struct divert_info **)filep->private_data = &divert_info_head; 
+  restore_flags(flags);
+  /*  start_divert(); */
+  return(0);
+} /* isdn_divert_open */
+
+/*******************/
+/* close routine   */
+/*******************/
+#if (LINUX_VERSION_CODE < 0x020117)
+static void isdn_divert_close(struct inode *ino, struct file *filep)
+#else
+static int isdn_divert_close(struct inode *ino, struct file *filep)
+#endif
+{ struct divert_info *inf; 
+  int flags;
+
+  save_flags(flags);
+  cli();
+  if_used--;
+  inf = *((struct divert_info **)filep->private_data);
+  while (inf)
+   { inf->usage_cnt--;
+     inf = inf->next;
+   } 
+  restore_flags(flags);
+  if (if_used <= 0)
+   while (divert_info_head)
+    { inf = divert_info_head;
+      divert_info_head = divert_info_head->next;
+      kfree(inf);
+    }
+  MOD_DEC_USE_COUNT;
+#if (LINUX_VERSION_CODE < 0x020117)
+#else
+  return(0);
+#endif
+} /* isdn_divert_close */
+
+/*********/
+/* IOCTL */
+/*********/
+static int isdn_divert_ioctl(struct inode *inode, struct file *file, 
+                             uint cmd, ulong arg)
+{ divert_ioctl dioctl;
+  int i, flags;
+  divert_rule *rulep;
+  char *cp;
+
+  if ((i = copy_from_user(&dioctl,(char *) arg, sizeof(dioctl))))
+    return(i); 
+ 
+  switch (cmd)
+   { 
+     case IIOCGETVER:
+       dioctl.drv_version = DIVERT_IIOC_VERSION ; /* set version */
+       break;
+
+     case IIOCGETDRV:
+       if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
+         return(-EINVAL);  
+       break;
+
+     case IIOCGETNAM:
+       cp = divert_if.drv_to_name(dioctl.getid.drvid);
+       if (!cp) return(-EINVAL);
+       if (!*cp) return(-EINVAL);
+       strcpy(dioctl.getid.drvnam,cp);  
+       break;
+
+     case IIOCGETRULE:
+       if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+         return(-EINVAL);  
+       dioctl.getsetrule.rule = *rulep; /* copy data */
+       break;
+
+     case IIOCMODRULE:
+       if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+         return(-EINVAL);  
+       save_flags(flags);
+       cli();
+       *rulep = dioctl.getsetrule.rule; /* copy data */
+       restore_flags(flags);
+       return(0); /* no copy required */
+       break;
+
+     case IIOCINSRULE:
+       return(insertrule(dioctl.getsetrule.ruleidx,&dioctl.getsetrule.rule));
+       break;
+
+     case IIOCDELRULE:
+       return(deleterule(dioctl.getsetrule.ruleidx));
+       break;
+
+     case IIOCDODFACT:
+       return(deflect_extern_action(dioctl.fwd_ctrl.subcmd,
+                                    dioctl.fwd_ctrl.callid,
+                                    dioctl.fwd_ctrl.to_nr)); 
+
+     case  IIOCDOCFACT:
+     case  IIOCDOCFDIS:
+     case  IIOCDOCFINT:
+       if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) 
+         return(-EINVAL); /* invalid driver */
+       if ((i = cf_command(dioctl.cf_ctrl.drvid,
+                          (cmd == IIOCDOCFACT) ? 1: (cmd == IIOCDOCFDIS) ? 0:2,
+                          dioctl.cf_ctrl.cfproc,
+                          dioctl.cf_ctrl.msn,  
+                          dioctl.cf_ctrl.service,
+                          dioctl.cf_ctrl.fwd_nr,
+                          &dioctl.cf_ctrl.procid)))
+         return(i);    
+       break;
+   
+     default: 
+       return(-EINVAL);
+   } /* switch cmd */
+  return(copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */
+} /* isdn_divert_ioctl */
+
+
+#ifdef CONFIG_PROC_FS
+#if (LINUX_VERSION_CODE < 0x020117)
+static LSTYPE
+isdn_divert_lseek(struct inode *inode, struct file *file, LSARG offset, int orig)
+#else
+static loff_t
+isdn_divert_lseek(struct file *file, loff_t offset, int orig)
+#endif
+{
+	return -ESPIPE;
+}
+
+#if (LINUX_VERSION_CODE < 0x020117)
+static struct file_operations isdn_fops =
+{
+	isdn_divert_lseek,
+	isdn_divert_read,
+	isdn_divert_write,
+	NULL,                          /* isdn_readdir */
+	isdn_divert_select,            /* isdn_select */
+	isdn_divert_ioctl,             /* isdn_ioctl */
+	NULL,                          /* isdn_mmap */
+	isdn_divert_open,
+	isdn_divert_close,
+	NULL                           /* fsync */
+};
+
+#else
+
+static struct file_operations isdn_fops =
+{
+	isdn_divert_lseek,
+	isdn_divert_read,
+	isdn_divert_write,
+	NULL,                          /* isdn_readdir */
+	isdn_divert_poll,              /* isdn_poll */
+	isdn_divert_ioctl,             /* isdn_ioctl */
+	NULL,                          /* isdn_mmap */
+	isdn_divert_open,
+	NULL,                          /* flush */ 
+	isdn_divert_close,
+	NULL                           /* fsync */
+};
+#endif  /* kernel >= 2.1 */
+
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_isdn_inode_ops = {
+	&isdn_fops,	        /* isdn divert special file-ops */
+	NULL,			/* create */
+	NULL,  		        /* 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 */
+};
+
+/****************************/
+/* isdn subdir in /proc/net */
+/****************************/
+static struct proc_dir_entry isdn_proc_entry = 
+  { 0, 4, "isdn", S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0, 0, 
+    &proc_dir_inode_operations,NULL,NULL,NULL,NULL,NULL
+  };
+
+static struct proc_dir_entry isdn_divert_entry =
+{ 0, 6, "divert",S_IFREG | S_IRUGO, 1, 0, 0, 0, &proc_isdn_inode_ops,
+   NULL
+  }; 
+
+/*****************************************************************/
+/* variables used for automatic determining existence of proc fs */
+/*****************************************************************/
+static int (*proc_reg_dynamic)(struct proc_dir_entry *, struct proc_dir_entry *) = NULL;
+static int (*proc_unreg)(struct proc_dir_entry *, int) = NULL;
+
+#endif CONFIG_PROC_FS
+
+/***************************************************************************/
+/* divert_dev_init must be called before the proc filesystem may be used   */
+/***************************************************************************/
+int divert_dev_init(void)
+{ int i;
+
+#ifdef CONFIG_PROC_FS
+#if (LINUX_VERSION_CODE < 0x020117)
+  (void *) proc_reg_dynamic = get_module_symbol("","proc_register_dynamic");
+  (void *) proc_unreg = get_module_symbol("","proc_unregister");
+  if (proc_unreg)
+   { i = proc_reg_dynamic(&proc_net,&isdn_proc_entry);  
+     if (i) return(i);
+     i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry);
+     if (i) 
+      { proc_unreg(&proc_net,isdn_proc_entry.low_ino);
+        return(i);
+      }
+   } /* proc exists */
+#else
+  (void *) proc_reg_dynamic = get_module_symbol("","proc_register");
+  (void *) proc_unreg = get_module_symbol("","proc_unregister");
+  if (proc_unreg)
+   { i = proc_reg_dynamic(proc_net,&isdn_proc_entry);  
+     if (i) return(i);
+     i = proc_reg_dynamic(&isdn_proc_entry,&isdn_divert_entry);
+     if (i) 
+      { proc_unreg(proc_net,isdn_proc_entry.low_ino);
+        return(i);
+      }
+   } /* proc exists */
+#endif
+#endif CONFIG_PROC_FS
+
+  return(0);
+} /* divert_dev_init */
+
+/***************************************************************************/
+/* divert_dev_deinit must be called before leaving isdn when included as   */
+/* a module.                                                               */
+/***************************************************************************/
+int divert_dev_deinit(void)
+{ int i;
+
+#ifdef CONFIG_PROC_FS
+  if (proc_unreg)
+   { i = proc_unreg(&isdn_proc_entry,isdn_divert_entry.low_ino);
+     if (i) return(i);
+#if (LINUX_VERSION_CODE < 0x020117)
+     i = proc_unreg(&proc_net,isdn_proc_entry.low_ino);  
+#else
+     i = proc_unreg(proc_net,isdn_proc_entry.low_ino);  
+#endif
+     if (i) return(i);
+   } /* proc exists */
+#endif CONFIG_PROC_FS
+
+  return(0);
+} /* divert_dev_deinit */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/isdn_divert.c linux.pre11.3/drivers/isdn/divert/isdn_divert.c
--- linux.vanilla/drivers/isdn/divert/isdn_divert.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/divert/isdn_divert.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,902 @@
+/* 
+ * $Id: isdn_divert.c,v 1.2 1999/07/04 21:37:32 werner Exp $
+ *
+ * DSS1 main diversion supplementary handling for i4l.
+ *
+ * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_divert.c,v $
+ * Revision 1.2  1999/07/04 21:37:32  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+
+
+#include <linux/config.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include "isdn_divert.h"
+
+/**********************************/
+/* structure keeping calling info */
+/**********************************/
+struct call_struc
+  { isdn_ctrl ics; /* delivered setup + driver parameters */
+    ulong divert_id; /* Id delivered to user */
+    unsigned char akt_state; /* actual state */
+    char deflect_dest[35]; /* deflection destination */   
+    struct timer_list timer; /* timer control structure */
+    char info[90]; /* device info output */ 
+    struct call_struc *next; /* pointer to next entry */
+    struct call_struc *prev;
+  };
+
+
+/********************************************/
+/* structure keeping deflection table entry */
+/********************************************/
+struct deflect_struc
+  { struct deflect_struc *next,*prev; 
+    divert_rule rule; /* used rule */
+  };
+
+
+/*****************************************/
+/* variables for main diversion services */
+/*****************************************/
+/* diversion/deflection processes */
+static struct call_struc *divert_head = NULL; /* head of remembered entrys */
+static ulong next_id = 1; /* next info id */   
+static struct deflect_struc *table_head = NULL;
+static struct deflect_struc *table_tail = NULL; 
+static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ 
+
+/***************************/
+/* timer callback function */
+/***************************/
+static void deflect_timer_expire(ulong arg)
+{ int flags;
+  struct call_struc *cs = (struct call_struc *) arg;
+
+  save_flags(flags);
+  cli();
+  del_timer(&cs->timer); /* delete active timer */
+  restore_flags(flags);
+
+  switch(cs->akt_state)
+   { case DEFLECT_PROCEED:
+       cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
+       divert_if.ll_cmd(&cs->ics);                   	  
+       save_flags(flags);
+       cli();
+       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+       add_timer(&cs->timer);
+       restore_flags(flags); 
+       break;
+
+     case DEFLECT_ALERT:
+       cs->ics.command = ISDN_CMD_REDIR; /* protocol */
+       strcpy(cs->ics.parm.setup.phone,cs->deflect_dest);
+       strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed");
+       divert_if.ll_cmd(&cs->ics);                   	  
+       save_flags(flags);
+       cli();
+       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+       add_timer(&cs->timer);
+       restore_flags(flags); 
+       break;
+
+     case DEFLECT_AUTODEL:
+     default:
+       save_flags(flags);
+       cli();
+       if (cs->prev) 
+         cs->prev->next = cs->next; /* forward link */
+        else
+         divert_head = cs->next;
+       if (cs->next)
+         cs->next->prev = cs->prev; /* back link */           
+       restore_flags(flags); 
+       kfree(cs);
+       return;
+
+   } /* switch */
+} /* deflect_timer_func */
+
+
+/*****************************************/
+/* handle call forwarding de/activations */
+/* 0 = deact, 1 = act, 2 = interrogate   */
+/*****************************************/
+int cf_command(int drvid, int mode, 
+               u_char proc, char *msn, 
+               u_char service, char *fwd_nr, ulong *procid)
+{ int retval,msnlen,flags;
+  int fwd_len;
+  char *p,*ielenp,tmp[60];
+  struct call_struc *cs;
+
+  if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */
+  if ((proc & 0x7F) > 2) return(-EINVAL);
+  proc &= 3;
+  p = tmp;
+  *p++ = 0x30; /* enumeration */
+  ielenp = p++; /* remember total length position */
+  *p++ = 0xa; /* proc tag */
+  *p++ = 1;   /* length */
+  *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */
+  *p++ = 0xa; /* service tag */
+  *p++ = 1;   /* length */
+  *p++ = service; /* service to handle */
+
+  if (mode == 1) 
+   { if (!*fwd_nr) return(-EINVAL); /* destination missing */
+     if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */
+     fwd_len = strlen(fwd_nr);
+     *p++ = 0x30; /* number enumeration */
+     *p++ = fwd_len + 2; /* complete forward to len */ 
+     *p++ = 0x80; /* fwd to nr */
+     *p++ = fwd_len; /* length of number */
+     strcpy(p,fwd_nr); /* copy number */
+     p += fwd_len; /* pointer beyond fwd */
+   } /* activate */
+
+  msnlen = strlen(msn);
+  *p++ = 0x80; /* msn number */
+  if (msnlen > 1)
+   { *p++ = msnlen; /* length */
+     strcpy(p,msn);
+     p += msnlen;
+   }
+  else *p++ = 0;
+
+  *ielenp = p - ielenp - 1; /* set total IE length */ 
+
+  /* allocate mem for information struct */  
+  if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) 
+             return(-ENOMEM); /* no memory */
+  init_timer(&cs->timer);
+  cs->info[0] = '\0';
+  cs->timer.function = deflect_timer_expire;
+  cs->timer.data = (ulong) cs; /* pointer to own structure */
+  cs->ics.driver = drvid;
+  cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
+  cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
+  cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */ 
+  cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */
+  cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
+  cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
+  
+  save_flags(flags);
+  cli();
+  cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
+  restore_flags(flags);
+  *procid = cs->ics.parm.dss1_io.ll_id;  
+
+  sprintf(cs->info,"%d 0x%lx %s%s 0 %s %0x %d%s%s\n",
+	  (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
+          cs->ics.parm.dss1_io.ll_id,
+          (mode != 2) ? "" : "0 ",
+          divert_if.drv_to_name(cs->ics.driver),
+          msn,
+          service & 0xFF,
+          proc,
+          (mode != 1) ? "" : " 0 ",
+          (mode != 1) ? "" : fwd_nr);
+ 
+  retval = divert_if.ll_cmd(&cs->ics); /* excute command */
+
+  if (!retval)
+   { cs->prev = NULL;
+     save_flags(flags);
+     cli();
+     cs->next = divert_head;
+     divert_head = cs; 
+     restore_flags(flags);
+   }
+  else
+   kfree(cs);
+  return(retval); 
+} /* cf_command */
+
+
+/****************************************/
+/* handle a external deflection command */
+/****************************************/
+int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
+{ struct call_struc *cs;
+  isdn_ctrl ic;
+  int flags;
+  int i;
+
+  if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */
+  cs = divert_head; /* start of parameter list */
+  while (cs)
+   { if (cs->divert_id == callid) break; /* found */
+     cs = cs->next;  
+   } /* search entry */
+  if (!cs) return(-EINVAL); /* invalid callid */
+
+  ic.driver = cs->ics.driver;
+  ic.arg = cs->ics.arg;
+  i = -EINVAL;
+  if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */
+  switch (cmd & 0x7F)
+   { case 0: /* hangup */
+       del_timer(&cs->timer); 
+       ic.command = ISDN_CMD_HANGUP;
+       i = divert_if.ll_cmd(&ic);                   	  
+       save_flags(flags);
+       cli();
+       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+       add_timer(&cs->timer);
+       restore_flags(flags); 
+     break;      
+
+     case 1: /* alert */
+       if (cs->akt_state == DEFLECT_ALERT) return(0);
+       cmd &= 0x7F; /* never wait */
+       del_timer(&cs->timer); 
+       ic.command = ISDN_CMD_ALERT;
+       if ((i = divert_if.ll_cmd(&ic)))
+	{ save_flags(flags);
+          cli();
+          cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+          cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+          add_timer(&cs->timer);
+          restore_flags(flags);
+        }
+       else
+          cs->akt_state = DEFLECT_ALERT; 
+     break;      
+
+     case 2: /* redir */
+       del_timer(&cs->timer); 
+       strcpy(cs->ics.parm.setup.phone, to_nr);
+       strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
+       ic.command = ISDN_CMD_REDIR;
+       if ((i = divert_if.ll_cmd(&ic)))
+	{ save_flags(flags);
+          cli();
+          cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+          cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+          add_timer(&cs->timer);
+          restore_flags(flags);
+        }
+       else
+          cs->akt_state = DEFLECT_ALERT; 
+     break;      
+
+   } /* switch */
+  return(i);
+} /* deflect_extern_action */
+
+/********************************/
+/* insert a new rule before idx */
+/********************************/
+int insertrule(int idx, divert_rule *newrule)
+{ struct deflect_struc *ds,*ds1;
+  int flags;
+
+  if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), 
+                                              GFP_KERNEL))) 
+    return(-ENOMEM); /* no memory */
+
+  ds->rule = *newrule; /* set rule */
+
+  save_flags(flags);
+  cli();
+
+  if (idx >= 0)
+   { ds1 = table_head;
+     while ((ds1) && (idx > 0))
+      { idx--;
+        ds1 = ds1->next;
+      } 
+     if (!ds1) idx = -1; 
+   }
+
+  if (idx < 0)
+   { ds->prev = table_tail; /* previous entry */
+     ds->next = NULL; /* end of chain */
+     if (ds->prev) 
+       ds->prev->next = ds; /* last forward */
+      else
+        table_head = ds; /* is first entry */
+     table_tail = ds; /* end of queue */
+   }
+  else
+    { ds->next = ds1; /* next entry */
+      ds->prev = ds1->prev; /* prev entry */
+      ds1->prev = ds; /* backward chain old element */
+      if (!ds->prev)
+        table_head = ds; /* first element */
+   }
+
+  restore_flags(flags);
+  return(0);
+} /* insertrule */
+
+/***********************************/
+/* delete the rule at position idx */
+/***********************************/
+int deleterule(int idx)
+{ struct deflect_struc *ds,*ds1;
+  int flags;
+  
+  if (idx < 0) 
+   { save_flags(flags);
+     cli();
+     ds = table_head;
+     table_head = NULL;
+     table_tail = NULL;
+     restore_flags(flags);
+     while (ds)
+      { ds1 = ds; 
+        ds = ds->next;
+        kfree(ds1);
+      } 
+     return(0); 
+   }
+
+  save_flags(flags);
+  cli();
+  ds = table_head;
+
+  while ((ds) && (idx > 0))
+   { idx--; 
+     ds = ds->next;  
+   }
+
+  if (!ds) 
+   { restore_flags(flags);
+     return(-EINVAL);
+   }  
+
+  if (ds->next) 
+    ds->next->prev = ds->prev; /* backward chain */
+   else
+     table_tail = ds->prev; /* end of chain */
+
+  if (ds->prev)
+    ds->prev->next = ds->next; /* forward chain */
+   else
+     table_head = ds->next; /* start of chain */      
+  
+  restore_flags(flags);
+  kfree(ds);
+  return(0);
+} /* deleterule */
+
+/*******************************************/
+/* get a pointer to a specific rule number */
+/*******************************************/
+divert_rule *getruleptr(int idx)
+{ struct deflect_struc *ds = table_head;
+  
+  if (idx < 0) return(NULL);
+  while ((ds) && (idx >= 0))
+   { if (!(idx--)) 
+      { return(&ds->rule);
+        break;
+      }
+     ds = ds->next;  
+   }
+  return(NULL);
+} /* getruleptr */
+
+/*************************************************/
+/* called from common module on an incoming call */
+/*************************************************/
+int isdn_divert_icall(isdn_ctrl *ic)
+{ int retval = 0;
+  int flags;
+  struct call_struc *cs = NULL; 
+  struct deflect_struc *dv;
+  char *p,*p1;
+  u_char accept;
+
+  /* first check the internal deflection table */
+  for (dv = table_head; dv ; dv = dv->next )
+   { /* scan table */
+     if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
+         ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
+       continue; /* call option check */  
+     if (!(dv->rule.drvid & (1L << ic->driver))) 
+       continue; /* driver not matching */ 
+     if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) 
+       continue; /* si1 not matching */
+     if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) 
+       continue; /* si2 not matching */
+
+     p = dv->rule.my_msn;
+     p1 = ic->parm.setup.eazmsn;
+     accept = 0;
+     while (*p)
+      { /* complete compare */
+        if (*p == '-')
+	  { accept = 1; /* call accepted */
+            break;
+          }
+        if (*p++ != *p1++) 
+          break; /* not accepted */
+        if ((!*p) && (!*p1))
+          accept = 1;
+      } /* complete compare */
+     if (!accept) continue; /* not accepted */
+ 
+     if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0]))
+      { p = dv->rule.caller;
+        p1 = ic->parm.setup.phone;
+        accept = 0;
+        while (*p)
+	 { /* complete compare */
+           if (*p == '-')
+	    { accept = 1; /* call accepted */
+              break;
+            }
+           if (*p++ != *p1++) 
+             break; /* not accepted */
+           if ((!*p) && (!*p1))
+             accept = 1;
+         } /* complete compare */
+        if (!accept) continue; /* not accepted */
+      }  
+
+     switch (dv->rule.action)
+       { case DEFLECT_IGNORE:
+           return(0);
+           break;
+
+         case DEFLECT_ALERT:
+         case DEFLECT_PROCEED:
+         case DEFLECT_REPORT:
+         case DEFLECT_REJECT:
+           if (dv->rule.action == DEFLECT_PROCEED)
+	    if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) 
+              return(0); /* no external deflection needed */  
+           if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) 
+             return(0); /* no memory */
+           init_timer(&cs->timer);
+           cs->info[0] = '\0';
+           cs->timer.function = deflect_timer_expire;
+           cs->timer.data = (ulong) cs; /* pointer to own structure */
+           
+           cs->ics = *ic; /* copy incoming data */
+           if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0");
+           if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0");
+	   cs->ics.parm.setup.screen = dv->rule.screen;  
+           if (dv->rule.waittime) 
+             cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
+           else
+            if (dv->rule.action == DEFLECT_PROCEED)
+              cs->timer.expires = jiffies + (HZ * extern_wait_max); 
+            else  
+              cs->timer.expires = 0;
+           cs->akt_state = dv->rule.action;                
+           save_flags(flags);
+           cli();
+           cs->divert_id = next_id++; /* new sequence number */
+           restore_flags(flags);
+           cs->prev = NULL;
+           if (cs->akt_state == DEFLECT_ALERT)
+             { strcpy(cs->deflect_dest,dv->rule.to_nr);
+               if (!cs->timer.expires)
+		 { strcpy(ic->parm.setup.eazmsn,"Testtext direkt");
+                   ic->parm.setup.screen = dv->rule.screen;
+                   strcpy(ic->parm.setup.phone,dv->rule.to_nr);
+                   cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
+                   cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
+                   retval = 4; 
+                 }
+               else
+                 retval = 1; /* alerting */                 
+             }
+           else
+             { cs->deflect_dest[0] = '\0';
+	       retval = 3; /* only proceed */
+             }  
+           sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
+                   cs->akt_state,
+                   cs->divert_id,
+                   divert_if.drv_to_name(cs->ics.driver),
+                   (ic->command == ISDN_STAT_ICALLW) ? "1":"0", 
+                   cs->ics.parm.setup.phone, 
+                   cs->ics.parm.setup.eazmsn,
+                   cs->ics.parm.setup.si1,
+                   cs->ics.parm.setup.si2,
+                   cs->ics.parm.setup.screen,
+                   dv->rule.waittime,
+                   cs->deflect_dest);
+           if ((dv->rule.action == DEFLECT_REPORT) ||
+               (dv->rule.action == DEFLECT_REJECT))
+	    { put_info_buffer(cs->info);
+	      kfree(cs); /* remove */
+              return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */ 
+            }              
+           break;
+  
+         default:
+           return(0); /* ignore call */
+           break;
+       } /* switch action */    
+     break; 
+   } /* scan_table */
+
+  if (cs) 
+   { cs->prev = NULL;
+     save_flags(flags);
+     cli();
+     cs->next = divert_head;
+     divert_head = cs; 
+     if (cs->timer.expires) add_timer(&cs->timer);
+     restore_flags(flags);
+
+     put_info_buffer(cs->info); 
+     return(retval);
+   }
+  else
+     return(0);
+} /* isdn_divert_icall */
+
+
+void deleteprocs(void)
+{ struct call_struc *cs, *cs1; 
+  int flags;
+
+  save_flags(flags);
+  cli();
+  cs = divert_head;
+  divert_head = NULL;
+  while (cs)
+   { del_timer(&cs->timer);
+     cs1 = cs;
+     cs = cs->next;
+     kfree(cs1);
+   } 
+  restore_flags(flags);
+} /* deleteprocs */
+
+/****************************************************/
+/* put a address including address type into buffer */
+/****************************************************/
+int put_address(char *st, u_char *p, int len)
+{ u_char retval = 0;
+  u_char adr_typ = 0; /* network standard */
+
+  if (len < 2) return(retval);
+  if (*p == 0xA1)
+   { retval = *(++p) + 2; /* total length */
+     if (retval > len) return(0); /* too short */
+     len = retval - 2; /* remaining length */
+     if (len < 3) return(0);
+     if ((*(++p) != 0x0A) || (*(++p) != 1)) return(0);
+     adr_typ = *(++p);
+     len -= 3;
+     p++;
+     if (len < 2) return(0);
+     if (*p++ != 0x12) return(0);
+     if (*p > len) return(0); /* check number length */
+     len = *p++;
+   }   
+  else
+   if (*p == 0x80)
+    { retval = *(++p) + 2; /* total length */
+      if (retval > len) return(0);
+      len = retval - 2;
+      p++;
+    }
+   else  
+    return(0); /* invalid address information */
+
+  sprintf(st,"%d ",adr_typ);
+  st += strlen(st);
+  if (!len) 
+    *st++ = '-';
+  else
+   while (len--)
+     *st++ = *p++;
+  *st = '\0';
+  return(retval);
+} /* put_address */
+
+/*************************************/
+/* report a succesfull interrogation */
+/*************************************/
+int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
+{ char *src = ic->parm.dss1_io.data;
+  int restlen = ic->parm.dss1_io.datalen;
+  int cnt = 1;
+  u_char n,n1;
+  char st[90], *p, *stp;
+
+  if (restlen < 2) return(-100); /* frame too short */
+  if (*src++ != 0x30) return(-101);
+  if ((n = *src++) > 0x81) return(-102); /* invalid length field */
+  restlen -= 2; /* remaining bytes */
+  if (n == 0x80)
+   { if (restlen < 2) return(-103);
+     if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-104);
+     restlen -= 2;
+   }
+  else
+   if ( n == 0x81)
+    { n = *src++;
+      restlen--;
+      if (n > restlen) return(-105);
+      restlen = n;
+    }
+   else
+    if (n > restlen) return(-106);
+     else 
+      restlen = n; /* standard format */   
+  if (restlen < 3) return(-107); /* no procedure */
+  if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return(-108);
+  restlen -= 3; 
+  if (restlen < 2) return(-109); /* list missing */
+  if (*src == 0x31)
+   { src++; 
+     if ((n = *src++) > 0x81) return(-110); /* invalid length field */
+     restlen -= 2; /* remaining bytes */
+     if (n == 0x80)
+      { if (restlen < 2) return(-111);
+        if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-112);
+        restlen -= 2;
+      }
+     else
+      if ( n == 0x81)
+       { n = *src++;
+         restlen--;
+         if (n > restlen) return(-113);
+         restlen = n;
+       }
+      else
+       if (n > restlen) return(-114);
+        else 
+         restlen = n; /* standard format */   
+   } /* result list header */ 
+
+  while (restlen >= 2)
+   { stp = st;
+     sprintf(stp,"%d 0x%lx %d %s ",DIVERT_REPORT, ic->parm.dss1_io.ll_id,
+                 cnt++,divert_if.drv_to_name(ic->driver));
+     stp += strlen(stp);
+     if (*src++ != 0x30) return(-115); /* invalid enum */
+     n = *src++;
+     restlen -= 2;
+     if (n > restlen) return(-116); /* enum length wrong */
+     restlen -= n;
+     p = src; /* one entry */
+     src += n;
+     if (!(n1 = put_address(stp,p,n & 0xFF))) continue;
+     stp += strlen(stp);
+     p += n1;
+     n -= n1;
+     if (n < 6) continue; /* no service and proc */
+     if ((*p++ != 0x0A) || (*p++ != 1)) continue;
+     sprintf(stp," 0x%02x ",(*p++) & 0xFF);
+     stp += strlen(stp);
+     if ((*p++ != 0x0A) || (*p++ != 1)) continue;
+     sprintf(stp,"%d ",(*p++) & 0xFF);
+     stp += strlen(stp);
+     n -= 6;
+     if (n > 2)
+      { if (*p++ != 0x30) continue;
+        if (*p > (n-2)) continue;
+        n = *p++;
+        if (!(n1 = put_address(stp,p,n & 0xFF))) continue;
+        stp += strlen(stp);
+      }
+     sprintf(stp,"\n");
+     put_info_buffer(st);
+   } /* while restlen */
+  if (restlen) return(-117);
+  return(0);   
+} /* interrogate_success */
+
+/*********************************************/
+/* callback for protocol specific extensions */
+/*********************************************/
+int prot_stat_callback(isdn_ctrl *ic)
+{ struct call_struc *cs, *cs1;
+  int i,flags;
+
+  cs = divert_head; /* start of list */
+  cs1 = NULL;
+  while (cs)
+   { if (ic->driver == cs->ics.driver) 
+      { switch (cs->ics.arg)
+	 { case DSS1_CMD_INVOKE:
+             if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
+                 (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id))
+	      { switch (ic->arg)
+		{  case DSS1_STAT_INVOKE_ERR:
+                     sprintf(cs->info,"128 0x%lx 0x%x\n", 
+                             ic->parm.dss1_io.ll_id,
+                             ic->parm.dss1_io.timeout);
+                     put_info_buffer(cs->info);
+                   break;
+                   
+                   case DSS1_STAT_INVOKE_RES:
+                     switch (cs->ics.parm.dss1_io.proc)
+		      {  case  7:
+                         case  8:
+                            put_info_buffer(cs->info); 
+                           break;
+                       
+                         case  11:
+                           i = interrogate_success(ic,cs);
+                           if (i)
+                             sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT, 
+                                     ic->parm.dss1_io.ll_id,i);
+                           put_info_buffer(cs->info); 
+                           break;
+                       
+		         default: 
+                           printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc);
+                           break;
+                      } 
+
+
+#if 0
+  sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id);
+  p = st + strlen(st);
+  p1 = ic->parm.dss1_io.data;
+  i = ic->parm.dss1_io.datalen;
+  while ((i > 0) && (p - st < 530))
+   { p += sprintf(p," %02x",(*p1++) & 0xFF);
+     i--;
+   }
+  sprintf(p, "\n");
+  put_info_buffer(st);
+#endif
+                   break;
+ 
+		   default:
+                     printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg);
+                   break;  
+                 } 
+                cs1 = cs; /* remember structure */
+                cs = NULL; 
+                continue; /* abort search */
+              } /* id found */ 
+           break;
+   
+	   case DSS1_CMD_INVOKE_ABORT:
+             printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); 
+           break;   
+         
+	   default:
+             printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg); 
+           break; 
+         } /* switch ics.arg */ 
+        cs = cs->next; 
+      } /* driver ok */
+   }  
+   
+  if (!cs1) 
+   { printk(KERN_WARNING "dss1_divert unhandled process\n");
+     return(0);
+   }  
+
+  if (cs1->ics.driver == -1)
+   { save_flags(flags);
+     cli();
+     del_timer(&cs1->timer);
+     if (cs1->prev) 
+       cs1->prev->next = cs1->next; /* forward link */
+     else
+       divert_head = cs1->next;
+     if (cs1->next)
+       cs1->next->prev = cs1->prev; /* back link */           
+     restore_flags(flags); 
+     kfree(cs1);
+   } 
+
+  return(0);
+} /* prot_stat_callback */
+
+
+/***************************/
+/* status callback from HL */
+/***************************/
+int isdn_divert_stat_callback(isdn_ctrl *ic)
+{ struct call_struc *cs, *cs1;
+  int flags, retval;
+
+  retval = -1;
+  cs = divert_head; /* start of list */
+     while (cs)
+      { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg))
+         { switch (ic->command)
+	    { case ISDN_STAT_DHUP:
+                sprintf(cs->info,"129 0x%lx\n",cs->divert_id);
+                del_timer(&cs->timer);
+                cs->ics.driver = -1;
+                break;
+
+	      case ISDN_STAT_CAUSE:
+                sprintf(cs->info,"130 0x%lx %s\n",cs->divert_id,ic->parm.num);
+                break;
+
+	      case ISDN_STAT_REDIR:
+                sprintf(cs->info,"131 0x%lx\n",cs->divert_id);
+                del_timer(&cs->timer);
+                cs->ics.driver = -1;
+                break; 
+
+	      default:
+                sprintf(cs->info,"999 0x%lx 0x%x\n",cs->divert_id,(int)(ic->command));
+                break; 
+            }
+          put_info_buffer(cs->info);
+          retval = 0; 
+         }
+        cs1 = cs; 
+        cs = cs->next;
+        if (cs1->ics.driver == -1)
+          { 
+            save_flags(flags);
+            cli();
+            if (cs1->prev) 
+              cs1->prev->next = cs1->next; /* forward link */
+            else
+              divert_head = cs1->next;
+            if (cs1->next)
+              cs1->next->prev = cs1->prev; /* back link */           
+            restore_flags(flags); 
+            kfree(cs1);
+          } 
+      }  
+  return(retval); /* not found */
+} /* isdn_divert_stat_callback */ 
+
+
+/********************/
+/* callback from ll */
+/********************/ 
+int ll_callback(isdn_ctrl *ic)
+{
+  switch (ic->command)
+   { case ISDN_STAT_ICALL:
+     case ISDN_STAT_ICALLW:
+       return(isdn_divert_icall(ic));
+     break;
+
+     case ISDN_STAT_PROT:
+       if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO)
+	{ if (ic->arg != DSS1_STAT_INVOKE_BRD)
+            return(prot_stat_callback(ic));
+          else
+            return(0); /* DSS1 invoke broadcast */
+        }
+       else
+         return(-1); /* protocol not euro */    
+
+     default:
+       return(isdn_divert_stat_callback(ic));
+   }
+} /* ll_callback */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/divert/isdn_divert.h linux.pre11.3/drivers/isdn/divert/isdn_divert.h
--- linux.vanilla/drivers/isdn/divert/isdn_divert.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/divert/isdn_divert.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,159 @@
+/* 
+ * $Id: isdn_divert.h,v 1.2 1999/07/04 21:37:33 werner Exp $
+ *
+ * Header for the diversion supplementary ioctl interface.
+ *
+ * Copyright 1998       by Werner Cornelius (werner@ikt.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_divert.h,v $
+ * Revision 1.2  1999/07/04 21:37:33  werner
+ * Ported from kernel version 2.0
+ *
+ *
+ *
+ */
+
+
+
+#include <linux/config.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/******************************************/
+/* IOCTL codes for interface to user prog */
+/******************************************/
+#define DIVERT_IIOC_VERSION 0x01 /* actual version */
+#define IIOCGETVER   _IO('I', 1)  /* get version of interface */
+#define IIOCGETDRV   _IO('I', 2)  /* get driver number */
+#define IIOCGETNAM   _IO('I', 3)  /* get driver name */
+#define IIOCGETRULE  _IO('I', 4)  /* read one rule */
+#define IIOCMODRULE  _IO('I', 5)  /* modify/replace a rule */  
+#define IIOCINSRULE  _IO('I', 6)  /* insert/append one rule */
+#define IIOCDELRULE  _IO('I', 7)  /* delete a rule */
+#define IIOCDODFACT  _IO('I', 8)  /* hangup/reject/alert/immediately deflect a call */
+#define IIOCDOCFACT  _IO('I', 9)  /* activate control forwarding in PBX */
+#define IIOCDOCFDIS  _IO('I',10)  /* deactivate control forwarding in PBX */
+#define IIOCDOCFINT  _IO('I',11)  /* interrogate control forwarding in PBX */
+
+/*************************************/
+/* states reported through interface */
+/*************************************/
+#define DEFLECT_IGNORE    0  /* ignore incoming call */
+#define DEFLECT_REPORT    1  /* only report */
+#define DEFLECT_PROCEED   2  /* deflect when externally triggered */
+#define DEFLECT_ALERT     3  /* alert and deflect after delay */ 
+#define DEFLECT_REJECT    4  /* reject immediately */
+#define DIVERT_ACTIVATE   5  /* diversion activate */
+#define DIVERT_DEACTIVATE 6  /* diversion deactivate */
+#define DIVERT_REPORT     7  /* interrogation result */ 
+#define DEFLECT_AUTODEL 255  /* only for internal use */ 
+
+#define DEFLECT_ALL_IDS   0xFFFFFFFF /* all drivers selected */
+
+typedef struct
+ { ulong drvid;     /* driver ids, bit mapped */
+   char my_msn[35]; /* desired msn, subaddr allowed */
+   char caller[35]; /* caller id, partial string with * + subaddr allowed */
+   char to_nr[35];  /* deflected to number incl. subaddress */
+   u_char si1,si2;  /* service indicators, si1=bitmask, si1+2 0 = all */
+   u_char screen;   /* screening: 0 = no info, 1 = info, 2 = nfo with nr */
+   u_char callopt;  /* option for call handling: 
+                       0 = all calls
+                       1 = only non waiting calls
+                       2 = only waiting calls */
+   u_char action;   /* desired action: 
+                       0 = don't report call -> ignore
+                       1 = report call, do not allow/proceed for deflection
+                       2 = report call, send proceed, wait max waittime secs
+                       3 = report call, alert and deflect after waittime 
+                       4 = report call, reject immediately  
+                       actions 1-2 only take place if interface is opened 
+		    */
+   u_char waittime; /* maximum wait time for proceeding */ 
+ } divert_rule;
+
+typedef union
+ { int drv_version; /* return of driver version */
+   struct 
+   { int drvid; /* id of driver */
+     char drvnam[30]; /* name of driver */
+   } getid;
+   struct
+   { int ruleidx; /* index of rule */
+     divert_rule rule; /* rule parms */ 
+   } getsetrule;
+   struct
+   { u_char subcmd;  /* 0 = hangup/reject,
+                        1 = alert,
+                        2 = deflect */
+     ulong callid;   /* id of call delivered by ascii output */
+     char to_nr[35]; /* destination when deflect,
+                        else uus1 string (maxlen 31),
+                        data from rule used if empty */ 
+   } fwd_ctrl; 
+   struct
+   { int drvid;      /* id of driver */
+     u_char cfproc;  /* cfu = 0, cfb = 1, cfnr = 2 */
+     ulong procid;   /* process id returned when no error */ 
+     u_char service; /* basically coded service, 0 = all */
+     char msn[25];   /* desired msn, empty = all */
+     char fwd_nr[35];/* forwarded to number + subaddress */
+   } cf_ctrl;  
+ } divert_ioctl;
+
+#ifdef __KERNEL__
+
+#include <linux/isdnif.h>
+#include <linux/isdn_divertif.h>
+
+#define AUTODEL_TIME 30 /* timeout in s to delete internal entrys */
+
+/**************************************************/
+/* structure keeping ascii info for device output */
+/**************************************************/
+struct divert_info
+  { struct divert_info *next;
+    ulong usage_cnt; /* number of files still to work */   
+    char info_start[2]; /* info string start */ 
+  }; 
+
+
+/**************/
+/* Prototypes */
+/**************/
+extern ulong if_used; /* number of interface users */
+extern int divert_dev_deinit(void);
+extern int divert_dev_init(void);
+extern void put_info_buffer(char *);
+extern int ll_callback(isdn_ctrl *);
+extern isdn_divert_if divert_if;
+extern divert_rule *getruleptr(int);
+extern int insertrule(int, divert_rule *);
+extern int deleterule(int);
+extern void deleteprocs(void);
+extern int deflect_extern_action(u_char, ulong, char *);
+extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *);
+
+#endif __KERNEL__
+
+
+
+
+
+
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/Makefile linux.pre11.3/drivers/isdn/eicon/Makefile
--- linux.vanilla/drivers/isdn/eicon/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/Makefile	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,13 @@
+L_OBJS :=
+M_OBJS :=
+O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
+
+O_TARGET :=
+ifeq ($(CONFIG_ISDN_DRV_EICON),y)
+  O_TARGET += eicon.o
+else
+  O_TARGET += eicon.o
+  M_OBJS   = eicon.o
+endif
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon.h linux.pre11.3/drivers/isdn/eicon/eicon.h
--- linux.vanilla/drivers/isdn/eicon/eicon.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,544 @@
+/* $Id: eicon.h,v 1.7 1999/07/11 17:16:23 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ *
+ * Copyright 1998    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de) 
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon.h,v $
+ * Revision 1.7  1999/07/11 17:16:23  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.6  1999/06/09 19:31:24  armin
+ * Wrong PLX size for request_region() corrected.
+ * Added first MCA code from Erik Weber.
+ *
+ * Revision 1.5  1999/03/29 11:19:41  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.4  1999/03/02 12:37:42  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.3  1999/01/24 20:14:07  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.2  1999/01/10 18:46:04  armin
+ * Bug with wrong values in HLC fixed.
+ * Bytes to send are counted and limited now.
+ *
+ * Revision 1.1  1999/01/01 18:09:41  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+
+#ifndef eicon_h
+#define eicon_h
+
+#define EICON_IOCTL_SETMMIO   0
+#define EICON_IOCTL_GETMMIO   1
+#define EICON_IOCTL_SETIRQ    2
+#define EICON_IOCTL_GETIRQ    3
+#define EICON_IOCTL_LOADBOOT  4
+#define EICON_IOCTL_ADDCARD   5
+#define EICON_IOCTL_GETTYPE   6
+#define EICON_IOCTL_LOADPCI   7 
+#define EICON_IOCTL_LOADISA   8 
+#define EICON_IOCTL_GETVER    9 
+
+#define EICON_IOCTL_MANIF    90 
+
+#define EICON_IOCTL_FREEIT   97
+#define EICON_IOCTL_TEST     98
+#define EICON_IOCTL_DEBUGVAR 99
+
+/* Bus types */
+#define EICON_BUS_ISA          1
+#define EICON_BUS_MCA          2
+#define EICON_BUS_PCI          3
+
+/* Constants for describing Card-Type */
+#define EICON_CTYPE_S            0
+#define EICON_CTYPE_SX           1
+#define EICON_CTYPE_SCOM         2
+#define EICON_CTYPE_QUADRO       3
+#define EICON_CTYPE_S2M          4
+#define EICON_CTYPE_MAESTRA      5
+#define EICON_CTYPE_MAESTRAQ     6
+#define EICON_CTYPE_MAESTRAQ_U   7
+#define EICON_CTYPE_MAESTRAP     8
+#define EICON_CTYPE_ISABRI       0x10
+#define EICON_CTYPE_ISAPRI       0x20
+#define EICON_CTYPE_MASK         0x0f
+#define EICON_CTYPE_QUADRO_NR(n) (n<<4)
+
+#define MAX_HEADER_LEN 10
+
+/* Struct for adding new cards */
+typedef struct eicon_cdef {
+        int membase;
+        int irq;
+        char id[10];
+} eicon_cdef;
+
+#define EICON_ISA_BOOT_MEMCHK 1
+#define EICON_ISA_BOOT_NORMAL 2
+
+/* Struct for downloading protocol via ioctl for ISA cards */
+/* same struct for downloading protocol via ioctl for MCA cards */
+typedef struct {
+	/* start-up parameters */
+	unsigned char tei;
+	unsigned char nt2;
+	unsigned char skip1;
+	unsigned char WatchDog;
+	unsigned char Permanent;
+	unsigned char XInterface;
+	unsigned char StableL2;
+	unsigned char NoOrderCheck;
+	unsigned char HandsetType;
+	unsigned char skip2;
+	unsigned char LowChannel;
+	unsigned char ProtVersion;
+	unsigned char Crc4;
+	unsigned char Loopback;
+	unsigned char oad[32];
+	unsigned char osa[32];
+	unsigned char spid[32];
+	unsigned char boot_opt;
+	unsigned long bootstrap_len;
+	unsigned long firmware_len;
+	unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */
+} eicon_isa_codebuf;
+
+/* Struct for downloading protocol via ioctl for PCI cards */
+typedef struct {
+        /* start-up parameters */
+        unsigned char tei;
+        unsigned char nt2;
+        unsigned char WatchDog;
+        unsigned char Permanent;
+        unsigned char XInterface;
+        unsigned char StableL2;
+        unsigned char NoOrderCheck;
+        unsigned char HandsetType;
+        unsigned char LowChannel;
+        unsigned char ProtVersion;
+        unsigned char Crc4;
+        unsigned char NoHscx30Mode;  /* switch PRI into No HSCX30 test mode */
+        unsigned char Loopback;      /* switch card into Loopback mode */
+        struct q931_link_s
+        {
+          unsigned char oad[32];
+          unsigned char osa[32];
+          unsigned char spid[32];
+        } l[2];
+        unsigned long protocol_len;
+	unsigned int  dsp_code_num;
+        unsigned long dsp_code_len[9];
+        unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */
+} eicon_pci_codebuf;
+
+/* Data for downloading protocol via ioctl */
+typedef union {
+	eicon_isa_codebuf isa;
+	eicon_isa_codebuf mca;
+	eicon_pci_codebuf pci;
+} eicon_codebuf;
+
+/* Data for Management interface */
+typedef struct {
+	int count;
+	int pos;
+	int length[50];
+	unsigned char data[700]; 
+} eicon_manifbuf;
+
+
+#ifdef __KERNEL__
+
+/* Kernel includes */
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+#include <linux/isdnif.h>
+
+typedef struct {
+  __u16 length __attribute__ ((packed)); /* length of data/parameter field */
+  __u8  P[1];                          /* data/parameter field */
+} eicon_PBUFFER;
+
+#include "eicon_isa.h"
+
+/* Macro for delay via schedule() */
+#define SLEEP(j) {                     \
+  current->state = TASK_INTERRUPTIBLE; \
+  schedule_timeout(j);                 \
+}
+
+#endif /* KERNEL */
+
+
+#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48
+#define DSP_COMBIFILE_FORMAT_VERSION_BCD    0x0100
+
+#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48
+#define DSP_FILE_FORMAT_VERSION_BCD         0x0100
+
+typedef struct tag_dsp_combifile_header
+{
+  char                  format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
+  __u16                  format_version_bcd             __attribute__ ((packed));
+  __u16                  header_size                    __attribute__ ((packed));
+  __u16                  combifile_description_size     __attribute__ ((packed));
+  __u16                  directory_entries              __attribute__ ((packed));
+  __u16                  directory_size                 __attribute__ ((packed));
+  __u16                  download_count                 __attribute__ ((packed));
+  __u16                  usage_mask_size                __attribute__ ((packed));
+} t_dsp_combifile_header;
+
+typedef struct tag_dsp_combifile_directory_entry
+{
+  __u16                  card_type_number               __attribute__ ((packed));
+  __u16                  file_set_number                __attribute__ ((packed));
+} t_dsp_combifile_directory_entry;
+
+typedef struct tag_dsp_file_header
+{
+  char                  format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed));
+  __u16                 format_version_bcd              __attribute__ ((packed));
+  __u16                 download_id                     __attribute__ ((packed));
+  __u16                 download_flags                  __attribute__ ((packed));
+  __u16                 required_processing_power       __attribute__ ((packed));
+  __u16                 interface_channel_count         __attribute__ ((packed));
+  __u16                 header_size                     __attribute__ ((packed));
+  __u16                 download_description_size       __attribute__ ((packed));
+  __u16                 memory_block_table_size         __attribute__ ((packed));
+  __u16                 memory_block_count              __attribute__ ((packed));
+  __u16                 segment_table_size              __attribute__ ((packed));
+  __u16                 segment_count                   __attribute__ ((packed));
+  __u16                 symbol_table_size               __attribute__ ((packed));
+  __u16                 symbol_count                    __attribute__ ((packed));
+  __u16                 total_data_size_dm              __attribute__ ((packed));
+  __u16                 data_block_count_dm             __attribute__ ((packed));
+  __u16                 total_data_size_pm              __attribute__ ((packed));
+  __u16                 data_block_count_pm             __attribute__ ((packed));
+} t_dsp_file_header;
+
+typedef struct tag_dsp_memory_block_desc
+{
+  __u16                 alias_memory_block;
+  __u16                 memory_type;
+  __u16                 address;
+  __u16                 size;             /* DSP words */
+} t_dsp_memory_block_desc;
+
+typedef struct tag_dsp_segment_desc
+{
+  __u16                 memory_block;
+  __u16                 attributes;
+  __u16                 base;
+  __u16                 size;
+  __u16                 alignment;        /* ==0 -> no other legal start address than base */
+} t_dsp_segment_desc;
+
+typedef struct tag_dsp_symbol_desc
+{
+  __u16                 symbol_id;
+  __u16                 segment;
+  __u16                 offset;
+  __u16                 size;             /* DSP words */
+} t_dsp_symbol_desc;
+
+typedef struct tag_dsp_data_block_header
+{
+  __u16                 attributes;
+  __u16                 segment;
+  __u16                 offset;
+  __u16                 size;             /* DSP words */
+} t_dsp_data_block_header;
+
+typedef struct tag_dsp_download_desc      /* be sure to keep native alignment for MAESTRA's */
+{
+  __u16                 download_id;
+  __u16                 download_flags;
+  __u16                 required_processing_power;
+  __u16                 interface_channel_count;
+  __u16                 excess_header_size;
+  __u16                 memory_block_count;
+  __u16                 segment_count;
+  __u16                 symbol_count;
+  __u16                 data_block_count_dm;
+  __u16                 data_block_count_pm;
+  __u8  *            p_excess_header_data               __attribute__ ((packed));
+  char  *            p_download_description             __attribute__ ((packed));
+  t_dsp_memory_block_desc  *p_memory_block_table        __attribute__ ((packed));
+  t_dsp_segment_desc  *p_segment_table                  __attribute__ ((packed));
+  t_dsp_symbol_desc  *p_symbol_table                    __attribute__ ((packed));
+  __u16 *            p_data_blocks_dm                   __attribute__ ((packed));
+  __u16 *            p_data_blocks_pm                   __attribute__ ((packed));
+} t_dsp_download_desc;
+
+
+#ifdef __KERNEL__
+
+typedef struct {
+  __u8                  Req;            /* pending request          */
+  __u8                  Rc;             /* return code received     */
+  __u8                  Ind;            /* indication received      */
+  __u8                  ReqCh;          /* channel of current Req   */
+  __u8                  RcCh;           /* channel of current Rc    */
+  __u8                  IndCh;          /* channel of current Ind   */
+  __u8                  D3Id;           /* ID used by this entity   */
+  __u8                  B2Id;           /* ID used by this entity   */
+  __u8                  GlobalId;       /* reserved field           */
+  __u8                  XNum;           /* number of X-buffers      */
+  __u8                  RNum;           /* number of R-buffers      */
+  struct sk_buff_head   X;              /* X-buffer queue           */
+  struct sk_buff_head   R;              /* R-buffer queue           */
+  __u8                  RNR;            /* receive not ready flag   */
+  __u8                  complete;       /* receive complete status  */
+  __u8                  busy;           /* busy flag                */
+  __u16                 ref;            /* saved reference          */
+} entity;
+
+
+typedef struct {
+	int	       No;		 /* Channel Number	        */
+	unsigned short callref;          /* Call Reference              */
+	unsigned short fsm_state;        /* Current D-Channel state     */
+	unsigned short eazmask;          /* EAZ-Mask for this Channel   */
+	int		queued;          /* User-Data Bytes in TX queue */
+	int		waitq;           /* User-Data Bytes in wait queue */
+	int		waitpq;          /* User-Data Bytes in packet queue */
+	unsigned short plci;
+	unsigned short ncci;
+	unsigned char  l2prot;           /* Layer 2 protocol            */
+	unsigned char  l3prot;           /* Layer 3 protocol            */
+	entity		e;		 /* Entity  			*/
+	char		cpn[32];	 /* remember cpn		*/
+	char		oad[32];	 /* remember oad		*/
+	unsigned char   cause[2];	 /* Last Cause			*/
+	unsigned char	si1;
+	unsigned char	si2;
+} eicon_chan;
+
+typedef struct {
+	eicon_chan *ptr;
+} eicon_chan_ptr;
+
+#include "eicon_pci.h"
+
+#define EICON_FLAGS_RUNNING  1 /* Cards driver activated */
+#define EICON_FLAGS_PVALID   2 /* Cards port is valid    */
+#define EICON_FLAGS_IVALID   4 /* Cards irq is valid     */
+#define EICON_FLAGS_MVALID   8 /* Cards membase is valid */
+#define EICON_FLAGS_LOADED   8 /* Firmware loaded        */
+
+#define EICON_BCH            2 /* # of channels per card */
+
+/* D-Channel states */
+#define EICON_STATE_NULL     0
+#define EICON_STATE_ICALL    1
+#define EICON_STATE_OCALL    2
+#define EICON_STATE_IWAIT    3
+#define EICON_STATE_OWAIT    4
+#define EICON_STATE_IBWAIT   5
+#define EICON_STATE_OBWAIT   6
+#define EICON_STATE_BWAIT    7
+#define EICON_STATE_BHWAIT   8
+#define EICON_STATE_BHWAIT2  9
+#define EICON_STATE_DHWAIT  10
+#define EICON_STATE_DHWAIT2 11
+#define EICON_STATE_BSETUP  12
+#define EICON_STATE_ACTIVE  13
+#define EICON_STATE_ICALLW  14
+#define EICON_STATE_LISTEN  15
+#define EICON_STATE_WMCONN  16
+
+#define EICON_MAX_QUEUED  8000 /* 2 * maxbuff */
+
+#define EICON_LOCK_TX 0
+#define EICON_LOCK_RX 1
+
+typedef union {
+	eicon_isa_card isa;
+	eicon_pci_card pci;
+	eicon_isa_card mca;
+} eicon_hwif;
+
+typedef struct {
+	__u8 ret;
+	__u8 id;
+	__u8 ch;
+} eicon_ack;
+
+typedef struct {
+	__u8 code;
+	__u8 id;
+	__u8 ch;
+} eicon_req;
+
+typedef struct {
+	__u8 ret;
+	__u8 id;
+	__u8 ch;
+	__u8 more;
+} eicon_indhdr;
+
+typedef struct msn_entry {
+	char eaz;
+        char msn[16];
+        struct msn_entry * next;
+} msn_entry;
+
+/*
+ * Per card driver data
+ */
+typedef struct eicon_card {
+	eicon_hwif hwif;                 /* Hardware dependant interface     */
+        u_char ptype;                    /* Protocol type (1TR6 or Euro)     */
+        u_char bus;                      /* Bustype (ISA, MCA, PCI)          */
+        u_char type;                     /* Cardtype (EICON_CTYPE_...)       */
+	struct eicon_card *qnext;  	 /* Pointer to next quadro adapter   */
+        int Feature;                     /* Protocol Feature Value           */
+        struct eicon_card *next;	 /* Pointer to next device struct    */
+        int myid;                        /* Driver-Nr. assigned by linklevel */
+        unsigned long flags;             /* Statusflags                      */
+        unsigned long ilock;             /* Semaphores for IRQ-Routines      */
+	struct sk_buff_head rcvq;        /* Receive-Message queue            */
+	struct sk_buff_head sndq;        /* Send-Message queue               */
+	struct sk_buff_head rackq;       /* Req-Ack-Message queue            */
+	struct sk_buff_head sackq;       /* Data-Ack-Message queue           */
+	u_char *ack_msg;                 /* Ptr to User Data in User skb     */
+	__u16 need_b3ack;                /* Flag: Need ACK for current skb   */
+	struct sk_buff *sbuf;            /* skb which is currently sent      */
+	struct tq_struct snd_tq;         /* Task struct for xmit bh          */
+	struct tq_struct rcv_tq;         /* Task struct for rcv bh           */
+	struct tq_struct ack_tq;         /* Task struct for ack bh           */
+	msn_entry *msn_list;
+	unsigned short msgnum;           /* Message number for sending       */
+	eicon_chan*	IdTable[256];	 /* Table to find entity   */
+	__u16  ref_in;
+	__u16  ref_out;
+	int    nchannels;                /* Number of B-Channels             */
+	int    ReadyInt;		 /* Ready Interrupt		     */
+	eicon_chan *bch;                 /* B-Channel status/control         */
+	char   status_buf[256];          /* Buffer for status messages       */
+	char   *status_buf_read;
+	char   *status_buf_write;
+	char   *status_buf_end;
+        isdn_if interface;               /* Interface to upper layer         */
+        char regname[35];                /* Name used for request_region     */
+#ifdef CONFIG_MCA
+        int  mca_slot;                   /* # of cards MCA slot              */
+#endif
+} eicon_card;
+
+/* -----------------------------------------------------------**
+** The PROTOCOL_FEATURE_STRING                                **
+** defines capabilities and                                   **
+** features of the actual protocol code. It's used as a bit   **
+** mask.                                                      **
+** The following Bits are defined:                            **
+** -----------------------------------------------------------*/
+#define PROTCAP_TELINDUS  0x0001  /* Telindus Variant of protocol code   */
+#define PROTCAP_MANIF     0x0002  /* Management interface implemented    */
+#define PROTCAP_V_42      0x0004  /* V42 implemented                     */
+#define PROTCAP_V90D      0x0008  /* V.90D (implies up to 384k DSP code) */
+#define PROTCAP_EXTD_FAX  0x0010  /* Extended FAX (ECM, 2D, T6, Polling) */
+#define PROTCAP_FREE4     0x0020  /* not used                            */
+#define PROTCAP_FREE5     0x0040  /* not used                            */
+#define PROTCAP_FREE6     0x0080  /* not used                            */
+#define PROTCAP_FREE7     0x0100  /* not used                            */
+#define PROTCAP_FREE8     0x0200  /* not used                            */
+#define PROTCAP_FREE9     0x0400  /* not used                            */
+#define PROTCAP_FREE10    0x0800  /* not used                            */
+#define PROTCAP_FREE11    0x1000  /* not used                            */
+#define PROTCAP_FREE12    0x2000  /* not used                            */
+#define PROTCAP_FREE13    0x4000  /* not used                            */
+#define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
+
+#include "eicon_idi.h"
+
+extern eicon_card *cards;
+extern char *eicon_ctype_name[];
+
+
+extern __inline__ void eicon_schedule_tx(eicon_card *card)
+{
+        queue_task(&card->snd_tq, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+extern __inline__ void eicon_schedule_rx(eicon_card *card)
+{
+        queue_task(&card->rcv_tq, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+extern __inline__ void eicon_schedule_ack(eicon_card *card)
+{
+        queue_task(&card->ack_tq, &tq_immediate);
+        mark_bh(IMMEDIATE_BH);
+}
+
+extern char *eicon_find_eaz(eicon_card *, char);
+extern int eicon_addcard(int, int, int, char *);
+extern void eicon_io_transmit(eicon_card *card);
+extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs);
+extern void eicon_io_rcv_dispatch(eicon_card *ccard);
+extern void eicon_io_ack_dispatch(eicon_card *ccard);
+#ifdef CONFIG_MCA
+extern int eicon_mca_find_card(int, int, int, char *);
+extern int eicon_mca_probe(int, int, int, int, char *);
+extern int eicon_info(char *, int , void *);
+#endif /* CONFIG_MCA */
+
+extern ulong DebugVar;
+
+#endif  /* __KERNEL__ */
+
+#endif	/* eicon_h */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_dsp.h linux.pre11.3/drivers/isdn/eicon/eicon_dsp.h
--- linux.vanilla/drivers/isdn/eicon/eicon_dsp.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_dsp.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,313 @@
+/* $Id: eicon_dsp.h,v 1.3 1999/07/11 17:16:24 armin Exp $
+ *
+ * ISDN lowlevel-module for Eicon.Diehl active cards.
+ *        DSP definitions
+ *
+ * Copyright 1999    by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: eicon_dsp.h,v $
+ * Revision 1.3  1999/07/11 17:16:24  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.2  1999/03/29 11:19:42  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.1  1999/03/02 12:18:54  armin
+ * First checkin of DSP defines for audio features.
+ *
+ *
+ */
+
+#ifndef DSP_H 
+#define DSP_H
+
+#define DSP_UDATA_REQUEST_RECONFIGURE           0
+/*
+parameters:
+  <word> reconfigure delay (in 8kHz samples)
+  <word> reconfigure code
+  <byte> reconfigure hdlc preamble flags
+*/
+
+#define DSP_RECONFIGURE_TX_FLAG             0x8000
+#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG    0x4000
+#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG   0x2000
+#define DSP_RECONFIGURE_HDLC_FLAG           0x1000
+#define DSP_RECONFIGURE_SYNC_FLAG           0x0800
+#define DSP_RECONFIGURE_PROTOCOL_MASK       0x00ff
+#define DSP_RECONFIGURE_IDLE                0
+#define DSP_RECONFIGURE_V25                 1
+#define DSP_RECONFIGURE_V21_CH2             2
+#define DSP_RECONFIGURE_V27_2400            3
+#define DSP_RECONFIGURE_V27_4800            4
+#define DSP_RECONFIGURE_V29_7200            5
+#define DSP_RECONFIGURE_V29_9600            6
+#define DSP_RECONFIGURE_V33_12000           7
+#define DSP_RECONFIGURE_V33_14400           8
+#define DSP_RECONFIGURE_V17_7200            9
+#define DSP_RECONFIGURE_V17_9600            10
+#define DSP_RECONFIGURE_V17_12000           11
+#define DSP_RECONFIGURE_V17_14400           12
+
+/*
+data indications if transparent framer
+  <byte> data 0
+  <byte> data 1
+  ...
+
+data indications if HDLC framer
+  <byte> data 0
+  <byte> data 1
+  ...
+  <byte> CRC 0
+  <byte> CRC 1
+  <byte> preamble flags
+*/
+
+#define DSP_UDATA_REQUEST_SWITCH_FRAMER         1
+/*
+parameters:
+  <byte> transmit framer type
+  <byte> receive framer type
+*/
+
+#define DSP_REQUEST_SWITCH_FRAMER_HDLC          0
+#define DSP_REQUEST_SWITCH_FRAMER_TRANSPARENT   1
+#define DSP_REQUEST_SWITCH_FRAMER_ASYNC         2
+
+
+#define DSP_UDATA_REQUEST_CLEARDOWN             2
+/*
+parameters:
+  - none -
+*/
+
+
+#define DSP_UDATA_REQUEST_TX_CONFIRMATION_ON    3
+/*
+parameters:
+  - none -
+*/
+
+
+#define DSP_UDATA_REQUEST_TX_CONFIRMATION_OFF   4
+/*
+parameters:
+  - none -
+*/
+
+
+#define DSP_UDATA_INDICATION_SYNC               0
+/*
+returns:
+  <word> time of sync (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_DCD_OFF            1
+/*
+returns:
+  <word> time of DCD off (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_DCD_ON             2
+/*
+returns:
+  <word> time of DCD on (sampled from counter at 8kHz)
+  <byte> connected norm
+  <word> connected options
+  <dword> connected speed (bit/s, max of tx and rx speed)
+  <word> roundtrip delay (ms)
+  <dword> connected speed tx (bit/s)
+  <dword> connected speed rx (bit/s)
+*/
+
+#define DSP_UDATA_INDICATION_CTS_OFF            3
+/*
+returns:
+  <word> time of CTS off (sampled from counter at 8kHz)
+*/
+
+#define DSP_UDATA_INDICATION_CTS_ON             4
+/*
+returns:
+  <word> time of CTS on (sampled from counter at 8kHz)
+  <byte> connected norm
+  <word> connected options
+  <dword> connected speed (bit/s, max of tx and rx speed)
+  <word> roundtrip delay (ms)
+  <dword> connected speed tx (bit/s)
+  <dword> connected speed rx (bit/s)
+*/
+
+typedef struct eicon_dsp_ind {
+	__u16	time		__attribute__ ((packed));
+	__u8	norm		__attribute__ ((packed));
+	__u16	options		__attribute__ ((packed));
+	__u32	speed		__attribute__ ((packed));
+	__u16	delay		__attribute__ ((packed));
+	__u32	txspeed		__attribute__ ((packed));
+	__u32	rxspeed		__attribute__ ((packed));
+} eicon_dsp_ind;
+
+#define DSP_CONNECTED_NORM_UNSPECIFIED      0
+#define DSP_CONNECTED_NORM_V21              1
+#define DSP_CONNECTED_NORM_V23              2
+#define DSP_CONNECTED_NORM_V22              3
+#define DSP_CONNECTED_NORM_V22_BIS          4
+#define DSP_CONNECTED_NORM_V32_BIS          5
+#define DSP_CONNECTED_NORM_V34              6
+#define DSP_CONNECTED_NORM_V8               7
+#define DSP_CONNECTED_NORM_BELL_212A        8
+#define DSP_CONNECTED_NORM_BELL_103         9
+#define DSP_CONNECTED_NORM_V29_LEASED_LINE  10
+#define DSP_CONNECTED_NORM_V33_LEASED_LINE  11
+#define DSP_CONNECTED_NORM_V90              12
+#define DSP_CONNECTED_NORM_V21_CH2          13
+#define DSP_CONNECTED_NORM_V27_TER          14
+#define DSP_CONNECTED_NORM_V29              15
+#define DSP_CONNECTED_NORM_V33              16
+#define DSP_CONNECTED_NORM_V17              17
+
+#define DSP_CONNECTED_OPTION_TRELLIS             0x0001
+#define DSP_CONNECTED_OPTION_V42_TRANS           0x0002
+#define DSP_CONNECTED_OPTION_V42_LAPM            0x0004
+#define DSP_CONNECTED_OPTION_SHORT_TRAIN         0x0008
+#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010
+
+
+#define DSP_UDATA_INDICATION_DISCONNECT         5
+/*
+returns:
+  <byte> cause
+*/
+
+#define DSP_DISCONNECT_CAUSE_NONE               0x00
+#define DSP_DISCONNECT_CAUSE_BUSY_TONE          0x01
+#define DSP_DISCONNECT_CAUSE_CONGESTION_TONE    0x02
+#define DSP_DISCONNECT_CAUSE_INCOMPATIBILITY    0x03
+#define DSP_DISCONNECT_CAUSE_CLEARDOWN          0x04
+#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT   0x05
+
+
+#define DSP_UDATA_INDICATION_TX_CONFIRMATION    6
+/*
+returns:
+  <word> confirmation number
+*/
+
+
+#define DSP_UDATA_REQUEST_SEND_DTMF_DIGITS      16
+/*
+parameters:
+  <word> tone duration (ms)
+  <word> gap duration (ms)
+  <byte> digit 0 tone code
+  ...
+  <byte> digit n tone code
+*/
+
+#define DSP_SEND_DTMF_DIGITS_HEADER_LENGTH      5
+
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_697_HZ    0x00
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_770_HZ    0x01
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_852_HZ    0x02
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_941_HZ    0x03
+#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_MASK      0x03
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ  0x00
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ  0x04
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ  0x08
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ  0x0c
+#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_MASK     0x0c
+
+#define DSP_DTMF_DIGIT_TONE_CODE_0              0x07
+#define DSP_DTMF_DIGIT_TONE_CODE_1              0x00
+#define DSP_DTMF_DIGIT_TONE_CODE_2              0x04
+#define DSP_DTMF_DIGIT_TONE_CODE_3              0x08
+#define DSP_DTMF_DIGIT_TONE_CODE_4              0x01
+#define DSP_DTMF_DIGIT_TONE_CODE_5              0x05
+#define DSP_DTMF_DIGIT_TONE_CODE_6              0x09
+#define DSP_DTMF_DIGIT_TONE_CODE_7              0x02
+#define DSP_DTMF_DIGIT_TONE_CODE_8              0x06
+#define DSP_DTMF_DIGIT_TONE_CODE_9              0x0a
+#define DSP_DTMF_DIGIT_TONE_CODE_STAR           0x03
+#define DSP_DTMF_DIGIT_TONE_CODE_HASHMARK       0x0b
+#define DSP_DTMF_DIGIT_TONE_CODE_A              0x0c
+#define DSP_DTMF_DIGIT_TONE_CODE_B              0x0d
+#define DSP_DTMF_DIGIT_TONE_CODE_C              0x0e
+#define DSP_DTMF_DIGIT_TONE_CODE_D              0x0f
+
+
+#define DSP_UDATA_INDICATION_DTMF_DIGITS_SENT   16
+/*
+returns:
+  - none -
+  One indication will be sent for every request.
+*/
+
+
+#define DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER  17
+/*
+parameters:
+  <word> tone duration (ms)
+  <word> gap duration (ms)
+*/
+typedef struct enable_dtmf_s {
+	__u16 tone;
+	__u16 gap;
+} enable_dtmf_s;
+
+#define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18
+/*
+parameters:
+  - none -
+*/
+
+#define DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17
+/*
+returns:
+  <byte> digit 0 tone code
+  ...
+  <byte> digit n tone code
+*/
+
+#define DSP_DTMF_DIGITS_RECEIVED_HEADER_LENGTH  1
+
+
+#define DSP_UDATA_INDICATION_MODEM_CALLING_TONE 18
+/*
+returns:
+  - none -
+*/
+
+#define DSP_UDATA_INDICATION_FAX_CALLING_TONE   19
+/*
+returns:
+  - none -
+*/
+
+#define DSP_UDATA_INDICATION_ANSWER_TONE        20
+/*
+returns:
+  - none -
+*/
+
+#endif	/* DSP_H */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_idi.c linux.pre11.3/drivers/isdn/eicon/eicon_idi.c
--- linux.vanilla/drivers/isdn/eicon/eicon_idi.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_idi.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,1638 @@
+/* $Id: eicon_idi.c,v 1.10 1999/07/11 17:16:24 armin Exp $
+ *
+ * ISDN lowlevel-module for Eicon.Diehl active cards.
+ *        IDI interface 
+ *
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_idi.c,v $
+ * Revision 1.10  1999/07/11 17:16:24  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.9  1999/03/29 11:19:42  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.8  1999/03/02 12:37:43  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.7  1999/02/03 18:34:35  armin
+ * Channel selection for outgoing calls w/o CHI.
+ * Added channel # in debug messages.
+ * L2 Transparent should work with 800 byte/packet now.
+ *
+ * Revision 1.6  1999/01/26 07:18:59  armin
+ * Bug with wrong added CPN fixed.
+ *
+ * Revision 1.5  1999/01/24 20:14:11  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.4  1999/01/10 18:46:05  armin
+ * Bug with wrong values in HLC fixed.
+ * Bytes to send are counted and limited now.
+ *
+ * Revision 1.3  1999/01/05 14:49:34  armin
+ * Added experimental usage of full BC and HLC for
+ * speech, 3.1kHz audio, fax gr.2/3
+ *
+ * Revision 1.2  1999/01/04 13:19:29  armin
+ * Channel status with listen-request wrong - fixed.
+ *
+ * Revision 1.1  1999/01/01 18:09:41  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "eicon.h"
+#include "eicon_idi.h"
+#include "eicon_dsp.h"
+
+#undef EICON_FULL_SERVICE_OKTETT
+
+char *eicon_idi_revision = "$Revision: 1.10 $";
+
+eicon_manifbuf *manbuf;
+
+static char BC_Speech[3] = 	{ 0x80, 0x90, 0xa3 };
+static char BC_31khz[3] =  	{ 0x90, 0x90, 0xa3 };
+static char BC_64k[2] =    	{ 0x88, 0x90 };
+static char BC_video[3] =  	{ 0x91, 0x90, 0xa5 };
+
+#ifdef EICON_FULL_SERVICE_OKTETT
+/* 
+static char HLC_telephony[2] =	{ 0x91, 0x81 }; 
+*/
+static char HLC_faxg3[2] =  	{ 0x91, 0x84 };
+#endif
+
+int eicon_idi_manage_assign(eicon_card *card);
+int eicon_idi_manage_remove(eicon_card *card);
+
+int
+idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
+{
+	int l = 0;
+	int tmp;
+
+	tmp = 0;
+  if (!signet) {
+	/* Signal Layer */
+	reqbuf->XBuffer.P[l++] = CAI;
+	reqbuf->XBuffer.P[l++] = 1;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = KEY;
+	reqbuf->XBuffer.P[l++] = 3;
+	reqbuf->XBuffer.P[l++] = 'I';
+	reqbuf->XBuffer.P[l++] = '4';
+	reqbuf->XBuffer.P[l++] = 'L';
+	reqbuf->XBuffer.P[l++] = SHIFT|6;
+	reqbuf->XBuffer.P[l++] = SIN;
+	reqbuf->XBuffer.P[l++] = 2;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0; /* end */
+	reqbuf->Req = ASSIGN;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 0;
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 0; /* Sig Entity */
+  }
+  else {
+	/* Network Layer */
+	reqbuf->XBuffer.P[l++] = CAI;
+	reqbuf->XBuffer.P[l++] = 1;
+	reqbuf->XBuffer.P[l++] = chan->e.D3Id;
+	reqbuf->XBuffer.P[l++] = LLC;
+	reqbuf->XBuffer.P[l++] = 2;
+	switch(chan->l2prot) {
+		case ISDN_PROTO_L2_HDLC:
+			reqbuf->XBuffer.P[l++] = 2;
+			break;
+		case ISDN_PROTO_L2_X75I:
+		case ISDN_PROTO_L2_X75UI:
+		case ISDN_PROTO_L2_X75BUI:
+			reqbuf->XBuffer.P[l++] = 5; 
+			break;
+		case ISDN_PROTO_L2_TRANS:
+		case ISDN_PROTO_L2_MODEM:
+			reqbuf->XBuffer.P[l++] = 2;
+			break;
+		default:
+			reqbuf->XBuffer.P[l++] = 1;
+	}
+	switch(chan->l3prot) {
+		case ISDN_PROTO_L3_TRANS:
+		default:
+			reqbuf->XBuffer.P[l++] = 4;
+	}
+	reqbuf->XBuffer.P[l++] = 0; /* end */
+	reqbuf->Req = ASSIGN;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 0x20;
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 1; /* Net Entity */
+  }
+   return(0);
+}
+
+int
+idi_put_req(eicon_REQ *reqbuf, int rq, int signet)
+{
+	reqbuf->Req = rq;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+	reqbuf->XBuffer.length = 1;
+	reqbuf->XBuffer.P[0] = 0;
+	reqbuf->Reference = signet;
+   return(0);
+}
+
+int
+idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
+{
+	int l = 9;
+	reqbuf->Req = CALL_RES;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+	reqbuf->XBuffer.P[0] = CAI;
+	reqbuf->XBuffer.P[1] = 6;
+	reqbuf->XBuffer.P[2] = 9;
+	reqbuf->XBuffer.P[3] = 0;
+	reqbuf->XBuffer.P[4] = 0;
+	reqbuf->XBuffer.P[5] = 0;
+	reqbuf->XBuffer.P[6] = 32;
+	reqbuf->XBuffer.P[7] = 3;
+	switch(chan->l2prot) {
+		case ISDN_PROTO_L2_X75I:
+		case ISDN_PROTO_L2_X75UI:
+		case ISDN_PROTO_L2_X75BUI:
+		case ISDN_PROTO_L2_HDLC:
+			reqbuf->XBuffer.P[1] = 1;
+			reqbuf->XBuffer.P[2] = 0x05;
+			l = 4;
+			break;
+		case ISDN_PROTO_L2_V11096:
+			reqbuf->XBuffer.P[2] = 0x0d;
+			reqbuf->XBuffer.P[3] = 5;
+			reqbuf->XBuffer.P[4] = 0;
+			break;
+		case ISDN_PROTO_L2_V11019:
+			reqbuf->XBuffer.P[2] = 0x0d;
+			reqbuf->XBuffer.P[3] = 6;
+			reqbuf->XBuffer.P[4] = 0;
+			break;
+		case ISDN_PROTO_L2_V11038:
+			reqbuf->XBuffer.P[2] = 0x0d;
+			reqbuf->XBuffer.P[3] = 7;
+			reqbuf->XBuffer.P[4] = 0;
+			break;
+		case ISDN_PROTO_L2_MODEM:
+			reqbuf->XBuffer.P[2] = 0x11;
+			reqbuf->XBuffer.P[3] = 7;
+			reqbuf->XBuffer.P[4] = 0;
+			reqbuf->XBuffer.P[5] = 0;
+			reqbuf->XBuffer.P[6] = 128;
+			reqbuf->XBuffer.P[7] = 0;
+			break;
+		case ISDN_PROTO_L2_TRANS:
+			switch(chan->l3prot) {
+				case ISDN_PROTO_L3_TRANSDSP:
+					reqbuf->XBuffer.P[2] = 22; /* DTMF, audio events on */
+			}
+			break;
+	}
+	reqbuf->XBuffer.P[8] = 0;
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 0; /* Sig Entity */
+	if (DebugVar & 8)
+		printk(KERN_DEBUG"idi_req: Ch%d: Call_Res\n", chan->No);
+   return(0);
+}
+
+int
+idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
+{
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+	eicon_REQ *reqbuf;
+	eicon_chan_ptr *chan2;
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                return -ENOMEM; 
+	}
+
+	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+	chan2->ptr = chan;
+
+	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+	if (DebugVar & 8)
+		printk(KERN_DEBUG "idi_req: Ch%d: 0x%02x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig");
+	if (layer) cmd |= 0x700;
+	switch(cmd) {
+		case ASSIGN:
+		case ASSIGN|0x700:
+			idi_assign_req(reqbuf, layer, chan);
+			break;
+		case REMOVE:
+		case REMOVE|0x700:
+			idi_put_req(reqbuf, REMOVE, layer);
+			break;
+		case INDICATE_REQ:
+			idi_put_req(reqbuf, INDICATE_REQ, 0);
+			break;
+		case HANGUP:
+			idi_put_req(reqbuf, HANGUP, 0);
+			break;
+		case REJECT:
+			idi_put_req(reqbuf, REJECT, 0);
+			break;
+		case CALL_ALERT:
+			idi_put_req(reqbuf, CALL_ALERT, 0);
+			break;
+		case CALL_RES:
+			idi_call_res_req(reqbuf, chan);
+			break;
+		case IDI_N_CONNECT|0x700:
+			idi_put_req(reqbuf, IDI_N_CONNECT, 1);
+			break;
+		case IDI_N_CONNECT_ACK|0x700:
+			idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1);
+			break;
+		case IDI_N_DISC|0x700:
+			idi_put_req(reqbuf, IDI_N_DISC, 1);
+			break;
+		case IDI_N_DISC_ACK|0x700:
+			idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
+			break;
+		default:
+			if (DebugVar & 1)
+				printk(KERN_ERR "idi_req: Ch%d: Unknown request\n", chan->No);
+			return(-1);
+	}
+
+	skb_queue_tail(&chan->e.X, skb);
+	skb_queue_tail(&card->sndq, skb2); 
+	eicon_schedule_tx(card);
+	return(0);
+}
+
+int
+eicon_idi_listen_req(eicon_card *card, eicon_chan *chan)
+{
+	if (DebugVar & 16)
+		printk(KERN_DEBUG"idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask);
+	if (!chan->e.D3Id) {
+		idi_do_req(card, chan, ASSIGN, 0); 
+	}
+	if (chan->fsm_state == EICON_STATE_NULL) {
+		idi_do_req(card, chan, INDICATE_REQ, 0);
+		chan->fsm_state = EICON_STATE_LISTEN;
+	}
+  return(0);
+}
+
+unsigned char
+idi_si2bc(int si1, int si2, char *bc, char *hlc)
+{
+  hlc[0] = 0;
+  switch(si1) {
+	case 1:
+		bc[0] = 0x90;		/* 3,1 kHz audio */
+		bc[1] = 0x90;		/* 64 kbit/s */
+		bc[2] = 0xa3;		/* G.711 A-law */
+#ifdef EICON_FULL_SERVICE_OKTETT
+		if (si2 == 1) {
+			bc[0] = 0x80;	/* Speech */
+			hlc[0] = 0x02;	/* hlc len */
+			hlc[1] = 0x91;	/* first hic */
+			hlc[2] = 0x81;	/* Telephony */
+		}
+#endif
+		return(3);
+	case 2:
+		bc[0] = 0x90;		/* 3,1 kHz audio */
+		bc[1] = 0x90;		/* 64 kbit/s */
+		bc[2] = 0xa3;		/* G.711 A-law */
+#ifdef EICON_FULL_SERVICE_OKTETT
+		if (si2 == 2) {
+			hlc[0] = 0x02;	/* hlc len */
+			hlc[1] = 0x91;	/* first hic */
+			hlc[2] = 0x84;	/* Fax Gr.2/3 */
+		}
+#endif
+		return(3);
+	case 5:
+	case 7:
+	default:
+		bc[0] = 0x88;
+		bc[1] = 0x90;
+		return(2);
+  }
+ return (0);
+}
+
+int
+idi_hangup(eicon_card *card, eicon_chan *chan)
+{
+	if ((chan->fsm_state == EICON_STATE_ACTIVE) ||
+	    (chan->fsm_state == EICON_STATE_WMCONN)) {
+  		if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1);
+	}
+	if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
+	idi_do_req(card, chan, HANGUP, 0);
+	chan->fsm_state = EICON_STATE_NULL;
+	if (DebugVar & 8)
+		printk(KERN_DEBUG"idi_req: Ch%d: Hangup\n", chan->No);
+  return(0);
+}
+
+int
+idi_connect_res(eicon_card *card, eicon_chan *chan)
+{
+  chan->fsm_state = EICON_STATE_IWAIT;
+  idi_do_req(card, chan, CALL_RES, 0);
+  idi_do_req(card, chan, ASSIGN, 1);
+  return(0);
+}
+
+int
+idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
+                    char *eazmsn, int si1, int si2)
+{
+	int l = 0;
+	int i;
+	unsigned char tmp;
+	unsigned char bc[5];
+	unsigned char hlc[5];
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+	eicon_REQ *reqbuf;
+	eicon_chan_ptr *chan2;
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                return -ENOMEM; 
+	}
+
+	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+	chan2->ptr = chan;
+
+	reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+	reqbuf->Req = CALL_REQ;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+
+	reqbuf->XBuffer.P[l++] = CPN;
+	reqbuf->XBuffer.P[l++] = strlen(phone) + 1;
+	reqbuf->XBuffer.P[l++] = 0xc1;
+	for(i=0; i<strlen(phone);i++) 
+		reqbuf->XBuffer.P[l++] = phone[i];
+
+	reqbuf->XBuffer.P[l++] = OAD;
+	reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2;
+	reqbuf->XBuffer.P[l++] = 0x01;
+	reqbuf->XBuffer.P[l++] = 0x81;
+	for(i=0; i<strlen(eazmsn);i++) 
+		reqbuf->XBuffer.P[l++] = eazmsn[i];
+
+	if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
+		reqbuf->XBuffer.P[l++] = BC;
+		reqbuf->XBuffer.P[l++] = tmp;
+		for(i=0; i<tmp;i++) 
+			reqbuf->XBuffer.P[l++] = bc[i];
+		if ((tmp=hlc[0])) {
+			reqbuf->XBuffer.P[l++] = HLC;
+			reqbuf->XBuffer.P[l++] = tmp;
+			for(i=1; i<=tmp;i++) 
+				reqbuf->XBuffer.P[l++] = hlc[i];
+		}
+	}
+        reqbuf->XBuffer.P[l++] = CAI;
+        reqbuf->XBuffer.P[l++] = 6;
+        reqbuf->XBuffer.P[l++] = 0x09;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 0;
+	reqbuf->XBuffer.P[l++] = 32;
+	reqbuf->XBuffer.P[l++] = 3;
+        switch(chan->l2prot) {
+		case ISDN_PROTO_L2_X75I:
+		case ISDN_PROTO_L2_X75UI:
+		case ISDN_PROTO_L2_X75BUI:
+                case ISDN_PROTO_L2_HDLC:
+                        reqbuf->XBuffer.P[l-6] = 5;
+                        reqbuf->XBuffer.P[l-7] = 1;
+			l -= 5; 
+                        break;
+                case ISDN_PROTO_L2_V11096:
+                        reqbuf->XBuffer.P[l-7] = 3;
+                        reqbuf->XBuffer.P[l-6] = 0x0d;
+                        reqbuf->XBuffer.P[l-5] = 5;
+                        reqbuf->XBuffer.P[l-4] = 0;
+                        l -= 3;
+                        break;
+                case ISDN_PROTO_L2_V11019:
+                        reqbuf->XBuffer.P[l-7] = 3;
+                        reqbuf->XBuffer.P[l-6] = 0x0d;
+                        reqbuf->XBuffer.P[l-5] = 6;
+                        reqbuf->XBuffer.P[l-4] = 0;
+                        l -= 3;
+                        break;
+                case ISDN_PROTO_L2_V11038:
+                        reqbuf->XBuffer.P[l-7] = 3;
+                        reqbuf->XBuffer.P[l-6] = 0x0d;
+                        reqbuf->XBuffer.P[l-5] = 7;
+                        reqbuf->XBuffer.P[l-4] = 0;
+                        l -= 3;
+                        break;
+                case ISDN_PROTO_L2_MODEM:
+			reqbuf->XBuffer.P[l-6] = 0x11;
+			reqbuf->XBuffer.P[l-5] = 7;
+			reqbuf->XBuffer.P[l-4] = 0;
+			reqbuf->XBuffer.P[l-3] = 0;
+			reqbuf->XBuffer.P[l-2] = 128;
+			reqbuf->XBuffer.P[l-1] = 0;
+                        break;
+		case ISDN_PROTO_L2_TRANS:
+			switch(chan->l3prot) {
+				case ISDN_PROTO_L3_TRANSDSP:
+					reqbuf->XBuffer.P[l-6] = 22; /* DTMF, audio events on */
+			}
+			break;
+        }
+	
+	reqbuf->XBuffer.P[l++] = 0; /* end */
+	reqbuf->XBuffer.length = l;
+	reqbuf->Reference = 0; /* Sig Entity */
+
+	skb_queue_tail(&chan->e.X, skb);
+	skb_queue_tail(&card->sndq, skb2); 
+	eicon_schedule_tx(card);
+
+	if (DebugVar & 8)
+  		printk(KERN_DEBUG"idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone);
+   return(0);
+}
+
+
+void
+idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len)
+{
+	int i,j;
+	int pos = 0;
+	int codeset = 0;
+	int wlen = 0;
+	int lock = 0;
+	__u8 w;
+	__u16 code;
+	isdn_ctrl cmd;
+
+  memset(message, 0, sizeof(idi_ind_message));
+
+  if ((!len) || (!buffer[pos])) return;
+  while(pos <= len) {
+	w = buffer[pos++];
+	if (!w) return;
+	if (w & 0x80) {
+		wlen = 0;
+	}
+	else {
+		wlen = buffer[pos++];
+	}
+
+	if (pos > len) return;
+
+	if (lock & 0x80) lock &= 0x7f;
+	else codeset = lock;
+
+	if((w&0xf0) == SHIFT) {
+		codeset = w;
+		if(!(codeset & 0x08)) lock = codeset & 7;
+		codeset &= 7;
+		lock |= 0x80;
+	}
+	else {
+		if (w==ESC && wlen >=2) {
+			code = buffer[pos++]|0x800;
+			wlen--;
+		}
+		else code = w;
+		code |= (codeset<<8);
+
+		switch(code) {
+			case OAD:
+				j = 1;
+				if (wlen) {
+					message->plan = buffer[pos++];
+					if (message->plan &0x80) 
+						message->screen = 0;
+					else {
+						message->screen = buffer[pos++];
+						j = 2;
+					}
+				}
+				for(i=0; i < wlen-j; i++) 
+					message->oad[i] = buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, 
+						message->plan, message->screen, message->oad);
+				break;
+			case RDN:
+				j = 1;
+				if (wlen) {
+					if (!(buffer[pos++] & 0x80)) {
+						pos++; 
+						j = 2;
+					}
+				}
+				for(i=0; i < wlen-j; i++) 
+					message->rdn[i] = buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: RDN= %s\n", chan->No, 
+						message->rdn);
+				break;
+			case CPN:
+				for(i=0; i < wlen; i++) 
+					message->cpn[i] = buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No,
+						(__u8)message->cpn[0], message->cpn + 1);
+				break;
+			case DSA:
+				pos++;
+				for(i=0; i < wlen-1; i++) 
+					message->dsa[i] = buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa);
+				break;
+			case OSA:
+				pos++;
+				for(i=0; i < wlen-1; i++) 
+					message->osa[i] = buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
+				break;
+			case BC:
+				for(i=0; i < wlen; i++) 
+					message->bc[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No,
+						message->bc[0],message->bc[1],message->bc[2]);
+				break;
+			case 0x800|BC:
+				for(i=0; i < wlen; i++) 
+					message->e_bc[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]);
+				break;
+			case LLC:
+				for(i=0; i < wlen; i++) 
+					message->llc[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0],
+						message->llc[1],message->llc[2],message->llc[3]);
+				break;
+			case HLC:
+				for(i=0; i < wlen; i++) 
+					message->hlc[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No,
+						message->hlc[0], message->hlc[1],
+						message->hlc[2], message->hlc[3], message->hlc[4]);
+				break;
+			case DSP:
+			case 0x600|DSP:
+				for(i=0; i < wlen; i++) 
+					message->display[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: Display: %s\n", chan->No,
+						message->display);
+				break;
+			case 0x600|KEY:
+				for(i=0; i < wlen; i++) 
+					message->keypad[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: Keypad: %s\n", chan->No,
+						message->keypad);
+				break;
+			case NI:
+			case 0x600|NI:
+				if (wlen) {
+					if (DebugVar & 4) {
+						switch(buffer[pos] & 127) {
+							case 0:
+								printk(KERN_DEBUG"idi_inf: Ch%d: User suspended.\n", chan->No);
+								break;
+							case 1:
+								printk(KERN_DEBUG"idi_inf: Ch%d: User resumed.\n", chan->No);
+								break;
+							case 2:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Bearer service change.\n", chan->No);
+								break;
+							default:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Notification %x.\n", 
+										chan->No, buffer[pos] & 127);
+						}
+					}
+					pos += wlen;
+				}
+				break;
+			case PI:
+			case 0x600|PI:
+				if (wlen > 1) {
+					if (DebugVar & 4) {
+						switch(buffer[pos+1] & 127) {
+							case 1:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No);
+								break;
+							case 2:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No);
+								break;
+							case 3:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No);
+								break;
+							case 4:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No);
+								break;
+							case 5:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Interworking has occurred.\n", chan->No);
+								break;
+							case 8:
+								printk(KERN_DEBUG"idi_inf: Ch%d: In-band information available.\n", chan->No);
+								break;
+							default:
+								printk(KERN_DEBUG"idi_inf: Ch%d: Unknown Progress %x.\n", 
+										chan->No, buffer[pos+1] & 127);
+						}
+					}
+				}
+				pos += wlen;
+				break;
+			case CAU:
+				for(i=0; i < wlen; i++) 
+					message->cau[i] = buffer[pos++];
+				memcpy(&chan->cause, &message->cau, 2);
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: CAU=%d %d\n", chan->No,
+						message->cau[0],message->cau[1]);
+				break;
+			case 0x800|CAU:
+				for(i=0; i < wlen; i++) 
+					message->e_cau[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: ECAU=%d %d\n", chan->No,
+						message->e_cau[0],message->e_cau[1]);
+				break;
+			case 0x800|CHI:
+				for(i=0; i < wlen; i++) 
+					message->e_chi[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: ESC/CHI=%d\n", chan->No,
+						message->e_cau[0]);
+				break;
+			case 0x800|0x7a:
+				pos ++;
+				message->e_mt=buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt);
+				break;
+			case DT:
+				for(i=0; i < wlen; i++) 
+					message->dt[i] = buffer[pos++];
+				if (DebugVar & 4)
+					printk(KERN_DEBUG"idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No,
+						message->dt[2], message->dt[1], message->dt[0],
+						message->dt[3], message->dt[4], message->dt[5]);
+				break;
+			case 0x600|SIN:
+				for(i=0; i < wlen; i++) 
+					message->sin[i] = buffer[pos++];
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: SIN=%d %d\n", chan->No,
+						message->sin[0],message->sin[1]);
+				break;
+			case 0x600|CPS:
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: Called Party Status in ind\n", chan->No);
+				pos += wlen;
+				break;
+			case 0x600|CIF:
+				for (i = 0; i < wlen; i++)
+					if (buffer[pos + i] != '0') break;
+				memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i);
+				cmd.parm.num[wlen - i] = 0;
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num);
+				pos += wlen;
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_CINF;
+				cmd.arg = chan->No;
+				ccard->interface.statcallb(&cmd);
+				break;
+			case 0x600|DATE:
+				if (DebugVar & 2)
+					printk(KERN_DEBUG"idi_inf: Ch%d: Date in ind\n", chan->No);
+				pos += wlen;
+				break;
+			case 0xe08: 
+			case 0xe7a: 
+			case 0xe04: 
+			case 0xe00: 
+				/* *** TODO *** */
+			case CHA:
+				/* Charge advice */
+			case FTY:
+			case 0x600|FTY:
+			case CHI:
+			case 0x800:
+				/* Not yet interested in this */
+				pos += wlen;
+				break;
+			case 0x880:
+				/* Managment Information Element */
+				if (!manbuf) {
+					if (DebugVar & 1)
+						printk(KERN_WARNING"idi_err: manbuf not allocated\n");
+				}
+				else {
+					memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen);
+					manbuf->length[manbuf->count] = wlen;
+					manbuf->count++;
+					manbuf->pos += wlen;
+				}
+				pos += wlen;
+				break;
+			default:
+				pos += wlen;
+				if (DebugVar & 6)
+					printk(KERN_WARNING"idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", 
+						chan->No, code, wlen);
+		}
+	}
+  }
+}
+
+void
+idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2)
+{
+  si1[0] = 0;
+  si2[0] = 0;
+  if (memcmp(bc, BC_Speech, 3) == 0) {		/* Speech */
+	si1[0] = 1;
+#ifdef EICON_FULL_SERVICE_OKTETT
+	si2[0] = 1;
+#endif
+  }
+  if (memcmp(bc, BC_31khz, 3) == 0) {		/* 3.1kHz audio */
+	si1[0] = 1;
+#ifdef EICON_FULL_SERVICE_OKTETT
+	si2[0] = 2;
+  	if (memcmp(hlc, HLC_faxg3, 2) == 0) {	/* Fax Gr.2/3 */
+		si1[0] = 2;
+	}
+#endif
+  }
+  if (memcmp(bc, BC_64k, 2) == 0) {		/* unrestricted 64 kbits */
+	si1[0] = 7;
+  }
+  if (memcmp(bc, BC_video, 3) == 0) {		/* video */
+	si1[0] = 4;
+  }
+}
+
+int
+idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len)
+{
+	struct sk_buff *skb;
+	struct sk_buff *skb2;
+	eicon_REQ *reqbuf;
+	eicon_chan_ptr *chan2;
+
+	if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) {
+		if (DebugVar & 1)
+			printk(KERN_DEBUG"idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state);
+		return -ENODEV;
+	}
+	if (DebugVar & 8)
+		printk(KERN_DEBUG"idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No,
+				UReq, buffer[0], buffer[1], buffer[2], buffer[3]);
+
+	skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC);
+	skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+	if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+			printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+			return -ENOMEM;
+	}
+
+	chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+	chan2->ptr = chan;
+
+	reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
+
+	reqbuf->Req = IDI_N_UDATA;
+	reqbuf->ReqCh = 0;
+	reqbuf->ReqId = 1;
+
+	reqbuf->XBuffer.length = len + 1;
+	reqbuf->XBuffer.P[0] = UReq;
+	memcpy(&reqbuf->XBuffer.P[1], buffer, len);
+	reqbuf->Reference = 1; /* Net Entity */
+
+	skb_queue_tail(&chan->e.X, skb);
+	skb_queue_tail(&card->sndq, skb2);
+	eicon_schedule_tx(card);
+	return (0);
+}
+
+void
+idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value)
+{
+	u_char buf[6];
+	struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf;
+
+	memset(buf, 0, 6);
+	switch(cmd) {
+		case ISDN_AUDIO_SETDD:
+			if (value[0]) {
+				dtmf_buf->tone = (__u16) (value[1] * 5);
+				dtmf_buf->gap = (__u16) (value[1] * 5);
+				idi_send_udata(ccard, chan,
+					DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER,
+					buf, 4);
+			} else {
+				idi_send_udata(ccard, chan,
+					DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER,
+					buf, 0);
+			}
+			break;
+	}
+}
+
+void
+idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len)
+{
+	isdn_ctrl cmd;
+	eicon_dsp_ind *p = (eicon_dsp_ind *) (&buffer[1]);
+        static char *connmsg[] =
+        {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34",
+         "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90",
+         "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"};
+	static u_char dtmf_code[] = {
+	'1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'
+	};
+
+	switch (buffer[0]) {
+		case DSP_UDATA_INDICATION_SYNC:
+			if (DebugVar & 16)
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time);
+			break;
+		case DSP_UDATA_INDICATION_DCD_OFF:
+			if (DebugVar & 8)
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time);
+			break;
+		case DSP_UDATA_INDICATION_DCD_ON:
+			if ((chan->l2prot == ISDN_PROTO_L2_MODEM) &&
+			    (chan->fsm_state == EICON_STATE_WMCONN)) {
+				chan->fsm_state = EICON_STATE_ACTIVE;
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_BCONN;
+				cmd.arg = chan->No;
+				sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
+				ccard->interface.statcallb(&cmd);
+			}
+			if (DebugVar & 8) {
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time);
+				printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No,
+					    p->norm, p->options, p->speed, p->delay); 
+			    }
+			break;
+		case DSP_UDATA_INDICATION_CTS_OFF:
+			if (DebugVar & 8)
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time);
+			break;
+		case DSP_UDATA_INDICATION_CTS_ON:
+			if (DebugVar & 8) {
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time);
+				printk(KERN_DEBUG"idi_ind: Ch%d: %d %d %d %d\n", chan->No,
+					    p->norm, p->options, p->speed, p->delay); 
+			}
+			break;
+		case DSP_UDATA_INDICATION_DISCONNECT:
+			if (DebugVar & 8)
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]);
+			break;
+		case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED:
+			if (DebugVar & 8)
+  				printk(KERN_DEBUG"idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No,
+					dtmf_code[buffer[1]]);
+			cmd.driver = ccard->myid;
+			cmd.command = ISDN_STAT_AUDIO;
+			cmd.parm.num[0] = ISDN_AUDIO_DTMF;
+			cmd.parm.num[1] = dtmf_code[buffer[1]];
+			cmd.arg = chan->No;
+			ccard->interface.statcallb(&cmd);
+			break;
+		default:
+			if (DebugVar & 8)
+				printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]);
+	}
+}
+
+void
+idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
+{
+	int tmp;
+	int free_buff;
+	struct sk_buff *skb2;
+        eicon_IND *ind = (eicon_IND *)skb->data;
+	eicon_chan *chan;
+	idi_ind_message message;
+	isdn_ctrl cmd;
+
+	if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
+  		dev_kfree_skb(skb);
+		return;
+	}
+	
+	if ((DebugVar & 128) || 
+	   ((DebugVar & 16) && (ind->Ind != 8))) {
+        	printk(KERN_DEBUG "idi_hdl: Ch%d: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
+		        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
+	}
+
+	free_buff = 1;
+	/* Signal Layer */
+	if (chan->e.D3Id == ind->IndId) {
+		idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
+		switch(ind->Ind) {
+			case HANGUP:
+				if (DebugVar & 8)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: Hangup\n", chan->No);
+		                while((skb2 = skb_dequeue(&chan->e.X))) {
+					dev_kfree_skb(skb2);
+				}
+				chan->e.busy = 0;
+				chan->queued = 0;
+				chan->waitq = 0;
+				chan->waitpq = 0;
+				chan->fsm_state = EICON_STATE_NULL;
+				if (message.e_cau[0] & 0x7f) {
+					cmd.driver = ccard->myid;
+					cmd.arg = chan->No;
+					sprintf(cmd.parm.num,"E%02x%02x", 
+						chan->cause[0]&0x7f, message.e_cau[0]&0x7f); 
+					cmd.command = ISDN_STAT_CAUSE;
+					ccard->interface.statcallb(&cmd);
+				}
+				chan->cause[0] = 0; 
+				cmd.driver = ccard->myid;
+				cmd.arg = chan->No;
+				cmd.command = ISDN_STAT_DHUP;
+				ccard->interface.statcallb(&cmd);
+				eicon_idi_listen_req(ccard, chan);
+				break;
+			case INDICATE_IND:
+				if (DebugVar & 8)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: Indicate_Ind\n", chan->No);
+				chan->fsm_state = EICON_STATE_ICALL;
+				idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2);
+				strcpy(chan->cpn, message.cpn + 1);
+				if (strlen(message.dsa)) {
+					strcat(chan->cpn, ".");
+					strcat(chan->cpn, message.dsa);
+				}
+				strcpy(chan->oad, message.oad);
+				try_stat_icall_again: 
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_ICALL;
+				cmd.arg = chan->No;
+				cmd.parm.setup.si1 = chan->si1;
+				cmd.parm.setup.si2 = chan->si2;
+				strcpy(cmd.parm.setup.eazmsn, chan->cpn);
+				strcpy(cmd.parm.setup.phone, chan->oad);
+				cmd.parm.setup.plan = message.plan;
+				cmd.parm.setup.screen = message.screen;
+				tmp = ccard->interface.statcallb(&cmd);
+				switch(tmp) {
+					case 0: /* no user responding */
+						idi_do_req(ccard, chan, HANGUP, 0);
+						break;
+					case 1: /* alert */
+						if (DebugVar & 8)
+  							printk(KERN_DEBUG"idi_req: Ch%d: Call Alert\n", chan->No);
+						if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) {
+							chan->fsm_state = EICON_STATE_ICALL;
+							idi_do_req(ccard, chan, CALL_ALERT, 0);
+						}
+						break;
+					case 2: /* reject */
+						if (DebugVar & 8)
+  							printk(KERN_DEBUG"idi_req: Ch%d: Call Reject\n", chan->No);
+						idi_do_req(ccard, chan, REJECT, 0);
+						break;
+					case 3: /* incomplete number */
+						if (DebugVar & 8)
+  							printk(KERN_DEBUG"idi_req: Ch%d: Incomplete Number\n", chan->No);
+					        switch(ccard->type) {
+					                case EICON_CTYPE_MAESTRAP:
+					                case EICON_CTYPE_S2M:
+								/* TODO (other protocols) */
+								chan->fsm_state = EICON_STATE_ICALLW;
+								break;
+							default:
+								idi_do_req(ccard, chan, HANGUP, 0);
+						}
+						break;
+				}
+				break;
+			case INFO_IND:
+				if (DebugVar & 8)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: Info_Ind\n", chan->No);
+				if ((chan->fsm_state == EICON_STATE_ICALLW) &&
+				    (message.cpn[0])) {
+					strcat(chan->cpn, message.cpn + 1);
+					goto try_stat_icall_again;
+				}
+				break;
+			case CALL_IND:
+				if (DebugVar & 8)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: Call_Ind\n", chan->No);
+				if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) {
+					chan->fsm_state = EICON_STATE_IBWAIT;
+					cmd.driver = ccard->myid;
+					cmd.command = ISDN_STAT_DCONN;
+					cmd.arg = chan->No;
+					ccard->interface.statcallb(&cmd);
+					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+				} else
+					idi_hangup(ccard, chan);
+				break;
+			case CALL_CON:
+				if (DebugVar & 8)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: Call_Con\n", chan->No);
+				if (chan->fsm_state == EICON_STATE_OCALL) {
+					chan->fsm_state = EICON_STATE_OBWAIT;
+					cmd.driver = ccard->myid;
+					cmd.command = ISDN_STAT_DCONN;
+					cmd.arg = chan->No;
+					ccard->interface.statcallb(&cmd);
+					idi_do_req(ccard, chan, ASSIGN, 1); 
+					idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
+				} else
+				idi_hangup(ccard, chan);
+				break;
+			case AOC_IND:
+				if (DebugVar & 8)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: Advice of Charge\n", chan->No);
+				break;
+			default:
+				if (DebugVar & 8)
+					printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
+		}
+	}
+	/* Network Layer */
+	else if (chan->e.B2Id == ind->IndId) {
+
+		if (chan->No == ccard->nchannels) {
+			/* Management Indication */
+			idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
+			chan->fsm_state = 1;
+		} 
+		else
+		switch(ind->Ind) {
+			case IDI_N_CONNECT_ACK:
+				if (DebugVar & 16)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect_Ack\n", chan->No);
+				if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
+					chan->fsm_state = EICON_STATE_WMCONN;
+					break;
+				}
+				chan->fsm_state = EICON_STATE_ACTIVE;
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_BCONN;
+				cmd.arg = chan->No;
+				ccard->interface.statcallb(&cmd);
+				break; 
+			case IDI_N_CONNECT:
+				if (DebugVar & 16)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: N_Connect\n", chan->No);
+				if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
+				if (chan->l2prot == ISDN_PROTO_L2_MODEM) {
+					chan->fsm_state = EICON_STATE_WMCONN;
+					break;
+				}
+				chan->fsm_state = EICON_STATE_ACTIVE;
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_BCONN;
+				cmd.arg = chan->No;
+				ccard->interface.statcallb(&cmd);
+				break; 
+			case IDI_N_DISC:
+				if (DebugVar & 16)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC\n", chan->No);
+				if (chan->e.B2Id) {
+					idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1);
+					idi_do_req(ccard, chan, REMOVE, 1);
+				}
+				chan->queued = 0;
+				chan->waitq = 0;
+				chan->waitpq = 0;
+				if (chan->fsm_state == EICON_STATE_ACTIVE) {
+					cmd.driver = ccard->myid;
+					cmd.command = ISDN_STAT_BHUP;
+					cmd.arg = chan->No;
+					ccard->interface.statcallb(&cmd);
+				}
+				break; 
+			case IDI_N_DISC_ACK:
+				if (DebugVar & 16)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: N_DISC_ACK\n", chan->No);
+				break; 
+			case IDI_N_DATA_ACK:
+				if (DebugVar & 16)
+  					printk(KERN_DEBUG"idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
+				break;
+			case IDI_N_DATA:
+				skb_pull(skb, sizeof(eicon_IND) - 1);
+				if (DebugVar & 128)
+					printk(KERN_DEBUG"idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len);
+				ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb);
+				free_buff = 0; 
+				break; 
+			case IDI_N_UDATA:
+				idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
+				break; 
+			default:
+				if (DebugVar & 8)
+					printk(KERN_WARNING "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind);
+		}
+	}
+	else {
+		if (DebugVar & 1)
+			printk(KERN_ERR "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No);
+	}
+   if (free_buff) dev_kfree_skb(skb);
+}
+
+void
+idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
+{
+	isdn_ctrl cmd;
+
+	if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
+		/* I dont know why this happens, just ignoring this RC */
+		if (DebugVar & 16)
+			printk(KERN_DEBUG "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, 
+				ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id);
+		return;
+	}
+
+	/* Management Interface */	
+	if (chan->No == ccard->nchannels) {
+		/* Managementinterface: changing state */
+		if (chan->e.Req == 0x04)
+			chan->fsm_state = 1;
+	}
+
+	/* Remove an Id */
+	if (chan->e.Req == REMOVE) {
+		if (ack->Reference == chan->e.ref) {
+			ccard->IdTable[ack->RcId] = NULL;
+			if (DebugVar & 16)
+				printk(KERN_DEBUG "idi_ack: Ch%d: Removed : Id=%d Ch=%d (%s)\n", chan->No,
+					ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig");
+			if (!chan->e.ReqCh) 
+				chan->e.D3Id = 0;
+			else
+				chan->e.B2Id = 0;
+		}
+		else {
+			if (DebugVar & 1)
+				printk(KERN_DEBUG "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No,
+					ack->Reference, chan->e.ref);
+		}
+		return;
+	}
+
+	/* Signal layer */
+	if (!chan->e.ReqCh) {
+		if (DebugVar & 16)
+			printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+				ack->RcId, ack->RcCh, ack->Reference);
+	} else {
+	/* Network layer */
+		switch(chan->e.Req & 0x0f) {
+			case IDI_N_MDATA:
+			case IDI_N_DATA:
+				if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
+					if (chan->queued) {
+						cmd.driver = ccard->myid;
+						cmd.command = ISDN_STAT_BSENT;
+						cmd.arg = chan->No;
+						cmd.parm.length = chan->waitpq;
+						ccard->interface.statcallb(&cmd);
+					}
+					chan->waitpq = 0;
+				}
+				chan->queued -= chan->waitq;
+				if (chan->queued < 0) chan->queued = 0;
+				break;
+			default:
+				if (DebugVar & 16)
+					printk(KERN_DEBUG "idi_ack: Ch%d: RC OK Id=%d Ch=%d (ref:%d)\n", chan->No,
+						ack->RcId, ack->RcCh, ack->Reference);
+		}
+	}
+}
+
+void
+idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
+{
+	int j;
+        eicon_RC *ack = (eicon_RC *)skb->data;
+	eicon_chan *chan;
+	isdn_ctrl cmd;
+	int dCh = -1;
+
+	if ((chan = ccard->IdTable[ack->RcId]) != NULL)
+		dCh = chan->No;
+	
+
+	switch (ack->Rc) {
+		case OK_FC:
+		case N_FLOW_CONTROL:
+		case ASSIGN_RC:
+			if (DebugVar & 1)
+				printk(KERN_ERR "idi_ack: Ch%d: unhandled RC 0x%x\n",
+					dCh, ack->Rc);
+		case READY_INT:
+		case TIMER_INT:
+			/* we do nothing here */
+			break;
+
+		case OK:
+			if (!chan) {
+				if (DebugVar & 1)
+					printk(KERN_ERR "idi_ack: Ch%d: OK on chan without Id\n", dCh);
+				break;
+			}
+			idi_handle_ack_ok(ccard, chan, ack);
+			break;
+
+		case ASSIGN_OK:
+			if (chan) {
+				if (DebugVar & 1)
+					printk(KERN_ERR "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%d,%d)\n",
+						chan->No, chan->e.D3Id, chan->e.B2Id);
+			}
+			for(j = 0; j < ccard->nchannels + 1; j++) {
+				if (ccard->bch[j].e.ref == ack->Reference) {
+					if (!ccard->bch[j].e.ReqCh) 
+						ccard->bch[j].e.D3Id  = ack->RcId;
+					else
+						ccard->bch[j].e.B2Id  = ack->RcId;
+					ccard->IdTable[ack->RcId] = &ccard->bch[j];
+					ccard->bch[j].e.busy = 0;
+					ccard->bch[j].e.ref = 0;
+					if (DebugVar & 16)
+						printk(KERN_DEBUG"idi_ack: Ch%d: Id %d assigned (%s)\n", j, 
+							ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
+					break;
+				}
+			}		
+			if (j > ccard->nchannels) {
+				if (DebugVar & 24)
+					printk(KERN_DEBUG"idi_ack: Ch??: ref %d not found for Id %d\n", 
+						ack->Reference, ack->RcId);
+			}
+			break;
+
+		case OUT_OF_RESOURCES:
+		case UNKNOWN_COMMAND:
+		case WRONG_COMMAND:
+		case WRONG_ID:
+		case WRONG_CH:
+		case UNKNOWN_IE:
+		case WRONG_IE:
+		default:
+			chan->e.busy = 0;
+			if (DebugVar & 24)
+				printk(KERN_ERR "eicon_ack: Ch%d: Not OK: Rc=%d Id=%d Ch=%d\n", dCh, 
+					ack->Rc, ack->RcId, ack->RcCh);
+			if (dCh == ccard->nchannels) { /* Management */
+				chan->fsm_state = 2;
+			} else if (dCh >= 0) {
+					/* any other channel */
+					/* card reports error: we hangup */
+				idi_hangup(ccard, chan);
+				cmd.driver = ccard->myid;
+				cmd.command = ISDN_STAT_DHUP;
+				cmd.arg = chan->No;
+				ccard->interface.statcallb(&cmd);
+			}
+	}
+	if (chan)
+		chan->e.busy = 0;
+	dev_kfree_skb(skb);
+	eicon_schedule_tx(ccard);
+}
+
+int
+idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que)
+{
+        struct sk_buff *xmit_skb;
+        struct sk_buff *skb2;
+        eicon_REQ *reqbuf;
+        eicon_chan_ptr *chan2;
+        int len, plen = 0, offset = 0;
+	unsigned long flags;
+
+        if (chan->fsm_state != EICON_STATE_ACTIVE) {
+		if (DebugVar & 1)
+			printk(KERN_DEBUG"idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state);
+                return -ENODEV;
+	}
+
+        len = skb->len;
+	if (len > 2138)	/* too much for the shared memory */
+		return -1;
+        if (!len)
+                return 0;
+	if (chan->queued + len > ((chan->l2prot == ISDN_PROTO_L2_TRANS) ? 4000 : EICON_MAX_QUEUED))
+		return 0;
+	if (DebugVar & 128)
+		printk(KERN_DEBUG"idi_snd: Ch%d: %d bytes\n", chan->No, len);
+
+	save_flags(flags);
+	cli();
+	while(offset < len) {
+
+		plen = ((len - offset) > 270) ? 270 : len - offset;
+
+	        xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC);
+        	skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+	        if ((!skb) || (!skb2)) {
+			restore_flags(flags);
+			if (DebugVar & 1)
+	        	        printk(KERN_WARNING "idi_err: Ch%d: alloc_skb failed\n", chan->No);
+                	return -ENOMEM;
+	        }
+
+	        chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+        	chan2->ptr = chan;
+
+	        reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
+		if (((len - offset) > 270) &&
+			(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
+		        reqbuf->Req = IDI_N_MDATA;
+		} else {
+		        reqbuf->Req = IDI_N_DATA;
+			if (ack) reqbuf->Req |= N_D_BIT;
+		}	
+        	reqbuf->ReqCh = 0;
+	        reqbuf->ReqId = 1;
+		memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen);
+		reqbuf->XBuffer.length = plen;
+		reqbuf->Reference = 1; /* Net Entity */
+
+		skb_queue_tail(&chan->e.X, xmit_skb);
+		skb_queue_tail(&card->sndq, skb2); 
+
+		offset += plen;
+	}
+	if (que)
+		chan->queued += len;
+	restore_flags(flags);
+	eicon_schedule_tx(card);
+        dev_kfree_skb(skb);
+        return len;
+}
+
+
+
+int
+eicon_idi_manage_assign(eicon_card *card)
+{
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+        eicon_REQ  *reqbuf;
+        eicon_chan     *chan;
+        eicon_chan_ptr *chan2;
+
+        chan = &(card->bch[card->nchannels]);
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+			printk(KERN_WARNING "idi_err: alloc_skb failed\n");
+                return -ENOMEM;
+        }
+
+        chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+        chan2->ptr = chan;
+
+        reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+
+        reqbuf->XBuffer.P[0] = 0;
+        reqbuf->Req = ASSIGN;
+        reqbuf->ReqCh = 0;
+        reqbuf->ReqId = 0xe0;
+        reqbuf->XBuffer.length = 1;
+        reqbuf->Reference = 2; /* Man Entity */
+
+        skb_queue_tail(&chan->e.X, skb);
+        skb_queue_tail(&card->sndq, skb2);
+        eicon_schedule_tx(card);
+        return(0);
+}
+
+
+int
+eicon_idi_manage_remove(eicon_card *card)
+{
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+        eicon_REQ  *reqbuf;
+        eicon_chan     *chan;
+        eicon_chan_ptr *chan2;
+
+        chan = &(card->bch[card->nchannels]);
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err: alloc_skb failed\n");
+                return -ENOMEM;
+        }
+
+        chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+        chan2->ptr = chan;
+
+        reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+
+        reqbuf->Req = REMOVE;
+        reqbuf->ReqCh = 0;
+        reqbuf->ReqId = 1;
+        reqbuf->XBuffer.length = 0;
+        reqbuf->Reference = 2; /* Man Entity */
+
+        skb_queue_tail(&chan->e.X, skb);
+        skb_queue_tail(&card->sndq, skb2);
+        eicon_schedule_tx(card);
+        return(0);
+}
+
+
+int
+eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
+{
+	int l = 0;
+	int ret = 0;
+	int timeout;
+	int i;
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+        eicon_REQ  *reqbuf;
+        eicon_chan     *chan;
+        eicon_chan_ptr *chan2;
+
+        chan = &(card->bch[card->nchannels]);
+
+	if (chan->e.D3Id) return -EBUSY;
+	chan->e.D3Id = 1;
+	while((skb2 = skb_dequeue(&chan->e.X)))
+		dev_kfree_skb(skb2);
+	chan->e.busy = 0;
+ 
+	if ((ret = eicon_idi_manage_assign(card))) {
+		chan->e.D3Id = 0;
+		return(ret); 
+	}
+
+        timeout = jiffies + 50;
+        while (timeout > jiffies) {
+                if (chan->e.B2Id) break;
+                SLEEP(10);
+        }
+        if (!chan->e.B2Id) {
+		chan->e.D3Id = 0;
+		return -EIO;
+	}
+
+	chan->fsm_state = 0;
+
+	if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err: alloc_manifbuf failed\n");
+		chan->e.D3Id = 0;
+		return -ENOMEM;
+	}
+	if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
+		chan->e.D3Id = 0;
+		return -EFAULT;
+	}
+
+        skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC);
+        skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
+
+        if ((!skb) || (!skb2)) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "idi_err_manif: alloc_skb failed\n");
+		kfree(manbuf);
+		chan->e.D3Id = 0;
+                return -ENOMEM;
+        }
+
+        chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr));
+        chan2->ptr = chan;
+
+        reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ));
+
+        reqbuf->XBuffer.P[l++] = ESC;
+        reqbuf->XBuffer.P[l++] = 6;
+        reqbuf->XBuffer.P[l++] = 0x80;
+	for (i = 0; i < manbuf->length[0]; i++)
+	        reqbuf->XBuffer.P[l++] = manbuf->data[i];
+        reqbuf->XBuffer.P[1] = manbuf->length[0] + 1;
+
+        reqbuf->XBuffer.P[l++] = 0;
+        reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */
+        reqbuf->ReqCh = 0;
+        reqbuf->ReqId = 1;
+        reqbuf->XBuffer.length = l;
+        reqbuf->Reference = 2; /* Man Entity */
+
+        skb_queue_tail(&chan->e.X, skb);
+        skb_queue_tail(&card->sndq, skb2);
+
+	manbuf->count = 0;
+	manbuf->pos = 0;
+
+        eicon_schedule_tx(card);
+
+        timeout = jiffies + 50;
+        while (timeout > jiffies) {
+                if (chan->fsm_state) break;
+                SLEEP(10);
+        }
+        if ((!chan->fsm_state) || (chan->fsm_state == 2)) {
+		eicon_idi_manage_remove(card);
+		kfree(manbuf);
+		chan->e.D3Id = 0;
+		return -EIO;
+	}
+
+	if ((ret = eicon_idi_manage_remove(card))) {
+		chan->e.D3Id = 0;
+		return(ret);
+	}
+
+	if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
+		chan->e.D3Id = 0;
+		return -EFAULT;
+	}
+
+	kfree(manbuf);
+	chan->e.D3Id = 0;
+  return(0);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_idi.h linux.pre11.3/drivers/isdn/eicon/eicon_idi.h
--- linux.vanilla/drivers/isdn/eicon/eicon_idi.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_idi.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,260 @@
+/* $Id: eicon_idi.h,v 1.5 1999/07/11 17:16:26 armin Exp $
+ *
+ * ISDN lowlevel-module for the Eicon.Diehl active cards.
+ * IDI-Interface
+ *
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_idi.h,v $
+ * Revision 1.5  1999/07/11 17:16:26  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.4  1999/03/29 11:19:44  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.3  1999/03/02 12:37:45  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.2  1999/01/24 20:14:18  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.1  1999/01/01 18:09:42  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#ifndef IDI_H
+#define IDI_H
+
+
+#define ASSIGN  0x01
+#define REMOVE  0xff
+	
+#define CALL_REQ 1      /* call request                             */
+#define CALL_CON 1      /* call confirmation                        */
+#define CALL_IND 2      /* incoming call connected                  */
+#define LISTEN_REQ 2    /* listen request                           */
+#define HANGUP 3        /* hangup request/indication                */
+#define SUSPEND 4       /* call suspend request/confirm             */
+#define RESUME 5        /* call resume request/confirm              */
+#define SUSPEND_REJ 6   /* suspend rejected indication              */
+#define USER_DATA 8     /* user data for user to user signaling     */
+#define CONGESTION 9    /* network congestion indication            */
+#define INDICATE_REQ 10 /* request to indicate an incoming call     */
+#define INDICATE_IND 10 /* indicates that there is an incoming call */
+#define CALL_RES 11     /* accept an incoming call                  */
+#define CALL_ALERT 12   /* send ALERT for incoming call             */
+#define INFO_REQ 13     /* INFO request                             */
+#define INFO_IND 13     /* INFO indication                          */
+#define REJECT 14       /* reject an incoming call                  */
+#define RESOURCES 15    /* reserve B-Channel hardware resources     */
+#define TEL_CTRL 16     /* Telephone control request/indication     */
+#define STATUS_REQ 17   /* Request D-State (returned in INFO_IND)   */
+#define FAC_REG_REQ 18  /* connection idependent fac registration   */
+#define FAC_REG_ACK 19  /* fac registration acknowledge             */
+#define FAC_REG_REJ 20  /* fac registration reject                  */
+#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call       */
+#define AOC_IND       26/* Advice of Charge                         */
+
+#define IDI_N_MDATA         (0x01)
+#define IDI_N_CONNECT       (0x02)
+#define IDI_N_CONNECT_ACK   (0x03)
+#define IDI_N_DISC          (0x04)
+#define IDI_N_DISC_ACK      (0x05)
+#define IDI_N_RESET         (0x06)
+#define IDI_N_RESET_ACK     (0x07)
+#define IDI_N_DATA          (0x08)
+#define IDI_N_EDATA         (0x09)
+#define IDI_N_UDATA         (0x0a)
+#define IDI_N_BDATA         (0x0b)
+#define IDI_N_DATA_ACK      (0x0c)
+#define IDI_N_EDATA_ACK     (0x0d)
+
+#define N_Q_BIT         0x10    /* Q-bit for req/ind                */
+#define N_M_BIT         0x20    /* M-bit for req/ind                */
+#define N_D_BIT         0x40    /* D-bit for req/ind                */
+
+
+#define SHIFT 0x90              /* codeset shift                    */
+#define MORE 0xa0               /* more data                        */
+#define CL 0xb0                 /* congestion level                 */
+
+        /* codeset 0                                                */
+
+#define BC  0x04                /* Bearer Capability                */
+#define CAU 0x08                /* cause                            */
+#define CAD 0x0c                /* Connected address                */
+#define CAI 0x10                /* call identity                    */
+#define CHI 0x18                /* channel identification           */
+#define LLI 0x19                /* logical link id                  */
+#define CHA 0x1a                /* charge advice                    */
+#define FTY 0x1c
+#define PI  0x1e		/* Progress Indicator		    */
+#define NI  0x27		/* Notification Indicator	    */
+#define DT  0x29                /* ETSI date/time                   */
+#define KEY 0x2c                /* keypad information element       */
+#define DSP 0x28                /* display                          */
+#define OAD 0x6c                /* origination address              */
+#define OSA 0x6d                /* origination sub-address          */
+#define CPN 0x70                /* called party number              */
+#define DSA 0x71                /* destination sub-address          */
+#define RDN 0x74		/* redirecting number		    */
+#define LLC 0x7c                /* low layer compatibility          */
+#define HLC 0x7d                /* high layer compatibility         */
+#define UUI 0x7e                /* user user information            */
+#define ESC 0x7f                /* escape extension                 */
+
+#define DLC 0x20                /* data link layer configuration    */
+#define NLC 0x21                /* network layer configuration      */
+
+        /* codeset 6                                                */
+
+#define SIN 0x01                /* service indicator                */
+#define CIF 0x02                /* charging information             */
+#define DATE 0x03               /* date                             */
+#define CPS 0x07                /* called party status              */
+
+/*------------------------------------------------------------------*/
+/* return code coding                                               */
+/*------------------------------------------------------------------*/
+
+#define UNKNOWN_COMMAND         0x01    /* unknown command          */
+#define WRONG_COMMAND           0x02    /* wrong command            */
+#define WRONG_ID                0x03    /* unknown task/entity id   */
+#define WRONG_CH                0x04    /* wrong task/entity id     */
+#define UNKNOWN_IE              0x05    /* unknown information el.  */
+#define WRONG_IE                0x06    /* wrong information el.    */
+#define OUT_OF_RESOURCES        0x07    /* card out of res.         */
+#define N_FLOW_CONTROL          0x10    /* Flow-Control, retry      */
+#define ASSIGN_RC               0xe0    /* ASSIGN acknowledgement   */
+#define ASSIGN_OK               0xef    /* ASSIGN OK                */
+#define OK_FC                   0xfc    /* Flow-Control RC          */
+#define READY_INT               0xfd    /* Ready interrupt          */
+#define TIMER_INT               0xfe    /* timer interrupt          */
+#define OK                      0xff    /* command accepted         */
+
+/*------------------------------------------------------------------*/
+
+typedef struct {
+	char cpn[32];
+	char oad[32];
+	char dsa[32];
+	char osa[32];
+	__u8 plan;
+	__u8 screen;
+	__u8 sin[4];
+	__u8 chi[4];
+	__u8 e_chi[4];
+	__u8 bc[12];
+	__u8 e_bc[12];
+ 	__u8 llc[18];
+	__u8 hlc[5];
+	__u8 cau[4];
+	__u8 e_cau[2];
+	__u8 e_mt;
+	__u8 dt[6];
+	char display[83];
+	char keypad[35];
+	char rdn[32];
+} idi_ind_message;
+
+typedef struct { 
+  __u16 next            __attribute__ ((packed));
+  __u8  Req             __attribute__ ((packed));
+  __u8  ReqId           __attribute__ ((packed));
+  __u8  ReqCh           __attribute__ ((packed));
+  __u8  Reserved1       __attribute__ ((packed));
+  __u16 Reference       __attribute__ ((packed));
+  __u8  Reserved[8]     __attribute__ ((packed));
+  eicon_PBUFFER XBuffer; 
+} eicon_REQ;
+
+typedef struct {
+  __u16 next            __attribute__ ((packed));
+  __u8  Rc              __attribute__ ((packed));
+  __u8  RcId            __attribute__ ((packed));
+  __u8  RcCh            __attribute__ ((packed));
+  __u8  Reserved1       __attribute__ ((packed));
+  __u16 Reference       __attribute__ ((packed));
+  __u8  Reserved2[8]    __attribute__ ((packed));
+} eicon_RC;
+
+typedef struct {
+  __u16 next            __attribute__ ((packed));
+  __u8  Ind             __attribute__ ((packed));
+  __u8  IndId           __attribute__ ((packed));
+  __u8  IndCh           __attribute__ ((packed));
+  __u8  MInd            __attribute__ ((packed));
+  __u16 MLength         __attribute__ ((packed));
+  __u16 Reference       __attribute__ ((packed));
+  __u8  RNR             __attribute__ ((packed));
+  __u8  Reserved        __attribute__ ((packed));
+  __u32 Ack             __attribute__ ((packed));
+  eicon_PBUFFER RBuffer;
+} eicon_IND;
+
+typedef struct {
+  __u16 NextReq  __attribute__ ((packed));  /* pointer to next Req Buffer */
+  __u16 NextRc   __attribute__ ((packed));  /* pointer to next Rc Buffer  */
+  __u16 NextInd  __attribute__ ((packed));  /* pointer to next Ind Buffer */
+  __u8 ReqInput  __attribute__ ((packed));  /* number of Req Buffers sent */
+  __u8 ReqOutput  __attribute__ ((packed)); /* number of Req Buffers returned */
+  __u8 ReqReserved  __attribute__ ((packed));/*number of Req Buffers reserved */
+  __u8 Int  __attribute__ ((packed));       /* ISDN-P interrupt           */
+  __u8 XLock  __attribute__ ((packed));     /* Lock field for arbitration */
+  __u8 RcOutput  __attribute__ ((packed));  /* number of Rc buffers received */
+  __u8 IndOutput  __attribute__ ((packed)); /* number of Ind buffers received */
+  __u8 IMask  __attribute__ ((packed));     /* Interrupt Mask Flag        */
+  __u8 Reserved1[2]  __attribute__ ((packed)); /* reserved field, do not use */
+  __u8 ReadyInt  __attribute__ ((packed));  /* request field for ready int */
+  __u8 Reserved2[12]  __attribute__ ((packed)); /* reserved field, do not use */
+  __u8 InterfaceType  __attribute__ ((packed)); /* interface type 1=16K    */
+  __u16 Signature  __attribute__ ((packed));    /* ISDN-P initialized ind  */
+  __u8 B[1];                            /* buffer space for Req,Ind and Rc */
+} eicon_pr_ram;
+
+typedef struct {
+	__u8		*Data;
+	unsigned int	Size;
+	unsigned int	Len;
+	__u8		*Next;
+} eicon_OBJBUFFER;
+
+extern int idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer);
+extern int idi_hangup(eicon_card *card, eicon_chan *chan);
+extern int idi_connect_res(eicon_card *card, eicon_chan *chan);
+extern int eicon_idi_listen_req(eicon_card *card, eicon_chan *chan);
+extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
+	                    char *eazmsn, int si1, int si2);
+
+extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb);
+extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb);
+extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb);
+extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que);
+extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value);
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_io.c linux.pre11.3/drivers/isdn/eicon/eicon_io.c
--- linux.vanilla/drivers/isdn/eicon/eicon_io.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_io.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,755 @@
+/* $Id: eicon_io.c,v 1.1 1999/03/29 11:19:45 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * Code for communicating with hardware.
+ *
+ * Copyright 1999    by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * Thanks to	Eicon Technology Diehl GmbH & Co. oHG for 
+ *		documents, informations and hardware. 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_io.c,v $
+ * Revision 1.1  1999/03/29 11:19:45  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ *
+ */
+
+
+#include "eicon.h"
+
+void
+eicon_io_rcv_dispatch(eicon_card *ccard) {
+        struct sk_buff *skb, *skb2, *skb_new;
+        eicon_IND *ind, *ind2, *ind_new;
+        eicon_chan *chan;
+
+        if (!ccard) {
+		if (DebugVar & 1)
+	                printk(KERN_WARNING "eicon_io_rcv_dispatch: NULL card!\n");
+                return;
+        }
+
+	while((skb = skb_dequeue(&ccard->rcvq))) {
+        	ind = (eicon_IND *)skb->data;
+
+        	if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
+			if (DebugVar & 1) {
+				switch(ind->Ind) {
+					case IDI_N_DISC_ACK: 
+						/* doesn't matter if this happens */ 
+						break;
+					default: 
+						printk(KERN_ERR "idi: Indication for unknown channel Ind=%d Id=%d\n", ind->Ind, ind->IndId);
+						printk(KERN_DEBUG "idi_hdl: Ch??: Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n",
+							ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
+				}
+			}
+	                dev_kfree_skb(skb);
+	                continue;
+	        }
+
+		if (chan->e.complete) { /* check for rec-buffer chaining */
+			if (ind->MLength == ind->RBuffer.length) {
+				chan->e.complete = 1;
+				idi_handle_ind(ccard, skb);
+				continue;
+			}
+			else {
+				chan->e.complete = 0;
+				ind->Ind = ind->MInd;
+				skb_queue_tail(&chan->e.R, skb);
+				continue;
+			}
+		}
+		else {
+			if (!(skb2 = skb_dequeue(&chan->e.R))) {
+				chan->e.complete = 1;
+				if (DebugVar & 1)
+	                		printk(KERN_ERR "eicon: buffer incomplete, but 0 in queue\n");
+	                	dev_kfree_skb(skb);
+	                	dev_kfree_skb(skb2);
+				continue;	
+			}
+	        	ind2 = (eicon_IND *)skb2->data;
+			skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length),
+					GFP_ATOMIC);
+			ind_new = (eicon_IND *)skb_put(skb_new,
+					((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length));
+			ind_new->Ind = ind2->Ind;
+			ind_new->IndId = ind2->IndId;
+			ind_new->IndCh = ind2->IndCh;
+			ind_new->MInd = ind2->MInd;
+			ind_new->MLength = ind2->MLength;
+			ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length;
+			memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length);
+			memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length);
+                	dev_kfree_skb(skb);
+                	dev_kfree_skb(skb2);
+			if (ind->MLength == ind->RBuffer.length) {
+				chan->e.complete = 2;
+				idi_handle_ind(ccard, skb_new);
+				continue;
+			}
+			else {
+				chan->e.complete = 0;
+				skb_queue_tail(&chan->e.R, skb_new);
+				continue;
+			}
+		}
+	}
+}
+
+void
+eicon_io_ack_dispatch(eicon_card *ccard) {
+        struct sk_buff *skb;
+
+        if (!ccard) {
+		if (DebugVar & 1)
+			printk(KERN_WARNING "eicon_io_ack_dispatch: NULL card!\n");
+                return;
+        }
+	while((skb = skb_dequeue(&ccard->rackq))) {
+		idi_handle_ack(ccard, skb);
+	}
+}
+
+
+/*
+ *  IO-Functions for different card-types
+ */
+
+u8 ram_inb(eicon_card *card, void *adr) {
+        eicon_pci_card *pcard;
+        eicon_isa_card *icard;
+        u32 addr = (u32) adr;
+	
+	pcard = &card->hwif.pci;
+	icard = &card->hwif.isa;
+
+        switch(card->type) {
+                case EICON_CTYPE_MAESTRA:
+                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
+                        return(inb((u16)pcard->PCIreg + M_DATA));
+                case EICON_CTYPE_MAESTRAP:
+                case EICON_CTYPE_S2M:
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+                        return(readb(addr));
+        }
+ return(0);
+}
+
+u16 ram_inw(eicon_card *card, void *adr) {
+        eicon_pci_card *pcard;
+        eicon_isa_card *icard;
+        u32 addr = (u32) adr;
+	
+	pcard = &card->hwif.pci;
+	icard = &card->hwif.isa;
+
+        switch(card->type) {
+                case EICON_CTYPE_MAESTRA:
+                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
+                        return(inw((u16)pcard->PCIreg + M_DATA));
+                case EICON_CTYPE_MAESTRAP:
+                case EICON_CTYPE_S2M:
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+                        return(readw(addr));
+        }
+ return(0);
+}
+
+void ram_outb(eicon_card *card, void *adr, u8 data) {
+        eicon_pci_card *pcard;
+        eicon_isa_card *icard;
+        u32 addr = (u32) adr;
+
+	pcard = &card->hwif.pci;
+	icard = &card->hwif.isa;
+
+        switch(card->type) {
+                case EICON_CTYPE_MAESTRA:
+                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
+                        outb((u8)data, (u16)pcard->PCIreg + M_DATA);
+                        break;
+                case EICON_CTYPE_MAESTRAP:
+                case EICON_CTYPE_S2M:
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+                        writeb(data, addr);
+                        break;
+        }
+}
+
+void ram_outw(eicon_card *card, void *adr , u16 data) {
+        eicon_pci_card *pcard;
+        eicon_isa_card *icard;
+        u32 addr = (u32) adr;
+
+	pcard = &card->hwif.pci;
+	icard = &card->hwif.isa;
+
+        switch(card->type) {
+                case EICON_CTYPE_MAESTRA:
+                        outw((u16)addr, (u16)pcard->PCIreg + M_ADDR);
+                        outw((u16)data, (u16)pcard->PCIreg + M_DATA);
+                        break;
+                case EICON_CTYPE_MAESTRAP:
+                case EICON_CTYPE_S2M:
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+                        writew(data, addr);
+                        break;
+        }
+}
+
+void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) {
+        int i;
+        switch(card->type) {
+                case EICON_CTYPE_MAESTRA:
+                        for(i = 0; i < len; i++) {
+                                writeb(ram_inb(card, adr + i), adrto + i);
+                        }
+                        break;
+                case EICON_CTYPE_MAESTRAP:
+                        memcpy(adrto, adr, len);
+                        break;
+                case EICON_CTYPE_S2M:
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+                        memcpy_fromio(adrto, adr, len);
+                        break;
+        }
+}
+
+void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) {
+        int i;
+        switch(card->type) {
+                case EICON_CTYPE_MAESTRA:
+                        for(i = 0; i < len; i++) {
+                                ram_outb(card, adrto + i, readb(adr + i));
+                        }
+                        break;
+                case EICON_CTYPE_MAESTRAP:
+                        memcpy(adrto, adr, len);
+                        break;
+                case EICON_CTYPE_S2M:
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+                        memcpy_toio(adrto, adr, len);
+                        break;
+        }
+}
+
+/*
+ *  Transmit-Function
+ */
+void
+eicon_io_transmit(eicon_card *ccard) {
+        eicon_pci_card *pci_card;
+        eicon_isa_card *isa_card;
+        struct sk_buff *skb;
+        struct sk_buff *skb2;
+        unsigned long flags;
+        char *ram, *reg, *cfg;
+	eicon_pr_ram  *prram = 0;
+	eicon_isa_com	*com = 0;
+	eicon_REQ *ReqOut = 0;
+	eicon_REQ *reqbuf = 0;
+	eicon_chan *chan;
+	eicon_chan_ptr *chan2;
+	int ReqCount;
+	int scom = 0;
+	int tmp = 0;
+	int quloop = 1;
+
+	pci_card = &ccard->hwif.pci;
+	isa_card = &ccard->hwif.isa;
+
+        if (!ccard) {
+		if (DebugVar & 1)
+                	printk(KERN_WARNING "eicon_transmit: NULL card!\n");
+                return;
+        }
+
+	switch(ccard->type) {
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+			scom = 1;
+			com = (eicon_isa_com *)isa_card->shmem;
+			break;
+		case EICON_CTYPE_S2M:
+			scom = 0;
+			prram = (eicon_pr_ram *)isa_card->shmem;
+			break;
+		case EICON_CTYPE_MAESTRAP:
+			scom = 0;
+        		ram = (char *)pci_card->PCIram;
+		        reg = (char *)pci_card->PCIreg;
+        		cfg = (char *)pci_card->PCIcfg;
+			prram = (eicon_pr_ram *)ram;
+			break;
+		case EICON_CTYPE_MAESTRA:
+			scom = 0;
+        		ram = (char *)pci_card->PCIram;
+		        reg = (char *)pci_card->PCIreg;
+        		cfg = (char *)pci_card->PCIcfg;
+			prram = 0;
+			break;
+		default:
+                	printk(KERN_WARNING "eicon_transmit: unsupported card-type!\n");
+			return;
+	}
+
+	ReqCount = 0;
+	if (!(skb2 = skb_dequeue(&ccard->sndq)))
+		quloop = 0; 
+	while(quloop) { 
+                save_flags(flags);
+                cli();
+		if (scom) {
+			if (ram_inb(ccard, &com->Req)) {
+				if (!ccard->ReadyInt) {
+					tmp = ram_inb(ccard, &com->ReadyInt) + 1;
+					ram_outb(ccard, &com->ReadyInt, tmp);
+					ccard->ReadyInt++;
+				}
+        	                restore_flags(flags);
+                	        skb_queue_head(&ccard->sndq, skb2);
+				if (DebugVar & 32)
+        	                	printk(KERN_INFO "eicon: transmit: Card not ready\n");
+	                        return;
+			}
+		} else {
+	                if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
+        	                restore_flags(flags);
+                	        skb_queue_head(&ccard->sndq, skb2);
+				if (DebugVar & 32)
+        	                	printk(KERN_INFO "eicon: transmit: Card not ready\n");
+	                        return;
+        	        }
+		}
+		restore_flags(flags);
+		chan2 = (eicon_chan_ptr *)skb2->data;
+		chan = chan2->ptr;
+		if (!chan->e.busy) {
+		 if((skb = skb_dequeue(&chan->e.X))) { 
+                	save_flags(flags);
+	                cli();
+			reqbuf = (eicon_REQ *)skb->data;
+			if (scom) {
+				ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length);
+				ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
+				ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh);
+				
+			} else {
+				/* get address of next available request buffer */
+				ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)];
+				ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length);
+				ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
+				ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh);
+				ram_outb(ccard, &ReqOut->Req, reqbuf->Req); 
+			}
+
+			if (reqbuf->ReqId &0x1f) { /* if this is no ASSIGN */
+
+				if (!reqbuf->Reference) { /* Signal Layer */
+					if (scom)
+						ram_outb(ccard, &com->ReqId, chan->e.D3Id); 
+					else
+						ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id); 
+
+					chan->e.ReqCh = 0; 
+				}
+				else {			/* Net Layer */
+					if (scom)
+						ram_outb(ccard, &com->ReqId, chan->e.B2Id); 
+					else
+						ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id); 
+
+					chan->e.ReqCh = 1;
+					if (((reqbuf->Req & 0x0f) == 0x08) ||
+					   ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
+						chan->waitq = reqbuf->XBuffer.length;
+						chan->waitpq += reqbuf->XBuffer.length;
+					}
+				}
+
+			} else {	/* It is an ASSIGN */
+
+				if (scom)
+					ram_outb(ccard, &com->ReqId, reqbuf->ReqId); 
+				else
+					ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId); 
+
+				if (!reqbuf->Reference) 
+					chan->e.ReqCh = 0; 
+				 else
+					chan->e.ReqCh = 1; 
+			} 
+			if (scom)
+			 	chan->e.ref = ccard->ref_out++;
+			else
+			 	chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
+
+			chan->e.Req = reqbuf->Req;
+			ReqCount++; 
+			if (scom)
+				ram_outb(ccard, &com->Req, reqbuf->Req); 
+			else
+				ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); 
+
+			chan->e.busy = 1; 
+			restore_flags(flags);
+			if (DebugVar & 32)
+	                	printk(KERN_DEBUG "eicon: Req=%x Id=%x Ch=%x Len=%x Ref=%d\n", 
+							reqbuf->Req, 
+							ram_inb(ccard, &ReqOut->ReqId),
+							reqbuf->ReqCh, reqbuf->XBuffer.length,
+							chan->e.ref); 
+			dev_kfree_skb(skb);
+		 }
+		 dev_kfree_skb(skb2);
+		} 
+		else {
+		skb_queue_tail(&ccard->sackq, skb2);
+		if (DebugVar & 32)
+                	printk(KERN_INFO "eicon: transmit: busy chan %d\n", chan->No); 
+		}
+
+		if (scom)
+			quloop = 0;
+		else
+			if (!(skb2 = skb_dequeue(&ccard->sndq)))
+				quloop = 0;
+
+	}
+	if (!scom)
+		ram_outb(ccard, &prram->ReqInput, (__u8)(ram_inb(ccard, &prram->ReqInput) + ReqCount)); 
+
+	while((skb = skb_dequeue(&ccard->sackq))) { 
+		skb_queue_tail(&ccard->sndq, skb);
+	}
+}
+
+
+/*
+ * IRQ handler 
+ */
+void
+eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
+	eicon_card *ccard = (eicon_card *)dev_id;
+        eicon_pci_card *pci_card;
+        eicon_isa_card *isa_card;
+    	char *ram = 0;
+	char *reg = 0;
+	char *cfg = 0;	
+	eicon_pr_ram  *prram = 0;
+	eicon_isa_com	*com = 0;
+        eicon_RC *RcIn;
+        eicon_IND *IndIn;
+	struct sk_buff *skb;
+        int Count = 0;
+	int Rc = 0;
+	int Ind = 0;
+	unsigned char *irqprobe = 0;
+	int scom = 0;
+	int tmp = 0;
+
+
+        if (!ccard) {
+                printk(KERN_WARNING "eicon_irq: spurious interrupt %d\n", irq);
+                return;
+        }
+
+	if (ccard->type == EICON_CTYPE_QUADRO) {
+		tmp = 4;
+		while(tmp) {
+			com = (eicon_isa_com *)ccard->hwif.isa.shmem;
+			if ((readb(ccard->hwif.isa.intack))) { /* quadro found */
+				break;
+			}
+			ccard = ccard->qnext;
+			tmp--;
+		}
+	}
+
+	pci_card = &ccard->hwif.pci;
+	isa_card = &ccard->hwif.isa;
+
+	switch(ccard->type) {
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+			scom = 1;
+			com = (eicon_isa_com *)isa_card->shmem;
+			irqprobe = &isa_card->irqprobe;
+			break;
+		case EICON_CTYPE_S2M:
+			scom = 0;
+			prram = (eicon_pr_ram *)isa_card->shmem;
+			irqprobe = &isa_card->irqprobe;
+			break;
+		case EICON_CTYPE_MAESTRAP:
+			scom = 0;
+			ram = (char *)pci_card->PCIram;
+			reg = (char *)pci_card->PCIreg;
+			cfg = (char *)pci_card->PCIcfg;
+			irqprobe = &pci_card->irqprobe;
+			prram = (eicon_pr_ram *)ram;
+			break;
+		case EICON_CTYPE_MAESTRA:
+			scom = 0;
+			ram = (char *)pci_card->PCIram;
+			reg = (char *)pci_card->PCIreg;
+			cfg = (char *)pci_card->PCIcfg;
+			irqprobe = &pci_card->irqprobe;
+			prram = 0;
+			break;
+		default:
+                	printk(KERN_WARNING "eicon_irq: unsupported card-type!\n");
+			return;
+	}
+
+	if (*irqprobe) {
+		switch(ccard->type) {
+			case EICON_CTYPE_S:
+			case EICON_CTYPE_SX:
+			case EICON_CTYPE_SCOM:
+			case EICON_CTYPE_QUADRO:
+				if (readb(isa_card->intack)) {
+        		               	writeb(0, &com->Rc);
+					writeb(0, isa_card->intack);
+				}
+				(*irqprobe)++;
+				break;
+			case EICON_CTYPE_S2M:
+				if (readb(isa_card->intack)) {
+        		               	writeb(0, &prram->RcOutput);
+					writeb(0, isa_card->intack);
+				}
+				(*irqprobe)++;
+				break;
+			case EICON_CTYPE_MAESTRAP:
+	        		if (readb(&ram[0x3fe])) { 
+        		               	writeb(0, &prram->RcOutput);
+				        writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
+				        writew(0, &cfg[MP_IRQ_RESET + 2]);
+					writeb(0, &ram[0x3fe]);
+       			        } 
+				*irqprobe = 0;
+				break;
+			case EICON_CTYPE_MAESTRA:
+				outb(0x08, pci_card->PCIreg + M_RESET);
+				*irqprobe = 0;
+				break;
+		}
+		return;
+	}
+
+	switch(ccard->type) {
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+		case EICON_CTYPE_S2M:
+			if (!(readb(isa_card->intack))) { /* card did not interrupt */
+				if (DebugVar & 1)
+					printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n");
+				return;
+			} 
+			break;
+		case EICON_CTYPE_MAESTRAP:
+			if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */
+				if (DebugVar & 1)
+					printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n");
+				return;
+			} 
+			break;
+		case EICON_CTYPE_MAESTRA:
+			outw(0x3fe, pci_card->PCIreg + M_ADDR);
+			if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */
+				if (DebugVar & 1)
+					printk(KERN_DEBUG "eicon: IRQ: card tells no interrupt!\n");
+				return;
+			} 
+			break;
+	}
+
+    if (scom) {
+
+        /* if a return code is available ...  */
+	if ((tmp = ram_inb(ccard, &com->Rc))) {
+		eicon_RC *ack;
+		if (tmp == READY_INT) {
+			if (DebugVar & 64)
+                        	printk(KERN_INFO "eicon: IRQ Rc=READY_INT\n");
+			if (ccard->ReadyInt) {
+				ccard->ReadyInt--;
+				ram_outb(ccard, &com->Rc, 0);
+			}
+		} else {
+			skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
+			ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
+			ack->Rc = tmp;
+			ack->RcId = ram_inb(ccard, &com->RcId);
+			ack->RcCh = ram_inb(ccard, &com->RcCh);
+			ack->Reference = ccard->ref_in++;
+			if (DebugVar & 64)
+                        	printk(KERN_INFO "eicon: IRQ Rc=%d Id=%d Ch=%d Ref=%d\n",
+					tmp,ack->RcId,ack->RcCh,ack->Reference);
+			skb_queue_tail(&ccard->rackq, skb);
+			eicon_schedule_ack(ccard);
+			ram_outb(ccard, &com->Req, 0);
+			ram_outb(ccard, &com->Rc, 0);
+		}
+
+	} else {
+
+	        /* if an indication is available ...  */
+		if ((tmp = ram_inb(ccard, &com->Ind))) {
+			eicon_IND *ind;
+			int len = ram_inw(ccard, &com->RBuffer.length);
+			skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
+			ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
+			ind->Ind = tmp;
+			ind->IndId = ram_inb(ccard, &com->IndId);
+			ind->IndCh = ram_inb(ccard, &com->IndCh);
+			ind->MInd  = ram_inb(ccard, &com->MInd);
+			ind->MLength = ram_inw(ccard, &com->MLength);
+			ind->RBuffer.length = len; 
+			if (DebugVar & 64)
+                        	printk(KERN_INFO "eicon: IRQ Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n",
+				tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
+			ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len);
+			skb_queue_tail(&ccard->rcvq, skb);
+			eicon_schedule_rx(ccard);
+			ram_outb(ccard, &com->Ind, 0);
+		}
+	}
+
+    } else {
+
+        /* if return codes are available ...  */
+        if((Count = ram_inb(ccard, &prram->RcOutput))) {
+		eicon_RC *ack;
+                /* get the buffer address of the first return code */
+                RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &prram->NextRc)];
+                /* for all return codes do ...  */
+                while(Count--) {
+
+                        if((Rc=ram_inb(ccard, &RcIn->Rc))) {
+				skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
+				ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
+				ack->Rc = Rc;
+				ack->RcId = ram_inb(ccard, &RcIn->RcId);
+				ack->RcCh = ram_inb(ccard, &RcIn->RcCh);
+				ack->Reference = ram_inw(ccard, &RcIn->Reference);
+				if (DebugVar & 64)
+	                        	printk(KERN_INFO "eicon: IRQ Rc=%d Id=%d Ch=%d Ref=%d\n",
+						Rc,ack->RcId,ack->RcCh,ack->Reference);
+                        	ram_outb(ccard, &RcIn->Rc, 0);
+				 skb_queue_tail(&ccard->rackq, skb);
+				 eicon_schedule_ack(ccard);
+                        }
+                        /* get buffer address of next return code   */
+                        RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &RcIn->next)];
+                }
+                /* clear all return codes (no chaining!) */
+                ram_outb(ccard, &prram->RcOutput, 0);
+        }
+
+        /* if indications are available ... */
+        if((Count = ram_inb(ccard, &prram->IndOutput))) {
+		eicon_IND *ind;
+                /* get the buffer address of the first indication */
+                IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &prram->NextInd)];
+                /* for all indications do ... */
+                while(Count--) {
+			Ind = ram_inb(ccard, &IndIn->Ind);
+			if(Ind) {
+				int len = ram_inw(ccard, &IndIn->RBuffer.length);
+				skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
+				ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
+				ind->Ind = Ind;
+				ind->IndId = ram_inb(ccard, &IndIn->IndId);
+				ind->IndCh = ram_inb(ccard, &IndIn->IndCh);
+				ind->MInd  = ram_inb(ccard, &IndIn->MInd);
+				ind->MLength = ram_inw(ccard, &IndIn->MLength);
+				ind->RBuffer.length = len;
+				if (DebugVar & 64)
+	                        	printk(KERN_INFO "eicon: IRQ Ind=%d Id=%d Ch=%d MInd=%d MLen=%d Len=%d\n",
+					Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len);
+                                ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len);
+				skb_queue_tail(&ccard->rcvq, skb);
+				eicon_schedule_rx(ccard);
+				ram_outb(ccard, &IndIn->Ind, 0);
+                        }
+                        /* get buffer address of next indication  */
+                        IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &IndIn->next)];
+                }
+                ram_outb(ccard, &prram->IndOutput, 0);
+        }
+
+    } 
+
+	/* clear interrupt */
+	switch(ccard->type) {
+		case EICON_CTYPE_QUADRO:
+			writeb(0, isa_card->intack);
+			writeb(0, &com[0x401]);
+			break;
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_S2M:
+			writeb(0, isa_card->intack);
+			break;
+		case EICON_CTYPE_MAESTRAP:
+			writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
+			writew(0, &cfg[MP_IRQ_RESET + 2]); 
+			writeb(0, &ram[0x3fe]); 
+			break;
+		case EICON_CTYPE_MAESTRA:
+			outb(0x08, pci_card->PCIreg + M_RESET);
+			outw(0x3fe, pci_card->PCIreg + M_ADDR);
+			outb(0, pci_card->PCIreg + M_DATA);
+			break;
+	}
+
+  return;
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_isa.c linux.pre11.3/drivers/isdn/eicon/eicon_isa.c
--- linux.vanilla/drivers/isdn/eicon/eicon_isa.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_isa.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,432 @@
+/* $Id: eicon_isa.c,v 1.5 1999/04/01 12:48:33 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * Hardware-specific code for old ISA cards.
+ *
+ * Copyright 1998    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_isa.c,v $
+ * Revision 1.5  1999/04/01 12:48:33  armin
+ * Changed some log outputs.
+ *
+ * Revision 1.4  1999/03/29 11:19:46  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.3  1999/03/02 12:37:45  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.2  1999/01/24 20:14:19  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.1  1999/01/01 18:09:43  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#include "eicon.h"
+#include "eicon_isa.h"
+
+#define check_shmem   check_region
+#define release_shmem release_region
+#define request_shmem request_region
+
+char *eicon_isa_revision = "$Revision: 1.5 $";
+
+/* Mask for detecting invalid IRQ parameter */
+static int eicon_isa_valid_irq[] = {
+	0x1c1c, /* 2, 3, 4, 10, 11, 12 (S)*/
+	0x1c1c, /* 2, 3, 4, 10, 11, 12 (SX) */
+	0x1cbc, /* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */
+	0x1cbc, /* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */
+	0x1cbc  /* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */
+};
+
+static void
+eicon_isa_release_shmem(eicon_isa_card *card) {
+	if (card->mvalid)
+		release_shmem((unsigned long)card->shmem, card->ramsize);
+	card->mvalid = 0;
+}
+
+static void
+eicon_isa_release_irq(eicon_isa_card *card) {
+	if (!card->master)
+		return;
+	if (card->ivalid)
+		free_irq(card->irq, card);
+	card->ivalid = 0;
+}
+
+void
+eicon_isa_release(eicon_isa_card *card) {
+	eicon_isa_release_irq(card);
+	eicon_isa_release_shmem(card);
+}
+
+void
+eicon_isa_printpar(eicon_isa_card *card) {
+	switch (card->type) {
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+		case EICON_CTYPE_S2M:
+			printk(KERN_INFO "Eicon %s at 0x%lx, irq %d\n",
+			       eicon_ctype_name[card->type],
+			       (unsigned long)card->shmem,
+			       card->irq);
+	}
+}
+
+int
+eicon_isa_find_card(int Mem, int Irq, char * Id)
+{
+	int primary = 1;
+
+	if (!strlen(Id))
+		return -1;
+
+	/* Check for valid membase address */
+	if ((Mem < 0x0c0000) ||
+	    (Mem > 0x0fc000) ||
+	    (Mem & 0xfff)) { 
+		printk(KERN_WARNING "eicon_isa: illegal membase 0x%x for %s\n",
+			 Mem, Id);
+		return -1;
+	}
+	if (check_shmem(Mem, RAMSIZE)) {
+		printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.\n", Mem);
+		return -1;
+	}
+
+        writew(0x55aa, Mem + 0x402);
+        if (readw(Mem + 0x402) != 0x55aa) primary = 0;
+	writew(0, Mem + 0x402);
+	if (readw(Mem + 0x402) != 0) primary = 0;
+
+	printk(KERN_INFO "Eicon: Driver-ID: %s\n", Id);
+	if (primary) {
+		printk(KERN_INFO "Eicon: assuming pri card at 0x%x\n", Mem);
+		writeb(0, Mem + 0x3ffe);
+		return EICON_CTYPE_ISAPRI;
+	} else {
+		printk(KERN_INFO "Eicon: assuming bri card at 0x%x\n", Mem);
+		writeb(0, Mem + 0x400);
+		return EICON_CTYPE_ISABRI;
+	}
+	return -1;
+}
+
+int
+eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
+	int	tmp;
+	int               timeout;
+	eicon_isa_codebuf cbuf;
+	unsigned char     *code;
+	eicon_isa_boot    *boot;
+
+	if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf)))
+		return -EFAULT;
+
+	/* Allocate code-buffer and copy code from userspace */
+	if (cbuf.bootstrap_len > 1024) {
+		printk(KERN_WARNING "eicon_isa_boot: Invalid startup-code size %ld\n",
+		       cbuf.bootstrap_len);
+		return -EINVAL;
+	}
+	if (!(code = kmalloc(cbuf.bootstrap_len, GFP_KERNEL))) {
+		printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n");
+		return -ENOMEM;
+	}
+	if (copy_from_user(code, &cb->code, cbuf.bootstrap_len)) {
+		kfree(code);
+		return -EFAULT;
+	}
+
+	switch(card->type) {
+		case EICON_CTYPE_S:
+		case EICON_CTYPE_SX:
+		case EICON_CTYPE_SCOM:
+		case EICON_CTYPE_QUADRO:
+		case EICON_CTYPE_ISABRI:
+			card->ramsize  = RAMSIZE;
+			card->intack   = (__u8 *)card->shmem + INTACK;
+			card->startcpu = (__u8 *)card->shmem + STARTCPU;
+			card->stopcpu  = (__u8 *)card->shmem + STOPCPU;
+			break;
+		case EICON_CTYPE_S2M:
+		case EICON_CTYPE_ISAPRI:
+			card->ramsize  = RAMSIZE_P;
+			card->intack   = (__u8 *)card->shmem + INTACK_P;
+			card->startcpu = (__u8 *)card->shmem + STARTCPU_P;
+			card->stopcpu  = (__u8 *)card->shmem + STOPCPU_P;
+			break;
+		default:
+			printk(KERN_WARNING "eicon_isa_boot: Invalid card type %d\n", card->type);
+			return -EINVAL;
+	}
+
+	/* Register shmem */
+	if (check_shmem((unsigned long)card->shmem, card->ramsize)) {
+		printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n",
+			(unsigned long)card->shmem);
+		kfree(code);
+		return -EBUSY;
+	}
+	request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN");
+	card->mvalid = 1;
+
+	/* clear any pending irq's */
+	readb(card->intack);
+	/* set reset-line active */
+	writeb(0, card->stopcpu); 
+	/* clear irq-requests */
+	writeb(0, card->intack);
+	readb(card->intack);
+
+	/* Copy code into card */
+	memcpy_toio(&card->shmem->c, code, cbuf.bootstrap_len);
+
+	/* Check for properly loaded code */
+	if (!check_signature((unsigned long)&card->shmem->c, code, 1020)) {
+		printk(KERN_WARNING "eicon_isa_boot: Could not load startup-code\n");
+		eicon_isa_release_shmem(card);
+		kfree(code);
+		return -EIO;
+	}
+	/* if 16k-ramsize, duplicate the reset-jump-code */
+	if (card->ramsize == RAMSIZE_P)
+		memcpy_toio((__u8 *)card->shmem + 0x3ff0, &code[0x3f0], 12);
+
+	kfree(code);
+	boot = &card->shmem->boot;
+
+	/* Delay 0.2 sec. */
+	SLEEP(20);
+
+	/* Start CPU */
+	writeb(cbuf.boot_opt, &boot->ctrl);
+	writeb(0, card->startcpu); 
+
+	/* Delay 0.2 sec. */
+	SLEEP(20);
+
+	timeout = jiffies + (HZ * 22);
+	while (timeout > jiffies) {
+		if (readb(&boot->ctrl) == 0)
+			break;
+		SLEEP(10);
+	}
+	if (readb(&boot->ctrl) != 0) {
+		printk(KERN_WARNING "eicon_isa_boot: CPU test failed\n");
+		eicon_isa_release_shmem(card);
+		return -EIO;
+	}
+
+	/* Check for memory-test errors */
+	if (readw(&boot->ebit)) {
+		printk(KERN_WARNING "eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)\n",
+		       readw(&boot->ebit), readl(&boot->eloc));
+		eicon_isa_release_shmem(card);
+		return -EIO;
+	}
+
+        /* Check card type and memory size */
+        tmp = readb(&boot->card);
+	if ((tmp < 0) || (tmp > 4)) {
+		printk(KERN_WARNING "eicon_isa_boot: Type detect failed\n");
+		eicon_isa_release_shmem(card);
+		return -EIO;
+	}
+	card->type = tmp;
+	((eicon_card *)card->card)->type = tmp;
+
+        tmp = readb(&boot->msize);
+        if (tmp != 8 && tmp != 16 && tmp != 24 &&
+            tmp != 32 && tmp != 48 && tmp != 60) {
+                printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n");
+		eicon_isa_release_shmem(card);
+                return -EIO;
+        }
+	printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]); 
+	if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) {
+		tmp = eicon_addcard(card->type, (unsigned long)card->shmem, card->irq, 
+					((eicon_card *)card->card)->regname);
+		printk(KERN_INFO "Eicon: %d adapters added\n", tmp);
+	}
+	return 0;
+}
+
+int
+eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
+	eicon_isa_boot    *boot;
+	int               tmp;
+	int               timeout;
+	int 		  j;
+	eicon_isa_codebuf cbuf;
+	unsigned char     *code;
+	unsigned char     *p;
+
+	if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf)))
+		return -EFAULT;
+
+	if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) {
+		printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n");
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(code, &cb->code, cbuf.firmware_len)) {
+		kfree(code);
+		return -EFAULT;
+	}
+
+	boot = &card->shmem->boot;
+
+	if ((!card->ivalid) && card->master) {
+		card->irqprobe = 1;
+		/* Check for valid IRQ */
+		if ((card->irq < 0) || (card->irq > 15) || 
+		    (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) {
+			printk(KERN_WARNING "eicon_isa_boot: illegal irq: %d\n", card->irq);
+			eicon_isa_release_shmem(card);
+			kfree(code);
+			return -EINVAL;
+		}
+		/* Register irq */
+		if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card))
+			card->ivalid = 1;
+		else {
+			printk(KERN_WARNING "eicon_isa_boot: irq %d already in use.\n",
+			       card->irq);
+			eicon_isa_release_shmem(card);
+			kfree(code);
+			return -EBUSY;
+		}
+	}
+
+        tmp = readb(&boot->msize);
+        if (tmp != 8 && tmp != 16 && tmp != 24 &&
+            tmp != 32 && tmp != 48 && tmp != 60) {
+                printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n");
+		eicon_isa_release_shmem(card);
+                return -EIO;
+        }
+
+	eicon_isa_printpar(card);
+
+	/* Download firmware */
+	printk(KERN_INFO "%s %dkB, loading firmware ...\n", 
+	       eicon_ctype_name[card->type],
+	       tmp * 16);
+	tmp = cbuf.firmware_len >> 8;
+	p = code;
+	while (tmp--) {
+		memcpy_toio(&boot->b, p, 256);
+		writeb(1, &boot->ctrl);
+		timeout = jiffies + 10;
+		while (timeout > jiffies) {
+			if (readb(&boot->ctrl) == 0)
+				break;
+			SLEEP(2);
+		}
+		if (readb(&boot->ctrl)) {
+			printk(KERN_WARNING "eicon_isa_boot: download timeout at 0x%x\n", p-code);
+			eicon_isa_release(card);
+			kfree(code);
+			return -EIO;
+		}
+		p += 256;
+	}
+	kfree(code);
+
+	/* Initialize firmware parameters */
+	memcpy_toio(&card->shmem->c[8], &cbuf.tei, 14);
+	memcpy_toio(&card->shmem->c[32], &cbuf.oad, 96);
+	memcpy_toio(&card->shmem->c[128], &cbuf.oad, 96);
+	
+	/* Start firmware, wait for signature */
+	writeb(2, &boot->ctrl);
+	timeout = jiffies + (5*HZ);
+	while (timeout > jiffies) {
+		if (readw(&boot->signature) == 0x4447)
+			break;
+		SLEEP(2);
+	}
+	if (readw(&boot->signature) != 0x4447) {
+		printk(KERN_WARNING "eicon_isa_boot: firmware selftest failed %04x\n",
+		       readw(&boot->signature));
+		eicon_isa_release(card);
+		return -EIO;
+	}
+
+	card->channels = readb(&card->shmem->c[0x3f6]);
+
+	/* clear irq-requests, reset irq-count */
+	readb(card->intack);
+	writeb(0, card->intack);
+
+	if (card->master) {
+		card->irqprobe = 1;
+		/* Trigger an interrupt and check if it is delivered */
+		tmp = readb(&card->shmem->com.ReadyInt);
+		tmp ++;
+		writeb(tmp, &card->shmem->com.ReadyInt);
+		timeout = jiffies + 20;
+		while (timeout > jiffies) {
+			if (card->irqprobe > 1)
+				break;
+			SLEEP(2);
+		}
+		if (card->irqprobe == 1) {
+			printk(KERN_WARNING "eicon_isa_boot: IRQ test failed\n");
+			eicon_isa_release(card);
+			return -EIO;
+		}
+	}
+	writeb(card->irq, &card->shmem->com.Int);
+
+	/* initializing some variables */
+	((eicon_card *)card->card)->ReadyInt = 0;
+	((eicon_card *)card->card)->ref_in  = 1;
+	((eicon_card *)card->card)->ref_out = 1;
+	for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
+	for(j=0; j< (card->channels + 1); j++) {
+		((eicon_card *)card->card)->bch[j].e.busy = 0;
+		((eicon_card *)card->card)->bch[j].e.D3Id = 0;
+		((eicon_card *)card->card)->bch[j].e.B2Id = 0;
+		((eicon_card *)card->card)->bch[j].e.ref = 0;
+		((eicon_card *)card->card)->bch[j].e.Req = 0;
+		((eicon_card *)card->card)->bch[j].e.complete = 1;
+		((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
+	}
+
+	printk(KERN_INFO "Eicon: Supported channels: %d\n", card->channels); 
+	printk(KERN_INFO "%s successfully started\n", eicon_ctype_name[card->type]);
+
+	/* Enable normal IRQ processing */
+	card->irqprobe = 0;
+	return 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_isa.h linux.pre11.3/drivers/isdn/eicon/eicon_isa.h
--- linux.vanilla/drivers/isdn/eicon/eicon_isa.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_isa.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,144 @@
+/* $Id: eicon_isa.h,v 1.3 1999/03/29 11:19:47 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ *
+ * Copyright 1998    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_isa.h,v $
+ * Revision 1.3  1999/03/29 11:19:47  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.2  1999/03/02 12:37:46  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.1  1999/01/01 18:09:44  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#ifndef eicon_isa_h
+#define eicon_isa_h
+
+#ifdef __KERNEL__
+
+/* Factory defaults for ISA-Cards */
+#define EICON_ISA_MEMBASE 0xd0000
+#define EICON_ISA_IRQ     3
+/* shmem offset for Quadro parts */
+#define EICON_ISA_QOFFSET 0x0800
+
+typedef struct {
+        __u16 length __attribute__ ((packed));   /* length of data/parameter field         */
+        __u8  P[270];                            /* data/parameter field                   */
+} eicon_scom_PBUFFER;
+
+/* General communication buffer */
+typedef struct {
+        __u8   Req;                                /* request register                       */
+	__u8   ReqId;                              /* request task/entity identification     */
+	__u8   Rc;                                 /* return code register                   */
+	__u8   RcId;                               /* return code task/entity identification */
+	__u8   Ind;                                /* Indication register                    */
+	__u8   IndId;                              /* Indication task/entity identification  */
+	__u8   IMask;                              /* Interrupt Mask Flag                    */
+	__u8   RNR;                                /* Receiver Not Ready (set by PC)         */
+	__u8   XLock;                              /* XBuffer locked Flag                    */
+	__u8   Int;                                /* ISDN interrupt                         */
+	__u8   ReqCh;                              /* Channel field for layer-3 Requests     */
+	__u8   RcCh;                               /* Channel field for layer-3 Returncodes  */
+	__u8   IndCh;                              /* Channel field for layer-3 Indications  */
+	__u8   MInd;                               /* more data indication field             */
+	__u16  MLength;                            /* more data total packet length          */
+	__u8   ReadyInt;                           /* request field for ready interrupt      */
+	__u8   Reserved[12];                       /* reserved space                         */
+	__u8   IfType;                             /* 1 = 16k-Interface                      */
+	__u16  Signature __attribute__ ((packed)); /* ISDN adapter Signature                 */
+	eicon_scom_PBUFFER XBuffer;                /* Transmit Buffer                        */
+	eicon_scom_PBUFFER RBuffer;                /* Receive Buffer                         */
+} eicon_isa_com;
+
+/* struct for downloading firmware */
+typedef struct {
+	__u8  ctrl;
+	__u8  card;
+	__u8  msize;
+	__u8  fill0;
+	__u16 ebit __attribute__ ((packed));
+	__u32 eloc __attribute__ ((packed));
+	__u8  reserved[20];
+	__u16 signature __attribute__ ((packed));
+	__u8  fill[224];
+	__u8  b[256];
+} eicon_isa_boot;
+
+/* Shared memory */
+typedef union {
+	unsigned char  c[0x400];
+	eicon_isa_com  com;
+	eicon_isa_boot boot;
+} eicon_isa_shmem;
+
+/*
+ * card's description
+ */
+typedef struct {
+	int               ramsize;
+	int               irq;	    /* IRQ                        */
+	void*             card;
+	eicon_isa_shmem*  shmem;    /* Shared-memory area         */
+	unsigned char*    intack;   /* Int-Acknowledge            */
+	unsigned char*    stopcpu;  /* Writing here stops CPU     */
+	unsigned char*    startcpu; /* Writing here starts CPU    */
+	unsigned char     type;     /* card type                  */
+	int		  channels; /* No. of channels		  */
+	unsigned char     irqprobe; /* Flag: IRQ-probing          */
+	unsigned char     mvalid;   /* Flag: Memory is valid      */
+	unsigned char     ivalid;   /* Flag: IRQ is valid         */
+	unsigned char     master;   /* Flag: Card ist Quadro 1/4  */
+	void*             generic;  /* Ptr to generic card struct */
+} eicon_isa_card;
+
+/* Offsets for special locations on standard cards */
+#define INTACK     0x03fe 
+#define STOPCPU    0x0400
+#define STARTCPU   0x0401
+#define RAMSIZE    0x0400
+/* Offsets for special location on PRI card */
+#define INTACK_P   0x3ffc
+#define STOPCPU_P  0x3ffe
+#define STARTCPU_P 0x3fff
+#define RAMSIZE_P  0x4000
+
+
+extern int eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb);
+extern int eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb);
+extern void eicon_isa_release(eicon_isa_card *card);
+extern void eicon_isa_printpar(eicon_isa_card *card);
+extern void eicon_isa_transmit(eicon_isa_card *card);
+extern int eicon_isa_find_card(int Mem, int Irq, char * Id);
+
+#endif  /* __KERNEL__ */
+
+#endif	/* eicon_isa_h */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_mod.c linux.pre11.3/drivers/isdn/eicon/eicon_mod.c
--- linux.vanilla/drivers/isdn/eicon/eicon_mod.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_mod.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,1460 @@
+/* $Id: eicon_mod.c,v 1.7 1999/07/11 17:16:27 armin Exp $
+ *
+ * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * 
+ * Copyright 1997    by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de) 
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * 
+ * Thanks to    Eicon Technology Diehl GmbH & Co. oHG for
+ *              documents, informations and hardware.
+ *
+ *              Deutsche Telekom AG for S2M support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_mod.c,v $
+ * Revision 1.7  1999/07/11 17:16:27  armin
+ * Bugfixes in queue handling.
+ * Added DSP-DTMF decoder functions.
+ * Reorganized ack_handler.
+ *
+ * Revision 1.6  1999/06/09 19:31:26  armin
+ * Wrong PLX size for request_region() corrected.
+ * Added first MCA code from Erik Weber.
+ *
+ * Revision 1.5  1999/04/01 12:48:35  armin
+ * Changed some log outputs.
+ *
+ * Revision 1.4  1999/03/29 11:19:47  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.3  1999/03/02 12:37:47  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.2  1999/01/24 20:14:21  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.1  1999/01/01 18:09:44  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#ifdef CONFIG_MCA
+#include <linux/mca.h>
+#endif
+
+#include "eicon.h"
+
+#define INCLUDE_INLINE_FUNCS
+
+static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
+                                                     start of card-list   */
+
+static char *eicon_revision = "$Revision: 1.7 $";
+
+extern char *eicon_pci_revision;
+extern char *eicon_isa_revision;
+extern char *eicon_idi_revision;
+
+#ifdef MODULE
+#define MOD_USE_COUNT (GET_USE_COUNT (&__this_module))
+#endif
+
+#define EICON_CTRL_VERSION 1
+
+ulong DebugVar;
+
+/* Parameters to be set by insmod */
+static int   membase      = -1;
+static int   irq          = -1;
+static char *id           = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+MODULE_DESCRIPTION(             "Driver for Eicon.Diehl active ISDN cards");
+MODULE_AUTHOR(                  "Armin Schindler");
+MODULE_SUPPORTED_DEVICE(        "ISDN subsystem");
+MODULE_PARM_DESC(membase,	"Base address of first ISA card");
+MODULE_PARM_DESC(irq,    	"IRQ of first card");
+MODULE_PARM_DESC(id,   		"ID-String of first card");
+MODULE_PARM(membase,    	"i");
+MODULE_PARM(irq,          	"i");
+MODULE_PARM(id,           	"s");
+
+char *eicon_ctype_name[] = {
+        "ISDN-S",
+        "ISDN-SX",
+        "ISDN-SCOM",
+        "ISDN-QUADRO",
+        "ISDN-S2M",
+        "DIVA Server BRI/PCI",
+        "DIVA Server 4BRI/PCI",
+        "DIVA Server 4BRI/PCI",
+        "DIVA Server PRI/PCI"
+};
+
+static int
+getrel(char *p)
+{
+        int v = 0;
+	char *tmp = 0;
+
+	if ((tmp = strchr(p, '.')))
+		p = tmp + 1;
+        while (p[0] >= '0' && p[0] <= '9') {
+                v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0');
+		p++;
+	}
+        return v;
+
+
+}
+
+static char *
+eicon_getrev(const char *revision)
+{
+	char *rev;
+	char *p;
+	if ((p = strchr(revision, ':'))) {
+		rev = p + 2;
+		p = strchr(rev, '$');
+		*--p = 0;
+	} else rev = "?.??";
+	return rev;
+
+}
+
+static eicon_chan *
+find_channel(eicon_card *card, int channel)
+{
+	if ((channel >= 0) && (channel < card->nchannels))
+        	return &(card->bch[channel]);
+	if (DebugVar & 1)
+		printk(KERN_WARNING "eicon: Invalid channel %d\n", channel);
+	return NULL;
+}
+
+/*
+ * Free MSN list
+ */
+static void
+eicon_clear_msn(eicon_card *card)
+{
+        struct msn_entry *p = card->msn_list;
+        struct msn_entry *q;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+        card->msn_list = NULL;
+	restore_flags(flags);
+        while (p) {
+                q  = p->next;
+                kfree(p);
+                p = q;
+        }
+}
+
+/*
+ * Find an MSN entry in the list.
+ * If ia5 != 0, return IA5-encoded EAZ, else
+ * return a bitmask with corresponding bit set.
+ */
+static __u16
+eicon_find_msn(eicon_card *card, char *msn, int ia5)
+{
+        struct msn_entry *p = card->msn_list;
+	__u8 eaz = '0';
+
+	while (p) {
+		if (!strcmp(p->msn, msn)) {
+			eaz = p->eaz;
+			break;
+		}
+		p = p->next;
+	}
+	if (!ia5)
+		return (1 << (eaz - '0'));
+	else
+		return eaz;
+}
+
+/*
+ * Find an EAZ entry in the list.
+ * return a string with corresponding msn.
+ */
+char *
+eicon_find_eaz(eicon_card *card, char eaz)
+{
+        struct msn_entry *p = card->msn_list;
+
+	while (p) {
+		if (p->eaz == eaz)
+			return(p->msn);
+		p = p->next;
+	}
+	return("\0");
+}
+
+#if 0
+/*
+ * Add or delete an MSN to the MSN list
+ *
+ * First character of msneaz is EAZ, rest is MSN.
+ * If length of eazmsn is 1, delete that entry.
+ */
+static int
+eicon_set_msn(eicon_card *card, char *eazmsn)
+{
+        struct msn_entry *p = card->msn_list;
+        struct msn_entry *q = NULL;
+	unsigned long flags;
+	int i;
+	
+	if (!strlen(eazmsn))
+		return 0;
+	if (strlen(eazmsn) > 16)
+		return -EINVAL;
+	for (i = 0; i < strlen(eazmsn); i++)
+		if (!isdigit(eazmsn[i]))
+			return -EINVAL;
+        if (strlen(eazmsn) == 1) {
+		/* Delete a single MSN */
+		while (p) {
+			if (p->eaz == eazmsn[0]) {
+				save_flags(flags);
+				cli();
+				if (q)
+					q->next = p->next;
+				else
+					card->msn_list = p->next;
+				restore_flags(flags);
+				kfree(p);
+				if (DebugVar & 8)
+					printk(KERN_DEBUG
+					       "Mapping for EAZ %c deleted\n",
+					       eazmsn[0]);
+				return 0;
+			}
+			q = p;
+			p = p->next;
+		}
+		return 0;
+        }
+	/* Add a single MSN */
+	while (p) {
+		/* Found in list, replace MSN */
+		if (p->eaz == eazmsn[0]) {
+			save_flags(flags);
+			cli();
+			strcpy(p->msn, &eazmsn[1]);
+			restore_flags(flags);
+			if (DebugVar & 8)
+				printk(KERN_DEBUG
+				       "Mapping for EAZ %c changed to %s\n",
+				       eazmsn[0],
+				       &eazmsn[1]);
+			return 0;
+		}
+		p = p->next;
+	}
+	/* Not found in list, add new entry */
+	p = kmalloc(sizeof(msn_entry), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	p->eaz = eazmsn[0];
+	strcpy(p->msn, &eazmsn[1]);
+	p->next = card->msn_list;
+	save_flags(flags);
+	cli();
+	card->msn_list = p;
+	restore_flags(flags);
+	if (DebugVar & 8)
+		printk(KERN_DEBUG
+		       "Mapping %c -> %s added\n",
+		       eazmsn[0],
+		       &eazmsn[1]);
+	return 0;
+}
+#endif
+
+static void
+eicon_rcv_dispatch(struct eicon_card *card)
+{
+	switch (card->bus) {
+		case EICON_BUS_ISA:
+		case EICON_BUS_MCA:
+		case EICON_BUS_PCI:
+			eicon_io_rcv_dispatch(card);
+			break;
+		default:
+			if (DebugVar & 1)
+				printk(KERN_WARNING
+				       "eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
+	}
+}
+
+static void
+eicon_ack_dispatch(struct eicon_card *card)
+{
+	switch (card->bus) {
+		case EICON_BUS_ISA:
+		case EICON_BUS_MCA:
+		case EICON_BUS_PCI:
+			eicon_io_ack_dispatch(card);
+			break;
+		default:
+			if (DebugVar & 1)
+				printk(KERN_WARNING
+			       		"eicon_ack_dispatch: Illegal bustype %d\n", card->bus);
+	}
+}
+
+static void
+eicon_transmit(struct eicon_card *card)
+{
+	switch (card->bus) {
+		case EICON_BUS_ISA:
+		case EICON_BUS_MCA:
+		case EICON_BUS_PCI:
+			eicon_io_transmit(card);
+			break;
+		default:
+			if (DebugVar & 1)
+				printk(KERN_WARNING
+				       "eicon_transmit: Illegal bustype %d\n", card->bus);
+	}
+}
+
+static int
+eicon_command(eicon_card * card, isdn_ctrl * c)
+{
+        ulong a;
+        eicon_chan *chan;
+	eicon_cdef cdef;
+	isdn_ctrl cmd;
+	char tmp[17];
+	int ret = 0;
+	unsigned long flags;
+ 
+        switch (c->command) {
+		case ISDN_CMD_IOCTL:
+			memcpy(&a, c->parm.num, sizeof(ulong));
+			switch (c->arg) {
+				case EICON_IOCTL_GETVER:
+					return(EICON_CTRL_VERSION);
+				case EICON_IOCTL_GETTYPE:
+					return(card->type);
+				case EICON_IOCTL_GETMMIO:
+					switch (card->bus) {
+						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
+							return (int)card->hwif.isa.shmem;
+#if CONFIG_PCI
+						case EICON_BUS_PCI:
+							return card->hwif.pci.PCIram;
+#endif
+						default:
+							if (DebugVar & 1)
+								printk(KERN_WARNING
+								       "eicon: Illegal BUS type %d\n",
+							       card->bus);
+							ret = -ENODEV;
+					}
+				case EICON_IOCTL_SETMMIO:
+					if (card->flags & EICON_FLAGS_LOADED)
+						return -EBUSY;
+					switch (card->bus) {
+						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
+							if (eicon_isa_find_card(a,
+								card->hwif.isa.irq,
+								card->regname) < 0)
+								return -EFAULT;
+							card->hwif.isa.shmem = (eicon_isa_shmem *)a;
+							return 0;
+						default:
+							if (DebugVar & 1)
+								printk(KERN_WARNING
+							      		"eicon: Illegal BUS type %d\n",
+							       card->bus);
+							ret = -ENODEV;
+					}					
+				case EICON_IOCTL_GETIRQ:
+					switch (card->bus) {
+						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
+							return card->hwif.isa.irq;
+#if CONFIG_PCI
+						case EICON_BUS_PCI:
+							return card->hwif.pci.irq;
+#endif
+						default:
+							if (DebugVar & 1)
+								printk(KERN_WARNING
+								       "eicon: Illegal BUS type %d\n",
+							       card->bus);
+							ret = -ENODEV;
+					}
+				case EICON_IOCTL_SETIRQ:
+					if (card->flags & EICON_FLAGS_LOADED)
+						return -EBUSY;
+					if ((a < 2) || (a > 15))
+						return -EFAULT;
+					switch (card->bus) {
+						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
+							card->hwif.isa.irq = a;
+							return 0;
+						default:
+							if (DebugVar & 1)
+								printk(KERN_WARNING
+							      		"eicon: Illegal BUS type %d\n",
+							       card->bus);
+							ret = -ENODEV;
+					}					
+				case EICON_IOCTL_LOADBOOT:
+					if (card->flags & EICON_FLAGS_RUNNING)
+						return -EBUSY;  
+					switch (card->bus) {
+						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
+							ret = eicon_isa_bootload(
+								&(card->hwif.isa),
+								&(((eicon_codebuf *)a)->isa));
+							break;
+						default:
+							if (DebugVar & 1)
+								printk(KERN_WARNING
+								       "eicon: Illegal BUS type %d\n",
+							       card->bus);
+							ret = -ENODEV;
+					}
+					return ret;
+				case EICON_IOCTL_LOADISA:
+					if (card->flags & EICON_FLAGS_RUNNING)
+						return -EBUSY;  
+					switch (card->bus) {
+						case EICON_BUS_ISA:
+						case EICON_BUS_MCA:
+							ret = eicon_isa_load(
+								&(card->hwif.isa),
+								&(((eicon_codebuf *)a)->isa));
+							if (!ret) {
+                                                                card->flags |= EICON_FLAGS_LOADED;
+                                                                card->flags |= EICON_FLAGS_RUNNING;
+								if (card->hwif.isa.channels > 1) {
+									cmd.command = ISDN_STAT_ADDCH;
+									cmd.driver = card->myid;
+									cmd.arg = card->hwif.isa.channels - 1;
+									card->interface.statcallb(&cmd);
+								}
+								cmd.command = ISDN_STAT_RUN;    
+								cmd.driver = card->myid;        
+								cmd.arg = 0;                    
+								card->interface.statcallb(&cmd);
+							}
+							break;
+						default:
+							if (DebugVar & 1)
+								printk(KERN_WARNING
+								       "eicon: Illegal BUS type %d\n",
+							       card->bus);
+							ret = -ENODEV;
+					}
+					return ret;
+
+				case EICON_IOCTL_MANIF:
+					if (!card->flags & EICON_FLAGS_RUNNING)
+						return -ENODEV;
+					if (!card->Feature & PROTCAP_MANIF)
+						return -ENODEV;
+					ret = eicon_idi_manage(
+						card, 
+						(eicon_manifbuf *)a);
+					return ret;
+#if CONFIG_PCI 
+				case EICON_IOCTL_LOADPCI:
+						if (card->flags & EICON_FLAGS_RUNNING)
+							return -EBUSY;  
+                                                if (card->bus == EICON_BUS_PCI) {
+							switch(card->type) {
+								case EICON_CTYPE_MAESTRA:
+                                                		        ret = eicon_pci_load_bri(
+		                                                                &(card->hwif.pci),
+                		                                                &(((eicon_codebuf *)a)->pci)); 
+									break;
+
+								case EICON_CTYPE_MAESTRAP:
+		                                                        ret = eicon_pci_load_pri(
+                		                                                &(card->hwif.pci),
+                                		                                &(((eicon_codebuf *)a)->pci)); 
+									break;
+							}
+                                                        if (!ret) {
+                                                                card->flags |= EICON_FLAGS_LOADED;
+                                                                card->flags |= EICON_FLAGS_RUNNING;
+								if (card->hwif.pci.channels > 1) {
+									cmd.command = ISDN_STAT_ADDCH;
+									cmd.driver = card->myid;
+									cmd.arg = card->hwif.pci.channels - 1;
+									card->interface.statcallb(&cmd);
+								}
+								cmd.command = ISDN_STAT_RUN;    
+								cmd.driver = card->myid;        
+								cmd.arg = 0;                    
+								card->interface.statcallb(&cmd);
+							} 
+                                                        return ret;
+						} else return -ENODEV;
+#endif
+#if 0
+				case EICON_IOCTL_SETMSN:
+					if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp))))
+						return -EFAULT;
+					if ((ret = eicon_set_msn(card, tmp)))
+						return ret;
+#if 0
+					if (card->flags & EICON_FLAGS_RUNNING)
+						return(eicon_capi_manufacturer_req_msn(card));
+#endif
+					return 0;
+#endif
+				case EICON_IOCTL_ADDCARD:
+					if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef))))
+						return -EFAULT;
+					if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id)))
+						return -EIO;
+					return 0;
+				case EICON_IOCTL_DEBUGVAR:
+					DebugVar = a;
+					printk(KERN_DEBUG"Eicon: Debug Value set to %ld\n", DebugVar);
+					return 0;
+#ifdef MODULE
+				case EICON_IOCTL_FREEIT:
+					while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT;
+					MOD_INC_USE_COUNT;
+					return 0;
+#endif
+				default:
+					return -EINVAL;
+			}
+			break;
+		case ISDN_CMD_DIAL:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			save_flags(flags);
+			cli();
+			if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) {
+				restore_flags(flags);
+				if (DebugVar & 1)
+					printk(KERN_WARNING "Dial on channel %d with state %d\n",
+					chan->No, chan->fsm_state);
+				return -EBUSY;
+			}
+			if (card->ptype == ISDN_PTYPE_EURO)
+				tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1);
+			else
+				tmp[0] = c->parm.setup.eazmsn[0];
+			chan->fsm_state = EICON_STATE_OCALL;
+			chan->callref = 0xffff;
+			restore_flags(flags);
+			
+			ret = idi_connect_req(card, chan, c->parm.setup.phone,
+						     c->parm.setup.eazmsn,
+						     c->parm.setup.si1,
+						     c->parm.setup.si2);
+			if (ret) {
+				cmd.driver = card->myid;
+				cmd.command = ISDN_STAT_DHUP;
+				cmd.arg &= 0x1f;
+				card->interface.statcallb(&cmd);
+			}
+			return ret;
+		case ISDN_CMD_ACCEPTD:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			if (chan->fsm_state == EICON_STATE_ICALL) { 
+				idi_connect_res(card, chan);
+			}
+			return 0;
+		case ISDN_CMD_ACCEPTB:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			return 0;
+		case ISDN_CMD_HANGUP:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			idi_hangup(card, chan);
+			return 0;
+		case ISDN_CMD_SETEAZ:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			if (strlen(c->parm.num)) {
+				if (card->ptype == ISDN_PTYPE_EURO) {
+					chan->eazmask = eicon_find_msn(card, c->parm.num, 0);
+				}
+				if (card->ptype == ISDN_PTYPE_1TR6) {
+					int i;
+					chan->eazmask = 0;
+					for (i = 0; i < strlen(c->parm.num); i++)
+						if (isdigit(c->parm.num[i]))
+							chan->eazmask |= (1 << (c->parm.num[i] - '0'));
+				}
+			} else
+				chan->eazmask = 0x3ff;
+			eicon_idi_listen_req(card, chan);
+			return 0;
+		case ISDN_CMD_CLREAZ:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			chan->eazmask = 0;
+			eicon_idi_listen_req(card, chan);
+			return 0;
+		case ISDN_CMD_SETL2:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			chan->l2prot = (c->arg >> 8);
+			return 0;
+		case ISDN_CMD_GETL2:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			return chan->l2prot;
+		case ISDN_CMD_SETL3:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			chan->l3prot = (c->arg >> 8);
+			return 0;
+		case ISDN_CMD_GETL3:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			return chan->l3prot;
+		case ISDN_CMD_GETEAZ:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (DebugVar & 1)
+				printk(KERN_DEBUG "eicon CMD_GETEAZ not implemented\n");
+			return 0;
+		case ISDN_CMD_SETSIL:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (DebugVar & 1)
+				printk(KERN_DEBUG "eicon CMD_SETSIL not implemented\n");
+			return 0;
+		case ISDN_CMD_GETSIL:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (DebugVar & 1)
+				printk(KERN_DEBUG "eicon CMD_GETSIL not implemented\n");
+			return 0;
+		case ISDN_CMD_LOCK:
+			MOD_INC_USE_COUNT;
+			return 0;
+		case ISDN_CMD_UNLOCK:
+			MOD_DEC_USE_COUNT;
+			return 0;
+		case ISDN_CMD_AUDIO:
+			if (!card->flags & EICON_FLAGS_RUNNING)
+				return -ENODEV;
+			if (!(chan = find_channel(card, c->arg & 0x1f)))
+				break;
+			idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num);
+			return 0;
+        }
+	
+        return -EINVAL;
+}
+
+/*
+ * Find card with given driverId
+ */
+static inline eicon_card *
+eicon_findcard(int driverid)
+{
+        eicon_card *p = cards;
+
+        while (p) {
+                if (p->myid == driverid)
+                        return p;
+                p = p->next;
+        }
+        return (eicon_card *) 0;
+}
+
+/*
+ * Wrapper functions for interface to linklevel
+ */
+static int
+if_command(isdn_ctrl * c)
+{
+        eicon_card *card = eicon_findcard(c->driver);
+
+        if (card)
+                return (eicon_command(card, c));
+        printk(KERN_ERR
+             "eicon: if_command %d called with invalid driverId %d!\n",
+               c->command, c->driver);
+        return -ENODEV;
+}
+
+static int
+if_writecmd(const u_char * buf, int len, int user, int id, int channel)
+{
+        eicon_card *card = eicon_findcard(id);
+
+        if (card) {
+                if (!card->flags & EICON_FLAGS_RUNNING)
+                        return -ENODEV;
+                return (len);
+        }
+        printk(KERN_ERR
+               "eicon: if_writecmd called with invalid driverId!\n");
+        return -ENODEV;
+}
+
+static int
+if_readstatus(u_char * buf, int len, int user, int id, int channel)
+{
+#if 0
+	/* Not yet used */
+        eicon_card *card = eicon_findcard(id);
+	
+        if (card) {
+                if (!card->flags & EICON_FLAGS_RUNNING)
+                        return -ENODEV;
+                return (eicon_readstatus(buf, len, user, card));
+        }
+        printk(KERN_ERR
+               "eicon: if_readstatus called with invalid driverId!\n");
+#endif
+        return -ENODEV;
+}
+
+static int
+if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
+{
+        eicon_card *card = eicon_findcard(id);
+	eicon_chan *chan;
+	int ret = 0;
+	int len;
+
+	len = skb->len;
+	
+        if (card) {
+                if (!card->flags & EICON_FLAGS_RUNNING) {
+			dev_kfree_skb(skb);
+                        return -ENODEV;
+		}
+        	if (!(chan = find_channel(card, channel))) {
+			dev_kfree_skb(skb);
+			return -ENODEV;
+		}
+		if (chan->fsm_state == EICON_STATE_ACTIVE) {
+				ret = idi_send_data(card, chan, ack, skb, 1);
+			return (ret);
+		} else {
+			dev_kfree_skb(skb);
+			return -ENODEV;
+		}
+        }
+        printk(KERN_ERR
+               "eicon: if_sendbuf called with invalid driverId!\n");
+	dev_kfree_skb(skb);
+        return -ENODEV;
+}
+
+
+/*
+ * Allocate a new card-struct, initialize it
+ * link it into cards-list.
+ */
+static void
+eicon_alloccard(int Type, int membase, int irq, char *id)
+{
+	int i;
+	int j;
+	int qloop;
+	char qid[5];
+        eicon_card *card;
+#if CONFIG_PCI
+	eicon_pci_card *pcic;
+#endif
+
+	qloop = (Type == EICON_CTYPE_QUADRO)?2:0;
+	for (i = 0; i <= qloop; i++) {
+		if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) {
+			printk(KERN_WARNING
+			       "eicon: (%s) Could not allocate card-struct.\n", id);
+			return;
+		}
+		memset((char *) card, 0, sizeof(eicon_card));
+		skb_queue_head_init(&card->sndq);
+		skb_queue_head_init(&card->rcvq);
+		skb_queue_head_init(&card->rackq);
+		skb_queue_head_init(&card->sackq);
+		card->snd_tq.routine = (void *) (void *) eicon_transmit;
+		card->snd_tq.data = card;
+		card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch;
+		card->rcv_tq.data = card;
+		card->ack_tq.routine = (void *) (void *) eicon_ack_dispatch;
+		card->ack_tq.data = card;
+		card->interface.maxbufsize = 4000;
+		card->interface.command = if_command;
+		card->interface.writebuf_skb = if_sendbuf;
+		card->interface.writecmd = if_writecmd;
+		card->interface.readstat = if_readstatus;
+		card->interface.features =
+			ISDN_FEATURE_L2_X75I |
+			ISDN_FEATURE_L2_HDLC |
+			ISDN_FEATURE_L2_TRANS |
+			ISDN_FEATURE_L3_TRANS |
+			ISDN_FEATURE_P_UNKNOWN;
+		card->interface.hl_hdrlen = 20;
+		card->ptype = ISDN_PTYPE_UNKNOWN;
+		strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
+		card->myid = -1;
+		card->type = Type;
+		switch (Type) {
+#if CONFIG_MCA /* only needed for MCA */
+                        case EICON_CTYPE_S:
+                        case EICON_CTYPE_SX:
+                        case EICON_CTYPE_SCOM:
+                                if (membase == -1)
+                                        membase = EICON_ISA_MEMBASE;
+                                if (irq == -1)
+                                        irq = EICON_ISA_IRQ;
+                                card->bus = EICON_BUS_MCA;
+                                card->hwif.isa.card = (void *)card;
+                                card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
+                                card->hwif.isa.master = 1;
+
+                                card->hwif.isa.irq = irq;
+                                card->hwif.isa.type = Type;
+                                card->nchannels = 2;
+                                card->interface.channels = 1;
+                                break;
+#endif /* CONFIG_MCA */
+			case EICON_CTYPE_QUADRO:
+				if (membase == -1)
+					membase = EICON_ISA_MEMBASE;
+				if (irq == -1)
+					irq = EICON_ISA_IRQ;
+                                card->bus = EICON_BUS_ISA;
+				card->hwif.isa.card = (void *)card;
+				card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET);
+				card->hwif.isa.master = 0;
+				strcpy(card->interface.id, id);
+				if (id[strlen(id) - 1] == 'a') {
+					card->interface.id[strlen(id) - 1] = 'a' + i + 1;
+				} else {
+					sprintf(qid, "_%c",'2' + i);
+					strcat(card->interface.id, qid);
+				}
+				printk(KERN_INFO "Eicon: Quadro: Driver-Id %s added.\n",
+					card->interface.id);
+				if (i == 0) {
+					eicon_card *p = cards;
+					while(p) {
+						if ((p->hwif.isa.master) && (p->hwif.isa.irq == irq)) {
+							p->qnext = card;
+							break;
+						}
+						p = p->next;
+					}
+					if (!p) {
+						printk(KERN_WARNING "eicon_alloccard: Quadro Master not found.\n");
+						kfree(card);
+						return;
+					}
+				} else {
+					cards->qnext = card;
+				}
+				card->hwif.isa.irq = irq;
+				card->hwif.isa.type = Type;
+				card->nchannels = 2;
+				card->interface.channels = 1;
+				break;
+#if CONFIG_PCI
+			case EICON_CTYPE_MAESTRA:
+				(eicon_pci_card *)pcic = (eicon_pci_card *)membase;
+                                card->bus = EICON_BUS_PCI;
+				card->interface.features |=
+					ISDN_FEATURE_L2_V11096 |
+					ISDN_FEATURE_L2_V11019 |
+					ISDN_FEATURE_L2_V11038 |
+					ISDN_FEATURE_L2_MODEM |
+					ISDN_FEATURE_L2_FAX |
+					ISDN_FEATURE_L3_TRANSDSP |
+					ISDN_FEATURE_L3_FAX;
+                                card->hwif.pci.card = (void *)card;
+				card->hwif.pci.PCIreg = pcic->PCIreg;
+				card->hwif.pci.PCIcfg = pcic->PCIcfg;
+                                card->hwif.pci.master = 1;
+                                card->hwif.pci.mvalid = pcic->mvalid;
+                                card->hwif.pci.ivalid = 0;
+                                card->hwif.pci.irq = irq;
+                                card->hwif.pci.type = Type;
+				card->flags = 0;
+                                card->nchannels = 2;
+				card->interface.channels = 1;
+				break;
+
+			case EICON_CTYPE_MAESTRAP:
+				(eicon_pci_card *)pcic = (eicon_pci_card *)membase;
+                                card->bus = EICON_BUS_PCI;
+				card->interface.features |=
+					ISDN_FEATURE_L2_V11096 |
+					ISDN_FEATURE_L2_V11019 |
+					ISDN_FEATURE_L2_V11038 |
+					ISDN_FEATURE_L2_MODEM |
+					ISDN_FEATURE_L2_FAX |
+					ISDN_FEATURE_L3_TRANSDSP |
+					ISDN_FEATURE_L3_FAX;
+                                card->hwif.pci.card = (void *)card;
+                                card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem;
+				card->hwif.pci.PCIreg = pcic->PCIreg;
+				card->hwif.pci.PCIram = pcic->PCIram;
+				card->hwif.pci.PCIcfg = pcic->PCIcfg;
+                                card->hwif.pci.master = 1;
+                                card->hwif.pci.mvalid = pcic->mvalid;
+                                card->hwif.pci.ivalid = 0;
+                                card->hwif.pci.irq = irq;
+                                card->hwif.pci.type = Type;
+				card->flags = 0;
+                                card->nchannels = 30;
+				card->interface.channels = 1;
+				break;
+#endif
+			case EICON_CTYPE_ISABRI:
+				if (membase == -1)
+					membase = EICON_ISA_MEMBASE;
+				if (irq == -1)
+					irq = EICON_ISA_IRQ;
+				card->bus = EICON_BUS_ISA;
+				card->hwif.isa.card = (void *)card;
+				card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
+				card->hwif.isa.master = 1;
+				card->hwif.isa.irq = irq;
+				card->hwif.isa.type = Type;
+				card->nchannels = 2;
+				card->interface.channels = 1;
+				break;
+			case EICON_CTYPE_ISAPRI:
+				if (membase == -1)
+					membase = EICON_ISA_MEMBASE;
+				if (irq == -1)
+					irq = EICON_ISA_IRQ;
+                                card->bus = EICON_BUS_ISA;
+				card->hwif.isa.card = (void *)card;
+				card->hwif.isa.shmem = (eicon_isa_shmem *)membase;
+				card->hwif.isa.master = 1;
+				card->hwif.isa.irq = irq;
+				card->hwif.isa.type = Type;
+				card->nchannels = 30;
+				card->interface.channels = 1;
+				break;
+			default:
+				printk(KERN_WARNING "eicon_alloccard: Invalid type %d\n", Type);
+				kfree(card);
+				return;
+		}
+		if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1)
+							 , GFP_KERNEL))) {
+			printk(KERN_WARNING
+			       "eicon: (%s) Could not allocate bch-struct.\n", id);
+			kfree(card);
+			return;
+		}
+		for (j=0; j< (card->nchannels + 1); j++) {
+			memset((char *)&card->bch[j], 0, sizeof(eicon_chan));
+			card->bch[j].plci = 0x8000;
+			card->bch[j].ncci = 0x8000;
+			card->bch[j].l2prot = ISDN_PROTO_L2_X75I;
+			card->bch[j].l3prot = ISDN_PROTO_L3_TRANS;
+			card->bch[j].e.D3Id = 0;
+			card->bch[j].e.B2Id = 0;
+			card->bch[j].e.Req = 0;
+			card->bch[j].No = j;
+			skb_queue_head_init(&card->bch[j].e.X);
+			skb_queue_head_init(&card->bch[j].e.R);
+		}
+		card->next = cards;
+		cards = card;
+	}
+}
+
+/*
+ * register card at linklevel
+ */
+static int
+eicon_registercard(eicon_card * card)
+{
+        switch (card->bus) {
+		case EICON_BUS_ISA:
+			/* TODO something to print */
+			break;
+#ifdef CONFIG_MCA
+		case EICON_BUS_MCA:
+			eicon_isa_printpar(&card->hwif.isa);
+			break;
+#endif
+		case EICON_BUS_PCI:
+#if CONFIG_PCI
+			eicon_pci_printpar(&card->hwif.pci); 
+			break;
+#endif
+		default:
+			if (DebugVar & 1)
+				printk(KERN_WARNING
+				       "eicon_registercard: Illegal BUS type %d\n",
+			       card->bus);
+			return -1;
+        }
+        if (!register_isdn(&card->interface)) {
+                printk(KERN_WARNING
+                       "eicon_registercard: Unable to register %s\n",
+                       card->interface.id);
+                return -1;
+        }
+        card->myid = card->interface.channels;
+        sprintf(card->regname, "%s", card->interface.id);
+        return 0;
+}
+
+#ifdef MODULE
+static void
+unregister_card(eicon_card * card)
+{
+        isdn_ctrl cmd;
+
+        cmd.command = ISDN_STAT_UNLOAD;
+        cmd.driver = card->myid;
+        card->interface.statcallb(&cmd);
+        switch (card->bus) {
+		case EICON_BUS_ISA:
+#ifdef CONFIG_MCA
+		case EICON_BUS_MCA:
+#endif
+			eicon_isa_release(&card->hwif.isa);
+			break;
+		case EICON_BUS_PCI:
+#if CONFIG_PCI
+			eicon_pci_release(&card->hwif.pci);
+			break;
+#endif
+		default:
+			if (DebugVar & 1)
+				printk(KERN_WARNING
+				       "eicon: Invalid BUS type %d\n",
+			       card->bus);
+			break;
+        }
+}
+#endif /* MODULE */
+
+static void
+eicon_freecard(eicon_card *card) {
+	eicon_clear_msn(card);
+	kfree(card->bch);
+	kfree(card);
+}
+
+int
+eicon_addcard(int Type, int membase, int irq, char *id)
+{
+	eicon_card *p;
+	eicon_card *q = NULL;
+	int registered;
+	int added = 0;
+	int failed = 0;
+
+	if (!Type) /* ISA */
+		if ((Type = eicon_isa_find_card(membase, irq, id)) < 0)
+			return 0;
+	eicon_alloccard(Type, membase, irq, id);
+        p = cards;
+        while (p) {
+		registered = 0;
+		if (!p->interface.statcallb) {
+			/* Not yet registered.
+			 * Try to register and activate it.
+			 */
+			added++;
+			switch (p->bus) {
+				case EICON_BUS_ISA:
+				case EICON_BUS_MCA:
+					if (eicon_registercard(p))
+						break;
+					registered = 1;
+					break;
+				case EICON_BUS_PCI:
+#if CONFIG_PCI
+					if (eicon_registercard(p))
+						break;
+					registered = 1;
+					break;
+#endif
+				default:
+					if (DebugVar & 1)
+						printk(KERN_WARNING
+						       "eicon: addcard: Invalid BUS type %d\n",
+					       p->bus);
+			}
+		} else
+			/* Card already registered */
+			registered = 1;
+                if (registered) {
+			/* Init OK, next card ... */
+                        q = p;
+                        p = p->next;
+                } else {
+                        /* registering failed, remove card from list, free memory */
+                        printk(KERN_WARNING
+                               "eicon: Initialization of %s failed\n",
+                               p->interface.id);
+                        if (q) {
+                                q->next = p->next;
+                                eicon_freecard(p);
+                                p = q->next;
+                        } else {
+                                cards = p->next;
+                                eicon_freecard(p);
+                                p = cards;
+                        }
+			failed++;
+                }
+	}
+        return (added - failed);
+}
+
+#define DRIVERNAME "Eicon active ISDN driver"
+#define DRIVERRELEASE "1"
+
+#ifdef MODULE
+#define eicon_init init_module
+#endif
+
+__initfunc(int
+eicon_init(void))
+{
+	int card_count = 0;
+	int release = 0;
+	char tmprev[50];
+
+	DebugVar = 1;
+
+        printk(KERN_INFO "%s Rev: ", DRIVERNAME);
+	strcpy(tmprev, eicon_revision);
+	printk("%s/", eicon_getrev(tmprev));
+	release += getrel(tmprev);
+	strcpy(tmprev, eicon_pci_revision);
+	printk("%s/", eicon_getrev(tmprev));
+	release += getrel(tmprev);
+	strcpy(tmprev, eicon_isa_revision);
+	printk("%s/", eicon_getrev(tmprev));
+	release += getrel(tmprev);
+	strcpy(tmprev, eicon_idi_revision);
+	printk("%s\n", eicon_getrev(tmprev));
+	release += getrel(tmprev);
+	sprintf(tmprev,"%d", release);
+        printk(KERN_INFO "%s Release: %s.%s\n", DRIVERNAME,
+		DRIVERRELEASE, tmprev);
+
+#ifdef CONFIG_MCA
+	/* Check if we have MCA-bus */
+        if (!MCA_bus)
+                {
+                printk(KERN_INFO
+                        "eicon: No MCA bus, ISDN-interfaces  not probed.\n");
+        } else {
+		if (DebugVar & 8)
+               		printk(KERN_DEBUG
+			       "eicon_mca_find_card, irq=%d.\n", 
+                                irq);
+               	if (!eicon_mca_find_card(0, membase, irq, id))
+                       card_count++;
+        };
+#else
+	card_count = eicon_addcard(0, membase, irq, id);
+#endif /* CONFIG_MCA */
+ 
+#if CONFIG_PCI
+	card_count += eicon_pci_find_card(id);
+#endif
+        if (!cards) {
+#ifdef MODULE
+                printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n");
+#endif
+		return -ENODEV;
+
+	} else
+		printk(KERN_INFO "Eicon: %d card%s added\n", card_count, 
+                       (card_count>1)?"s":"");
+        /* No symbols to export, hide all symbols */
+        EXPORT_NO_SYMBOLS;
+        return 0;
+}
+
+#ifdef MODULE
+void
+cleanup_module(void)
+{
+        eicon_card *card = cards;
+        eicon_card *last;
+        while (card) {
+#ifdef CONFIG_MCA
+        	if (MCA_bus)
+                        {
+                        mca_mark_as_unused (card->mca_slot);
+                        mca_set_adapter_procfn(card->mca_slot, NULL, NULL);
+                        };
+#endif
+                unregister_card(card); 
+                card = card->next;
+        }
+        card = cards;
+        while (card) {
+                last = card;
+                card = card->next;
+		eicon_freecard(last);
+        }
+        printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
+}
+
+#else /* no module */
+__initfunc(void
+eicon_setup(char *str, int *ints))
+{
+        int i, argc;
+
+        argc = ints[0];
+        i = 1;
+        if (argc) {
+		membase = irq = -1;
+		if (argc) {
+			membase = ints[i];
+			i++;
+			argc--;
+		}
+		if (argc) {
+			irq = ints[i];
+			i++;
+			argc--;
+		}
+		if (strlen(str)) {
+			strcpy(id, str);
+		} else {
+			strcpy(id, "eicon");
+		} 
+		/* eicon_addcard(0, membase, irq, id); */
+       		printk(KERN_INFO "eicon: membase=0x%x irq=%d id=%s\n", membase, irq, id);
+	}
+}
+#endif /* MODULE */
+
+
+#ifdef CONFIG_MCA
+
+struct eicon_mca_adapters_struct {
+	char * name;
+	int adf_id;
+};
+/* possible MCA-brands of eicon cards                                         */
+struct eicon_mca_adapters_struct eicon_mca_adapters[] = {
+	{ "ISDN-P/2 Adapter", 0x6abb },
+	{ "ISDN-[S|SX|SCOM]/2 Adapter", 0x6a93 },
+	{ "DIVA /MCA", 0x6336 },
+	{ NULL, 0 },
+};
+
+int eicon_mca_find_card(int type,          /* type-idx of eicon-card          */
+                        int membase,
+		        int irq,
+			char * id)         /* name of eicon-isdn-dev          */
+{
+	int j, curr_slot = 0;
+
+	if (DebugVar & 8)
+        	printk(KERN_DEBUG
+                       "eicon_mca_find_card type: %d, membase: %#x, irq %d \n",
+                       type, membase, irq);
+	/* find a no-driver-assigned eicon card                               */
+	for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) 
+		{
+		for ( curr_slot=0; curr_slot<=MCA_MAX_SLOT_NR; curr_slot++) 
+			{
+			curr_slot = mca_find_unused_adapter(
+				         eicon_mca_adapters[j].adf_id, curr_slot);
+			if (curr_slot != MCA_NOTFOUND) 
+				{
+				/* check if pre-set parameters match
+				   these of the card, check cards memory      */
+				if (!(int) eicon_mca_probe(curr_slot,
+                                                           j,
+                                                	   membase, 
+                                                           irq,
+                                                           id))
+					{
+					return 0;
+					/* means: adapter parms did match     */
+					};
+			};
+			break;
+			/* MCA_NOTFOUND-branch: no matching adapter of
+			   THIS flavor found, next flavor                     */
+
+            	};
+	};
+	/* all adapter flavors checked without match, finito with:            */
+        return ENODEV;
+};
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ *  stolen from 3c523.c/elmc_getinfo, ewe, 10.5.1999 
+ */
+int eicon_info(char * buf, int slot, void *d)
+{
+	int len = 0;
+	struct eicon_card *dev;
+
+        dev = (struct eicon_card *) d;
+
+	if (dev == NULL)
+		return len;
+	len += sprintf(buf+len, "eicon ISDN adapter, type %d.\n",dev->type);
+	len += sprintf(buf+len, "IRQ: %d\n", dev->hwif.isa.irq);
+	len += sprintf(buf+len, "MEMBASE: %#lx\n", (unsigned long)dev->hwif.isa.shmem);
+
+	return len;
+};
+
+int eicon_mca_probe(int slot,  /* slot-nr where the card was detected         */
+		    int a_idx, /* idx-nr of probed card in eicon_mca_adapters */
+                    int membase,
+                    int irq,
+		    char * id) /* name of eicon-isdn-dev                      */
+{				
+	unsigned char adf_pos0;
+	int cards_irq, cards_membase, cards_io;
+	int type = EICON_CTYPE_S;
+	int irq_array[]={0,3,4,2};
+	int irq_array1[]={3,4,0,0,2,10,11,12};
+
+        adf_pos0 = mca_read_stored_pos(slot,2);
+	if (DebugVar & 8)
+		printk(KERN_DEBUG
+                       "eicon_mca_probe irq=%d, membase=%d\n", 
+                        irq,
+                        membase);
+	switch (a_idx) {
+		case 0:                /* P/2-Adapter (== PRI/S2M ? )         */
+			cards_membase= 0xC0000+((adf_pos0>>4)*0x4000);
+			if (membase == -1) { 
+				membase = cards_membase;
+			} else {
+				if (membase != cards_membase)
+					return ENODEV;
+			};
+			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
+			if (irq == -1) { 
+				irq = cards_irq;
+			} else {
+				if (irq != irq)
+					return ENODEV;
+			};
+			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
+			type = EICON_CTYPE_ISAPRI; 
+			break;
+
+		case 1:                /* [S|SX|SCOM]/2                       */
+			cards_membase= 0xC0000+((adf_pos0>>4)*0x2000);
+			if (membase == -1) { 
+				membase = cards_membase;
+			} else {
+				if (membase != cards_membase)
+					return ENODEV;
+			};
+			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
+			if (irq == -1) { 
+				irq = cards_irq;
+			} else {
+				if (irq != cards_irq)
+					return ENODEV;
+			};
+
+			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
+			type = EICON_CTYPE_SCOM; 
+		 	break;	
+
+		case 2:                /* DIVA/MCA                            */
+			cards_io = 0x200+ ((adf_pos0>>4)* 0x20);
+			cards_irq = irq_array1[(adf_pos0 & 0x7)];
+			if (irq == -1) { 
+				irq = cards_irq;
+			} else {
+				if (irq != irq)
+					return ENODEV;
+			};
+			type = 0; 
+			break;
+		default:
+			return  ENODEV;
+	};
+	/* Uebereinstimmung vorgegebener membase & irq */
+	if ( 1 == eicon_addcard(type, membase, irq, id)) { 
+		mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name);
+  		mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards);
+
+        	mca_mark_as_used(slot);
+		cards->mca_slot = slot; 
+		/* card->io noch setzen  oder ?? */
+		if (DebugVar & 8)
+			printk("eicon_addcard: erfolgreich fuer slot: %d.\n", 
+			cards->mca_slot+1);
+		return  0 ; /* eicon_addcard hat eine Karte zugefuegt */
+	} else {
+		return ENODEV;
+	};
+};
+#endif /* CONFIG_MCA */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_pci.c linux.pre11.3/drivers/isdn/eicon/eicon_pci.c
--- linux.vanilla/drivers/isdn/eicon/eicon_pci.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_pci.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,956 @@
+/* $Id: eicon_pci.c,v 1.7 1999/06/09 19:31:29 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * Hardware-specific code for PCI cards.
+ *
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * Thanks to	Eicon Technology Diehl GmbH & Co. oHG for 
+ *		documents, informations and hardware. 
+ *
+ *		Deutsche Telekom AG for S2M support.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_pci.c,v $
+ * Revision 1.7  1999/06/09 19:31:29  armin
+ * Wrong PLX size for request_region() corrected.
+ * Added first MCA code from Erik Weber.
+ *
+ * Revision 1.6  1999/04/01 12:48:37  armin
+ * Changed some log outputs.
+ *
+ * Revision 1.5  1999/03/29 11:19:49  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.4  1999/03/02 12:37:48  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.3  1999/01/24 20:14:24  armin
+ * Changed and added debug stuff.
+ * Better data sending. (still problems with tty's flip buffer)
+ *
+ * Revision 1.2  1999/01/10 18:46:06  armin
+ * Bug with wrong values in HLC fixed.
+ * Bytes to send are counted and limited now.
+ *
+ * Revision 1.1  1999/01/01 18:09:45  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#include <linux/pci.h>
+
+#include "eicon.h"
+#include "eicon_pci.h"
+
+
+char *eicon_pci_revision = "$Revision: 1.7 $";
+
+#if CONFIG_PCI	         /* intire stuff is only for PCI */
+
+#undef EICON_PCI_DEBUG 
+
+int eicon_pci_find_card(char *ID)
+{
+  if (pci_present()) { 
+    struct pci_dev *pdev = NULL;  
+    int pci_nextindex=0, pci_cards=0, pci_akt=0; 
+    int pci_type = PCI_MAESTRA;
+    int NoMorePCICards = FALSE;
+    char *ram, *reg, *cfg;	
+    unsigned int pram=0, preg=0, pcfg=0;
+    char did[12];
+    eicon_pci_card *aparms;
+
+   if (!(aparms = (eicon_pci_card *) kmalloc(sizeof(eicon_pci_card), GFP_KERNEL))) {
+                  printk(KERN_WARNING
+                      "eicon_pci: Could not allocate card-struct.\n");
+                  return 0;
+   }
+
+  for (pci_cards = 0; pci_cards < 0x0f; pci_cards++)
+  {
+  do {
+      if ((pdev = pci_find_device(PCI_VENDOR_EICON,          
+                                  pci_type,                  
+                                  pdev)))                    
+	{
+              pci_nextindex++;
+              break;
+	}
+	else {
+              pci_nextindex = 0;
+              switch (pci_type) /* switch to next card type */
+               {
+               case PCI_MAESTRA:
+                 pci_type = PCI_MAESTRAQ; break;
+               case PCI_MAESTRAQ:
+                 pci_type = PCI_MAESTRAQ_U; break;
+               case PCI_MAESTRAQ_U:
+                 pci_type = PCI_MAESTRAP; break;
+               default:
+               case PCI_MAESTRAP:
+                 NoMorePCICards = TRUE;
+               }
+	}
+     }
+     while (!NoMorePCICards);
+     if (NoMorePCICards)
+        {
+           if (pci_cards < 1) {
+           printk(KERN_INFO "Eicon: No supported PCI cards found.\n");
+	   kfree(aparms);	
+           return 0;
+           }
+           else
+           {
+           printk(KERN_INFO "Eicon: %d PCI card%s registered.\n",
+			pci_cards, (pci_cards > 1) ? "s":"");
+	   kfree(aparms);	
+           return (pci_cards);
+           }
+        }
+
+   pci_akt = 0;
+   switch(pci_type)
+   {
+    case PCI_MAESTRA:
+         printk(KERN_INFO "Eicon: DIVA Server BRI/PCI detected !\n");
+          aparms->type = EICON_CTYPE_MAESTRA;
+
+          aparms->irq = pdev->irq;
+          preg = pdev->base_address[2] & 0xfffffffc;
+          pcfg = pdev->base_address[1] & 0xffffff80;
+
+#ifdef EICON_PCI_DEBUG
+          printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
+          printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", preg);
+          printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", pcfg);
+#endif
+	 pci_akt = 1;
+         break;
+
+    case PCI_MAESTRAQ:
+    case PCI_MAESTRAQ_U:
+         printk(KERN_ERR "Eicon: DIVA Server 4BRI/PCI detected but not supported !\n");
+         pci_cards--;
+	 pci_akt = 0;
+         break;
+
+    case PCI_MAESTRAP:
+         printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n");
+          aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/
+          aparms->irq = pdev->irq;
+          pram = pdev->base_address[0] & 0xfffff000;
+          preg = pdev->base_address[2] & 0xfffff000;
+          pcfg = pdev->base_address[4] & 0xfffff000;
+
+#ifdef EICON_PCI_DEBUG
+          printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq);
+          printk(KERN_DEBUG "eicon_pci: ram=0x%x\n",
+               (pram));
+          printk(KERN_DEBUG "eicon_pci: reg=0x%x\n",
+               (preg));
+          printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n",
+               (pcfg));
+#endif
+	  pci_akt = 1;
+	  break;	
+    default:
+         printk(KERN_ERR "eicon_pci: Unknown PCI card detected !\n");
+         pci_cards--;
+	 pci_akt = 0;
+	 break;
+   }
+
+	if (pci_akt) {
+		/* remapping memory */
+		switch(pci_type)
+		{
+    		case PCI_MAESTRA:
+			aparms->PCIreg = (unsigned int) preg;
+			aparms->PCIcfg = (unsigned int) pcfg;
+			if (check_region((aparms->PCIreg), 0x20)) {
+				printk(KERN_WARNING "eicon_pci: reg port already in use !\n");
+				aparms->PCIreg = 0;
+				break;	
+			} else {
+				request_region(aparms->PCIreg, 0x20, "eicon reg");
+			}
+			if (check_region((aparms->PCIcfg), 0x80)) {
+				printk(KERN_WARNING "eicon_pci: cfg port already in use !\n");
+				aparms->PCIcfg = 0;
+				release_region(aparms->PCIreg, 0x20);
+				break;	
+			} else {
+				request_region(aparms->PCIcfg, 0x80, "eicon cfg");
+			}
+			break;
+    		case PCI_MAESTRAQ:
+		case PCI_MAESTRAQ_U:
+		case PCI_MAESTRAP:
+			aparms->shmem = (eicon_pci_shmem *) ioremap(pram, 0x10000);
+			ram = (u8 *) ((u32)aparms->shmem + MP_SHARED_RAM_OFFSET);
+			reg =  ioremap(preg, 0x4000);
+			cfg =  ioremap(pcfg, 0x1000);	
+			aparms->PCIram = (unsigned int) ram;
+			aparms->PCIreg = (unsigned int) reg;
+			aparms->PCIcfg = (unsigned int) cfg;
+			break;
+		 }
+		if ((!aparms->PCIreg) || (!aparms->PCIcfg)) {
+			printk(KERN_ERR "eicon_pci: Card could not be added !\n");
+			pci_cards--;
+		} else {
+			aparms->mvalid = 1;
+	
+			sprintf(did, "%s%d", (strlen(ID) < 1) ? "eicon":ID, pci_cards);
+
+			printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[aparms->type] , did);
+
+			if (!(eicon_addcard(aparms->type, (int) aparms, aparms->irq, did))) {
+				printk(KERN_ERR "eicon_pci: Card could not be added !\n");
+				pci_cards--;
+			}
+		}
+	}
+
+  }
+ } else
+	printk(KERN_ERR "eicon_pci: Kernel compiled with PCI but no PCI-bios found !\n");
+ return 0;
+}
+
+/*
+ * Checks protocol file id for "F#xxxx" string fragment to
+ * extract the features, supported by this protocol version.
+ * binary representation of the feature string value is returned
+ * in *value. The function returns 0 if feature string was not
+ * found or has a wrong format, else 1.
+ */
+static int GetProtFeatureValue(char *sw_id, int *value)
+{
+  __u8 i, offset;
+
+  while (*sw_id)
+  {
+    if ((sw_id[0] == 'F') && (sw_id[1] == '#'))
+    {
+      sw_id = &sw_id[2];
+      for (i=0, *value=0; i<4; i++, sw_id++)
+      {
+        if ((*sw_id >= '0') && (*sw_id <= '9'))
+        {
+          offset = '0';
+        }
+        else if ((*sw_id >= 'A') && (*sw_id <= 'F'))
+        {
+          offset = 'A' + 10;
+        }
+        else if ((*sw_id >= 'a') && (*sw_id <= 'f'))
+        {
+          offset = 'a' + 10;
+        }
+        else
+        {
+          return 0;
+        }
+        *value |= (*sw_id - offset) << (4*(3-i));
+      }
+      return 1;
+    }
+    else
+    {
+      sw_id++;
+    }
+  }
+  return 0;
+}
+
+
+void
+eicon_pci_printpar(eicon_pci_card *card) {
+        switch (card->type) {
+                case EICON_CTYPE_MAESTRA:
+			printk(KERN_INFO "%s at 0x%x / 0x%x, irq %d\n",
+				eicon_ctype_name[card->type],
+				(unsigned int)card->PCIreg,
+				(unsigned int)card->PCIcfg,
+				card->irq); 
+			break;
+                case EICON_CTYPE_MAESTRAQ:
+                case EICON_CTYPE_MAESTRAQ_U:
+                case EICON_CTYPE_MAESTRAP:
+			printk(KERN_INFO "%s at 0x%x, irq %d\n",
+				eicon_ctype_name[card->type],
+				(unsigned int)card->shmem,
+				card->irq); 
+#ifdef EICON_PCI_DEBUG
+		        printk(KERN_INFO "eicon_pci: remapped ram= 0x%x\n",(unsigned int)card->PCIram);
+		        printk(KERN_INFO "eicon_pci: remapped reg= 0x%x\n",(unsigned int)card->PCIreg);
+		        printk(KERN_INFO "eicon_pci: remapped cfg= 0x%x\n",(unsigned int)card->PCIcfg); 
+#endif
+			break;
+	}
+}
+
+
+static void
+eicon_pci_release_shmem(eicon_pci_card *card) {
+	if (!card->master)
+		return;
+	if (card->mvalid) {
+        	switch (card->type) {
+                	case EICON_CTYPE_MAESTRA:
+			        /* reset board */
+				outb(0, card->PCIcfg + 0x4c);	/* disable interrupts from PLX */
+				outb(0, card->PCIreg + M_RESET);
+				SLEEP(20);
+				outb(0, card->PCIreg + M_ADDRH);
+				outw(0, card->PCIreg + M_ADDR);
+				outw(0, card->PCIreg + M_DATA);
+
+				release_region(card->PCIreg, 0x20);
+				release_region(card->PCIcfg, 0x80);
+				break;
+                	case EICON_CTYPE_MAESTRAQ:
+	                case EICON_CTYPE_MAESTRAQ_U:
+	                case EICON_CTYPE_MAESTRAP:
+			        /* reset board */
+		        	writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
+			        SLEEP(20);
+			        writeb(0, card->PCIreg + MP_RESET);
+			        SLEEP(20);
+
+				iounmap((void *)card->shmem);
+				iounmap((void *)card->PCIreg);
+				iounmap((void *)card->PCIcfg);
+				break;
+		}
+	}
+	card->mvalid = 0;
+}
+
+static void
+eicon_pci_release_irq(eicon_pci_card *card) {
+	if (!card->master)
+		return;
+	if (card->ivalid)
+		free_irq(card->irq, card);
+	card->ivalid = 0;
+}
+
+void
+eicon_pci_release(eicon_pci_card *card) {
+        eicon_pci_release_irq(card);
+        eicon_pci_release_shmem(card);
+}
+
+/*
+ * Upload buffer content to adapters shared memory
+ * on verify error, 1 is returned and a message is printed on screen
+ * else 0 is returned
+ * Can serve IO-Type and Memory type adapters
+ */
+int eicon_upload(t_dsp_download_space   *p_para,
+            __u16                 length,   /* byte count */
+            __u8                  *buffer,
+            int                   verify)
+{
+  __u32               i, dwdata = 0, val = 0, timeout;
+  __u16               data;
+  eicon_pci_boot *boot = 0;
+
+  switch (p_para->type) /* actions depend on type of union */
+  {
+    case DL_PARA_IO_TYPE:
+      for (i=0; i<length; i+=2)
+      {
+	outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
+	outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); 
+	/* outw (((u16 *)code)[i >> 1], p_para->dat.io.ioDATA); */
+	outw (*(u16 *)&buffer[i], p_para->dat.io.ioDATA); 
+      }
+      if (verify) /* check written block */
+      {
+        for (i=0; i<length; i+=2)
+        {
+	  outb ((u8) ((p_para->dat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH);
+          outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); 
+          data = inw(p_para->dat.io.ioDATA);
+          if (data != *(u16 *)&buffer[i])
+          {
+            p_para->dat.io.r3addr  += i;
+            p_para->dat.io.BadData  = data;
+            p_para->dat.io.GoodData = *(u16 *)&buffer[i];
+            return 1;
+          }
+        }
+      }
+      break;
+
+    case DL_PARA_MEM_TYPE:
+      boot = p_para->dat.mem.boot;
+      writel(p_para->dat.mem.r3addr, &boot->addr);
+      for (i=0; i<length; i+=4)
+      {
+        writel(((u32 *)buffer)[i >> 2], &boot->data[i]);
+      }
+      if (verify) /* check written block */
+      {
+        for (i=0; i<length; i+=4)
+        {
+          dwdata = readl(&boot->data[i]);
+          if (((u32 *)buffer)[i >> 2] != dwdata)
+          {
+            p_para->dat.mem.r3addr  += i;
+            p_para->dat.mem.BadData  = dwdata;
+            p_para->dat.mem.GoodData = ((u32 *)buffer)[i >> 2];
+            return 1;
+          }
+        }
+      }
+      writel(((length + 3) / 4), &boot->len);  /* len in dwords */
+      writel(2, &boot->cmd);
+
+	timeout = jiffies + 20;
+	while (timeout > jiffies) {
+		val = readl(&boot->cmd);
+		if (!val) break;
+		SLEEP(2);
+	}
+	if (val)
+         {
+		p_para->dat.mem.timeout = 1;
+		return 1;
+	 }
+      break;
+  }
+  return 0;
+}
+
+
+/* show header information of code file */
+static
+int eicon_pci_print_hdr(unsigned char *code, int offset)
+{
+  unsigned char hdr[80];
+  int i, fvalue = 0;
+
+  i = 0;
+  while ((i < (sizeof(hdr) -1))
+          && (code[offset + i] != '\0')
+          && (code[offset + i] != '\r')
+          && (code[offset + i] != '\n'))
+   {
+     hdr[i] = code[offset + i];
+     i++;
+   }
+   hdr[i] = '\0';
+   printk(KERN_DEBUG "Eicon: loading %s\n", hdr);
+   if (GetProtFeatureValue(hdr, &fvalue)) return(fvalue);
+    else return(0);
+}
+
+
+/*
+ * Configure a card, download code into BRI card,
+ * check if we get interrupts and return 0 on succes.
+ * Return -ERRNO on failure.
+ */
+int
+eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
+        int               i,j;
+        int               timeout;
+	unsigned int	  offset, offp=0, size, length;
+	int		  signature = 0;
+	int		  FeatureValue = 0;
+        eicon_pci_codebuf cbuf;
+	t_dsp_download_space dl_para;
+	t_dsp_download_desc  dsp_download_table;
+        unsigned char     *code;
+	unsigned int	  reg;
+	unsigned int	  cfg;
+
+        if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
+                return -EFAULT;
+
+	reg = card->PCIreg;
+	cfg = card->PCIcfg;
+
+	/* reset board */
+	outb(0, reg + M_RESET);
+	SLEEP(10);
+	outb(0, reg + M_ADDRH);
+	outw(0, reg + M_ADDR);
+	outw(0, reg + M_DATA);
+
+#ifdef EICON_PCI_DEBUG
+	 printk(KERN_DEBUG "eicon_pci: reset card\n");
+#endif
+
+	/* clear shared memory */
+	outb(0xff, reg + M_ADDRH);
+	outw(0, reg + M_ADDR);
+	for(i = 0; i < 0xffff; i++) outw(0, reg + M_DATA);
+	SLEEP(10);
+
+#ifdef EICON_PCI_DEBUG
+	 printk(KERN_DEBUG "eicon_pci: clear shared memory\n");
+#endif
+
+	/* download protocol and dsp file */
+
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
+#endif
+
+       	/* Allocate code-buffer */
+       	if (!(code = kmalloc(400, GFP_KERNEL))) {
+                printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
+       	        return -ENOMEM;
+        }
+
+	/* prepare protocol upload */
+	dl_para.type		= DL_PARA_IO_TYPE;
+	dl_para.dat.io.ioADDR	= reg + M_ADDR;
+	dl_para.dat.io.ioADDRH	= reg + M_ADDRH;
+	dl_para.dat.io.ioDATA	= reg + M_DATA;
+
+	for (j = 0; j <= cbuf.dsp_code_num; j++) 
+	 {	
+	   if (j == 0)  size = cbuf.protocol_len;
+	           else size = cbuf.dsp_code_len[j];
+
+        	offset = 0;
+
+		if (j == 0) dl_para.dat.io.r3addr = 0;
+		if (j == 1) dl_para.dat.io.r3addr = M_DSP_CODE_BASE +
+					((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
+		if (j == 2) dl_para.dat.io.r3addr = M_DSP_CODE_BASE;
+		if (j == 3) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + sizeof(__u32);
+
+           do  /* download block of up to 400 bytes */
+            {
+              length = ((size - offset) >= 400) ? 400 : (size - offset);
+
+        	if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
+                	kfree(code);
+	                return -EFAULT;
+        	}
+
+		if ((offset == 0) && (j < 2)) {
+		       	FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); 
+#ifdef EICON_PCI_DEBUG
+	if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%04x.\n", FeatureValue);
+#endif
+			if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
+                  		printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
+				kfree(code);
+		                return -EFAULT;
+			}
+                	((eicon_card *)card->card)->Feature = FeatureValue;
+		}
+
+		if (eicon_upload(&dl_para, length, code, 1))
+		{
+                  printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
+		  kfree(code);
+                  return -EIO;
+		}
+              /* move onto next block */
+              offset += length;
+	      dl_para.dat.io.r3addr += length;
+            } while (offset < size);
+
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "Eicon: %d bytes loaded.\n", offset);
+#endif
+	offp += size;
+	}
+	kfree(code);	
+
+	/* clear signature */
+	outb(0xff, reg + M_ADDRH);
+	outw(0x1e, reg + M_ADDR);
+	outw(0, reg + M_DATA);
+
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
+#endif
+	/* copy configuration data into shared memory */
+	outw(8, reg + M_ADDR); outb(cbuf.tei, reg + M_DATA);
+	outw(9, reg + M_ADDR); outb(cbuf.nt2, reg + M_DATA);
+	outw(10,reg + M_ADDR); outb(0, reg + M_DATA);
+	outw(11,reg + M_ADDR); outb(cbuf.WatchDog, reg + M_DATA);
+	outw(12,reg + M_ADDR); outb(cbuf.Permanent, reg + M_DATA);
+	outw(13,reg + M_ADDR); outb(0, reg + M_DATA);                 /* XInterface */
+	outw(14,reg + M_ADDR); outb(cbuf.StableL2, reg + M_DATA);
+	outw(15,reg + M_ADDR); outb(cbuf.NoOrderCheck, reg + M_DATA);
+	outw(16,reg + M_ADDR); outb(0, reg + M_DATA);                 /* HandsetType */
+	outw(17,reg + M_ADDR); outb(0, reg + M_DATA);                 /* SigFlags */
+	outw(18,reg + M_ADDR); outb(cbuf.LowChannel, reg + M_DATA);
+	outw(19,reg + M_ADDR); outb(cbuf.ProtVersion, reg + M_DATA);
+	outw(20,reg + M_ADDR); outb(cbuf.Crc4, reg + M_DATA);
+	outw(21,reg + M_ADDR); outb((cbuf.Loopback) ? 2:0, reg + M_DATA);
+
+	for (i=0;i<32;i++)
+	{
+		outw( 32+i, reg + M_ADDR); outb(cbuf.l[0].oad[i], reg + M_DATA);
+		outw( 64+i, reg + M_ADDR); outb(cbuf.l[0].osa[i], reg + M_DATA);
+		outw( 96+i, reg + M_ADDR); outb(cbuf.l[0].spid[i], reg + M_DATA);
+		outw(128+i, reg + M_ADDR); outb(cbuf.l[1].oad[i], reg + M_DATA);
+		outw(160+i, reg + M_ADDR); outb(cbuf.l[1].osa[i], reg + M_DATA);
+		outw(192+i, reg + M_ADDR); outb(cbuf.l[1].spid[i], reg + M_DATA);
+	}
+
+#ifdef EICON_PCI_DEBUG
+           printk(KERN_ERR "eicon_pci: starting CPU...\n");
+#endif
+	/* let the CPU run */
+	outw(0x08, reg + M_RESET);
+
+        timeout = jiffies + (5*HZ);
+        while (timeout > jiffies) {
+	   outw(0x1e, reg + M_ADDR);	
+           signature = inw(reg + M_DATA);
+           if (signature == DIVAS_SIGNATURE) break;
+           SLEEP(2);
+         }
+        if (signature != DIVAS_SIGNATURE)
+         {
+#ifdef EICON_PCI_DEBUG
+           printk(KERN_ERR "eicon_pci: signature 0x%x expected 0x%x\n",signature,DIVAS_SIGNATURE);
+#endif
+           printk(KERN_ERR "eicon_pci: Timeout, protocol code not running !\n");
+           return -EIO; 
+         }
+#ifdef EICON_PCI_DEBUG
+        printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
+#endif
+
+        /* get serial number and number of channels supported by card */
+	outb(0xff, reg + M_ADDRH);
+	outw(0x3f6, reg + M_ADDR);
+        card->channels = inw(reg + M_DATA);
+        card->serial = (u32)inw(cfg + 0x22) << 16 | (u32)inw(cfg + 0x26);
+        printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
+        printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
+
+        /* test interrupt */
+        card->irqprobe = 1;
+
+        if (!card->ivalid) {
+                if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card))
+                 {
+                  printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
+                  return -EIO;
+                 }
+        }
+        card->ivalid = 1;
+
+#ifdef EICON_PCI_DEBUG
+        printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
+#endif
+        /* Trigger an interrupt and check if it is delivered */
+        outb(0x41, cfg + 0x4c);		/* enable PLX for interrupts */
+	outb(0x89, reg + M_RESET);	/* place int request */
+
+        timeout = jiffies + 20;
+        while (timeout > jiffies) {
+          if (card->irqprobe != 1) break;
+          SLEEP(5);
+         }
+        if (card->irqprobe == 1) {
+           free_irq(card->irq, card); 
+           card->ivalid = 0; 
+           printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
+           return -EIO;
+         }
+
+   /* initializing some variables */
+   ((eicon_card *)card->card)->ReadyInt = 0;
+   for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
+   for(j=0; j< (card->channels + 1); j++) {
+                ((eicon_card *)card->card)->bch[j].e.busy = 0;
+                ((eicon_card *)card->card)->bch[j].e.D3Id = 0;
+                ((eicon_card *)card->card)->bch[j].e.B2Id = 0;
+                ((eicon_card *)card->card)->bch[j].e.ref = 0;
+                ((eicon_card *)card->card)->bch[j].e.Req = 0;
+                ((eicon_card *)card->card)->bch[j].e.complete = 1;
+                ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
+   }
+
+   printk(KERN_INFO "Eicon: Card successfully started\n");
+
+ return 0;
+}
+
+
+/*
+ * Configure a card, download code into PRI card,
+ * check if we get interrupts and return 0 on succes.
+ * Return -ERRNO on failure.
+ */
+int
+eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb) {
+        eicon_pci_boot    *boot;
+	eicon_pr_ram  *prram;
+        int               i,j;
+        int               timeout;
+	int		  FeatureValue = 0;
+	unsigned int	  offset, offp=0, size, length;
+	unsigned long int signature = 0;
+	t_dsp_download_space dl_para;
+	t_dsp_download_desc  dsp_download_table;
+        eicon_pci_codebuf cbuf;
+        unsigned char     *code;
+	unsigned char	  req_int;
+    	char *ram, *reg, *cfg;	
+
+        if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf)))
+                return -EFAULT;
+
+        boot = &card->shmem->boot;
+	ram = (char *)card->PCIram;
+	reg = (char *)card->PCIreg;
+	cfg = (char *)card->PCIcfg;
+	prram = (eicon_pr_ram *)ram;
+
+	/* reset board */
+	writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET);
+	SLEEP(20);
+	writeb(0, card->PCIreg + MP_RESET);
+	SLEEP(20);
+
+	/* set command count to 0 */
+	writel(0, &boot->reserved); 
+
+	/* check if CPU increments the life word */
+        i = readw(&boot->live);
+        SLEEP(20);
+        if (i == readw(&boot->live)) {
+           printk(KERN_ERR "eicon_pci: card is reset, but CPU not running !\n");
+           return -EIO;
+         }
+#ifdef EICON_PCI_DEBUG
+	 printk(KERN_DEBUG "eicon_pci: reset card OK (CPU running)\n");
+#endif
+
+	/* download firmware : DSP and Protocol */
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: downloading firmware...\n");
+#endif
+
+       	/* Allocate code-buffer */
+       	if (!(code = kmalloc(400, GFP_KERNEL))) {
+                printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n");
+       	        return -ENOMEM;
+        }
+
+	/* prepare protocol upload */
+	dl_para.type		= DL_PARA_MEM_TYPE;
+	dl_para.dat.mem.boot	= boot;
+
+        for (j = 0; j <= cbuf.dsp_code_num; j++)
+         {
+	   if (j==0) size = cbuf.protocol_len;
+		else size = cbuf.dsp_code_len[j];	
+
+           if (j==1) writel(MP_DSP_ADDR, &boot->addr); /* DSP code entry point */
+
+		if (j == 0) dl_para.dat.io.r3addr = MP_PROTOCOL_ADDR;
+		if (j == 1) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE +
+					((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc);
+		if (j == 2) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE;
+		if (j == 3) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + sizeof(__u32);
+
+           offset = 0;
+           do  /* download block of up to 400 bytes */
+            {
+              length = ((size - offset) >= 400) ? 400 : (size - offset);
+
+        	if (copy_from_user(code, (&cb->code) + offp + offset, length)) {
+                	kfree(code);
+	                return -EFAULT;
+        	}
+
+		if ((offset == 0) && (j < 2)) {
+	           	FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); 
+#ifdef EICON_PCI_DEBUG
+	if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%x.\n", FeatureValue);
+#endif
+			if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) {
+                  		printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n");
+				kfree(code);
+		                return -EFAULT;
+			}
+                	((eicon_card *)card->card)->Feature = FeatureValue;
+		}
+
+		if (eicon_upload(&dl_para, length, code, 1))
+		{
+		  if (dl_para.dat.mem.timeout == 0)
+	                  printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr);
+			else
+			  printk(KERN_ERR "eicon_pci: timeout, no ACK to load !\n");
+		  kfree(code);
+                  return -EIO;
+		}
+
+              /* move onto next block */
+              offset += length;
+	      dl_para.dat.mem.r3addr += length;
+            } while (offset < size);
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: %d bytes loaded.\n", offset);
+#endif
+	 offp += size;
+         }
+	 kfree(code);	
+
+	/* initialize the adapter data structure */
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n");
+#endif
+        /* clear out config space */
+        for (i = 0; i < 256; i++) writeb(0, &ram[i]);
+
+        /* copy configuration down to the card */
+        writeb(cbuf.tei, &ram[8]);
+        writeb(cbuf.nt2, &ram[9]);
+        writeb(0, &ram[10]);
+        writeb(cbuf.WatchDog, &ram[11]);
+        writeb(cbuf.Permanent, &ram[12]);
+        writeb(cbuf.XInterface, &ram[13]);
+        writeb(cbuf.StableL2, &ram[14]);
+        writeb(cbuf.NoOrderCheck, &ram[15]);
+        writeb(cbuf.HandsetType, &ram[16]);
+        writeb(0, &ram[17]);
+        writeb(cbuf.LowChannel, &ram[18]);
+        writeb(cbuf.ProtVersion, &ram[19]);
+        writeb(cbuf.Crc4, &ram[20]);
+        for (i = 0; i < 32; i++)
+         {
+           writeb(cbuf.l[0].oad[i], &ram[32 + i]);
+           writeb(cbuf.l[0].osa[i], &ram[64 + i]);
+           writeb(cbuf.l[0].spid[i], &ram[96 + i]);
+           writeb(cbuf.l[1].oad[i], &ram[128 + i]);
+           writeb(cbuf.l[1].osa[i], &ram[160 + i]);
+           writeb(cbuf.l[1].spid[i], &ram[192 + i]);
+         }
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: configured card OK\n");
+#endif
+
+	/* start adapter */
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: tell card to start...\n");
+#endif
+        writel(MP_PROTOCOL_ADDR, &boot->addr); /* RISC code entry point */
+        writel(3, &boot->cmd); /* DIVAS_START_CMD */
+
+        /* wait till card ACKs */
+        timeout = jiffies + (5*HZ);
+        while (timeout > jiffies) {
+           signature = readl(&boot->signature);
+           if ((signature >> 16) == DIVAS_SIGNATURE) break;
+           SLEEP(2);
+         }
+        if ((signature >> 16) != DIVAS_SIGNATURE)
+         {
+#ifdef EICON_PCI_DEBUG
+           printk(KERN_ERR "eicon_pci: signature 0x%lx expected 0x%x\n",(signature >> 16),DIVAS_SIGNATURE);
+#endif
+           printk(KERN_ERR "eicon_pci: timeout, protocol code not running !\n");
+           return -EIO;
+         }
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n");
+#endif
+
+	/* get serial number and number of channels supported by card */
+        card->channels = readb(&ram[0x3f6]);
+        card->serial = readl(&ram[0x3f0]);
+        printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels);
+        printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial);
+
+	/* test interrupt */
+	readb(&ram[0x3fe]);
+        writeb(0, &ram[0x3fe]); /* reset any pending interrupt */
+	readb(&ram[0x3fe]);
+
+        writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]);
+        writew(0, &cfg[MP_IRQ_RESET + 2]);
+
+        card->irqprobe = 1;
+
+	if (!card->ivalid) {
+	        if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) 
+        	 {
+	          printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq);
+        	  return -EIO;
+	         }
+	}
+	card->ivalid = 1;
+
+        req_int = readb(&prram->ReadyInt);
+#ifdef EICON_PCI_DEBUG
+	printk(KERN_DEBUG "eicon_pci: testing interrupt\n");
+#endif
+        req_int++;
+        /* Trigger an interrupt and check if it is delivered */
+        writeb(req_int, &prram->ReadyInt);
+
+        timeout = jiffies + 20;
+        while (timeout > jiffies) {
+          if (card->irqprobe != 1) break;
+          SLEEP(2);
+         }
+        if (card->irqprobe == 1) {
+           free_irq(card->irq, card);
+	   card->ivalid = 0;
+           printk(KERN_ERR "eicon_pci: Getting no interrupts !\n");
+           return -EIO;
+         }
+
+   /* initializing some variables */
+   ((eicon_card *)card->card)->ReadyInt = 0;
+   for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL;
+   for(j=0; j< (card->channels + 1); j++) {
+		((eicon_card *)card->card)->bch[j].e.busy = 0;
+		((eicon_card *)card->card)->bch[j].e.D3Id = 0;
+		((eicon_card *)card->card)->bch[j].e.B2Id = 0;
+		((eicon_card *)card->card)->bch[j].e.ref = 0;
+		((eicon_card *)card->card)->bch[j].e.Req = 0;
+                ((eicon_card *)card->card)->bch[j].e.complete = 1;
+                ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL;
+   }
+
+   printk(KERN_INFO "Eicon: Card successfully started\n");
+
+ return 0;
+}
+
+#endif	/* CONFIG_PCI */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/eicon/eicon_pci.h linux.pre11.3/drivers/isdn/eicon/eicon_pci.h
--- linux.vanilla/drivers/isdn/eicon/eicon_pci.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/eicon/eicon_pci.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,188 @@
+/* $Id: eicon_pci.h,v 1.3 1999/03/29 11:19:51 armin Exp $
+ *
+ * ISDN low-level module for Eicon.Diehl active ISDN-Cards (PCI part).
+ *
+ * Copyright 1998,99 by Armin Schindler (mac@melware.de)
+ * Copyright 1999    Cytronics & Melware (info@melware.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: eicon_pci.h,v $
+ * Revision 1.3  1999/03/29 11:19:51  armin
+ * I/O stuff now in seperate file (eicon_io.c)
+ * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
+ *
+ * Revision 1.2  1999/03/02 12:37:50  armin
+ * Added some important checks.
+ * Analog Modem with DSP.
+ * Channels will be added to Link-Level after loading firmware.
+ *
+ * Revision 1.1  1999/01/01 18:09:46  armin
+ * First checkin of new eicon driver.
+ * DIVA-Server BRI/PCI and PRI/PCI are supported.
+ * Old diehl code is obsolete.
+ *
+ *
+ */
+
+#ifndef eicon_pci_h
+#define eicon_pci_h
+
+#ifdef __KERNEL__
+
+
+#define PCI_VENDOR_EICON        0x1133
+#define PCI_DIVA_PRO20          0xe001	/* Not supported */
+#define PCI_DIVA20              0xe002	/* Not supported */
+#define PCI_DIVA_PRO20_U        0xe003	/* Not supported */
+#define PCI_DIVA20_U            0xe004	/* Not supported */
+#define PCI_MAESTRA             0xe010
+#define PCI_MAESTRAQ            0xe012
+#define PCI_MAESTRAQ_U          0xe013
+#define PCI_MAESTRAP            0xe014
+
+#define DIVA_PRO20          1
+#define DIVA20              2
+#define DIVA_PRO20_U        3
+#define DIVA20_U            4
+#define MAESTRA             5
+#define MAESTRAQ            6
+#define MAESTRAQ_U          7
+#define MAESTRAP            8
+
+#define TRUE  1
+#define FALSE 0
+
+#define DIVAS_SIGNATURE 0x4447
+
+
+/* MAESTRA BRI PCI */
+
+#define M_RESET		0x10		/* offset of reset register */
+#define M_DATA		0x00		/* offset of data register */
+#define M_ADDR		0x04		/* offset of address register */
+#define M_ADDRH		0x0c		/* offset of high address register */
+
+#define M_DSP_CODE_LEN            0xbf7d0000
+#define M_DSP_CODE                0xbf7d0004  /* max 128K DSP-Code */ 
+#define M_DSP_CODE_BASE           0xbf7a0000  
+#define M_MAX_DSP_CODE_SIZE       0x00050000  /* max 320K DSP-Code (Telindus) */
+
+
+
+/* MAESTRA PRI PCI */
+
+#define MP_SHARED_RAM_OFFSET 0x1000  /* offset of shared RAM base in the DRAM memory bar */
+
+#define MP_IRQ_RESET     0xc18       /* offset of interrupt status register in the CONFIG memory bar */
+#define MP_IRQ_RESET_VAL 0xfe        /* value to clear an interrupt */
+
+#define MP_PROTOCOL_ADDR 0xa0011000  /* load address of protocol code */
+#define MP_DSP_ADDR      0xa03c0000  /* load address of DSP code */
+#define MP_MAX_PROTOCOL_CODE_SIZE  0x000a0000   /* max 640K Protocol-Code */
+#define MP_DSP_CODE_BASE           0xa03a0000
+#define MP_MAX_DSP_CODE_SIZE       0x00060000   /* max 384K DSP-Code */
+
+#define MP_RESET         0x20        /* offset of RESET register in the DEVICES memory bar */
+
+/* RESET register bits */
+#define _MP_S2M_RESET    0x10        /* active lo   */
+#define _MP_LED2         0x08        /* 1 = on      */
+#define _MP_LED1         0x04        /* 1 = on      */
+#define _MP_DSP_RESET    0x02        /* active lo   */
+#define _MP_RISC_RESET   0x81        /* active hi, bit 7 for compatibility with old boards */
+
+/* boot interface structure */
+typedef struct {
+	__u32 cmd	__attribute__ ((packed));
+	__u32 addr	__attribute__ ((packed));
+	__u32 len	__attribute__ ((packed));
+	__u32 err	__attribute__ ((packed));
+	__u32 live	__attribute__ ((packed));
+	__u32 reserved[(0x1020>>2)-6] __attribute__ ((packed));
+	__u32 signature	__attribute__ ((packed));
+	__u8 data[1];    /* real interface description */
+} eicon_pci_boot;
+
+
+#define DL_PARA_IO_TYPE   0
+#define DL_PARA_MEM_TYPE  1
+
+typedef struct tag_dsp_download_space
+{
+  __u16 type;  /* see definitions above to differ union elements */
+  union
+  {
+    struct
+    {
+      __u32               r3addr;
+      __u16               ioADDR;
+      __u16               ioADDRH;
+      __u16               ioDATA;
+      __u16               BadData;  /* in case of verify error */
+      __u16               GoodData;
+    } io;     /* for io based adapters */
+    struct
+    {
+      __u32               r3addr;
+      eicon_pci_boot	  *boot;
+      __u32               BadData;  /* in case of verify error */
+      __u32               GoodData;
+      __u16               timeout;
+    } mem;    /* for memory based adapters */
+  } dat;
+} t_dsp_download_space;
+
+
+/* Shared memory */
+typedef union {
+	eicon_pci_boot boot;
+} eicon_pci_shmem;
+
+/*
+ * card's description
+ */
+typedef struct {
+	int		  ramsize;
+	int   		  irq;	    /* IRQ		          */
+	unsigned int      PCIram;
+	unsigned int	  PCIreg;
+	unsigned int	  PCIcfg;
+	long int   	  serial;   /* Serial No.		  */
+	int		  channels; /* No. of supported channels  */
+        void*             card;
+        eicon_pci_shmem*  shmem;    /* Shared-memory area         */
+        unsigned char*    intack;   /* Int-Acknowledge            */
+        unsigned char*    stopcpu;  /* Writing here stops CPU     */
+        unsigned char*    startcpu; /* Writing here starts CPU    */
+        unsigned char     type;     /* card type                  */
+        unsigned char     irqprobe; /* Flag: IRQ-probing          */
+        unsigned char     mvalid;   /* Flag: Memory is valid      */
+        unsigned char     ivalid;   /* Flag: IRQ is valid         */
+        unsigned char     master;   /* Flag: Card is Quadro 1/4   */
+        void*             generic;  /* Ptr to generic card struct */
+} eicon_pci_card;
+
+
+
+extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb);
+extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb);
+extern void eicon_pci_release(eicon_pci_card *card);
+extern void eicon_pci_printpar(eicon_pci_card *card);
+extern int eicon_pci_find_card(char *ID);
+
+#endif  /* __KERNEL__ */
+
+#endif	/* eicon_pci_h */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/Makefile linux.pre11.3/drivers/isdn/hisax/Makefile
--- linux.vanilla/drivers/isdn/hisax/Makefile	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/hisax/Makefile	Mon Jul 19 23:59:33 1999
@@ -8,7 +8,7 @@
 O_TARGET :=
 
 O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \
-          lmgr.o q931.o callc.o fsm.o
+          lmgr.o q931.o callc.o fsm.o cert.o
 
 # EXTRA_CFLAGS += -S
 
@@ -25,12 +25,11 @@
 endif
 
 ISAC_OBJ :=
-ARCOFI_OBJ :=
 HSCX_OBJ :=
+ISAR_OBJ :=
 HFC_OBJ :=
 HFC_2BDS0 :=
-RAWHDLC_OBJ :=
-
+JADE_OBJ :=
 ifeq ($(CONFIG_HISAX_16_0),y)
 	 O_OBJS += teles0.o
 	 ISAC_OBJ := isac.o
@@ -43,17 +42,40 @@
 	 HSCX_OBJ := hscx.o
 endif
 
+ifeq ($(CONFIG_HISAX_TELESPCI),y)
+	 O_OBJS += telespci.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_S0BOX),y)
+	 O_OBJS += s0box.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
 ifeq ($(CONFIG_HISAX_AVM_A1),y)
 	 O_OBJS += avm_a1.o
 	 ISAC_OBJ := isac.o
 	 HSCX_OBJ := hscx.o
 endif
 
+ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y)
+	 O_OBJS += avm_a1p.o
+ 	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+ 
+ifeq ($(CONFIG_HISAX_FRITZPCI),y)
+	 O_OBJS += avm_pci.o
+ 	 ISAC_OBJ := isac.o
+endif
+
+
 ifeq ($(CONFIG_HISAX_ELSA),y)
 	 O_OBJS += elsa.o
 	 ISAC_OBJ := isac.o
 	 HSCX_OBJ := hscx.o
-	 ARCOFI_OBJ := arcofi.o
 endif
 
 ifeq ($(CONFIG_HISAX_IX1MICROR2),y)
@@ -84,6 +106,7 @@
 	 O_OBJS += sedlbauer.o
 	 ISAC_OBJ := isac.o
 	 HSCX_OBJ := hscx.o
+	 ISAR_OBJ := isar.o
 endif
 
 ifeq ($(CONFIG_HISAX_SPORTSTER),y)
@@ -103,15 +126,13 @@
 	 ISAC_OBJ := isac.o
 endif
 
-ifeq ($(CONFIG_HISAX_TELES3C),y)
-	 O_OBJS += teles3c.o
+ifeq ($(CONFIG_HISAX_HFCS),y)
+	 O_OBJS += hfcscard.o
 	 HFC_2BDS0 := hfc_2bds0.o
 endif
-ifeq ($(CONFIG_HISAX_AMD7930),y)
-	 RAWHDLC_OBJ := foreign.o rawhdlc.o
-endif
-ifeq ($(CONFIG_HISAX_DBRI),y)
-	 RAWHDLC_OBJ := foreign.o rawhdlc.o
+
+ifeq ($(CONFIG_HISAX_HFC_PCI),y)
+	 HFC_2BDS0 += hfc_pci.o
 endif
 
 ifeq ($(CONFIG_HISAX_NICCY),y)
@@ -120,7 +141,45 @@
 	 HSCX_OBJ := hscx.o
 endif
 
-O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(HFC_OBJ) $(ARCOFI_OBJ) $(HFC_2BDS0) $(RAWHDLC_OBJ)
+ifeq ($(CONFIG_HISAX_ISURF),y)
+	 O_OBJS += isurf.o
+	 ISAC_OBJ := isac.o
+	 ISAR_OBJ := isar.o
+endif
+
+ifeq ($(CONFIG_HISAX_HSTSAPHIR),y)
+	 O_OBJS += saphir.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_BKM_A4T),y)
+	 O_OBJS += bkm_a4t.o
+	 ISAC_OBJ := isac.o
+	 JADE_OBJ := jade.o
+endif
+ifeq ($(CONFIG_HISAX_SCT_QUADRO),y)
+	 O_OBJS += bkm_a8.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+ifeq ($(CONFIG_HISAX_GAZEL),y)
+	 O_OBJS += gazel.o
+	 ISAC_OBJ := isac.o
+	 HSCX_OBJ := hscx.o
+endif
+
+# ifeq ($(CONFIG_HISAX_TESTEMU),y)
+#	 O_OBJS += testemu.o
+# endif
+
+ifeq ($(ISAC_OBJ), isac.o)
+	ISAC_OBJ += arcofi.o
+endif
+
+O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ)
+O_OBJS += $(HFC_OBJ) $(HFC_2BDS0)
 OX_OBJS += config.o
 
 O_TARGET :=
@@ -134,4 +193,14 @@
   endif
 endif
 
+
 include $(TOPDIR)/Rules.make
+
+MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
+	    tei.c callc.c cert.c l3dss1.c l3_1tr6.c elsa.c
+
+CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+
+cert.o:	$(MD5FILES) md5sums.asc
+	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/amd7930.c linux.pre11.3/drivers/isdn/hisax/amd7930.c
--- linux.vanilla/drivers/isdn/hisax/amd7930.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/amd7930.c	Mon Jul 19 23:59:33 1999
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.2 1998/02/12 23:07:10 keil Exp $
+/* $Id: amd7930.c,v 1.3 1999/07/12 21:04:52 keil Exp $
  *
  * HiSax ISDN driver - chip specific routines for AMD 7930
  *
@@ -7,6 +7,10 @@
  *
  *
  * $Log: amd7930.c,v $
+ * Revision 1.3  1999/07/12 21:04:52  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
  * Revision 1.2  1998/02/12 23:07:10  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -105,7 +109,7 @@
 #include "rawhdlc.h"
 #include <linux/interrupt.h>
 
-static const char *amd7930_revision = "$Revision: 1.2 $";
+static const char *amd7930_revision = "$Revision: 1.3 $";
 
 #define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
 #define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
@@ -733,8 +737,6 @@
 			return(0);
 		case CARD_RELEASE:
 			release_amd7930(cs);
-			return(0);
-		case CARD_SETIRQ:
 			return(0);
 		case CARD_INIT:
 			cs->l1cmd = amd7930_l1cmd;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/arcofi.c linux.pre11.3/drivers/isdn/hisax/arcofi.c
--- linux.vanilla/drivers/isdn/hisax/arcofi.c	Sun Nov  8 15:10:14 1998
+++ linux.pre11.3/drivers/isdn/hisax/arcofi.c	Mon Jul 19 23:59:33 1999
@@ -1,12 +1,31 @@
-/* $Id: arcofi.c,v 1.1 1997/10/29 18:51:20 keil Exp $
+/* $Id: arcofi.c,v 1.7 1999/07/01 08:11:17 keil Exp $
 
- * arcofi.h   Ansteuerung ARCOFI 2165
+ * arcofi.c   Ansteuerung ARCOFI 2165
  *
  * Author     Karsten Keil (keil@temic-ech.spacenet.de)
  *
  *
  *
  * $Log: arcofi.c,v $
+ * Revision 1.7  1999/07/01 08:11:17  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.6  1998/09/30 22:21:56  keil
+ * cosmetics
+ *
+ * Revision 1.5  1998/09/27 12:52:57  keil
+ * cosmetics
+ *
+ * Revision 1.4  1998/08/20 13:50:24  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.3  1998/05/25 12:57:38  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.2  1998/04/15 16:47:16  keil
+ * new interface
+ *
  * Revision 1.1  1997/10/29 18:51:20  keil
  * New files
  *
@@ -16,35 +35,120 @@
 #include "hisax.h"
 #include "isdnl1.h"
 #include "isac.h"
+#include "arcofi.h"
 
-int
-send_arcofi(struct IsdnCardState *cs, const u_char *msg) {
+#define ARCOFI_TIMER_VALUE	20
+
+static void
+add_arcofi_timer(struct IsdnCardState *cs) {
+	if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+		del_timer(&cs->dc.isac.arcofitimer);
+	}	
+	init_timer(&cs->dc.isac.arcofitimer);
+	cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
+	add_timer(&cs->dc.isac.arcofitimer);
+}
+
+static void
+send_arcofi(struct IsdnCardState *cs) {
 	u_char val;
-	char tmp[32];
-	long flags;
-	int cnt=2;
 	
-	cs->mon_txp = 0;
-	cs->mon_txc = msg[0];
-	memcpy(cs->mon_tx, &msg[1], cs->mon_txc);
-	cs->mocr &= 0x0f;
-	cs->mocr |= 0xa0;
-	test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags);
-	cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+	add_arcofi_timer(cs);
+	cs->dc.isac.mon_txp = 0;
+	cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
+	memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc);
+	switch(cs->dc.isac.arcofi_bc) {
+		case 0: break;
+		case 1: cs->dc.isac.mon_tx[1] |= 0x40;
+			break;
+		default: break;
+	}
+	cs->dc.isac.mocr &= 0x0f;
+	cs->dc.isac.mocr |= 0xa0;
+	cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 	val = cs->readisac(cs, ISAC_MOSR);
-	cs->writeisac(cs, ISAC_MOX1, cs->mon_tx[cs->mon_txp++]);
-	cs->mocr |= 0x10;
-	cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-	save_flags(flags);
-	sti();
-	while (cnt && !test_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
-		cnt--;
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+	cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
+	cs->dc.isac.mocr |= 0x10;
+	cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+}
+
+int
+arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
+	if (cs->debug & L1_DEB_MONITOR) {
+		debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event);
 	}
-	restore_flags(flags);
-	sprintf(tmp, "arcofi tout %d", cnt);
-	debugl1(cs, tmp);
-	return(cnt);	
+	if (event == ARCOFI_TIMEOUT) {
+		cs->dc.isac.arcofi_state = ARCOFI_NOP;
+		test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags);
+		wake_up_interruptible(&cs->dc.isac.arcofi_wait);
+ 		return(1);
+	}
+	switch (cs->dc.isac.arcofi_state) {
+		case ARCOFI_NOP:
+			if (event == ARCOFI_START) {
+				cs->dc.isac.arcofi_list = data;
+				cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
+				send_arcofi(cs);
+			}
+			break;
+		case ARCOFI_TRANSMIT:
+			if (event == ARCOFI_TX_END) {
+				if (cs->dc.isac.arcofi_list->receive) {
+					add_arcofi_timer(cs);
+					cs->dc.isac.arcofi_state = ARCOFI_RECEIVE;
+				} else {
+					if (cs->dc.isac.arcofi_list->next) {
+						cs->dc.isac.arcofi_list =
+							cs->dc.isac.arcofi_list->next;
+						send_arcofi(cs);
+					} else {
+						if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+							del_timer(&cs->dc.isac.arcofitimer);
+						}
+						cs->dc.isac.arcofi_state = ARCOFI_NOP;
+						wake_up_interruptible(&cs->dc.isac.arcofi_wait);
+					}
+				}
+			}
+			break;
+		case ARCOFI_RECEIVE:
+			if (event == ARCOFI_RX_END) {
+				if (cs->dc.isac.arcofi_list->next) {
+					cs->dc.isac.arcofi_list =
+						cs->dc.isac.arcofi_list->next;
+					cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
+					send_arcofi(cs);
+				} else {
+					if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+						del_timer(&cs->dc.isac.arcofitimer);
+					}
+					cs->dc.isac.arcofi_state = ARCOFI_NOP;
+					wake_up_interruptible(&cs->dc.isac.arcofi_wait);
+				}
+			}
+			break;
+		default:
+			debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state);
+			return(2);
+	}
+	return(0);
 }
 
+static void
+arcofi_timer(struct IsdnCardState *cs) {
+	arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
+}
+
+void
+clear_arcofi(struct IsdnCardState *cs) {
+	if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
+		del_timer(&cs->dc.isac.arcofitimer);
+	}
+}
+
+void
+init_arcofi(struct IsdnCardState *cs) {
+	cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
+	cs->dc.isac.arcofitimer.data = (long) cs;
+	init_timer(&cs->dc.isac.arcofitimer);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/arcofi.h linux.pre11.3/drivers/isdn/hisax/arcofi.h
--- linux.vanilla/drivers/isdn/hisax/arcofi.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/arcofi.h	Mon Jul 19 23:59:33 1999
@@ -1,4 +1,4 @@
-/* $Id: arcofi.h,v 1.1 1997/10/29 18:51:20 keil Exp $
+/* $Id: arcofi.h,v 1.4 1999/07/01 08:11:18 keil Exp $
 
  * arcofi.h   Ansteuerung ARCOFI 2165
  *
@@ -7,6 +7,16 @@
  *
  *
  * $Log: arcofi.h,v $
+ * Revision 1.4  1999/07/01 08:11:18  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.3  1998/05/25 12:57:39  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.2  1998/04/15 16:47:17  keil
+ * new interface
+ *
  * Revision 1.1  1997/10/29 18:51:20  keil
  * New files
  *
@@ -14,4 +24,16 @@
  
 #define ARCOFI_USE	1
 
-extern int send_arcofi(struct IsdnCardState *cs, const u_char *msg);
+/* states */
+#define ARCOFI_NOP	0
+#define ARCOFI_TRANSMIT	1
+#define ARCOFI_RECEIVE	2
+/* events */
+#define ARCOFI_START	1
+#define ARCOFI_TX_END	2
+#define ARCOFI_RX_END	3
+#define ARCOFI_TIMEOUT	4
+
+extern int arcofi_fsm(struct IsdnCardState *cs, int event, void *data);
+extern void init_arcofi(struct IsdnCardState *cs);
+extern void clear_arcofi(struct IsdnCardState *cs);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/asuscom.c linux.pre11.3/drivers/isdn/hisax/asuscom.c
--- linux.vanilla/drivers/isdn/hisax/asuscom.c	Sun Nov  8 15:10:14 1998
+++ linux.pre11.3/drivers/isdn/hisax/asuscom.c	Mon Jul 19 23:59:33 1999
@@ -1,13 +1,29 @@
-/* $Id: asuscom.c,v 1.2 1998/02/02 13:27:06 keil Exp $
+/* $Id: asuscom.c,v 1.7 1999/07/12 21:04:53 keil Exp $
 
  * asuscom.c     low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
  *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author     Karsten Keil (keil@isdn4linux.de)
  *
  * Thanks to  ASUSCOM NETWORK INC. Taiwan and  Dynalink NL for informations
  *
  *
  * $Log: asuscom.c,v $
+ * Revision 1.7  1999/07/12 21:04:53  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.6  1999/07/01 08:11:18  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.5  1998/11/15 23:54:19  keil
+ * changes from 2.0
+ *
+ * Revision 1.4  1998/06/18 23:18:20  keil
+ * Support for new IPAC card
+ *
+ * Revision 1.3  1998/04/15 16:46:53  keil
+ * new init code
+ *
  * Revision 1.2  1998/02/02 13:27:06  keil
  * New
  *
@@ -17,12 +33,13 @@
 #define __NO_VERSION__
 #include "hisax.h"
 #include "isac.h"
+#include "ipac.h"
 #include "hscx.h"
 #include "isdnl1.h"
 
 extern const char *CardType[];
 
-const char *Asuscom_revision = "$Revision: 1.2 $";
+const char *Asuscom_revision = "$Revision: 1.7 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -33,6 +50,12 @@
 #define ASUS_CTRL_U7	3
 #define ASUS_CTRL_POTS	5
 
+#define ASUS_IPAC_ALE	0
+#define ASUS_IPAC_DATA	1
+
+#define ASUS_ISACHSCX	1
+#define ASUS_IPAC	2
+
 /* CARD_ADR (Write) */
 #define ASUS_RESET      0x80	/* Bit 7 Reset-Leitung */
 
@@ -107,6 +130,30 @@
 }
 
 static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80));
+}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size);
+}
+
+static u_char
 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
 	return (readreg(cs->hw.asus.adr,
@@ -141,7 +188,7 @@
 asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
@@ -149,16 +196,12 @@
 	}
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -171,16 +214,58 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0);
+}
+
+static void
+asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+
+	if (!cs) {
+		printk(KERN_WARNING "ISDNLink: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
 	}
+	if (!icnt)
+		printk(KERN_WARNING "ASUS IRQ LOOP\n");
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0);
 }
 
 void
@@ -197,14 +282,27 @@
 {
 	long flags;
 
-	byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
+	if (cs->subtyp == ASUS_IPAC)
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20);
+	else
+		byteout(cs->hw.asus.adr, ASUS_RESET);	/* Reset On */
 	save_flags(flags);
 	sti();
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
-	byteout(cs->hw.asus.adr, 0);	/* Reset Off */
+	schedule_timeout((10*HZ)/1000);
+	if (cs->subtyp == ASUS_IPAC)
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0);
+	else
+		byteout(cs->hw.asus.adr, 0);	/* Reset Off */
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
+	if (cs->subtyp == ASUS_IPAC) {
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0);
+		writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12);
+	}
 	restore_flags(flags);
 }
 
@@ -218,14 +316,9 @@
 		case CARD_RELEASE:
 			release_io_asuscom(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &asuscom_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			cs->debug |= L1_DEB_IPAC;
+			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -238,6 +331,7 @@
 {
 	int bytecnt;
 	struct IsdnCardState *cs = card->cs;
+	u_char val;
 	char tmp[64];
 
 	strcpy(tmp, Asuscom_revision);
@@ -248,12 +342,6 @@
 	bytecnt = 8;
 	cs->hw.asus.cfg_reg = card->para[1];
 	cs->irq = card->para[0];
-	cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
-	cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
-	cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
-	cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
-	cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
-
 	if (check_region((cs->hw.asus.cfg_reg), bytecnt)) {
 		printk(KERN_WARNING
 		       "HiSax: %s config port %x-%x already in use\n",
@@ -264,27 +352,47 @@
 	} else {
 		request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn");
 	}
-
-	printk(KERN_INFO
-	       "ISDNLink: defined at 0x%x IRQ %d\n",
-	       cs->hw.asus.cfg_reg,
-	       cs->irq);
-	printk(KERN_INFO "ISDNLink: resetting card\n");
-	reset_asuscom(cs);
-	cs->readisac = &ReadISAC;
-	cs->writeisac = &WriteISAC;
-	cs->readisacfifo = &ReadISACfifo;
-	cs->writeisacfifo = &WriteISACfifo;
+	printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n",
+		cs->hw.asus.cfg_reg, cs->irq);
 	cs->BC_Read_Reg = &ReadHSCX;
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Asus_card_msg;
-	ISACVersion(cs, "ISDNLink:");
-	if (HscxVersion(cs, "ISDNLink:")) {
-		printk(KERN_WARNING
-		     "ISDNLink: wrong HSCX versions check IO address\n");
-		release_io_asuscom(cs);
-		return (0);
+	val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE, 
+		cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
+	if (val == 1) {
+		cs->subtyp = ASUS_IPAC;
+		cs->hw.asus.adr  = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;
+		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		cs->readisac = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &asuscom_interrupt_ipac;
+		printk(KERN_INFO "Asus: IPAC version %x\n", val);
+	} else {
+		cs->subtyp = ASUS_ISACHSCX;
+		cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR;
+		cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC;
+		cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX;
+		cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7;
+		cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS;
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &asuscom_interrupt;
+		ISACVersion(cs, "ISDNLink:");
+		if (HscxVersion(cs, "ISDNLink:")) {
+			printk(KERN_WARNING
+		     	"ISDNLink: wrong HSCX versions check IO address\n");
+			release_io_asuscom(cs);
+			return (0);
+		}
 	}
+	printk(KERN_INFO "ISDNLink: resetting card\n");
+	reset_asuscom(cs);
 	return (1);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/avm_a1.c linux.pre11.3/drivers/isdn/hisax/avm_a1.c
--- linux.vanilla/drivers/isdn/hisax/avm_a1.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/avm_a1.c	Mon Jul 19 23:59:33 1999
@@ -1,11 +1,24 @@
-/* $Id: avm_a1.c,v 2.7 1998/02/02 13:29:37 keil Exp $
+/* $Id: avm_a1.c,v 2.11 1999/07/12 21:04:54 keil Exp $
 
  * avm_a1.c     low level stuff for AVM A1 (Fritz) isdn cards
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: avm_a1.c,v $
+ * Revision 2.11  1999/07/12 21:04:54  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.10  1998/11/15 23:54:21  keil
+ * changes from 2.0
+ *
+ * Revision 2.9  1998/08/13 23:36:12  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.8  1998/04/15 16:44:27  keil
+ * new init code
+ *
  * Revision 2.7  1998/02/02 13:29:37  keil
  * fast io
  *
@@ -57,7 +70,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *avm_revision = "$Revision: 2.7 $";
+static const char *avm_revision = "$Revision: 2.11 $";
 
 #define	 AVM_A1_STAT_ISAC	0x01
 #define	 AVM_A1_STAT_HSCX	0x02
@@ -144,8 +157,7 @@
 avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 0;
-	char tmp[32];
+	u_char val, sval;
 
 	if (!cs) {
 		printk(KERN_WARNING "AVM A1: Spurious interrupt!\n");
@@ -155,35 +167,25 @@
 		if (!(sval & AVM_A1_STAT_TIMER)) {
 			byteout(cs->hw.avm.cfg_reg, 0x1E);
 			sval = bytein(cs->hw.avm.cfg_reg);
-		} else if (cs->debug & L1_DEB_INTSTAT) {
-			sprintf(tmp, "avm IntStatus %x", sval);
-			debugl1(cs, tmp);
-		}
+		} else if (cs->debug & L1_DEB_INTSTAT)
+			debugl1(cs, "avm IntStatus %x", sval);
 		if (!(sval & AVM_A1_STAT_HSCX)) {
 			val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA);
-			if (val) {
+			if (val)
 				hscx_int_main(cs, val);
-				stat |= 1;
-			}
 		}
 		if (!(sval & AVM_A1_STAT_ISAC)) {
 			val = readreg(cs->hw.avm.isac, ISAC_ISTA);
-			if (val) {
+			if (val)
 				isac_interrupt(cs, val);
-				stat |= 2;
-			}
 		}
 	}
-	if (stat & 1) {
-		writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
-		writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
-		writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
-		writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.avm.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0);
 }
 
 inline static void
@@ -213,14 +215,11 @@
 		case CARD_RELEASE:
 			release_ioregs(cs, 0x3f);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &avm_a1_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 1);
+			byteout(cs->hw.avm.cfg_reg, 0x16);
+			byteout(cs->hw.avm.cfg_reg, 0x1E);
+			inithscxisac(cs, 2);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -348,7 +347,6 @@
 	val = bytein(cs->hw.avm.cfg_reg + 2);
 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
 	       cs->hw.avm.cfg_reg + 2, val);
-	byteout(cs->hw.avm.cfg_reg, 0x1E);
 	val = bytein(cs->hw.avm.cfg_reg);
 	printk(KERN_INFO "AVM A1: Byte at %x is %x\n",
 	       cs->hw.avm.cfg_reg, val);
@@ -373,6 +371,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_a1_interrupt;
 	ISACVersion(cs, "AVM A1:");
 	if (HscxVersion(cs, "AVM A1:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/avm_a1p.c linux.pre11.3/drivers/isdn/hisax/avm_a1p.c
--- linux.vanilla/drivers/isdn/hisax/avm_a1p.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/avm_a1p.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,321 @@
+/* $Id: avm_a1p.c,v 2.4 1999/07/12 21:04:55 keil Exp $
+ *
+ * avm_a1p.c    low level stuff for the following AVM cards:
+ *              A1 PCMCIA
+ *		FRITZ!Card PCMCIA
+ *		FRITZ!Card PCMCIA 2.0
+ *
+ * Author       Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: avm_a1p.c,v $
+ * Revision 2.4  1999/07/12 21:04:55  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.3  1998/11/15 23:54:22  keil
+ * changes from 2.0
+ *
+ * Revision 2.2  1998/08/13 23:36:13  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.1  1998/07/15 15:01:23  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 1.1.2.1  1998/07/15 14:43:26  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ *
+ */
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+/* register offsets */
+#define ADDRREG_OFFSET		0x02
+#define DATAREG_OFFSET		0x03
+#define ASL0_OFFSET		0x04
+#define ASL1_OFFSET		0x05
+#define MODREG_OFFSET		0x06
+#define VERREG_OFFSET		0x07
+
+/* address offsets */
+#define ISAC_FIFO_OFFSET	0x00
+#define ISAC_REG_OFFSET		0x20
+#define HSCX_CH_DIFF		0x40
+#define HSCX_FIFO_OFFSET	0x80
+#define HSCX_REG_OFFSET		0xa0
+
+/* read bits ASL0 */
+#define	 ASL0_R_TIMER		0x10 /* active low */
+#define	 ASL0_R_ISAC		0x20 /* active low */
+#define	 ASL0_R_HSCX		0x40 /* active low */
+#define	 ASL0_R_TESTBIT		0x80
+#define  ASL0_R_IRQPENDING	(ASL0_R_ISAC|ASL0_R_HSCX|ASL0_R_TIMER)
+
+/* write bits ASL0 */
+#define	 ASL0_W_RESET		0x01
+#define	 ASL0_W_TDISABLE	0x02
+#define	 ASL0_W_TRESET		0x04
+#define	 ASL0_W_IRQENABLE	0x08
+#define	 ASL0_W_TESTBIT		0x80
+
+/* write bits ASL1 */
+#define	 ASL1_W_LED0		0x10
+#define	 ASL1_W_LED1		0x20
+#define	 ASL1_W_ENABLE_S0	0xC0
+ 
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+static const char *avm_revision = "$Revision: 2.4 $";
+
+static inline u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	long flags;
+        u_char ret;
+
+        offset -= 0x20;
+	save_flags(flags);
+	cli();
+        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+	ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+	restore_flags(flags);
+	return ret;
+}
+
+static inline void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	long flags;
+
+        offset -= 0x20;
+
+	save_flags(flags);
+	cli();
+        byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset);
+	byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
+	restore_flags(flags);
+}
+
+static inline void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+	insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+	restore_flags(flags);
+}
+
+static inline void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET);
+	outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+	restore_flags(flags);
+}
+
+static inline u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	u_char ret;
+	long flags;
+
+        offset -= 0x20;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+	ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET);
+	restore_flags(flags);
+	return ret;
+}
+
+static inline void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	long flags;
+
+        offset -= 0x20;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset);
+	byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value);
+	restore_flags(flags);
+}
+
+static inline void
+ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
+	insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+	restore_flags(flags);
+}
+
+static inline void
+WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,
+			HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF);
+	outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size);
+	restore_flags(flags);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) 
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val, sval;
+
+	if (!cs) {
+		printk(KERN_WARNING "AVM A1 PCMCIA: Spurious interrupt!\n");
+		return;
+	}
+	while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) {
+		if (cs->debug & L1_DEB_INTSTAT)
+			debugl1(cs, "avm IntStatus %x", sval);
+		if (sval & ASL0_R_HSCX) {
+                        val = ReadHSCX(cs, 1, HSCX_ISTA);
+			if (val)
+				hscx_int_main(cs, val);
+		}
+		if (sval & ASL0_R_ISAC) {
+			val = ReadISAC(cs, ISAC_ISTA);
+			if (val)
+				isac_interrupt(cs, val);
+		}
+	}
+	WriteHSCX(cs, 0, HSCX_MASK, 0xff);
+	WriteHSCX(cs, 1, HSCX_MASK, 0xff);
+	WriteISAC(cs, ISAC_MASK, 0xff);
+	WriteISAC(cs, ISAC_MASK, 0x00);
+	WriteHSCX(cs, 0, HSCX_MASK, 0x00);
+	WriteHSCX(cs, 1, HSCX_MASK, 0x00);
+}
+
+static int
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+			HZDELAY(HZ / 5 + 1);
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
+			HZDELAY(HZ / 5 + 1);
+			byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+			return 0;
+
+		case CARD_RELEASE:
+			/* free_irq is done in HiSax_closecard(). */
+		        /* free_irq(cs->irq, cs); */
+			return 0;
+
+		case CARD_INIT:
+			clear_pending_isac_ints(cs);
+			clear_pending_hscx_ints(cs);
+			inithscxisac(cs, 1);
+			inithscxisac(cs, 2);
+			return 0;
+
+		case CARD_TEST:
+			/* we really don't need it for the PCMCIA Version */
+			return 0;
+
+		default:
+			/* all card drivers ignore others, so we do the same */
+			return 0;
+	}
+	return 0;
+}
+
+__initfunc(int
+setup_avm_a1_pcmcia(struct IsdnCard *card))
+{
+	u_char model, vers;
+	struct IsdnCardState *cs = card->cs;
+	long flags;
+	char tmp[64];
+
+
+	strcpy(tmp, avm_revision);
+	printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n",
+						 HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_A1_PCMCIA)
+		return (0);
+
+	cs->hw.avm.cfg_reg = card->para[1];
+	cs->irq = card->para[0];
+
+
+	save_flags(flags);
+	outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0);
+        sti();
+
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+	HZDELAY(HZ / 5 + 1);
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET);
+	HZDELAY(HZ / 5 + 1);
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00);
+
+	byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, ASL0_W_TDISABLE|ASL0_W_TRESET);
+
+	restore_flags(flags);
+
+	model = bytein(cs->hw.avm.cfg_reg+MODREG_OFFSET);
+	vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET);
+
+	printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n",
+				cs->hw.avm.cfg_reg, cs->irq, model, vers);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_a1p_interrupt;
+
+	ISACVersion(cs, "AVM A1 PCMCIA:");
+	if (HscxVersion(cs, "AVM A1 PCMCIA:")) {
+		printk(KERN_WARNING
+		       "AVM A1 PCMCIA: wrong HSCX versions check IO address\n");
+		return (0);
+	}
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/avm_pci.c linux.pre11.3/drivers/isdn/hisax/avm_pci.c
--- linux.vanilla/drivers/isdn/hisax/avm_pci.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/avm_pci.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,898 @@
+/* $Id: avm_pci.c,v 1.9 1999/07/12 21:04:57 keil Exp $
+
+ * avm_pci.c    low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
+ *              Thanks to AVM, Berlin for informations
+ *
+ * Author       Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: avm_pci.c,v $
+ * Revision 1.9  1999/07/12 21:04:57  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.8  1999/07/01 08:11:19  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.7  1999/02/22 18:26:30  keil
+ * Argh ! ISAC address was only set with PCI
+ *
+ * Revision 1.6  1998/11/27 19:59:28  keil
+ * set subtype for Fritz!PCI
+ *
+ * Revision 1.5  1998/11/27 12:56:45  keil
+ * forgot to update setup function name
+ *
+ * Revision 1.4  1998/11/15 23:53:19  keil
+ * Fritz!PnP; changes from 2.0
+ *
+ * Revision 1.3  1998/09/27 23:53:39  keil
+ * Fix error handling
+ *
+ * Revision 1.2  1998/09/27 12:54:55  keil
+ * bcs assign was lost in setstack, very bad results
+ *
+ * Revision 1.1  1998/08/20 13:47:30  keil
+ * first version
+ *
+ *
+ *
+ */
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "isdnl1.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+#include <linux/interrupt.h>
+
+extern const char *CardType[];
+static const char *avm_pci_rev = "$Revision: 1.9 $";
+
+#define  AVM_FRITZ_PCI		1
+#define  AVM_FRITZ_PNP		2
+
+#define  PCI_VENDOR_AVM		0x1244
+#define  PCI_FRITZPCI_ID	0xa00
+
+#define  HDLC_FIFO		0x0
+#define  HDLC_STATUS		0x4
+
+#define	 AVM_HDLC_1		0x00
+#define	 AVM_HDLC_2		0x01
+#define	 AVM_ISAC_FIFO		0x02
+#define	 AVM_ISAC_REG_LOW	0x04
+#define	 AVM_ISAC_REG_HIGH	0x06
+
+#define  AVM_STATUS0_IRQ_ISAC	0x01
+#define  AVM_STATUS0_IRQ_HDLC	0x02
+#define  AVM_STATUS0_IRQ_TIMER	0x04
+#define  AVM_STATUS0_IRQ_MASK	0x07
+
+#define  AVM_STATUS0_RESET	0x01
+#define  AVM_STATUS0_DIS_TIMER	0x02
+#define  AVM_STATUS0_RES_TIMER	0x04
+#define  AVM_STATUS0_ENA_IRQ	0x08
+#define  AVM_STATUS0_TESTBIT	0x10
+
+#define  AVM_STATUS1_INT_SEL	0x0f
+#define  AVM_STATUS1_ENA_IOM	0x80
+
+#define  HDLC_MODE_ITF_FLG	0x01
+#define  HDLC_MODE_TRANS	0x02
+#define  HDLC_MODE_CCR_7	0x04
+#define  HDLC_MODE_CCR_16	0x08
+#define  HDLC_MODE_TESTLOOP	0x80
+
+#define  HDLC_INT_XPR		0x80
+#define  HDLC_INT_XDU		0x40
+#define  HDLC_INT_RPR		0x20
+#define  HDLC_INT_MASK		0xE0
+
+#define  HDLC_STAT_RME		0x01
+#define  HDLC_STAT_RDO		0x10
+#define  HDLC_STAT_CRCVFRRAB	0x0E
+#define  HDLC_STAT_CRCVFR	0x06
+#define  HDLC_STAT_RML_MASK	0x3f00
+
+#define  HDLC_CMD_XRS		0x80
+#define  HDLC_CMD_XME		0x01
+#define  HDLC_CMD_RRS		0x20
+#define  HDLC_CMD_XML_MASK	0x3f00
+
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+	register u_char val;
+	register long flags;
+
+	save_flags(flags);
+	cli();
+	outb(idx, cs->hw.avm.cfg_reg + 4);
+	val = inb(cs->hw.avm.isac + (offset & 0xf));
+	restore_flags(flags);
+	return (val);
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
+	register long flags;
+
+	save_flags(flags);
+	cli();
+	outb(idx, cs->hw.avm.cfg_reg + 4);
+	outb(value, cs->hw.avm.isac + (offset & 0xf));
+	restore_flags(flags);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
+	insb(cs->hw.avm.isac, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
+	outsb(cs->hw.avm.isac, data, size);
+}
+
+static inline u_int
+ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset)
+{
+	register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+	register u_int val;
+	register long flags;
+
+	save_flags(flags);
+	cli();
+	outl(idx, cs->hw.avm.cfg_reg + 4);
+	val = inl(cs->hw.avm.isac + offset);
+	restore_flags(flags);
+	return (val);
+}
+
+static inline void
+WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value)
+{
+	register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+	register long flags;
+
+	save_flags(flags);
+	cli();
+	outl(idx, cs->hw.avm.cfg_reg + 4);
+	outl(value, cs->hw.avm.isac + offset);
+	restore_flags(flags);
+}
+
+static inline u_char
+ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset)
+{
+	register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+	register u_char val;
+	register long flags;
+
+	save_flags(flags);
+	cli();
+	outb(idx, cs->hw.avm.cfg_reg + 4);
+	val = inb(cs->hw.avm.isac + offset);
+	restore_flags(flags);
+	return (val);
+}
+
+static inline void
+WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
+{
+	register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
+	register long flags;
+
+	save_flags(flags);
+	cli();
+	outb(idx, cs->hw.avm.cfg_reg + 4);
+	outb(value, cs->hw.avm.isac + offset);
+	restore_flags(flags);
+}
+
+static u_char
+ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset)
+{
+	return(0xff & ReadHDLCPCI(cs, chan, offset));
+}
+
+static void
+WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
+{
+	WriteHDLCPCI(cs, chan, offset, value);
+}
+
+static inline
+struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
+{
+	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
+		return(&cs->bcs[0]);
+	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
+		return(&cs->bcs[1]);
+	else
+		return(NULL);
+}
+
+void inline
+hdlc_sched_event(struct BCState *bcs, int event)
+{
+	bcs->event |= 1 << event;
+	queue_task(&bcs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+void
+write_ctrl(struct BCState *bcs, int which) {
+
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs, "hdlc %c wr%x ctrl %x",
+			'A' + bcs->channel, which, bcs->hw.hdlc.ctrl.ctrl);
+	if (bcs->cs->subtyp == AVM_FRITZ_PCI) {
+		WriteHDLCPCI(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl.ctrl);
+	} else {
+		if (which & 4)
+			WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 2,
+				bcs->hw.hdlc.ctrl.sr.mode);
+		if (which & 2)
+			WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 1,
+				bcs->hw.hdlc.ctrl.sr.xml);
+		if (which & 1)
+			WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS,
+				bcs->hw.hdlc.ctrl.sr.cmd);
+	}
+}
+
+void
+modehdlc(struct BCState *bcs, int mode, int bc)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int hdlc = bcs->channel;
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hdlc %c mode %d ichan %d",
+			'A' + hdlc, mode, bc);
+	bcs->mode = mode;
+	bcs->channel = bc;
+	bcs->hw.hdlc.ctrl.ctrl = 0;
+	switch (mode) {
+		case (L1_MODE_NULL):
+			bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
+			bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
+			write_ctrl(bcs, 5);
+			break;
+		case (L1_MODE_TRANS):
+			bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
+			bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
+			write_ctrl(bcs, 5);
+			bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
+			write_ctrl(bcs, 1);
+			bcs->hw.hdlc.ctrl.sr.cmd = 0;
+			hdlc_sched_event(bcs, B_XMTBUFREADY);
+			break;
+		case (L1_MODE_HDLC):
+			bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
+			bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+			write_ctrl(bcs, 5);
+			bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
+			write_ctrl(bcs, 1);
+			bcs->hw.hdlc.ctrl.sr.cmd = 0;
+			hdlc_sched_event(bcs, B_XMTBUFREADY);
+			break;
+	}
+}
+
+static inline void
+hdlc_empty_fifo(struct BCState *bcs, int count)
+{
+	register u_int *ptr;
+	u_char *p;
+	u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
+	int cnt=0;
+	struct IsdnCardState *cs = bcs->cs;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hdlc_empty_fifo %d", count);
+	if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
+		return;
+	}
+	ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+	bcs->hw.hdlc.rcvidx += count;
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		outl(idx, cs->hw.avm.cfg_reg + 4);
+		while (cnt < count) {
+			*ptr++ = inl(cs->hw.avm.isac);
+			cnt += 4;
+		}
+	} else {
+		outb(idx, cs->hw.avm.cfg_reg + 4);
+		while (cnt < count) {
+			*p++ = inb(cs->hw.avm.isac);
+			cnt++;
+		}
+	}
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		if (cs->subtyp == AVM_FRITZ_PNP)
+			p = (u_char *) ptr;
+		t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
+			     bcs->channel ? 'B' : 'A', count);
+		QuickHex(t, p, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static inline void
+hdlc_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int count, cnt =0;
+	int fifo_size = 32;
+	u_char *p;
+	u_int *ptr;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hdlc_fill_fifo");
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
+	if (bcs->tx_skb->len > fifo_size) {
+		count = fifo_size;
+	} else {
+		count = bcs->tx_skb->len;
+		if (bcs->mode != L1_MODE_TRANS)
+			bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
+	}
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
+	ptr = (u_int *) p = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hdlc.count += count;
+	bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
+	write_ctrl(bcs, 3);  /* sets the correct index too */
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		while (cnt<count) {
+			outl(*ptr++, cs->hw.avm.isac);
+			cnt += 4;
+		}
+	} else {
+		while (cnt<count) {
+			outb(*p++, cs->hw.avm.isac);
+			cnt++;
+		}
+	}
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		if (cs->subtyp == AVM_FRITZ_PNP)
+			p = (u_char *) ptr;
+		t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
+			     bcs->channel ? 'B' : 'A', count);
+		QuickHex(t, p, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static void
+fill_hdlc(struct BCState *bcs)
+{
+	long flags;
+	save_flags(flags);
+	cli();
+	hdlc_fill_fifo(bcs);
+	restore_flags(flags);
+}
+
+static inline void
+HDLC_irq(struct BCState *bcs, u_int stat) {
+	int len;
+	struct sk_buff *skb;
+
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
+	if (stat & HDLC_INT_RPR) {
+		if (stat & HDLC_STAT_RDO) {
+			if (bcs->cs->debug & L1_DEB_HSCX)
+				debugl1(bcs->cs, "RDO");
+			else
+				debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
+			bcs->hw.hdlc.ctrl.sr.xml = 0;
+			bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_RRS;
+			write_ctrl(bcs, 1);
+			bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
+			write_ctrl(bcs, 1);
+			bcs->hw.hdlc.rcvidx = 0;
+		} else {
+			if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
+				len = 32;
+			hdlc_empty_fifo(bcs, len);
+			if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
+				if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
+					(bcs->mode == L1_MODE_TRANS)) {
+					if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
+						printk(KERN_WARNING "HDLC: receive out of memory\n");
+					else {
+						memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
+							bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
+						skb_queue_tail(&bcs->rqueue, skb);
+					}
+					bcs->hw.hdlc.rcvidx = 0;
+					hdlc_sched_event(bcs, B_RCVBUFREADY);
+				} else {
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs, "invalid frame");
+					else
+						debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
+					bcs->hw.hdlc.rcvidx = 0;
+				}
+			}
+		}
+	}
+	if (stat & HDLC_INT_XDU) {
+		/* Here we lost an TX interrupt, so
+		 * restart transmitting the whole frame.
+		 */
+		if (bcs->tx_skb) {
+			skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
+			bcs->tx_cnt += bcs->hw.hdlc.count;
+			bcs->hw.hdlc.count = 0;
+//			hdlc_sched_event(bcs, B_XMTBUFREADY);
+			if (bcs->cs->debug & L1_DEB_WARN)
+				debugl1(bcs->cs, "ch%d XDU", bcs->channel);
+		} else if (bcs->cs->debug & L1_DEB_WARN)
+			debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);
+		bcs->hw.hdlc.ctrl.sr.xml = 0;
+		bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
+		write_ctrl(bcs, 1);
+		bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
+		write_ctrl(bcs, 1);
+		hdlc_fill_fifo(bcs);
+	} else if (stat & HDLC_INT_XPR) {
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				hdlc_fill_fifo(bcs);
+				return;
+			} else {
+				if (bcs->st->lli.l1writewakeup &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hdlc.count);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				bcs->hw.hdlc.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hdlc.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			hdlc_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			hdlc_sched_event(bcs, B_XMTBUFREADY);
+		}
+	}
+}
+
+inline void
+HDLC_irq_main(struct IsdnCardState *cs)
+{
+	u_int stat;
+	long  flags;
+	struct BCState *bcs;
+
+	save_flags(flags);
+	cli();
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);
+	} else {
+		stat = ReadHDLCPnP(cs, 0, HDLC_STATUS);
+		if (stat & HDLC_INT_RPR)
+			stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS+1))<<8;
+	}
+	if (stat & HDLC_INT_MASK) {
+		if (!(bcs = Sel_BCS(cs, 0))) {
+			if (cs->debug)
+				debugl1(cs, "hdlc spurious channel 0 IRQ");
+		} else
+			HDLC_irq(bcs, stat);
+	}
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		stat = ReadHDLCPCI(cs, 1, HDLC_STATUS);
+	} else {
+		stat = ReadHDLCPnP(cs, 1, HDLC_STATUS);
+		if (stat & HDLC_INT_RPR)
+			stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS+1))<<8;
+	}
+	if (stat & HDLC_INT_MASK) {
+		if (!(bcs = Sel_BCS(cs, 1))) {
+			if (cs->debug)
+				debugl1(cs, "hdlc spurious channel 1 IRQ");
+		} else
+			HDLC_irq(bcs, stat);
+	}
+	restore_flags(flags);
+}
+
+void
+hdlc_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			save_flags(flags);
+			cli();
+			if (st->l1.bcs->tx_skb) {
+				skb_queue_tail(&st->l1.bcs->squeue, skb);
+				restore_flags(flags);
+			} else {
+				st->l1.bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+				st->l1.bcs->hw.hdlc.count = 0;
+				restore_flags(flags);
+				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
+				printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
+				break;
+			}
+			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			st->l1.bcs->tx_skb = skb;
+			st->l1.bcs->hw.hdlc.count = 0;
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			break;
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			modehdlc(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			modehdlc(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
+	}
+}
+
+void
+close_hdlcstate(struct BCState *bcs)
+{
+	modehdlc(bcs, 0, 0);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.hdlc.rcvbuf) {
+			kfree(bcs->hw.hdlc.rcvbuf);
+			bcs->hw.hdlc.rcvbuf = NULL;
+		}
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
+		}
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+int
+open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for hdlc.rcvbuf\n");
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hdlc.rcvbuf);
+			bcs->hw.hdlc.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.hdlc.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+int
+setstack_hdlc(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_hdlcstate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = hdlc_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+HISAX_INITFUNC(void
+clear_pending_hdlc_ints(struct IsdnCardState *cs))
+{
+	u_int val;
+
+	if (cs->subtyp == AVM_FRITZ_PCI) {
+		val = ReadHDLCPCI(cs, 0, HDLC_STATUS);
+		debugl1(cs, "HDLC 1 STA %x", val);
+		val = ReadHDLCPCI(cs, 1, HDLC_STATUS);
+		debugl1(cs, "HDLC 2 STA %x", val);
+	} else {
+		val = ReadHDLCPnP(cs, 0, HDLC_STATUS);
+		debugl1(cs, "HDLC 1 STA %x", val);
+		val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1);
+		debugl1(cs, "HDLC 1 RML %x", val);
+		val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2);
+		debugl1(cs, "HDLC 1 MODE %x", val);
+		val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3);
+		debugl1(cs, "HDLC 1 VIN %x", val);
+		val = ReadHDLCPnP(cs, 1, HDLC_STATUS);
+		debugl1(cs, "HDLC 2 STA %x", val);
+		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1);
+		debugl1(cs, "HDLC 2 RML %x", val);
+		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2);
+		debugl1(cs, "HDLC 2 MODE %x", val);
+		val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);
+		debugl1(cs, "HDLC 2 VIN %x", val);
+	}
+}
+
+HISAX_INITFUNC(void
+inithdlc(struct IsdnCardState *cs))
+{
+	cs->bcs[0].BC_SetStack = setstack_hdlc;
+	cs->bcs[1].BC_SetStack = setstack_hdlc;
+	cs->bcs[0].BC_Close = close_hdlcstate;
+	cs->bcs[1].BC_Close = close_hdlcstate;
+	modehdlc(cs->bcs, 0, 0);
+	modehdlc(cs->bcs + 1, 0, 0);
+}
+
+static void
+avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	u_char sval;
+
+	if (!cs) {
+		printk(KERN_WARNING "AVM PCI: Spurious interrupt!\n");
+		return;
+	}
+	sval = inb(cs->hw.avm.cfg_reg + 2);
+	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
+		/* possible a shared  IRQ reqest */
+		return;
+	if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
+		val = ReadISAC(cs, ISAC_ISTA);
+		isac_interrupt(cs, val);
+	}
+	if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
+		HDLC_irq_main(cs);
+	}
+	WriteISAC(cs, ISAC_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0x0);
+}
+
+static void
+reset_avmpcipnp(struct IsdnCardState *cs)
+{
+	long flags;
+
+	printk(KERN_INFO "AVM PCI/PnP: reset\n");
+	save_flags(flags);
+	sti();
+	outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
+	outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
+	printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
+}
+
+static int
+AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			reset_avmpcipnp(cs);
+			return(0);
+		case CARD_RELEASE:
+			outb(0, cs->hw.avm.cfg_reg + 2);
+			release_region(cs->hw.avm.cfg_reg, 32);
+			return(0);
+		case CARD_INIT:
+			clear_pending_isac_ints(cs);
+			initisac(cs);
+			clear_pending_hdlc_ints(cs);
+			inithdlc(cs);
+			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
+				cs->hw.avm.cfg_reg + 2);
+			WriteISAC(cs, ISAC_MASK, 0);
+			outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
+				AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
+			/* RESET Receiver and Transmitter */
+			WriteISAC(cs, ISAC_CMDR, 0x41);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *dev_avm __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
+
+__initfunc(int
+setup_avm_pcipnp(struct IsdnCard *card))
+{
+	u_int val, ver;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, avm_pci_rev);
+	printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_FRITZPCI)
+		return (0);
+	if (card->para[1]) {
+		cs->hw.avm.cfg_reg = card->para[1];
+		cs->irq = card->para[0];
+		cs->subtyp = AVM_FRITZ_PNP;
+	} else {
+#if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "FritzPCI: no PCI bus present\n");
+			return(0);
+		}
+		if ((dev_avm = pci_find_device(PCI_VENDOR_AVM,
+			PCI_FRITZPCI_ID,  dev_avm))) {
+			cs->irq = dev_avm->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "FritzPCI: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.avm.cfg_reg = dev_avm->base_address[1] &
+				PCI_BASE_ADDRESS_IO_MASK; 
+			if (!cs->hw.avm.cfg_reg) {
+				printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			cs->subtyp = AVM_FRITZ_PCI;
+		} else {
+			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+			return(0);
+		}
+#else
+		for (; pci_index < 255; pci_index++) {
+			unsigned char pci_bus, pci_device_fn;
+			unsigned int ioaddr;
+			unsigned char irq;
+
+			if (pcibios_find_device (PCI_VENDOR_AVM,
+				PCI_FRITZPCI_ID, pci_index,
+				&pci_bus, &pci_device_fn) != 0) {
+				continue;
+			}
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+				PCI_INTERRUPT_LINE, &irq);
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_1, &ioaddr);
+			cs->irq = irq;
+			cs->hw.avm.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK;
+			if (!cs->hw.avm.cfg_reg) {
+				printk(KERN_WARNING "FritzPCI: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			cs->subtyp = AVM_FRITZ_PCI;
+			break;
+		}
+		if (pci_index == 255) {
+			printk(KERN_WARNING "FritzPCI: No PCI card found\n");
+			return(0);
+		}
+		pci_index++;
+#endif /* COMPAT_HAS_NEW_PCI */
+		cs->irq_flags |= SA_SHIRQ;
+#else
+		printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n");
+		return (0);
+#endif /* CONFIG_PCI */
+	}
+	cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+	if (check_region((cs->hw.avm.cfg_reg), 32)) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.avm.cfg_reg,
+		       cs->hw.avm.cfg_reg + 31);
+		return (0);
+	} else {
+		request_region(cs->hw.avm.cfg_reg, 32,
+			(cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP");
+	}
+	switch (cs->subtyp) {
+	  case AVM_FRITZ_PCI:
+		val = inl(cs->hw.avm.cfg_reg);
+		printk(KERN_INFO "AVM PCI: stat %#x\n", val);
+		printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
+			val & 0xff, (val>>8) & 0xff);
+		cs->BC_Read_Reg = &ReadHDLC_s;
+		cs->BC_Write_Reg = &WriteHDLC_s;
+		break;
+	  case AVM_FRITZ_PNP:
+		val = inb(cs->hw.avm.cfg_reg);
+		ver = inb(cs->hw.avm.cfg_reg + 1);
+		printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
+		reset_avmpcipnp(cs);
+		cs->BC_Read_Reg = &ReadHDLCPnP;
+		cs->BC_Write_Reg = &WriteHDLCPnP;
+		break;
+	  default:
+	  	printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);
+	  	return(0);
+	}
+	printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
+		(cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
+		cs->irq, cs->hw.avm.cfg_reg);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Send_Data = &fill_hdlc;
+	cs->cardmsg = &AVM_card_msg;
+	cs->irq_func = &avm_pcipnp_interrupt;
+	ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/bkm_a4t.c linux.pre11.3/drivers/isdn/hisax/bkm_a4t.c
--- linux.vanilla/drivers/isdn/hisax/bkm_a4t.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/bkm_a4t.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,397 @@
+/* $Id: bkm_a4t.c,v 1.4 1999/07/14 11:43:14 keil Exp $
+ * bkm_a4t.c    low level stuff for T-Berkom A4T
+ *              derived from the original file sedlbauer.c
+ *              derived from the original file niccy.c
+ *              derived from the original file netjet.c
+ *
+ * Author       Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: bkm_a4t.c,v $
+ * Revision 1.4  1999/07/14 11:43:14  keil
+ * correct PCI_SUBSYSTEM_VENDOR_ID
+ *
+ * Revision 1.3  1999/07/12 21:04:58  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:53  keil
+ * Initial version
+ *
+ *
+ */
+
+#define __NO_VERSION__
+
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "jade.h"
+#include "isdnl1.h"
+#include "bkm_ax.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+
+extern const char *CardType[];
+
+const char *bkm_a4t_revision = "$Revision: 1.4 $";
+
+
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
+{
+	register u_int ret;
+	long flags;
+	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
+	save_flags(flags);
+	cli();
+	*po = (GCS_2 | PO_WRITE | off);
+	__WAITI20__(po);
+	*po = (ale | PO_READ);
+	__WAITI20__(po);
+	ret = *po;
+	restore_flags(flags);
+	return ((unsigned char) ret);
+}
+
+
+static inline void
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo read without cli because it's allready done  */
+	int i;
+	for (i = 0; i < size; i++)
+		*data++ = readreg(ale, adr, off);
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	long flags;
+	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
+	save_flags(flags);
+	cli();
+	*po = (GCS_2 | PO_WRITE | off);
+	__WAITI20__(po);
+	*po = (ale | PO_WRITE | data);
+	__WAITI20__(po);
+	restore_flags(flags);
+}
+
+
+static inline void
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo write without cli because it's allready done  */
+	int i;
+
+	for (i = 0; i < size; i++)
+		writereg(ale, adr, off, *data++);
+}
+
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size);
+}
+
+static u_char
+ReadJADE(struct IsdnCardState *cs, int jade, u_char offset)
+{
+	return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))));
+}
+
+static void
+WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value);
+}
+
+/*
+ * fast interrupt JADE stuff goes here
+ */
+
+#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\
+ 		cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)))
+#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\
+ 		cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data)
+
+#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\
+		cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
+#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\
+		cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt)
+
+#include "jade_irq.c"
+
+static void
+bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val = 0;
+	I20_REGISTER_FILE *pI20_Regs;
+
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: Telekom A4T: Spurious interrupt!\n");
+		return;
+	}
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+
+	/* ISDN interrupt pending? */
+	if (pI20_Regs->i20IntStatus & intISDN) {
+		/* Reset the ISDN interrupt     */
+		pI20_Regs->i20IntStatus = intISDN;
+		/* Disable ISDN interrupt */
+		pI20_Regs->i20IntCtrl &= ~intISDN;
+		/* Channel A first */
+		val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0x80);
+		if (val) {
+			jade_int_main(cs, val, 0);
+		}
+		/* Channel B  */
+		val = readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, jade_HDLC_ISR + 0xC0);
+		if (val) {
+			jade_int_main(cs, val, 1);
+		}
+		/* D-Channel */
+		val = readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, ISAC_ISTA);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+		/* Reenable ISDN interrupt */
+		pI20_Regs->i20IntCtrl |= intISDN;
+	}
+}
+
+void
+release_io_bkm(struct IsdnCardState *cs)
+{
+	if (cs->hw.ax.base) {
+		iounmap((void *) cs->hw.ax.base);
+		cs->hw.ax.base = 0;
+	}
+}
+
+static void
+enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
+{
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+		if (bEnable)
+			pI20_Regs->i20IntCtrl |= (intISDN | intPCI);
+		else
+			/* CAUTION: This disables the video capture driver too */
+			pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI);
+	}
+}
+
+static void
+reset_bkm(struct IsdnCardState *cs)
+{
+	long flags;
+
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+		save_flags(flags);
+		sti();
+		/* Issue the I20 soft reset     */
+		pI20_Regs->i20SysControl = 0xFF;	/* all in */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10 * HZ) / 1000);
+		/* Remove the soft reset */
+		pI20_Regs->i20SysControl = sysRESET | 0xFF;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10 * HZ) / 1000);
+		/* Set our configuration */
+		pI20_Regs->i20SysControl = sysRESET | sysCFG;
+		/* Issue ISDN reset     */
+		pI20_Regs->i20GuestControl = guestWAIT_CFG |
+		    g_A4T_JADE_RES |
+		    g_A4T_ISAR_RES |
+		    g_A4T_ISAC_RES |
+		    g_A4T_JADE_BOOTR |
+		    g_A4T_ISAR_BOOTR;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10 * HZ) / 1000);
+
+		/* Remove RESET state from ISDN */
+		pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES |
+						g_A4T_JADE_RES |
+						g_A4T_ISAR_RES);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10 * HZ) / 1000);
+		restore_flags(flags);
+	}
+}
+
+static int
+BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			/* Disable ints */
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			return (0);
+		case CARD_RELEASE:
+			/* Sanity */
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			release_io_bkm(cs);
+			return (0);
+		case CARD_INIT:
+			clear_pending_isac_ints(cs);
+			clear_pending_jade_ints(cs);
+			initisac(cs);
+			initjade(cs);
+			/* Enable ints */
+			enable_bkm_int(cs, 1);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static struct pci_dev *dev_a4t __initdata = NULL;
+#else
+static int pci_index __initdata = 0;
+#endif
+
+__initfunc(int
+	   setup_bkm_a4t(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	u_int pci_memaddr = 0, found = 0;
+	I20_REGISTER_FILE *pI20_Regs;
+#if CONFIG_PCI
+#ifndef COMPAT_HAS_NEW_PCI
+	u_char pci_bus, pci_device_fn, pci_irq = 0;
+#endif
+#endif
+
+	strcpy(tmp, bkm_a4t_revision);
+	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_BKM_A4T) {
+		cs->subtyp = BKM_A4T;
+	} else
+		return (0);
+
+#if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
+		return (0);
+	}
+	if ((dev_a4t = pci_find_device(I20_VENDOR_ID, I20_DEVICE_ID, dev_a4t))) {
+		u_int sub_sys_id = 0;
+
+		pci_read_config_dword(dev_a4t, PCI_SUBSYSTEM_VENDOR_ID,
+			&sub_sys_id);
+		if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) {
+			found = 1;
+			pci_memaddr = dev_a4t->base_address[0];
+			cs->irq = dev_a4t->irq;
+		}
+	}
+#else
+	for (; pci_index < 0xff; pci_index++) {
+		if (pcibios_find_device(I20_VENDOR_ID,
+				I20_DEVICE_ID,
+				pci_index,
+				&pci_bus,
+				&pci_device_fn) == PCIBIOS_SUCCESSFUL) {
+			u_int sub_sys_id = 0;
+
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id);
+			if (sub_sys_id == ((A4T_SUBSYS_ID << 16) | A4T_SUBVEN_ID)) {
+				found = 1;
+				pcibios_read_config_byte(pci_bus, pci_device_fn,
+					   PCI_INTERRUPT_LINE, &pci_irq);
+				cs->irq = pci_irq;
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+				       PCI_BASE_ADDRESS_0, &pci_memaddr);
+				break;
+			}
+		}
+	}
+#endif				/* COMPAT_HAS_NEW_PCI */
+	if (!found) {
+		printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]);
+		return (0);
+	}
+#ifndef COMPAT_HAS_NEW_PCI
+	pci_index++;
+#endif
+	if (!cs->irq) {		/* IRQ range check ?? */
+		printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]);
+		return (0);
+	}
+	if (!pci_memaddr) {
+		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
+		return (0);
+	}
+	pci_memaddr &= PCI_BASE_ADDRESS_MEM_MASK;
+	cs->hw.ax.base = (u_int) ioremap(pci_memaddr, 4096);
+	/* Check suspecious address */
+	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
+	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
+		printk(KERN_WARNING "HiSax: %s address %x-%x suspecious\n",
+		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
+		iounmap((void *) cs->hw.ax.base);
+		cs->hw.ax.base = 0;
+		return (0);
+	}
+	cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET;
+	cs->hw.ax.isac_ale = GCS_1;
+	cs->hw.ax.jade_ale = GCS_3;
+#else
+	printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]);
+	printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
+	return (0);
+#endif				/* CONFIG_PCI */
+	printk(KERN_INFO "HiSax: %s: Card configured at 0x%X IRQ %d\n",
+	       CardType[card->typ], cs->hw.ax.base, cs->irq);
+
+	reset_bkm(cs);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadJADE;
+	cs->BC_Write_Reg = &WriteJADE;
+	cs->BC_Send_Data = &jade_fill_fifo;
+	cs->cardmsg = &BKM_card_msg;
+	cs->irq_func = &bkm_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ISACVersion(cs, "Telekom A4T:");
+	/* Jade version */
+	JadeVersion(cs, "Telekom A4T:");
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/bkm_a8.c linux.pre11.3/drivers/isdn/hisax/bkm_a8.c
--- linux.vanilla/drivers/isdn/hisax/bkm_a8.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/bkm_a8.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,523 @@
+/* $Id: bkm_a8.c,v 1.4 1999/07/14 11:43:15 keil Exp $
+ * bkm_a8.c     low level stuff for Scitel Quadro (4*S0, passive)
+ *              derived from the original file sedlbauer.c
+ *              derived from the original file niccy.c
+ *              derived from the original file netjet.c
+ *
+ * Author       Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: bkm_a8.c,v $
+ * Revision 1.4  1999/07/14 11:43:15  keil
+ * correct PCI_SUBSYSTEM_VENDOR_ID
+ *
+ * Revision 1.3  1999/07/12 21:04:59  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:54  keil
+ * Initial version
+ *
+ *
+ */
+#define __NO_VERSION__
+
+#include "hisax.h"
+#include "isac.h"
+#include "ipac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+#include "bkm_ax.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+
+#define	ATTEMPT_PCI_REMAPPING	/* Required for PLX rev 1 */
+
+extern const char *CardType[];
+
+const char sct_quadro_revision[] = "$Revision: 1.4 $";
+
+/* To survive the startup phase */
+typedef struct {
+	u_int active;		/* true/false */
+	u_int base;		/* ipac base address */
+} IPAC_STATE;
+
+static IPAC_STATE ipac_state[4 + 1] __initdata =
+{
+	{0, 0},			/* dummy */
+	{0, 0},			/* SCT_1 */
+	{0, 0},			/* SCT_2 */
+	{0, 0},			/* SCT_3 */
+	{0, 0}			/* SCT_4 */
+};
+
+static const char *sct_quadro_subtypes[] =
+{
+	"",
+	"#1",
+	"#2",
+	"#3",
+	"#4"
+};
+
+
+#define wordout(addr,val) outw(val,addr)
+#define wordin(addr) inw(addr)
+
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
+{
+	register u_char ret;
+	long flags;
+	save_flags(flags);
+	cli();
+	wordout(ale, off);
+	ret = wordin(adr) & 0xFF;
+	restore_flags(flags);
+	return (ret);
+}
+
+static inline void
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo read without cli because it's allready done  */
+	int i;
+	wordout(ale, off);
+	for (i = 0; i < size; i++)
+		data[i] = wordin(adr) & 0xFF;
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	long flags;
+	save_flags(flags);
+	cli();
+	wordout(ale, off);
+	wordout(adr, data);
+	restore_flags(flags);
+}
+
+static inline void
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo write without cli because it's allready done  */
+	int i;
+	wordout(ale, off);
+	for (i = 0; i < size; i++)
+		wordout(adr, data[i]);
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size);
+}
+
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value);
+}
+
+/* Check whether the specified ipac is already active or not */
+static int
+is_ipac_active(u_int ipac_nr)
+{
+	return (ipac_state[ipac_nr].active);
+}
+
+/* Set the specific ipac to active */
+static void
+set_ipac_active(u_int ipac_nr, u_int active)
+{
+	/* set activation state */
+	ipac_state[ipac_nr].active = active;
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \
+	cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+	int i;
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: Scitel Quadro: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
+
+      Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val) {
+			hscx_int_main(cs, val);
+		}
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n",
+		       CardType[cs->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF);
+	writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0);
+
+	/* Read out all interrupt sources from currently not active ipacs */
+	/* "Handle" all interrupts from currently not active ipac by reading the regs */
+	for (i = SCT_1; i <= SCT_4; i++)
+		if (!is_ipac_active(i)) {
+			u_int base = ipac_state[i].base;
+			if (readreg(base, base + 4, 0xC1)) {
+				readreg(base, base + 4, 0xA0);
+				readreg(base, base + 4, 0xA4);
+				readreg(base, base + 4, 0x20);
+				readreg(base, base + 4, 0x24);
+				readreg(base, base + 4, 0x60);
+				readreg(base, base + 4, 0x64);
+				readreg(base, base + 4, 0xC1);
+				readreg(base, base + 4, ISAC_CIR0 + 0x80);
+			}
+		}
+}
+
+
+void
+release_io_sct_quadro(struct IsdnCardState *cs)
+{
+	/* ?? */
+}
+
+static void
+enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable)
+{
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		if (bEnable)
+			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41));
+		else
+			/* Issue general di only if no ipac is active */
+			if (!is_ipac_active(SCT_1) &&
+			    !is_ipac_active(SCT_2) &&
+			    !is_ipac_active(SCT_3) &&
+			    !is_ipac_active(SCT_4))
+			wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41));
+	}
+}
+
+static void
+reset_bkm(struct IsdnCardState *cs)
+{
+	long flags;
+
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		if (!is_ipac_active(SCT_1) &&
+		    !is_ipac_active(SCT_2) &&
+		    !is_ipac_active(SCT_3) &&
+		    !is_ipac_active(SCT_4)) {
+			/* Issue total reset only if no ipac is active */
+			wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4));
+
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((10 * HZ) / 1000);
+
+			/* Remove the soft reset */
+			wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4));
+
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((10 * HZ) / 1000);
+			restore_flags(flags);
+		}
+	}
+}
+
+static int
+BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			/* Disable ints */
+			set_ipac_active(cs->subtyp, 0);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			return (0);
+		case CARD_RELEASE:
+			/* Sanity */
+			set_ipac_active(cs->subtyp, 0);
+			enable_bkm_int(cs, 0);
+			reset_bkm(cs);
+			release_io_sct_quadro(cs);
+			return (0);
+		case CARD_INIT:
+			cs->debug |= L1_DEB_IPAC;
+			set_ipac_active(cs->subtyp, 1);
+			inithscxisac(cs, 3);
+			/* Enable ints */
+			enable_bkm_int(cs, 1);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static struct pci_dev *dev_a8 __initdata = NULL;
+#else
+static int pci_index __initdata = 0;
+#endif
+
+__initfunc(int
+	   setup_sct_quadro(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+#if CONFIG_PCI
+	u_char pci_bus = 0, pci_device_fn = 0, pci_irq = 0, pci_rev_id;
+	u_int found = 0;
+	u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5;
+#endif
+
+	strcpy(tmp, sct_quadro_revision);
+	printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ == ISDN_CTYPE_SCT_QUADRO) {
+		cs->subtyp = SCT_1;	/* Preset */
+	} else
+		return (0);
+
+	/* Identify subtype by para[0] */
+	if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4)
+		cs->subtyp = card->para[0];
+	else
+		printk(KERN_WARNING "HiSax: %s: Invalid subcontroller in configuration, default to 1\n",
+		       CardType[card->typ]);
+#if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "bkm_a4t: no PCI bus present\n");
+		return (0);
+	}
+	if ((dev_a8 = pci_find_device(PLX_VENDOR_ID, PLX_DEVICE_ID, dev_a8))) {
+		u_int sub_sys_id = 0;
+
+		pci_read_config_dword(dev_a8, PCI_SUBSYSTEM_VENDOR_ID,
+			&sub_sys_id);
+		if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) {
+			found = 1;
+			pci_ioaddr1 = dev_a8->base_address[1];
+			pci_irq = dev_a8->irq;
+			pci_bus = dev_a8->bus->number;
+			pci_device_fn = dev_a8->devfn;
+		}
+	}
+#else
+	for (; pci_index < 0xff; pci_index++) {
+		if (pcibios_find_device(
+				PLX_VENDOR_ID,
+				PLX_DEVICE_ID,
+				pci_index,
+				&pci_bus,
+				&pci_device_fn) == PCIBIOS_SUCCESSFUL) {
+			
+			u_int sub_sys_id = 0;
+
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_SUBSYSTEM_VENDOR_ID, &sub_sys_id);
+			if (sub_sys_id == ((SCT_SUBSYS_ID << 16) | SCT_SUBVEN_ID)) {
+				found = 1;
+				pcibios_read_config_byte(pci_bus, pci_device_fn,
+					PCI_INTERRUPT_LINE, &pci_irq);
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_1, &pci_ioaddr1);
+				cs->irq = pci_irq;
+				break;
+			}
+		}
+	}
+#endif /* COMPAT_HAS_NEW_PCI */
+	if (!found) {
+		printk(KERN_WARNING "HiSax: %s (%s): Card not found\n",
+		       CardType[card->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+		return (0);
+	}
+#ifndef COMPAT_HAS_NEW_PCI
+	pci_index++; /* need for more as one card */
+#endif
+	if (!pci_irq) {		/* IRQ range check ?? */
+		printk(KERN_WARNING "HiSax: %s (%s): No IRQ\n",
+		       CardType[card->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+		return (0);
+	}
+#ifdef ATTEMPT_PCI_REMAPPING
+/* HACK: PLX revision 1 bug: PLX address bit 7 must not be set */
+	pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_REVISION_ID, &pci_rev_id);
+	if ((pci_ioaddr1 & 0x80) && (pci_rev_id == 1)) {
+		printk(KERN_WARNING "HiSax: %s (%s): PLX rev 1, remapping required!\n",
+			CardType[card->typ],
+			sct_quadro_subtypes[cs->subtyp]);
+		/* Restart PCI negotiation */
+		pcibios_write_config_dword(pci_bus, pci_device_fn,
+			PCI_BASE_ADDRESS_1, (u_int) - 1);
+		/* Move up by 0x80 byte */
+		pci_ioaddr1 += 0x80;
+		pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
+		pcibios_write_config_dword(pci_bus, pci_device_fn,
+			PCI_BASE_ADDRESS_1, pci_ioaddr1);
+#ifdef COMPAT_HAS_NEW_PCI
+		dev_a8->base_address[1] = pci_ioaddr1;
+#endif /* COMPAT_HAS_NEW_PCI */
+	}
+/* End HACK */
+#endif
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &pci_ioaddr1);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &pci_ioaddr2);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_3, &pci_ioaddr3);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_4, &pci_ioaddr4);
+	pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_5, &pci_ioaddr5);
+	if (!pci_ioaddr1 || !pci_ioaddr2 || !pci_ioaddr3 || !pci_ioaddr4 || !pci_ioaddr5) {
+		printk(KERN_WARNING "HiSax: %s (%s): No IO base address(es)\n",
+		       CardType[card->typ],
+		       sct_quadro_subtypes[cs->subtyp]);
+		return (0);
+	}
+	pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr2 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr3 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr4 &= PCI_BASE_ADDRESS_IO_MASK;
+	pci_ioaddr5 &= PCI_BASE_ADDRESS_IO_MASK;
+	/* Take over */
+	cs->irq = pci_irq;
+	cs->irq_flags |= SA_SHIRQ;
+	/* pci_ioaddr1 is unique to all subdevices */
+	/* pci_ioaddr2 is for the fourth subdevice only */
+	/* pci_ioaddr3 is for the third subdevice only */
+	/* pci_ioaddr4 is for the second subdevice only */
+	/* pci_ioaddr5 is for the first subdevice only */
+	cs->hw.ax.plx_adr = pci_ioaddr1;
+	/* Enter all ipac_base addresses */
+	ipac_state[SCT_1].base = pci_ioaddr5 + 0x00;
+	ipac_state[SCT_2].base = pci_ioaddr4 + 0x08;
+	ipac_state[SCT_3].base = pci_ioaddr3 + 0x10;
+	ipac_state[SCT_4].base = pci_ioaddr2 + 0x20;
+	/* For isac and hscx control path */
+	cs->hw.ax.base = ipac_state[cs->subtyp].base;
+	/* For isac and hscx data path */
+	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
+#else
+	printk(KERN_WARNING "HiSax: %s (%s): NO_PCI_BIOS\n",
+	       CardType[card->typ],
+	       sct_quadro_subtypes[cs->subtyp]);
+	printk(KERN_WARNING "HiSax: %s (%s): Unable to configure\n",
+	       CardType[card->typ],
+	       sct_quadro_subtypes[cs->subtyp]);
+	return (0);
+#endif				/* CONFIG_PCI */
+	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4X, 0x%.4X, 0x%.4X and IRQ %d\n",
+	       CardType[card->typ],
+	       sct_quadro_subtypes[cs->subtyp],
+	       cs->hw.ax.plx_adr,
+	       cs->hw.ax.base,
+	       cs->hw.ax.data_adr,
+	       cs->irq);
+
+	test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+
+	/* Disable all currently not active ipacs */
+	if (!is_ipac_active(SCT_1))
+		set_ipac_active(SCT_1, 0);
+	if (!is_ipac_active(SCT_2))
+		set_ipac_active(SCT_2, 0);
+	if (!is_ipac_active(SCT_3))
+		set_ipac_active(SCT_3, 0);
+	if (!is_ipac_active(SCT_4))
+		set_ipac_active(SCT_4, 0);
+
+	/* Perfom general reset (if possible) */
+	reset_bkm(cs);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &BKM_card_msg;
+	cs->irq_func = &bkm_interrupt_ipac;
+
+	printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n",
+		CardType[card->typ],
+		sct_quadro_subtypes[cs->subtyp],
+		readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID));
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/bkm_ax.h linux.pre11.3/drivers/isdn/hisax/bkm_ax.h
--- linux.vanilla/drivers/isdn/hisax/bkm_ax.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/bkm_ax.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,133 @@
+/* $Id: bkm_ax.h,v 1.2 1999/07/01 08:07:55 keil Exp $
+ * bkm_ax.h   low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive)
+ *
+ * Author     Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: bkm_ax.h,v $
+ * Revision 1.2  1999/07/01 08:07:55  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+#ifndef	__BKM_AX_H__
+#define	__BKM_AX_H__
+
+/* Supported boards	(subtypes) */
+#define SCT_1		1
+#define	SCT_2		2
+#define	SCT_3		3
+#define	SCT_4		4
+#define BKM_A4T		5
+
+
+/* A4T																*/
+#define I20_DEVICE_ID       	0x6120  /* I20 PCI device ID */
+#define I20_VENDOR_ID       	0x11DE  /* I20 PCI vendor ID */
+#define	A4T_SUBVEN_ID		0x0871	
+#define	A4T_SUBSYS_ID		0xFFA4
+/* Scitel Quadro 																*/
+#define	PLX_DEVICE_ID		0x9050	/* Scitel Quadro PLX */
+#define	PLX_VENDOR_ID		0x10B5
+#define	SCT_SUBVEN_ID		0x0871
+#define	SCT_SUBSYS_ID		0xFFA8
+
+
+#define	PLX_ADDR_PLX		0x14	/* Addr PLX configuration */
+#define	PLX_ADDR_ISAC		0x18	/* Addr ISAC */
+#define	PLX_ADDR_HSCX		0x1C	/* Addr HSCX */
+#define	PLX_ADDR_ALE		0x20	/* Addr ALE */
+#define	PLX_ADDR_ALEPLUS	0x24	/* Next Addr behind ALE */
+
+#define	PLX_SUBVEN		0x2C	/* Offset SubVendor */
+#define	PLX_SUBSYS		0x2E	/* Offset SubSystem */
+
+
+/* Application specific registers I20 (Siemens SZB6120H) */
+typedef	struct {
+		/* Video front end horizontal configuration register */
+	volatile u_int	i20VFEHorzCfg;	/* Offset 00 */
+		/* Video front end vertical configuration register */
+	volatile u_int	i20VFEVertCfg;	/* Offset 04 */	
+		/* Video front end scaler and pixel format register */
+	volatile u_int	i20VFEScaler;	/* Offset 08 */	
+		/* Video display top register */
+	volatile u_int	i20VDispTop;   	/* Offset 0C */	
+		/* Video display bottom register */
+	volatile u_int	i20VDispBottom;	/* Offset 10 */	
+		/* Video stride, status and frame grab register */
+	volatile u_int	i20VidFrameGrab;/* Offset 14 */	
+		/* Video display configuration register */
+	volatile u_int	i20VDispCfg;	/* Offset 18 */	
+		/* Video masking map top */
+	volatile u_int	i20VMaskTop;	/* Offset 1C */	
+		/* Video masking map bottom */
+	volatile u_int	i20VMaskBottom;	/* Offset 20 */	
+		/* Overlay control register */
+	volatile u_int 	i20OvlyControl;	/* Offset 24 */	
+		/* System, PCI and general purpose pins control register */
+ 	volatile u_int	i20SysControl; 	/* Offset 28 */	
+#define	sysRESET		0x01000000	/* bit 24:Softreset (Low)		*/
+			/* GPIO 4...0: Output fixed for our cfg! */
+#define	sysCFG			0x000000E0	/* GPIO 7,6,5: Input */
+	/* General purpose pins and guest bus control register */
+ 	volatile u_int	i20GuestControl;/* Offset 2C */	
+#define	guestWAIT_CFG	0x00005555	/* 4 PCI waits for all */
+#define	guestISDN_INT_E	0x01000000	/* ISDN Int en (low) */
+#define	guestVID_INT_E 	0x02000000	/* Video interrupt en (low) */
+#define	guestADI1_INT_R	0x04000000	/* ADI #1 int req (low) */
+#define	guestADI2_INT_R	0x08000000	/* ADI #2 int req (low) */
+#define	guestISDN_RES	0x10000000	/* ISDN reset bit (high) */
+#define	guestADI1_INT_S	0x20000000	/* ADI #1 int pending (low) */
+#define	guestADI2_INT_S	0x40000000	/* ADI #2 int pending (low) */
+#define	guestISDN_INT_S	0x80000000	/* ISAC int pending (low) */
+
+#define	g_A4T_JADE_RES	0x01000000	/* JADE Reset (High) */
+#define	g_A4T_ISAR_RES	0x02000000	/* ISAR Reset (High) */
+#define	g_A4T_ISAC_RES	0x04000000	/* ISAC Reset (High) */
+#define	g_A4T_JADE_BOOTR 0x08000000	/* JADE enable boot SRAM (Low) NOT USED */
+#define	g_A4T_ISAR_BOOTR 0x10000000	/* ISAR enable boot SRAM (Low) NOT USED */
+#define	g_A4T_JADE_INT_S 0x20000000	/* JADE interrupt pnd (Low) */
+#define	g_A4T_ISAR_INT_S 0x40000000	/* ISAR interrupt pnd (Low) */
+#define	g_A4T_ISAC_INT_S 0x80000000	/* ISAC interrupt pnd (Low) */
+
+ 	volatile u_int	i20CodeSource;	/* Offset 30 */	
+ 	volatile u_int	i20CodeXferCtrl;/* Offset 34 */	
+ 	volatile u_int	i20CodeMemPtr;	/* Offset 38 */	
+
+  	volatile u_int	i20IntStatus;	/* Offset 3C */	
+ 	volatile u_int	i20IntCtrl;	/* Offset 40 */	
+#define	intISDN		0x40000000	/* GIRQ1En (ISAC/ADI) (High) */
+#define	intVID		0x20000000	/* GIRQ0En (VSYNC)    (High) */
+#define	intCOD		0x10000000	/* CodRepIrqEn        (High) */
+#define	intPCI 		0x01000000	/* PCI IntA enable    (High) */
+
+ 	volatile u_int	i20I2CCtrl;	/* Offset 44					*/	
+} I20_REGISTER_FILE, *PI20_REGISTER_FILE;
+
+/*
+ * Postoffice structure for A4T
+ *
+ */
+#define	PO_OFFSET	0x00000200	/* Postoffice offset from base */
+
+#define	GCS_0		0x00000000 	/* Guest bus chip selects */
+#define	GCS_1		0x00100000
+#define	GCS_2		0x00200000
+#define	GCS_3		0x00300000
+
+#define	PO_READ		0x00000000	/* R/W from/to guest bus */
+#define	PO_WRITE	0x00800000
+
+#define	PO_PEND		0x02000000
+
+#define POSTOFFICE(postoffice) *(volatile unsigned int*)(postoffice)
+
+/* Wait unlimited (don't worry)										*/ 
+#define	__WAITI20__(postoffice)										\
+do {		   	 		   											\
+  	while ((POSTOFFICE(postoffice) & PO_PEND)) ;					\
+} while (0)
+
+#endif	/* __BKM_AX_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/callc.c linux.pre11.3/drivers/isdn/hisax/callc.c
--- linux.vanilla/drivers/isdn/hisax/callc.c	Mon Dec 28 23:09:42 1998
+++ linux.pre11.3/drivers/isdn/hisax/callc.c	Mon Jul 19 23:59:33 1999
@@ -1,12 +1,74 @@
-/* $Id: callc.c,v 2.13 1998/02/12 23:07:16 keil Exp $
+/* $Id: callc.c,v 2.29 1999/07/13 21:05:41 werner Exp $
 
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
  * Thanks to    Jan den Ouden
  *              Fritz Elfert
  *
  * $Log: callc.c,v $
+ * Revision 2.29  1999/07/13 21:05:41  werner
+ * Modified set_channel_limit to use new callback ISDN_STAT_DISCH.
+ *
+ * Revision 2.28  1999/07/09 08:30:02  keil
+ * cosmetics
+ *
+ * Revision 2.27  1999/07/05 23:51:38  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 2.26  1999/07/01 08:11:21  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.25  1999/01/02 11:17:20  keil
+ * Changes for 2.2
+ *
+ * Revision 2.24  1998/11/15 23:54:24  keil
+ * changes from 2.0
+ *
+ * Revision 2.23  1998/09/30 22:21:57  keil
+ * cosmetics
+ *
+ * Revision 2.22  1998/08/20 13:50:29  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.21  1998/08/13 23:36:15  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.20  1998/06/26 15:13:05  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 2.19  1998/05/25 14:08:06  keil
+ * HiSax 3.0
+ * fixed X.75 and leased line to work again
+ * Point2Point and fixed TEI are runtime options now:
+ *    hisaxctrl <id> 7 1  set PTP
+ *    hisaxctrl <id> 8 <TEIVALUE *2 >
+ *    set fixed TEI to TEIVALUE (0-63)
+ *
+ * Revision 2.18  1998/05/25 12:57:40  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.17  1998/04/15 16:46:06  keil
+ * RESUME support
+ *
+ * Revision 2.16  1998/04/10 10:35:17  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.15  1998/03/19 13:18:37  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 2.14  1998/03/07 22:56:54  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 2.13  1998/02/12 23:07:16  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -60,12 +122,18 @@
 
 #define __NO_VERSION__
 #include "hisax.h"
+#include "../avmb1/capicmd.h"  /* this should be moved in a common place */
 
 #ifdef MODULE
+#ifdef COMPAT_HAS_NEW_SYMTAB
 #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
-#endif				/* MODULE */
+#else
+extern long mod_use_count_;
+#define MOD_USE_COUNT mod_use_count_
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif	/* MODULE */
 
-const char *lli_revision = "$Revision: 2.13 $";
+const char *lli_revision = "$Revision: 2.29 $";
 
 extern struct IsdnCard cards[];
 extern int nrcards;
@@ -77,20 +145,18 @@
 
 static struct Fsm callcfsm =
 {NULL, 0, 0, NULL, NULL};
-static struct Fsm lcfsm =
-{NULL, 0, 0, NULL, NULL};
 
 static int chancount = 0;
 
-/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */ 
-#define ALERT_REJECT 1
+/* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
+#define ALERT_REJECT 0
 
 /* Value to delay the sending of the first B-channel paket after CONNECT
  * here is no value given by ITU, but experience shows that 300 ms will
  * work on many networks, if you or your other side is behind local exchanges
  * a greater value may be recommented. If the delay is to short the first paket
  * will be lost and autodetect on many comercial routers goes wrong !
- * You can adjust this value on runtime with 
+ * You can adjust this value on runtime with
  * hisaxctrl <id> 2 <value>
  * value is in milliseconds
  */
@@ -98,27 +164,7 @@
 
 /* Flags for remembering action done in lli */
 
-#define  FLG_START_D	0
-#define  FLG_ESTAB_D	1
-#define  FLG_CALL_SEND	2
-#define  FLG_CALL_REC   3
-#define  FLG_CALL_ALERT	4
-#define  FLG_START_B	5
-#define  FLG_CONNECT_B	6
-#define  FLG_LL_DCONN	7
-#define  FLG_LL_BCONN	8
-#define  FLG_DISC_SEND	9
-#define  FLG_DISC_REC	10
-#define  FLG_REL_REC	11
-#define  FLG_DO_ALERT	12
-#define  FLG_DO_HANGUP	13
-#define  FLG_DO_CONNECT	14
-#define  FLG_DO_ESTAB	15
-
-/*
- * Because of callback it's a good idea to delay the shutdown of the d-channel
- */
-#define	DREL_TIMER_VALUE 10000
+#define  FLG_START_B	0
 
 /*
  * Find card with given driverId
@@ -136,55 +182,66 @@
 	return (struct IsdnCardState *) 0;
 }
 
-static void
-link_debug(struct Channel *chanp, char *s, int direction)
+int
+discard_queue(struct sk_buff_head *q)
 {
-	char tmp[100], tm[32];
+	struct sk_buff *skb;
+	int ret=0;
 
-	jiftime(tm, jiffies);
-	sprintf(tmp, "%s Channel %d %s %s\n", tm, chanp->chan,
-		direction ? "LL->HL" : "HL->LL", s);
-	HiSax_putstatus(chanp->cs, tmp);
+	while ((skb = skb_dequeue(q))) {
+		idev_kfree_skb(skb, FREE_READ);
+		ret++;
+	}
+	return(ret);
 }
 
+static void
+link_debug(struct Channel *chanp, int direction, char *fmt, ...)
+{
+	va_list args;
+	char tmp[16];
+
+	va_start(args, fmt);
+	sprintf(tmp, "Ch%d %s ", chanp->chan,
+		direction ? "LL->HL" : "HL->LL");
+	VHiSax_putstatus(chanp->cs, tmp, fmt, args);
+	va_end(args);
+}
 
 enum {
-	ST_NULL,		/*  0 inactive */
-	ST_OUT_WAIT_D,		/*  1 outgoing, awaiting d-channel establishment */
-	ST_IN_WAIT_D,		/*  2 incoming, awaiting d-channel establishment */
-	ST_OUT_DIAL,		/*  3 outgoing, SETUP send; awaiting confirm */
-	ST_IN_WAIT_LL,		/*  4 incoming call received; wait for LL confirm */
-	ST_IN_ALERT_SEND,	/*  5 incoming call received; ALERT send */
-	ST_IN_WAIT_CONN_ACK,	/*  6 incoming CONNECT send; awaiting CONN_ACK */
-	ST_WAIT_BCONN,		/*  7 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */
-	ST_ACTIVE,		/*  8 active, b channel prot. established */
-	ST_WAIT_BRELEASE,	/*  9 call clear. (initiator), awaiting b channel prot. rel. */
-	ST_WAIT_BREL_DISC,	/* 10 call clear. (receiver), DISCONNECT req. received */
-	ST_WAIT_DCOMMAND,	/* 11 call clear. (receiver), awaiting DCHANNEL message */
-	ST_WAIT_DRELEASE,	/* 12 DISCONNECT sent, awaiting RELEASE */
-	ST_WAIT_D_REL_CNF,	/* 13 RELEASE sent, awaiting RELEASE confirm */
-	ST_WAIT_DSHUTDOWN,	/*  14 awaiting d-channel shutdown */
+        ST_NULL,                /*  0 inactive */
+        ST_OUT_DIAL,            /*  1 outgoing, SETUP send; awaiting confirm */
+        ST_IN_WAIT_LL,          /*  2 incoming call received; wait for LL confirm */
+        ST_IN_ALERT_SENT,       /*  3 incoming call received; ALERT send */
+        ST_IN_WAIT_CONN_ACK,    /*  4 incoming CONNECT send; awaiting CONN_ACK */
+        ST_WAIT_BCONN,          /*  5 CONNECT/CONN_ACK received, awaiting b-channel prot. estbl. */
+        ST_ACTIVE,              /*  6 active, b channel prot. established */
+        ST_WAIT_BRELEASE,       /*  7 call clear. (initiator), awaiting b channel prot. rel. */
+        ST_WAIT_BREL_DISC,      /*  8 call clear. (receiver), DISCONNECT req. received */
+        ST_WAIT_DCOMMAND,       /*  9 call clear. (receiver), awaiting DCHANNEL message */
+        ST_WAIT_DRELEASE,       /* 10 DISCONNECT sent, awaiting RELEASE */
+        ST_WAIT_D_REL_CNF,      /* 11 RELEASE sent, awaiting RELEASE confirm */
+        ST_IN_PROCEED_SEND,     /* 12 incoming call, proceeding send */ 
 };
+  
 
-#define STATE_COUNT (ST_WAIT_DSHUTDOWN +1)
+#define STATE_COUNT (ST_IN_PROCEED_SEND + 1)
 
-static char *strState[] =
-{
-	"ST_NULL",
-	"ST_OUT_WAIT_D",
-	"ST_IN_WAIT_D",
-	"ST_OUT_DIAL",
-	"ST_IN_WAIT_LL",
-	"ST_IN_ALERT_SEND",
-	"ST_IN_WAIT_CONN_ACK",
-	"ST_WAIT_BCONN",
-	"ST_ACTIVE",
+  static char *strState[] =
+  {
+        "ST_NULL",
+        "ST_OUT_DIAL",
+        "ST_IN_WAIT_LL",
+        "ST_IN_ALERT_SENT",
+        "ST_IN_WAIT_CONN_ACK",
+        "ST_WAIT_BCONN",
+        "ST_ACTIVE",
 	"ST_WAIT_BRELEASE",
 	"ST_WAIT_BREL_DISC",
 	"ST_WAIT_DCOMMAND",
 	"ST_WAIT_DRELEASE",
 	"ST_WAIT_D_REL_CNF",
-	"ST_WAIT_DSHUTDOWN",
+        "ST_IN_PROCEED_SEND",
 };
 
 enum {
@@ -192,29 +249,28 @@
 	EV_SETUP_CNF,		/*  1 */
 	EV_ACCEPTB,		/*  2 */
 	EV_DISCONNECT_IND,	/*  3 */
-	EV_RELEASE_CNF,		/*  4 */
-	EV_DLEST,		/*  5 */
-	EV_DLRL,		/*  6 */
+	EV_RELEASE, 		/*  4 */
+	EV_LEASED,		/*  5 */
+	EV_LEASED_REL,		/*  6 */
 	EV_SETUP_IND,		/*  7 */
-	EV_RELEASE_IND,		/*  8 */
-	EV_ACCEPTD,		/*  9 */
-	EV_SETUP_CMPL_IND,	/* 10 */
-	EV_BC_EST,		/* 11 */
-	EV_WRITEBUF,		/* 12 */
-	EV_ESTABLISH,		/* 13 */
-	EV_HANGUP,		/* 14 */
-	EV_BC_REL,		/* 15 */
-	EV_CINF,		/* 16 */
-	EV_SUSPEND,		/* 17 */
-	EV_RESUME,		/* 18 */
-	EV_SHUTDOWN_D,		/* 19 */
-	EV_NOSETUP_RSP,		/* 20 */
-	EV_SETUP_ERR,		/* 21 */
-	EV_CONNECT_ERR,		/* 22 */
-	EV_RELEASE_ERR,		/* 23 */
+	EV_ACCEPTD,		/*  8 */
+	EV_SETUP_CMPL_IND,	/*  9 */
+	EV_BC_EST,		/* 10 */
+	EV_WRITEBUF,		/* 11 */
+	EV_HANGUP,		/* 12 */
+	EV_BC_REL,		/* 13 */
+	EV_CINF,		/* 14 */
+	EV_SUSPEND,		/* 15 */
+	EV_RESUME,		/* 16 */
+	EV_NOSETUP_RSP,		/* 17 */
+	EV_SETUP_ERR,		/* 18 */
+	EV_CONNECT_ERR,		/* 19 */
+	EV_PROCEED,		/* 20 */
+	EV_ALERT,		/* 21 */ 
+	EV_REDIR,		/* 22 */ 
 };
 
-#define EVENT_COUNT (EV_RELEASE_ERR +1)
+#define EVENT_COUNT (EV_REDIR + 1)
 
 static char *strEvent[] =
 {
@@ -222,83 +278,45 @@
 	"EV_SETUP_CNF",
 	"EV_ACCEPTB",
 	"EV_DISCONNECT_IND",
-	"EV_RELEASE_CNF",
-	"EV_DLEST",
-	"EV_DLRL",
+	"EV_RELEASE",
+	"EV_LEASED",
+	"EV_LEASED_REL",
 	"EV_SETUP_IND",
-	"EV_RELEASE_IND",
 	"EV_ACCEPTD",
 	"EV_SETUP_CMPL_IND",
 	"EV_BC_EST",
 	"EV_WRITEBUF",
-	"EV_ESTABLISH",
 	"EV_HANGUP",
 	"EV_BC_REL",
 	"EV_CINF",
 	"EV_SUSPEND",
 	"EV_RESUME",
-	"EV_SHUTDOWN_D",
 	"EV_NOSETUP_RSP",
 	"EV_SETUP_ERR",
 	"EV_CONNECT_ERR",
-	"EV_RELEASE_ERR",
-};
-
-enum {
-	ST_LC_NULL,
-	ST_LC_ACTIVATE_WAIT,
-	ST_LC_DELAY,
-	ST_LC_ESTABLISH_WAIT,
-	ST_LC_CONNECTED,
-	ST_LC_FLUSH_WAIT,
-	ST_LC_RELEASE_WAIT,
-};
-
-#define LC_STATE_COUNT (ST_LC_RELEASE_WAIT+1)
-
-static char *strLcState[] =
-{
-	"ST_LC_NULL",
-	"ST_LC_ACTIVATE_WAIT",
-	"ST_LC_DELAY",
-	"ST_LC_ESTABLISH_WAIT",
-	"ST_LC_CONNECTED",
-	"ST_LC_FLUSH_WAIT",
-	"ST_LC_RELEASE_WAIT",
-};
-
-enum {
-	EV_LC_ESTABLISH,
-	EV_LC_PH_ACTIVATE,
-	EV_LC_PH_DEACTIVATE,
-	EV_LC_DL_ESTABLISH,
-	EV_LC_TIMER,
-	EV_LC_DL_RELEASE,
-	EV_LC_RELEASE,
+	"EV_PROCEED",
+	"EV_ALERT",
+	"EV_REDIR",
 };
 
-#define LC_EVENT_COUNT (EV_LC_RELEASE+1)
 
-static char *strLcEvent[] =
+static inline void
+HL_LL(struct Channel *chanp, int command)
 {
-	"EV_LC_ESTABLISH",
-	"EV_LC_PH_ACTIVATE",
-	"EV_LC_PH_DEACTIVATE",
-	"EV_LC_DL_ESTABLISH",
-	"EV_LC_TIMER",
-	"EV_LC_DL_RELEASE",
-	"EV_LC_RELEASE",
-};
-
-#define LC_D  0
-#define LC_B  1
+        isdn_ctrl ic;
+ 
+        ic.driver = chanp->cs->myid;
+        ic.command = command;
+        ic.arg = chanp->chan;
+        chanp->cs->iif.statcallb(&ic);
+}
 
 static inline void
 lli_deliver_cause(struct Channel *chanp)
 {
-	isdn_ctrl ic;
-
-	if (chanp->proc->para.cause < 0)
+        isdn_ctrl ic;
+ 
+	if (chanp->proc->para.cause == NO_CAUSE)
 		return;
 	ic.driver = chanp->cs->myid;
 	ic.command = ISDN_STAT_CAUSE;
@@ -312,166 +330,121 @@
 	chanp->cs->iif.statcallb(&ic);
 }
 
-static void
-lli_d_established(struct FsmInst *fi, int event, void *arg)
+static inline void
+lli_close(struct FsmInst *fi)
 {
-	struct Channel *chanp = fi->userdata;
-
-	test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-	if (chanp->leased) {
-		isdn_ctrl ic;
-		int ret;
-		char txt[32];
+        struct Channel *chanp = fi->userdata;
 
-		chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan);
-		FsmChangeState(fi, ST_IN_WAIT_LL);
-		test_and_set_bit(FLG_CALL_REC, &chanp->Flags);
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_ICALL_LEASED", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_ICALL;
-		ic.arg = chanp->chan;
-		ic.parm.setup.si1 = 7;
-		ic.parm.setup.si2 = 0;
-		ic.parm.setup.plan = 0;
-		ic.parm.setup.screen = 0;
-		sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1); 
-		sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid);
-		ret = chanp->cs->iif.statcallb(&ic);
-		if (chanp->debug & 1) {
-			sprintf(txt, "statcallb ret=%d", ret);
-			link_debug(chanp, txt, 1);
-		}
-		if (!ret) {
-			chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
-			FsmChangeState(fi, ST_NULL);
-		}
-	} else if (fi->state == ST_WAIT_DSHUTDOWN)
-		FsmChangeState(fi, ST_NULL);
+        FsmChangeState(fi, ST_NULL);
+        chanp->Flags = 0;
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+}
+
+ static void
+lli_leased_in(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        isdn_ctrl ic;
+        int ret;
+ 
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+        FsmChangeState(fi, ST_IN_WAIT_LL);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_ICALL_LEASED");
+        ic.driver = chanp->cs->myid;
+	ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW);
+        ic.arg = chanp->chan;
+        ic.parm.setup.si1 = 7;
+        ic.parm.setup.si2 = 0;
+        ic.parm.setup.plan = 0;
+        ic.parm.setup.screen = 0;
+        sprintf(ic.parm.setup.eazmsn,"%d", chanp->chan + 1);
+        sprintf(ic.parm.setup.phone,"LEASED%d", chanp->cs->myid);
+        ret = chanp->cs->iif.statcallb(&ic);
+        if (chanp->debug & 1)
+                link_debug(chanp, 1, "statcallb ret=%d", ret);
+ 
+        if (!ret) {
+                chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+                FsmChangeState(fi, ST_NULL);
+        }
 }
 
-static void
-lli_d_released(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-
-	test_and_clear_bit(FLG_START_D, &chanp->Flags);
-}
 
 /*
  * Dial out
  */
 static void
+lli_init_bchan_out(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+ 
+        FsmChangeState(fi, ST_WAIT_BCONN);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_DCONN");
+        HL_LL(chanp, ISDN_STAT_DCONN);
+        init_b_st(chanp, 0);
+        chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
+}
+
+static void
 lli_prep_dialout(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_OUT_WAIT_D);
 	FsmDelTimer(&chanp->drel_timer, 60);
 	FsmDelTimer(&chanp->dial_timer, 73);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = 0;
-	chanp->lc_b->l2_start = !0;
-	switch (chanp->l2_active_protocol) {
-		case (ISDN_PROTO_L2_X75I):
-			chanp->lc_b->l2_establish = !0;
-			break;
-		case (ISDN_PROTO_L2_HDLC):
-		case (ISDN_PROTO_L2_TRANS):
-			chanp->lc_b->l2_establish = 0;
-			break;
-		default:
-			printk(KERN_WARNING "lli_prep_dialout unknown protocol\n");
-			break;
-	}
-	if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
-		FsmEvent(fi, EV_DLEST, NULL);
-	} else {
-		chanp->Flags = 0;
-		test_and_set_bit(FLG_START_D, &chanp->Flags);
-		if (chanp->leased) {
-			chanp->lc_d->l2_establish = 0;
-		}
-		FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
-	}
-}
 
-static void
-lli_do_dialout(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-
-	FsmChangeState(fi, ST_OUT_DIAL);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan);
-	if (chanp->leased) {
-		FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
-	} else {
-		test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_REQ, chanp);
-		test_and_set_bit(FLG_CALL_SEND, &chanp->Flags);
-	}
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+        if (chanp->leased) {
+                lli_init_bchan_out(fi, event, arg);
+        } else {
+                FsmChangeState(fi, ST_OUT_DIAL);
+                chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp);
+        }
 }
 
 static void
-lli_init_bchan_out(struct FsmInst *fi, int event, void *arg)
+lli_resume(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
-	FsmChangeState(fi, ST_WAIT_BCONN);
-	test_and_set_bit(FLG_LL_DCONN, &chanp->Flags);
-	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_DCONN", 0);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DCONN;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	init_b_st(chanp, 0);
-	test_and_set_bit(FLG_START_B, &chanp->Flags);
-	FsmEvent(&chanp->lc_b->lcfi, EV_LC_ESTABLISH, NULL);
+        FsmDelTimer(&chanp->drel_timer, 60);
+        FsmDelTimer(&chanp->dial_timer, 73);
+        chanp->l2_active_protocol = chanp->l2_protocol;
+        chanp->incoming = 0;
+ 
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
+        if (chanp->leased) {
+                lli_init_bchan_out(fi, event, arg);
+        } else {
+                FsmChangeState(fi, ST_OUT_DIAL);
+                chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp);
+        }
 }
 
 static void
 lli_go_active(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
 	FsmChangeState(fi, ST_ACTIVE);
 	chanp->data_open = !0;
-	test_and_set_bit(FLG_CONNECT_B, &chanp->Flags);
 	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_BCONN", 0);
-	test_and_set_bit(FLG_LL_BCONN, &chanp->Flags);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_BCONN;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) chanp->chan);
+		link_debug(chanp, 0, "STAT_BCONN");
+	HL_LL(chanp, ISDN_STAT_BCONN);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan);
 }
 
-/* incomming call */
 
-static void
-lli_start_dchan(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
+/*
+ * RESUME
+ */
 
-	FsmChangeState(fi, ST_IN_WAIT_D);
-	FsmDelTimer(&chanp->drel_timer, 61);
-	if (event == EV_ACCEPTD)
-		test_and_set_bit(FLG_DO_CONNECT, &chanp->Flags);
-	else if (event == EV_HANGUP) {
-		test_and_set_bit(FLG_DO_HANGUP, &chanp->Flags);
-#ifdef ALERT_REJECT		
-		test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);
-#endif
-	} 
-	if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
-		FsmEvent(fi, EV_DLEST, NULL);
-	} else if (!test_and_set_bit(FLG_START_D, &chanp->Flags))
-		FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
-}
+/* incomming call */
 
 static void
 lli_deliver_call(struct FsmInst *fi, int event, void *arg)
@@ -479,9 +452,8 @@
 	struct Channel *chanp = fi->userdata;
 	isdn_ctrl ic;
 	int ret;
-	char txt[32];
 
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) chanp->chan);
+	chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan);
 	/*
 	 * Report incoming calls only once to linklevel, use CallFlags
 	 * which is set to 3 with each broadcast message in isdnl1.c
@@ -489,11 +461,11 @@
 	 */
 	if (1) { /* for only one TEI */
 		FsmChangeState(fi, ST_IN_WAIT_LL);
-		test_and_set_bit(FLG_CALL_REC, &chanp->Flags);
 		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_ICALL", 0);
+			link_debug(chanp, 0, (chanp->chan < 2) ? "STAT_ICALL" : "STAT_ICALLW");
 		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_ICALL;
+		ic.command = ((chanp->chan < 2) ? ISDN_STAT_ICALL : ISDN_STAT_ICALLW);
+
 		ic.arg = chanp->chan;
 		/*
 		 * No need to return "unknown" for calls without OAD,
@@ -501,962 +473,496 @@
 		 */
 		ic.parm.setup = chanp->proc->para.setup;
 		ret = chanp->cs->iif.statcallb(&ic);
-		if (chanp->debug & 1) {
-			sprintf(txt, "statcallb ret=%d", ret);
-			link_debug(chanp, txt, 1);
-		}
+		if (chanp->debug & 1)
+			link_debug(chanp, 1, "statcallb ret=%d", ret);
+
 		switch (ret) {
-			case 1:	/* OK, anybody likes this call */
+			case 1:	/* OK, someone likes this call */
 				FsmDelTimer(&chanp->drel_timer, 61);
-				if (test_bit(FLG_ESTAB_D, &chanp->Flags)) {
-					FsmChangeState(fi, ST_IN_ALERT_SEND);
-					test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags);
-					chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING_REQ, chanp->proc);
-				} else {
-					test_and_set_bit(FLG_DO_ALERT, &chanp->Flags);
-					FsmChangeState(fi, ST_IN_WAIT_D);
-					test_and_set_bit(FLG_START_D, &chanp->Flags);
-					FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
-				}
+				FsmChangeState(fi, ST_IN_ALERT_SENT);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+				break;
+	      	        case 4: /* direct redirect */
+		        case 3: /* Proceeding desired */
+				FsmDelTimer(&chanp->drel_timer, 61);
+				FsmChangeState(fi, ST_IN_PROCEED_SEND);
+                                chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc);
+                                if (ret == 4)
+				 { chanp->setup = ic.parm.setup;
+				   chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
+                                 }   
 				break;
 			case 2:	/* Rejecting Call */
-				test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
 				break;
 			case 0:	/* OK, nobody likes this call */
 			default:	/* statcallb problems */
-				chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE, chanp->proc);
-				chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+				chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
+				chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 				FsmChangeState(fi, ST_NULL);
-#ifndef LAYER2_WATCHING
-				if (test_bit(FLG_ESTAB_D, &chanp->Flags))
-					FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 61);
-#endif
 				break;
 		}
 	} else {
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE, chanp->proc);
-		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
-		FsmChangeState(fi, ST_NULL);
-#ifndef LAYER2_WATCHING
-		if (test_bit(FLG_ESTAB_D, &chanp->Flags))
-			FsmRestartTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 62);
-#endif
+		chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc);
+		chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
 	}
 }
 
 static void
-lli_establish_d(struct FsmInst *fi, int event, void *arg)
+lli_send_dconnect(struct FsmInst *fi, int event, void *arg)
 {
-	/* This establish the D-channel for pending L3 messages 
-	 * without blocking th channel
-	 */
 	struct Channel *chanp = fi->userdata;
 
-	test_and_set_bit(FLG_DO_ESTAB, &chanp->Flags);
-	FsmChangeState(fi, ST_IN_WAIT_D);
-	test_and_set_bit(FLG_START_D, &chanp->Flags);
-	FsmEvent(&chanp->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+	FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
 }
 
 static void
-lli_do_action(struct FsmInst *fi, int event, void *arg)
+lli_send_alert(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-	if (chanp->leased) {
-		FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-		test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags);
-		test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags);
-		FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
-	} else if (test_and_clear_bit(FLG_DO_CONNECT, &chanp->Flags) &&
-		!test_bit(FLG_DO_HANGUP, &chanp->Flags)) {
-		FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-		test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_RSP, chanp->proc);
-	} else if (test_and_clear_bit(FLG_DO_ALERT, &chanp->Flags)) {
-		if (test_bit(FLG_DO_HANGUP, &chanp->Flags))
-			FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
-		FsmChangeState(fi, ST_IN_ALERT_SEND);
-		test_and_set_bit(FLG_CALL_ALERT, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING_REQ, chanp->proc);
-	} else if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags)) {
-		FsmChangeState(fi, ST_WAIT_DRELEASE);
-		chanp->proc->para.cause = 0x15;		/* Call Rejected */
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT_REQ, chanp->proc);
-		test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
-	} else if (test_and_clear_bit(FLG_DO_ESTAB, &chanp->Flags)) {
-		FsmChangeState(fi, ST_NULL);
-		chanp->Flags = 0;
-		test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_ESTABLISH, chanp->proc);
-		chanp->proc = NULL;
-#ifndef LAYER2_WATCHING
-		FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60);
-#endif
-	}
+	FsmChangeState(fi, ST_IN_ALERT_SENT);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 }
 
 static void
-lli_send_dconnect(struct FsmInst *fi, int event, void *arg)
+lli_send_redir(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP_RSP, chanp->proc);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc);
 }
 
 static void
 lli_init_bchan_in(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
 	FsmChangeState(fi, ST_WAIT_BCONN);
-	test_and_set_bit(FLG_LL_DCONN, &chanp->Flags);
 	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_DCONN", 0);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DCONN;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
+		link_debug(chanp, 0, "STAT_DCONN");
+	HL_LL(chanp, ISDN_STAT_DCONN);
 	chanp->l2_active_protocol = chanp->l2_protocol;
 	chanp->incoming = !0;
-	chanp->lc_b->l2_start = 0;
-	switch (chanp->l2_active_protocol) {
-		case (ISDN_PROTO_L2_X75I):
-			chanp->lc_b->l2_establish = !0;
-			break;
-		case (ISDN_PROTO_L2_HDLC):
-		case (ISDN_PROTO_L2_TRANS):
-			chanp->lc_b->l2_establish = 0;
-			break;
-		default:
-			printk(KERN_WARNING "bchannel unknown protocol\n");
-			break;
-	}
 	init_b_st(chanp, !0);
-	test_and_set_bit(FLG_START_B, &chanp->Flags);
-	FsmEvent(&chanp->lc_b->lcfi, EV_LC_ESTABLISH, NULL);
-}
-
-/* Call clearing */
-
-static void
-lli_cancel_call(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	chanp->proc->para.cause = 0x10;		/* Normal Call Clearing */
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT_REQ, chanp->proc);
-	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL);
 }
 
 static void
-lli_shutdown_d(struct FsmInst *fi, int event, void *arg)
+lli_setup_rsp(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-
-	FsmDelTimer(&chanp->drel_timer, 62);
-#ifdef LAYER2_WATCHING
-	FsmChangeState(fi, ST_NULL);
-#else
-	if (!test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags)) {
-		if (chanp->chan) {
-			if (chanp->cs->channel[0].fi.state != ST_NULL)
-				return;
-		} else {
-			if (chanp->cs->channel[1].fi.state != ST_NULL)
-				return;
-		}
-	}
-	FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
-	test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
-	FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
+        struct Channel *chanp = fi->userdata;
+ 
+        if (chanp->leased) {
+                lli_init_bchan_in(fi, event, arg);
+        } else {
+                FsmChangeState(fi, ST_IN_WAIT_CONN_ACK);
+#ifdef WANT_ALERT
+                chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
 #endif
+               chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc);
+       }
 }
 
-static void
-lli_timeout_d(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	FsmChangeState(fi, ST_NULL);
-	chanp->Flags = 0;
-	test_and_set_bit(FLG_ESTAB_D, &chanp->Flags);
-#ifndef LAYER2_WATCHING
-	FsmAddTimer(&chanp->drel_timer, DREL_TIMER_VALUE, EV_SHUTDOWN_D, NULL, 60);
-#endif
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
-}
+/* Call suspend */
 
 static void
-lli_go_null(struct FsmInst *fi, int event, void *arg)
+lli_suspend(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_NULL);
-	chanp->Flags = 0;
-	FsmDelTimer(&chanp->drel_timer, 63);
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc);
 }
 
-static void
-lli_disconn_bchan(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_WAIT_BRELEASE);
-	test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags);
-	FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
-}
+/* Call clearing */
 
 static void
-lli_send_d_disc(struct FsmInst *fi, int event, void *arg)
+lli_disconnect_req(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
-	if (test_bit(FLG_DISC_REC, &chanp->Flags) ||
-		test_bit(FLG_REL_REC, &chanp->Flags))
-		return;
 	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (chanp->leased) {
-		ic.command = ISDN_STAT_CAUSE;
-		ic.arg = chanp->chan;
-		sprintf(ic.parm.num, "L0010");
-		chanp->cs->iif.statcallb(&ic);
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-		FsmChangeState(fi, ST_WAIT_DSHUTDOWN);
-		test_and_clear_bit(FLG_ESTAB_D, &chanp->Flags);
-		FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
-	} else {
-		if (test_and_clear_bit(FLG_DO_HANGUP, &chanp->Flags))
-			chanp->proc->para.cause = 0x15;		/* Call Reject */
-		else
-			chanp->proc->para.cause = 0x10;		/* Normal Call Clearing */
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT_REQ, chanp->proc);
-		test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);
-	}
+	chanp->proc->para.cause = 0x10;	/* Normal Call Clearing */
+	chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
 }
 
 static void
-lli_released_bchan(struct FsmInst *fi, int event, void *arg)
+lli_disconnect_reject(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_WAIT_DCOMMAND);
-	chanp->data_open = 0;
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	release_b_st(chanp);
-	test_and_clear_bit(FLG_START_B, &chanp->Flags);
+        FsmChangeState(fi, ST_WAIT_DRELEASE);
+        chanp->proc->para.cause = 0x15;         /* Call Rejected */
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc);
 }
 
-
 static void
-lli_release_bchan(struct FsmInst *fi, int event, void *arg)
+lli_dhup_close(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-	chanp->data_open = 0;
-	test_and_set_bit(FLG_DISC_REC, &chanp->Flags);
-	FsmChangeState(fi, ST_WAIT_BREL_DISC);
-	test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags);
-	FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_DHUP");
+        lli_deliver_cause(chanp);
+        HL_LL(chanp, ISDN_STAT_DHUP);
+ 
+        lli_close(fi);
 }
 
 static void
-lli_received_d_rel(struct FsmInst *fi, int event, void *arg)
+lli_reject_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_NULL);
-	test_and_set_bit(FLG_REL_REC, &chanp->Flags);
-	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->lc_b->l2_establish = 0;	/* direct reset in lc_b->lcfi */
-		FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
-	}
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (test_bit(FLG_LL_DCONN, &chanp->Flags) ||
-		test_bit(FLG_CALL_SEND, &chanp->Flags) ||
-		test_bit(FLG_CALL_ALERT, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	lli_timeout_d(fi, event, arg);
+#ifndef ALERT_REJECT
+        chanp->proc->para.cause = 0x15;         /* Call Rejected */
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc);
+        lli_dhup_close(fi, event, arg);
+#else
+        FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63);
+        FsmChangeState(fi, ST_IN_ALERT_SENT);
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc);
+#endif
 }
 
 static void
-lli_received_d_relcnf(struct FsmInst *fi, int event, void *arg)
+lli_disconn_bchan(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
 	chanp->data_open = 0;
-	FsmChangeState(fi, ST_NULL);
-	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->lc_b->l2_establish = 0;	/* direct reset in lc_b->lcfi */
-		FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
-	}
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (test_bit(FLG_LL_DCONN, &chanp->Flags) ||
-		test_bit(FLG_CALL_SEND, &chanp->Flags) ||
-		test_bit(FLG_CALL_ALERT, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	test_and_clear_bit(FLG_DISC_SEND, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_REC, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	lli_timeout_d(fi, event, arg);
+	FsmChangeState(fi, ST_WAIT_BRELEASE);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 }
 
 static void
-lli_received_d_disc(struct FsmInst *fi, int event, void *arg)
+lli_start_disc(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
 	isdn_ctrl ic;
 
-	chanp->data_open = 0;
-	FsmChangeState(fi, ST_WAIT_D_REL_CNF);
-	test_and_set_bit(FLG_DISC_REC, &chanp->Flags);
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
+	if (chanp->leased) {
+		ic.command = ISDN_STAT_CAUSE;
 		ic.arg = chanp->chan;
+		sprintf(ic.parm.num, "L0010");
 		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (test_bit(FLG_LL_DCONN, &chanp->Flags) ||
-		test_bit(FLG_CALL_SEND, &chanp->Flags) ||
-		test_bit(FLG_CALL_ALERT, &chanp->Flags)) {
 		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
+			link_debug(chanp, 0, "STAT_DHUP");
+		HL_LL(chanp, ISDN_STAT_DHUP);
+		lli_close(fi);
+	} else {
+	        lli_disconnect_req(fi, event, arg);
 	}
-	test_and_clear_bit(FLG_CALL_ALERT, &chanp->Flags);
-	test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE_REQ, chanp->proc);
 }
 
-/* processing charge info */
 static void
-lli_charge_info(struct FsmInst *fi, int event, void *arg)
+lli_rel_b_disc(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_CINF;
-	ic.arg = chanp->chan;
-	sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo);
-	chanp->cs->iif.statcallb(&ic);
-}
-
-/* error procedures */
-
-static void
-lli_no_dchan(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_NODCH", 0);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_NODCH;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	chanp->Flags = 0;
-	FsmChangeState(fi, ST_NULL);
-	FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
-}
-
-static void
-lli_no_dchan_ready(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_DHUP", 0);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-}
-
-static void
-lli_no_dchan_in(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_DHUP", 0);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc);
-	chanp->Flags = 0;
-	FsmChangeState(fi, ST_NULL);
-	FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
-}
-
-static void
-lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg)
-{
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	FsmChangeState(fi, ST_NULL);
-	test_and_clear_bit(FLG_CALL_SEND, &chanp->Flags);
-	if (chanp->debug & 1)
-		link_debug(chanp, "STAT_DHUP", 0);
-	ic.driver = chanp->cs->myid;
-	ic.command = ISDN_STAT_DHUP;
-	ic.arg = chanp->chan;
-	chanp->cs->iif.statcallb(&ic);
-	lli_shutdown_d(fi, event, arg);
+        struct Channel *chanp = fi->userdata;
+ 
+        release_b_st(chanp);
+        lli_start_disc(fi, event, arg);
 }
 
 static void
-lli_setup_err(struct FsmInst *fi, int event, void *arg)
+lli_bhup_disc(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
-
-	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);	/* DISCONN was sent from L3 */
+        struct Channel *chanp = fi->userdata;
+  
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_disc(fi, event, arg);
 }
 
 static void
-lli_connect_err(struct FsmInst *fi, int event, void *arg)
+lli_bhup_rel_b(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
+        struct Channel *chanp = fi->userdata;
 
-	FsmChangeState(fi, ST_WAIT_DRELEASE);
-	if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_DHUP", 0);
-		lli_deliver_cause(chanp);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	test_and_set_bit(FLG_DISC_SEND, &chanp->Flags);	/* DISCONN was sent from L3 */
+        FsmChangeState(fi, ST_WAIT_DCOMMAND);
+        chanp->data_open = 0;
+                if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+        release_b_st(chanp);
 }
 
 static void
-lli_got_dlrl(struct FsmInst *fi, int event, void *arg)
+lli_release_bchan(struct FsmInst *fi, int event, void *arg)
 {
 	struct Channel *chanp = fi->userdata;
-	isdn_ctrl ic;
 
 	chanp->data_open = 0;
-	FsmChangeState(fi, ST_NULL);
-	if (test_and_clear_bit(FLG_CONNECT_B, &chanp->Flags)) {
-		chanp->lc_b->l2_establish = 0;	/* direct reset in lc_b->lcfi */
-		FsmEvent(&chanp->lc_b->lcfi, EV_LC_RELEASE, NULL);
-	}
-	if (test_and_clear_bit(FLG_LL_BCONN, &chanp->Flags)) {
-		if (chanp->debug & 1)
-			link_debug(chanp, "STAT_BHUP", 0);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_BHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-	}
-	if (test_and_clear_bit(FLG_START_B, &chanp->Flags))
-		release_b_st(chanp);
-	if (chanp->leased) {
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_CAUSE;
-		ic.arg = chanp->chan;
-		sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f);
-		chanp->cs->iif.statcallb(&ic);
-		ic.driver = chanp->cs->myid;
-		ic.command = ISDN_STAT_DHUP;
-		ic.arg = chanp->chan;
-		chanp->cs->iif.statcallb(&ic);
-		chanp->Flags = 0;
-	} else {
-		if (test_and_clear_bit(FLG_LL_DCONN, &chanp->Flags)) {
-			if (chanp->debug & 1)
-				link_debug(chanp, "STAT_DHUP", 0);
-			if (chanp->cs->protocol == ISDN_PTYPE_EURO) {
-				chanp->proc->para.cause = 0x2f;
-				chanp->proc->para.loc = 0;
-			} else {
-				chanp->proc->para.cause = 0x70;
-				chanp->proc->para.loc = 0;
-			}
-			lli_deliver_cause(chanp);
-			ic.driver = chanp->cs->myid;
-			ic.command = ISDN_STAT_DHUP;
-			ic.arg = chanp->chan;
-			chanp->cs->iif.statcallb(&ic);
-		}
-		chanp->d_st->lli.l4l3(chanp->d_st, CC_DLRL, chanp->proc);
-		chanp->Flags = 0;
-		FsmEvent(&chanp->lc_d->lcfi, EV_LC_RELEASE, NULL);
-	}
-	chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) chanp->chan);
-}
-
-/* *INDENT-OFF* */
-static struct FsmNode fnlist[] HISAX_INITDATA =
-{
-	{ST_NULL,		EV_DIAL,		lli_prep_dialout},
-	{ST_NULL,		EV_SETUP_IND,		lli_deliver_call},
-	{ST_NULL,		EV_SHUTDOWN_D,		lli_shutdown_d},
-	{ST_NULL,		EV_DLRL,		lli_go_null},
-	{ST_NULL,		EV_DLEST,		lli_d_established},
-	{ST_NULL,		EV_ESTABLISH,		lli_establish_d},
-	{ST_OUT_WAIT_D,		EV_DLEST,		lli_do_dialout},
-	{ST_OUT_WAIT_D,		EV_DLRL,		lli_no_dchan},
-	{ST_OUT_WAIT_D,		EV_HANGUP,		lli_no_dchan},
-	{ST_IN_WAIT_D,		EV_DLEST,		lli_do_action},
-	{ST_IN_WAIT_D,		EV_DLRL,		lli_no_dchan_in},
-	{ST_IN_WAIT_D,		EV_ACCEPTD,		lli_start_dchan},
-	{ST_IN_WAIT_D,		EV_HANGUP,		lli_start_dchan},
-	{ST_OUT_DIAL,		EV_SETUP_CNF,		lli_init_bchan_out},
-	{ST_OUT_DIAL,		EV_HANGUP,		lli_cancel_call},
-	{ST_OUT_DIAL,		EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_OUT_DIAL,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_OUT_DIAL,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_OUT_DIAL,		EV_NOSETUP_RSP,		lli_no_setup_rsp},
-	{ST_OUT_DIAL,		EV_SETUP_ERR,		lli_setup_err},
-	{ST_OUT_DIAL,		EV_DLRL,		lli_got_dlrl},
-	{ST_IN_WAIT_LL,		EV_DLEST,		lli_d_established},
-	{ST_IN_WAIT_LL,		EV_DLRL,		lli_d_released},
-	{ST_IN_WAIT_LL,		EV_ACCEPTD,		lli_start_dchan},
-	{ST_IN_WAIT_LL,		EV_HANGUP,		lli_start_dchan},
-	{ST_IN_WAIT_LL,		EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_IN_WAIT_LL,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_IN_WAIT_LL,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_IN_ALERT_SEND,	EV_SETUP_CMPL_IND,	lli_init_bchan_in},
-	{ST_IN_ALERT_SEND,	EV_ACCEPTD,		lli_send_dconnect},
-	{ST_IN_ALERT_SEND,	EV_HANGUP,		lli_send_d_disc},
-	{ST_IN_ALERT_SEND,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_IN_ALERT_SEND,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_IN_ALERT_SEND,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_IN_ALERT_SEND,	EV_DLRL,		lli_got_dlrl},
-	{ST_IN_WAIT_CONN_ACK,	EV_SETUP_CMPL_IND,	lli_init_bchan_in},
-	{ST_IN_WAIT_CONN_ACK,	EV_HANGUP,		lli_send_d_disc},
-	{ST_IN_WAIT_CONN_ACK,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_IN_WAIT_CONN_ACK,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_IN_WAIT_CONN_ACK,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_IN_WAIT_CONN_ACK,	EV_CONNECT_ERR,		lli_connect_err},
-	{ST_IN_WAIT_CONN_ACK,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BCONN,		EV_BC_EST,		lli_go_active},
-	{ST_WAIT_BCONN,		EV_BC_REL,		lli_send_d_disc},
-	{ST_WAIT_BCONN,		EV_HANGUP,		lli_send_d_disc},
-	{ST_WAIT_BCONN,		EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_WAIT_BCONN,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_BCONN,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_BCONN,		EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BCONN,		EV_CINF,		lli_charge_info},
-	{ST_ACTIVE,		EV_CINF,		lli_charge_info},
-	{ST_ACTIVE,		EV_BC_REL,		lli_released_bchan},
-	{ST_ACTIVE,		EV_HANGUP,		lli_disconn_bchan},
-	{ST_ACTIVE,		EV_DISCONNECT_IND,	lli_release_bchan},
-	{ST_ACTIVE,		EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_ACTIVE,		EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_ACTIVE,		EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BRELEASE,	EV_BC_REL,		lli_send_d_disc},
-	{ST_WAIT_BRELEASE,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_WAIT_BRELEASE,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_BRELEASE,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_BRELEASE,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_BREL_DISC,	EV_BC_REL,		lli_received_d_disc},
-	{ST_WAIT_BREL_DISC,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_BREL_DISC,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_BREL_DISC,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_DCOMMAND,	EV_HANGUP,		lli_send_d_disc},
-	{ST_WAIT_DCOMMAND,	EV_DISCONNECT_IND,	lli_received_d_disc},
-	{ST_WAIT_DCOMMAND,	EV_RELEASE_CNF,		lli_received_d_relcnf},
-	{ST_WAIT_DCOMMAND,	EV_RELEASE_IND,		lli_received_d_rel},
-	{ST_WAIT_DCOMMAND,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_DRELEASE,	EV_RELEASE_IND,		lli_timeout_d},
-	{ST_WAIT_DRELEASE,	EV_RELEASE_CNF,		lli_timeout_d},
-	{ST_WAIT_DRELEASE,	EV_RELEASE_ERR,		lli_timeout_d},
-	{ST_WAIT_DRELEASE,	EV_DIAL,		lli_no_dchan_ready},
-	{ST_WAIT_DRELEASE,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_D_REL_CNF,	EV_RELEASE_CNF,		lli_timeout_d},
-	{ST_WAIT_D_REL_CNF,	EV_RELEASE_ERR,		lli_timeout_d},
-/* ETS 300-104 16.1 */
-	{ST_WAIT_D_REL_CNF,     EV_RELEASE_IND,         lli_timeout_d},
-	{ST_WAIT_D_REL_CNF,	EV_DIAL,		lli_no_dchan_ready},
-	{ST_WAIT_D_REL_CNF,	EV_DLRL,		lli_got_dlrl},
-	{ST_WAIT_DSHUTDOWN,	EV_DLRL,		lli_go_null},
-	{ST_WAIT_DSHUTDOWN,	EV_DLEST,		lli_d_established},
-	{ST_WAIT_DSHUTDOWN,	EV_DIAL,		lli_prep_dialout},
-	{ST_WAIT_DSHUTDOWN,	EV_SETUP_IND,		lli_deliver_call},
-};
-/* *INDENT-ON* */
-
-
-#define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
-
-static void
-lc_activate_l1(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 50);
-	FsmChangeState(fi, ST_LC_ACTIVATE_WAIT);
-	/* This timeout is to avoid a hang if no L1 activation is possible */
-	FsmAddTimer(&lf->act_timer, 30000, EV_LC_TIMER, NULL, 50);
-	lf->st->ma.manl1(lf->st, PH_ACTIVATE_REQ, NULL);
-}
-
-static void
-lc_activated_from_l1(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	if (lf->l2_establish)
-		FsmChangeState(fi, ST_LC_DELAY);
-	else {
-		FsmChangeState(fi, ST_LC_CONNECTED);
-		lf->lccall(lf, LC_ESTABLISH, NULL);
-	}
+	FsmChangeState(fi, ST_WAIT_BREL_DISC);
+	chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
 }
 
-static void
-lc_l1_activated(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 50);
-	FsmChangeState(fi, ST_LC_DELAY);
-	/* This timer is needed for delay the first paket on a channel
-	   to be shure that the other side is ready too */
-	if (lf->delay)
-		FsmAddTimer(&lf->act_timer, lf->delay, EV_LC_TIMER, NULL, 51);
-	else
-		FsmEvent(fi, EV_LC_TIMER, NULL);
-}
 
 static void
-lc_start_l2(struct FsmInst *fi, int event, void *arg)
+lli_rel_b_dhup(struct FsmInst *fi, int event, void *arg)
 {
-	struct LcFsm *lf = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-/*	if (!lf->st->l1.act_state)
-		lf->st->l1.act_state = 2;
-*/	if (lf->l2_establish) {
-		FsmChangeState(fi, ST_LC_ESTABLISH_WAIT);
-		if (lf->l2_start)
-			lf->st->ma.manl2(lf->st, DL_ESTABLISH, NULL);
-	} else {
-		FsmChangeState(fi, ST_LC_CONNECTED);
-		lf->lccall(lf, LC_ESTABLISH, NULL);
-	}
+        release_b_st(chanp);
+        lli_dhup_close(fi, event, arg);
 }
 
 static void
-lc_connected(struct FsmInst *fi, int event, void *arg)
+lli_bhup_dhup(struct FsmInst *fi, int event, void *arg)
 {
-	struct LcFsm *lf = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-	FsmDelTimer(&lf->act_timer, 50);
-	FsmChangeState(fi, ST_LC_CONNECTED);
-	lf->lccall(lf, LC_ESTABLISH, NULL);
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_dhup(fi, event, arg);
 }
 
 static void
-lc_release_l2(struct FsmInst *fi, int event, void *arg)
+lli_abort(struct FsmInst *fi, int event, void *arg)
 {
-	struct LcFsm *lf = fi->userdata;
+        struct Channel *chanp = fi->userdata;
 
-	if (lf->l2_establish) {
-		FsmChangeState(fi, ST_LC_RELEASE_WAIT);
-		lf->st->ma.manl2(lf->st, DL_RELEASE, NULL);
-	} else {
-		FsmChangeState(fi, ST_LC_NULL);
-		lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL);
-		lf->lccall(lf, LC_RELEASE, NULL);
-	}
+        chanp->data_open = 0;
+        chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+ 
+        lli_bhup_dhup(fi, event, arg);
 }
-
+ 
 static void
-lc_l2_released(struct FsmInst *fi, int event, void *arg)
+lli_release_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct LcFsm *lf = fi->userdata;
-
-	FsmChangeState(fi, ST_LC_RELEASE_WAIT);
-	FsmDelTimer(&lf->act_timer, 51);
-	/* This delay is needed for send out the UA frame before
-	 * PH_DEACTIVATE the interface
-	 */
-	FsmAddTimer(&lf->act_timer, 20, EV_LC_TIMER, NULL, 54);
+        struct Channel *chanp = fi->userdata;
+ 
+        FsmChangeState(fi, ST_WAIT_D_REL_CNF);
+        chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc);
 }
 
 static void
-lc_release_l1(struct FsmInst *fi, int event, void *arg)
+lli_rel_b_release_req(struct FsmInst *fi, int event, void *arg)
 {
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 54);
-	FsmChangeState(fi, ST_LC_NULL);
-	lf->st->ma.manl1(lf->st, PH_DEACTIVATE_REQ, NULL);
-	lf->lccall(lf, LC_RELEASE, NULL);
+        struct Channel *chanp = fi->userdata;
+ 
+        release_b_st(chanp);
+        lli_release_req(fi, event, arg);
 }
 
 static void
-lc_l1_deactivated(struct FsmInst *fi, int event, void *arg)
-{
-	struct LcFsm *lf = fi->userdata;
-
-	FsmDelTimer(&lf->act_timer, 54);
-	FsmChangeState(fi, ST_LC_NULL);
-	lf->lccall(lf, LC_RELEASE, NULL);
-}
-/* *INDENT-OFF* */
-static struct FsmNode LcFnList[] HISAX_INITDATA =
-{
-	{ST_LC_NULL,  		EV_LC_ESTABLISH,	lc_activate_l1},
-	{ST_LC_NULL,  		EV_LC_PH_ACTIVATE,	lc_activated_from_l1},
-	{ST_LC_NULL,  		EV_LC_DL_ESTABLISH,	lc_connected},
-	{ST_LC_ACTIVATE_WAIT,	EV_LC_PH_ACTIVATE,	lc_l1_activated},
-	{ST_LC_ACTIVATE_WAIT,	EV_LC_TIMER,		lc_release_l1},
-	{ST_LC_ACTIVATE_WAIT,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_DELAY,  		EV_LC_ESTABLISH,	lc_start_l2},
-	{ST_LC_DELAY,		EV_LC_TIMER,		lc_start_l2},
-	{ST_LC_DELAY,		EV_LC_DL_ESTABLISH,	lc_connected},
-	{ST_LC_DELAY,  		EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_ESTABLISH_WAIT,	EV_LC_DL_ESTABLISH,	lc_connected},
-	{ST_LC_ESTABLISH_WAIT,	EV_LC_RELEASE,		lc_release_l1},
-	{ST_LC_ESTABLISH_WAIT,	EV_LC_DL_RELEASE,	lc_release_l1},
-	{ST_LC_ESTABLISH_WAIT,  EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_CONNECTED,	EV_LC_ESTABLISH,	lc_connected},
-	{ST_LC_CONNECTED,	EV_LC_RELEASE,		lc_release_l2},
-	{ST_LC_CONNECTED,	EV_LC_DL_RELEASE,	lc_l2_released},
-	{ST_LC_CONNECTED,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_FLUSH_WAIT,	EV_LC_TIMER,		lc_release_l2},
-	{ST_LC_FLUSH_WAIT,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-	{ST_LC_RELEASE_WAIT,	EV_LC_DL_RELEASE,	lc_release_l1},
-	{ST_LC_RELEASE_WAIT,	EV_LC_TIMER,		lc_release_l1},
-	{ST_LC_FLUSH_WAIT,  	EV_LC_PH_DEACTIVATE,	lc_l1_deactivated},
-};
-/* *INDENT-ON* */
-
-
-#define LC_FN_COUNT (sizeof(LcFnList)/sizeof(struct FsmNode))
-
-HISAX_INITFUNC(void
-CallcNew(void))
+lli_bhup_release_req(struct FsmInst *fi, int event, void *arg)
 {
-	callcfsm.state_count = STATE_COUNT;
-	callcfsm.event_count = EVENT_COUNT;
-	callcfsm.strEvent = strEvent;
-	callcfsm.strState = strState;
-	FsmNew(&callcfsm, fnlist, FNCOUNT);
-
-	lcfsm.state_count = LC_STATE_COUNT;
-	lcfsm.event_count = LC_EVENT_COUNT;
-	lcfsm.strEvent = strLcEvent;
-	lcfsm.strState = strLcState;
-	FsmNew(&lcfsm, LcFnList, LC_FN_COUNT);
+        struct Channel *chanp = fi->userdata;
+ 
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_release_req(fi, event, arg);
 }
 
-void
-CallcFree(void)
-{
-	FsmFree(&lcfsm);
-	FsmFree(&callcfsm);
-}
 
+/* processing charge info */
 static void
-release_b_st(struct Channel *chanp)
+lli_charge_info(struct FsmInst *fi, int event, void *arg)
 {
-	struct PStack *st = chanp->b_st;
+	struct Channel *chanp = fi->userdata;
+	isdn_ctrl ic;
 
-	chanp->bcs->BC_Close(chanp->bcs);
-	switch (chanp->l2_active_protocol) {
-		case (ISDN_PROTO_L2_X75I):
-			releasestack_isdnl2(st);
-			break;
-		case (ISDN_PROTO_L2_HDLC):
-		case (ISDN_PROTO_L2_TRANS):
-			releasestack_transl2(st);
-			break;
-	}
-	/* Reset B-Channel Statemachine */
-	FsmDelTimer(&chanp->lc_b->act_timer, 79);
-	FsmChangeState(&chanp->lc_b->lcfi, ST_LC_NULL);
+	ic.driver = chanp->cs->myid;
+	ic.command = ISDN_STAT_CINF;
+	ic.arg = chanp->chan;
+	sprintf(ic.parm.num, "%d", chanp->proc->para.chargeinfo);
+	chanp->cs->iif.statcallb(&ic);
 }
 
+/* error procedures */
+
 static void
-dc_l1man(struct PStack *st, int pr, void *arg)
+lli_dchan_not_ready(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp;
+	struct Channel *chanp = fi->userdata;
 
-	chanp = (struct Channel *) st->lli.userdata;
-	switch (pr) {
-		case (PH_ACTIVATE_CNF):
-		case (PH_ACTIVATE_IND):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_ACTIVATE, NULL);
-			break;
-		case (PH_DEACTIVATE_IND):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_PH_DEACTIVATE, NULL);
-			break;
-	}
+	if (chanp->debug & 1)
+		link_debug(chanp, 0, "STAT_DHUP");
+        HL_LL(chanp, ISDN_STAT_DHUP); 
 }
 
 static void
-dc_l2man(struct PStack *st, int pr, void *arg)
+lli_no_setup_rsp(struct FsmInst *fi, int event, void *arg)
 {
-	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	struct Channel *chanp = fi->userdata;
 
-	switch (pr) {
-		case (DL_ESTABLISH):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_ESTABLISH, NULL);
-			break;
-		case (DL_RELEASE):
-			FsmEvent(&chanp->lc_d->lcfi, EV_LC_DL_RELEASE, NULL);
-			break;
-	}
-}
+	if (chanp->debug & 1)
+		link_debug(chanp, 0, "STAT_DHUP");
+	HL_LL(chanp, ISDN_STAT_DHUP);
+        lli_close(fi); 
+}
+
+static void
+lli_error(struct FsmInst *fi, int event, void *arg)
+{
+        FsmChangeState(fi, ST_WAIT_DRELEASE);
+}
+
+static void
+lli_failure_l(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+        isdn_ctrl ic;
+
+        FsmChangeState(fi, ST_NULL);
+        ic.driver = chanp->cs->myid;
+        ic.command = ISDN_STAT_CAUSE;
+        ic.arg = chanp->chan;
+        sprintf(ic.parm.num, "L%02X%02X", 0, 0x2f);
+        chanp->cs->iif.statcallb(&ic);
+        HL_LL(chanp, ISDN_STAT_DHUP);
+        chanp->Flags = 0;
+        chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan);
+}
+
+static void
+lli_rel_b_fail(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        release_b_st(chanp);
+        lli_failure_l(fi, event, arg);
+}
+
+static void
+lli_bhup_fail(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        if (chanp->debug & 1)
+                link_debug(chanp, 0, "STAT_BHUP");
+        HL_LL(chanp, ISDN_STAT_BHUP);
+ 
+        lli_rel_b_fail(fi, event, arg);
+}
+
+static void
+lli_failure_a(struct FsmInst *fi, int event, void *arg)
+{
+        struct Channel *chanp = fi->userdata;
+
+        chanp->data_open = 0;
+        chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL);
+ 
+        lli_bhup_fail(fi, event, arg);
+}
+
+  /* *INDENT-OFF* */
+  static struct FsmNode fnlist[] HISAX_INITDATA =
+  {
+        {ST_NULL,               EV_DIAL,                lli_prep_dialout},
+        {ST_NULL,               EV_RESUME,              lli_resume},
+        {ST_NULL,               EV_SETUP_IND,           lli_deliver_call},
+        {ST_NULL,               EV_LEASED,              lli_leased_in},
+        {ST_OUT_DIAL,           EV_SETUP_CNF,           lli_init_bchan_out},
+        {ST_OUT_DIAL,           EV_HANGUP,              lli_disconnect_req},
+        {ST_OUT_DIAL,           EV_DISCONNECT_IND,      lli_release_req},
+        {ST_OUT_DIAL,           EV_RELEASE,             lli_dhup_close},
+        {ST_OUT_DIAL,           EV_NOSETUP_RSP,         lli_no_setup_rsp},
+        {ST_OUT_DIAL,           EV_SETUP_ERR,           lli_error},
+        {ST_IN_WAIT_LL,         EV_LEASED_REL,          lli_failure_l},
+        {ST_IN_WAIT_LL,         EV_ACCEPTD,             lli_setup_rsp},
+        {ST_IN_WAIT_LL,         EV_HANGUP,              lli_reject_req},
+        {ST_IN_WAIT_LL,         EV_DISCONNECT_IND,      lli_release_req},
+        {ST_IN_WAIT_LL,         EV_RELEASE,             lli_dhup_close},
+        {ST_IN_ALERT_SENT,      EV_SETUP_CMPL_IND,      lli_init_bchan_in},
+        {ST_IN_ALERT_SENT,      EV_ACCEPTD,             lli_send_dconnect},
+        {ST_IN_ALERT_SENT,      EV_HANGUP,              lli_disconnect_reject},
+        {ST_IN_ALERT_SENT,      EV_DISCONNECT_IND,      lli_release_req},
+        {ST_IN_ALERT_SENT,      EV_RELEASE,             lli_dhup_close},
+	{ST_IN_ALERT_SENT,	EV_REDIR,		lli_send_redir},
+	{ST_IN_PROCEED_SEND,	EV_REDIR,		lli_send_redir},
+	{ST_IN_PROCEED_SEND,	EV_ALERT,		lli_send_alert},
+	{ST_IN_PROCEED_SEND,	EV_ACCEPTD,		lli_send_dconnect},
+	{ST_IN_PROCEED_SEND,	EV_HANGUP,		lli_disconnect_reject},
+	{ST_IN_PROCEED_SEND,	EV_DISCONNECT_IND,	lli_dhup_close},
+        {ST_IN_ALERT_SENT,      EV_RELEASE,             lli_dhup_close},
+        {ST_IN_WAIT_CONN_ACK,   EV_SETUP_CMPL_IND,      lli_init_bchan_in},
+        {ST_IN_WAIT_CONN_ACK,   EV_HANGUP,              lli_disconnect_req},
+        {ST_IN_WAIT_CONN_ACK,   EV_DISCONNECT_IND,      lli_release_req},
+        {ST_IN_WAIT_CONN_ACK,   EV_RELEASE,             lli_dhup_close},
+        {ST_IN_WAIT_CONN_ACK,   EV_CONNECT_ERR,         lli_error},
+        {ST_WAIT_BCONN,         EV_BC_EST,              lli_go_active},
+        {ST_WAIT_BCONN,         EV_BC_REL,              lli_rel_b_disc},
+        {ST_WAIT_BCONN,         EV_HANGUP,              lli_rel_b_disc},
+        {ST_WAIT_BCONN,         EV_DISCONNECT_IND,      lli_rel_b_release_req},
+        {ST_WAIT_BCONN,         EV_RELEASE,             lli_rel_b_dhup},
+        {ST_WAIT_BCONN,         EV_LEASED_REL,          lli_rel_b_fail},
+        {ST_WAIT_BCONN,         EV_CINF,                lli_charge_info},
+        {ST_ACTIVE,             EV_CINF,                lli_charge_info},
+        {ST_ACTIVE,             EV_BC_REL,              lli_bhup_rel_b},
+        {ST_ACTIVE,             EV_SUSPEND,             lli_suspend},
+        {ST_ACTIVE,             EV_HANGUP,              lli_disconn_bchan},
+        {ST_ACTIVE,             EV_DISCONNECT_IND,      lli_release_bchan},
+        {ST_ACTIVE,             EV_RELEASE,             lli_abort},
+        {ST_ACTIVE,             EV_LEASED_REL,          lli_failure_a},
+        {ST_WAIT_BRELEASE,      EV_BC_REL,              lli_bhup_disc},
+        {ST_WAIT_BRELEASE,      EV_DISCONNECT_IND,      lli_bhup_release_req},
+        {ST_WAIT_BRELEASE,      EV_RELEASE,             lli_bhup_dhup},
+        {ST_WAIT_BRELEASE,      EV_LEASED_REL,          lli_bhup_fail},
+        {ST_WAIT_BREL_DISC,     EV_BC_REL,              lli_bhup_release_req},
+        {ST_WAIT_BREL_DISC,     EV_RELEASE,             lli_bhup_dhup},
+        {ST_WAIT_DCOMMAND,      EV_HANGUP,              lli_start_disc},
+        {ST_WAIT_DCOMMAND,      EV_DISCONNECT_IND,      lli_release_req},
+        {ST_WAIT_DCOMMAND,      EV_RELEASE,             lli_dhup_close},
+        {ST_WAIT_DCOMMAND,      EV_LEASED_REL,          lli_failure_l},
+        {ST_WAIT_DRELEASE,      EV_RELEASE,             lli_dhup_close},
+        {ST_WAIT_DRELEASE,      EV_DIAL,                lli_dchan_not_ready},
+  /* ETS 300-104 16.1 */
+        {ST_WAIT_D_REL_CNF,     EV_RELEASE,             lli_dhup_close},
+        {ST_WAIT_D_REL_CNF,     EV_DIAL,                lli_dchan_not_ready},
+};
+  /* *INDENT-ON* */
 
-static void
-bc_l1man(struct PStack *st, int pr, void *arg)
+
+  #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode))
+
+HISAX_INITFUNC(void
+CallcNew(void))
 {
-	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	callcfsm.state_count = STATE_COUNT;
+	callcfsm.event_count = EVENT_COUNT;
+	callcfsm.strEvent = strEvent;
+	callcfsm.strState = strState;
+	FsmNew(&callcfsm, fnlist, FNCOUNT);
+}
 
-	switch (pr) {
-		case (PH_ACTIVATE_IND):
-		case (PH_ACTIVATE_CNF):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_ACTIVATE, NULL);
-			break;
-		case (PH_DEACTIVATE_IND):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_PH_DEACTIVATE, NULL);
-			break;
-	}
+void
+CallcFree(void)
+{
+	FsmFree(&callcfsm);
 }
 
 static void
-bc_l2man(struct PStack *st, int pr, void *arg)
+release_b_st(struct Channel *chanp)
 {
-	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	struct PStack *st = chanp->b_st;
 
-	switch (pr) {
-		case (DL_ESTABLISH):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL);
-			break;
-		case (DL_RELEASE):
-			FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_RELEASE, NULL);
-			break;
-	}
+        if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) {
+                chanp->bcs->BC_Close(chanp->bcs);
+                switch (chanp->l2_active_protocol) {
+			case (ISDN_PROTO_L2_X75I):
+				releasestack_isdnl2(st);
+				break;
+			case (ISDN_PROTO_L2_HDLC):
+			case (ISDN_PROTO_L2_TRANS):
+			case (ISDN_PROTO_L2_MODEM):
+                                releasestack_transl2(st);
+                                break;
+                }
+        } 
 }
 
 struct Channel
-*selectfreechannel(struct PStack *st)
+*selectfreechannel(struct PStack *st, int bch)
 {
 	struct IsdnCardState *cs = st->l1.hardware;
 	struct Channel *chanp = st->lli.userdata;
@@ -1466,87 +972,96 @@
 		i=1;
 	else
 		i=0;
-	while (i<2) {
+
+        if (!bch) 
+         { i = 2; /* virtual channel */
+           chanp += 2;
+         }
+
+	while (i < ((bch) ? cs->chanlimit : (2 + MAX_WAITING_CALLS))) {
 		if (chanp->fi.state == ST_NULL)
 			return (chanp);
 		chanp++;
 		i++;
-	}		
-	return (NULL);
-}
-
-int
-is_activ(struct PStack *st)
-{
-	struct IsdnCardState *cs = st->l1.hardware;
-	struct Channel *chanp = st->lli.userdata;
-	int i;
+	}
 
-	if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
-		i=1;
-	else
-		i=0;
-	while (i<2) {
-		if (test_bit(FLG_ESTAB_D, &chanp->Flags))
-			return (1);
+        if (bch) /* number of channels is limited */ 
+         { i = 2; /* virtual channel */
+           chanp = st->lli.userdata;
+	   chanp += i;
+	   while (i < (2 + MAX_WAITING_CALLS)) {
+		if (chanp->fi.state == ST_NULL)
+			return (chanp);
 		chanp++;
 		i++;
-	}		
-	return (0);
+	   }
+         }
+	return (NULL);
 }
 
+static void stat_redir_result(struct IsdnCardState *cs, int chan, ulong result)
+{	isdn_ctrl ic;
+  
+	ic.driver = cs->myid;
+	ic.command = ISDN_STAT_REDIR;
+	ic.arg = chan; 
+	(ulong)(ic.parm.num[0]) = result;
+	cs->iif.statcallb(&ic);
+} /* stat_redir_result */
+
 static void
-ll_handler(struct l3_process *pc, int pr, void *arg)
+dchan_l3l4(struct PStack *st, int pr, void *arg)
 {
+	struct l3_process *pc = arg;
+        struct IsdnCardState *cs = st->l1.hardware;
 	struct Channel *chanp;
-	char tmp[64], tm[32];
 
-	if (pr == CC_SETUP_IND) {
-		if (!(chanp = selectfreechannel(pc->st))) {
-			pc->st->lli.l4l3(pc->st, CC_DLRL, pc);
-			return;
-		} else {
-			chanp->proc = pc;
-			pc->chan = chanp;
+        if(!pc)
+                return;
+ 
+        if (pr == (CC_SETUP | INDICATION)) {
+                if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) {
+                        pc->para.cause = 0x11;          /* User busy */
+                        pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc);
+                } else {
+                        chanp->proc = pc;
+                        pc->chan = chanp;
 			FsmEvent(&chanp->fi, EV_SETUP_IND, NULL);
-			return;
 		}
-	} else if (pr == CC_ESTABLISH) {
-		if (is_activ(pc->st)) {
-			pc->st->lli.l4l3(pc->st, CC_ESTABLISH, pc);
-			return;
-		} else if (!(chanp = selectfreechannel(pc->st))) {
-			pc->st->lli.l4l3(pc->st, CC_DLRL, pc);
-			return;
-		} else {
-			chanp->proc = pc;
-			FsmEvent(&chanp->fi, EV_ESTABLISH, NULL);
-			return;
-		}
-
-			
+		return;
 	}
-	chanp = pc->chan;
+	if (!(chanp = pc->chan))
+		return;
+
 	switch (pr) {
-		case (CC_DISCONNECT_IND):
+		case (CC_DISCONNECT | INDICATION):
 			FsmEvent(&chanp->fi, EV_DISCONNECT_IND, NULL);
 			break;
-		case (CC_RELEASE_CNF):
-			FsmEvent(&chanp->fi, EV_RELEASE_CNF, NULL);
+		case (CC_RELEASE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
+			break;
+		case (CC_SUSPEND | CONFIRM):
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
+			break;
+		case (CC_RESUME | CONFIRM):
+			FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
+			break;
+		case (CC_RESUME_ERR):
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
-		case (CC_RELEASE_IND):
-			FsmEvent(&chanp->fi, EV_RELEASE_IND, NULL);
+		case (CC_RELEASE | INDICATION):
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
-		case (CC_SETUP_COMPLETE_IND):
+		case (CC_SETUP_COMPL | INDICATION):
 			FsmEvent(&chanp->fi, EV_SETUP_CMPL_IND, NULL);
 			break;
-		case (CC_SETUP_CNF):
+		case (CC_SETUP | CONFIRM):
 			FsmEvent(&chanp->fi, EV_SETUP_CNF, NULL);
 			break;
-		case (CC_INFO_CHARGE):
+		case (CC_CHARGE | INDICATION):
 			FsmEvent(&chanp->fi, EV_CINF, NULL);
 			break;
-		case (CC_NOSETUP_RSP_ERR):
+		case (CC_NOSETUP_RSP):
 			FsmEvent(&chanp->fi, EV_NOSETUP_RSP, NULL);
 			break;
 		case (CC_SETUP_ERR):
@@ -1556,17 +1071,22 @@
 			FsmEvent(&chanp->fi, EV_CONNECT_ERR, NULL);
 			break;
 		case (CC_RELEASE_ERR):
-			FsmEvent(&chanp->fi, EV_RELEASE_ERR, NULL);
-			break;
-		case (CC_PROCEEDING_IND):
-		case (CC_ALERTING_IND):
+			FsmEvent(&chanp->fi, EV_RELEASE, NULL);
 			break;
+		case (CC_PROCEED_SEND | INDICATION):
+		case (CC_PROCEEDING | INDICATION):
+		case (CC_ALERTING | INDICATION):
+		case (CC_PROGRESS | INDICATION):
+		case (CC_NOTIFY | INDICATION):
+			break;
+		case (CC_REDIR | INDICATION):
+			stat_redir_result(cs, chanp->chan, pc->redir_result); 
+			break;                         
 		default:
 			if (chanp->debug & 0x800) {
-				jiftime(tm, jiffies);
-				sprintf(tmp, "%s Channel %d L3->L4 unknown primitiv %d\n",
-					tm, chanp->chan, pr);
-				HiSax_putstatus(chanp->cs, tmp);
+				HiSax_putstatus(chanp->cs, "Ch",
+					"%d L3->L4 unknown primitiv %#x",
+					chanp->chan, pr);
 			}
 	}
 }
@@ -1576,7 +1096,7 @@
 {
 	struct PStack *st = chanp->d_st;
 	struct IsdnCardState *cs = chanp->cs;
-	char tmp[128];
+	char tmp[16];
 
 	HiSax_addlist(cs, st);
 	setstack_HiSax(st, cs);
@@ -1590,95 +1110,51 @@
 	st->l2.window = 1;
 	st->l2.T200 = 1000;	/* 1000 milliseconds  */
 	st->l2.N200 = 3;	/* try 3 times        */
-	if (st->protocol == ISDN_PTYPE_1TR6)
-		st->l2.T203 = 10000;	/* 10000 milliseconds */
+	st->l2.T203 = 10000;	/* 10000 milliseconds */
+	if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags))
+		sprintf(tmp, "DCh%d Q.921 ", chanp->chan);
 	else
-		st->l2.T203 = 10000;	/* 5000 milliseconds  */
-	
-	sprintf(tmp, "Channel %d q.921", chanp->chan);
+		sprintf(tmp, "DCh Q.921 ");
 	setstack_isdnl2(st, tmp);
-	setstack_isdnl3(st, chanp);
+	setstack_l3dc(st, chanp);
 	st->lli.userdata = chanp;
 	st->lli.l2writewakeup = NULL;
-	st->l3.l3l4 = ll_handler;
-	st->l1.l1man = dc_l1man;
-	st->l2.l2man = dc_l2man;
+	st->l3.l3l4 = dchan_l3l4;
 }
 
 static void
-callc_debug(struct FsmInst *fi, char *s)
+callc_debug(struct FsmInst *fi, char *fmt, ...)
 {
-	char str[80], tm[32];
+	va_list args;
 	struct Channel *chanp = fi->userdata;
+	char tmp[16];
 
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Channel %d callc %s\n", tm, chanp->chan, s);
-	HiSax_putstatus(chanp->cs, str);
-}
-
-static void
-lc_debug(struct FsmInst *fi, char *s)
-{
-	char str[256], tm[32];
-	struct LcFsm *lf = fi->userdata;
-
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Channel %d dc %s\n", tm, lf->ch->chan, s);
-	HiSax_putstatus(lf->ch->cs, str);
-}
-
-static void
-dlc_debug(struct FsmInst *fi, char *s)
-{
-	char str[256], tm[32];
-	struct LcFsm *lf = fi->userdata;
-
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Channel %d bc %s\n", tm, lf->ch->chan, s);
-	HiSax_putstatus(lf->ch->cs, str);
+	va_start(args, fmt);
+	sprintf(tmp, "Ch%d callc ", chanp->chan);
+	VHiSax_putstatus(chanp->cs, tmp, fmt, args);
+	va_end(args);
 }
 
 static void
-lccall_d(struct LcFsm *lf, int pr, void *arg)
-{
-	struct IsdnCardState *cs = lf->st->l1.hardware;
-	struct Channel *chanp;
-	int i;
-
-	if (test_bit(FLG_TWO_DCHAN, &cs->HW_Flags)) {
-		chanp = lf->ch;
-		i = 1;
-	} else {
-		chanp = cs->channel;
-		i = 0;
-	}
-	while (i < 2) {
-		switch (pr) {
-			case (LC_ESTABLISH):
-				FsmEvent(&chanp->fi, EV_DLEST, NULL);
-				break;
-			case (LC_RELEASE):
-				FsmEvent(&chanp->fi, EV_DLRL, NULL);
-				break;
-		}
-		chanp++;
-		i++;
-	}
+dummy_pstack(struct PStack *st, int pr, void *arg) {
+	printk(KERN_WARNING"call to dummy_pstack pr=%04x arg %lx\n", pr, (long)arg);
 }
 
 static void
-lccall_b(struct LcFsm *lf, int pr, void *arg)
-{
-	struct Channel *chanp = lf->ch;
-
-	switch (pr) {
-		case (LC_ESTABLISH):
-			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
-			break;
-		case (LC_RELEASE):
-			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
-			break;
-	}
+init_PStack(struct PStack **stp) {
+	*stp = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+	(*stp)->next = NULL;
+	(*stp)->l1.l1l2 = dummy_pstack;
+	(*stp)->l1.l1hw = dummy_pstack;
+	(*stp)->l1.l1tei = dummy_pstack;
+	(*stp)->l2.l2tei = dummy_pstack;
+	(*stp)->l2.l2l1 = dummy_pstack;
+	(*stp)->l2.l2l3 = dummy_pstack;
+	(*stp)->l3.l3l2 = dummy_pstack;
+        (*stp)->l3.l3ml3 = dummy_pstack;
+	(*stp)->l3.l3l4 = dummy_pstack;
+	(*stp)->lli.l4l3 = dummy_pstack;
+	(*stp)->ma.layer = dummy_pstack;
 }
 
 static void
@@ -1693,9 +1169,8 @@
 	chanp->debug = 0;
 	chanp->Flags = 0;
 	chanp->leased = 0;
-	chanp->b_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
-	chanp->b_st->next = NULL;
-
+	init_PStack(&chanp->b_st);
+	chanp->b_st->l1.delay = DEFAULT_B_DELAY;
 	chanp->fi.fsm = &callcfsm;
 	chanp->fi.state = ST_NULL;
 	chanp->fi.debug = 0;
@@ -1704,56 +1179,35 @@
 	FsmInitTimer(&chanp->fi, &chanp->dial_timer);
 	FsmInitTimer(&chanp->fi, &chanp->drel_timer);
 	if (!chan || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
-		chanp->d_st = kmalloc(sizeof(struct PStack), GFP_ATOMIC);
+		init_PStack(&chanp->d_st);
+		if (chan)
+			csta->channel->d_st->next = chanp->d_st;
 		chanp->d_st->next = NULL;
 		init_d_st(chanp);
-		chanp->lc_d = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC);
-		chanp->lc_d->lcfi.fsm = &lcfsm;
-		chanp->lc_d->lcfi.state = ST_LC_NULL;
-		chanp->lc_d->lcfi.debug = 0;
-		chanp->lc_d->lcfi.userdata = chanp->lc_d;
-		chanp->lc_d->lcfi.printdebug = lc_debug;
-		chanp->lc_d->type = LC_D;
-		chanp->lc_d->delay = 0;
-		chanp->lc_d->ch = chanp;
-		chanp->lc_d->st = chanp->d_st;
-		chanp->lc_d->l2_establish = !0;
-		chanp->lc_d->l2_start = !0;
-		chanp->lc_d->lccall = lccall_d;
-		FsmInitTimer(&chanp->lc_d->lcfi, &chanp->lc_d->act_timer);
 	} else {
 		chanp->d_st = csta->channel->d_st;
-		chanp->lc_d = csta->channel->lc_d;
 	}
-	chanp->lc_b = kmalloc(sizeof(struct LcFsm), GFP_ATOMIC);
-	chanp->lc_b->lcfi.fsm = &lcfsm;
-	chanp->lc_b->lcfi.state = ST_LC_NULL;
-	chanp->lc_b->lcfi.debug = 0;
-	chanp->lc_b->lcfi.userdata = chanp->lc_b;
-	chanp->lc_b->lcfi.printdebug = dlc_debug;
-	chanp->lc_b->type = LC_B;
-	chanp->lc_b->delay = DEFAULT_B_DELAY;
-	chanp->lc_b->ch = chanp;
-	chanp->lc_b->st = chanp->b_st;
-	chanp->lc_b->l2_establish = !0;
-	chanp->lc_b->l2_start = !0;
-	chanp->lc_b->lccall = lccall_b;
-	FsmInitTimer(&chanp->lc_b->lcfi, &chanp->lc_b->act_timer);
 	chanp->data_open = 0;
 }
 
 int
 CallcNewChan(struct IsdnCardState *csta)
-{
+{       int i;
+
 	chancount += 2;
 	init_chan(0, csta);
 	init_chan(1, csta);
 	printk(KERN_INFO "HiSax: 2 channels added\n");
-#ifdef LAYER2_WATCHING
-	printk(KERN_INFO "LAYER2 ESTABLISH\n");
-	test_and_set_bit(FLG_START_D, &csta->channel->Flags);
-	FsmEvent(&csta->channel->lc_d->lcfi, EV_LC_ESTABLISH, NULL);
-#endif
+
+	for (i = 0; i < MAX_WAITING_CALLS; i++) 
+		init_chan(i+2,csta);
+	printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n");        
+
+	if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) {
+		printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
+		csta->channel->d_st->lli.l4l3(csta->channel->d_st,
+			DL_ESTABLISH | REQUEST, NULL);
+	}
 	return (2);
 }
 
@@ -1779,29 +1233,16 @@
 	for (i = 0; i < 2; i++) {
 		FsmDelTimer(&csta->channel[i].drel_timer, 74);
 		FsmDelTimer(&csta->channel[i].dial_timer, 75);
-		FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77);
-		FsmDelTimer(&csta->channel[i].lc_b->act_timer, 76);
-		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
-			release_d_st(csta->channel + i);
-		if (csta->channel[i].b_st) {
-			if (test_and_clear_bit(FLG_START_B, &csta->channel[i].Flags))
-				release_b_st(csta->channel + i);
-			kfree(csta->channel[i].b_st);
-			csta->channel[i].b_st = NULL;
-		} else
+                if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags))
+                        release_d_st(csta->channel + i);
+                if (csta->channel[i].b_st) {
+                        release_b_st(csta->channel + i);
+                        kfree(csta->channel[i].b_st);
+                        csta->channel[i].b_st = NULL;
+                } else
 			printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i);
-		if (csta->channel[i].lc_b) {
-			kfree(csta->channel[i].lc_b);
-			csta->channel[i].b_st = NULL;
-		}
 		if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
 			release_d_st(csta->channel + i);
-			FsmDelTimer(&csta->channel[i].lc_d->act_timer, 77);
-			if (csta->channel[i].lc_d) {
-				kfree(csta->channel[i].lc_d);
-				csta->channel[i].d_st = NULL;
-			} else
-				printk(KERN_WARNING "CallcFreeChan lc_d ch%d allready freed\n", i);
 		} else
 			csta->channel[i].d_st = NULL;
 	}
@@ -1814,15 +1255,23 @@
 	struct sk_buff *skb = arg;
 
 	switch (pr) {
-		case (DL_DATA):
+		case (DL_DATA  | INDICATION):
 			if (chanp->data_open)
 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
 			else {
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 			}
 			break;
+		case (DL_ESTABLISH | INDICATION):
+		case (DL_ESTABLISH | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
+			break;
+		case (DL_RELEASE | INDICATION):
+		case (DL_RELEASE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
+			break;
 		default:
-			printk(KERN_WARNING "lldata_handler unknown primitive %d\n",
+			printk(KERN_WARNING "lldata_handler unknown primitive %#x\n",
 			       pr);
 			break;
 	}
@@ -1835,22 +1284,24 @@
 	struct sk_buff *skb = arg;
 
 	switch (pr) {
-		case (PH_DATA_IND):
+		case (PH_DATA | INDICATION):
 			if (chanp->data_open)
 				chanp->cs->iif.rcvcallb_skb(chanp->cs->myid, chanp->chan, skb);
 			else {
-				if (chanp->lc_b->lcfi.state == ST_LC_DELAY)
-					FsmEvent(&chanp->lc_b->lcfi, EV_LC_DL_ESTABLISH, NULL);
-				if (chanp->data_open) {
-					link_debug(chanp, "channel now open", 0);
-					chanp->cs->iif.rcvcallb_skb(chanp->cs->myid,
-						chanp->chan, skb);
-				} else
-					dev_kfree_skb(skb);
+				link_debug(chanp, 0, "channel not open");
+				idev_kfree_skb(skb, FREE_READ);
 			}
 			break;
+		case (PH_ACTIVATE | INDICATION):
+		case (PH_ACTIVATE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_EST, NULL);
+			break;
+		case (PH_DEACTIVATE | INDICATION):
+		case (PH_DEACTIVATE | CONFIRM):
+			FsmEvent(&chanp->fi, EV_BC_REL, NULL);
+			break;
 		default:
-			printk(KERN_WARNING "lltrans_handler unknown primitive %d\n",
+			printk(KERN_WARNING "lltrans_handler unknown primitive %#x\n",
 			       pr);
 			break;
 	}
@@ -1874,10 +1325,25 @@
 {
 	struct PStack *st = chanp->b_st;
 	struct IsdnCardState *cs = chanp->cs;
-	char tmp[128];
+	char tmp[16];
 
 	st->l1.hardware = cs;
-	chanp->bcs->mode = 2;
+	if (chanp->leased)
+		st->l1.bc = chanp->chan & 1;
+	else
+		st->l1.bc = chanp->proc->para.bchannel - 1;
+	switch (chanp->l2_active_protocol) {
+		case (ISDN_PROTO_L2_X75I):
+		case (ISDN_PROTO_L2_HDLC):
+			st->l1.mode = L1_MODE_HDLC;
+			break;
+		case (ISDN_PROTO_L2_TRANS):
+			st->l1.mode = L1_MODE_TRANS;
+			break;
+		case (ISDN_PROTO_L2_MODEM):
+			st->l1.mode = L1_MODE_MODEM;
+			break;
+	}
 	if (chanp->bcs->BC_SetStack(st, chanp->bcs))
 		return (-1);
 	st->l2.flag = 0;
@@ -1892,50 +1358,89 @@
 	st->l3.debug = 0;
 	switch (chanp->l2_active_protocol) {
 		case (ISDN_PROTO_L2_X75I):
-			sprintf(tmp, "Channel %d x.75", chanp->chan);
+			sprintf(tmp, "Ch%d X.75", chanp->chan);
 			setstack_isdnl2(st, tmp);
+			setstack_l3bc(st, chanp);
 			st->l2.l2l3 = lldata_handler;
-			st->l1.l1man = bc_l1man;
-			st->l2.l2man = bc_l2man;
 			st->lli.userdata = chanp;
 			st->lli.l1writewakeup = NULL;
 			st->lli.l2writewakeup = ll_writewakeup;
 			st->l2.l2m.debug = chanp->debug & 16;
 			st->l2.debug = chanp->debug & 64;
-			st->ma.manl2(st, MDL_NOTEIPROC, NULL);
-			st->l1.mode = L1_MODE_HDLC;
-			if (chanp->leased)
-				st->l1.bc = chanp->chan & 1;
-			else
-				st->l1.bc = chanp->proc->para.bchannel - 1;
 			break;
 		case (ISDN_PROTO_L2_HDLC):
-			st->l1.l1l2 = lltrans_handler;
-			st->l1.l1man = bc_l1man;
-			st->lli.userdata = chanp;
-			st->lli.l1writewakeup = ll_writewakeup;
-			st->l1.mode = L1_MODE_HDLC;
-			if (chanp->leased)
-				st->l1.bc = chanp->chan & 1;
-			else
-				st->l1.bc = chanp->proc->para.bchannel - 1;
-			break;
 		case (ISDN_PROTO_L2_TRANS):
+		case (ISDN_PROTO_L2_MODEM):
 			st->l1.l1l2 = lltrans_handler;
-			st->l1.l1man = bc_l1man;
 			st->lli.userdata = chanp;
 			st->lli.l1writewakeup = ll_writewakeup;
-			st->l1.mode = L1_MODE_TRANS;
-			if (chanp->leased)
-				st->l1.bc = chanp->chan & 1;
-			else
-				st->l1.bc = chanp->proc->para.bchannel - 1;
+			setstack_transl2(st);
+			setstack_l3bc(st, chanp);
 			break;
 	}
+        test_and_set_bit(FLG_START_B, &chanp->Flags);
+ 
 	return (0);
 }
 
 static void
+leased_l4l3(struct PStack *st, int pr, void *arg)
+{
+	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	struct sk_buff *skb = arg;
+
+	switch (pr) {
+		case (DL_DATA | REQUEST):
+			link_debug(chanp, 0, "leased line d-channel DATA");
+			idev_kfree_skb(skb, FREE_READ);
+			break;
+		case (DL_ESTABLISH | REQUEST):
+			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
+			break;
+		case (DL_RELEASE | REQUEST):
+			break;
+		default:
+			printk(KERN_WARNING "transd_l4l3 unknown primitive %#x\n",
+			       pr);
+			break;
+	}
+}
+
+static void
+leased_l1l2(struct PStack *st, int pr, void *arg)
+{
+	struct Channel *chanp = (struct Channel *) st->lli.userdata;
+	struct sk_buff *skb = arg;
+	int i,event = EV_LEASED_REL;
+
+	switch (pr) {
+		case (PH_DATA | INDICATION):
+			link_debug(chanp, 0, "leased line d-channel DATA");
+			idev_kfree_skb(skb, FREE_READ);
+			break;
+		case (PH_ACTIVATE | INDICATION):
+		case (PH_ACTIVATE | CONFIRM):
+			event = EV_LEASED;
+		case (PH_DEACTIVATE | INDICATION):
+		case (PH_DEACTIVATE | CONFIRM):
+			if (test_bit(FLG_TWO_DCHAN, &chanp->cs->HW_Flags))
+				i = 1;
+			else
+				i = 0;
+			while (i < 2) {
+				FsmEvent(&chanp->fi, event, NULL);
+				chanp++;
+				i++;
+			}
+			break;
+		default:
+			printk(KERN_WARNING
+				"transd_l1l2 unknown primitive %#x\n", pr);
+			break;
+	}
+}
+
+static void
 channel_report(struct Channel *chanp)
 {
 }
@@ -1946,30 +1451,117 @@
 	int i;
 	struct Channel *chanp = csta->channel;
 
-	for (i = 0; i < 2; i++) {
+	for (i = 0; i < (2 + MAX_WAITING_CALLS) ; i++) {
 		chanp[i].debug = debugflags;
 		chanp[i].fi.debug = debugflags & 2;
 		chanp[i].d_st->l2.l2m.debug = debugflags & 8;
 		chanp[i].b_st->l2.l2m.debug = debugflags & 0x10;
 		chanp[i].d_st->l2.debug = debugflags & 0x20;
 		chanp[i].b_st->l2.debug = debugflags & 0x40;
-		chanp[i].lc_d->lcfi.debug = debugflags & 0x80;
-		chanp[i].lc_b->lcfi.debug = debugflags & 0x100;
+		chanp[i].d_st->l3.l3m.debug = debugflags & 0x80;
+		chanp[i].b_st->l3.l3m.debug = debugflags & 0x100;
 		chanp[i].b_st->ma.tei_m.debug = debugflags & 0x200;
 		chanp[i].b_st->ma.debug = debugflags & 0x200;
 		chanp[i].d_st->l1.l1m.debug = debugflags & 0x1000;
+		chanp[i].b_st->l1.l1m.debug = debugflags & 0x2000;
+	}
+	if (debugflags & 4)
+		csta->debug |= DEB_DLOG_HEX;
+	else
+		csta->debug &= ~DEB_DLOG_HEX;
+}
+
+static char tmpbuf[256];
+
+static void
+capi_debug(struct Channel *chanp, capi_msg *cm)
+{
+	char *t = tmpbuf;
+
+	t += sprintf(tmpbuf, "%d CAPIMSG", chanp->chan);
+	t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length);
+	t--;
+	*t= 0;
+	HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
+}
+
+void
+lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
+	if ((cm->para[0] != 3) || (cm->para[1] != 0))
+		return;
+	if (cm->para[2]<3)
+		return;
+	if (cm->para[4] != 0)
+		return;
+	switch(cm->para[3]) {
+		case 4: /* Suspend */
+			if (cm->para[5]) {
+				strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+				FsmEvent(&chanp->fi, EV_SUSPEND, cm);
+			}
+			break;
+		case 5: /* Resume */
+			if (cm->para[5]) {
+				strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1);
+				if (chanp->fi.state == ST_NULL) {
+					FsmEvent(&chanp->fi, EV_RESUME, cm);
+				} else {
+					FsmDelTimer(&chanp->dial_timer, 72);
+					FsmAddTimer(&chanp->dial_timer, 80, EV_RESUME, cm, 73);
+				}
+			}
+			break;
+	}
+}
+
+void
+lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
+	if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
+		(cs->typ == ISDN_CTYPE_ELSA_PCI)) {
+		if (cs->hw.elsa.MFlag) {
+			cs->cardmsg(cs, CARD_AUX_IND, cm->para);
+		}
 	}
-	csta->dlogflag = debugflags & 4;
 }
 
+
+/***************************************************************/
+/* Limit the available number of channels for the current card */
+/***************************************************************/
+static int 
+set_channel_limit(struct IsdnCardState *cs, int chanmax)
+{ isdn_ctrl ic;
+  int i, ii;
+  
+  if ((chanmax < 0) || (chanmax > 2))
+    return(-EINVAL);
+  cs->chanlimit = 0;
+  for (ii = 0; ii < 2; ii++) {
+    ic.driver = cs->myid;
+    ic.command = ISDN_STAT_DISCH;
+    ic.arg = ii;
+    if (ii >= chanmax)
+      ic.parm.num[0] = 0; /* disabled */
+    else
+      ic.parm.num[0] = 1; /* enabled */
+    i = cs->iif.statcallb(&ic); 
+    if (i) return(-EINVAL);
+    if (ii < chanmax) 
+      cs->chanlimit++;
+  }
+  return(0);
+} /* set_channel_limit */
+
+
 int
 HiSax_command(isdn_ctrl * ic)
 {
 	struct IsdnCardState *csta = hisax_findcard(ic->driver);
+	struct PStack *st;
 	struct Channel *chanp;
-	char tmp[128];
 	int i;
-	unsigned int num;
+	u_int num;
+	u_long adr;
 
 	if (!csta) {
 		printk(KERN_ERR
@@ -1977,32 +1569,32 @@
 		       ic->command, ic->driver);
 		return -ENODEV;
 	}
+
 	switch (ic->command) {
 		case (ISDN_CMD_SETEAZ):
 			chanp = csta->channel + ic->arg;
-			if (chanp->debug & 1) {
-				sprintf(tmp, "SETEAZ card %d %s", csta->cardnr + 1,
-					ic->parm.num);
-				link_debug(chanp, tmp, 1);
-			}
 			break;
+
 		case (ISDN_CMD_SETL2):
 			chanp = csta->channel + (ic->arg & 0xff);
-			if (chanp->debug & 1) {
-				sprintf(tmp, "SETL2 card %d %ld", csta->cardnr + 1,
-					ic->arg >> 8);
-				link_debug(chanp, tmp, 1);
-			}
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "SETL2 card %d %ld",
+					csta->cardnr + 1, ic->arg >> 8);
 			chanp->l2_protocol = ic->arg >> 8;
 			break;
+		case (ISDN_CMD_SETL3):
+			chanp = csta->channel + (ic->arg & 0xff);
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "SETL3 card %d %ld",
+					csta->cardnr + 1, ic->arg >> 8);
+			chanp->l3_protocol = ic->arg >> 8;
+			break;
 		case (ISDN_CMD_DIAL):
 			chanp = csta->channel + (ic->arg & 0xff);
-			if (chanp->debug & 1) {
-				sprintf(tmp, "DIAL %s -> %s (%d,%d)",
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "DIAL %s -> %s (%d,%d)",
 					ic->parm.setup.eazmsn, ic->parm.setup.phone,
-				 ic->parm.setup.si1, ic->parm.setup.si2);
-				link_debug(chanp, tmp, 1);
-			}
+					ic->parm.setup.si1, ic->parm.setup.si2);
 			chanp->setup = ic->parm.setup;
 			if (!strcmp(chanp->setup.eazmsn, "0"))
 				chanp->setup.eazmsn[0] = '\0';
@@ -2018,57 +1610,54 @@
 		case (ISDN_CMD_ACCEPTB):
 			chanp = csta->channel + ic->arg;
 			if (chanp->debug & 1)
-				link_debug(chanp, "ACCEPTB", 1);
+				link_debug(chanp, 1, "ACCEPTB");
 			FsmEvent(&chanp->fi, EV_ACCEPTB, NULL);
 			break;
 		case (ISDN_CMD_ACCEPTD):
 			chanp = csta->channel + ic->arg;
 			if (chanp->debug & 1)
-				link_debug(chanp, "ACCEPTD", 1);
+				link_debug(chanp, 1, "ACCEPTD");
 			FsmEvent(&chanp->fi, EV_ACCEPTD, NULL);
 			break;
 		case (ISDN_CMD_HANGUP):
 			chanp = csta->channel + ic->arg;
 			if (chanp->debug & 1)
-				link_debug(chanp, "HANGUP", 1);
+				link_debug(chanp, 1, "HANGUP");
 			FsmEvent(&chanp->fi, EV_HANGUP, NULL);
 			break;
-		case (ISDN_CMD_SUSPEND):
+		case (CAPI_PUT_MESSAGE):
 			chanp = csta->channel + ic->arg;
-			if (chanp->debug & 1) {
-				sprintf(tmp, "SUSPEND %s", ic->parm.num);
-				link_debug(chanp, tmp, 1);
-			}
-			FsmEvent(&chanp->fi, EV_SUSPEND, ic);
-			break;
-		case (ISDN_CMD_RESUME):
-			chanp = csta->channel + ic->arg;
-			if (chanp->debug & 1) {
-				sprintf(tmp, "RESUME %s", ic->parm.num);
-				link_debug(chanp, tmp, 1);
+			if (chanp->debug & 1)
+				capi_debug(chanp, &ic->parm.cmsg);
+			if (ic->parm.cmsg.Length < 8)
+				break;
+			switch(ic->parm.cmsg.Command) {
+				case CAPI_FACILITY:
+					if (ic->parm.cmsg.Subcommand == CAPI_REQ)
+						lli_got_fac_req(chanp, &ic->parm.cmsg);
+					break;
+				case CAPI_MANUFACTURER:
+					if (ic->parm.cmsg.Subcommand == CAPI_REQ)
+						lli_got_manufacturer(chanp, csta, &ic->parm.cmsg);
+					break;
+				default:
+					break;
 			}
-			FsmEvent(&chanp->fi, EV_RESUME, ic);
 			break;
 		case (ISDN_CMD_LOCK):
 			HiSax_mod_inc_use_count();
 #ifdef MODULE
-			if (csta->channel[0].debug & 0x400) {
-				jiftime(tmp, jiffies);
-				i = strlen(tmp);
-				sprintf(tmp + i, "   LOCK modcnt %d\n", MOD_USE_COUNT);
-				HiSax_putstatus(csta, tmp);
-			}
+			if (csta->channel[0].debug & 0x400)
+				HiSax_putstatus(csta, "   LOCK ", "modcnt %lx",
+					MOD_USE_COUNT);
 #endif				/* MODULE */
 			break;
 		case (ISDN_CMD_UNLOCK):
 			HiSax_mod_dec_use_count();
 #ifdef MODULE
-			if (csta->channel[0].debug & 0x400) {
-				jiftime(tmp, jiffies);
-				i = strlen(tmp);
-				sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT);
-				HiSax_putstatus(csta, tmp);
-			}
+			if (csta->channel[0].debug & 0x400)
+				HiSax_putstatus(csta, " UNLOCK ", "modcnt %lx",
+					MOD_USE_COUNT);
 #endif				/* MODULE */
 			break;
 		case (ISDN_CMD_IOCTL):
@@ -2081,19 +1670,19 @@
 				case (1):
 					num = *(unsigned int *) ic->parm.num;
 					distr_debug(csta, num);
-					sprintf(tmp, "debugging flags card %d set to %x\n",
+					printk(KERN_DEBUG "HiSax: debugging flags card %d set to %x\n",
 						csta->cardnr + 1, num);
-					HiSax_putstatus(csta, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
+					HiSax_putstatus(csta, "debugging flags ",
+						"card %d set to %x", csta->cardnr + 1, num);
 					break;
 				case (2):
-					num = *(unsigned int *) ic->parm.num; 
-					csta->channel[0].lc_b->delay = num;
-					csta->channel[1].lc_b->delay = num;
-					sprintf(tmp, "delay card %d set to %d ms\n",
+					num = *(unsigned int *) ic->parm.num;
+					csta->channel[0].b_st->l1.delay = num;
+					csta->channel[1].b_st->l1.delay = num;
+					HiSax_putstatus(csta, "delay ", "card %d set to %d ms",
+						csta->cardnr + 1, num);
+					printk(KERN_DEBUG "HiSax: delay card %d set to %d ms\n",
 						csta->cardnr + 1, num);
-					HiSax_putstatus(csta, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
 					break;
 				case (3):
 					for (i = 0; i < *(unsigned int *) ic->parm.num; i++)
@@ -2106,54 +1695,141 @@
 				case (5):	/* set card in leased mode */
 					num = *(unsigned int *) ic->parm.num;
 					if ((num <1) || (num > 2)) {
-						sprintf(tmp, "Set LEASED wrong channel %d\n",
+						HiSax_putstatus(csta, "Set LEASED ",
+							"wrong channel %d", num);
+						printk(KERN_WARNING "HiSax: Set LEASED wrong channel %d\n",
 							num);
-						HiSax_putstatus(csta, tmp);
-						printk(KERN_WARNING "HiSax: %s", tmp);
 					} else {
 						num--;
-						csta->channel[num].leased = 1;
-						csta->channel[num].lc_d->l2_establish = 0;
-						sprintf(tmp, "card %d channel %d set leased mode\n",
+						chanp = csta->channel +num;
+						chanp->leased = 1;
+						HiSax_putstatus(csta, "Card",
+							"%d channel %d set leased mode\n",
 							csta->cardnr + 1, num + 1);
-						HiSax_putstatus(csta, tmp);
-						FsmEvent(&csta->channel[num].lc_d->lcfi, EV_LC_ESTABLISH, NULL);
+						chanp->d_st->l1.l1l2 = leased_l1l2;
+						chanp->d_st->lli.l4l3 = leased_l4l3;
+						chanp->d_st->lli.l4l3(chanp->d_st,
+							DL_ESTABLISH | REQUEST, NULL);
 					}
 					break;
 				case (6):	/* set B-channel test loop */
 					num = *(unsigned int *) ic->parm.num;
 					if (csta->stlist)
-						csta->stlist->ma.manl1(csta->stlist,
-							PH_TESTLOOP_REQ, (void *) num);
+						csta->stlist->l2.l2l1(csta->stlist,
+							PH_TESTLOOP | REQUEST, (void *) (long)num);
+					break;
+				case (7):	/* set card in PTP mode */
+					num = *(unsigned int *) ic->parm.num;
+					if (test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) {
+						printk(KERN_ERR "HiSax PTP mode only with one TEI possible\n");
+					} else if (num) {
+						test_and_set_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
+						test_and_set_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
+						csta->channel[0].d_st->l2.tei = 0;
+						HiSax_putstatus(csta, "set card ", "in PTP mode");
+						printk(KERN_DEBUG "HiSax: set card in PTP mode\n");
+						printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n");
+						csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st,
+							DL_ESTABLISH | REQUEST, NULL);
+					} else {
+						test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag);
+						test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag);
+						HiSax_putstatus(csta, "set card ", "in PTMP mode");
+						printk(KERN_DEBUG "HiSax: set card in PTMP mode\n");
+					}
+					break;
+				case (8):	/* set card in FIXED TEI mode */
+					num = *(unsigned int *) ic->parm.num;
+					chanp = csta->channel + (num & 1);
+					num = num >>1;
+					test_and_set_bit(FLG_FIXED_TEI, &chanp->d_st->l2.flag);
+					chanp->d_st->l2.tei = num;
+					HiSax_putstatus(csta, "set card ", "in FIXED TEI (%d) mode", num);
+					printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n",
+						num);
+					break;
+				case (9): /* load firmware */
+					memcpy(&adr, ic->parm.num, sizeof(ulong));
+					csta->cardmsg(csta, CARD_LOAD_FIRM,
+						(void *) adr);
 					break;
 #ifdef MODULE
 				case (55):
-					while ( MOD_USE_COUNT > 0)
-                                           MOD_DEC_USE_COUNT;
+					MOD_USE_COUNT = 0;
 					HiSax_mod_inc_use_count();
 					break;
 #endif				/* MODULE */
 				case (11):
+					num = csta->debug & DEB_DLOG_HEX;
 					csta->debug = *(unsigned int *) ic->parm.num;
-					sprintf(tmp, "l1 debugging flags card %d set to %x\n",
+					csta->debug |= num;
+					HiSax_putstatus(cards[0].cs, "l1 debugging ",
+						"flags card %d set to %x",
+						csta->cardnr + 1, csta->debug);
+					printk(KERN_DEBUG "HiSax: l1 debugging flags card %d set to %x\n",
 						csta->cardnr + 1, csta->debug);
-					HiSax_putstatus(cards[0].cs, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
 					break;
 				case (13):
 					csta->channel[0].d_st->l3.debug = *(unsigned int *) ic->parm.num;
 					csta->channel[1].d_st->l3.debug = *(unsigned int *) ic->parm.num;
-					sprintf(tmp, "l3 debugging flags card %d set to %x\n",
+					HiSax_putstatus(cards[0].cs, "l3 debugging ",
+						"flags card %d set to %x\n", csta->cardnr + 1,
+						*(unsigned int *) ic->parm.num);
+					printk(KERN_DEBUG "HiSax: l3 debugging flags card %d set to %x\n",
 						csta->cardnr + 1, *(unsigned int *) ic->parm.num);
-					HiSax_putstatus(cards[0].cs, tmp);
-					printk(KERN_DEBUG "HiSax: %s", tmp);
 					break;
+			        case  (10):
+				        i = *(unsigned int *) ic->parm.num;
+					if ((i < 0) || (i > 2))
+					  return(-EINVAL); /* invalid number */
+					return(set_channel_limit(csta, i));
+				        break;
+			        case  (12):
+				        i = *(unsigned int *) ic->parm.num;
+#ifdef CONFIG_HISAX_HFC_PCI
+					if (csta->typ != ISDN_CTYPE_HFC_PCI)
+					  return(-EINVAL);
+					return(hfcpci_set_echo(csta,i));    
+#else
+					return(-EINVAL);    
+#endif
+				        break;
 				default:
 					printk(KERN_DEBUG "HiSax: invalid ioclt %d\n",
 					       (int) ic->arg);
 					return (-EINVAL);
 			}
 			break;
+		
+		case (ISDN_CMD_PROCEED):
+			chanp = csta->channel + ic->arg;
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "PROCEED");
+			FsmEvent(&chanp->fi, EV_PROCEED, NULL);
+			break;
+
+		case (ISDN_CMD_ALERT):
+			chanp = csta->channel + ic->arg;
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "ALERT");
+			FsmEvent(&chanp->fi, EV_ALERT, NULL);
+			break;
+
+		case (ISDN_CMD_REDIR):
+			chanp = csta->channel + ic->arg;
+			if (chanp->debug & 1)
+				link_debug(chanp, 1, "REDIR");
+			chanp->setup = ic->parm.setup;
+			FsmEvent(&chanp->fi, EV_REDIR, NULL);
+			break;
+
+		/* protocol specific io commands */
+	        case (ISDN_CMD_PROT_IO):
+			for (st = csta->stlist; st; st = st->next)
+				if (st->protocol == (ic->arg & 0xFF))
+					return(st->lli.l4l3_proto(st, ic));
+			return(-EINVAL);                     
+			break;
 		default:
 			break;
 	}
@@ -2170,7 +1846,6 @@
 	int len = skb->len;
 	unsigned long flags;
 	struct sk_buff *nskb;
-	char tmp[64];
 
 	if (!csta) {
 		printk(KERN_ERR
@@ -2180,13 +1855,13 @@
 	chanp = csta->channel + chan;
 	st = chanp->b_st;
 	if (!chanp->data_open) {
-		link_debug(chanp, "writebuf: channel not open", 1);
+		link_debug(chanp, 1, "writebuf: channel not open");
 		return -EIO;
 	}
 	if (len > MAX_DATA_SIZE) {
-		sprintf(tmp, "writebuf: packet too large (%d bytes)", len);
-		printk(KERN_WARNING "HiSax_%s !\n", tmp);
-		link_debug(chanp, tmp, 1);
+		link_debug(chanp, 1, "writebuf: packet too large (%d bytes)", len);
+		printk(KERN_WARNING "HiSax_writebuf: packet too large (%d bytes) !\n",
+			len);
 		return -EINVAL;
 	}
 	if (len) {
@@ -2194,25 +1869,24 @@
 			/* Must return 0 here, since this is not an error
 			 * but a temporary lack of resources.
 			 */
-			if (chanp->debug & 0x800) {
-				sprintf(tmp, "writebuf: no buffers for %d bytes", len);
-				link_debug(chanp, tmp, 1);
-			}
+			if (chanp->debug & 0x800)
+				link_debug(chanp, 1, "writebuf: no buffers for %d bytes", len);
 			return 0;
-		}
+		} else if (chanp->debug & 0x800)
+			link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM);
 		save_flags(flags);
 		cli();
 		nskb = skb_clone(skb, GFP_ATOMIC);
 		if (nskb) {
 			if (!ack)
 				nskb->pkt_type = PACKET_NOACK;
-			if (chanp->lc_b->l2_establish)
-				st->l3.l3l2(st, DL_DATA, nskb);
+			if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I)
+				st->l3.l3l2(st, DL_DATA | REQUEST, nskb);
 			else {
 				chanp->bcs->tx_cnt += len;
-				st->l2.l2l1(st, PH_DATA_REQ, nskb);
+				st->l2.l2l1(st, PH_DATA | REQUEST, nskb);
 			}
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_WRITE);
 		} else
 			len = 0;
 		restore_flags(flags);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/cert.c linux.pre11.3/drivers/isdn/hisax/cert.c
--- linux.vanilla/drivers/isdn/hisax/cert.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/cert.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,55 @@
+/* $Id: cert.c,v 2.1 1998/11/15 23:51:15 keil Exp $
+
+ * Author       Karsten Keil (keil@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
+ * $Log: cert.c,v $
+ * Revision 2.1  1998/11/15 23:51:15  keil
+ * certification stuff
+ *
+ * Revision 1.2.2.1  1998/11/03 21:46:37  keil
+ * first version
+ *
+ *
+ */
+ 
+#include <linux/kernel.h>
+
+int
+certification_check(int output) {
+
+#ifdef CERTIFICATION
+#if CERTIFICATION == 0
+	if (output) {
+		printk(KERN_INFO "HiSax: Approval certification valid\n");
+		printk(KERN_INFO "HiSax: Approved with ELSA Quickstep series cards\n");
+		printk(KERN_INFO "HiSax: Approval registration numbers:\n");
+		printk(KERN_INFO "HiSax: German D133361J CETECOM ICT Services GmbH\n");
+		printk(KERN_INFO "HiSax: EU (D133362J) CETECOM ICT Services GmbH\n");
+	}
+	return(0);
+#endif
+#if CERTIFICATION == 1
+	if (output) {
+		printk(KERN_INFO "HiSax: Approval certification failed because of\n");
+		printk(KERN_INFO "HiSax: unauthorized source code changes\n");
+	}
+	return(1);
+#endif
+#if CERTIFICATION == 127
+	if (output) {
+		printk(KERN_INFO "HiSax: Approval certification not possible\n");
+		printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n");
+	}
+	return(2);
+#endif
+#else
+	if (output) {
+		printk(KERN_INFO "HiSax: Certification not verified\n");
+	}
+	return(3);
+#endif
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/config.c linux.pre11.3/drivers/isdn/hisax/config.c
--- linux.vanilla/drivers/isdn/hisax/config.c	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/hisax/config.c	Mon Jul 19 23:59:33 1999
@@ -1,10 +1,67 @@
-/* $Id: config.c,v 2.12 1998/02/11 17:28:02 keil Exp $
+/* $Id: config.c,v 2.28 1999/07/14 12:38:36 werner Exp $
 
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.28  1999/07/14 12:38:36  werner
+ * Added changes for echo channel handling
+ *
+ * Revision 2.27  1999/07/12 21:05:00  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.26  1999/07/08 21:27:17  keil
+ * version 3.2
+ *
+ * Revision 2.25  1999/07/05 23:51:44  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 2.24  1999/07/01 08:11:26  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.23  1999/02/17 10:53:02  cpetig
+ * Added Hisax_closecard to exported symbols.
+ * As indicated by Oliver Schoett <os@sdm.de>.
+ *
+ * If anyone is annoyed by exporting symbols deep inside the code, please
+ * contact me.
+ *
+ * Revision 2.22  1999/02/04 21:41:53  keil
+ * Fix printk msg
+ *
+ * Revision 2.21  1999/02/04 10:48:52  keil
+ * Fix readstat bug
+ *
+ * Revision 2.20  1998/11/15 23:54:28  keil
+ * changes from 2.0
+ *
+ * Revision 2.19  1998/08/13 23:36:18  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.18  1998/07/30 21:01:37  niemann
+ * Fixed Sedlbauer Speed Fax PCMCIA missing isdnl3new
+ *
+ * Revision 2.17  1998/07/15 15:01:26  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.16  1998/05/25 14:10:03  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.15  1998/05/25 12:57:43  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.14  1998/04/15 16:38:25  keil
+ * Add S0Box and Teles PCI support
+ *
+ * Revision 2.13  1998/03/09 23:19:23  keil
+ * Changes for PCMCIA
+ *
  * Revision 2.12  1998/02/11 17:28:02  keil
  * Niccy PnP/PCI support
  *
@@ -55,6 +112,12 @@
 #include <linux/timer.h>
 #include <linux/config.h>
 #include "hisax.h"
+#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#define HISAX_STATUS_BUFSIZE 4096
+#define INCLUDE_INLINE_FUNCS
 
 /*
  * This structure array contains one entry per card. An entry looks
@@ -78,42 +141,107 @@
  *   13 Teleint          p0=irq p1=iobase
  *   14 Teles 16.3c      p0=irq p1=iobase
  *   15 Sedlbauer speed  p0=irq p1=iobase
+ *   15 Sedlbauer PC/104	p0=irq p1=iobase
+ *   15 Sedlbauer speed pci	no parameter
  *   16 USR Sportster internal  p0=irq  p1=iobase
  *   17 MIC card                p0=irq  p1=iobase
  *   18 ELSA Quickstep 1000PCI  no parameter
  *   19 Compaq ISDN S0 ISA card p0=irq  p1=IO0 (HSCX)  p2=IO1 (ISAC) p3=IO2
  *   20 Travers Technologies NETjet PCI card
- *   21 reserved TELES PCI
+ *   21 TELES PCI               no parameter
  *   22 Sedlbauer Speed Star    p0=irq p1=iobase
  *   23 reserved
  *   24 Dr Neuhaus Niccy PnP/PCI card p0=irq p1=IO0 p2=IO1 (PnP only)
- *
- *
+ *   25 Teles S0Box             p0=irq p1=iobase (from isapnp setup)
+ *   26 AVM A1 PCMCIA (Fritz)   p0=irq p1=iobase
+ *   27 AVM PnP/PCI 		p0=irq p1=iobase (PCI no parameter)
+ *   28 Sedlbauer Speed Fax+ 	p0=irq p1=iobase (from isapnp setup)
+ *   29 Siemens I-Surf          p0=irq p1=iobase p2=memory (from isapnp setup)   
+ *   30 ACER P10                p0=irq p1=iobase (from isapnp setup)   
+ *   31 HST Saphir              p0=irq  p1=iobase
+ *   32 Telekom A4T             none
+ *   33 Scitel Quadro		p0=subcontroller (4*S0, subctrl 1...4)
+ *   34	Gazel ISDN cards
+ *   35 HFC 2BDS0 PCI           none
  * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
  *
  *
  */
 
+const char *CardType[] =
+{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP",
+ "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2",
+ "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c",
+ "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
+ "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
+ "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI",
+ "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir",
+ "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI",
+};
+
+void HiSax_closecard(int cardnr);
+
 #ifdef CONFIG_HISAX_ELSA
 #define DEFAULT_CARD ISDN_CTYPE_ELSA
 #define DEFAULT_CFG {0,0,0,0}
-#ifdef MODULE
 int elsa_init_pcmcia(void*, int, int*, int);
+#ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(elsa_init_pcmcia);
-#endif
-#endif
+#else
+static struct symbol_table hisax_syms_elsa = {
+#include <linux/symtab_begin.h>
+	X(elsa_init_pcmcia),
+#include <linux/symtab_end.h>
+};
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* CONFIG_HISAX_ELSA */
+
 #ifdef CONFIG_HISAX_AVM_A1
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_A1
 #define DEFAULT_CFG {10,0x340,0,0}
 #endif
+
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA
+#define DEFAULT_CFG {11,0x170,0,0}
+int avm_a1_init_pcmcia(void*, int, int*, int);
+#ifdef COMPAT_HAS_NEW_SYMTAB
+EXPORT_SYMBOL(avm_a1_init_pcmcia);
+#else
+static struct symbol_table hisax_syms_avm_a1= {
+#include <linux/symtab_begin.h>
+	X(avm_a1_init_pcmcia),
+	X(HiSax_closecard),
+#include <linux/symtab_end.h>
+};
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* CONFIG_HISAX_AVM_A1_PCMCIA */
+
+#ifdef CONFIG_HISAX_FRITZPCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_FRITZPCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
 #ifdef CONFIG_HISAX_16_3
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_16_3
 #define DEFAULT_CFG {15,0x180,0,0}
 #endif
+
+#ifdef CONFIG_HISAX_S0BOX
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_S0BOX
+#define DEFAULT_CFG {7,0x378,0,0}
+#endif
+
 #ifdef CONFIG_HISAX_16_0
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -121,6 +249,13 @@
 #define DEFAULT_CFG {15,0xd0000,0xd80,0}
 #endif
 
+#ifdef CONFIG_HISAX_TELESPCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_TELESPCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
 #ifdef CONFIG_HISAX_IX1MICROR2
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -155,8 +290,16 @@
 #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER
 #define DEFAULT_CFG {11,0x270,0,0}
 int sedl_init_pcmcia(void*, int, int*, int);
+#ifdef COMPAT_HAS_NEW_SYMTAB
 EXPORT_SYMBOL(sedl_init_pcmcia);
-#endif
+#else
+static struct symbol_table hisax_syms_sedl= {
+#include <linux/symtab_begin.h>
+	X(sedl_init_pcmcia),
+#include <linux/symtab_end.h>
+};
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* CONFIG_HISAX_SEDLBAUER */
 
 #ifdef CONFIG_HISAX_SPORTSTER
 #undef DEFAULT_CARD
@@ -179,13 +322,21 @@
 #define DEFAULT_CFG {0,0,0,0}
 #endif
 
-#ifdef CONFIG_HISAX_TELES3C
+#ifdef CONFIG_HISAX_HFCS
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
 #define DEFAULT_CARD ISDN_CTYPE_TELES3C
 #define DEFAULT_CFG {5,0x500,0,0}
 #endif
 
+#ifdef CONFIG_HISAX_HFC_PCI
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_HFC_PCI
+#define DEFAULT_CFG {0,0,0,0}
+#endif
+
+
 #ifdef CONFIG_HISAX_AMD7930
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
@@ -193,20 +344,48 @@
 #define DEFAULT_CFG {12,0x3e0,0,0}
 #endif
 
-#ifdef CONFIG_HISAX_DBRI
+#ifdef CONFIG_HISAX_NICCY
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
-#define DEFAULT_CARD ISDN_CTYPE_DBRI
+#define DEFAULT_CARD ISDN_CTYPE_NICCY
 #define DEFAULT_CFG {0,0x0,0,0}
 #endif
 
-#ifdef CONFIG_HISAX_NICCY
+#ifdef CONFIG_HISAX_ISURF
 #undef DEFAULT_CARD
 #undef DEFAULT_CFG
-#define DEFAULT_CARD ISDN_CTYPE_NICCY
+#define DEFAULT_CARD ISDN_CTYPE_ISURF
+#define DEFAULT_CFG {5,0x100,0xc8000,0}
+#endif
+
+#ifdef CONFIG_HISAX_HSTSAPHIR
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_HSTSAPHIR
+#define DEFAULT_CFG {5,0x250,0,0}
+#endif
+
+#ifdef CONFIG_HISAX_BKM_A4T            
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_BKM_A4T
 #define DEFAULT_CFG {0,0x0,0,0}
 #endif
 
+#ifdef CONFIG_HISAX_SCT_QUADRO
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_SCT_QUADRO
+#define DEFAULT_CFG {1,0x0,0,0}
+#endif
+
+#ifdef CONFIG_HISAX_GAZEL
+#undef DEFAULT_CARD
+#undef DEFAULT_CFG
+#define DEFAULT_CARD ISDN_CTYPE_GAZEL
+#define DEFAULT_CFG {15,0x180,0,0}
+#endif
+
 #ifdef CONFIG_HISAX_1TR6
 #define DEFAULT_PROTO ISDN_PTYPE_1TR6
 #define DEFAULT_PROTO_NAME "1TR6"
@@ -232,10 +411,10 @@
 #endif
 
 #define FIRST_CARD { \
-  DEFAULT_CARD, \
-  DEFAULT_PROTO, \
-  DEFAULT_CFG, \
-  NULL, \
+	DEFAULT_CARD, \
+	DEFAULT_PROTO, \
+	DEFAULT_CFG, \
+	NULL, \
 }
 
 #define EMPTY_CARD	{0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
@@ -250,29 +429,20 @@
 	EMPTY_CARD,
 	EMPTY_CARD,
 	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
-	EMPTY_CARD,
 };
 
-static char HiSaxID[96] HISAX_INITDATA = "\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\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \
+static char HiSaxID[64] HISAX_INITDATA = "\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\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\0\0\0\0\0\0\0\0";
+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 char *HiSax_id HISAX_INITDATA = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
 static int type[] HISAX_INITDATA =
-{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 int protocol[] HISAX_INITDATA =
-{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 int io[] HISAX_INITDATA =
-{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+{0, 0, 0, 0, 0, 0, 0, 0};
 #undef IO0_IO1
 #ifdef CONFIG_HISAX_16_3
 #define IO0_IO1
@@ -283,29 +453,30 @@
 #endif
 #ifdef IO0_IO1
 static int io0[] HISAX_INITDATA =
-{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 int io1[] HISAX_INITDATA =
-{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
 static int irq[] HISAX_INITDATA =
-{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 int mem[] HISAX_INITDATA =
-{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 char *id HISAX_INITDATA = HiSaxID;
 
+#ifdef COMPAT_HAS_NEW_SYMTAB
 MODULE_AUTHOR("Karsten Keil");
-MODULE_PARM(type, "1-3i");
-MODULE_PARM(protocol, "1-2i");
+MODULE_PARM(type, "1-8i");
+MODULE_PARM(protocol, "1-8i");
 MODULE_PARM(io, "1-8i");
-MODULE_PARM(irq, "1-2i");
-MODULE_PARM(mem, "1-12i");
+MODULE_PARM(irq, "1-8i");
+MODULE_PARM(mem, "1-8i");
 MODULE_PARM(id, "s");
 #ifdef CONFIG_HISAX_16_3	/* For Creatix/Teles PnP */
 MODULE_PARM(io0, "1-8i");
 MODULE_PARM(io1, "1-8i");
-#endif
-
-#endif
+#endif /* CONFIG_HISAX_16_3 */
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* MODULE */
 
 int nrcards;
 
@@ -333,23 +504,25 @@
 HISAX_INITFUNC(void
 HiSaxVersion(void))
 {
-	char tmp[64], rev[64];
-	char *r = rev;
+	char tmp[64];
 
+	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
+#ifdef MODULE
+	printk(KERN_INFO "HiSax: Version 3.2a (module)\n");
+#else
+	printk(KERN_INFO "HiSax: Version 3.2a (kernel)\n");
+#endif
 	strcpy(tmp, l1_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
 	strcpy(tmp, l2_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Layer2 Revision %s\n", HiSax_getrev(tmp));
+	strcpy(tmp, tei_revision);
+	printk(KERN_INFO "HiSax: TeiMgr Revision %s\n", HiSax_getrev(tmp));
 	strcpy(tmp, l3_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
+	printk(KERN_INFO "HiSax: Layer3 Revision %s\n", HiSax_getrev(tmp));
 	strcpy(tmp, lli_revision);
-	r += sprintf(r, "%s/", HiSax_getrev(tmp));
-	strcpy(tmp, tei_revision);
-	r += sprintf(r, "%s", HiSax_getrev(tmp));
-
-	printk(KERN_INFO "HiSax: Driver for Siemens chip set ISDN cards\n");
-	printk(KERN_INFO "HiSax: Version 2.8\n");
-	printk(KERN_INFO "HiSax: Revisions %s\n", rev);
+	printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp));
+	certification_check(1);
 }
 
 void
@@ -375,7 +548,7 @@
 	argc = ints[0];
 	i = 0;
 	j = 1;
-	while (argc && (i < 16)) {
+	while (argc && (i < HISAX_MAX_CARDS)) {
 		if (argc) {
 			cards[i].typ = ints[j];
 			j++;
@@ -413,32 +586,864 @@
 }
 #endif
 
+#if CARD_TELES0
+extern int setup_teles0(struct IsdnCard *card);
+#endif
+
+#if CARD_TELES3
+extern int setup_teles3(struct IsdnCard *card);
+#endif
+
+#if CARD_S0BOX
+extern int setup_s0box(struct IsdnCard *card);
+#endif
+
+#if CARD_TELESPCI
+extern int setup_telespci(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1
+extern int setup_avm_a1(struct IsdnCard *card);
+#endif
+
+#if CARD_AVM_A1_PCMCIA
+extern int setup_avm_a1_pcmcia(struct IsdnCard *card);
+#endif
+
+#if CARD_FRITZPCI
+extern int setup_avm_pcipnp(struct IsdnCard *card);
+#endif
+
+#if CARD_ELSA
+extern int setup_elsa(struct IsdnCard *card);
+#endif
+
+#if CARD_IX1MICROR2
+extern int setup_ix1micro(struct IsdnCard *card);
+#endif
+
+#if CARD_DIEHLDIVA
+extern	int  setup_diva(struct IsdnCard *card);
+#endif
+
+#if CARD_ASUSCOM
+extern int setup_asuscom(struct IsdnCard *card);
+#endif
+
+#if CARD_TELEINT
+extern int setup_TeleInt(struct IsdnCard *card);
+#endif
+
+#if CARD_SEDLBAUER
+extern int setup_sedlbauer(struct IsdnCard *card);
+#endif
+
+#if CARD_SPORTSTER
+extern int setup_sportster(struct IsdnCard *card);
+#endif
+
+#if CARD_MIC
+extern int setup_mic(struct IsdnCard *card);
+#endif
+
+#if CARD_NETJET
+extern int setup_netjet(struct IsdnCard *card);
+#endif
+
+#if CARD_HFCS
+extern int setup_hfcs(struct IsdnCard *card);
+#endif
+
+#if CARD_HFC_PCI
+extern int setup_hfcpci(struct IsdnCard *card);
+#endif
+
+#if CARD_AMD7930
+extern int setup_amd7930(struct IsdnCard *card);
+#endif
+
+#if CARD_NICCY
+extern int setup_niccy(struct IsdnCard *card);
+#endif
+
+#if CARD_ISURF
+extern int setup_isurf(struct IsdnCard *card);
+#endif
+
+#if CARD_HSTSAPHIR
+extern int setup_saphir(struct IsdnCard *card);
+#endif
+
+#if CARD_TESTEMU
+extern int setup_testemu(struct IsdnCard *card);
+#endif
+
+#if	CARD_BKM_A4T
+extern int setup_bkm_a4t(struct IsdnCard *card);
+#endif
+
+#if	CARD_SCT_QUADRO
+extern int setup_sct_quadro(struct IsdnCard *card);
+#endif
+
+#if CARD_GAZEL
+extern int setup_gazel(struct IsdnCard *card);
+#endif
+
+/*
+ * Find card with given driverId
+ */
+static inline struct IsdnCardState
+*hisax_findcard(int driverid)
+{
+	int i;
+
+	for (i = 0; i < nrcards; i++)
+		if (cards[i].cs)
+			if (cards[i].cs->myid == driverid)
+				return (cards[i].cs);
+	return (NULL);
+}
+
+/*
+ * Find card with given card number
+ */
+struct IsdnCardState
+*hisax_get_card(int cardnr)
+{
+	if ((cardnr <= nrcards) && (cardnr>0))
+		if (cards[cardnr-1].cs)
+			return (cards[cardnr-1].cs);
+	return (NULL);
+}
+
+int
+HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
+{
+	int count,cnt;
+	u_char *p = buf;
+	struct IsdnCardState *cs = hisax_findcard(id);
+
+	if (cs) {
+		if (len > HISAX_STATUS_BUFSIZE) {
+			printk(KERN_WARNING "HiSax: status overflow readstat %d/%d\n",
+				len, HISAX_STATUS_BUFSIZE);
+		}
+		count = cs->status_end - cs->status_read +1;
+		if (count >= len)
+			count = len;
+		if (user)
+			copy_to_user(p, cs->status_read, count);
+		else
+			memcpy(p, cs->status_read, count);
+		cs->status_read += count;
+		if (cs->status_read > cs->status_end)
+			cs->status_read = cs->status_buf;
+		p += count;
+		count = len - count;
+		while (count) {
+			if (count > HISAX_STATUS_BUFSIZE)
+				cnt = HISAX_STATUS_BUFSIZE;
+			else
+				cnt = count;
+			if (user)
+				copy_to_user(p, cs->status_read, cnt);
+			else
+				memcpy(p, cs->status_read, cnt);
+			p += cnt;
+			cs->status_read += cnt % HISAX_STATUS_BUFSIZE;
+			count -= cnt;
+		}
+		return len;
+	} else {
+		printk(KERN_ERR
+		 "HiSax: if_readstatus called with invalid driverId!\n");
+		return -ENODEV;
+	}
+}
+
+inline int
+jiftime(char *s, long mark)
+{
+	s += 8;
+
+	*s-- = '\0';
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = '.';
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = mark % 6 + '0';
+	mark /= 6;
+	*s-- = ':';
+	*s-- = mark % 10 + '0';
+	mark /= 10;
+	*s-- = mark % 10 + '0';
+	return(8);
+}
+
+static u_char tmpbuf[HISAX_STATUS_BUFSIZE];
+
+void
+VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args)
+{
+/* if head == NULL the fmt contains the full info */
+
+	long flags;
+	int count, i;
+	u_char *p;
+	isdn_ctrl ic;
+	int len;
+
+	save_flags(flags);
+	cli();
+	p = tmpbuf;
+	if (head) {
+		p += jiftime(p, jiffies);
+		p += sprintf(p, " %s", head);
+		p += vsprintf(p, fmt, args);
+		*p++ = '\n';
+		*p = 0;
+		len = p - tmpbuf;
+		p = tmpbuf;
+	} else {
+		p = fmt;
+		len = strlen(fmt);
+	}
+	if (!cs) {
+		printk(KERN_WARNING "HiSax: No CardStatus for message %s", p);
+		restore_flags(flags);
+		return;
+	}
+	if (len > HISAX_STATUS_BUFSIZE) {
+		printk(KERN_WARNING "HiSax: status overflow %d/%d\n",
+			len, HISAX_STATUS_BUFSIZE);
+		restore_flags(flags);
+		return;
+	}
+	count = len;
+	i = cs->status_end - cs->status_write +1;
+	if (i >= len)
+		i = len;
+	len -= i;
+	memcpy(cs->status_write, p, i);
+	cs->status_write += i;
+	if (cs->status_write > cs->status_end)
+		cs->status_write = cs->status_buf;
+	p += i;
+	if (len) {
+		memcpy(cs->status_write, p, len);
+		cs->status_write += len;
+	}
+#ifdef KERNELSTACK_DEBUG
+	i = (ulong)&len - current->kernel_stack_page;
+	sprintf(tmpbuf, "kstack %s %lx use %ld\n", current->comm,
+		current->kernel_stack_page, i);
+	len = strlen(tmpbuf);
+	for (p = tmpbuf, i = len; i > 0; i--, p++) {
+		*cs->status_write++ = *p;
+		if (cs->status_write > cs->status_end)
+			cs->status_write = cs->status_buf;
+		count++;
+	}
+#endif
+	restore_flags(flags);
+	if (count) {
+		ic.command = ISDN_STAT_STAVAIL;
+		ic.driver = cs->myid;
+		ic.arg = count;
+		cs->iif.statcallb(&ic);
+	}
+}
+
+void
+HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	VHiSax_putstatus(cs, head, fmt, args);
+	va_end(args);
+}
+
+int
+ll_run(struct IsdnCardState *cs)
+{
+	long flags;
+	isdn_ctrl ic;
+
+	save_flags(flags);
+	cli();
+	ic.driver = cs->myid;
+	ic.command = ISDN_STAT_RUN;
+	cs->iif.statcallb(&ic);
+	restore_flags(flags);
+	return 0;
+}
+
+void
+ll_stop(struct IsdnCardState *cs)
+{
+	isdn_ctrl ic;
+
+	ic.command = ISDN_STAT_STOP;
+	ic.driver = cs->myid;
+	cs->iif.statcallb(&ic);
+	CallcFreeChan(cs);
+}
+
+static void
+ll_unload(struct IsdnCardState *cs)
+{
+	isdn_ctrl ic;
+
+	ic.command = ISDN_STAT_UNLOAD;
+	ic.driver = cs->myid;
+	cs->iif.statcallb(&ic);
+	if (cs->status_buf)
+		kfree(cs->status_buf);
+	cs->status_read = NULL;
+	cs->status_write = NULL;
+	cs->status_end = NULL;
+	kfree(cs->dlog);
+}
+
+static void
+closecard(int cardnr)
+{
+	struct IsdnCardState *csta = cards[cardnr].cs;
+
+	if (csta->bcs->BC_Close != NULL) {
+		csta->bcs->BC_Close(csta->bcs + 1);
+		csta->bcs->BC_Close(csta->bcs);
+	}
+
+	discard_queue(&csta->rq);
+	discard_queue(&csta->sq);
+	if (csta->rcvbuf) {
+		kfree(csta->rcvbuf);
+		csta->rcvbuf = NULL;
+	}
+	if (csta->tx_skb) {
+		idev_kfree_skb(csta->tx_skb, FREE_WRITE);
+		csta->tx_skb = NULL;
+	}
+	if (csta->DC_Close != NULL) {
+		csta->DC_Close(csta);
+	}
+	csta->cardmsg(csta, CARD_RELEASE, NULL);
+	if (csta->dbusytimer.function != NULL)
+		del_timer(&csta->dbusytimer);
+	ll_unload(csta);
+}
+
+HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
+{
+	int irq_cnt, cnt = 3;
+	long flags;
+
+	if (!cs->irq)
+		return(cs->cardmsg(cs, CARD_INIT, NULL));
+	save_flags(flags);
+	cli();
+	irq_cnt = kstat_irqs(cs->irq);
+	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
+		irq_cnt);
+	if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) {
+		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
+			cs->irq);
+		restore_flags(flags);
+		return(1);
+	}
+	while (cnt) {
+		cs->cardmsg(cs, CARD_INIT, NULL);
+		sti();
+		current->state = TASK_INTERRUPTIBLE;
+		/* Timeout 10ms */
+		schedule_timeout((10*HZ)/1000);
+		restore_flags(flags);
+		printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
+			cs->irq, kstat_irqs(cs->irq));
+		if (kstat_irqs(cs->irq) == irq_cnt) {
+			printk(KERN_WARNING
+			       "%s: IRQ(%d) getting no interrupts during init %d\n",
+			       CardType[cs->typ], cs->irq, 4 - cnt);
+			if (cnt == 1) {
+				free_irq(cs->irq, cs);
+				return (2);
+			} else {
+				cs->cardmsg(cs, CARD_RESET, NULL);
+				cnt--;
+			}
+		} else {
+			cs->cardmsg(cs, CARD_TEST, NULL);
+			return(0);
+		}
+	}
+	restore_flags(flags);
+	return(3);
+}
+
+HISAX_INITFUNC(static int
+checkcard(int cardnr, char *id, int *busy_flag))
+{
+	long flags;
+	int ret = 0;
+	struct IsdnCard *card = cards + cardnr;
+	struct IsdnCardState *cs;
+
+	save_flags(flags);
+	cli();
+	if (!(cs = (struct IsdnCardState *)
+		kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for IsdnCardState(card %d)\n",
+		       cardnr + 1);
+		restore_flags(flags);
+		return (0);
+	}
+	memset(cs, 0, sizeof(struct IsdnCardState));
+	card->cs = cs;
+	cs->chanlimit = 2; /* maximum B-channel number */
+	cs->logecho = 0; /* No echo logging */
+	cs->cardnr = cardnr;
+	cs->debug = L1_DEB_WARN;
+	cs->HW_Flags = 0;
+	cs->busy_flag = busy_flag;
+	cs->irq_flags = I4L_IRQ_FLAG;
+#if TEI_PER_CARD
+#else
+	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#endif
+	cs->protocol = card->protocol;
+
+	if ((card->typ > 0) && (card->typ <= ISDN_CTYPE_COUNT)) {
+		if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for dlog(card %d)\n",
+				cardnr + 1);
+			restore_flags(flags);
+			return (0);
+		}
+		if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for status_buf(card %d)\n",
+				cardnr + 1);
+			kfree(cs->dlog);
+			restore_flags(flags);
+			return (0);
+		}
+		cs->stlist = NULL;
+		cs->status_read = cs->status_buf;
+		cs->status_write = cs->status_buf;
+		cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
+		cs->typ = card->typ;
+		strcpy(cs->iif.id, id);
+		cs->iif.channels = 2;
+		cs->iif.maxbufsize = MAX_DATA_SIZE;
+		cs->iif.hl_hdrlen = MAX_HEADER_LEN;
+		cs->iif.features =
+			ISDN_FEATURE_L2_X75I |
+			ISDN_FEATURE_L2_HDLC |
+//			ISDN_FEATURE_L2_MODEM |
+			ISDN_FEATURE_L2_TRANS |
+			ISDN_FEATURE_L3_TRANS |
+#ifdef	CONFIG_HISAX_1TR6
+			ISDN_FEATURE_P_1TR6 |
+#endif
+#ifdef	CONFIG_HISAX_EURO
+			ISDN_FEATURE_P_EURO |
+#endif
+#ifdef	CONFIG_HISAX_NI1
+			ISDN_FEATURE_P_NI1 |
+#endif
+			0;
+
+		cs->iif.command = HiSax_command;
+		cs->iif.writecmd = NULL;
+		cs->iif.writebuf_skb = HiSax_writebuf_skb;
+		cs->iif.readstat = HiSax_readstatus;
+		register_isdn(&cs->iif);
+		cs->myid = cs->iif.channels;
+		printk(KERN_INFO
+			"HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
+			(card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
+			(card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
+			(card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
+			(card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
+			"NONE", cs->iif.id, cs->myid);
+		switch (card->typ) {
+#if CARD_TELES0
+			case ISDN_CTYPE_16_0:
+			case ISDN_CTYPE_8_0:
+				ret = setup_teles0(card);
+				break;
+#endif
+#if CARD_TELES3
+			case ISDN_CTYPE_16_3:
+			case ISDN_CTYPE_PNP:
+			case ISDN_CTYPE_TELESPCMCIA:
+			case ISDN_CTYPE_COMPAQ_ISA:
+				ret = setup_teles3(card);
+				break;
+#endif
+#if CARD_S0BOX
+			case ISDN_CTYPE_S0BOX:
+				ret = setup_s0box(card);
+				break;
+#endif
+#if CARD_TELESPCI
+			case ISDN_CTYPE_TELESPCI:
+				ret = setup_telespci(card);
+				break;
+#endif
+#if CARD_AVM_A1
+			case ISDN_CTYPE_A1:
+				ret = setup_avm_a1(card);
+				break;
+#endif
+#if CARD_AVM_A1_PCMCIA
+			case ISDN_CTYPE_A1_PCMCIA:
+				ret = setup_avm_a1_pcmcia(card);
+				break;
+#endif
+#if CARD_FRITZPCI
+			case ISDN_CTYPE_FRITZPCI:
+				ret = setup_avm_pcipnp(card);
+				break;
+#endif
+#if CARD_ELSA
+			case ISDN_CTYPE_ELSA:
+			case ISDN_CTYPE_ELSA_PNP:
+			case ISDN_CTYPE_ELSA_PCMCIA:
+			case ISDN_CTYPE_ELSA_PCI:
+				ret = setup_elsa(card);
+				break;
+#endif
+#if CARD_IX1MICROR2
+			case ISDN_CTYPE_IX1MICROR2:
+				ret = setup_ix1micro(card);
+				break;
+#endif
+#if CARD_DIEHLDIVA
+			case ISDN_CTYPE_DIEHLDIVA:
+				ret = setup_diva(card);
+				break;
+#endif
+#if CARD_ASUSCOM
+			case ISDN_CTYPE_ASUSCOM:
+				ret = setup_asuscom(card);
+				break;
+#endif
+#if CARD_TELEINT
+			case ISDN_CTYPE_TELEINT:
+				ret = setup_TeleInt(card);
+				break;
+#endif
+#if CARD_SEDLBAUER
+			case ISDN_CTYPE_SEDLBAUER:
+			case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+			case ISDN_CTYPE_SEDLBAUER_FAX:
+				ret = setup_sedlbauer(card);
+				break;
+#endif
+#if CARD_SPORTSTER
+			case ISDN_CTYPE_SPORTSTER:
+				ret = setup_sportster(card);
+				break;
+#endif
+#if CARD_MIC
+			case ISDN_CTYPE_MIC:
+				ret = setup_mic(card);
+				break;
+#endif
+#if CARD_NETJET
+			case ISDN_CTYPE_NETJET:
+				ret = setup_netjet(card);
+				break;
+#endif
+#if CARD_HFCS
+			case ISDN_CTYPE_TELES3C:
+			case ISDN_CTYPE_ACERP10:
+				ret = setup_hfcs(card);
+				break;
+#endif
+#if CARD_HFC_PCI
+		        case ISDN_CTYPE_HFC_PCI: 
+				ret = setup_hfcpci(card);
+				break;
+#endif
+#if CARD_NICCY
+			case ISDN_CTYPE_NICCY:
+				ret = setup_niccy(card);
+				break;
+#endif
+#if CARD_AMD7930
+			case ISDN_CTYPE_AMD7930:
+				ret = setup_amd7930(card);
+				break;
+#endif
+#if CARD_ISURF
+			case ISDN_CTYPE_ISURF:
+				ret = setup_isurf(card);
+				break;
+#endif
+#if CARD_HSTSAPHIR
+			case ISDN_CTYPE_HSTSAPHIR:
+				ret = setup_saphir(card);
+				break;
+#endif
+#if CARD_TESTEMU
+			case ISDN_CTYPE_TESTEMU:
+				ret = setup_testemu(card);
+				break;
+#endif
+#if	CARD_BKM_A4T       
+           	case ISDN_CTYPE_BKM_A4T:
+	        	ret = setup_bkm_a4t(card);
+			break;
+#endif
+#if	CARD_SCT_QUADRO
+	        case ISDN_CTYPE_SCT_QUADRO:
+    			ret = setup_sct_quadro(card);
+			break;
+#endif
+#if CARD_GAZEL
+ 		case ISDN_CTYPE_GAZEL:
+ 			ret = setup_gazel(card);
+ 			break;
+#endif
+		default:
+			printk(KERN_WARNING
+				"HiSax: Support for %s Card not selected\n",
+				CardType[card->typ]);
+			ll_unload(cs);
+			restore_flags(flags);
+			return (0);
+		}
+	} else {
+		printk(KERN_WARNING
+		       "HiSax: Card Type %d out of range\n",
+		       card->typ);
+		restore_flags(flags);
+		return (0);
+	}
+	if (!ret) {
+		ll_unload(cs);
+		restore_flags(flags);
+		return (0);
+	}
+	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for isac rcvbuf\n");
+		return (1);
+	}
+	cs->rcvidx = 0;
+	cs->tx_skb = NULL;
+	cs->tx_cnt = 0;
+	cs->event = 0;
+	cs->tqueue.next = 0;
+	cs->tqueue.sync = 0;
+	cs->tqueue.data = cs;
+
+	skb_queue_head_init(&cs->rq);
+	skb_queue_head_init(&cs->sq);
+
+	init_bcstate(cs, 0);
+	init_bcstate(cs, 1);
+	ret = init_card(cs);
+	if (ret) {
+		closecard(cardnr);
+		restore_flags(flags);
+		return (0);
+	}
+	init_tei(cs, cs->protocol);
+	CallcNewChan(cs);
+	/* ISAR needs firmware download first */
+	if (!test_bit(HW_ISAR, &cs->HW_Flags))
+		ll_run(cs);
+	restore_flags(flags);
+	return (1);
+}
+
+HISAX_INITFUNC(void
+HiSax_shiftcards(int idx))
+{
+	int i;
+
+	for (i = idx; i < (HISAX_MAX_CARDS - 1); i++)
+		memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
+}
+
+HISAX_INITFUNC(int
+HiSax_inithardware(int *busy_flag))
+{
+	int foundcards = 0;
+	int i = 0;
+	int t = ',';
+	int flg = 0;
+	char *id;
+	char *next_id = HiSax_id;
+	char ids[20];
+
+	if (strchr(HiSax_id, ','))
+		t = ',';
+	else if (strchr(HiSax_id, '%'))
+		t = '%';
+
+	while (i < nrcards) {
+		if (cards[i].typ < 1)
+			break;
+		id = next_id;
+		if ((next_id = strchr(id, t))) {
+			*next_id++ = 0;
+			strcpy(ids, id);
+			flg = i + 1;
+		} else {
+			next_id = id;
+			if (flg >= i)
+				strcpy(ids, id);
+			else
+				sprintf(ids, "%s%d", id, i);
+		}
+		if (checkcard(i, ids, busy_flag)) {
+			foundcards++;
+			i++;
+		} else {
+			printk(KERN_WARNING "HiSax: Card %s not installed !\n",
+			       CardType[cards[i].typ]);
+			if (cards[i].cs)
+				kfree((void *) cards[i].cs);
+			cards[i].cs = NULL;
+			HiSax_shiftcards(i);
+		}
+	}
+	return foundcards;
+}
+
+void
+HiSax_closecard(int cardnr)
+{
+	int 	i,last=nrcards - 1;
+
+	if (cardnr>last)
+		return;
+	if (cards[cardnr].cs) {
+		ll_stop(cards[cardnr].cs);
+		release_tei(cards[cardnr].cs);
+		closecard(cardnr);
+		if (cards[cardnr].cs->irq)
+			free_irq(cards[cardnr].cs->irq, cards[cardnr].cs);
+		kfree((void *) cards[cardnr].cs);
+		cards[cardnr].cs = NULL;
+	}
+	i = cardnr;
+	while (i!=last) {
+		cards[i] = cards[i+1];
+		i++;
+	}
+	nrcards--;
+}
+
+void
+HiSax_reportcard(int cardnr)
+{
+	struct IsdnCardState *cs = cards[cardnr].cs;
+	struct PStack *stptr;
+	struct l3_process *pc;
+	int j, i = 1;
+
+	printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
+	printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
+	printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
+	printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
+		(ulong) & HiSax_reportcard);
+	printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
+	printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc0 flg %x\n",
+		cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag);
+	printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n",
+		cs->bcs[0].mode, cs->bcs[0].channel);
+	printk(KERN_DEBUG "HiSax: bcs 1 mode %d ch%d\n",
+		cs->bcs[1].mode, cs->bcs[1].channel);
+	printk(KERN_DEBUG "HiSax: cs setstack_d 0x%lX\n", (ulong) cs->setstack_d);
+	printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist));
+	stptr = cs->stlist;
+	while (stptr != NULL) {
+		printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr);
+		printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp);
+		printk(KERN_DEBUG "HiSax: dst%d l1.l1hw 0x%lX\n", i, (ulong) stptr->l1.l1hw);
+		printk(KERN_DEBUG "HiSax:   tei %d sapi %d\n",
+		       stptr->l2.tei, stptr->l2.sap);
+		printk(KERN_DEBUG "HiSax:      man 0x%lX\n", (ulong) stptr->ma.layer);
+		pc = stptr->l3.proc;
+		while (pc) {
+			printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref,
+			       (ulong) pc);
+			printk(KERN_DEBUG "HiSax:    state %d  st 0x%lX chan 0x%lX\n",
+			    pc->state, (ulong) pc->st, (ulong) pc->chan);
+			pc = pc->next;
+		}
+		stptr = stptr->next;
+		i++;
+	}
+	for (j = 0; j < 2; j++) {
+		printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j,
+		       (ulong) & cs->channel[j]);
+		stptr = cs->channel[j].b_st;
+		i = 1;
+		while (stptr != NULL) {
+			printk(KERN_DEBUG "HiSax:  b_st%d 0x%lX\n", i, (ulong) stptr);
+			printk(KERN_DEBUG "HiSax:    man 0x%lX\n", (ulong) stptr->ma.layer);
+			stptr = stptr->next;
+			i++;
+		}
+	}
+}
+
+
 __initfunc(int
 HiSax_init(void))
 {
 	int i;
-	
+
 #ifdef MODULE
 	int nzproto = 0;
 #ifdef CONFIG_HISAX_ELSA
 	if (type[0] == ISDN_CTYPE_ELSA_PCMCIA) {
 		/* we have exported  and return in this case */
+#ifndef COMPAT_HAS_NEW_SYMTAB
+		register_symtab(&hisax_syms_elsa);
+#endif
 		return 0;
 	}
 #endif
 #ifdef CONFIG_HISAX_SEDLBAUER
 	if (type[0] == ISDN_CTYPE_SEDLBAUER_PCMCIA) {
 		/* we have to export  and return in this case */
+#ifndef COMPAT_HAS_NEW_SYMTAB
+		register_symtab(&hisax_syms_sedl);
+#endif
+		return 0;
+	}
+#endif
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+	if (type[0] == ISDN_CTYPE_A1_PCMCIA) {
+		/* we have to export  and return in this case */
+#ifndef COMPAT_HAS_NEW_SYMTAB
+		register_symtab(&hisax_syms_avm_a1);
+#endif
 		return 0;
 	}
 #endif
 #endif
-	HiSaxVersion();
 	nrcards = 0;
+	HiSaxVersion();
 #ifdef MODULE
 	if (id)			/* If id= string used */
 		HiSax_id = id;
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].typ = type[i];
 		if (protocol[i]) {
 			cards[i].protocol = protocol[i];
@@ -476,6 +1481,7 @@
 			case ISDN_CTYPE_16_3:
 			case ISDN_CTYPE_TELESPCMCIA:
 			case ISDN_CTYPE_A1:
+			case ISDN_CTYPE_A1_PCMCIA:
 			case ISDN_CTYPE_ELSA_PNP:
 			case ISDN_CTYPE_ELSA_PCMCIA:
 			case ISDN_CTYPE_IX1MICROR2:
@@ -484,16 +1490,32 @@
 			case ISDN_CTYPE_TELEINT:
 			case ISDN_CTYPE_SEDLBAUER:
 			case ISDN_CTYPE_SEDLBAUER_PCMCIA:
+			case ISDN_CTYPE_SEDLBAUER_FAX:
 			case ISDN_CTYPE_SPORTSTER:
 			case ISDN_CTYPE_MIC:
 			case ISDN_CTYPE_TELES3C:
+			case ISDN_CTYPE_ACERP10:
+			case ISDN_CTYPE_S0BOX:
+			case ISDN_CTYPE_FRITZPCI:
+			case ISDN_CTYPE_HSTSAPHIR:
+			case ISDN_CTYPE_GAZEL:
+				cards[i].para[0] = irq[i];
+				cards[i].para[1] = io[i];
+				break;
+			case ISDN_CTYPE_ISURF:
 				cards[i].para[0] = irq[i];
 				cards[i].para[1] = io[i];
+				cards[i].para[2] = mem[i];
 				break;
 			case ISDN_CTYPE_ELSA_PCI:
 			case ISDN_CTYPE_NETJET:
 			case ISDN_CTYPE_AMD7930:
-			case ISDN_CTYPE_DBRI:
+			case ISDN_CTYPE_TELESPCI:
+				break;
+			case ISDN_CTYPE_BKM_A4T:
+	  		   	break;
+			case ISDN_CTYPE_SCT_QUADRO:
+	          	cards[i].para[0] = irq[i];
 				break;
 		}
 	}
@@ -507,29 +1529,32 @@
 		HiSax_id = HiSaxID;
 	if (!HiSaxID[0])
 		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < 16; i++)
+	for (i = 0; i < HISAX_MAX_CARDS; i++)
 		if (cards[i].typ > 0)
 			nrcards++;
 	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
 	       nrcards, (nrcards > 1) ? "s" : "");
 
 	CallcNew();
+	Isdnl3New();
 	Isdnl2New();
 	TeiNew();
 	Isdnl1New();
 	if (HiSax_inithardware(NULL)) {
 		/* Install only, if at least one card found */
-		/* No symbols to export, hide all symbols */
-
 #ifdef MODULE
-		EXPORT_NO_SYMBOLS;
+#ifndef COMPAT_HAS_NEW_SYMTAB
+		/* No symbols to export, hide all symbols */
+		register_symtab(NULL);
 		printk(KERN_INFO "HiSax: module installed\n");
-#endif
+#endif /* COMPAT_HAS_NEW_SYMTAB */
+#endif /* MODULE */
 		return (0);
 	} else {
 		Isdnl1Free();
 		TeiFree();
 		Isdnl2Free();
+		Isdnl3Free();
 		CallcFree();
 		return -EIO;
 	}
@@ -539,13 +1564,27 @@
 void
 cleanup_module(void)
 {
-	HiSax_closehardware();
+	int cardnr = nrcards -1;
+	long flags;
+
+	save_flags(flags);
+	cli();
+	while(cardnr>=0)
+		HiSax_closecard(cardnr--);
+	Isdnl1Free();
+	TeiFree();
+	Isdnl2Free();
+	Isdnl3Free();
+	CallcFree();
+	restore_flags(flags);
 	printk(KERN_INFO "HiSax module removed\n");
 }
+#endif
 
 #ifdef CONFIG_HISAX_ELSA
 int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
 {
+#ifdef MODULE
 	int i;
 	int nzproto = 0;
 
@@ -553,10 +1592,10 @@
 	HiSaxVersion();
 	if (id)			/* If id= string used */
 		HiSax_id = id;
-	/* Initialize all 16 structs, even though we only accept
+	/* Initialize all 8 structs, even though we only accept
 	   two pcmcia cards
 	   */
-	for (i = 0; i < 16; i++) {
+	for (i = 0; i < HISAX_MAX_CARDS; i++) {
 		cards[i].para[0] = irq[i];
 		cards[i].para[1] = io[i];
 		cards[i].typ = type[i];
@@ -575,7 +1614,7 @@
 		HiSax_id = HiSaxID;
 	if (!HiSaxID[0])
 		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < 16; i++)
+	for (i = 0; i < HISAX_MAX_CARDS; i++)
 		if (cards[i].typ > 0)
 			nrcards++;
 	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
@@ -583,16 +1622,71 @@
 
 	Isdnl1New();
 	CallcNew();
+	Isdnl3New();
 	Isdnl2New();
 	TeiNew();
 	HiSax_inithardware(busy_flag);
 	printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
 	return (0);
 }
 #endif
+
 #ifdef CONFIG_HISAX_SEDLBAUER
 int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
 {
+#ifdef MODULE
+	int i;
+	int nzproto = 0;
+
+	nrcards = 0;
+	HiSaxVersion();
+	if (id)			/* If id= string used */
+		HiSax_id = id;
+	/* Initialize all 8 structs, even though we only accept
+	   two pcmcia cards
+	   */
+	for (i = 0; i < HISAX_MAX_CARDS; i++) {
+		cards[i].para[0] = irq[i];
+		cards[i].para[1] = io[i];
+		cards[i].typ = type[i];
+		if (protocol[i]) {
+			cards[i].protocol = protocol[i];
+			nzproto++;
+		}
+	}
+	cards[0].para[0] = pcm_irq;
+	cards[0].para[1] = (int)pcm_iob;
+	cards[0].protocol = prot;
+	cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
+	nzproto = 1;
+
+	if (!HiSax_id)
+		HiSax_id = HiSaxID;
+	if (!HiSaxID[0])
+		strcpy(HiSaxID, "HiSax");
+	for (i = 0; i < HISAX_MAX_CARDS; i++)
+		if (cards[i].typ > 0)
+			nrcards++;
+	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+	       nrcards, (nrcards > 1) ? "s" : "");
+
+	CallcNew();
+	Isdnl3New();
+	Isdnl2New();
+	Isdnl1New();
+	TeiNew();
+	HiSax_inithardware(busy_flag);
+	printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
+	return (0);
+}
+#endif
+
+#ifdef CONFIG_HISAX_AVM_A1_PCMCIA
+int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot)
+{
+#ifdef MODULE
 	int i;
 	int nzproto = 0;
 
@@ -615,14 +1709,14 @@
 	cards[0].para[0] = pcm_irq;
 	cards[0].para[1] = (int)pcm_iob;
 	cards[0].protocol = prot;
-	cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
+	cards[0].typ = ISDN_CTYPE_A1_PCMCIA;
 	nzproto = 1;
 
 	if (!HiSax_id)
 		HiSax_id = HiSaxID;
 	if (!HiSaxID[0])
 		strcpy(HiSaxID, "HiSax");
-	for (i = 0; i < 16; i++)
+	for (i = 0; i < HISAX_MAX_CARDS; i++)
 		if (cards[i].typ > 0)
 			nrcards++;
 	printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
@@ -630,11 +1724,12 @@
 
 	Isdnl1New();
 	CallcNew();
+	Isdnl3New();
 	Isdnl2New();
 	TeiNew();
 	HiSax_inithardware(busy_flag);
 	printk(KERN_NOTICE "HiSax: module installed\n");
+#endif
 	return (0);
 }
 #endif
-#endif 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/diva.c linux.pre11.3/drivers/isdn/hisax/diva.c
--- linux.vanilla/drivers/isdn/hisax/diva.c	Sun Nov  8 15:10:14 1998
+++ linux.pre11.3/drivers/isdn/hisax/diva.c	Mon Jul 19 23:59:33 1999
@@ -1,13 +1,37 @@
-/* $Id: diva.c,v 1.5 1998/02/02 13:29:38 keil Exp $
+/* $Id: diva.c,v 1.12 1999/07/12 21:05:04 keil Exp $
 
  * diva.c     low level stuff for Eicon.Diehl Diva Family ISDN cards
  *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author     Karsten Keil (keil@isdn4linux.de)
  *
  * Thanks to Eicon Technology Diehl GmbH & Co. oHG for documents and informations
  *
  *
  * $Log: diva.c,v $
+ * Revision 1.12  1999/07/12 21:05:04  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.11  1999/07/01 08:11:29  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.10  1998/11/15 23:54:31  keil
+ * changes from 2.0
+ *
+ * Revision 1.9  1998/06/27 22:52:03  keil
+ * support for Diva 2.01
+ *
+ * Revision 1.8  1998/05/25 12:57:46  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.7  1998/04/15 16:42:36  keil
+ * new init code
+ * new PCI init (2.1.94)
+ *
+ * Revision 1.6  1998/03/07 22:56:57  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 1.5  1998/02/02 13:29:38  keil
  * fast io
  *
@@ -31,13 +55,16 @@
 #include "hisax.h"
 #include "isac.h"
 #include "hscx.h"
+#include "ipac.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
 #include <linux/bios32.h>
+#endif
 
 extern const char *CardType[];
 
-const char *Diva_revision = "$Revision: 1.5 $";
+const char *Diva_revision = "$Revision: 1.12 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -47,6 +74,8 @@
 #define DIVA_ISA_ISAC_DATA	2
 #define DIVA_ISA_ISAC_ADR	6
 #define DIVA_ISA_CTRL		7
+#define DIVA_IPAC_ADR		0
+#define DIVA_IPAC_DATA		1
 
 #define DIVA_PCI_ISAC_DATA	8
 #define DIVA_PCI_ISAC_ADR	0xc
@@ -55,6 +84,8 @@
 /* SUB Types */
 #define DIVA_ISA	1
 #define DIVA_PCI	2
+#define DIVA_IPAC_ISA	3
+#define DIVA_IPAC_PCI	4
 
 /* PCI stuff */
 #define PCI_VENDOR_EICON_DIEHL	0x1133
@@ -62,10 +93,12 @@
 #define PCI_DIVA20_ID		0xe002
 #define PCI_DIVA20PRO_U_ID	0xe003
 #define PCI_DIVA20_U_ID		0xe004
+#define PCI_DIVA_201		0xe005
 
 /* CTRL (Read) */
 #define DIVA_IRQ_STAT	0x01
 #define DIVA_EEPROM_SDA	0x02
+
 /* CTRL (Write) */
 #define DIVA_IRQ_REQ	0x01
 #define DIVA_RESET	0x08
@@ -76,6 +109,13 @@
 #define DIVA_ISA_LED_B	0x40
 #define DIVA_IRQ_CLR	0x80
 
+/* Siemens PITA */
+#define PITA_MISC_REG		0x1c
+#define PITA_PARA_SOFTRESET	0x01000000
+#define PITA_PARA_MPX_MODE	0x04000000
+#define PITA_INT0_ENABLE	0x00020000
+#define PITA_INT0_STATUS	0x00000002
+
 static inline u_char
 readreg(unsigned int ale, unsigned int adr, u_char off)
 {
@@ -120,6 +160,22 @@
 	outsb(adr, data, size);
 }
 
+static inline u_char
+memreadreg(unsigned long adr, u_char off)
+{
+	return(0xff & *((unsigned int *)
+		(((unsigned int *)adr) + off)));
+}
+
+static inline void
+memwritereg(unsigned long adr, u_char off, u_char data)
+{
+	register u_char *p;
+	
+	p = (unsigned char *)(((unsigned int *)adr) + off);
+	*p = data;
+}
+
 /* Interface functions */
 
 static u_char
@@ -140,13 +196,37 @@
 	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
 }
 
-static void 
+static void
 WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 {
 	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size);
 }
 
 static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80));
+}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size);
+}
+
+static u_char
 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
 	return(readreg(cs->hw.diva.hscx_adr,
@@ -160,6 +240,44 @@
 		cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
+static u_char
+MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80));
+}
+
+static void
+MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value);
+}
+
+static void
+MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	while(size--)
+		*data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80);
+}
+
+static void
+MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+	while(size--)
+		memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++);
+}
+
+static u_char
+MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
+}
+
 /*
  * fast interrupt HSCX stuff goes here
  */
@@ -168,21 +286,21 @@
 		cs->hw.diva.hscx, reg + (nr ? 0x40 : 0))
 #define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \
                 cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data)
-                
+
 #define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \
 		cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
-		
+
 #define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \
 		cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt)
-		
+
 #include "hscx_irq.c"
 
 static void
 diva_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 0;
-	int cnt=8;
+	u_char val, sval;
+	int cnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
@@ -190,43 +308,421 @@
 	}
 	while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) {
 		val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40);
-		if (val) {
+		if (val)
 			hscx_int_main(cs, val);
-			stat |= 1;
-		}
 		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA);
-		if (val) {
+		if (val)
 			isac_interrupt(cs, val);
-			stat |= 2;
-		}
 		cnt--;
 	}
 	if (!cnt)
 		printk(KERN_WARNING "Diva: IRQ LOOP\n");
-	if (stat & 1) {
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0);
+}
+
+static void
+diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista,val;
+	int icnt=5;
+
+	if (!cs) {
+		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
+Start_IPACISA:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPACISA;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n");
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0);
+}
+
+static inline void
+MemwaitforCEC(struct IsdnCardState *cs, int hscx)
+{
+	int to = 50;
+
+	while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
+		udelay(1);
+		to--;
+	}
+	if (!to)
+		printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
+}
+
+
+static inline void
+MemwaitforXFW(struct IsdnCardState *cs, int hscx)
+{
+	int to = 50;
+
+	while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
+		udelay(1);
+		to--;
+	}
+	if (!to)
+		printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
+}
+
+static inline void
+MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	MemwaitforCEC(cs, hscx);
+	MemWriteHSCX(cs, hscx, HSCX_CMDR, data);
+	restore_flags(flags);
+}
+
+static void
+Memhscx_empty_fifo(struct BCState *bcs, int count)
+{
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+	long flags;
+	int cnt;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
+		MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	save_flags(flags);
+	cli();
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	cnt = count;
+	while (cnt--)
+		*ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0);
+	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
 	}
 }
 
+static void
+Memhscx_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count, cnt;
+	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
+	u_char *ptr,*p;
+	long flags;
+
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hscx_fill_fifo");
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+	cnt = count;
+	MemwaitforXFW(cs, bcs->hw.hscx.hscx);
+	save_flags(flags);
+	cli();
+	p = ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	while(cnt--)
+		memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0,
+			*p++);
+	MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static inline void
+Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
+{
+	u_char r;
+	struct BCState *bcs = cs->bcs + hscx;
+	struct sk_buff *skb;
+	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
+	int count;
+
+	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
+		return;
+
+	if (val & 0x80) {	/* RME */
+		r = MemReadHSCX(cs, hscx, HSCX_RSTA);
+		if ((r & 0xf0) != 0xa0) {
+			if (!(r & 0x80))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX invalid frame");
+			if ((r & 0x40) && bcs->mode)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX RDO mode=%d",
+						bcs->mode);
+			if (!(r & 0x20))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX CRC error");
+			MemWriteHSCXCMDR(cs, hscx, 0x80);
+		} else {
+			count = MemReadHSCX(cs, hscx, HSCX_RBCL) & (
+				test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
+			if (count == 0)
+				count = fifo_size;
+			Memhscx_empty_fifo(bcs, count);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "HSCX: receive out of memory\n");
+				else {
+					SET_SKB_FREE(skb);
+					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
+		}
+		bcs->hw.hscx.rcvidx = 0;
+		hscx_sched_event(bcs, B_RCVBUFREADY);
+	}
+	if (val & 0x40) {	/* RPF */
+		Memhscx_empty_fifo(bcs, fifo_size);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(fifo_size)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				SET_SKB_FREE(skb);
+				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			hscx_sched_event(bcs, B_RCVBUFREADY);
+		}
+	}
+	if (val & 0x10) {	/* XPR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				Memhscx_fill_fifo(bcs);
+				return;
+			} else {
+				if (bcs->st->lli.l1writewakeup &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				bcs->hw.hscx.count = 0; 
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			Memhscx_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			hscx_sched_event(bcs, B_XMTBUFREADY);
+		}
+	}
+}
+
+static inline void
+Memhscx_int_main(struct IsdnCardState *cs, u_char val)
+{
+
+	u_char exval;
+	struct BCState *bcs;
+
+	if (val & 0x01) {
+		bcs = cs->bcs + 1;
+		exval = MemReadHSCX(cs, 1, HSCX_EXIR);
+		if (exval & 0x40) {
+			if (bcs->mode == 1)
+				Memhscx_fill_fifo(bcs);
+			else {
+				/* Here we lost an TX interrupt, so
+				   * restart transmitting the whole frame.
+				 */
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B EXIR %x", exval);
+	}
+	if (val & 0xf8) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B interrupt %x", val);
+		Memhscx_interrupt(cs, val, 1);
+	}
+	if (val & 0x02) {
+		bcs = cs->bcs;
+		exval = MemReadHSCX(cs, 0, HSCX_EXIR);
+		if (exval & 0x40) {
+			if (bcs->mode == L1_MODE_TRANS)
+				Memhscx_fill_fifo(bcs);
+			else {
+				/* Here we lost an TX interrupt, so
+				   * restart transmitting the whole frame.
+				 */
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+					bcs->tx_cnt += bcs->hw.hscx.count;
+					bcs->hw.hscx.count = 0;
+				}
+				MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
+			}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A EXIR %x", exval);
+	}
+	if (val & 0x04) {
+		exval = MemReadHSCX(cs, 0, HSCX_ISTA);
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A interrupt %x", exval);
+		Memhscx_interrupt(cs, exval, 0);
+	}
+}
+
+static void
+diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista,val;
+	int icnt=5;
+	u_char *cfg;
+
+	if (!cs) {
+		printk(KERN_WARNING "Diva: Spurious interrupt!\n");
+		return;
+	}
+	cfg = (u_char *) cs->hw.diva.pci_cfg;
+	val = *cfg;
+	if (!(val & PITA_INT0_STATUS))
+		return; /* other shared IRQ */
+	*cfg = PITA_INT0_STATUS; /* Reset pending INT0 */
+	ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
+Start_IPACPCI:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			Memhscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
+	}
+	ista  = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPACPCI;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n");
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF);
+	memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
+}
+
 void
 release_io_diva(struct IsdnCardState *cs)
 {
 	int bytecnt;
-	
-	del_timer(&cs->hw.diva.tl);
-	if (cs->subtyp == DIVA_ISA)
+
+	if (cs->subtyp == DIVA_IPAC_PCI) {
+		u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
+
+		*cfg = 0; /* disable INT0/1 */ 
+		*cfg = 2; /* reset pending INT0 */
+		iounmap((void *)cs->hw.diva.cfg_reg);
+		iounmap((void *)cs->hw.diva.pci_cfg);
+		return;
+	} else if (cs->subtyp != DIVA_IPAC_ISA) {
+		del_timer(&cs->hw.diva.tl);
+		if (cs->hw.diva.cfg_reg)
+			byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
+	}
+	if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA))
 		bytecnt = 8;
 	else
 		bytecnt = 32;
 	if (cs->hw.diva.cfg_reg) {
-		byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */
 		release_region(cs->hw.diva.cfg_reg, bytecnt);
 	}
 }
@@ -238,19 +734,43 @@
 
 	save_flags(flags);
 	sti();
-	cs->hw.diva.ctrl_reg = 0;        /* Reset On */
-	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
-	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
-	if (cs->subtyp == DIVA_ISA)
-		cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
-	else
-		cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
-	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+	if (cs->subtyp == DIVA_IPAC_ISA) {
+		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10*HZ)/1000);
+		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10*HZ)/1000);
+		writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0);
+	} else if (cs->subtyp == DIVA_IPAC_PCI) {
+		unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
+					PITA_MISC_REG);
+		*ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10*HZ)/1000);
+		*ireg = PITA_PARA_MPX_MODE;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10*HZ)/1000);
+		memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
+	} else { /* DIVA 2.0 */
+		cs->hw.diva.ctrl_reg = 0;        /* Reset On */
+		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10*HZ)/1000);
+		cs->hw.diva.ctrl_reg |= DIVA_RESET;  /* Reset Off */
+		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout((10*HZ)/1000);
+		if (cs->subtyp == DIVA_ISA)
+			cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A;
+		else {
+			/* Workaround PCI9060 */
+			byteout(cs->hw.diva.pci_cfg + 0x69, 9);
+			cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A;
+		}
+		byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+	}
+	restore_flags(flags);
 }
 
 #define DIVA_ASSIGN 1
@@ -260,6 +780,8 @@
 {
 	int blink = 0;
 
+	if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI))
+		return;
 	del_timer(&cs->hw.diva.tl);
 	if (cs->hw.diva.status & DIVA_ASSIGN)
 		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
@@ -272,14 +794,14 @@
 	if (cs->hw.diva.status & 0xf000)
 		cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
-	else if (cs->hw.diva.status & 0x0f00) { 
+	else if (cs->hw.diva.status & 0x0f00) {
 		cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B;
 		blink = 500;
 	} else
 		cs->hw.diva.ctrl_reg &= ~((DIVA_ISA == cs->subtyp) ?
 			DIVA_ISA_LED_B : DIVA_PCI_LED_B);
-	
+
 	byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
 	if (blink) {
 		init_timer(&cs->hw.diva.tl);
@@ -291,6 +813,8 @@
 static int
 Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
+	u_int *ireg;
+
 	switch (mt) {
 		case CARD_RESET:
 			reset_diva(cs);
@@ -298,37 +822,35 @@
 		case CARD_RELEASE:
 			release_io_diva(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &diva_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			if (cs->subtyp == DIVA_IPAC_PCI) {
+				ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+				*ireg = PITA_INT0_ENABLE;
+			}
+			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
 			return(0);
-		case MDL_REMOVE_REQ:
+		case (MDL_REMOVE | REQUEST):
 			cs->hw.diva.status = 0;
 			break;
-		case MDL_ASSIGN_REQ:
+		case (MDL_ASSIGN | REQUEST):
 			cs->hw.diva.status |= DIVA_ASSIGN;
 			break;
 		case MDL_INFO_SETUP:
-			if ((int)arg) 
+			if ((long)arg)
 				cs->hw.diva.status |=  0x0200;
 			else
 				cs->hw.diva.status |=  0x0100;
 			break;
 		case MDL_INFO_CONN:
-			if ((int)arg) 
+			if ((long)arg)
 				cs->hw.diva.status |=  0x2000;
 			else
 				cs->hw.diva.status |=  0x1000;
 			break;
 		case MDL_INFO_REL:
-			if ((int)arg) {
+			if ((long)arg) {
 				cs->hw.diva.status &=  ~0x2000;
 				cs->hw.diva.status &=  ~0x0200;
 			} else {
@@ -337,18 +859,24 @@
 			}
 			break;
 	}
-	diva_led_handler(cs);
+	if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI))
+		diva_led_handler(cs);
 	return(0);
 }
 
-
-
-static 	int pci_index __initdata = 0;
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *dev_diva __initdata = NULL;
+static 	struct pci_dev *dev_diva_u __initdata = NULL;
+static 	struct pci_dev *dev_diva201 __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
 
 __initfunc(int
 setup_diva(struct IsdnCard *card))
 {
 	int bytecnt;
+	u_char val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
@@ -358,18 +886,75 @@
 		return(0);
 	cs->hw.diva.status = 0;
 	if (card->para[1]) {
-		cs->subtyp = DIVA_ISA;
 		cs->hw.diva.ctrl_reg = 0;
 		cs->hw.diva.cfg_reg = card->para[1];
-		cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
-		cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
-		cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
-		cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
-		cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+		val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR,
+			cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+		if (val == 1) {
+			cs->subtyp = DIVA_IPAC_ISA;
+			cs->hw.diva.ctrl = 0;
+			cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA;
+			cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA;
+			cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR;
+			cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+		} else {
+			cs->subtyp = DIVA_ISA;
+			cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL;
+			cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA;
+			cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA;
+			cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR;
+			cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+		}
 		cs->irq = card->para[0];
 		bytecnt = 8;
 	} else {
 #if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "Diva: no PCI bus present\n");
+			return(0);
+		}
+
+		cs->subtyp = 0;
+		if ((dev_diva = pci_find_device(PCI_VENDOR_EICON_DIEHL,
+			PCI_DIVA20_ID, dev_diva))) {
+			cs->subtyp = DIVA_PCI;
+			cs->irq = dev_diva->irq;
+			cs->hw.diva.cfg_reg = dev_diva->base_address[2]
+				& PCI_BASE_ADDRESS_IO_MASK;
+		} else if ((dev_diva_u = pci_find_device(PCI_VENDOR_EICON_DIEHL,
+			PCI_DIVA20_U_ID, dev_diva_u))) {
+			cs->subtyp = DIVA_PCI;
+			cs->irq = dev_diva_u->irq;
+			cs->hw.diva.cfg_reg = dev_diva_u->base_address[2]
+				& PCI_BASE_ADDRESS_IO_MASK;
+		} else if ((dev_diva201 = pci_find_device(PCI_VENDOR_EICON_DIEHL,
+			PCI_DIVA_201, dev_diva201))) {
+			cs->subtyp = DIVA_IPAC_PCI;
+			cs->irq = dev_diva201->irq;
+			cs->hw.diva.pci_cfg =
+				(ulong) ioremap((dev_diva201->base_address[0]
+					& PCI_BASE_ADDRESS_IO_MASK), 4096);
+			cs->hw.diva.cfg_reg =
+				(ulong) ioremap((dev_diva201->base_address[1]
+					& PCI_BASE_ADDRESS_IO_MASK), 4096);
+		} else {
+			printk(KERN_WARNING "Diva: No PCI card found\n");
+			return(0);
+		}
+
+		if (!cs->irq) {
+			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
+			return(0);
+		}
+
+		if (!cs->hw.diva.cfg_reg) {
+			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
+			return(0);
+		}
+#else
 		u_char pci_bus, pci_device_fn, pci_irq;
 		u_int pci_ioaddr;
 
@@ -380,9 +965,13 @@
 			   == PCIBIOS_SUCCESSFUL)
 				cs->subtyp = DIVA_PCI;
 			else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
-			   PCI_DIVA20_ID, pci_index, &pci_bus, &pci_device_fn)
+			   PCI_DIVA20_U_ID, pci_index, &pci_bus, &pci_device_fn)
 			   == PCIBIOS_SUCCESSFUL)
 			   	cs->subtyp = DIVA_PCI;
+			else if (pcibios_find_device(PCI_VENDOR_EICON_DIEHL,
+			   PCI_DIVA_201, pci_index, &pci_bus, &pci_device_fn)
+			   == PCIBIOS_SUCCESSFUL)
+			   	cs->subtyp = DIVA_IPAC_PCI;
 			else
 				break;
 			/* get IRQ */
@@ -390,8 +979,23 @@
 				PCI_INTERRUPT_LINE, &pci_irq);
 
 			/* get IO address */
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_2, &pci_ioaddr);
+			if (cs->subtyp == DIVA_IPAC_PCI) {
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_0, &pci_ioaddr);
+				cs->hw.diva.pci_cfg = (ulong) ioremap(pci_ioaddr,
+					4096);
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_1, &pci_ioaddr);
+				cs->hw.diva.cfg_reg = (ulong) ioremap(pci_ioaddr,
+					4096);
+			} else {
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_1, &pci_ioaddr);
+				cs->hw.diva.pci_cfg = pci_ioaddr & ~3;
+				pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_2, &pci_ioaddr);
+				cs->hw.diva.cfg_reg = pci_ioaddr & ~3;
+			}
 			if (cs->subtyp)
 				break;
 		}
@@ -399,65 +1003,103 @@
 			printk(KERN_WARNING "Diva: No PCI card found\n");
 			return(0);
 		}
+		pci_index++;
 		if (!pci_irq) {
 			printk(KERN_WARNING "Diva: No IRQ for PCI card found\n");
 			return(0);
 		}
-
 		if (!pci_ioaddr) {
 			printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n");
 			return(0);
 		}
-		pci_ioaddr &= ~3; /* remove io/mem flag */
-		cs->hw.diva.cfg_reg = pci_ioaddr; 
-		cs->hw.diva.ctrl = pci_ioaddr + DIVA_PCI_CTRL;
-		cs->hw.diva.isac = pci_ioaddr + DIVA_PCI_ISAC_DATA;
-		cs->hw.diva.hscx = pci_ioaddr + DIVA_HSCX_DATA;
-		cs->hw.diva.isac_adr = pci_ioaddr + DIVA_PCI_ISAC_ADR;
-		cs->hw.diva.hscx_adr = pci_ioaddr + DIVA_HSCX_ADR;
 		cs->irq = pci_irq;
-		bytecnt = 32;
+#endif /* COMPAT_HAS_NEW_PCI */
+		cs->irq_flags |= SA_SHIRQ;
 #else
 		printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n");
 		printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
 		return (0);
 #endif /* CONFIG_PCI */
+		if (cs->subtyp == DIVA_IPAC_PCI) {
+			cs->hw.diva.ctrl = 0;
+			cs->hw.diva.isac = 0;
+			cs->hw.diva.hscx = 0;
+			cs->hw.diva.isac_adr = 0;
+			cs->hw.diva.hscx_adr = 0;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			bytecnt = 0;
+		} else {
+			cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL;
+			cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA;
+			cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA;
+			cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR;
+			cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR;
+			bytecnt = 32;
+		}
 	}
 
 	printk(KERN_INFO
-		"Diva: %s card configured at 0x%x IRQ %d\n",
-		(cs->subtyp == DIVA_ISA) ? "ISA" : "PCI",
+		"Diva: %s card configured at %#lx IRQ %d\n",
+		(cs->subtyp == DIVA_PCI) ? "PCI" :
+		(cs->subtyp == DIVA_ISA) ? "ISA" : 
+		(cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI",
 		cs->hw.diva.cfg_reg, cs->irq);
-	if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.diva.cfg_reg,
-		       cs->hw.diva.cfg_reg + bytecnt);
-		return (0);
-	} else {
-		request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn");
+	if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI))
+		printk(KERN_INFO "Diva: %s PCI space at %#lx\n",
+			(cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI",
+			cs->hw.diva.pci_cfg);
+	if (cs->subtyp != DIVA_IPAC_PCI) {
+		if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
+			printk(KERN_WARNING
+			       "HiSax: %s config port %lx-%lx already in use\n",
+			       CardType[card->typ],
+			       cs->hw.diva.cfg_reg,
+			       cs->hw.diva.cfg_reg + bytecnt);
+			return (0);
+		} else {
+			request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn");
+		}
 	}
-
 	reset_diva(cs);
-	cs->hw.diva.tl.function = (void *) diva_led_handler;
-	cs->hw.diva.tl.data = (long) cs;
-	init_timer(&cs->hw.diva.tl);
-	cs->readisac  = &ReadISAC;
-	cs->writeisac = &WriteISAC;
-	cs->readisacfifo  = &ReadISACfifo;
-	cs->writeisacfifo = &WriteISACfifo;
 	cs->BC_Read_Reg  = &ReadHSCX;
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Diva_card_msg;
-
-	ISACVersion(cs, "Diva:");
-	if (HscxVersion(cs, "Diva:")) {
-		printk(KERN_WARNING
+	if (cs->subtyp == DIVA_IPAC_ISA) {
+		cs->readisac  = &ReadISAC_IPAC;
+		cs->writeisac = &WriteISAC_IPAC;
+		cs->readisacfifo  = &ReadISACfifo_IPAC;
+		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &diva_irq_ipac_isa;
+		val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	} else if (cs->subtyp == DIVA_IPAC_PCI) {
+		cs->readisac  = &MemReadISAC_IPAC;
+		cs->writeisac = &MemWriteISAC_IPAC;
+		cs->readisacfifo  = &MemReadISACfifo_IPAC;
+		cs->writeisacfifo = &MemWriteISACfifo_IPAC;
+		cs->BC_Read_Reg  = &MemReadHSCX;
+		cs->BC_Write_Reg = &MemWriteHSCX;
+		cs->BC_Send_Data = &Memhscx_fill_fifo;
+		cs->irq_func = &diva_irq_ipac_pci;
+		val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
+		printk(KERN_INFO "Diva: IPAC version %x\n", val);
+	} else { /* DIVA 2.0 */
+		cs->hw.diva.tl.function = (void *) diva_led_handler;
+		cs->hw.diva.tl.data = (long) cs;
+		init_timer(&cs->hw.diva.tl);
+		cs->readisac  = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo  = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &diva_interrupt;
+		ISACVersion(cs, "Diva:");
+		if (HscxVersion(cs, "Diva:")) {
+			printk(KERN_WARNING
 		       "Diva: wrong HSCX versions check IO address\n");
-		release_io_diva(cs);
-		return (0);
+			release_io_diva(cs);
+			return (0);
+		}
 	}
 	return (1);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/elsa.c linux.pre11.3/drivers/isdn/hisax/elsa.c
--- linux.vanilla/drivers/isdn/hisax/elsa.c	Sun Nov  8 15:10:14 1998
+++ linux.pre11.3/drivers/isdn/hisax/elsa.c	Mon Jul 19 23:59:33 1999
@@ -1,13 +1,48 @@
-/* $Id: elsa.c,v 2.6 1998/02/02 13:29:40 keil Exp $
+/* $Id: elsa.c,v 2.14 1999/07/12 21:05:07 keil Exp $
 
  * elsa.c     low level stuff for Elsa isdn cards
  *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author     Karsten Keil (keil@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
  *
  * Thanks to    Elsa GmbH for documents and informations
  *
+ *              Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE)
+ *              for ELSA PCMCIA support
+ *
  *
  * $Log: elsa.c,v $
+ * Revision 2.14  1999/07/12 21:05:07  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.13  1999/07/01 08:11:31  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.12  1998/11/15 23:54:35  keil
+ * changes from 2.0
+ *
+ * Revision 2.11  1998/08/20 13:50:34  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.10  1998/08/13 23:36:22  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.9  1998/05/25 12:57:48  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8  1998/04/15 16:41:42  keil
+ * QS3000 PCI support
+ * new init code
+ * new PCI init (2.1.94)
+ *
+ * Revision 2.7  1998/03/07 22:56:58  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 2.6  1998/02/02 13:29:40  keil
  * fast io
  *
@@ -29,15 +64,6 @@
  * Revision 2.0  1997/06/26 11:02:40  keil
  * New Layer and card interface
  *
- * Revision 1.14  1997/04/13 19:53:25  keil
- * Fixed QS1000 init, change in IRQ check delay for SMP
- *
- * Revision 1.13  1997/04/07 22:58:07  keil
- * need include config.h
- *
- * Revision 1.12  1997/04/06 22:54:14  keil
- * Using SKB's
- *
  * old changes removed KKe
  *
  */
@@ -51,14 +77,18 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
 #include <linux/bios32.h>
+#endif
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
 
 extern const char *CardType[];
 
-const char *Elsa_revision = "$Revision: 2.6 $";
+const char *Elsa_revision = "$Revision: 2.14 $";
 const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
- "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI"};
+ "PCMCIA", "QS 1000", "QS 3000", "QS 1000 PCI", "QS 3000 PCI"};
 
 const char *ITACVer[] =
 {"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2",
@@ -87,11 +117,13 @@
 #define ELSA_QS1000  7
 #define ELSA_QS3000  8
 #define ELSA_QS1000PCI 9
+#define ELSA_QS3000PCI 10
 
 /* PCI stuff */
 #define PCI_VENDOR_ELSA	0x1048
 #define PCI_QS1000_ID	0x1000
-
+#define PCI_QS3000_ID	0x3000
+#define ELSA_PCI_IRQ_MASK	0x04
 
 /* ITAC Registeradressen (only Microlink PC) */
 #define ITAC_SYS	0x34
@@ -128,6 +160,40 @@
 #define ELSA_BAD_PWR     2
 #define ELSA_ASSIGN      4
 
+#define RS_ISR_PASS_LIMIT 256
+#define _INLINE_ inline
+#define FLG_MODEM_ACTIVE 1
+/* IPAC AUX */
+#define ELSA_IPAC_LINE_LED	0x40	/* Bit 6 Gelbe LED */
+#define ELSA_IPAC_STAT_LED	0x80	/* Bit 7 Gruene LED */
+
+static struct arcofi_msg ARCOFI_XOP_F =
+	{NULL,0,2,{0xa1,0x3f,0,0,0,0,0,0,0,0}}; /* Normal OP */
+static struct arcofi_msg ARCOFI_XOP_1 =
+	{&ARCOFI_XOP_F,0,2,{0xa1,0x31,0,0,0,0,0,0,0,0}}; /* PWR UP */
+static struct arcofi_msg ARCOFI_SOP_F = 
+	{&ARCOFI_XOP_1,0,10,{0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12}};
+static struct arcofi_msg ARCOFI_COP_9 =
+	{&ARCOFI_SOP_F,0,10,{0xa1,0x29,0x80,0xcb,0xe9,0x88,0x00,0xc8,0xd8,0x80}}; /* RX */
+static struct arcofi_msg ARCOFI_COP_8 =
+	{&ARCOFI_COP_9,0,10,{0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}}; /* TX */
+static struct arcofi_msg ARCOFI_COP_7 =
+	{&ARCOFI_COP_8,0,4,{0xa1,0x27,0x80,0x80,0,0,0,0,0,0}}; /* GZ */
+static struct arcofi_msg ARCOFI_COP_6 =
+	{&ARCOFI_COP_7,0,6,{0xa1,0x26,0,0,0x82,0x7c,0,0,0,0}}; /* GRL GRH */
+static struct arcofi_msg ARCOFI_COP_5 =
+	{&ARCOFI_COP_6,0,4,{0xa1,0x25,0xbb,0x4a,0,0,0,0,0,0}}; /* GTX */
+static struct arcofi_msg ARCOFI_VERSION =
+	{NULL,1,2,{0xa0,0,0,0,0,0,0,0,0,0}};
+static struct arcofi_msg ARCOFI_XOP_0 =
+	{NULL,0,2,{0xa1,0x30,0,0,0,0,0,0,0,0}}; /* PWR Down */
+
+static void set_arcofi(struct IsdnCardState *cs, int bc);
+
+#if ARCOFI_USE
+#include "elsa_ser.c"
+#endif
+
 static inline u_char
 readreg(unsigned int ale, unsigned int adr, u_char off)
 {
@@ -296,12 +362,27 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char val;
-	int icnt=20;
+	int icnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
 		return;
 	}
+	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
+	/* The card tends to generate interrupts while being removed
+	   causing us to just crash the kernel. bad. */
+		printk(KERN_WARNING "Elsa: card not available!\n");
+		return;
+	}
+#if ARCOFI_USE
+	if (cs->hw.elsa.MFlag) {
+		val = serial_inp(cs, UART_IIR);
+		if (!(val & UART_IIR_NO_INT)) {
+			debugl1(cs,"IIR %02x", val);
+			rs_interrupt_elsa(intno, cs);
+		}
+	}
+#endif
 	val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
 	if (val) {
@@ -338,6 +419,14 @@
 			cs->hw.elsa.counter++;
 		}
 	}
+	if (cs->hw.elsa.MFlag) {
+		val = serial_inp(cs, UART_MCR);
+		val ^= 0x8;
+		serial_outp(cs, UART_MCR, val);
+		val = serial_inp(cs, UART_MCR);
+		val ^= 0x8;
+		serial_outp(cs, UART_MCR, val);
+	}
 	if (cs->hw.elsa.trig)
 		byteout(cs->hw.elsa.trig, 0x00);
 	writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0);
@@ -350,25 +439,28 @@
 {
 	struct IsdnCardState *cs = dev_id;
 	u_char ista,val;
-	char   tmp[64];
-	int icnt=20;
+	int icnt=5;
 
 	if (!cs) {
 		printk(KERN_WARNING "Elsa: Spurious interrupt!\n");
 		return;
 	}
-	if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) {
-	  /* The card tends to generate interrupts while being removed
-	     causing us to just crash the kernel. bad. */
-	  printk(KERN_WARNING "Elsa: card not available!\n");
-	  return;
+	val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */
+	if (!(val & ELSA_PCI_IRQ_MASK))
+		return;
+#if ARCOFI_USE
+	if (cs->hw.elsa.MFlag) {
+		val = serial_inp(cs, UART_IIR);
+		if (!(val & UART_IIR_NO_INT)) {
+			debugl1(cs,"IIR %02x", val);
+			rs_interrupt_elsa(intno, cs);
+		}
 	}
+#endif
 	ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA);
 Start_IPAC:
-	if (cs->debug & L1_DEB_IPAC) {
-		sprintf(tmp, "IPAC ISTA %02X", ista);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
 	if (ista & 0x0f) {
 		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40);
 		if (ista & 0x01)
@@ -407,17 +499,27 @@
 	int bytecnt = 8;
 
 	del_timer(&cs->hw.elsa.tl);
+	clear_arcofi(cs);
 	if (cs->hw.elsa.ctrl)
 		byteout(cs->hw.elsa.ctrl, 0);	/* LEDs Out */
-	if ((cs->subtyp == ELSA_PCFPRO) || 
-		(cs->subtyp == ELSA_QS3000) ||
-		(cs->subtyp == ELSA_PCF))
-		bytecnt = 16;
 	if (cs->subtyp == ELSA_QS1000PCI) {
 		byteout(cs->hw.elsa.cfg + 0x4c, 0x01);  /* disable IRQ */
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
 		bytecnt = 2;
 		release_region(cs->hw.elsa.cfg, 0x80);
 	}
+	if (cs->subtyp == ELSA_QS3000PCI) {
+		byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		release_region(cs->hw.elsa.cfg, 0x80);
+	}
+	if ((cs->subtyp == ELSA_PCFPRO) ||
+		(cs->subtyp == ELSA_QS3000) ||
+		(cs->subtyp == ELSA_PCF) ||
+		(cs->subtyp == ELSA_QS3000PCI)) {
+		bytecnt = 16;
+		release_modem(cs);
+	}
 	if (cs->hw.elsa.base)
 		release_region(cs->hw.elsa.base, bytecnt);
 }
@@ -445,45 +547,35 @@
 		if (cs->hw.elsa.trig)
 			byteout(cs->hw.elsa.trig, 0xff);
 	}
-	if (cs->subtyp == ELSA_QS1000PCI) {
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
 		save_flags(flags);
 		sti();
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20);
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
+		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00);
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout((10*HZ)/1000);	/* Timeout 10ms */
 		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0);
-		schedule();
+		schedule_timeout((10*HZ)/1000); /* Timeout 10ms */
 		restore_flags(flags);
-		byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c);
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff);
+		if (cs->subtyp == ELSA_QS1000PCI)
+			byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */
+		else if (cs->subtyp == ELSA_QS3000PCI)
+			byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */
 	}
 }
 
-const u_char ARCOFI_VERSION[] = {2,0xa0,0};
-const u_char ARCOFI_COP_5[] = {4,0xa1,0x25,0xbb,0x4a}; /* GTX */
-const u_char ARCOFI_COP_6[] = {6,0xa1,0x26,0,0,0x82,0x7c}; /* GRL GRH */
-const u_char ARCOFI_COP_7[] = {4,0xa1,0x27,0x80,0x80}; /* GZ */
-const u_char ARCOFI_COP_8[] = {10,0xa1,0x28,0x49,0x31,0x8,0x13,0x6e,0x88,0x2a,0x61}; /* TX */
-const u_char ARCOFI_COP_9[] = {10,0xa1,0x29,0x80,0xcb,0x9e,0x88,0x00,0xc8,0xd8,0x80}; /* RX */
-const u_char ARCOFI_XOP_0[] = {2,0xa1,0x30}; /* PWR Down */
-const u_char ARCOFI_XOP_1[] = {2,0xa1,0x31}; /* PWR Down */
-const u_char ARCOFI_XOP_F[] = {2,0xa1,0x3f}; /* PWR Down */
-const u_char ARCOFI_SOP_F[] = {10,0xa1,0x1f,0x00,0x50,0x10,0x00,0x00,0x80,0x02,0x12};
- 
 static void
-init_arcofi(struct IsdnCardState *cs) {
-	send_arcofi(cs, ARCOFI_COP_5);
-	send_arcofi(cs, ARCOFI_COP_6);
-	send_arcofi(cs, ARCOFI_COP_7);
-	send_arcofi(cs, ARCOFI_COP_8);
-	send_arcofi(cs, ARCOFI_COP_9);
-	send_arcofi(cs, ARCOFI_SOP_F);
-	send_arcofi(cs, ARCOFI_XOP_F);
+set_arcofi(struct IsdnCardState *cs, int bc) {
+	cs->dc.isac.arcofi_bc = bc;
+	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_COP_5);
+	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
 }
 
-static void
+static int
 check_arcofi(struct IsdnCardState *cs)
 {
 #if ARCOFI_USE
@@ -492,24 +584,24 @@
 	char *t;
 	u_char *p;
 
-	if (!cs->mon_tx)
-		if (!(cs->mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
+	if (!cs->dc.isac.mon_tx)
+		if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
 			if (cs->debug & L1_DEB_WARN)
 				debugl1(cs, "ISAC MON TX out of buffers!");
-			return;
+			return(0);
 		}
-	send_arcofi(cs, ARCOFI_VERSION);
-	if (test_and_clear_bit(HW_MON1_TX_END, &cs->HW_Flags)) {
-		if (test_and_clear_bit(HW_MON1_RX_END, &cs->HW_Flags)) {
-			sprintf(tmp, "Arcofi response received %d bytes", cs->mon_rxp);
-			debugl1(cs, tmp);
-			p = cs->mon_rx;
+	cs->dc.isac.arcofi_bc = 0;
+	arcofi_fsm(cs, ARCOFI_START, &ARCOFI_VERSION);
+	interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
+	if (!test_and_clear_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags)) {
+			debugl1(cs, "Arcofi response received %d bytes", cs->dc.isac.mon_rxp);
+			p = cs->dc.isac.mon_rx;
 			t = tmp;
 			t += sprintf(tmp, "Arcofi data");
-			QuickHex(t, p, cs->mon_rxp);
+			QuickHex(t, p, cs->dc.isac.mon_rxp);
 			debugl1(cs, tmp);
-			if ((cs->mon_rxp == 2) && (cs->mon_rx[0] == 0xa0)) {
-				switch(cs->mon_rx[1]) {
+			if ((cs->dc.isac.mon_rxp == 2) && (cs->dc.isac.mon_rx[0] == 0xa0)) {
+				switch(cs->dc.isac.mon_rx[1]) {
 					case 0x80:
 						debugl1(cs, "Arcofi 2160 detected");
 						arcofi_present = 1;
@@ -528,11 +620,9 @@
 				}
 			} else
 				debugl1(cs, "undefined Monitor response");
-			cs->mon_rxp = 0;
-		}
-	} else if (cs->mon_tx) {
-		sprintf(tmp, "Arcofi not detected");
-		debugl1(cs, tmp);
+			cs->dc.isac.mon_rxp = 0;
+	} else if (cs->dc.isac.mon_tx) {
+		debugl1(cs, "Arcofi not detected");
 	}
 	if (arcofi_present) {
 		if (cs->subtyp==ELSA_QS1000) {
@@ -572,9 +662,12 @@
 				"Elsa: %s detected modem at 0x%x\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
-		init_arcofi(cs);
+		arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
+		interruptible_sleep_on(&cs->dc.isac.arcofi_wait);
+		return(1);
 	}
 #endif
+	return(0);
 }
 
 static void
@@ -582,8 +675,7 @@
 {
 	int blink = 0;
 
-	if ((cs->subtyp == ELSA_PCMCIA) &&
-		(cs->subtyp == ELSA_QS1000PCI))
+	if (cs->subtyp == ELSA_PCMCIA)
 		return;
 	del_timer(&cs->hw.elsa.tl);
 	if (cs->hw.elsa.status & ELSA_ASSIGN)
@@ -602,7 +694,16 @@
 	} else
 		cs->hw.elsa.ctrl_reg &= ~ELSA_LINE_LED;
 
-	byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+	if ((cs->subtyp == ELSA_QS1000PCI) ||
+		(cs->subtyp == ELSA_QS3000PCI)) {
+		u_char led = 0xff;
+		if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED)
+			led ^= ELSA_IPAC_LINE_LED;
+		if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED)
+			led ^= ELSA_IPAC_STAT_LED;
+		writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led);
+	} else
+		byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
 	if (blink) {
 		init_timer(&cs->hw.elsa.tl);
 		cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000);
@@ -613,8 +714,9 @@
 static int
 Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
-	int pwr, ret = 0;
-	long flags;	
+	int len, ret = 0;
+	u_char *msg;
+	long flags;
 
 	switch (mt) {
 		case CARD_RESET:
@@ -623,29 +725,25 @@
 		case CARD_RELEASE:
 			release_io_elsa(cs);
 			return(0);
-		case CARD_SETIRQ:
-			if (cs->subtyp == ELSA_QS1000PCI)
-				ret = request_irq(cs->irq, &elsa_interrupt_ipac,
-					I4L_IRQ_FLAG, "HiSax", cs);
-			else
-				ret = request_irq(cs->irq, &elsa_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs);
-			return(ret);
 		case CARD_INIT:
-			if (cs->hw.elsa.trig)
-				byteout(cs->hw.elsa.trig, 0xff);
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
-			if (cs->subtyp == ELSA_QS1000) {
+			cs->debug |= L1_DEB_IPAC;
+			inithscxisac(cs, 1);
+			if ((cs->subtyp == ELSA_QS1000) ||
+			    (cs->subtyp == ELSA_QS3000))
+			{
 				byteout(cs->hw.elsa.timer, 0);
-				byteout(cs->hw.elsa.trig, 0xff);
 			}
+			if (cs->hw.elsa.trig)
+				byteout(cs->hw.elsa.trig, 0xff);
+			inithscxisac(cs, 2);
 			return(0);
 		case CARD_TEST:
-			if ((cs->subtyp != ELSA_PCMCIA) &&
-				(cs->subtyp != ELSA_QS1000PCI)) {
+			if ((cs->subtyp == ELSA_PCMCIA) ||
+				(cs->subtyp == ELSA_QS1000PCI)) {
+				return(0);
+			} else if (cs->subtyp == ELSA_QS3000PCI) {
+				ret = 0;
+			} else {
 				save_flags(flags);
 				cs->hw.elsa.counter = 0;
 				sti();
@@ -653,48 +751,51 @@
 				cs->hw.elsa.status |= ELSA_TIMER_AKTIV;
 				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
 				byteout(cs->hw.elsa.timer, 0);
-			} else
-				return(0);
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout((110*HZ)/1000);		/* Timeout 110ms */
-			restore_flags(flags);
-			cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
-			byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
-			cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
-			printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
-			       cs->hw.elsa.counter);
-			if (abs(cs->hw.elsa.counter - 13) < 3) {
-				printk(KERN_INFO "Elsa: timer and irq OK\n");
-				ret = 0;
-			} else {
-				printk(KERN_WARNING
-				       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
-				       cs->hw.elsa.counter, cs->irq);
-				ret = 1;
+				current->state = TASK_INTERRUPTIBLE;
+				schedule_timeout((110*HZ)/1000);
+				restore_flags(flags);
+				cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT;
+				byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg);
+				cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV;
+				printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n",
+				       cs->hw.elsa.counter);
+				if (abs(cs->hw.elsa.counter - 13) < 3) {
+					printk(KERN_INFO "Elsa: timer and irq OK\n");
+					ret = 0;
+				} else {
+					printk(KERN_WARNING
+					       "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n",
+					       cs->hw.elsa.counter, cs->irq);
+					ret = 1;
+				}
+			}
+#if ARCOFI_USE
+			if (check_arcofi(cs)) {
+				init_modem(cs);
 			}
-			check_arcofi(cs);
+#endif
 			elsa_led_handler(cs);
 			return(ret);
-		case MDL_REMOVE_REQ:
+		case (MDL_REMOVE | REQUEST):
 			cs->hw.elsa.status &= 0;
 			break;
-		case MDL_ASSIGN_REQ:
+		case (MDL_ASSIGN | REQUEST):
 			cs->hw.elsa.status |= ELSA_ASSIGN;
 			break;
 		case MDL_INFO_SETUP:
-			if ((int) arg)
+			if ((long) arg)
 				cs->hw.elsa.status |= 0x0200;
 			else
 				cs->hw.elsa.status |= 0x0100;
 			break;
 		case MDL_INFO_CONN:
-			if ((int) arg)
+			if ((long) arg)
 				cs->hw.elsa.status |= 0x2000;
 			else
 				cs->hw.elsa.status |= 0x1000;
 			break;
 		case MDL_INFO_REL:
-			if ((int) arg) {
+			if ((long) arg) {
 				cs->hw.elsa.status &= ~0x2000;
 				cs->hw.elsa.status &= ~0x0200;
 			} else {
@@ -703,13 +804,23 @@
 			}
 			break;
 		case CARD_AUX_IND:
+			if (cs->hw.elsa.MFlag) {
+				if (!arg)
+					return(0);
+				msg = arg;
+				len = *msg;
+				msg++;
+				modem_write_cmd(cs, msg, len);
+			}
 			break;
 	}
-	pwr = bytein(cs->hw.elsa.ale);
-	if (pwr & 0x08)
-		cs->hw.elsa.status |= ELSA_BAD_PWR;
-	else
-		cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+	if (cs->typ == ISDN_CTYPE_ELSA) {
+		int pwr = bytein(cs->hw.elsa.ale);
+		if (pwr & 0x08)
+			cs->hw.elsa.status |= ELSA_BAD_PWR;
+		else
+			cs->hw.elsa.status &= ~ELSA_BAD_PWR;
+	}
 	elsa_led_handler(cs);
 	return(ret);
 }
@@ -778,7 +889,12 @@
 	return (CARD_portlist[i]);
 }
 
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *dev_qs1000 __initdata = NULL;
+static 	struct pci_dev *dev_qs3000 __initdata = NULL;
+#else
 static 	int pci_index __initdata = 0;
+#endif
 
 int
 setup_elsa(struct IsdnCard *card)
@@ -793,6 +909,7 @@
 	printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp));
 	cs->hw.elsa.ctrl_reg = 0;
 	cs->hw.elsa.status = 0;
+	cs->hw.elsa.MFlag = 0;
 	if (cs->typ == ISDN_CTYPE_ELSA) {
 		cs->hw.elsa.base = card->para[0];
 		printk(KERN_INFO "Elsa: Microlink IO probing\n");
@@ -886,6 +1003,52 @@
 		       cs->irq);
 	} else if (cs->typ == ISDN_CTYPE_ELSA_PCI) {
 #if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "Elsa: no PCI bus present\n");
+			return(0);
+		}
+		cs->subtyp = 0;
+		if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ELSA, PCI_QS1000_ID,
+			 dev_qs1000))) {
+				cs->subtyp = ELSA_QS1000PCI;
+			cs->irq = dev_qs1000->irq;
+			cs->hw.elsa.cfg = dev_qs1000->base_address[1] & 
+				PCI_BASE_ADDRESS_IO_MASK;
+			cs->hw.elsa.base = dev_qs1000->base_address[3] & 
+				PCI_BASE_ADDRESS_IO_MASK;
+		} else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ELSA,
+			PCI_QS3000_ID, dev_qs3000))) {
+			cs->subtyp = ELSA_QS3000PCI;
+			cs->irq = dev_qs3000->irq;
+			cs->hw.elsa.cfg = dev_qs3000->base_address[1] & 
+				PCI_BASE_ADDRESS_IO_MASK;
+			cs->hw.elsa.base = dev_qs3000->base_address[3] & 
+				PCI_BASE_ADDRESS_IO_MASK;
+		} else {
+			printk(KERN_WARNING "Elsa: No PCI card found\n");
+			return(0);
+		}
+		if (!cs->irq) {
+			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
+			return(0);
+		}
+
+		if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) {
+			printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n");
+			return(0);
+		}
+		if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) {
+			printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n");
+			printk(KERN_WARNING "Elsa: If your system hangs now, read\n");
+			printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n");
+			printk(KERN_WARNING "Elsa: Waiting 5 sec to sync discs\n");
+			save_flags(flags);
+			sti();
+			HZDELAY(500);	/* wait 500*10 ms */
+			restore_flags(flags);
+		}
+#else
 		u_char pci_bus, pci_device_fn, pci_irq;
 		u_int pci_ioaddr;
 
@@ -895,6 +1058,10 @@
 			   PCI_QS1000_ID, pci_index, &pci_bus, &pci_device_fn)
 			   == PCIBIOS_SUCCESSFUL)
 				cs->subtyp = ELSA_QS1000PCI;
+			else if (pcibios_find_device(PCI_VENDOR_ELSA,
+			   PCI_QS3000_ID, pci_index, &pci_bus, &pci_device_fn)
+			   == PCIBIOS_SUCCESSFUL)
+				cs->subtyp = ELSA_QS3000PCI;
 			else
 				break;
 			/* get IRQ */
@@ -915,6 +1082,7 @@
 			printk(KERN_WARNING "Elsa: No PCI card found\n");
 			return(0);
 		}
+		pci_index++;
 		if (!pci_irq) {
 			printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n");
 			return(0);
@@ -926,13 +1094,15 @@
 		}
 		pci_ioaddr &= ~3; /* remove io/mem flag */
 		cs->hw.elsa.base = pci_ioaddr;
-		cs->hw.elsa.ale  = pci_ioaddr;
-		cs->hw.elsa.isac = pci_ioaddr +1;
-		cs->hw.elsa.hscx = pci_ioaddr +1; 
 		cs->irq = pci_irq;
+#endif /* COMPAT_HAS_NEW_PCI */
+		cs->hw.elsa.ale  = cs->hw.elsa.base;
+		cs->hw.elsa.isac = cs->hw.elsa.base +1;
+		cs->hw.elsa.hscx = cs->hw.elsa.base +1; 
 		test_and_set_bit(HW_IPAC, &cs->HW_Flags);
 		cs->hw.elsa.timer = 0;
 		cs->hw.elsa.trig  = 0;
+		cs->irq_flags |= SA_SHIRQ;
 		printk(KERN_INFO
 		       "Elsa: %s defined at 0x%x/0x%x IRQ %d\n",
 		       Elsa_Types[cs->subtyp],
@@ -957,6 +1127,7 @@
 			break;
 		case ELSA_PCFPRO:
 		case ELSA_PCF:
+		case ELSA_QS3000PCI:
 			bytecnt = 16;
 			break;
 		case ELSA_QS1000PCI:
@@ -980,7 +1151,7 @@
 	} else {
 		request_region(cs->hw.elsa.base, bytecnt, "elsa isdn");
 	}
-	if (cs->subtyp == ELSA_QS1000PCI) {
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
 		if (check_region(cs->hw.elsa.cfg, 0x80)) {
 			printk(KERN_WARNING
 			       "HiSax: %s pci port %x-%x already in use\n",
@@ -993,6 +1164,7 @@
 			request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci");
 		}
 	}
+	init_arcofi(cs);
 	cs->hw.elsa.tl.function = (void *) elsa_led_handler;
 	cs->hw.elsa.tl.data = (long) cs;
 	init_timer(&cs->hw.elsa.tl);
@@ -1020,16 +1192,17 @@
 		}
 		printk(KERN_INFO "Elsa: timer OK; resetting card\n");
 	}
-	reset_elsa(cs);
 	cs->BC_Read_Reg = &ReadHSCX;
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Elsa_card_msg;
-	if (cs->subtyp == ELSA_QS1000PCI) {
+	reset_elsa(cs);
+	if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) {
 		cs->readisac = &ReadISAC_IPAC;
 		cs->writeisac = &WriteISAC_IPAC;
 		cs->readisacfifo = &ReadISACfifo_IPAC;
 		cs->writeisacfifo = &WriteISACfifo_IPAC;
+		cs->irq_func = &elsa_interrupt_ipac;
 		val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID);
 		printk(KERN_INFO "Elsa: IPAC version %x\n", val);
 	} else {
@@ -1037,6 +1210,7 @@
 		cs->writeisac = &WriteISAC;
 		cs->readisacfifo = &ReadISACfifo;
 		cs->writeisacfifo = &WriteISACfifo;
+		cs->irq_func = &elsa_interrupt;
 		ISACVersion(cs, "Elsa:");
 		if (HscxVersion(cs, "Elsa:")) {
 			printk(KERN_WARNING
@@ -1056,4 +1230,3 @@
 	}
 	return (1);
 }
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/elsa_ser.c linux.pre11.3/drivers/isdn/hisax/elsa_ser.c
--- linux.vanilla/drivers/isdn/hisax/elsa_ser.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/elsa_ser.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,750 @@
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+
+#define MAX_MODEM_BUF	256
+#define WAKEUP_CHARS	(MAX_MODEM_BUF/2)
+#define RS_ISR_PASS_LIMIT 256
+#define BASE_BAUD ( 1843200 / 16 )
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+//#define SERIAL_DEBUG_OPEN 1
+//#define SERIAL_DEBUG_INTR 1
+//#define SERIAL_DEBUG_FLOW 1
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_REG
+//#define SERIAL_DEBUG_REG 1
+
+#ifdef SERIAL_DEBUG_REG
+static u_char deb[32];
+const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"};
+const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"};
+#endif
+
+static char *MInit_1 = "AT&F&C1E0&D2\r\0";
+static char *MInit_2 = "ATL2M1S64=13\r\0";
+static char *MInit_3 = "AT+FCLASS=0\r\0";
+static char *MInit_4 = "ATV1S2=128X1\r\0";
+static char *MInit_5 = "AT\\V8\\N3\r\0";
+static char *MInit_6 = "ATL0M0&G0%E1\r\0";
+static char *MInit_7 = "AT%L1%M0%C3\r\0";
+
+static char *MInit_speed28800 = "AT%G0%B28800\r\0";
+
+static char *MInit_dialout = "ATs7=60 x1 d\r\0";
+static char *MInit_dialin = "ATs7=60 x1 a\r\0";
+
+
+static inline unsigned int serial_in(struct IsdnCardState *cs, int offset)
+{
+#ifdef SERIAL_DEBUG_REG
+	u_int val = inb(cs->hw.elsa.base + 8 + offset);
+	debugl1(cs,"in   %s %02x",ModemIn[offset], val);
+	return(val);
+#else
+	return inb(cs->hw.elsa.base + 8 + offset);
+#endif
+}
+
+static inline unsigned int serial_inp(struct IsdnCardState *cs, int offset)
+{
+#ifdef SERIAL_DEBUG_REG
+#ifdef CONFIG_SERIAL_NOPAUSE_IO
+	u_int val = inb(cs->hw.elsa.base + 8 + offset);
+	debugl1(cs,"inp  %s %02x",ModemIn[offset], val);
+#else
+	u_int val = inb_p(cs->hw.elsa.base + 8 + offset);
+	debugl1(cs,"inP  %s %02x",ModemIn[offset], val);
+#endif
+	return(val);
+#else
+#ifdef CONFIG_SERIAL_NOPAUSE_IO
+	return inb(cs->hw.elsa.base + 8 + offset);
+#else
+	return inb_p(cs->hw.elsa.base + 8 + offset);
+#endif
+#endif
+}
+
+static inline void serial_out(struct IsdnCardState *cs, int offset, int value)
+{
+#ifdef SERIAL_DEBUG_REG
+	debugl1(cs,"out  %s %02x",ModemOut[offset], value);
+#endif
+	outb(value, cs->hw.elsa.base + 8 + offset);
+}
+
+static inline void serial_outp(struct IsdnCardState *cs, int offset,
+			       int value)
+{
+#ifdef SERIAL_DEBUG_REG
+#ifdef CONFIG_SERIAL_NOPAUSE_IO
+	debugl1(cs,"outp %s %02x",ModemOut[offset], value);
+#else
+	debugl1(cs,"outP %s %02x",ModemOut[offset], value);
+#endif
+#endif
+#ifdef CONFIG_SERIAL_NOPAUSE_IO
+	outb(value, cs->hw.elsa.base + 8 + offset);
+#else
+    	outb_p(value, cs->hw.elsa.base + 8 + offset);
+#endif
+}
+
+/*
+ * 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 IsdnCardState *cs, int baud)
+{
+	int	quot = 0, baud_base;
+	unsigned cval, fcr = 0;
+	int	bits;
+	unsigned long	flags;
+
+
+	/* byte size and parity */
+	cval = 0x03; bits = 10;
+	/* Determine divisor based on baud rate */
+	baud_base = BASE_BAUD;
+	quot = baud_base / baud;
+	/* If the quotient is ever zero, default to 9600 bps */
+	if (!quot)
+		quot = baud_base / 9600;
+
+	/* Set up FIFO's */
+	if ((baud_base / quot) < 2400)
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+	else
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
+	serial_outp(cs, UART_FCR, fcr);
+	/* CTS flow control flag and modem status interrupts */
+	cs->hw.elsa.IER &= ~UART_IER_MSI;
+	cs->hw.elsa.IER |= UART_IER_MSI;
+	serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+
+	debugl1(cs,"modem quot=0x%x", quot);
+	save_flags(flags);
+	cli();
+	serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */
+	serial_outp(cs, UART_DLL, quot & 0xff);		/* LS of divisor */
+	serial_outp(cs, UART_DLM, quot >> 8);		/* MS of divisor */
+	serial_outp(cs, UART_LCR, cval);		/* reset DLAB */
+	serial_inp(cs, UART_RX);
+	restore_flags(flags);
+}
+
+static int mstartup(struct IsdnCardState *cs)
+{
+	unsigned long flags;
+	int	retval=0;
+
+
+	save_flags(flags); cli();
+
+	/*
+	 * Clear the FIFO buffers and disable them
+	 * (they will be reenabled in change_speed())
+	 */
+	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
+
+	/*
+	 * At this point there's no way the LSR could still be 0xFF;
+	 * if it is, then bail out, because there's likely no UART
+	 * here.
+	 */
+	if (serial_inp(cs, UART_LSR) == 0xff) {
+		retval = -ENODEV;
+		goto errout;
+	}
+	
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) serial_inp(cs, UART_RX);
+	(void) serial_inp(cs, UART_IIR);
+	(void) serial_inp(cs, UART_MSR);
+
+	/*
+	 * Now, initialize the UART 
+	 */
+	serial_outp(cs, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
+
+	cs->hw.elsa.MCR = 0;
+	cs->hw.elsa.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
+	
+	/*
+	 * Finally, enable interrupts
+	 */
+	cs->hw.elsa.IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+	serial_outp(cs, UART_IER, cs->hw.elsa.IER);	/* enable interrupts */
+	
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void)serial_inp(cs, UART_LSR);
+	(void)serial_inp(cs, UART_RX);
+	(void)serial_inp(cs, UART_IIR);
+	(void)serial_inp(cs, UART_MSR);
+
+	cs->hw.elsa.transcnt = cs->hw.elsa.transp = 0;
+	cs->hw.elsa.rcvcnt = cs->hw.elsa.rcvp =0;
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(cs, BASE_BAUD);
+	cs->hw.elsa.MFlag = 1;
+errout:
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void mshutdown(struct IsdnCardState *cs)
+{
+	unsigned long	flags;
+
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk(KERN_DEBUG"Shutting down serial ....");
+#endif
+	
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+
+	cs->hw.elsa.IER = 0;
+	serial_outp(cs, UART_IER, 0x00);	/* disable all intrs */
+	cs->hw.elsa.MCR &= ~UART_MCR_OUT2;
+	
+	/* disable break condition */
+	serial_outp(cs, UART_LCR, serial_inp(cs, UART_LCR) & ~UART_LCR_SBC);
+	
+	cs->hw.elsa.MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+	serial_outp(cs, UART_MCR, cs->hw.elsa.MCR);
+
+	/* disable FIFO's */	
+	serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT));
+	serial_inp(cs, UART_RX);    /* read data port to reset things */
+	
+	restore_flags(flags);
+#ifdef SERIAL_DEBUG_OPEN
+	printk(" done\n");
+#endif
+}
+
+inline int
+write_modem(struct BCState *bcs) {
+	int ret=0;
+	struct IsdnCardState *cs = bcs->cs;
+	int count, len, fp, buflen;
+	long flags;
+	
+	if (!bcs->tx_skb)
+		return 0;
+	if (bcs->tx_skb->len <= 0)
+		return 0;
+	save_flags(flags);
+	cli();
+	buflen = MAX_MODEM_BUF - cs->hw.elsa.transcnt;
+	len = MIN(buflen, bcs->tx_skb->len);		
+	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
+	fp &= (MAX_MODEM_BUF -1);
+	count = MIN(len, MAX_MODEM_BUF - fp);
+	if (count < len) {
+		memcpy(cs->hw.elsa.transbuf + fp, bcs->tx_skb->data, count);
+		skb_pull(bcs->tx_skb, count);
+		cs->hw.elsa.transcnt += count;
+		ret = count;
+		count = len - count;
+		fp = 0;
+	}
+	memcpy((cs->hw.elsa.transbuf + fp), bcs->tx_skb->data, count);
+	skb_pull(bcs->tx_skb, count);
+	cs->hw.elsa.transcnt += count;
+	ret += count;
+	
+	if (cs->hw.elsa.transcnt && 
+	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
+			cs->hw.elsa.IER |= UART_IER_THRI;
+		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+	}
+	restore_flags(flags);
+	return(ret);
+}
+
+inline void
+modem_fill(struct BCState *bcs) {
+		
+	if (bcs->tx_skb) {
+		if (bcs->tx_skb->len) {
+			write_modem(bcs);
+			return;
+		} else {
+			if (bcs->st->lli.l1writewakeup &&
+				(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st,
+						bcs->hw.hscx.count);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
+		}
+	}
+	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+		bcs->hw.hscx.count = 0;
+		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+		write_modem(bcs);
+	} else {
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		hscx_sched_event(bcs, B_XMTBUFREADY);
+	}
+}
+
+static inline void receive_chars(struct IsdnCardState *cs,
+				 int *status)
+{
+	unsigned char ch;
+	struct sk_buff *skb;
+
+	do {
+		ch = serial_in(cs, UART_RX);
+		if (cs->hw.elsa.rcvcnt >= MAX_MODEM_BUF)
+			break;
+		cs->hw.elsa.rcvbuf[cs->hw.elsa.rcvcnt++] = ch;
+#ifdef SERIAL_DEBUG_INTR
+		printk("DR%02x:%02x...", ch, *status);
+#endif
+		if (*status & (UART_LSR_BI | UART_LSR_PE |
+			       UART_LSR_FE | UART_LSR_OE)) {
+					
+#ifdef SERIAL_DEBUG_INTR
+			printk("handling exept....");
+#endif
+		}
+		*status = serial_inp(cs, UART_LSR);
+	} while (*status & UART_LSR_DR);
+	if (cs->hw.elsa.MFlag == 2) {
+		if (!(skb = dev_alloc_skb(cs->hw.elsa.rcvcnt)))
+			printk(KERN_WARNING "ElsaSER: receive out of memory\n");
+		else {
+			memcpy(skb_put(skb, cs->hw.elsa.rcvcnt), cs->hw.elsa.rcvbuf, 
+				cs->hw.elsa.rcvcnt);
+			skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb);
+		}
+		hscx_sched_event(cs->hw.elsa.bcs, B_RCVBUFREADY);
+	} else {
+		char tmp[128];
+		char *t = tmp;
+
+		t += sprintf(t, "modem read cnt %d", cs->hw.elsa.rcvcnt);
+		QuickHex(t, cs->hw.elsa.rcvbuf, cs->hw.elsa.rcvcnt);
+		debugl1(cs, tmp);
+	}
+	cs->hw.elsa.rcvcnt = 0;
+}
+
+static inline void transmit_chars(struct IsdnCardState *cs, int *intr_done)
+{
+	int count;
+	
+	debugl1(cs, "transmit_chars: p(%x) cnt(%x)", cs->hw.elsa.transp, 
+		cs->hw.elsa.transcnt);
+	
+	if (cs->hw.elsa.transcnt <= 0) {
+		cs->hw.elsa.IER &= ~UART_IER_THRI;
+		serial_out(cs, UART_IER, cs->hw.elsa.IER);
+		return;
+	}
+	count = 16;
+	do {
+		serial_outp(cs, UART_TX, cs->hw.elsa.transbuf[cs->hw.elsa.transp++]);
+		if (cs->hw.elsa.transp >= MAX_MODEM_BUF)
+			cs->hw.elsa.transp=0;
+		if (--cs->hw.elsa.transcnt <= 0)
+			break;
+	} while (--count > 0);
+	if ((cs->hw.elsa.transcnt < WAKEUP_CHARS) && (cs->hw.elsa.MFlag==2))
+		modem_fill(cs->hw.elsa.bcs);
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+	if (intr_done)
+		*intr_done = 0;
+	if (cs->hw.elsa.transcnt <= 0) {
+		cs->hw.elsa.IER &= ~UART_IER_THRI;
+		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+	}
+}
+
+#if 0
+static inline void check_modem_status(struct IsdnCardState *cs)
+{
+	int	status;
+	struct async_struct *info = cs->hw.elsa.info;
+	struct	async_icount *icount;
+	
+	status = serial_inp(info, UART_MSR);
+
+	if (status & UART_MSR_ANY_DELTA) {
+		icount = &info->state->icount;
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			icount->rng++;
+		if (status & UART_MSR_DDSR)
+			icount->dsr++;
+		if (status & UART_MSR_DDCD) {
+			icount->dcd++;
+		}
+		if (status & UART_MSR_DCTS)
+			icount->cts++;
+//		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttys%d CD now %s...", info->line,
+		       (status & UART_MSR_DCD) ? "on" : "off");
+#endif		
+		if (status & UART_MSR_DCD)
+//			wake_up_interruptible(&info->open_wait);
+;
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("doing serial hangup...");
+#endif
+			if (info->tty)
+				tty_hangup(info->tty);
+		}
+	}
+#if 0
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				serial_outp(info, UART_IER, info->IER);
+//				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				serial_outp(info, UART_IER, info->IER);
+			}
+		}
+	}
+#endif 0
+}
+#endif
+
+static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
+{
+	int status, iir, msr;
+	int pass_counter = 0;
+	
+#ifdef SERIAL_DEBUG_INTR
+	printk("rs_interrupt_single(%d)...", irq);
+#endif
+
+	do {
+		status = serial_inp(cs, UART_LSR);
+		debugl1(cs,"rs LSR %02x", status);
+#ifdef SERIAL_DEBUG_INTR
+		printk("status = %x...", status);
+#endif
+		if (status & UART_LSR_DR)
+			receive_chars(cs, &status);
+		if (status & UART_LSR_THRE)
+			transmit_chars(cs, 0);
+		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+			printk("rs_single loop break.\n");
+			break;
+		}
+		iir = serial_inp(cs, UART_IIR);
+		debugl1(cs,"rs IIR %02x", iir);
+		if ((iir & 0xf) == 0) {
+			msr = serial_inp(cs, UART_MSR);
+			debugl1(cs,"rs MSR %02x", msr);
+		}
+	} while (!(iir & UART_IIR_NO_INT));
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+
+extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
+extern void modehscx(struct BCState *bcs, int mode, int bc);
+extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
+
+void
+close_elsastate(struct BCState *bcs)
+{
+	struct sk_buff *skb;
+
+	modehscx(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.hscx.rcvbuf) {
+			if (bcs->mode != L1_MODE_MODEM)
+				kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+		}
+		while ((skb = skb_dequeue(&bcs->rqueue))) {
+			idev_kfree_skb(skb, FREE_READ);
+		}
+		while ((skb = skb_dequeue(&bcs->squeue))) {
+			idev_kfree_skb(skb, FREE_WRITE);
+		}
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+void
+modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
+	int count, fp;
+	u_char *msg = buf;
+	long flags;
+	
+	if (!len)
+		return;
+	save_flags(flags);
+	cli();		
+	if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) {
+		restore_flags(flags);
+		return;
+	}
+	fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp;
+	fp &= (MAX_MODEM_BUF -1);
+	count = MIN(len, MAX_MODEM_BUF - fp);
+	if (count < len) {
+		memcpy(cs->hw.elsa.transbuf + fp, msg, count);
+		cs->hw.elsa.transcnt += count;
+		msg += count;
+		count = len - count;
+		fp = 0;
+	}
+	memcpy(cs->hw.elsa.transbuf + fp, msg, count);
+	cs->hw.elsa.transcnt += count;
+	if (cs->hw.elsa.transcnt && 
+	    !(cs->hw.elsa.IER & UART_IER_THRI)) {
+		cs->hw.elsa.IER |= UART_IER_THRI;
+		serial_outp(cs, UART_IER, cs->hw.elsa.IER);
+	}
+	restore_flags(flags);
+}
+
+void
+modem_set_init(struct IsdnCardState *cs) {
+	long flags;
+	int timeout;
+
+#define RCV_DELAY 20000	
+	save_flags(flags);
+	sti();
+	modem_write_cmd(cs, MInit_1, strlen(MInit_1));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_2, strlen(MInit_2));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_3, strlen(MInit_3));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_4, strlen(MInit_4));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY );
+	modem_write_cmd(cs, MInit_5, strlen(MInit_5));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_6, strlen(MInit_6));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	modem_write_cmd(cs, MInit_7, strlen(MInit_7));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	restore_flags(flags);
+}
+
+void
+modem_set_dial(struct IsdnCardState *cs, int outgoing) {
+	long flags;
+	int timeout;
+#define RCV_DELAY 20000	
+
+	save_flags(flags);
+	sti();
+	modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	if (outgoing)
+		modem_write_cmd(cs, MInit_dialout, strlen(MInit_dialout));
+	else
+		modem_write_cmd(cs, MInit_dialin, strlen(MInit_dialin));
+	timeout = 1000;
+	while(timeout-- && cs->hw.elsa.transcnt)
+		udelay(1000);
+	debugl1(cs, "msi tout=%d", timeout);
+	udelay(RCV_DELAY);
+	restore_flags(flags);
+}
+
+void
+modem_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	if (pr == (PH_DATA | REQUEST)) {
+		save_flags(flags);
+		cli();
+		if (st->l1.bcs->tx_skb) {
+			skb_queue_tail(&st->l1.bcs->squeue, skb);
+			restore_flags(flags);
+		} else {
+			st->l1.bcs->tx_skb = skb;
+			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			st->l1.bcs->hw.hscx.count = 0;
+			restore_flags(flags);
+			write_modem(st->l1.bcs);
+		}
+	} else if (pr == (PH_ACTIVATE | REQUEST)) {
+		test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+		st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+		set_arcofi(st->l1.bcs->cs, st->l1.bc);
+		mstartup(st->l1.bcs->cs);
+		modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag));
+		st->l1.bcs->cs->hw.elsa.MFlag=2;
+	} else if (pr == (PH_DEACTIVATE | REQUEST)) {
+		test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+		st->l1.bcs->cs->dc.isac.arcofi_bc = st->l1.bc;
+		arcofi_fsm(st->l1.bcs->cs, ARCOFI_START, &ARCOFI_XOP_0);
+		interruptible_sleep_on(&st->l1.bcs->cs->dc.isac.arcofi_wait);
+		st->l1.bcs->cs->hw.elsa.MFlag=1;
+	} else {
+		printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr);
+	}
+}
+
+int
+setstack_elsa(struct PStack *st, struct BCState *bcs)
+{
+
+	bcs->channel = st->l1.bc;
+	switch (st->l1.mode) {
+		case L1_MODE_HDLC:
+		case L1_MODE_TRANS:
+			if (open_hscxstate(st->l1.hardware, bcs))
+				return (-1);
+			st->l2.l2l1 = hscx_l2l1;
+			break;
+		case L1_MODE_MODEM:
+			bcs->mode = L1_MODE_MODEM;
+			if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+				bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf;
+				skb_queue_head_init(&bcs->rqueue);
+				skb_queue_head_init(&bcs->squeue);
+			}
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			bcs->event = 0;
+			bcs->hw.hscx.rcvidx = 0;
+			bcs->tx_cnt = 0;
+			bcs->cs->hw.elsa.bcs = bcs;
+			st->l2.l2l1 = modem_l2l1;
+			break;
+	}
+	st->l1.bcs = bcs;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+void
+init_modem(struct IsdnCardState *cs) {
+
+	cs->bcs[0].BC_SetStack = setstack_elsa;
+	cs->bcs[1].BC_SetStack = setstack_elsa;
+	cs->bcs[0].BC_Close = close_elsastate;
+	cs->bcs[1].BC_Close = close_elsastate;
+	if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF,
+		GFP_ATOMIC))) {
+		printk(KERN_WARNING
+			"Elsa: No modem mem hw.elsa.rcvbuf\n");
+		return;
+	}
+	if (!(cs->hw.elsa.transbuf = kmalloc(MAX_MODEM_BUF,
+		GFP_ATOMIC))) {
+		printk(KERN_WARNING
+			"Elsa: No modem mem hw.elsa.transbuf\n");
+		kfree(cs->hw.elsa.rcvbuf);
+		cs->hw.elsa.rcvbuf = NULL;
+		return;
+	}
+	if (mstartup(cs)) {
+		printk(KERN_WARNING "Elsa: problem startup modem\n");
+	}
+	modem_set_init(cs);
+}
+
+void
+release_modem(struct IsdnCardState *cs) {
+
+	cs->hw.elsa.MFlag = 0;
+	if (cs->hw.elsa.transbuf) {
+		if (cs->hw.elsa.rcvbuf) {
+			mshutdown(cs);
+			kfree(cs->hw.elsa.rcvbuf);
+			cs->hw.elsa.rcvbuf = NULL;
+		}
+		kfree(cs->hw.elsa.transbuf);
+		cs->hw.elsa.transbuf = NULL;
+	}
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/foreign.c linux.pre11.3/drivers/isdn/hisax/foreign.c
--- linux.vanilla/drivers/isdn/hisax/foreign.c	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/hisax/foreign.c	Mon Jul 19 23:59:33 1999
@@ -1,780 +0,0 @@
-/* $Id: foreign.c,v 1.1 1998/11/09 07:48:48 baccala Exp $
- *
- * HiSax ISDN driver - foreign chipset interface
- *
- * Author       Brent Baccala (baccala@FreeSoft.org)
- *
- *
- *
- * $Log: foreign.c,v $
- * Revision 1.1  1998/11/09 07:48:48  baccala
- * Initial DBRI ISDN code.  Sometimes works (brings up the link and you
- * can telnet through it), sometimes doesn't (crashes the machine)
- *
- * Revision 1.2  1998/02/12 23:07:10  keil
- * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
- *
- * Revision 1.1  1998/02/03 23:20:51  keil
- * New files for SPARC isdn support
- *
- * Revision 1.1  1998/01/08 04:17:12  baccala
- * ISDN comes to the Sparc.  Key points:
- *
- *    - Existing ISDN HiSax driver provides all the smarts
- *    - it compiles, runs, talks to an isolated phone switch, connects
- *      to a Cisco, pings go through
- *    - AMD 7930 support only (no DBRI yet)
- *    - no US NI-1 support (may not work on US phone system - untested)
- *    - periodic packet loss, apparently due to lost interrupts
- *    - ISDN sometimes freezes, requiring reboot before it will work again
- *
- * The code is unreliable enough to be consider alpha
- *
- *
- * 
- */
-
-#define __NO_VERSION__
-#include "hisax.h"
-#include "isac.h"
-#include "isdnl1.h"
-#include "foreign.h"
-#include "rawhdlc.h"
-#include <linux/interrupt.h>
-
-static const char *foreign_revision = "$Revision: 1.1 $";
-
-#define RCV_BUFSIZE	1024	/* Size of raw receive buffer in bytes */
-#define RCV_BUFBLKS	4	/* Number of blocks to divide buffer into
-				 * (must divide RCV_BUFSIZE) */
-
-static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
-
-static void
-Bchan_xmt_bh(struct BCState *bcs)
-{
-	struct sk_buff *skb;
-
-	if (bcs->hw.foreign.tx_skb != NULL) {
-		dev_kfree_skb(bcs->hw.foreign.tx_skb);
-		bcs->hw.foreign.tx_skb = NULL;
-	}
-
-	if ((skb = skb_dequeue(&bcs->squeue))) {
-		Bchan_fill_fifo(bcs, skb);
-	} else {
-		clear_bit(BC_FLG_BUSY, &bcs->Flag);
-		bcs->event |= 1 << B_XMTBUFREADY;
-		queue_task(&bcs->tqueue, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
-	}
-}
-
-static void
-Bchan_xmit_callback(struct BCState *bcs)
-{
-	queue_task(&bcs->hw.foreign.tq_xmt, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
- *
- * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
- * the packet (i.e. make_raw_hdlc_data).  Since this can be a
- * time-consuming operation, our completion callback just schedules
- * a bottom half to do encapsulation for the next packet.  In between,
- * the link will just idle
- *
- * L1_MODE_TRANS - Data goes through, well, transparent.  No HDLC encap,
- * and we can't just let the link idle, so the "bottom half" actually
- * gets called during the top half (it's our callback routine in this case),
- * but it's a lot faster now since we don't call make_raw_hdlc_data
- */
-
-static void
-Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct foreign_hw *hw = &bcs->hw.foreign;
-	int len;
-
-	if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
-		char tmp[2048];
-		char *t = tmp;
-
-		t += sprintf(t, "Bchan_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', skb->len);
-		if (cs->debug & L1_DEB_HSCX_FIFO)
-			QuickHex(t, skb->data, skb->len);
-		debugl1(cs, tmp);
-	}
-
-	if (hw->doHDLCprocessing) {
-		len = make_raw_hdlc_data(skb->data, skb->len,
-					 bcs->hw.foreign.tx_buff, RAW_BUFMAX);
-		if (len > 0)
-			cs->hw.foreign->bxmit(0, bcs->channel,
-                                              bcs->hw.foreign.tx_buff, len,
-                                              (void *) &Bchan_xmit_callback,
-                                              (void *) bcs);
-		dev_kfree_skb(skb);
-	} else {
-		cs->hw.foreign->bxmit(0, bcs->channel,
-                                      skb->data, skb->len,
-                                      (void *) &Bchan_xmit_callback,
-                                      (void *) bcs);
-		bcs->hw.foreign.tx_skb = skb;
-	}
-}
-
-static void
-Bchan_mode(struct BCState *bcs, int mode, int bc)
-{
-	struct IsdnCardState *cs = bcs->cs;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "foreign mode %d bchan %d/%d",
-			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
-	bcs->mode = mode;
-}
-
-/* Bchan_l2l1 is the entry point for upper layer routines that want to
- * transmit on the B channel.  PH_DATA_REQ is a normal packet that
- * we either start transmitting (if idle) or queue (if busy).
- * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
- * once the link is idle.  After a "pull" callback, the upper layer
- * routines can use PH_PULL_IND to send data.
- */
-
-static void
-Bchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct sk_buff *skb = arg;
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				skb_queue_tail(&st->l1.bcs->squeue, skb);
-			} else {
-				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-				Bchan_fill_fifo(st->l1.bcs, skb);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				printk(KERN_WARNING "foreign: this shouldn't happen\n");
-				break;
-			}
-			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			Bchan_fill_fifo(st->l1.bcs, skb);
-			break;
-		case (PH_PULL_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
-				clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-/*
-****************************************************************************
-***************** Receiver callback and bottom half ************************
-****************************************************************************
-*/
-
-/* Bchan_recv_done() is called when a frame has been completely decoded
- * into hw->rv_skb and we're ready to hand it off to the HiSax upper
- * layer.  If a "large" packet is received, stick rv_skb on the
- * receive queue and alloc a new (large) skb to act as buffer for
- * future receives.  If a small packet is received, leave rv_skb
- * alone, alloc a new skb of the correct size, and copy the packet
- * into it.  In any case, flag the channel as B_RCVBUFREADY and
- * queue the upper layer's task.
- */
-
-static void
-Bchan_recv_done(struct BCState *bcs, unsigned int len)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct foreign_hw *hw = &bcs->hw.foreign;
-	struct sk_buff *skb;
-
-	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char tmp[2048];
-		char *t = tmp;
-
-		t += sprintf(t, "Bchan_rcv %c cnt %d (%x)", bcs->channel ? 'B' : 'A', len, hw->rv_skb->tail);
-		QuickHex(t, hw->rv_skb->tail, len);
-		debugl1(cs, tmp);
-	}
-
-	if (len > HSCX_BUFMAX/2) {
-		/* Large packet received */
-
-		if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
-			printk(KERN_WARNING "foreign: receive out of memory\n");
-		} else {
-			skb_put(hw->rv_skb, len);
-			skb_queue_tail(&bcs->rqueue, hw->rv_skb);
-			hw->rv_skb = skb;
-
-			bcs->event |= 1 << B_RCVBUFREADY;
-			queue_task(&bcs->tqueue, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
-		}
-	} else {
-		/* Small packet received */
-
-		if (!(skb = dev_alloc_skb(len))) {
-			printk(KERN_WARNING "foreign: receive out of memory\n");
-		} else {
-			memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
-			skb_queue_tail(&bcs->rqueue, skb);
-
-			bcs->event |= 1 << B_RCVBUFREADY;
-			queue_task(&bcs->tqueue, &tq_immediate);
-			mark_bh(IMMEDIATE_BH);
-		}
-	}
-}
-
-/* Bchan_recv_callback()'s behavior depends on whether we're doing local
- * HDLC processing.  If so, receive into hw->rv_buff and queue Bchan_rcv_bh
- * to decode the HDLC at leisure.  Otherwise, receive directly into hw->rv_skb
- * and call Bchan_recv_done().  In either case, prepare a new buffer for
- * further receives and hand it to the hardware driver.
- */
-
-static void
-Bchan_recv_callback(struct BCState *bcs, int error, unsigned int len)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct foreign_hw *hw = &bcs->hw.foreign;
-
-	if (hw->doHDLCprocessing) {
-
-		hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
-		hw->rv_buff_in %= RCV_BUFSIZE;
-
-		if (hw->rv_buff_in != hw->rv_buff_out) {
-			cs->hw.foreign->brecv(0, bcs->channel,
-					      hw->rv_buff + hw->rv_buff_in,
-					      RCV_BUFSIZE/RCV_BUFBLKS,
-					      (void *) &Bchan_recv_callback,
-					      (void *) bcs);
-
-		}
-		queue_task(&hw->tq_rcv, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
-
-	} else {
-		if (error) {
-			char tmp[256];
-			sprintf(tmp, "B channel %c receive error %x",
-				bcs->channel ? 'B' : 'A', error);
-			debugl1(cs, tmp);
-		} else {
-			Bchan_recv_done(bcs, len);
-		}
-		cs->hw.foreign->brecv(0, bcs->channel,
-				      hw->rv_skb->tail, HSCX_BUFMAX,
-				      (void *) &Bchan_recv_callback,
-				      (void *) bcs);
-
-	}
-}
-
-/* Bchan_rcv_bh() is a "shim" bottom half handler stuck in between
- * Bchan_recv_callback() and the HiSax upper layer if we need to
- * do local HDLC processing.
- */
-
-static void
-Bchan_rcv_bh(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct foreign_hw *hw = &bcs->hw.foreign;
-	struct sk_buff *skb;
-	int len;
-
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[1024];
-
-		sprintf(tmp, "foreign_Bchan_rcv (%d/%d)",
-			hw->rv_buff_in, hw->rv_buff_out);
-		debugl1(cs, tmp);
-	}
-
-	do {
-		if (cs->debug & L1_DEB_HSCX) {
-			char tmp[1024];
-
-			QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
-				 RCV_BUFSIZE/RCV_BUFBLKS);
-			debugl1(cs, tmp);
-		}
-
-		while ((len = read_raw_hdlc_data(hw->hdlc_state,
-						 hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
-						 hw->rv_skb->tail, HSCX_BUFMAX))) {
-			if (len > 0) {
-				Bchan_recv_done(bcs, len);
-			} else {
-				char tmp[256];
-				sprintf(tmp, "B channel %c receive error",
-					bcs->channel ? 'B' : 'A');
-				debugl1(cs, tmp);
-			}
-		}
-
-		if (hw->rv_buff_in == hw->rv_buff_out) {
-			/* Buffer was filled up - need to restart receiver */
-			cs->hw.foreign->brecv(0, bcs->channel,
-                                              hw->rv_buff + hw->rv_buff_in,
-                                              RCV_BUFSIZE/RCV_BUFBLKS,
-                                              (void *) &Bchan_recv_callback,
-                                              (void *) bcs);
-		}
-
-		hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
-		hw->rv_buff_out %= RCV_BUFSIZE;
-
-	} while (hw->rv_buff_in != hw->rv_buff_out);
-}
-
-static void
-Bchan_close(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct sk_buff *skb;
-
-	Bchan_mode(bcs, 0, 0);
-	cs->hw.foreign->bclose(0, bcs->channel);
-
-	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-	}
-	test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
-}
-
-static int
-Bchan_open(struct BCState *bcs)
-{
-	struct IsdnCardState *cs = bcs->cs;
-	struct foreign_hw *hw = &bcs->hw.foreign;
-
-	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		skb_queue_head_init(&bcs->rqueue);
-		skb_queue_head_init(&bcs->squeue);
-	}
-	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
-
-	hw->doHDLCprocessing = 0;
-	if (bcs->mode == L1_MODE_HDLC) {
-		if (cs->hw.foreign->bopen(0, bcs->channel, 1, 0xff) == -1) {
-			if (cs->hw.foreign->bopen(0, bcs->channel, 0, 0xff) == -1) {
-				return (-1);
-			}
-			hw->doHDLCprocessing = 1;
-		}
-	} else {
-		if (cs->hw.foreign->bopen(0, bcs->channel, 0, 0xff) == -1) {
-			return (-1);
-		}
-	}
-
-	hw->rv_buff_in = 0;
-	hw->rv_buff_out = 0;
-	hw->tx_skb = NULL;
-	init_hdlc_state(hw->hdlc_state, 0);
-	cs->hw.foreign->brecv(0, bcs->channel,
-                              hw->rv_buff + hw->rv_buff_in,
-                              RCV_BUFSIZE/RCV_BUFBLKS,
-                              (void *) &Bchan_recv_callback, (void *) bcs);
-
-	bcs->event = 0;
-	bcs->tx_cnt = 0;
-	return (0);
-}
-
-static void
-Bchan_init(struct BCState *bcs)
-{
-	if (!(bcs->hw.foreign.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for foreign.tx_buff\n");
-		return;
-	}
-	if (!(bcs->hw.foreign.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for foreign.rv_buff\n");
-		return;
-	}
-	if (!(bcs->hw.foreign.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for foreign.rv_skb\n");
-		return;
-	}
-	if (!(bcs->hw.foreign.hdlc_state = kmalloc(sizeof(struct hdlc_state),
-						   GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for foreign.hdlc_state\n");
-		return;
-	}
-
-	bcs->hw.foreign.tq_rcv.sync = 0;
-	bcs->hw.foreign.tq_rcv.routine = (void (*)(void *)) &Bchan_rcv_bh;
-	bcs->hw.foreign.tq_rcv.data = (void *) bcs;
-
-	bcs->hw.foreign.tq_xmt.sync = 0;
-	bcs->hw.foreign.tq_xmt.routine = (void (*)(void *)) &Bchan_xmt_bh;
-	bcs->hw.foreign.tq_xmt.data = (void *) bcs;
-}
-
-static void
-Bchan_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				Bchan_mode(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
-int
-setstack_foreign(struct PStack *st, struct BCState *bcs)
-{
-	if (Bchan_open(bcs))
-		return (-1);
-	st->l1.bcs = bcs;
-	st->l2.l2l1 = Bchan_l2l1;
-	st->ma.manl1 = Bchan_manl1;
-	setstack_manager(st);
-	bcs->st = st;
-	return (0);
-}
-
-
-static void
-foreign_drecv_callback(void *arg, int error, unsigned int count)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct tq_struct task = {0, 0, (void *) &DChannel_proc_rcv, 0};
-	struct sk_buff *skb;
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	if (1) {
-		if (!(skb = alloc_skb(count, GFP_ATOMIC)))
-			printk(KERN_WARNING "HiSax: D receive out of memory\n");
-		else {
-			memcpy(skb_put(skb, count), cs->rcvbuf, count);
-			skb_queue_tail(&cs->rq, skb);
-		}
-
-		task.data = (void *) cs;
-		queue_task(&task, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
-	}
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "foreign Drecv cnt %d", count);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->rcvbuf, count);
-		debugl1(cs, tmp);
-	}
-
-	cs->hw.foreign->drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-		      &foreign_drecv_callback, cs);
-}
-
-static void
-foreign_dxmit_callback(void *arg, int error)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) arg;
-	static struct tq_struct task = {0, 0, (void *) &DChannel_proc_xmt, 0};
-
-        /* NOTE: This function is called directly from an interrupt handler */
-
-	/* may wish to do retransmission here, if error indicates collision */
-
-	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
-
-		t += sprintf(t, "foreign Dxmit cnt %d", cs->tx_skb->len);
-		if (error) t += sprintf(t, " ERR %x", error);
-		QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
-		debugl1(cs, tmp);
-	}
-
-	cs->tx_skb = NULL;
-
-	task.data = (void *) cs;
-	queue_task(&task, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-static void
-foreign_Dchan_l2l1(struct PStack *st, int pr, void *arg)
-{
-	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
-	struct sk_buff *skb = arg;
-	char str[64];
-
-	switch (pr) {
-		case (PH_DATA_REQ):
-			if (cs->tx_skb) {
-				skb_queue_tail(&cs->sq, skb);
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
-#endif
-			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
-					/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data+4, skb->len-4,
-						  str);
-				}
-				cs->tx_skb = skb;
-				cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-				if (cs->debug & L1_DEB_LAPD)
-					Logl2Frame(cs, skb, "PH_DATA", 0);
-#endif
-				cs->hw.foreign->dxmit(0, skb->data, skb->len,
-                                                      &foreign_dxmit_callback, cs);
-			}
-			break;
-		case (PH_PULL_IND):
-			if (cs->tx_skb) {
-				if (cs->debug & L1_DEB_WARN)
-					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
-				skb_queue_tail(&cs->sq, skb);
-				break;
-			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
-			cs->tx_skb = skb;
-			cs->tx_cnt = 0;
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
-#endif
-			cs->hw.foreign->dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
-                                              &foreign_dxmit_callback, cs);
-			break;
-		case (PH_PULL_REQ):
-#ifdef L2FRAME_DEBUG		/* psa */
-			if (cs->debug & L1_DEB_LAPD)
-				debugl1(cs, "-> PH_REQUEST_PULL");
-#endif
-			if (!cs->tx_skb) {
-				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
-			} else
-				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-			break;
-	}
-}
-
-int
-setDstack_foreign(struct PStack *st, struct IsdnCardState *cs)
-{
-	st->l2.l2l1 = foreign_Dchan_l2l1;
-	if (! cs->rcvbuf) {
-		printk("setDstack_foreign: No cs->rcvbuf!\n");
-	} else {
-		cs->hw.foreign->drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
-                                      &foreign_drecv_callback, cs);
-	}
-	return (0);
-}
-
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
-
-void
-foreign_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	u_char val;
-	char tmp[32];
-	
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "foreign_l1cmd msg %x", msg);
-		debugl1(cs, tmp);
-	}
-
-	switch(msg) {
-		case PH_RESET_REQ:
-			cs->hw.foreign->liu_deactivate(0);
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
-			break;
-		case PH_ENABLE_REQ:
-			break;
-		case PH_INFO3_REQ:
-			cs->hw.foreign->liu_activate(0,0);
-			break;
-		case PH_TESTLOOP_REQ:
-			break;
-		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "foreign_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
-			}
-			break;
-	}
-}
-
-static void
-foreign_new_ph(struct IsdnCardState *cs)
-{
-	switch (cs->hw.foreign->get_liu_state(0)) {
-	        case 3:
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
-                        break;
-
-	        case 7:
-			manl1_msg(cs, PH_I4_P8_IND, NULL);
-			break;
-
-	        case 8:
-			manl1_msg(cs, PH_RSYNC_IND, NULL);
-			break;
-	}
-}
-
-/* LIU state change callback */
-
-static void
-foreign_liu_callback(struct IsdnCardState *cs)
-{
-	static struct tq_struct task = {0, 0, (void *) &foreign_new_ph, 0};
-
-	if (!cs)
-		return;
-
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "foreign LIU state %d",
-                        cs->hw.foreign->get_liu_state(0));
-		debugl1(cs, tmp);
-	}
-
-	task.data = (void *) cs;
-	queue_task(&task, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-static void init_foreign(struct IsdnCardState *cs)
-{
-	Bchan_init(&cs->bcs[0]);
-	Bchan_init(&cs->bcs[1]);
-	cs->bcs[0].BC_SetStack = setstack_foreign;
-	cs->bcs[1].BC_SetStack = setstack_foreign;
-	cs->bcs[0].BC_Close = Bchan_close;
-	cs->bcs[1].BC_Close = Bchan_close;
-	Bchan_mode(cs->bcs, 0, 0);
-	Bchan_mode(cs->bcs + 1, 0, 0);
-}
-
-static int
-foreign_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	switch (mt) {
-		case CARD_RESET:
-			return(0);
-		case CARD_RELEASE:
-			return(0);
-		case CARD_SETIRQ:
-			return(0);
-		case CARD_INIT:
-			cs->l1cmd = foreign_l1cmd;
-                        cs->setstack_d = setDstack_foreign;
-			cs->hw.foreign->liu_init(0, &foreign_liu_callback,
-                                                (void *)cs);
-			init_foreign(cs);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
-
-#if CARD_AMD7930
-extern struct foreign_interface amd7930_foreign_interface;
-#endif
-
-#if CARD_DBRI
-extern struct foreign_interface dbri_foreign_interface;
-#endif
-
-__initfunc(int
-setup_foreign(struct IsdnCard *card))
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, foreign_revision);
-	printk(KERN_INFO "HiSax: Foreign chip driver Rev. %s\n",
-               HiSax_getrev(tmp));
-
-#if CARD_AMD7930
-	if (cs->typ == ISDN_CTYPE_AMD7930) {
-                cs->hw.foreign = &amd7930_foreign_interface;
-                cs->irq = cs->hw.foreign->get_irqnum(0);
-                if (cs->irq == 0)
-                        return (0);
-                cs->cardmsg = &foreign_card_msg;
-                return (1);
-        }
-#endif
-
-#if CARD_DBRI
-	if (cs->typ == ISDN_CTYPE_DBRI) {
-                cs->hw.foreign = &dbri_foreign_interface;
-                cs->irq = cs->hw.foreign->get_irqnum(0);
-                if (cs->irq == 0)
-                        return (0);
-                cs->cardmsg = &foreign_card_msg;
-                return (1);
-        }
-#endif
-
-        return(0);
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/foreign.h linux.pre11.3/drivers/isdn/hisax/foreign.h
--- linux.vanilla/drivers/isdn/hisax/foreign.h	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/hisax/foreign.h	Mon Jul 19 23:59:33 1999
@@ -1,193 +0,0 @@
-/* $Id: foreign.h,v 1.1 1998/11/09 07:48:57 baccala Exp $
- *
- * HiSax ISDN driver - foreign chipset interface
- *
- * Author       Brent Baccala (baccala@FreeSoft.org)
- *
- *
- *
- * $Log: foreign.h,v $
- * Revision 1.1  1998/11/09 07:48:57  baccala
- * Initial DBRI ISDN code.  Sometimes works (brings up the link and you
- * can telnet through it), sometimes doesn't (crashes the machine)
- *
- */
-
-/*
- *       ISDN operations
- *
- * Many of these routines take an "int dev" argument, which is simply
- * an index into the drivers[] array.  Currently, we only support a
- * single foreign chip, so the value should always be 0.  B channel
- * operations require an "int chan", which should be 0 for channel B1
- * and 1 for channel B2
- *
- * int get_irqnum(int dev)
- *
- *   returns the interrupt number being used by the chip.  ISDN4linux
- *   uses this number to watch the interrupt during initialization and
- *   make sure something is happening.
- *
- * int get_liu_state(int dev)
- *
- *   returns the current state of the ISDN Line Interface Unit (LIU)
- *   as a number between 2 (state F2) and 7 (state F7).  0 may also be
- *   returned if the chip doesn't exist or the LIU hasn't been
- *   activated.  The meanings of the states are defined in I.430, ISDN
- *   BRI Physical Layer Interface.  The most important two states are
- *   F3 (shutdown) and F7 (syncronized).
- *
- * void liu_init(int dev, void (*callback)(void *), void *callback_arg)
- *
- *   initializes the LIU and optionally registers a callback to be
- *   signaled upon a change of LIU state.  The callback will be called
- *   with a single opaque callback_arg.  Once the callback has been
- *   triggered, get_liu_state can be used to determine the LIU
- *   current state.
- *
- * void liu_activate(int dev, int priority)
- *
- *   requests LIU activation at a given D-channel priority.
- *   Successful activatation is achieved upon entering state F7, which
- *   will trigger any callback previously registered with
- *   liu_init.
- *
- * void liu_deactivate(int dev)
- *
- *   deactivates LIU.  Outstanding D and B channel transactions are
- *   terminated rudely and without callback notification.  LIU change
- *   of state callback will be triggered, however.
- *
- * void dxmit(int dev, __u8 *buffer, unsigned int count,
- *            void (*callback)(void *, int), void *callback_arg)
- *
- *   transmits a packet - specified with buffer, count - over the D-channel
- *   interface.  Buffer should begin with the LAPD address field and
- *   end with the information field.  FCS and flag sequences should not
- *   be included, nor is bit-stuffing required - all these functions are
- *   performed by the chip.  The callback function will be called
- *   DURING THE TOP HALF OF AN INTERRUPT HANDLER and will be passed
- *   both the arbitrary callback_arg and an integer error indication:
- *
- *       0 - successful transmission; ready for next packet
- *   non-0 - error value
- *
- *   The callback routine should defer any time-consuming operations
- *   to a bottom-half handler; however, dxmit may be called
- *   from within the callback to request back-to-back transmission of
- *   a second packet (without repeating the priority/collision mechanism)
- *
- *   A comment about the "collision detect" error, which is signalled
- *   whenever the echoed D-channel data didn't match the transmitted
- *   data.  This is part of ISDN's normal multi-drop T-interface
- *   operation, indicating that another device has attempted simultaneous
- *   transmission, but can also result from line noise.  An immediate
- *   requeue via dxmit is suggested, but repeated collision
- *   errors may indicate a more serious problem.
- *
- * void drecv(int dev, __u8 *buffer, unsigned int size,
- *            void (*callback)(void *, int, unsigned int),
- *            void *callback_arg)
- *
- *   register a buffer - buffer, size - into which a D-channel packet
- *   can be received.  The callback function will be called DURING
- *   THE TOP HALF OF AN INTERRUPT HANDLER and will be passed an
- *   arbitrary callback_arg, an integer error indication and the length
- *   of the received packet, which will start with the address field,
- *   end with the information field, and not contain flag or FCS
- *   bytes.  Bit-stuffing will already have been corrected for.
- *   Possible values of second callback argument "error":
- *
- *       0 - successful reception
- *   non-0 - error value
- *
- * int bopen(int dev, int chan, int hdlcmode, u_char xmit_idle_char)
- *
- *   This function should be called before any other operations on a B
- *   channel.  mode is either non-0 to (de)encapsulate using HDLC or 0
- *   for transparent operation. In addition to arranging for interrupt
- *   handling and channel multiplexing, it sets the xmit_idle_char
- *   which is transmitted on the interface when no data buffer is
- *   available.  Suggested values are: 0 for ISDN audio; FF for HDLC
- *   mark idle; 7E for HDLC flag idle.  Returns 0 on a successful
- *   open; -1 on error.
- *
- *   If the chip doesn't support HDLC encapsulation (the Am7930
- *   doesn't), an error will be returned opening L1_MODE_HDLC; the
- *   HiSax driver should retry with L1_MODE_TRANS, then be prepared to
- *   bit-stuff the data before shipping it to the driver.
- *
- * void bclose(int dev, int chan)
- *
- *   Shuts down a B channel when no longer in use.
- *
- * void bxmit(int dev, int chan, __u8 *buffer, unsigned int count,
- *            void (*callback)(void *, int), void *callback_arg)
- *
- *   transmits a data block - specified with buffer, count - over the
- *   B channel interface specified by dev/chan.  In mode L1_MODE_HDLC,
- *   a complete HDLC frames should be relayed with a single bxmit.
- *   The callback function will be called DURING THE TOP HALF OF AN
- *   INTERRUPT HANDLER and will be passed the arbitrary callback_arg
- *   and an integer error indication:
- *
- *       0 - successful transmission; ready for next packet
- *   non-0 - error
- *
- *   The callback routine should defer any time-consuming operations
- *   to a bottom-half handler; however, bxmit may be called
- *   from within the callback to request back-to-back transmission of
- *   another data block
- *
- * void brecv(int dev, int chan, __u8 *buffer, unsigned int size,
- *            void (*callback)(void *, int, unsigned int), void *callback_arg)
- *
- *   receive a raw data block - specified with buffer, size - over the
- *   B channel interface specified by dev/chan.  The callback function
- *   will be called DURING THE TOP HALF OF AN INTERRUPT HANDLER and
- *   will be passed the arbitrary callback_arg, an integer error
- *   indication and the length of the received packet.  In HDLC mode,
- *   the packet will start with the address field, end with the
- *   information field, and will not contain flag or FCS bytes.
- *   Bit-stuffing will already have been corrected for.
- *
- *   Possible values of second callback argument "error":
- *
- *       0 - successful reception
- *   non-0 - error value
- *
- *   The callback routine should defer any time-consuming operations
- *   to a bottom-half handler; however, brecv may be called
- *   from within the callback to register another buffer and ensure
- *   continuous B channel reception without loss of data
- * */
-
-struct foreign_interface {
-    int (*get_irqnum)(int dev);
-    int (*get_liu_state)(int dev);
-    void (*liu_init)(int dev, void (*callback)(void *), void *callback_arg);
-    void (*liu_activate)(int dev, int priority);
-    void (*liu_deactivate)(int dev);
-    void (*dxmit)(int dev, __u8 *buffer, unsigned int count,
-                  void (*callback)(void *, int),
-                  void *callback_arg);
-    void (*drecv)(int dev, __u8 *buffer, unsigned int size,
-                  void (*callback)(void *, int, unsigned int),
-                  void *callback_arg);
-    int (*bopen)(int dev, unsigned int chan,
-                 int hdlcmode, u_char xmit_idle_char);
-    void (*bclose)(int dev, unsigned int chan);
-    void (*bxmit)(int dev, unsigned int chan,
-                  __u8 *buffer, unsigned long count,
-                  void (*callback)(void *, int),
-                  void *callback_arg);
-    void (*brecv)(int dev, unsigned int chan,
-                  __u8 *buffer, unsigned long size,
-                  void (*callback)(void *, int, unsigned int),
-                  void *callback_arg);
-
-    struct foreign_interface *next;
-};
-
-extern struct foreign_interface amd7930_foreign_interface;
-extern struct foreign_interface dbri_foreign_interface;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/fsm.c linux.pre11.3/drivers/isdn/hisax/fsm.c
--- linux.vanilla/drivers/isdn/hisax/fsm.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/fsm.c	Mon Jul 19 23:59:33 1999
@@ -1,4 +1,4 @@
-/* $Id: fsm.c,v 1.7 1997/11/06 17:09:13 keil Exp $
+/* $Id: fsm.c,v 1.10 1998/11/15 23:54:39 keil Exp $
 
  * Author       Karsten Keil (keil@temic-ech.spacenet.de)
  *              based on the teles driver from Jan den Ouden
@@ -7,6 +7,18 @@
  *              Fritz Elfert
  *
  * $Log: fsm.c,v $
+ * Revision 1.10  1998/11/15 23:54:39  keil
+ * changes from 2.0
+ *
+ * Revision 1.9  1998/03/26 07:10:02  paul
+ * The jumpmatrix table in struct Fsm was an array of "int". This is not
+ * large enough for pointers to functions on Linux/Alpha (instant crash
+ * on "insmod hisax). Now there is a typedef for the pointer to function.
+ * This also prevents warnings about "incompatible pointer types".
+ *
+ * Revision 1.8  1998/03/07 22:56:59  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 1.7  1997/11/06 17:09:13  keil
  * New 2.1 init code
  *
@@ -41,18 +53,18 @@
 {
 	int i;
 
-	fsm->jumpmatrix = (int *)
-	    kmalloc(4L * fsm->state_count * fsm->event_count, GFP_KERNEL);
-	memset(fsm->jumpmatrix, 0, 4L * fsm->state_count * fsm->event_count);
+	fsm->jumpmatrix = (FSMFNPTR *)
+		kmalloc(sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
+	memset(fsm->jumpmatrix, 0, sizeof (FSMFNPTR) * fsm->state_count * fsm->event_count);
 
 	for (i = 0; i < fncount; i++) 
 		if ((fnlist[i].state>=fsm->state_count) || (fnlist[i].event>=fsm->event_count)) {
-			printk(KERN_ERR "FsmNew Error line %d st(%d/%d) ev(%d/%d)\n",
-				i,fnlist[i].state,fsm->state_count,
-				fnlist[i].event,fsm->event_count);
+			printk(KERN_ERR "FsmNew Error line %d st(%ld/%ld) ev(%ld/%ld)\n",
+				i,(long)fnlist[i].state,(long)fsm->state_count,
+				(long)fnlist[i].event,(long)fsm->event_count);
 		} else		
 			fsm->jumpmatrix[fsm->state_count * fnlist[i].event +
-				fnlist[i].state] = (int) fnlist[i].routine;
+				fnlist[i].state] = (FSMFNPTR) fnlist[i].routine;
 }
 
 void
@@ -64,31 +76,26 @@
 int
 FsmEvent(struct FsmInst *fi, int event, void *arg)
 {
-	void (*r) (struct FsmInst *, int, void *);
-	char str[80];
+	FSMFNPTR r;
 
 	if ((fi->state>=fi->fsm->state_count) || (event >= fi->fsm->event_count)) {
-		printk(KERN_ERR "FsmEvent Error st(%d/%d) ev(%d/%d)\n",
-			fi->state,fi->fsm->state_count,event,fi->fsm->event_count);
+		printk(KERN_ERR "FsmEvent Error st(%ld/%ld) ev(%d/%ld)\n",
+			(long)fi->state,(long)fi->fsm->state_count,event,(long)fi->fsm->event_count);
 		return(1);
 	}
-	r = (void (*)) fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
+	r = fi->fsm->jumpmatrix[fi->fsm->state_count * event + fi->state];
 	if (r) {
-		if (fi->debug) {
-			sprintf(str, "State %s Event %s",
+		if (fi->debug)
+			fi->printdebug(fi, "State %s Event %s",
 				fi->fsm->strState[fi->state],
 				fi->fsm->strEvent[event]);
-			fi->printdebug(fi, str);
-		}
 		r(fi, event, arg);
 		return (0);
 	} else {
-		if (fi->debug) {
-			sprintf(str, "State %s Event %s no routine",
+		if (fi->debug)
+			fi->printdebug(fi, "State %s Event %s no routine",
 				fi->fsm->strState[fi->state],
 				fi->fsm->strEvent[event]);
-			fi->printdebug(fi, str);
-		}
 		return (!0);
 	}
 }
@@ -96,25 +103,18 @@
 void
 FsmChangeState(struct FsmInst *fi, int newstate)
 {
-	char str[80];
-
 	fi->state = newstate;
-	if (fi->debug) {
-		sprintf(str, "ChangeState %s",
+	if (fi->debug)
+		fi->printdebug(fi, "ChangeState %s",
 			fi->fsm->strState[newstate]);
-		fi->printdebug(fi, str);
-	}
 }
 
 static void
 FsmExpireTimer(struct FsmTimer *ft)
 {
 #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmExpireTimer %lx", (long) ft);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmExpireTimer %lx", (long) ft);
 #endif
 	FsmEvent(ft->fi, ft->event, ft->arg);
 }
@@ -126,11 +126,8 @@
 	ft->tl.function = (void *) FsmExpireTimer;
 	ft->tl.data = (long) ft;
 #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmInitTimer %lx", (long) ft);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmInitTimer %lx", (long) ft);
 #endif
 	init_timer(&ft->tl);
 }
@@ -139,11 +136,8 @@
 FsmDelTimer(struct FsmTimer *ft, int where)
 {
 #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmDelTimer %lx %d", (long) ft, where);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmDelTimer %lx %d", (long) ft, where);
 #endif
 	del_timer(&ft->tl);
 }
@@ -154,11 +148,9 @@
 {
 
 #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmAddTimer %lx %d %d", (long) ft, millisec, where);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmAddTimer %lx %d %d",
+			(long) ft, millisec, where);
 #endif
 
 	if (ft->tl.next || ft->tl.prev) {
@@ -180,11 +172,9 @@
 {
 
 #if FSM_TIMER_DEBUG
-	if (ft->fi->debug) {
-		char str[40];
-		sprintf(str, "FsmRestartTimer %lx %d %d", (long) ft, millisec, where);
-		ft->fi->printdebug(ft->fi, str);
-	}
+	if (ft->fi->debug)
+		ft->fi->printdebug(ft->fi, "FsmRestartTimer %lx %d %d",
+			(long) ft, millisec, where);
 #endif
 
 	if (ft->tl.next || ft->tl.prev)
@@ -194,25 +184,4 @@
 	ft->arg = arg;
 	ft->tl.expires = jiffies + (millisec * HZ) / 1000;
 	add_timer(&ft->tl);
-}
-
-void
-jiftime(char *s, long mark)
-{
-	s += 8;
-
-	*s-- = '\0';
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = '.';
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = mark % 6 + '0';
-	mark /= 6;
-	*s-- = ':';
-	*s-- = mark % 10 + '0';
-	mark /= 10;
-	*s-- = mark % 10 + '0';
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/gazel.c linux.pre11.3/drivers/isdn/hisax/gazel.c
--- linux.vanilla/drivers/isdn/hisax/gazel.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/gazel.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,745 @@
+/* $Id: gazel.c,v 2.3 1999/07/12 21:05:09 keil Exp $
+
+ * gazel.c     low level stuff for Gazel isdn cards
+ *
+ * Author       BeWan Systems
+ *              based on source code from Karsten Keil
+ *
+ * $Log: gazel.c,v $
+ * Revision 2.3  1999/07/12 21:05:09  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.1  1999/07/08 21:26:17  keil
+ * new card
+ *
+ * Revision 1.0  1999/28/06
+ * Initial revision
+ *
+ */
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+#include "ipac.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+
+extern const char *CardType[];
+const char *gazel_revision = "$Revision: 2.3 $";
+
+#define R647      1
+#define R685      2
+#define R753      3
+#define R742      4
+
+/* Gazel R685 stuff */
+#define GAZEL_MANUFACTURER     0x10b5
+#define GAZEL_R685             0x1030
+#define GAZEL_R753             0x1152
+#define GAZEL_DJINN_ITOO       0x1151
+
+#define PLX_CNTRL    0x50	/* registre de controle PLX */
+#define RESET_GAZEL  0x4
+#define RESET_9050   0x40000000
+#define PLX_INCSR    0x4C	/* registre d'IT du 9050 */
+#define INT_ISAC_EN  0x8	/* 1 = enable IT isac */
+#define INT_ISAC     0x20	/* 1 = IT isac en cours */
+#define INT_HSCX_EN  0x1	/* 1 = enable IT hscx */
+#define INT_HSCX     0x4	/* 1 = IT hscx en cours */
+#define INT_PCI_EN   0x40	/* 1 = enable IT PCI */
+#define INT_IPAC_EN  0x3	/* enable IT ipac */
+
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+static inline u_char
+readreg(unsigned int adr, u_short off)
+{
+	return bytein(adr + off);
+}
+
+static inline void
+writereg(unsigned int adr, u_short off, u_char data)
+{
+	byteout(adr + off, data);
+}
+
+
+static inline void
+read_fifo(unsigned int adr, u_char * data, int size)
+{
+	insb(adr, data, size);
+}
+
+static void
+write_fifo(unsigned int adr, u_char * data, int size)
+{
+	outsb(adr, data, size);
+}
+
+static inline u_char
+readreg_ipac(unsigned int adr, u_short off)
+{
+	register u_char ret;
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(adr, off);
+	ret = bytein(adr + 4);
+	restore_flags(flags);
+	return ret;
+}
+
+static inline void
+writereg_ipac(unsigned int adr, u_short off, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(adr, off);
+	byteout(adr + 4, data);
+	restore_flags(flags);
+}
+
+
+static inline void
+read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
+{
+	byteout(adr, off);
+	insb(adr + 4, data, size);
+}
+
+static void
+write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size)
+{
+	byteout(adr, off);
+	outsb(adr + 4, data, size);
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			return (readreg(cs->hw.gazel.isac, off2));
+		case R753:
+		case R742:
+			return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2));
+	}
+	return 0;
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			writereg(cs->hw.gazel.isac, off2, value);
+			break;
+		case R753:
+		case R742:
+			writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value);
+			break;
+	}
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			read_fifo(cs->hw.gazel.isacfifo, data, size);
+			break;
+		case R753:
+		case R742:
+			read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
+			break;
+	}
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			write_fifo(cs->hw.gazel.isacfifo, data, size);
+			break;
+		case R753:
+		case R742:
+			write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size);
+			break;
+	}
+}
+
+static void
+ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+			break;
+		case R753:
+		case R742:
+			read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
+			break;
+	}
+}
+
+static void
+WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size)
+{
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size);
+			break;
+		case R753:
+		case R742:
+			write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size);
+			break;
+	}
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			return (readreg(cs->hw.gazel.hscx[hscx], off2));
+		case R753:
+		case R742:
+			return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2));
+	}
+	return 0;
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	u_short off2 = offset;
+
+	switch (cs->subtyp) {
+		case R647:
+			off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf));
+		case R685:
+			writereg(cs->hw.gazel.hscx[hscx], off2, value);
+			break;
+		case R753:
+		case R742:
+			writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value);
+			break;
+	}
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 5
+	struct IsdnCardState *cs = dev_id;
+	u_char valisac, valhscx;
+	int count = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
+		return;
+	}
+	do {
+		valhscx = ReadHSCX(cs, 1, HSCX_ISTA);
+		if (valhscx)
+			hscx_int_main(cs, valhscx);
+		valisac = ReadISAC(cs, ISAC_ISTA);
+		if (valisac)
+			isac_interrupt(cs, valisac);
+		count++;
+	} while ((valhscx || valisac) && (count < MAXCOUNT));
+
+	WriteHSCX(cs, 0, HSCX_MASK, 0xFF);
+	WriteHSCX(cs, 1, HSCX_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0xFF);
+	WriteISAC(cs, ISAC_MASK, 0x0);
+	WriteHSCX(cs, 0, HSCX_MASK, 0x0);
+	WriteHSCX(cs, 1, HSCX_MASK, 0x0);
+}
+
+
+static void
+gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val;
+	int count = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "Gazel: Spurious interrupt!\n");
+		return;
+	}
+	ista = ReadISAC(cs, IPAC_ISTA - 0x80);
+	do {
+		if (ista & 0x0f) {
+			val = ReadHSCX(cs, 1, HSCX_ISTA);
+			if (ista & 0x01)
+				val |= 0x01;
+			if (ista & 0x04)
+				val |= 0x02;
+			if (ista & 0x08)
+				val |= 0x04;
+			if (val) {
+				hscx_int_main(cs, val);
+			}
+		}
+		if (ista & 0x20) {
+			val = 0xfe & ReadISAC(cs, ISAC_ISTA);
+			if (val) {
+				isac_interrupt(cs, val);
+			}
+		}
+		if (ista & 0x10) {
+			val = 0x01;
+			isac_interrupt(cs, val);
+		}
+		ista = ReadISAC(cs, IPAC_ISTA - 0x80);
+		count++;
+	}
+	while ((ista & 0x3f) && (count < MAXCOUNT));
+
+	WriteISAC(cs, IPAC_MASK - 0x80, 0xFF);
+	WriteISAC(cs, IPAC_MASK - 0x80, 0xC0);
+}
+void
+release_io_gazel(struct IsdnCardState *cs)
+{
+	unsigned int i;
+
+	switch (cs->subtyp) {
+		case R647:
+			for (i = 0x0000; i < 0xC000; i += 0x1000)
+				release_region(i + cs->hw.gazel.hscx[0], 16);
+			release_region(0xC000 + cs->hw.gazel.hscx[0], 1);
+			break;
+
+		case R685:
+			release_region(cs->hw.gazel.hscx[0], 0x100);
+			release_region(cs->hw.gazel.cfg_reg, 0x80);
+			break;
+
+		case R753:
+			release_region(cs->hw.gazel.ipac, 0x8);
+			release_region(cs->hw.gazel.cfg_reg, 0x80);
+			break;
+
+		case R742:
+			release_region(cs->hw.gazel.ipac, 8);
+			break;
+	}
+}
+
+static int
+reset_gazel(struct IsdnCardState *cs)
+{
+	long flags;
+	unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg;
+
+	switch (cs->subtyp) {
+		case R647:
+			save_flags(flags);
+			cli();
+			writereg(addr, 0, 0);
+			HZDELAY(10);
+			writereg(addr, 0, 1);
+			HZDELAY(2);
+			restore_flags(flags);
+			break;
+		case R685:
+			plxcntrl = inl(addr + PLX_CNTRL);
+			plxcntrl |= (RESET_9050 + RESET_GAZEL);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+			HZDELAY(4);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			HZDELAY(10);
+			outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR);
+			break;
+		case R753:
+			plxcntrl = inl(addr + PLX_CNTRL);
+			plxcntrl |= (RESET_9050 + RESET_GAZEL);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			plxcntrl &= ~(RESET_9050 + RESET_GAZEL);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
+			HZDELAY(4);
+			outl(plxcntrl, addr + PLX_CNTRL);
+			HZDELAY(10);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
+			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
+			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
+			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
+			outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
+			break;
+		case R742:
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20);
+			HZDELAY(4);
+			WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00);
+			WriteISAC(cs, IPAC_ACFG - 0x80, 0xff);
+			WriteISAC(cs, IPAC_AOE - 0x80, 0x0);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xff);
+			WriteISAC(cs, IPAC_CONF - 0x80, 0x1);
+			WriteISAC(cs, IPAC_MASK - 0x80, 0xc0);
+			break;
+	}
+	return (0);
+}
+
+static int
+Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			reset_gazel(cs);
+			return (0);
+		case CARD_RELEASE:
+			release_io_gazel(cs);
+			return (0);
+		case CARD_INIT:
+			inithscxisac(cs, 1);
+			if ((cs->subtyp==R647)||(cs->subtyp==R685)) {
+				int i;
+				for (i=0;i<(2+MAX_WAITING_CALLS);i++) {
+					cs->bcs[i].hw.hscx.tsaxr0 = 0x1f;
+					cs->bcs[i].hw.hscx.tsaxr1 = 0x23;
+				}
+			}
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+static int
+reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs)
+{
+	unsigned int i, base = 0, adr = 0, len = 0;
+	long flags;
+
+	save_flags(flags);
+	cli();
+
+	switch (cs->subtyp) {
+		case R647:
+			base = cs->hw.gazel.hscx[0];
+			for (i = 0x0000; i < 0xC000; i += 0x1000) {
+				if (check_region(adr = (i + base), len = 16))
+					goto error;
+			}
+			if (check_region(adr = (0xC000 + base), len = 1))
+				goto error;
+
+			for (i = 0x0000; i < 0xC000; i += 0x1000)
+				request_region(i + base, 16, "gazel");
+			request_region(0xC000 + base, 1, "gazel");
+
+			break;
+
+		case R685:
+			if (check_region(adr = cs->hw.gazel.hscx[0], len = 0x100))
+				goto error;
+			if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
+				goto error;
+
+			request_region(cs->hw.gazel.hscx[0], 0x100, "gazel");
+			request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
+			break;
+
+		case R753:
+			if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
+				goto error;
+			if (check_region(adr = cs->hw.gazel.cfg_reg, len = 0x80))
+				goto error;
+
+			request_region(cs->hw.gazel.ipac, 0x8, "gazel");
+			request_region(cs->hw.gazel.cfg_reg, 0x80, "gazel");
+			break;
+
+		case R742:
+			if (check_region(adr = cs->hw.gazel.ipac, len = 0x8))
+				goto error;
+			request_region(cs->hw.gazel.ipac, 0x8, "gazel");
+			break;
+	}
+
+	restore_flags(flags);
+	return 0;
+
+      error:
+	restore_flags(flags);
+	printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n",
+	       CardType[cs->typ], adr, adr + len);
+	return 1;
+}
+
+static int
+setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs)
+{
+	printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n");
+	// we got an irq parameter, assume it is an ISA card
+	// R742 decodes address even in not started...
+	// R647 returns FF if not present or not started
+	// eventually needs improvment
+	if (readreg_ipac(card->para[1], IPAC_ID) == 1)
+		cs->subtyp = R742;
+	else
+		cs->subtyp = R647;
+
+	cs->hw.gazel.cfg_reg = card->para[1] + 0xC000;
+	cs->hw.gazel.ipac = card->para[1];
+	cs->hw.gazel.isac = card->para[1] + 0x8000;
+	cs->hw.gazel.hscx[0] = card->para[1];
+	cs->hw.gazel.hscx[1] = card->para[1] + 0x4000;
+	cs->irq = card->para[0];
+	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
+	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
+
+	switch (cs->subtyp) {
+		case R647:
+			printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n");
+			cs->dc.isac.adf2 = 0x87;
+			printk(KERN_INFO
+				"Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+				cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+			printk(KERN_INFO
+				"Gazel: hscx A:0x%X  hscx B:0x%X\n",
+				cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+
+			break;
+		case R742:
+			printk(KERN_INFO "Gazel: Card ISA R742 found\n");
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			printk(KERN_INFO
+			       "Gazel: config irq:%d ipac:0x%X\n",
+			       cs->irq, cs->hw.gazel.ipac);
+			break;
+	}
+
+	return (0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static struct pci_dev *dev_tel __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
+
+static int
+setup_gazelpci(struct IsdnCardState *cs)
+{
+	u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0;
+	u_char pci_irq = 0, found;
+	u_int nbseek, seekcard;
+
+	printk(KERN_WARNING "Gazel: PCI card automatic recognition\n");
+
+	found = 0;
+#ifdef COMPAT_HAS_NEW_PCI
+	if (!pci_present()) {
+		printk(KERN_WARNING "Gazel: No PCI bus present\n");
+		return 1;
+	}
+#endif
+	seekcard = GAZEL_R685;
+	for (nbseek = 0; nbseek < 3; nbseek++) {
+#ifdef COMPAT_HAS_NEW_PCI
+		if ((dev_tel = pci_find_device(GAZEL_MANUFACTURER, seekcard, dev_tel))) {
+
+			pci_irq = dev_tel->irq;
+			pci_ioaddr0 = dev_tel->base_address[1];
+			pci_ioaddr1 = dev_tel->base_address[2];
+			found = 1;
+		}
+#else
+		for (; pci_index < 0xff; pci_index++) {
+			u_char pci_bus, pci_device_fn;
+			
+			if (pcibios_find_device(GAZEL_MANUFACTURER, seekcard,
+				pci_index, &pci_bus, &pci_device_fn)
+				!= PCIBIOS_SUCCESSFUL)
+				break;
+			/* get IRQ */
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+				PCI_INTERRUPT_LINE, &pci_irq);
+			/* get IO address */
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_1, &pci_ioaddr0);
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_2, &pci_ioaddr1);
+			found = 1;
+			break;
+		}
+#endif /* COMPAT_HAS_NEW_PCI */
+		if (found)
+			break;
+		else {
+			switch (seekcard) {
+				case GAZEL_R685:
+					seekcard = GAZEL_R753;
+					break;
+				case GAZEL_R753:
+					seekcard = GAZEL_DJINN_ITOO;
+					break;
+			}
+#ifndef COMPAT_HAS_NEW_PCI
+			pci_index = 0;
+#endif
+		}
+	}
+	if (!found) {
+		printk(KERN_WARNING "Gazel: No PCI card found\n");
+		return (1);
+	}
+	if (!pci_irq) {
+		printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n");
+		return 1;
+	}
+	cs->hw.gazel.pciaddr[0] = pci_ioaddr0;
+	cs->hw.gazel.pciaddr[1] = pci_ioaddr1;
+
+	pci_ioaddr1 &= 0xfffe;
+	cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe;
+	cs->hw.gazel.ipac = pci_ioaddr1;
+	cs->hw.gazel.isac = pci_ioaddr1 + 0x80;
+	cs->hw.gazel.hscx[0] = pci_ioaddr1;
+	cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40;
+	cs->hw.gazel.isacfifo = cs->hw.gazel.isac;
+	cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0];
+	cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1];
+	cs->irq = pci_irq;
+	cs->irq_flags |= SA_SHIRQ;
+
+	switch (seekcard) {
+		case GAZEL_R685:
+			printk(KERN_INFO "Gazel: Card PCI R685 found\n");
+			cs->subtyp = R685;
+			cs->dc.isac.adf2 = 0x87;
+			printk(KERN_INFO
+			    "Gazel: config irq:%d isac:0x%X  cfg:0x%X\n",
+			cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg);
+			printk(KERN_INFO
+			       "Gazel: hscx A:0x%X  hscx B:0x%X\n",
+			     cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]);
+			break;
+		case GAZEL_R753:
+		case GAZEL_DJINN_ITOO:
+			printk(KERN_INFO "Gazel: Card PCI R753 found\n");
+			cs->subtyp = R753;
+			test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+			printk(KERN_INFO
+			    "Gazel: config irq:%d ipac:0x%X  cfg:0x%X\n",
+			cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg);
+			break;
+	}
+
+	return (0);
+}
+
+__initfunc(int
+	   setup_gazel(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+	u_char val;
+
+	strcpy(tmp, gazel_revision);
+	printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp));
+
+	if (cs->typ != ISDN_CTYPE_GAZEL)
+		return (0);
+
+	if (card->para[0]) {
+		if (setup_gazelisa(card, cs))
+			return (0);
+	} else {
+
+#if CONFIG_PCI
+		if (setup_gazelpci(cs))
+			return (0);
+#else
+		printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n");
+		return (0);
+#endif				/* CONFIG_PCI */
+	}
+
+	if (reserve_regions(card, cs)) {
+		return (0);
+	}
+	if (reset_gazel(cs)) {
+		printk(KERN_WARNING "Gazel: wrong IRQ\n");
+		release_io_gazel(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &Gazel_card_msg;
+
+	switch (cs->subtyp) {
+		case R647:
+		case R685:
+			cs->irq_func = &gazel_interrupt;
+			ISACVersion(cs, "Gazel:");
+			if (HscxVersion(cs, "Gazel:")) {
+				printk(KERN_WARNING
+				       "Gazel: wrong HSCX versions check IO address\n");
+				release_io_gazel(cs);
+				return (0);
+			}
+			break;
+		case R742:
+		case R753:
+			cs->irq_func = &gazel_interrupt_ipac;
+			val = ReadISAC(cs, IPAC_ID - 0x80);
+			printk(KERN_INFO "Gazel: IPAC version %x\n", val);
+			break;
+	}
+
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_2bds0.c linux.pre11.3/drivers/isdn/hisax/hfc_2bds0.c
--- linux.vanilla/drivers/isdn/hisax/hfc_2bds0.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/hfc_2bds0.c	Mon Jul 19 23:59:33 1999
@@ -1,4 +1,4 @@
-/* $Id: hfc_2bds0.c,v 1.3 1998/02/12 23:07:22 keil Exp $
+/* $Id: hfc_2bds0.c,v 1.9 1999/07/01 08:11:35 keil Exp $
  *
  *  specific routines for CCD's HFC 2BDS0
  *
@@ -6,6 +6,25 @@
  *
  *
  * $Log: hfc_2bds0.c,v $
+ * Revision 1.9  1999/07/01 08:11:35  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.8  1998/11/15 23:54:40  keil
+ * changes from 2.0
+ *
+ * Revision 1.7  1998/09/30 22:24:45  keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6  1998/08/13 23:36:26  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5  1998/06/27 22:52:58  keil
+ * make 16.3c working with 3.0
+ *
+ * Revision 1.4  1998/05/25 12:57:52  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 1.3  1998/02/12 23:07:22  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -46,11 +65,8 @@
 		}
 		ret = bytein(cs->hw.hfcD.addr);
 #if HFC_REG_DEBUG
-		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
-			char tmp[32];
-			sprintf(tmp, "t3c RD %02x %02x", reg, ret);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+			debugl1(cs, "t3c RD %02x %02x", reg, ret);
 #endif
 	} else
 		ret = bytein(cs->hw.hfcD.addr | 1);
@@ -67,11 +83,8 @@
 	if (data)
 		byteout(cs->hw.hfcD.addr, value);
 #if HFC_REG_DEBUG
-	if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB)) {
-		char tmp[16];
-		sprintf(tmp, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_HSCX_FIFO && (data != HFCD_DATA_NODEB))
+		debugl1(cs, "t3c W%c %02x %02x", data ? 'D' : 'C', reg, value);
 #endif
 }
 
@@ -227,7 +240,6 @@
 	int chksum;
 	long flags;
 	u_char stat, cip;
-	char tmp[64];
 	
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_empty_fifo");
@@ -255,6 +267,7 @@
 	} else if (!(skb = dev_alloc_skb(count - 3)))
 		printk(KERN_WARNING "HFC: receive out of memory\n");
 	else {
+		SET_SKB_FREE(skb);
 		ptr = skb_put(skb, count - 3);
 		idx = 0;
 		cip = HFCB_FIFO | HFCB_FIFO_OUT | HFCB_REC | HFCB_CHANNEL(bcs->channel);
@@ -272,7 +285,7 @@
 			sti();
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			skb = NULL;
 		} else {
 			cli();
@@ -283,14 +296,12 @@
 			WaitNoBusy(cs);
 			stat = ReadReg(cs, HFCD_DATA, cip);
 			sti();
-			if (cs->debug & L1_DEB_HSCX) {
-				sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x",
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
 					bcs->channel, chksum, stat);
-				debugl1(cs, tmp);
-			}
 			if (stat) {
 				debugl1(cs, "FIFO CRC error");
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				skb = NULL;
 			}
 		}
@@ -315,14 +326,11 @@
 	int idx, fcnt;
 	int count;
 	u_char cip;
-	char tmp[64];
-	
 
-	if (!bcs->hw.hfc.tx_skb)
+	if (!bcs->tx_skb)
 		return;
-	if (bcs->hw.hfc.tx_skb->len <= 0)
+	if (bcs->tx_skb->len <= 0)
 		return;
-
 	save_flags(flags);
 	cli();
 	SelFiFo(cs, HFCB_SEND | HFCB_CHANNEL(bcs->channel)); 
@@ -335,12 +343,10 @@
 	bcs->hw.hfc.f2 = ReadReg(cs, HFCD_DATA, cip);
 	bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_CHANNEL(bcs->channel));
 	sti();
- 	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
+ 	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
 			bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
 			bcs->hw.hfc.send[bcs->hw.hfc.f1]);
-		debugl1(cs, tmp);
-	}
 	fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
 	if (fcnt < 0)
 		fcnt += 32;
@@ -351,13 +357,11 @@
 		return;
 	}
 	count = GetFreeFifoBytes_B(bcs);
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d count(%d/%d),%lx",
-			bcs->channel, bcs->hw.hfc.tx_skb->len,
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d count(%ld/%d),%lx",
+			bcs->channel, bcs->tx_skb->len,
 			count, current->state);
-		debugl1(cs, tmp);
-	}
-	if (count < bcs->hw.hfc.tx_skb->len) {
+	if (count < bcs->tx_skb->len) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc_fill_fifo no fifo mem");
 		restore_flags(flags);
@@ -368,26 +372,26 @@
 	cli();
 	WaitForBusy(cs);
 	WaitNoBusy(cs);
-	WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]);
-	while (idx < bcs->hw.hfc.tx_skb->len) {
+	WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+	while (idx < bcs->tx_skb->len) {
 		cli();
 		if (!WaitNoBusy(cs))
 			break;
-		WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx]);
+		WriteReg(cs, HFCD_DATA_NODEB, cip, bcs->tx_skb->data[idx]);
 		sti();
 		idx++;
 	}
-	if (idx != bcs->hw.hfc.tx_skb->len) {
+	if (idx != bcs->tx_skb->len) {
 		sti();
 		debugl1(cs, "FIFO Send BUSY error");
 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
 	} else {
-		bcs->tx_cnt -= bcs->hw.hfc.tx_skb->len;
+		bcs->tx_cnt -= bcs->tx_skb->len;
 		if (bcs->st->lli.l1writewakeup &&
-			(PACKET_NOACK != bcs->hw.hfc.tx_skb->pkt_type))
-			bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hfc.tx_skb->len);
-		dev_kfree_skb(bcs->hw.hfc.tx_skb);
-		bcs->hw.hfc.tx_skb = NULL;
+			(PACKET_NOACK != bcs->tx_skb->pkt_type))
+			bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		bcs->tx_skb = NULL;
 	}
 	WaitForBusy(cs);
 	cli();
@@ -404,15 +408,12 @@
 hfc_send_data(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	char tmp[32];
 	
 	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
 		hfc_fill_fifo(bcs);
 		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-	} else {
-		sprintf(tmp,"send_data %d blocked", bcs->channel);
-		debugl1(cs, tmp);
-	}
+	} else
+		debugl1(cs,"send_data %d blocked", bcs->channel);
 }
 
 void
@@ -424,15 +425,13 @@
 	u_char f1, f2, cip;
 	int receive, count = 5;
 	struct sk_buff *skb;
-	char tmp[64];
 
 	save_flags(flags);
     Begin:
 	count--;
 	cli();
 	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
-		sprintf(tmp,"rec_data %d blocked", bcs->channel);
-		debugl1(cs, tmp);
+		debugl1(cs,"rec_data %d blocked", bcs->channel);
 		restore_flags(flags);
 		return;
 	}
@@ -445,11 +444,9 @@
 	f2 = ReadReg(cs, HFCD_DATA, cip);
 	sti();
 	if (f1 != f2) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d f1(%d) f2(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
 				bcs->channel, f1, f2);
-			debugl1(cs, tmp);
-		}
 		cli();
 		z1 = ReadZReg(cs, HFCB_FIFO | HFCB_Z1 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
 		z2 = ReadZReg(cs, HFCB_FIFO | HFCB_Z2 | HFCB_REC | HFCB_CHANNEL(bcs->channel));
@@ -458,11 +455,9 @@
 		if (rcnt < 0)
 			rcnt += cs->hw.hfcD.bfifosize;
 		rcnt++;
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
 				bcs->channel, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
 		if ((skb = hfc_empty_fifo(bcs, rcnt))) {
 			cli();
 			skb_queue_tail(&bcs->rqueue, skb);
@@ -490,12 +485,9 @@
 {
 	struct IsdnCardState *cs = bcs->cs;
 
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "HFCD bchannel mode %d bchan %d/%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "HFCD bchannel mode %d bchan %d/%d",
 			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
 	bcs->mode = mode;
 	bcs->channel = bc;
 	switch (mode) {
@@ -543,122 +535,99 @@
 	long flags;
 
 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
 			save_flags(flags);
 			cli();
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
 				skb_queue_tail(&st->l1.bcs->squeue, skb);
 				restore_flags(flags);
 			} else {
-				st->l1.bcs->hw.hfc.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
 /*				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
 */				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 				restore_flags(flags);
 			}
 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
 				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
 				break;
 			}
 			save_flags(flags);
 			cli();
 /*			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-*/			st->l1.bcs->hw.hfc.tx_skb = skb;
+*/			st->l1.bcs->tx_skb = skb;
 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 			restore_flags(flags);
 			break;
-		case (PH_PULL_REQ):
-			if (!st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_2bs0(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
 	}
 }
 
 void
 close_2bs0(struct BCState *bcs)
 {
-	struct sk_buff *skb;
-
-	mode_2bs0(bcs, 0, 0);
+	mode_2bs0(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-		if (bcs->hw.hfc.tx_skb) {
-			dev_kfree_skb(bcs->hw.hfc.tx_skb);
-			bcs->hw.hfc.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
 	}
 }
 
 static int
-open_hfcstate(struct IsdnCardState *cs,
-	      int bc)
+open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	struct BCState *bcs = cs->bcs + bc;
-
 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 		skb_queue_head_init(&bcs->rqueue);
 		skb_queue_head_init(&bcs->squeue);
 	}
-	bcs->hw.hfc.tx_skb = NULL;
+	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	bcs->event = 0;
 	bcs->tx_cnt = 0;
 	return (0);
 }
 
-static void
-hfc_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				mode_2bs0(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
 int
 setstack_2b(struct PStack *st, struct BCState *bcs)
 {
-	if (open_hfcstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+	if (open_hfcstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
 	st->l2.l2l1 = hfc_l2l1;
-	st->ma.manl1 = hfc_manl1;
 	setstack_manager(st);
 	bcs->st = st;
+	setstack_l1_B(st);
 	return (0);
 }
 
 static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
-
-static void
 hfcd_bh(struct IsdnCardState *cs)
 {
 /*	struct PStack *stptr;
@@ -671,27 +640,27 @@
 			debugl1(cs, "D-Channel Busy cleared");
 		stptr = cs->stlist;
 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 			stptr = stptr->next;
 		}
 	}
 #endif
 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
-		switch (cs->ph_state) {
+		switch (cs->dc.hfcd.ph_state) {
 			case (0):
-				manl1_msg(cs, PH_RESET_IND, NULL);
+				l1_msg(cs, HW_RESET | INDICATION, NULL);
 				break;
 			case (3):
-				manl1_msg(cs, PH_DEACT_IND, NULL);
+				l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
 				break;
 			case (8):
-				manl1_msg(cs, PH_RSYNC_IND, NULL);
+				l1_msg(cs, HW_RSYNC | INDICATION, NULL);
 				break;
 			case (6):
-				manl1_msg(cs, PH_INFO2_IND, NULL);
+				l1_msg(cs, HW_INFO2 | INDICATION, NULL);
 				break;
 			case (7):
-				manl1_msg(cs, PH_I4_P8_IND, NULL);
+				l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
 				break;
 			default:
 				break;
@@ -722,7 +691,6 @@
 	int chksum;
 	int count=5;
 	u_char *ptr;
-	char tmp[64];
 
 	save_flags(flags);
 	cli();
@@ -745,11 +713,9 @@
 		if (rcnt < 0)
 			rcnt += cs->hw.hfcD.dfifosize;
 		rcnt++;
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcd recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
 				f1, f2, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
 		sti();
 		idx = 0;
 		cip = HFCD_FIFO | HFCD_FIFO_OUT | HFCD_REC;
@@ -771,6 +737,7 @@
 			while ((idx++ < rcnt) && WaitNoBusy(cs))
 				ReadReg(cs, HFCD_DATA_NODEB, cip);
 		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
+			SET_SKB_FREE(skb);
 			ptr = skb_put(skb, rcnt - 3);
 			while (idx < (rcnt - 3)) {
 				cli();
@@ -785,7 +752,7 @@
 				sti();
 				debugl1(cs, "RFIFO D BUSY error");
 				printk(KERN_WARNING "HFC DFIFO channel BUSY Error\n");
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				skb = NULL;
 			} else {
 				cli();
@@ -796,14 +763,12 @@
 				WaitNoBusy(cs);
 				stat = ReadReg(cs, HFCD_DATA, cip);
 				sti();
-				if (cs->debug & L1_DEB_ISAC) {
-					sprintf(tmp, "empty_dfifo chksum %x stat %x",
+				if (cs->debug & L1_DEB_ISAC)
+					debugl1(cs, "empty_dfifo chksum %x stat %x",
 						chksum, stat);
-					debugl1(cs, tmp);
-				}
 				if (stat) {
 					debugl1(cs, "FIFO CRC error");
-					dev_kfree_skb(skb);
+					idev_kfree_skb(skb, FREE_READ);
 					skb = NULL;
 				} else {
 					skb_queue_tail(&cs->rq, skb);
@@ -837,7 +802,6 @@
 	int idx, fcnt;
 	int count;
 	u_char cip;
-	char tmp[64];
 
 	if (!cs->tx_skb)
 		return;
@@ -855,12 +819,10 @@
 	cs->hw.hfcD.f2 = ReadReg(cs, HFCD_DATA, cip) & 0xf;
 	cs->hw.hfcD.send[cs->hw.hfcD.f1] = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_SEND);
 	sti();
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfc_fill_Dfifo f1(%d) f2(%d) z1(%x)",
 			cs->hw.hfcD.f1, cs->hw.hfcD.f2,
 			cs->hw.hfcD.send[cs->hw.hfcD.f1]);
-		debugl1(cs, tmp);
-	}
 	fcnt = cs->hw.hfcD.f1 - cs->hw.hfcD.f2;
 	if (fcnt < 0)
 		fcnt += 16;
@@ -871,11 +833,9 @@
 		return;
 	}
 	count = GetFreeFifoBytes_D(cs);
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "hfc_fill_Dfifo count(%d/%d)",
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfc_fill_Dfifo count(%ld/%d)",
 			cs->tx_skb->len, count);
-		debugl1(cs, tmp);
-	}
 	if (count < cs->tx_skb->len) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "hfc_fill_Dfifo no fifo mem");
@@ -905,7 +865,7 @@
 	cli();
 	WaitNoBusy(cs);
 	ReadReg(cs, HFCD_DATA, HFCD_FIFO | HFCD_F1_INC | HFCD_SEND);
-	dev_kfree_skb(cs->tx_skb);
+	idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 	cs->tx_skb = NULL;
 	sti();
 	WaitForBusy(cs);
@@ -929,25 +889,20 @@
 {
        	u_char exval;
        	struct BCState *bcs;
-	char tmp[32];
 	int count=15;
 	long flags;
 
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "HFCD irq %x %s", val,
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCD irq %x %s", val,
 			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
 			"locked" : "unlocked");
-		debugl1(cs, tmp);
-	}
 	val &= cs->hw.hfcD.int_m1;
 	if (val & 0x40) { /* TE state machine irq */
 		exval = cs->readisac(cs, HFCD_STATES) & 0xf;
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "ph_state chg %d->%d", cs->ph_state,
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state,
 				exval);
-			debugl1(cs, tmp);
-		}
-		cs->ph_state = exval;
+		cs->dc.hfcd.ph_state = exval;
 		sched_event_D(cs, D_L1STATECHANGE);
 		val &= ~0x40;
 	}
@@ -983,23 +938,19 @@
 				if (cs->debug)
 					debugl1(cs, "hfcd spurious 0x01 IRQ");
 			} else {
-				if (bcs->hw.hfc.tx_skb) {
+				if (bcs->tx_skb) {
 					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
 						hfc_fill_fifo(bcs);
 						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						sprintf(tmp,"fill_data %d blocked", bcs->channel);
-						debugl1(cs, tmp);
-					}
+					} else
+						debugl1(cs,"fill_data %d blocked", bcs->channel);
 				} else {
-					if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
 							hfc_fill_fifo(bcs);
 							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else {
-							sprintf(tmp,"fill_data %d blocked", bcs->channel);
-							debugl1(cs, tmp);
-						}
+						} else
+							debugl1(cs,"fill_data %d blocked", bcs->channel);
 					} else {
 						hfc_sched_event(bcs, B_XMTBUFREADY);
 					}
@@ -1011,23 +962,19 @@
 				if (cs->debug)
 					debugl1(cs, "hfcd spurious 0x02 IRQ");
 			} else {
-				if (bcs->hw.hfc.tx_skb) {
+				if (bcs->tx_skb) {
 					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
 						hfc_fill_fifo(bcs);
 						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-					} else {
-						sprintf(tmp,"fill_data %d blocked", bcs->channel);
-						debugl1(cs, tmp);
-					}
+					} else
+						debugl1(cs,"fill_data %d blocked", bcs->channel);
 				} else {
-					if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
 							hfc_fill_fifo(bcs);
 							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
-						} else {
-							sprintf(tmp,"fill_data %d blocked", bcs->channel);
-							debugl1(cs, tmp);
-						}
+						} else
+							debugl1(cs,"fill_data %d blocked", bcs->channel);
 					} else {
 						hfc_sched_event(bcs, B_XMTBUFREADY);
 					}
@@ -1052,7 +999,7 @@
 					}
 					goto afterXPR;
 				} else {
-					dev_kfree_skb(cs->tx_skb);
+					idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 					cs->tx_cnt = 0;
 					cs->tx_skb = NULL;
 				}
@@ -1072,10 +1019,8 @@
 		if (cs->hw.hfcD.int_s1 && count--) {
 			val = cs->hw.hfcD.int_s1;
 			cs->hw.hfcD.int_s1 = 0;
-			if (cs->debug & L1_DEB_ISAC) {
-				sprintf(tmp, "HFCD irq %x loop %d", val, 15-count);
-				debugl1(cs, tmp);
-			}
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "HFCD irq %x loop %d", val, 15-count);
 		} else
 			val = 0;
 		restore_flags(flags);
@@ -1083,13 +1028,17 @@
 }
 
 static void
-HFCD_l2l1(struct PStack *st, int pr, void *arg)
+HFCD_l1hw(struct PStack *st, int pr, void *arg)
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
-	char str[64];
+	
 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
 			if (cs->tx_skb) {
 				skb_queue_tail(&cs->sq, skb);
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -1097,12 +1046,6 @@
 					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
 #endif
 			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data + 4, skb->len - 4,
-						  str);
-				}
 				cs->tx_skb = skb;
 				cs->tx_cnt = 0;
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -1117,19 +1060,17 @@
 
 			}
 			break;
-		case (PH_PULL_IND):
+		case (PH_PULL | INDICATION):
 			if (cs->tx_skb) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
 				skb_queue_tail(&cs->sq, skb);
 				break;
 			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
+			if (cs->debug & DEB_DLOG_HEX)
 				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
 			cs->tx_skb = skb;
 			cs->tx_cnt = 0;
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -1142,47 +1083,39 @@
 			} else
 				debugl1(cs, "hfc_fill_dfifo blocked");
 			break;
-		case (PH_PULL_REQ):
+		case (PH_PULL | REQUEST):
 #ifdef L2FRAME_DEBUG		/* psa */
 			if (cs->debug & L1_DEB_LAPD)
 				debugl1(cs, "-> PH_REQUEST_PULL");
 #endif
 			if (!cs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
-	}
-}
-
-void
-hfcd_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	char tmp[32];
-	switch(msg) {
-		case PH_RESET_REQ:
+		case (HW_RESET | REQUEST):
 			cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */
 			udelay(6);
 			cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */
 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
 			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
 			break;
-		case PH_ENABLE_REQ:
+		case (HW_ENABLE | REQUEST):
 			cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION);
 			break;
-		case PH_DEACT_ACK:
+		case (HW_DEACTIVATE | REQUEST):
 			cs->hw.hfcD.mst_m &= ~HFCD_MASTER;
 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
 			break;
-		case PH_INFO3_REQ:
+		case (HW_INFO3 | REQUEST):
 			cs->hw.hfcD.mst_m |= HFCD_MASTER;
 			cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
 			break;
 #if 0
-		case PH_TESTLOOP_REQ:
+		case (HW_TESTLOOP | REQUEST):
 			u_char val = 0;
 			if (1 & (int) arg)
 				val |= 0x0c;
@@ -1208,10 +1141,8 @@
 			break;
 #endif
 		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "hfcd_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
-			}
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
 			break;
 	}
 }
@@ -1219,7 +1150,7 @@
 void
 setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
 {
-	st->l2.l2l1 = HFCD_l2l1;
+	st->l1.l1hw = HFCD_l1hw;
 }
 
 static void
@@ -1234,7 +1165,7 @@
 		stptr = cs->stlist;
 		
 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
 			stptr = stptr->next;
 		}
 	}
@@ -1260,7 +1191,6 @@
 init2bds0(struct IsdnCardState *cs))
 {
 	cs->setstack_d = setstack_hfcd;
-	cs->l1cmd = hfcd_l1cmd;
 	cs->dbusytimer.function = (void *) hfc_dbusy_timer;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_2bs0.c linux.pre11.3/drivers/isdn/hisax/hfc_2bs0.c
--- linux.vanilla/drivers/isdn/hisax/hfc_2bs0.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/hfc_2bs0.c	Mon Jul 19 23:59:33 1999
@@ -1,11 +1,27 @@
-/* $Id: hfc_2bs0.c,v 1.4 1998/02/12 23:07:29 keil Exp $
+/* $Id: hfc_2bs0.c,v 1.9 1999/07/01 08:11:36 keil Exp $
 
  *  specific routines for CCD's HFC 2BS0
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: hfc_2bs0.c,v $
+ * Revision 1.9  1999/07/01 08:11:36  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.8  1998/11/15 23:54:43  keil
+ * changes from 2.0
+ *
+ * Revision 1.7  1998/09/30 22:24:46  keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6  1998/08/13 23:36:28  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5  1998/05/25 12:57:54  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 1.4  1998/02/12 23:07:29  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -109,7 +125,6 @@
 	int idx, cnt;
 	int rcnt, z1, z2;
 	u_char cip, f1, f2;
-	char tmp[64];
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_clear_fifo");
@@ -129,21 +144,17 @@
 	z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
 	cnt = 32;
 	while (((f1 != f2) || (z1 != z2)) && cnt--) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc clear %d f1(%d) f2(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc clear %d f1(%d) f2(%d)",
 				bcs->channel, f1, f2);
-			debugl1(cs, tmp);
-		}
 		rcnt = z1 - z2;
 		if (rcnt < 0)
 			rcnt += cs->hw.hfc.fifosize;
 		if (rcnt)
 			rcnt++;
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc clear %d z1(%x) z2(%x) cnt(%d)",
 				bcs->channel, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
 		idx = 0;
 		while ((idx < rcnt) && WaitNoBusy(cs)) {
@@ -180,7 +191,6 @@
 	int idx;
 	int chksum;
 	u_char stat, cip;
-	char tmp[64];
 
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hfc_empty_fifo");
@@ -212,6 +222,7 @@
 	if (!(skb = dev_alloc_skb(count - 3)))
 		printk(KERN_WARNING "HFC: receive out of memory\n");
 	else {
+		SET_SKB_FREE(skb);
 		ptr = skb_put(skb, count - 3);
 		idx = 0;
 		cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel);
@@ -222,7 +233,7 @@
 		if (idx != count - 3) {
 			debugl1(cs, "RFIFO BUSY error");
 			printk(KERN_WARNING "HFC FIFO channel %d BUSY Error\n", bcs->channel);
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			WaitNoBusy(cs);
 			stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC |
 					       HFC_CHANNEL(bcs->channel));
@@ -235,14 +246,12 @@
 		chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip);
 		WaitNoBusy(cs);
 		stat = cs->BC_Read_Reg(cs, HFC_DATA, cip);
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc_empty_fifo %d chksum %x stat %x",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x",
 				bcs->channel, chksum, stat);
-			debugl1(cs, tmp);
-		}
 		if (stat) {
 			debugl1(cs, "FIFO CRC error");
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
 			skb = NULL;
 		}
 		WaitNoBusy(cs);
@@ -261,11 +270,10 @@
 	int idx, fcnt;
 	int count;
 	u_char cip;
-	char tmp[64];
 
-	if (!bcs->hw.hfc.tx_skb)
+	if (!bcs->tx_skb)
 		return;
-	if (bcs->hw.hfc.tx_skb->len <= 0)
+	if (bcs->tx_skb->len <= 0)
 		return;
 
 	save_flags(flags);
@@ -281,12 +289,10 @@
 	WaitNoBusy(cs);
 	bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 	bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel));
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)",
 			bcs->channel, bcs->hw.hfc.f1, bcs->hw.hfc.f2,
 			bcs->hw.hfc.send[bcs->hw.hfc.f1]);
-		debugl1(cs, tmp);
-	}
 	fcnt = bcs->hw.hfc.f1 - bcs->hw.hfc.f2;
 	if (fcnt < 0)
 		fcnt += 32;
@@ -297,13 +303,11 @@
 		return;
 	}
 	count = GetFreeFifoBytes(bcs);
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "hfc_fill_fifo %d count(%d/%d)",
-			bcs->channel, bcs->hw.hfc.tx_skb->len,
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfc_fill_fifo %d count(%ld/%d)",
+			bcs->channel, bcs->tx_skb->len,
 			count);
-		debugl1(cs, tmp);
-	}
-	if (count < bcs->hw.hfc.tx_skb->len) {
+	if (count < bcs->tx_skb->len) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "hfc_fill_fifo no fifo mem");
 		restore_flags(flags);
@@ -311,18 +315,18 @@
 	}
 	cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel);
 	idx = 0;
-	while ((idx < bcs->hw.hfc.tx_skb->len) && WaitNoBusy(cs))
-		cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->hw.hfc.tx_skb->data[idx++]);
-	if (idx != bcs->hw.hfc.tx_skb->len) {
+	while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs))
+		cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]);
+	if (idx != bcs->tx_skb->len) {
 		debugl1(cs, "FIFO Send BUSY error");
 		printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel);
 	} else {
-		count =  bcs->hw.hfc.tx_skb->len;
+		count =  bcs->tx_skb->len;
 		bcs->tx_cnt -= count;
-		if (PACKET_NOACK == bcs->hw.hfc.tx_skb->pkt_type)
+		if (PACKET_NOACK == bcs->tx_skb->pkt_type)
 			count = -1;
-		dev_kfree_skb(bcs->hw.hfc.tx_skb);
-		bcs->hw.hfc.tx_skb = NULL;
+		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		bcs->tx_skb = NULL;
 		WaitForBusy(cs);
 		WaitNoBusy(cs);
 		cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel));
@@ -343,7 +347,6 @@
 	u_char f1, f2, cip;
 	int receive, transmit, count = 5;
 	struct sk_buff *skb;
-	char tmp[64];
 
 	save_flags(flags);
       Begin:
@@ -360,11 +363,9 @@
 	WaitNoBusy(cs);
 	f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip);
 	if (f1 != f2) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d f1(%d) f2(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d f1(%d) f2(%d)",
 				bcs->channel, f1, f2);
-			debugl1(cs, tmp);
-		}
 		WaitForBusy(cs);
 		z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel));
 		z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel));
@@ -372,11 +373,9 @@
 		if (rcnt < 0)
 			rcnt += cs->hw.hfc.fifosize;
 		rcnt++;
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)",
 				bcs->channel, z1, z2, rcnt);
-			debugl1(cs, tmp);
-		}
 /*              sti(); */
 		if ((skb = hfc_empty_fifo(bcs, rcnt))) {
 			skb_queue_tail(&bcs->rqueue, skb);
@@ -388,14 +387,14 @@
 	restore_flags(flags);
 	udelay(1);
 	cli();
-	if (bcs->hw.hfc.tx_skb) {
+	if (bcs->tx_skb) {
 		transmit = 1;
 		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 		hfc_fill_fifo(bcs);
 		if (test_bit(BC_FLG_BUSY, &bcs->Flag))
 			transmit = 0;
 	} else {
-		if ((bcs->hw.hfc.tx_skb = skb_dequeue(&bcs->squeue))) {
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 			transmit = 1;
 			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 			hfc_fill_fifo(bcs);
@@ -417,13 +416,11 @@
 {
 	struct IsdnCardState *cs = bcs->cs;
 
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "HFC 2BS0 mode %d bchan %d/%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "HFC 2BS0 mode %d bchan %d/%d",
 			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
 	bcs->mode = mode;
+	bcs->channel = bc;
 
 	switch (mode) {
 		case (L1_MODE_NULL):
@@ -468,57 +465,66 @@
 	long flags;
 
 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
 			save_flags(flags);
 			cli();
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
 				skb_queue_tail(&st->l1.bcs->squeue, skb);
 				restore_flags(flags);
 			} else {
-				st->l1.bcs->hw.hfc.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
 				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 				restore_flags(flags);
 			}
 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
 				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
 				break;
 			}
 			save_flags(flags);
 			cli();
 			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->hw.hfc.tx_skb = skb;
+			st->l1.bcs->tx_skb = skb;
 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 			restore_flags(flags);
 			break;
-		case (PH_PULL_REQ):
-			if (!st->l1.bcs->hw.hfc.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_hfc(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
 	}
 }
 
+
 void
 close_hfcstate(struct BCState *bcs)
 {
-	struct sk_buff *skb;
-
-	mode_hfc(bcs, 0, 0);
+	mode_hfc(bcs, 0, bcs->channel);
 	if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-		if (bcs->hw.hfc.tx_skb) {
-			dev_kfree_skb(bcs->hw.hfc.tx_skb);
-			bcs->hw.hfc.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
 	}
@@ -526,50 +532,30 @@
 }
 
 static int
-open_hfcstate(struct IsdnCardState *cs,
-	      int bc)
+open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	struct BCState *bcs = cs->bcs + bc;
-
 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 		skb_queue_head_init(&bcs->rqueue);
 		skb_queue_head_init(&bcs->squeue);
 	}
-	bcs->hw.hfc.tx_skb = NULL;
+	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	bcs->event = 0;
 	bcs->tx_cnt = 0;
 	return (0);
 }
 
-static void
-hfc_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				mode_hfc(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
 int
 setstack_hfc(struct PStack *st, struct BCState *bcs)
 {
-	if (open_hfcstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+	if (open_hfcstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
 	st->l2.l2l1 = hfc_l2l1;
-	st->ma.manl1 = hfc_manl1;
 	setstack_manager(st);
 	bcs->st = st;
+	setstack_l1_B(st);
 	return (0);
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_pci.c linux.pre11.3/drivers/isdn/hisax/hfc_pci.c
--- linux.vanilla/drivers/isdn/hisax/hfc_pci.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/hfc_pci.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,1498 @@
+/* $Id: hfc_pci.c,v 1.7 1999/07/14 21:24:20 werner Exp $
+
+ * hfc_pci.c     low level driver for CCD´s hfc-pci based cards
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)
+ *            based on existing driver for CCD hfc ISA cards
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
+ * Copyright 1999  by Karsten Keil (keil@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_pci.c,v $
+ * Revision 1.7  1999/07/14 21:24:20  werner
+ * fixed memcpy problem when using E-channel feature
+ *
+ * Revision 1.6  1999/07/13 21:08:08  werner
+ * added echo channel logging feature.
+ *
+ * Revision 1.5  1999/07/12 21:05:10  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.4  1999/07/04 21:51:39  werner
+ * Changes to solve problems with irq sharing and smp machines
+ * Thanks to Karsten Keil and Alex Holden for giving aid with
+ * testing and debugging
+ *
+ * Revision 1.3  1999/07/01 09:43:19  keil
+ * removed additional schedules in timeouts
+ *
+ * Revision 1.2  1999/07/01 08:07:51  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hfc_pci.h"
+#include "isdnl1.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+#include <linux/interrupt.h>
+
+extern const char *CardType[];
+
+static const char *hfcpci_revision = "$Revision: 1.7 $";
+
+#if CONFIG_PCI
+/*****************************/
+/* release D- and B-channels */
+/*****************************/
+void
+releasehfcpci(struct IsdnCardState *cs)
+{
+	if (cs->bcs[0].hw.hfc.send) {
+		kfree(cs->bcs[0].hw.hfc.send);
+		cs->bcs[0].hw.hfc.send = NULL;
+	}
+	if (cs->bcs[1].hw.hfc.send) {
+		kfree(cs->bcs[1].hw.hfc.send);
+		cs->bcs[1].hw.hfc.send = NULL;
+	}
+}
+
+/******************************************/
+/* free hardware resources used by driver */
+/******************************************/
+void
+release_io_hfcpci(struct IsdnCardState *cs)
+{
+#if CONFIG_PCI
+	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0);	/* disabe memory mapped ports + busmaster */
+#endif	/* CONFIG_PCI */
+	releasehfcpci(cs);
+	del_timer(&cs->hw.hfcpci.timer);
+	kfree(cs->hw.hfcpci.share_start);
+	cs->hw.hfcpci.share_start = NULL;
+	vfree(cs->hw.hfcpci.pci_io);
+}
+
+/********************************************************************************/
+/* function called to reset the HFC PCI chip. A complete software reset of chip */
+/* and fifos is done.                                                           */
+/********************************************************************************/
+static void
+reset_hfcpci(struct IsdnCardState *cs)
+{
+	long flags;
+
+	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
+	printk(KERN_INFO "HFC_PCI: resetting card\n");
+	pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER);	/* enable memory ports + busmaster */
+	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
+	save_flags(flags);
+	sti();
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((30 * HZ) / 1000);	/* Timeout 30ms */
+	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((20 * HZ) / 1000);	/* Timeout 20ms */
+	if (Read_hfc(cs, HFCPCI_STATUS) & 2)
+		printk(KERN_WARNING "HFC-PCI init bit busy\n");
+
+	cs->hw.hfcpci.fifo_en = 0x30;	/* only D fifos enabled */
+	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
+
+	cs->hw.hfcpci.trm = 0; /* no echo connect */
+	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+
+	Write_hfc(cs, HFCPCI_CLKDEL, 0x0e);	/* ST-Bit delay for TE-Mode */
+	cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE;
+	Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);	/* S/T Auto awake */
+	cs->hw.hfcpci.bswapped = 0; /* no exchange */
+	cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
+	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
+
+	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
+	cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | 
+	                       HFCPCI_INTS_L1STATE | HFCPCI_CLTIMER;
+	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+
+	/* Clear already pending ints */
+	if (Read_hfc(cs, HFCPCI_INT_S1));
+	if (Read_hfc(cs, HFCPCI_INT_S2));
+
+	Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2);	/* HFC ST 2 */
+	udelay(10);
+	Write_hfc(cs, HFCPCI_STATES, 2);	/* HFC ST 2 */
+	cs->hw.hfcpci.mst_m = HFCPCI_MASTER;	/* HFC Master Mode */
+
+	Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+	cs->hw.hfcpci.sctrl = 0;
+	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
+	cs->hw.hfcpci.sctrl_r = 0;
+	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
+	restore_flags(flags);
+}
+
+/***************************************************/
+/* Timer function called when kernel timer expires */
+/***************************************************/
+static void
+hfcpci_Timer(struct IsdnCardState *cs)
+{
+	cs->hw.hfcpci.timer.expires = jiffies + 75;
+	/* WD RESET */
+/*      WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80);
+   add_timer(&cs->hw.hfcpci.timer);
+ */
+}
+
+
+/*********************************/
+/* schedule a new D-channel task */
+/*********************************/
+static void
+sched_event_D_pci(struct IsdnCardState *cs, int event)
+{
+	test_and_set_bit(event, &cs->event);
+	queue_task(&cs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/*********************************/
+/* schedule a new b_channel task */
+/*********************************/
+static void
+hfcpci_sched_event(struct BCState *bcs, int event)
+{
+	bcs->event |= 1 << event;
+	queue_task(&bcs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+/************************************************/
+/* select a b-channel entry matching and active */
+/************************************************/
+static
+struct BCState *
+Sel_BCS(struct IsdnCardState *cs, int channel)
+{
+	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
+		return (&cs->bcs[0]);
+	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
+		return (&cs->bcs[1]);
+	else
+		return (NULL);
+}
+
+/*********************************************/
+/* read a complete B-frame out of the buffer */
+/*********************************************/
+static struct sk_buff
+*
+hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count)
+{
+	u_char *ptr, *ptr1, new_f2;
+	struct sk_buff *skb;
+	struct IsdnCardState *cs = bcs->cs;
+	int flags, total, maxlen, new_z2;
+	z_type *zp;
+
+	save_flags(flags);
+	sti();
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "hfcpci_empty_fifo");
+	zp = &bz->za[bz->f2];	/* point to Z-Regs */
+	new_z2 = zp->z2 + count;	/* new position in fifo */
+	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
+	new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
+	if ((count > HSCX_BUFMAX + 3) || (count < 4) ||
+	    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count);
+		bz->za[new_f2].z2 = new_z2;
+		bz->f2 = new_f2;	/* next buffer */
+		skb = NULL;
+	} else if (!(skb = dev_alloc_skb(count - 3)))
+		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
+	else {
+		SET_SKB_FREE(skb);
+		total = count;
+		count -= 3;
+		ptr = skb_put(skb, count);
+
+		if (zp->z1 >= zp->z2)
+			maxlen = count;		/* complete transfer */
+		else
+			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
+
+		ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
+		memcpy(ptr, ptr1, maxlen);	/* copy data */
+		count -= maxlen;
+
+		if (count) {	/* rest remaining */
+			ptr += maxlen;
+			ptr1 = bdata;	/* start of buffer */
+			memcpy(ptr, ptr1, count);	/* rest */
+		}
+		bz->za[new_f2].z2 = new_z2;
+		bz->f2 = new_f2;	/* next buffer */
+
+	}
+	restore_flags(flags);
+	return (skb);
+}
+
+/*******************************/
+/* D-channel receive procedure */
+/*******************************/
+static
+int
+receive_dmsg(struct IsdnCardState *cs)
+{
+	struct sk_buff *skb;
+	int maxlen;
+	int rcnt, total;
+	int count = 5;
+	u_char *ptr, *ptr1;
+	dfifo_type *df;
+	z_type *zp;
+
+	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx;
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_dmsg blocked");
+		return (1);
+	}
+	while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
+		zp = &df->za[df->f2 & D_FREG_MASK];
+		rcnt = zp->z1 - zp->z2;
+		if (rcnt < 0)
+			rcnt += D_FIFO_SIZE;
+		rcnt++;
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
+				df->f1, df->f2, zp->z1, zp->z2, rcnt);
+
+		if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
+		    (df->data[zp->z1])) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
+			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
+			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
+		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
+			SET_SKB_FREE(skb);
+			total = rcnt;
+			rcnt -= 3;
+			ptr = skb_put(skb, rcnt);
+
+			if (zp->z1 >= zp->z2)
+				maxlen = rcnt;	/* complete transfer */
+			else
+				maxlen = D_FIFO_SIZE - zp->z2;	/* maximum */
+
+			ptr1 = df->data + zp->z2;	/* start of data */
+			memcpy(ptr, ptr1, maxlen);	/* copy data */
+			rcnt -= maxlen;
+
+			if (rcnt) {	/* rest remaining */
+				ptr += maxlen;
+				ptr1 = df->data;	/* start of buffer */
+				memcpy(ptr, ptr1, rcnt);	/* rest */
+			}
+			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
+			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1);
+
+			skb_queue_tail(&cs->rq, skb);
+			sched_event_D_pci(cs, D_RCVBUFREADY);
+		} else
+			printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
+	}
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	return (1);
+}
+
+/**********************************/
+/* B-channel main receive routine */
+/**********************************/
+void
+main_rec_hfcpci(struct BCState *bcs)
+{
+	long flags;
+	struct IsdnCardState *cs = bcs->cs;
+	int rcnt;
+	int receive, count = 5;
+	struct sk_buff *skb;
+	bzfifo_type *bz;
+	u_char *bdata;
+	z_type *zp;
+
+
+	save_flags(flags);
+	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
+	} else {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b1;
+	}
+      Begin:
+	count--;
+	cli();
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "rec_data %d blocked", bcs->channel);
+		restore_flags(flags);
+		return;
+	}
+	sti();
+	if (bz->f1 != bz->f2) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)",
+				bcs->channel, bz->f1, bz->f2);
+		zp = &bz->za[bz->f2];
+
+		rcnt = zp->z1 - zp->z2;
+		if (rcnt < 0)
+			rcnt += B_FIFO_SIZE;
+		rcnt++;
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)",
+				bcs->channel, zp->z1, zp->z2, rcnt);
+		if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) {
+			cli();
+			skb_queue_tail(&bcs->rqueue, skb);
+			sti();
+			hfcpci_sched_event(bcs, B_RCVBUFREADY);
+		}
+		rcnt = bz->f1 - bz->f2;
+		if (rcnt < 0)
+			rcnt += MAX_B_FRAMES + 1;
+		if (rcnt > 1)
+			receive = 1;
+		else
+			receive = 0;
+	} else
+		receive = 0;
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	if (count && receive)
+		goto Begin;
+	restore_flags(flags);
+	return;
+}
+
+/**************************/
+/* D-channel send routine */
+/**************************/
+static void
+hfcpci_fill_dfifo(struct IsdnCardState *cs)
+{
+	long flags;
+	int fcnt;
+	int count, new_z1, maxlen;
+	dfifo_type *df;
+	u_char *src, *dst, new_f1;
+
+	if (!cs->tx_skb)
+		return;
+	if (cs->tx_skb->len <= 0)
+		return;
+
+	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_tx;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
+			df->f1, df->f2,
+			df->za[df->f1 & D_FREG_MASK].z1);
+	fcnt = df->f1 - df->f2;	/* frame count actually buffered */
+	if (fcnt < 0)
+		fcnt += (MAX_D_FRAMES + 1);	/* if wrap around */
+	if (fcnt > (MAX_D_FRAMES - 1)) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci_fill_Dfifo more as 14 frames");
+		return;
+	}
+	/* now determine free bytes in FIFO buffer */
+	count = df->za[df->f1 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1;
+	if (count <= 0)
+		count += D_FIFO_SIZE;	/* count now contains available bytes */
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "hfcpci_fill_Dfifo count(%ld/%d)",
+			cs->tx_skb->len, count);
+	if (count < cs->tx_skb->len) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci_fill_Dfifo no fifo mem");
+		return;
+	}
+	count = cs->tx_skb->len;	/* get frame len */
+	new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1);
+	new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
+	src = cs->tx_skb->data;	/* source pointer */
+	dst = df->data + df->za[df->f1 & D_FREG_MASK].z1;
+	maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1;		/* end fifo */
+	if (maxlen > count)
+		maxlen = count;	/* limit size */
+	memcpy(dst, src, maxlen);	/* first copy */
+
+	count -= maxlen;	/* remaining bytes */
+	if (count) {
+		dst = df->data;	/* start of buffer */
+		src += maxlen;	/* new position */
+		memcpy(dst, src, count);
+	}
+	save_flags(flags);
+	cli();
+	df->za[new_f1 & D_FREG_MASK].z1 = new_z1;	/* for next buffer */
+	df->za[df->f1 & D_FREG_MASK].z1 = new_z1;	/* new pos actual buffer */
+	df->f1 = new_f1;	/* next frame */
+	restore_flags(flags);
+
+	idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+	cs->tx_skb = NULL;
+	return;
+}
+
+/**************************/
+/* B-channel send routine */
+/**************************/
+static void
+hfcpci_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int flags, maxlen, fcnt;
+	int count, new_z1;
+	bzfifo_type *bz;
+	u_char *bdata;
+	u_char new_f1, *src, *dst;
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	save_flags(flags);
+	sti();
+
+	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2;
+	} else {
+		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
+		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1;
+	}
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfcpci_fill_fifo %d f1(%d) f2(%d) z1(f1)(%x)",
+			bcs->channel, bz->f1, bz->f2,
+			bz->za[bz->f1].z1);
+
+	fcnt = bz->f1 - bz->f2;	/* frame count actually buffered */
+	if (fcnt < 0)
+		fcnt += (MAX_B_FRAMES + 1);	/* if wrap around */
+	if (fcnt > (MAX_B_FRAMES - 1)) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames");
+		restore_flags(flags);
+		return;
+	}
+	/* now determine free bytes in FIFO buffer */
+	count = bz->za[bz->f1].z2 - bz->za[bz->f1].z1;
+	if (count <= 0)
+		count += B_FIFO_SIZE;	/* count now contains available bytes */
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hfcpci_fill_fifo %d count(%ld/%d),%lx",
+			bcs->channel, bcs->tx_skb->len,
+			count, current->state);
+
+	if (count < bcs->tx_skb->len) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "hfcpci_fill_fifo no fifo mem");
+		restore_flags(flags);
+		return;
+	}
+	count = bcs->tx_skb->len;	/* get frame len */
+	new_z1 = bz->za[bz->f1].z1 + count;	/* new buffer Position */
+	if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
+		new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
+
+	new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
+	src = bcs->tx_skb->data;	/* source pointer */
+	dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL);
+	maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1;		/* end fifo */
+	if (maxlen > count)
+		maxlen = count;	/* limit size */
+	memcpy(dst, src, maxlen);	/* first copy */
+
+	count -= maxlen;	/* remaining bytes */
+	if (count) {
+		dst = bdata;	/* start of buffer */
+		src += maxlen;	/* new position */
+		memcpy(dst, src, count);
+	}
+	bcs->tx_cnt -= bcs->tx_skb->len;
+	if (bcs->st->lli.l1writewakeup &&
+	    (PACKET_NOACK != bcs->tx_skb->pkt_type))
+		bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+
+	cli();
+	bz->za[new_f1].z1 = new_z1;	/* for next buffer */
+	bz->f1 = new_f1;	/* next frame */
+	restore_flags(flags);
+
+	idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	return;
+}
+
+/***********************/
+/* set/reset echo mode */
+/***********************/ 
+int hfcpci_set_echo(struct IsdnCardState *cs, int i)
+{
+  if (cs->chanlimit > 1)
+    return(-EINVAL);
+  if (i) {
+    cs->logecho = 1;
+    cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */
+    cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
+    cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
+  }
+  else {
+    cs->logecho = 0;
+    cs->hw.hfcpci.trm &= ~0x20; /* enable echo chan */
+    cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
+    cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
+  }
+    cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
+    cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
+    cs->hw.hfcpci.conn &= ~0x18;
+    cs->hw.hfcpci.ctmt &= ~2;
+  Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
+  Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
+  Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
+  Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+  Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
+  Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
+  Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+  return(0);
+} /* hfcpci_set_echo */ 
+
+/*****************************/
+/* E-channel receive routine */
+/*****************************/
+static void receive_emsg(struct IsdnCardState *cs)
+{
+	long flags;
+	int rcnt;
+	int receive, count = 5;
+	bzfifo_type *bz;
+	u_char *bdata;
+	z_type *zp;
+	u_char *ptr, *ptr1, new_f2;
+	int total, maxlen, new_z2;
+	u_char e_buffer[256];
+
+	save_flags(flags);
+	bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
+	bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
+      Begin:
+	count--;
+	cli();
+	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		debugl1(cs, "echo_rec_data blocked");
+		restore_flags(flags);
+		return;
+	}
+	sti();
+	if (bz->f1 != bz->f2) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)",
+				bz->f1, bz->f2);
+		zp = &bz->za[bz->f2];
+
+		rcnt = zp->z1 - zp->z2;
+		if (rcnt < 0)
+			rcnt += B_FIFO_SIZE;
+		rcnt++;
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
+				zp->z1, zp->z2, rcnt);
+                new_z2 = zp->z2 + rcnt; /* new position in fifo */
+		if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
+		  new_z2 -= B_FIFO_SIZE; /* buffer wrap */
+		new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
+	        if ((rcnt > 256 + 3) || (count < 4) ||
+		    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
+		  if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
+		  bz->za[new_f2].z2 = new_z2;
+		  bz->f2 = new_f2;	/* next buffer */
+		} else {
+		    total = rcnt;
+		    rcnt -= 3;
+		    ptr = e_buffer;
+
+		    if (zp->z1 >= zp->z2)
+			maxlen = rcnt;		/* complete transfer */
+		    else
+			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
+
+		    ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
+		    memcpy(ptr, ptr1, maxlen);	/* copy data */
+		    rcnt -= maxlen;
+
+		    if (rcnt) {	/* rest remaining */
+			ptr += maxlen;
+			ptr1 = bdata;	/* start of buffer */
+			memcpy(ptr, ptr1, rcnt);	/* rest */
+		    }
+		    bz->za[new_f2].z2 = new_z2;
+		    bz->f2 = new_f2;	/* next buffer */
+		    if (cs->debug & DEB_DLOG_HEX) {
+		      	ptr = cs->dlog;
+			if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
+			  *ptr++ = 'E';
+			  *ptr++ = 'C';
+			  *ptr++ = 'H';
+			  *ptr++ = 'O';
+			  *ptr++ = ':';
+			  ptr += QuickHex(ptr, e_buffer, total - 3);
+			  ptr--;
+			  *ptr++ = '\n';
+			  *ptr = 0;
+			  HiSax_putstatus(cs, NULL, cs->dlog);
+			} else
+			  HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
+		    }
+
+	}
+
+		rcnt = bz->f1 - bz->f2;
+		if (rcnt < 0)
+			rcnt += MAX_B_FRAMES + 1;
+		if (rcnt > 1)
+			receive = 1;
+		else
+			receive = 0;
+	} else
+		receive = 0;
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	if (count && receive)
+		goto Begin;
+	restore_flags(flags);
+	return;
+} /* receive_emsg */
+
+/*********************/
+/* Interrupt handler */
+/*********************/
+static void
+hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char exval;
+	struct BCState *bcs;
+	int count = 15;
+	long flags;
+	u_char val, stat;
+
+	if (!cs) {
+		printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n");
+		return;
+	}
+	if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
+		val = Read_hfc(cs, HFCPCI_INT_S1);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val);
+	} else
+		return;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFC-PCI irq %x %s", val,
+			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
+			"locked" : "unlocked");
+	val &= cs->hw.hfcpci.int_m1;
+	if (val & 0x40) {	/* TE state machine irq */
+		exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
+				exval);
+		cs->dc.hfcpci.ph_state = exval;
+		sched_event_D_pci(cs, D_L1STATECHANGE);
+		val &= ~0x40;
+	}
+	while (val) {
+		save_flags(flags);
+		cli();
+		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			cs->hw.hfcpci.int_s1 |= val;
+			restore_flags(flags);
+			return;
+		}
+		if (cs->hw.hfcpci.int_s1 & 0x18) {
+			exval = val;
+			val = cs->hw.hfcpci.int_s1;
+			cs->hw.hfcpci.int_s1 = exval;
+		}
+		if (val & 0x08) {
+			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) {
+				if (cs->debug)
+					debugl1(cs, "hfcpci spurious 0x08 IRQ");
+			} else
+				main_rec_hfcpci(bcs);
+		}
+		if (val & 0x10) { 
+		        if (cs->logecho)
+			  receive_emsg(cs);
+			else    
+			if (!(bcs = Sel_BCS(cs, 1))) {
+				if (cs->debug)
+					debugl1(cs, "hfcpci spurious 0x10 IRQ");
+			} else
+				main_rec_hfcpci(bcs);
+		}
+		if (val & 0x01) {
+			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1:0))) {
+				if (cs->debug)
+					debugl1(cs, "hfcpci spurious 0x01 IRQ");
+			} else {
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcpci_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcpci_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
+			}
+		}
+		if (val & 0x02) {
+			if (!(bcs = Sel_BCS(cs, 1))) {
+				if (cs->debug)
+					debugl1(cs, "hfcpci spurious 0x02 IRQ");
+			} else {
+				if (bcs->tx_skb) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_fifo(bcs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else
+						debugl1(cs, "fill_data %d blocked", bcs->channel);
+				} else {
+					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+							hfcpci_fill_fifo(bcs);
+							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+						} else
+							debugl1(cs, "fill_data %d blocked", bcs->channel);
+					} else {
+						hfcpci_sched_event(bcs, B_XMTBUFREADY);
+					}
+				}
+			}
+		}
+		if (val & 0x20) {	/* receive dframe */
+			receive_dmsg(cs);
+		}
+		if (val & 0x04) {	/* dframe transmitted */
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				sched_event_D_pci(cs, D_CLEARBUSY);
+			if (cs->tx_skb) {
+				if (cs->tx_skb->len) {
+					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+						hfcpci_fill_dfifo(cs);
+						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+					} else {
+						debugl1(cs, "hfcpci_fill_dfifo irq blocked");
+					}
+					goto afterXPR;
+				} else {
+					idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+					cs->tx_cnt = 0;
+					cs->tx_skb = NULL;
+				}
+			}
+			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
+				cs->tx_cnt = 0;
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcpci_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else {
+					debugl1(cs, "hfcpci_fill_dfifo irq blocked");
+				}
+			} else
+				sched_event_D_pci(cs, D_XMTBUFREADY);
+		}
+	      afterXPR:
+		if (cs->hw.hfcpci.int_s1 && count--) {
+			val = cs->hw.hfcpci.int_s1;
+			cs->hw.hfcpci.int_s1 = 0;
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count);
+		} else
+			val = 0;
+		restore_flags(flags);
+	}
+}
+
+/********************************************************************/
+/* timer callback for D-chan busy resolution. Currently no function */
+/********************************************************************/
+static void
+hfcpci_dbusy_timer(struct IsdnCardState *cs)
+{
+#if 0
+	struct PStack *stptr;
+	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
+		if (cs->debug)
+			debugl1(cs, "D-Channel Busy");
+		test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
+		stptr = cs->stlist;
+
+		while (stptr != NULL) {
+			stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
+			stptr = stptr->next;
+		}
+	}
+#endif
+}
+
+/*************************************/
+/* Layer 1 D-channel hardware access */
+/*************************************/
+static void
+HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
+{
+	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
+	struct sk_buff *skb = arg;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			if (cs->tx_skb) {
+				skb_queue_tail(&cs->sq, skb);
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
+#endif
+			} else {
+				cs->tx_skb = skb;
+				cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+				if (cs->debug & L1_DEB_LAPD)
+					Logl2Frame(cs, skb, "PH_DATA", 0);
+#endif
+				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+					hfcpci_fill_dfifo(cs);
+					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+				} else
+					debugl1(cs, "hfcpci_fill_dfifo blocked");
+
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (cs->tx_skb) {
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
+				skb_queue_tail(&cs->sq, skb);
+				break;
+			}
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
+			cs->tx_skb = skb;
+			cs->tx_cnt = 0;
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
+#endif
+			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+				hfcpci_fill_dfifo(cs);
+				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+			} else
+				debugl1(cs, "hfcpci_fill_dfifo blocked");
+			break;
+		case (PH_PULL | REQUEST):
+#ifdef L2FRAME_DEBUG		/* psa */
+			if (cs->debug & L1_DEB_LAPD)
+				debugl1(cs, "-> PH_REQUEST_PULL");
+#endif
+			if (!cs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (HW_RESET | REQUEST):
+			Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);	/* HFC ST 3 */
+			udelay(6);
+			Write_hfc(cs, HFCPCI_STATES, 3);	/* HFC ST 2 */
+			cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
+			break;
+		case (HW_ENABLE | REQUEST):
+			Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
+			break;
+		case (HW_DEACTIVATE | REQUEST):
+      			cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			break;
+		case (HW_INFO3 | REQUEST):
+			cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			break;
+#if 0
+		case (HW_TESTLOOP | REQUEST):
+			u_char val = 0;
+			if (1 & (int) arg)
+				val |= 0x0c;
+			if (2 & (int) arg)
+				val |= 0x3;
+			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
+				/* IOM 1 Mode */
+				if (!val) {
+					cs->writeisac(cs, ISAC_SPCR, 0xa);
+					cs->writeisac(cs, ISAC_ADF1, 0x2);
+				} else {
+					cs->writeisac(cs, ISAC_SPCR, val);
+					cs->writeisac(cs, ISAC_ADF1, 0xa);
+				}
+			} else {
+				/* IOM 2 Mode */
+				cs->writeisac(cs, ISAC_SPCR, val);
+				if (val)
+					cs->writeisac(cs, ISAC_ADF1, 0x8);
+				else
+					cs->writeisac(cs, ISAC_ADF1, 0x0);
+			}
+			break;
+#endif
+		default:
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
+			break;
+	}
+}
+
+/***********************************************/
+/* called during init setting l1 stack pointer */
+/***********************************************/
+void
+setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
+{
+	st->l1.l1hw = HFCPCI_l1hw;
+}
+
+/**************************************/
+/* send B-channel data if not blocked */
+/**************************************/
+static void
+hfcpci_send_data(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+		hfcpci_fill_fifo(bcs);
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		debugl1(cs, "send_data %d blocked", bcs->channel);
+}
+
+/***************************************************************/
+/* activate/deactivate hardware for selected channels and mode */
+/***************************************************************/
+void
+mode_hfcpci(struct BCState *bcs, int mode, int bc)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int flags;
+
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d",
+			mode, bc, bcs->channel);
+	bcs->mode = mode;
+	bcs->channel = bc;
+	if (cs->chanlimit > 1) { 
+	  cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
+	  cs->hw.hfcpci.sctrl_e &= ~0x80; 
+	}
+	else {
+	  if (bc) {
+	    cs->hw.hfcpci.bswapped = 1; /* B1 and B2 exchanged */
+	    cs->hw.hfcpci.sctrl_e |= 0x80;
+	    bc = 0; /* B1 controller used */
+	  }
+	  else {
+	    cs->hw.hfcpci.bswapped = 0; /* B1 and B2 normal mode */
+	    cs->hw.hfcpci.sctrl_e &= ~0x80; 
+	  }  
+	}  
+	save_flags(flags);
+	cli();
+	switch (mode) {
+		case (L1_MODE_NULL):
+			if (bc) {
+				cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
+				cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
+				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
+				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
+			} else {
+				cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA;
+				cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA;
+				cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
+				cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+			}
+			break;
+		case (L1_MODE_TRANS):
+			if (bc) {
+				cs->hw.hfcpci.ctmt |= 2;
+				cs->hw.hfcpci.conn &= ~0x18;
+				cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
+				cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
+			} else {
+				cs->hw.hfcpci.ctmt |= 1;
+				cs->hw.hfcpci.conn &= ~0x3;
+				cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
+				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+			}
+			break;
+		case (L1_MODE_HDLC):
+			if (bc) {
+				cs->hw.hfcpci.ctmt &= ~2;
+				cs->hw.hfcpci.conn &= ~0x18;
+				cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
+				cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS+HFCPCI_INTS_B2REC);
+			} else {
+				cs->hw.hfcpci.ctmt &= ~1;
+				cs->hw.hfcpci.conn &= ~0x3;
+				cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
+				cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
+				cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
+				cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS+HFCPCI_INTS_B1REC);
+			}
+			break;
+	}
+	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+	restore_flags(flags);
+	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
+	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
+	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
+	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
+	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
+}
+
+/******************************/
+/* Layer2 -> Layer 1 Transfer */
+/******************************/
+static void
+hfcpci_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			save_flags(flags);
+			cli();
+			if (st->l1.bcs->tx_skb) {
+				skb_queue_tail(&st->l1.bcs->squeue, skb);
+				restore_flags(flags);
+			} else {
+				st->l1.bcs->tx_skb = skb;
+/*                              test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+				restore_flags(flags);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
+				printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
+				break;
+			}
+			save_flags(flags);
+			cli();
+/*                      test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+ */ st->l1.bcs->tx_skb = skb;
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			restore_flags(flags);
+			break;
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_hfcpci(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_hfcpci(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
+	}
+}
+
+/******************************************/
+/* deactivate B-channel access and queues */
+/******************************************/
+static void
+close_hfcpci(struct BCState *bcs)
+{
+	mode_hfcpci(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		}
+	}
+}
+
+/*************************************/
+/* init B-channel queues and control */
+/*************************************/
+static int
+open_hfcpcistate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+/*********************************/
+/* inits the stack for B-channel */
+/*********************************/
+static int
+setstack_2b(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_hfcpcistate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = hfcpci_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+/***************************/
+/* handle L1 state changes */
+/***************************/
+static void
+hfcpci_bh(struct IsdnCardState *cs)
+{
+/*      struct PStack *stptr;
+ */
+	if (!cs)
+		return;
+#if 0
+	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
+		if (cs->debug)
+			debugl1(cs, "D-Channel Busy cleared");
+		stptr = cs->stlist;
+		while (stptr != NULL) {
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
+			stptr = stptr->next;
+		}
+	}
+#endif
+	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+		switch (cs->dc.hfcpci.ph_state) {
+			case (0):
+				l1_msg(cs, HW_RESET | INDICATION, NULL);
+				break;
+			case (3):
+				l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
+				break;
+			case (8):
+				l1_msg(cs, HW_RSYNC | INDICATION, NULL);
+				break;
+			case (6):
+				l1_msg(cs, HW_INFO2 | INDICATION, NULL);
+				break;
+			case (7):
+				l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
+				break;
+			default:
+				break;
+		}
+	}
+	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
+		DChannel_proc_rcv(cs);
+	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
+		DChannel_proc_xmt(cs);
+}
+
+
+/*************************************/
+/* Alloc memory send data for queues */
+/*************************************/
+__initfunc(unsigned int
+	   *init_send_hfcpci(int cnt))
+{
+	int i, *send;
+
+	if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) {
+		printk(KERN_WARNING
+		       "HiSax: No memory for hfcpci.send\n");
+		return (NULL);
+	}
+	for (i = 0; i < cnt; i++)
+		send[i] = 0x1fff;
+	return (send);
+}
+
+/********************************/
+/* called for card init message */
+/********************************/
+__initfunc(void
+	   inithfcpci(struct IsdnCardState *cs))
+{
+	cs->setstack_d = setstack_hfcpci;
+	cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
+	cs->dbusytimer.data = (long) cs;
+	init_timer(&cs->dbusytimer);
+	cs->tqueue.routine = (void *) (void *) hfcpci_bh;
+#if 0
+	if (!cs->hw.hfcpci.send)
+		cs->hw.hfcpci.send = init_send_hfcpci(16);
+#endif
+	if (!cs->bcs[0].hw.hfc.send)
+		cs->bcs[0].hw.hfc.send = init_send_hfcpci(32);
+	if (!cs->bcs[1].hw.hfc.send)
+		cs->bcs[1].hw.hfc.send = init_send_hfcpci(32);
+	cs->BC_Send_Data = &hfcpci_send_data;
+	cs->bcs[0].BC_SetStack = setstack_2b;
+	cs->bcs[1].BC_SetStack = setstack_2b;
+	cs->bcs[0].BC_Close = close_hfcpci;
+	cs->bcs[1].BC_Close = close_hfcpci;
+	mode_hfcpci(cs->bcs, 0, 0);
+	mode_hfcpci(cs->bcs + 1, 0, 1);
+}
+
+
+
+/*******************************************/
+/* handle card messages from control layer */
+/*******************************************/
+static int
+hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	long flags;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCPCI: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			reset_hfcpci(cs);
+			return (0);
+		case CARD_RELEASE:
+			release_io_hfcpci(cs);
+			return (0);
+		case CARD_INIT:
+			inithfcpci(cs);
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((80 * HZ) / 1000);	/* Timeout 80ms */
+			/* now switch timer interrupt off */
+			cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
+			Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+			/* reinit mode reg */
+			Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
+			restore_flags(flags);
+			return (0);
+		case CARD_TEST:
+			return (0);
+	}
+	return (0);
+}
+
+
+/* this variable is used as card index when more than one cards are present */
+#ifdef COMPAT_HAS_NEW_PCI
+static struct pci_dev *dev_hfcpci __initdata = NULL;
+#else
+static int pci_index __initdata = 0;
+#endif
+
+#endif				/* CONFIG_PCI */
+
+__initfunc(int
+	   setup_hfcpci(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, hfcpci_revision);
+	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
+#if CONFIG_PCI
+	cs->hw.hfcpci.int_s1 = 0;
+#if 0
+	cs->hw.hfcpci.send = NULL;
+#endif
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->dc.hfcpci.ph_state = 0;
+	cs->hw.hfcpci.fifo = 255;
+	if (cs->typ == ISDN_CTYPE_HFC_PCI) {
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "HFC-PCI: no PCI bus present\n");
+			return (0);
+		}
+		if ((dev_hfcpci = pci_find_device(PCI_VENDOR_CCD,
+					  PCI_CCD_PCI_ID, dev_hfcpci))) {
+			cs->hw.hfcpci.pci_bus = dev_hfcpci->bus->number;
+			cs->hw.hfcpci.pci_device_fn = dev_hfcpci->devfn;
+			cs->irq = dev_hfcpci->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+				return (0);
+			}
+			cs->hw.hfcpci.pci_io = (char *)
+			    dev_hfcpci->base_address[1];
+		} else {
+			printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+			return (0);
+		}
+#else
+		for (; pci_index < 255; pci_index++) {
+			unsigned char irq;
+
+			if (pcibios_find_device(PCI_VENDOR_CCD,
+						PCI_CCD_PCI_ID, pci_index,
+						&cs->hw.hfcpci.pci_bus, &cs->hw.hfcpci.pci_device_fn) != 0) {
+				continue;
+			}
+			pcibios_read_config_byte(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn,
+					       PCI_INTERRUPT_LINE, &irq);
+			cs->irq = irq;
+
+			pcibios_read_config_dword(cs->hw.hfcpci.pci_bus,
+				cs->hw.hfcpci.pci_device_fn, PCI_BASE_ADDRESS_1,
+				(void *) &cs->hw.hfcpci.pci_io);
+			break;
+		}
+		if (pci_index == 255) {
+			printk(KERN_WARNING "HFC-PCI: No card found\n");
+			return (0);
+		}
+		pci_index++;
+#endif				/* COMPAT_HAS_NEW_PCI */
+		if (!cs->hw.hfcpci.pci_io) {
+			printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
+			return (0);
+		}
+		/* Allocate memory for FIFOS */
+		/* Because the HFC-PCI needs a 32K physical alignment, we */
+		/* need to allocate the double mem and align the address */
+		if (!((void *) cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) {
+			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+			return 0;
+		}
+		(ulong) cs->hw.hfcpci.fifos =
+		    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
+		pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
+				       cs->hw.hfcpci.pci_device_fn, 0x80,
+					   (u_int) virt_to_bus(cs->hw.hfcpci.fifos));
+		cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
+		printk(KERN_INFO
+		 "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n",
+		       (u_int) cs->hw.hfcpci.pci_io,
+		       (u_int) cs->hw.hfcpci.fifos,
+		       (u_int) virt_to_bus(cs->hw.hfcpci.fifos),
+		       cs->irq, HZ);
+		pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
+		cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */
+		cs->hw.hfcpci.int_m1 = 0;
+		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
+		Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
+		/* At this point the needed PCI config is done */
+		/* fifos are still not enabled */
+	} else
+		return (0);	/* no valid card type */
+
+
+	cs->readisac = NULL;
+	cs->writeisac = NULL;
+	cs->readisacfifo = NULL;
+	cs->writeisacfifo = NULL;
+	cs->BC_Read_Reg = NULL;
+	cs->BC_Write_Reg = NULL;
+	cs->irq_func = &hfcpci_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+
+	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
+	cs->hw.hfcpci.timer.data = (long) cs;
+	init_timer(&cs->hw.hfcpci.timer);
+
+	reset_hfcpci(cs);
+	cs->cardmsg = &hfcpci_card_msg;
+	return (1);
+#else
+	printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n");
+	return (0);
+#endif				/* CONFIG_PCI */
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfc_pci.h linux.pre11.3/drivers/isdn/hisax/hfc_pci.h
--- linux.vanilla/drivers/isdn/hisax/hfc_pci.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/hfc_pci.h	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,250 @@
+/* $Id: hfc_pci.h,v 1.3 1999/07/14 12:39:34 werner Exp $
+
+ *  specific defines for CCD's HFC 2BDS0 PCI chips
+ *
+ * Author     Werner Cornelius (werner@isdn4linux.de)      
+ *
+ * Copyright 1999  by Werner Cornelius (werner@isdn4linux.de)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: hfc_pci.h,v $
+ * Revision 1.3  1999/07/14 12:39:34  werner
+ * Added changes for echo handling.
+ *
+ * Revision 1.2  1999/07/01 08:07:52  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+
+/* defines for PCI config */
+
+#define PCI_VENDOR_CCD	 0x1397
+#define PCI_CCD_PCI_ID	 0x2BD0
+// #define PCI_VENDOR_CCD	 0x1043
+// #define PCI_CCD_PCI_ID	 0x675
+#define PCI_ENA_MEMIO    0x02
+#define PCI_ENA_MASTER   0x04
+
+
+/* GCI/IOM bus monitor registers */
+
+#define HCFPCI_C_I       0x08
+#define HFCPCI_TRxR      0x0C
+#define HFCPCI_MON1_D    0x28
+#define HFCPCI_MON2_D    0x2C
+
+
+/* GCI/IOM bus timeslot registers */
+
+#define HFCPCI_B1_SSL    0x80
+#define HFCPCI_B2_SSL    0x84
+#define HFCPCI_AUX1_SSL  0x88
+#define HFCPCI_AUX2_SSL  0x8C
+#define HFCPCI_B1_RSL    0x90
+#define HFCPCI_B2_RSL    0x94
+#define HFCPCI_AUX1_RSL  0x98
+#define HFCPCI_AUX2_RSL  0x9C
+
+/* GCI/IOM bus data registers */
+
+#define HFCPCI_B1_D      0xA0
+#define HFCPCI_B2_D      0xA4
+#define HFCPCI_AUX1_D    0xA8
+#define HFCPCI_AUX2_D    0xAC
+
+/* GCI/IOM bus configuration registers */
+
+#define HFCPCI_MST_EMOD  0xB4
+#define HFCPCI_MST_MODE	 0xB8
+#define HFCPCI_CONNECT 	 0xBC
+
+
+/* Interrupt and status registers */
+
+#define HFCPCI_FIFO_EN   0x44
+#define HFCPCI_TRM       0x48
+#define HFCPCI_B_MODE    0x4C
+#define HFCPCI_CHIP_ID   0x58
+#define HFCPCI_CIRM  	 0x60
+#define HFCPCI_CTMT	 0x64
+#define HFCPCI_INT_M1  	 0x68
+#define HFCPCI_INT_M2  	 0x6C
+#define HFCPCI_INT_S1  	 0x78
+#define HFCPCI_INT_S2  	 0x7C
+#define HFCPCI_STATUS  	 0x70
+
+/* S/T section registers */
+
+#define HFCPCI_STATES  	 0xC0
+#define HFCPCI_SCTRL  	 0xC4
+#define HFCPCI_SCTRL_E   0xC8
+#define HFCPCI_SCTRL_R   0xCC
+#define HFCPCI_SQ  	 0xD0
+#define HFCPCI_CLKDEL  	 0xDC
+#define HFCPCI_B1_REC    0xF0
+#define HFCPCI_B1_SEND   0xF0
+#define HFCPCI_B2_REC    0xF4
+#define HFCPCI_B2_SEND   0xF4
+#define HFCPCI_D_REC     0xF8
+#define HFCPCI_D_SEND    0xF8
+#define HFCPCI_E_REC     0xFC
+
+
+/* bits in status register (READ) */
+#define HFCPCI_PCI_PROC   0x02
+#define HFCPCI_NBUSY	  0x04 
+#define HFCPCI_TIMER_ELAP 0x10
+#define HFCPCI_STATINT	  0x20
+#define HFCPCI_FRAMEINT	  0x40
+#define HFCPCI_ANYINT	  0x80
+
+/* bits in CTMT (Write) */
+#define HFCPCI_CLTIMER    0x80
+#define HFCPCI_TIM3_125   0x00
+#define HFCPCI_TIM25      0x10
+#define HFCPCI_TIM50      0x14
+#define HFCPCI_TIM400     0x18
+#define HFCPCI_TIM800     0x1C
+#define HFCPCI_AUTO_TIMER 0x20
+#define HFCPCI_TRANSB2    0x02
+#define HFCPCI_TRANSB1    0x01
+
+/* bits in CIRM (Write) */
+#define HFCPCI_AUX_MSK    0x07
+#define HFCPCI_RESET  	  0x08
+#define HFCPCI_B1_REV     0x40
+#define HFCPCI_B2_REV     0x80
+
+/* bits in INT_M1 and INT_S1 */
+#define HFCPCI_INTS_B1TRANS  0x01
+#define HFCPCI_INTS_B2TRANS  0x02
+#define HFCPCI_INTS_DTRANS   0x04
+#define HFCPCI_INTS_B1REC    0x08
+#define HFCPCI_INTS_B2REC    0x10
+#define HFCPCI_INTS_DREC     0x20
+#define HFCPCI_INTS_L1STATE  0x40
+#define HFCPCI_INTS_TIMER    0x80
+
+/* bits in INT_M2 */
+#define HFCPCI_PROC_TRANS    0x01
+#define HFCPCI_GCI_I_CHG     0x02
+#define HFCPCI_GCI_MON_REC   0x04
+#define HFCPCI_IRQ_ENABLE    0x08
+#define HFCPCI_PMESEL        0x80
+
+/* bits in STATES */
+#define HFCPCI_STATE_MSK     0x0F
+#define HFCPCI_LOAD_STATE    0x10
+#define HFCPCI_ACTIVATE	     0x20
+#define HFCPCI_DO_ACTION     0x40
+#define HFCPCI_NT_G2_G3      0x80
+
+/* bits in HFCD_MST_MODE */
+#define HFCPCI_MASTER	     0x01
+#define HFCPCI_SLAVE         0x00
+/* remaining bits are for codecs control */
+
+/* bits in HFCD_SCTRL */
+#define SCTRL_B1_ENA	     0x01
+#define SCTRL_B2_ENA	     0x02
+#define SCTRL_MODE_TE        0x00
+#define SCTRL_MODE_NT        0x04
+#define SCTRL_LOW_PRIO	     0x08
+#define SCTRL_SQ_ENA	     0x10
+#define SCTRL_TEST	     0x20
+#define SCTRL_NONE_CAP	     0x40
+#define SCTRL_PWR_DOWN	     0x80
+
+/* bits in SCTRL_E  */
+#define HFCPCI_AUTO_AWAKE    0x01
+#define HFCPCI_DBIT_1        0x04
+#define HFCPCI_IGNORE_COL    0x08
+#define HFCPCI_CHG_B1_B2     0x80
+
+/****************************/
+/* bits in FIFO_EN register */
+/****************************/
+#define HFCPCI_FIFOEN_B1     0x03
+#define HFCPCI_FIFOEN_B2     0x0C
+#define HFCPCI_FIFOEN_DTX    0x10
+#define HFCPCI_FIFOEN_B2RX   0x08
+
+
+/***********************************/
+/* definitions of fifo memory area */
+/***********************************/
+#define MAX_D_FRAMES 15
+#define MAX_B_FRAMES 31
+#define B_SUB_VAL    0x200
+#define B_FIFO_SIZE  (0x2000 - B_SUB_VAL)
+#define D_FIFO_SIZE  512
+#define D_FREG_MASK  0xF
+
+typedef struct {
+    unsigned short z1;  /* Z1 pointer 16 Bit */
+    unsigned short z2;  /* Z2 pointer 16 Bit */
+  } z_type;
+
+typedef struct {
+    u_char data[D_FIFO_SIZE]; /* FIFO data space */
+    u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */
+    u_char f1,f2; /* f pointers */
+    u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */
+    z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */
+    u_char fill3[0x4000-0x2100]; /* align 16K */  
+  } dfifo_type;
+
+typedef struct {
+    z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ 
+    u_char f1,f2; /* f pointers */
+    u_char fill[0x2100-0x2082]; /* alignment */
+  } bzfifo_type;
+
+
+typedef union {
+    struct { 
+      dfifo_type d_tx; /* D-send channel */
+      dfifo_type d_rx; /* D-receive channel */
+    } d_chan; 
+    struct {
+      u_char fill1[0x200];
+      u_char txdat_b1[B_FIFO_SIZE];
+      bzfifo_type txbz_b1;
+
+      bzfifo_type txbz_b2;
+      u_char txdat_b2[B_FIFO_SIZE];
+
+      u_char fill2[D_FIFO_SIZE];
+
+      u_char rxdat_b1[B_FIFO_SIZE];
+      bzfifo_type rxbz_b1;
+
+      bzfifo_type rxbz_b2;
+      u_char rxdat_b2[B_FIFO_SIZE];
+    } b_chans;  
+    u_char fill[32768]; 
+  } fifo_area;
+
+
+#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c) 
+#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b))
+
+extern void main_irq_hcpci(struct BCState *bcs);
+extern void inithfcpci(struct IsdnCardState *cs);
+extern void releasehfcpci(struct IsdnCardState *cs);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hfcscard.c linux.pre11.3/drivers/isdn/hisax/hfcscard.c
--- linux.vanilla/drivers/isdn/hisax/hfcscard.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/hfcscard.c	Mon Jul 19 23:59:33 1999
@@ -0,0 +1,203 @@
+/* $Id: hfcscard.c,v 1.3 1999/07/12 21:05:12 keil Exp $
+
+ * hfcscard.c     low level stuff for hfcs based cards (Teles3c, ACER P10)
+ *
+ * Author     Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: hfcscard.c,v $
+ * Revision 1.3  1999/07/12 21:05:12  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:16:03  keil
+ * teles3c ---> hfcscard
+ *
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hfc_2bds0.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+
+static const char *hfcs_revision = "$Revision: 1.3 $";
+
+static void
+hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val, stat;
+
+	if (!cs) {
+		printk(KERN_WARNING "HFCS: Spurious interrupt!\n");
+		return;
+	}
+	if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & 
+		(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
+		val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val);
+		hfc2bds0_interrupt(cs, val);
+	} else {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat);
+	}
+}
+
+static void
+hfcs_Timer(struct IsdnCardState *cs)
+{
+	cs->hw.hfcD.timer.expires = jiffies + 75;
+	/* WD RESET */
+/*	WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
+	add_timer(&cs->hw.hfcD.timer);
+*/
+}
+
+void
+release_io_hfcs(struct IsdnCardState *cs)
+{
+	release2bds0(cs);
+	del_timer(&cs->hw.hfcD.timer);
+	if (cs->hw.hfcD.addr)
+		release_region(cs->hw.hfcD.addr, 2);
+}
+
+static void
+reset_hfcs(struct IsdnCardState *cs)
+{
+	long flags;
+
+	printk(KERN_INFO "HFCS: resetting card\n");
+	cs->hw.hfcD.cirm = HFCD_RESET;
+	if (cs->typ == ISDN_CTYPE_TELES3C)
+		cs->hw.hfcD.cirm |= HFCD_MEM8K;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset On */
+	save_flags(flags);
+	sti();
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((30*HZ)/1000);
+	cs->hw.hfcD.cirm = 0;
+	if (cs->typ == ISDN_CTYPE_TELES3C)
+		cs->hw.hfcD.cirm |= HFCD_MEM8K;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset Off */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	if (cs->typ == ISDN_CTYPE_TELES3C)
+		cs->hw.hfcD.cirm |= HFCD_INTB;
+	else if (cs->typ == ISDN_CTYPE_ACERP10)
+		cs->hw.hfcD.cirm |= HFCD_INTA;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
+	cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
+	cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
+	cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
+		HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
+		HFCD_INTS_DREC | HFCD_INTS_L1STATE;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
+	udelay(10);
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
+	cs->hw.hfcD.mst_m = 0;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, HFCD_MASTER); /* HFC Master */
+	cs->hw.hfcD.sctrl = 0;
+	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
+	restore_flags(flags);
+}
+
+static int
+hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	long flags;
+
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "HFCS: card_msg %x", mt);
+	switch (mt) {
+		case CARD_RESET:
+			reset_hfcs(cs);
+			return(0);
+		case CARD_RELEASE:
+			release_io_hfcs(cs);
+			return(0);
+		case CARD_INIT:
+			cs->hw.hfcD.timer.expires = jiffies + 75;
+			add_timer(&cs->hw.hfcD.timer);
+			init2bds0(cs);
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((80*HZ)/1000);
+			cs->hw.hfcD.ctmt |= HFCD_TIM800;
+			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
+			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+			restore_flags(flags);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+__initfunc(int
+setup_hfcs(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, hfcs_revision);
+	printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
+	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
+	cs->irq = card->para[0];
+	cs->hw.hfcD.cip = 0;
+	cs->hw.hfcD.int_s1 = 0;
+	cs->hw.hfcD.send = NULL;
+	cs->bcs[0].hw.hfc.send = NULL;
+	cs->bcs[1].hw.hfc.send = NULL;
+	cs->hw.hfcD.dfifosize = 512;
+	cs->dc.hfcd.ph_state = 0;
+	cs->hw.hfcD.fifo = 255;
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		cs->hw.hfcD.bfifosize = 1024 + 512;
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		cs->hw.hfcD.bfifosize = 7*1024 + 512;
+	} else
+		return (0);
+	if (check_region((cs->hw.hfcD.addr), 2)) {
+		printk(KERN_WARNING
+		       "HiSax: %s config port %x-%x already in use\n",
+		       CardType[card->typ],
+		       cs->hw.hfcD.addr,
+		       cs->hw.hfcD.addr + 2);
+		return (0);
+	} else {
+		request_region(cs->hw.hfcD.addr, 2, "HFCS isdn");
+	}
+	printk(KERN_INFO
+	       "HFCS: defined at 0x%x IRQ %d HZ %d\n",
+	       cs->hw.hfcD.addr,
+	       cs->irq, HZ);
+	if (cs->typ == ISDN_CTYPE_TELES3C) {
+		/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x56, cs->hw.hfcD.addr | 1);
+	} else if (cs->typ == ISDN_CTYPE_ACERP10) {
+		/* Acer P10 IO ADR is 0x300 */
+		outb(0x00, cs->hw.hfcD.addr);
+		outb(0x57, cs->hw.hfcD.addr | 1);
+	}
+	set_cs_func(cs);
+	cs->hw.hfcD.timer.function = (void *) hfcs_Timer;
+	cs->hw.hfcD.timer.data = (long) cs;
+	init_timer(&cs->hw.hfcD.timer);
+	reset_hfcs(cs);
+	cs->cardmsg = &hfcs_card_msg;
+	cs->irq_func = &hfcs_interrupt;
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hisax.h linux.pre11.3/drivers/isdn/hisax/hisax.h
--- linux.vanilla/drivers/isdn/hisax/hisax.h	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/hisax/hisax.h	Mon Jul 19 23:59:33 1999
@@ -1,8 +1,62 @@
-/* $Id: hisax.h,v 2.14 1998/02/11 17:28:04 keil Exp $
+/* $Id: hisax.h,v 2.30 1999/07/14 12:38:38 werner Exp $
 
  *   Basic declarations, defines and prototypes
  *
  * $Log: hisax.h,v $
+ * Revision 2.30  1999/07/14 12:38:38  werner
+ * Added changes for echo channel handling
+ *
+ * Revision 2.29  1999/07/12 21:05:14  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.28  1999/07/05 23:51:46  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 2.27  1999/07/01 08:11:38  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.26  1998/11/15 23:54:45  keil
+ * changes from 2.0
+ *
+ * Revision 2.25  1998/09/30 22:28:42  keil
+ * More work for ISAR support
+ *
+ * Revision 2.24  1998/08/20 13:50:39  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 2.23  1998/08/13 23:36:31  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.22  1998/07/15 15:01:28  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.21  1998/05/25 14:10:05  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.20  1998/05/25 12:57:57  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.19  1998/04/15 16:39:15  keil
+ * Add S0Box and Teles PCI support
+ *
+ * Revision 2.18  1998/03/26 07:10:04  paul
+ * The jumpmatrix table in struct Fsm was an array of "int". This is not
+ * large enough for pointers to functions on Linux/Alpha (instant crash
+ * on "insmod hisax). Now there is a typedef for the pointer to function.
+ * This also prevents warnings about "incompatible pointer types".
+ *
+ * Revision 2.17  1998/03/19 13:18:43  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 2.16  1998/03/09 23:19:25  keil
+ * Changes for PCMCIA
+ *
  * Revision 2.14  1998/02/11 17:28:04  keil
  * Niccy PnP/PCI support
  *
@@ -71,121 +125,104 @@
 #include <linux/wait.h>
 #include <linux/isdnif.h>
 #include <linux/tty.h>
-#include <linux/init.h>
+#include <linux/serial_reg.h>
+
+#define REQUEST		0
+#define CONFIRM		1
+#define INDICATION	2
+#define RESPONSE	3
+
+#define HW_ENABLE	0x0000
+#define HW_RESET	0x0004
+#define HW_POWERUP	0x0008
+#define HW_ACTIVATE	0x0010
+#define HW_DEACTIVATE	0x0018
+#define HW_INFO2	0x0020
+#define HW_INFO3	0x0030
+#define HW_INFO4_P8	0x0040
+#define HW_INFO4_P10	0x0048
+#define HW_RSYNC	0x0060
+#define HW_TESTLOOP	0x0070
+#define CARD_RESET	0x00F0
+#define CARD_INIT	0x00F2
+#define CARD_RELEASE	0x00F3
+#define CARD_TEST	0x00F4
+#define CARD_AUX_IND	0x00F5
+#define CARD_LOAD_FIRM	0x00F6
+
+#define PH_ACTIVATE	0x0100
+#define PH_DEACTIVATE	0x0110
+#define PH_DATA		0x0120
+#define PH_PULL		0x0130
+#define PH_TESTLOOP	0x0140
+#define PH_PAUSE	0x0150
+#define MPH_ACTIVATE	0x0180
+#define MPH_DEACTIVATE	0x0190
+#define MPH_INFORMATION	0x01A0
+
+#define DL_ESTABLISH	0x0200
+#define DL_RELEASE	0x0210
+#define DL_DATA		0x0220
+#define DL_FLUSH	0x0224
+#define DL_UNIT_DATA	0x0230
+#define MDL_ASSIGN	0x0280
+#define MDL_REMOVE	0x0284
+#define MDL_ERROR	0x0288
+#define MDL_INFO_SETUP	0x02E0
+#define MDL_INFO_CONN	0x02E4
+#define MDL_INFO_REL	0x02E8
+
+#define CC_SETUP	0x0300
+#define CC_RESUME	0x0304
+#define CC_MORE_INFO	0x0310
+#define CC_IGNORE	0x0320
+#define CC_REJECT	0x0324
+#define CC_SETUP_COMPL	0x0330
+#define CC_PROCEEDING	0x0340
+#define CC_ALERTING	0x0344
+#define CC_PROGRESS	0x0348
+#define CC_CONNECT	0x0350
+#define CC_CHARGE	0x0354
+#define CC_NOTIFY	0x0358
+#define CC_DISCONNECT	0x0360
+#define CC_RELEASE	0x0368
+#define CC_SUSPEND	0x0370
+#define CC_PROCEED_SEND 0x0374
+#define CC_REDIR        0x0378
+#define CC_T303		0x0383
+#define CC_T304		0x0384
+#define CC_T305		0x0385
+#define CC_T308_1	0x0388
+#define CC_T308_2	0x038A
+#define CC_T309         0x0309
+#define CC_T310		0x0390
+#define CC_T313		0x0393
+#define CC_T318		0x0398
+#define CC_T319		0x0399
+#define CC_NOSETUP_RSP	0x03E0
+#define CC_SETUP_ERR	0x03E1
+#define CC_SUSPEND_ERR	0x03E2
+#define CC_RESUME_ERR	0x03E3
+#define CC_CONNECT_ERR	0x03E4
+#define CC_RELEASE_ERR	0x03E5
+#define CC_RESTART	0x03F4
+#define CC_TDSS1_IO     0x13F4    /* DSS1 IO user timer */
+
+/* define maximum number of possible waiting incoming calls */
+#define MAX_WAITING_CALLS 2
 
-#define PH_ACTIVATE_REQ	0x0010
-#define PH_ACTIVATE_CNF	0x0011
-#define PH_ACTIVATE_IND	0x0012
-#define PH_DEACTIVATE_REQ 0x0020
-#define PH_DEACTIVATE_CNF 0x0021
-#define PH_DEACTIVATE_IND 0x0022
-#define PH_DEACT_REQ	0x0024
-#define PH_DEACT_CNF	0x0025
-#define PH_DEACT_IND	0x0026
-#define PH_DEACT_ACK	0x0027
-#define PH_TESTLOOP_REQ	0x0030
-#define PH_PAUSE_CNF	0x0035
-#define PH_PAUSE_IND	0x0036
-#define PH_PULL_REQ	0x0038
-#define PH_PULL_CNF	0x0039
-#define	PH_PULL_IND	0x003A
-#define PH_DATA_REQ	0x0040
-#define PH_DATA_IND	0x0042
-
-#define PH_INFO3_REQ	0x0008
-#define PH_INFO2_IND	0x000A
-#define PH_ENABLE_REQ	0x0004
-#define PH_RSYNC_IND	0x0006
-#define PH_RESET_REQ	0x0000
-#define PH_RESET_IND	0x0002
-#define PH_POWERUP_CNF	0x0003
-#define PH_ACTIV_REQ	0x000C
-#define PH_I4_P8_IND	0x000D
-#define PH_I4_P10_IND	0x000F
-
-#define MDL_ASSIGN_REQ	0x0050
-#define MDL_ASSIGN_IND	0x0052
-#define MDL_REMOVE_REQ	0x0054
-#define MDL_ERROR_REQ	0x0058
-#define MDL_ERROR_IND	0x005A
-#define CARD_AUX_IND	0x005E
-
-#define DL_UNIT_DATA	6
-#define CC_ESTABLISH	7
-#define DL_ESTABLISH	8
-#define DL_DATA		9
-
-#define CC_CONNECT	15
-#define DL_RELEASE	20
-#define DL_FLUSH	21
-
-#define CC_REJECT	23
-
-#define CC_SETUP_REQ	24
-#define CC_SETUP_CNF	25
-#define CC_SETUP_IND	26
-#define CC_SETUP_RSP	27
-#define CC_SETUP_COMPLETE_IND	28
-
-#define CC_DISCONNECT_REQ	29
-#define CC_DISCONNECT_IND	30
-
-#define CC_RELEASE_CNF	31
-#define CC_RELEASE_IND	32
-#define CC_RELEASE_REQ	33
-
-#define CC_REJECT_REQ	34
-
-#define CC_PROCEEDING_IND	35
-
-#define CC_DLRL		36
-#define CC_DLEST	37
-
-#define CC_ALERTING_REQ	38
-#define CC_ALERTING_IND	39
-
-#define DL_STOP		40
-#define DL_START	41
-
-#define MDL_INFO_SETUP	42
-#define MDL_INFO_CONN	43
-#define MDL_INFO_REL	44
-#define MDL_NOTEIPROC	46
-
-#define LC_ESTABLISH	47
-#define LC_RELEASE	48
-
-#define CC_INFO_CHARGE	52
-
-#define CC_MORE_INFO	53
-#define CC_IGNORE	54
-#define CC_RESTART	55
-
-
-#define CC_T303		60
-#define CC_T304		61
-#define CC_T305		62
-#define CC_T308_1	64
-#define CC_T308_2	65
-#define CC_T310		66
-#define CC_T313		67
-#define CC_T318		68
-#define CC_T319		69
-
-#define CC_NOSETUP_RSP_ERR	70
-#define CC_SETUP_ERR		71
-#define CC_CONNECT_ERR		72
-#define CC_RELEASE_ERR		73
-
-#define CARD_RESET	0x1001
-#define CARD_SETIRQ	0x1002
-#define CARD_INIT	0x1003
-#define CARD_RELEASE	0x1004
-#define CARD_TEST	0x1005
 
 #ifdef __KERNEL__
 
+/* include only l3dss1 specific process structures, but no other defines */
+#ifdef CONFIG_HISAX_EURO
+  #define l3dss1_process
+  #include "l3dss1.h" 
+  #undef  l3dss1_process
+#endif CONFIG_HISAX_EURO
+
 #define MAX_DFRAME_LEN	260
+#define MAX_DFRAME_LEN_L1	300
 #define HSCX_BUFMAX	4096
 #define MAX_DATA_SIZE	(HSCX_BUFMAX - 4)
 #define MAX_DATA_MEM	(HSCX_BUFMAX + 64)
@@ -193,6 +230,8 @@
 #define MAX_HEADER_LEN	4
 #define MAX_WINDOW	8
 #define MAX_MON_FRAME	32
+#define MAX_DLOG_SPACE	2048
+#define MAX_BLOG_SPACE	256
 
 /* #define I4L_IRQ_FLAG SA_INTERRUPT */
 #define I4L_IRQ_FLAG    0
@@ -201,8 +240,12 @@
  * Statemachine
  */
 
+struct FsmInst;
+
+typedef void (* FSMFNPTR)(struct FsmInst *, int, void *);
+
 struct Fsm {
-	int *jumpmatrix;
+	FSMFNPTR *jumpmatrix;
 	int state_count, event_count;
 	char **strEvent, **strState;
 };
@@ -213,7 +256,7 @@
 	int debug;
 	void *userdata;
 	int userint;
-	void (*printdebug) (struct FsmInst *, char *);
+	void (*printdebug) (struct FsmInst *, char *, ...);
 };
 
 struct FsmNode {
@@ -249,9 +292,10 @@
 	struct FsmInst l1m;
 	struct FsmTimer	timer;
 	void (*l1l2) (struct PStack *, int, void *);
-	void (*l1man) (struct PStack *, int, void *);
+	void (*l1hw) (struct PStack *, int, void *);
 	void (*l1tei) (struct PStack *, int, void *);
 	int mode, bc;
+	int delay;
 };
 
 #define GROUP_TEI	127
@@ -266,49 +310,57 @@
 #define FLG_ORIG	2
 #define FLG_MOD128	3
 #define FLG_PEND_REL	4
-#define FLG_L3_INIT	5 
-#define FLG_T200_RUN	6 
+#define FLG_L3_INIT	5
+#define FLG_T200_RUN	6
 #define FLG_ACK_PEND	7
 #define FLG_REJEXC	8
 #define FLG_OWN_BUSY	9
 #define FLG_PEER_BUSY	10
 #define FLG_DCHAN_BUSY	11
+#define FLG_L1_ACTIV	12
+#define FLG_ESTAB_PEND	13
+#define FLG_PTP		14
+#define FLG_FIXED_TEI	15
 
 struct Layer2 {
 	int tei;
-	int tei_wanted;
 	int sap;
 	int maxlen;
 	unsigned int flag;
-	int vs, va, vr;
+	unsigned int vs, va, vr;
 	int rc;
-	int window;
-	int sow;
+	unsigned int window;
+	unsigned int sow;
 	struct sk_buff *windowar[MAX_WINDOW];
 	struct sk_buff_head i_queue;
 	struct sk_buff_head ui_queue;
 	void (*l2l1) (struct PStack *, int, void *);
-	void (*l2man) (struct PStack *, int, void *);
 	void (*l2l3) (struct PStack *, int, void *);
 	void (*l2tei) (struct PStack *, int, void *);
 	struct FsmInst l2m;
 	struct FsmTimer t200, t203;
 	int T200, N200, T203;
 	int debug;
-	char debug_id[32];
+	char debug_id[16];
 };
 
 struct Layer3 {
-	void (*l3l4) (struct l3_process *, int, void *);
+	void (*l3l4) (struct PStack *, int, void *);
+        void (*l3ml3) (struct PStack *, int, void *);
 	void (*l3l2) (struct PStack *, int, void *);
+	struct FsmInst l3m;
+        struct FsmTimer l3m_timer;
+	struct sk_buff_head squeue;
 	struct l3_process *proc;
 	struct l3_process *global;
 	int N303;
 	int debug;
+	char debug_id[8];
 };
 
 struct LLInterface {
 	void (*l4l3) (struct PStack *, int, void *);
+        int  (*l4l3_proto) (struct PStack *, isdn_ctrl *);
 	void *userdata;
 	void (*l1writewakeup) (struct PStack *, int);
 	void (*l2writewakeup) (struct PStack *, int);
@@ -321,20 +373,19 @@
 	struct FsmTimer t202;
 	int T202, N202, debug;
 	void (*layer) (struct PStack *, int, void *);
-	void (*manl1) (struct PStack *, int, void *);
-	void (*manl2) (struct PStack *, int, void *);
 };
 
+#define NO_CAUSE 254
 
 struct Param {
-	int cause;
-	int loc;
+	u_char cause;
+	u_char loc;
+	u_char diag[6];
 	int bchannel;
-	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
-	int chargeinfo;		/* Charge Info - only for 1tr6 in
-				 * the moment
-				 */
+	int chargeinfo;
 	int spv;		/* SPV Flag */
+	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
+	u_char moderate;	/* transfer mode and rate (bearer octet 4) */
 };
 
 
@@ -343,9 +394,17 @@
 	struct Layer1 l1;
 	struct Layer2 l2;
 	struct Layer3 l3;
-	struct LLInterface lli; 
+	struct LLInterface lli;
 	struct Management ma;
 	int protocol;		/* EDSS1 or 1TR6 */
+
+        /* protocol specific data fields */
+        union
+	 { u_char uuuu; /* only as dummy */
+#ifdef CONFIG_HISAX_EURO
+           dss1_stk_priv dss1; /* private dss1 data */
+#endif CONFIG_HISAX_EURO              
+	 } prot;
 };
 
 struct l3_process {
@@ -358,24 +417,69 @@
 	struct Channel *chan;
 	struct PStack *st;
 	struct l3_process *next;
+        ulong redir_result;
+
+        /* protocol specific data fields */
+        union 
+	 { u_char uuuu; /* only when euro not defined, avoiding empty union */
+#ifdef CONFIG_HISAX_EURO 
+           dss1_proc_priv dss1; /* private dss1 data */
+#endif CONFIG_HISAX_EURO            
+	 } prot;
 };
 
 struct hscx_hw {
+	int hscx;
+	int rcvidx;
+	int count;              /* Current skb sent count */
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	u_char tsaxr0;
+	u_char tsaxr1;
+};
+
+struct isar_reg {
+	unsigned int Flags;
+	volatile u_char bstat;
+	volatile u_char iis;
+	volatile u_char cmsb;
+	volatile u_char clsb;
+	volatile u_char par[8];
+};
+
+struct isar_hw {
+	int dpath;
+	int rcvidx;
+	int txcnt;
+	int mml;
+	u_char *rcvbuf;         /* B-Channel receive Buffer */
+	struct isar_reg *reg;
+};
+
+struct hdlc_stat_reg {
+	u_char cmd  __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char fill __attribute__((packed));
+};
+
+struct hdlc_hw {
+	union {
+		u_int ctrl;
+		struct hdlc_stat_reg sr;
+	} ctrl;
+	u_int stat;
 	int rcvidx;
 	int count;              /* Current skb sent count */
 	u_char *rcvbuf;         /* B-Channel receive Buffer */
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
 };
 
 struct hfcB_hw {
 	unsigned int *send;
 	int f1;
 	int f2;
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
 };
 
 struct tiger_hw {
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
 	u_int *send;
 	u_int *s_irq;
 	u_int *s_end;
@@ -397,8 +501,7 @@
 	u_char s_state;
 };
 
-struct foreign_hw {
-	int doHDLCprocessing;
+struct amd7930_hw {
 	u_char *tx_buff;
 	u_char *rv_buff;
 	int rv_buff_in;
@@ -407,9 +510,9 @@
 	struct hdlc_state *hdlc_state;
 	struct tq_struct tq_rcv;
 	struct tq_struct tq_xmt;
-	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
 };
 
+
 #define BC_FLG_INIT	1
 #define BC_FLG_ACTIV	2
 #define BC_FLG_BUSY	3
@@ -420,6 +523,7 @@
 #define L1_MODE_NULL	0
 #define L1_MODE_TRANS	1
 #define L1_MODE_HDLC	2
+#define L1_MODE_MODEM	7
 
 struct BCState {
 	int channel;
@@ -427,34 +531,26 @@
 	int Flag;
 	struct IsdnCardState *cs;
 	int tx_cnt;		/* B-Channel transmit counter */
+	struct sk_buff *tx_skb; /* B-Channel transmit Buffer */
 	struct sk_buff_head rqueue;	/* B-Channel receive Queue */
 	struct sk_buff_head squeue;	/* B-Channel send Queue */
 	struct PStack *st;
+	u_char *blog;
+	struct timer_list transbusy;
 	struct tq_struct tqueue;
 	int event;
 	int  (*BC_SetStack) (struct PStack *, struct BCState *);
 	void (*BC_Close) (struct BCState *);
 	union {
 		struct hscx_hw hscx;
+		struct hdlc_hw hdlc;
+		struct isar_hw isar;
 		struct hfcB_hw hfc;
 		struct tiger_hw tiger;
-		struct foreign_hw foreign;
+		struct amd7930_hw  amd7930;
 	} hw;
 };
 
-struct LcFsm {
-	int type;
-	int delay;
-	struct FsmInst lcfi;
-	struct Channel *ch;
-	void (*lccall) (struct LcFsm *, int, void *);
-	struct PStack *st;
-	int l2_establish;
-	int l2_start;
-	struct FsmTimer act_timer;
-	char debug_id[32];
-};
-
 struct Channel {
 	struct PStack *b_st, *d_st;
 	struct IsdnCardState *cs;
@@ -462,11 +558,10 @@
 	int chan;
 	int incoming;
 	struct FsmInst fi;
-	struct LcFsm *lc_d;
-	struct LcFsm *lc_b;
 	struct FsmTimer drel_timer, dial_timer;
 	int debug;
 	int l2_protocol, l2_active_protocol;
+	int l3_protocol;
 	int data_open;
 	struct l3_process *proc;
 	setup_parm setup;	/* from isdnif.h numbers and Serviceindicator */
@@ -487,21 +582,33 @@
 	unsigned int counter;
 	unsigned int status;
 	struct timer_list tl;
+	unsigned int MFlag;
+	struct BCState *bcs;
+	u_char *transbuf;
+	u_char *rcvbuf;
+	unsigned int transp;
+	unsigned int rcvp;
+	unsigned int transcnt;
+	unsigned int rcvcnt;
+	u_char IER;
+	u_char FCR;
+	u_char LCR;
+	u_char MCR;
 	u_char ctrl_reg;
-};	
+};
 
 struct teles3_hw {
 	unsigned int cfg_reg;
-	unsigned int isac;
-	unsigned int hscx[2];
-	unsigned int isacfifo;
-	unsigned int hscxfifo[2];
-};	
+	signed   int isac;
+	signed   int hscx[2];
+	signed   int isacfifo;
+	signed   int hscxfifo[2];
+};
 
 struct teles0_hw {
 	unsigned int cfg_reg;
 	unsigned int membase;
-};	
+};
 
 struct avm_hw {
 	unsigned int cfg_reg;
@@ -510,7 +617,7 @@
 	unsigned int isacfifo;
 	unsigned int hscxfifo[2];
 	unsigned int counter;
-};	
+};
 
 struct ix1_hw {
 	unsigned int cfg_reg;
@@ -521,7 +628,8 @@
 };
 
 struct diva_hw {
-	unsigned int cfg_reg;
+	unsigned long cfg_reg;
+	unsigned long pci_cfg;
 	unsigned int ctrl;
 	unsigned int isac_adr;
 	unsigned int isac;
@@ -530,7 +638,7 @@
 	unsigned int status;
 	struct timer_list tl;
 	u_char ctrl_reg;
-};	
+};
 
 struct asus_hw {
 	unsigned int cfg_reg;
@@ -559,6 +667,9 @@
 	unsigned int hscx;
 	unsigned int reset_on;
 	unsigned int reset_off;
+	struct isar_reg isar;
+	unsigned int chip;
+	unsigned int bus;
 };
 
 struct spt_hw {
@@ -566,7 +677,7 @@
 	unsigned int isac;
 	unsigned int hscx[2];
 	unsigned char res_irq;
-};	
+};
 
 struct mic_hw {
 	unsigned int cfg_reg;
@@ -587,6 +698,31 @@
 	unsigned char last_is0;
 };
 
+struct hfcPCI_hw {
+	unsigned char cirm;
+	unsigned char ctmt;
+	unsigned char conn;
+	unsigned char mst_m;
+	unsigned char int_m1;
+	unsigned char int_m2;
+	unsigned char int_s1;
+	unsigned char sctrl;
+        unsigned char sctrl_r;
+        unsigned char sctrl_e;
+        unsigned char trm;
+	unsigned char stat;
+	unsigned char fifo;
+        unsigned char fifo_en;
+        unsigned char bswapped;
+  /*	unsigned int *send; */
+	unsigned char pci_bus;
+        unsigned char pci_device_fn;
+        unsigned char *pci_io; /* start of PCI IO memory */
+        void *share_start; /* shared memory for Fifos start */
+        void *fifos; /* FIFO memory */ 
+	struct timer_list timer;
+};
+
 struct hfcD_hw {
 	unsigned int addr;
 	unsigned int bfifosize;
@@ -608,24 +744,118 @@
 	struct timer_list timer;
 };
 
-#define HW_IOM1		0
-#define HW_IPAC		1
-#define FLG_TWO_DCHAN	4
-#define FLG_L1_DBUSY	5
-#define FLG_DBUSY_TIMER 6
-#define FLG_LOCK_ATOMIC 7
-#define HW_MON0_RX_END	8
-#define HW_MON1_RX_END	9
-#define HW_MON0_TX_END	10
-#define HW_MON1_TX_END	11
+struct isurf_hw {
+	unsigned int reset;
+	unsigned int isac;
+	unsigned int isar;
+	struct isar_reg isar_r;
+};
+
+struct saphir_hw {
+	unsigned int cfg_reg;
+	unsigned int ale;
+	unsigned int isac;
+	unsigned int hscx;
+	struct timer_list timer;
+};
+
+struct bkm_hw {
+	unsigned int base;
+	/* A4T stuff */
+	unsigned int isac_adr;
+	unsigned int isac_ale;
+	unsigned int jade_adr;
+	unsigned int jade_ale;
+	/* Scitel Quadro stuff */
+	unsigned int plx_adr;
+	unsigned int data_adr;
+};	
+
+struct gazel_hw {
+	unsigned int cfg_reg;
+	unsigned int pciaddr[2];
+        signed   int ipac;
+	signed   int isac;
+	signed   int hscx[2];
+	signed   int isacfifo;
+	signed   int hscxfifo[2];
+	unsigned char timeslot;
+	unsigned char iom2;
+};
+
+#ifdef  CONFIG_HISAX_TESTEMU
+struct te_hw {
+	unsigned char *sfifo;
+	unsigned char *sfifo_w;
+	unsigned char *sfifo_r;
+	unsigned char *sfifo_e;
+	int sfifo_cnt;
+	unsigned int stat;
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t rwaitq;
+	wait_queue_head_t swaitq;
+#else
+	struct wait_queue *rwaitq;
+	struct wait_queue *swaitq;
+#endif
+};
+#endif
+
+struct arcofi_msg {
+	struct arcofi_msg *next;
+	u_char receive;
+	u_char len;
+	u_char msg[10];
+};
+
+struct isac_chip {
+	int ph_state;
+	u_char *mon_tx;
+	u_char *mon_rx;
+	int mon_txp;
+	int mon_txc;
+	int mon_rxp;
+	struct arcofi_msg *arcofi_list;
+	struct timer_list arcofitimer;
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t arcofi_wait;
+#else
+	struct wait_queue *arcofi_wait;
+#endif
+	u_char arcofi_bc;
+	u_char arcofi_state;
+	u_char mocr;
+	u_char adf2;
+};
+
+struct hfcd_chip {
+	int ph_state;
+};
+
+struct hfcpci_chip {
+	int ph_state;
+};
+
+#define HW_IOM1			0
+#define HW_IPAC			1
+#define HW_ISAR			2
+#define FLG_TWO_DCHAN		4
+#define FLG_L1_DBUSY		5
+#define FLG_DBUSY_TIMER 	6
+#define FLG_LOCK_ATOMIC 	7
+#define FLG_ARCOFI_TIMER	8
+#define FLG_ARCOFI_ERROR	9
 
 struct IsdnCardState {
 	unsigned char typ;
 	unsigned char subtyp;
 	int protocol;
 	unsigned int irq;
-	int HW_Flags; 
+	unsigned long irq_flags;
+	int HW_Flags;
 	int *busy_flag;
+        int chanlimit; /* limited number of B-chans to use */
+        int logecho; /* log echo if supported by card */
 	union {
 		struct elsa_hw elsa;
 		struct teles0_hw teles0;
@@ -640,8 +870,15 @@
 		struct mic_hw mic;
 		struct njet_hw njet;
 		struct hfcD_hw hfcD;
+		struct hfcPCI_hw hfcpci;
 		struct ix1_hw niccy;
-                struct foreign_interface *foreign;
+		struct isurf_hw isurf;
+		struct saphir_hw saphir;
+#ifdef CONFIG_HISAX_TESTEMU
+		struct te_hw te;
+#endif
+		struct bkm_hw ax;
+		struct gazel_hw gazel;
 	} hw;
 	int myid;
 	isdn_if iif;
@@ -657,10 +894,21 @@
 	void   (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char);
 	void   (*BC_Send_Data) (struct BCState *);
 	int    (*cardmsg) (struct IsdnCardState *, int, void *);
-	void   (*l1cmd) (struct IsdnCardState *, int, void *);
-	struct Channel channel[2];
-	struct BCState bcs[2];
+	void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
+	void   (*DC_Close) (struct IsdnCardState *);
+	void   (*irq_func) (int, void *, struct pt_regs *);
+	struct Channel channel[2+MAX_WAITING_CALLS];
+	struct BCState bcs[2+MAX_WAITING_CALLS];
 	struct PStack *stlist;
+	struct sk_buff_head rq, sq; /* D-channel queues */
+	int cardnr;
+	char *dlog;
+	int debug;
+	union {
+		struct isac_chip isac;
+		struct hfcd_chip hfcd;
+		struct hfcpci_chip hfcpci;
+	} dc;
 	u_char *rcvbuf;
 	int rcvidx;
 	struct sk_buff *tx_skb;
@@ -668,19 +916,6 @@
 	int event;
 	struct tq_struct tqueue;
 	struct timer_list dbusytimer;
-	struct sk_buff_head rq, sq; /* D-channel queues */
-	int ph_state;
-	int cardnr;
-	int dlogflag;
-	char *dlogspace;
-	int debug;
-	u_char *mon_tx;
-	u_char *mon_rx;
-	int mon_txp;
-	int mon_txc;
-	int mon_rxp;
-	u_char mocr;
-	void   (*setstack_d) (struct PStack *, struct IsdnCardState *);
 };
 
 #define  MON0_RX	1
@@ -688,6 +923,8 @@
 #define  MON0_TX	4
 #define  MON1_TX	8
 
+#define	 HISAX_MAX_CARDS	8
+
 #define  ISDN_CTYPE_16_0	1
 #define  ISDN_CTYPE_8_0		2
 #define  ISDN_CTYPE_16_3	3
@@ -712,19 +949,37 @@
 #define  ISDN_CTYPE_SEDLBAUER_PCMCIA	22
 #define  ISDN_CTYPE_AMD7930	23
 #define  ISDN_CTYPE_NICCY	24
-#define  ISDN_CTYPE_DBRI	25
+#define  ISDN_CTYPE_S0BOX	25
+#define  ISDN_CTYPE_A1_PCMCIA	26
+#define  ISDN_CTYPE_FRITZPCI	27
+#define  ISDN_CTYPE_SEDLBAUER_FAX     28
+#define  ISDN_CTYPE_ISURF	29
+#define  ISDN_CTYPE_ACERP10	30
+#define  ISDN_CTYPE_HSTSAPHIR	31
+#define	 ISDN_CTYPE_BKM_A4T	32
+#define	 ISDN_CTYPE_SCT_QUADRO	33
+#define  ISDN_CTYPE_GAZEL	34
+#define  ISDN_CTYPE_HFC_PCI	35
+#define  ISDN_CTYPE_COUNT	35
 
-#define  ISDN_CTYPE_COUNT	25
 
 #ifdef ISDN_CHIP_ISAC
 #undef ISDN_CHIP_ISAC
 #endif
 
+#ifndef __initfunc
+#define __initfunc(__arginit) __arginit
+#endif
+
+#ifndef __initdata
+#define __initdata
+#endif
+
 #define HISAX_INITFUNC(__arginit) __initfunc(__arginit)
 #define HISAX_INITDATA __initdata
 
 #ifdef	CONFIG_HISAX_16_0
-#define  CARD_TELES0 (1<< ISDN_CTYPE_16_0) | (1<< ISDN_CTYPE_8_0)
+#define  CARD_TELES0 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -733,8 +988,7 @@
 #endif
 
 #ifdef	CONFIG_HISAX_16_3
-#define  CARD_TELES3 (1<< ISDN_CTYPE_16_3) | (1<< ISDN_CTYPE_PNP) | \
-		     (1<< ISDN_CTYPE_TELESPCMCIA) | (1<< ISDN_CTYPE_COMPAQ_ISA)
+#define  CARD_TELES3 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -742,18 +996,44 @@
 #define  CARD_TELES3  0
 #endif
 
+#ifdef	CONFIG_HISAX_TELESPCI
+#define  CARD_TELESPCI 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_TELESPCI  0
+#endif
+
 #ifdef	CONFIG_HISAX_AVM_A1
-#define  CARD_AVM_A1 (1<< ISDN_CTYPE_A1)
-#ifndef ISDN_CHIP_ISAC 
+#define  CARD_AVM_A1 1
+#ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
 #else
 #define  CARD_AVM_A1  0
 #endif
 
+#ifdef	CONFIG_HISAX_AVM_A1_PCMCIA
+#define  CARD_AVM_A1_PCMCIA 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_AVM_A1_PCMCIA  0
+#endif
+
+#ifdef	CONFIG_HISAX_FRITZPCI
+#define  CARD_FRITZPCI 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_FRITZPCI  0
+#endif
+
 #ifdef	CONFIG_HISAX_ELSA
-#define  CARD_ELSA (1<< ISDN_CTYPE_ELSA) | (1<< ISDN_CTYPE_ELSA_PNP) | \
-		   (1<< ISDN_CTYPE_ELSA_PCMCIA) | (1<< ISDN_CTYPE_ELSA_PCI)
+#define  CARD_ELSA 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -765,9 +1045,8 @@
 #define  CARD_ELSA  0
 #endif
 
-
 #ifdef	CONFIG_HISAX_IX1MICROR2
-#define	CARD_IX1MICROR2 (1 << ISDN_CTYPE_IX1MICROR2)
+#define	CARD_IX1MICROR2 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -776,7 +1055,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_DIEHLDIVA
-#define CARD_DIEHLDIVA (1 << ISDN_CTYPE_DIEHLDIVA)
+#define CARD_DIEHLDIVA 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -785,7 +1064,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_ASUSCOM
-#define CARD_ASUSCOM (1 << ISDN_CTYPE_ASUSCOM)
+#define CARD_ASUSCOM 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -794,7 +1073,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_TELEINT
-#define CARD_TELEINT (1 << ISDN_CTYPE_TELEINT)
+#define CARD_TELEINT 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -803,7 +1082,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_SEDLBAUER
-#define CARD_SEDLBAUER (1 << ISDN_CTYPE_SEDLBAUER) | (1 << ISDN_CTYPE_SEDLBAUER_PCMCIA)
+#define CARD_SEDLBAUER 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -812,7 +1091,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_SPORTSTER
-#define CARD_SPORTSTER (1 << ISDN_CTYPE_SPORTSTER)
+#define CARD_SPORTSTER 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -821,7 +1100,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_MIC
-#define CARD_MIC (1 << ISDN_CTYPE_MIC)
+#define CARD_MIC 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -830,7 +1109,7 @@
 #endif
 
 #ifdef  CONFIG_HISAX_NETJET
-#define CARD_NETJET (1 << ISDN_CTYPE_NETJET)
+#define CARD_NETJET 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -838,20 +1117,27 @@
 #define CARD_NETJET 0
 #endif
 
-#ifdef	CONFIG_HISAX_TELES3C
-#define  CARD_TELES3C (1<< ISDN_CTYPE_TELES3C)
+#ifdef	CONFIG_HISAX_HFCS
+#define  CARD_HFCS 1
 #else
-#define  CARD_TELES3C  0
+#define  CARD_HFCS 0
+#endif
+
+#ifdef	CONFIG_HISAX_HFC_PCI
+#define  CARD_HFC_PCI 1
+extern int hfcpci_set_echo(struct IsdnCardState *, int);
+#else
+#define  CARD_HFC_PCI 0
 #endif
 
 #ifdef  CONFIG_HISAX_AMD7930
-#define CARD_AMD7930 (1 << ISDN_CTYPE_AMD7930)
+#define CARD_AMD7930 1
 #else
 #define CARD_AMD7930 0
 #endif
 
 #ifdef	CONFIG_HISAX_NICCY
-#define	CARD_NICCY (1 << ISDN_CTYPE_NICCY)
+#define	CARD_NICCY 1
 #ifndef ISDN_CHIP_ISAC
 #define ISDN_CHIP_ISAC 1
 #endif
@@ -859,18 +1145,68 @@
 #define CARD_NICCY 0
 #endif
 
-#ifdef  CONFIG_HISAX_DBRI
-#define CARD_DBRI (1 << ISDN_CTYPE_DBRI)
+#ifdef	CONFIG_HISAX_ISURF
+#define	CARD_ISURF 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_ISURF 0
+#endif
+
+#ifdef	CONFIG_HISAX_S0BOX
+#define	CARD_S0BOX 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_S0BOX 0
+#endif
+
+#ifdef	CONFIG_HISAX_HSTSAPHIR
+#define	CARD_HSTSAPHIR 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
 #else
-#define CARD_DBRI 0
+#define CARD_HSTSAPHIR 0
 #endif
 
+#ifdef	CONFIG_HISAX_TESTEMU
+#define	CARD_TESTEMU 1
+#define ISDN_CTYPE_TESTEMU 99
+#undef ISDN_CTYPE_COUNT
+#define  ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU
+#else
+#define CARD_TESTEMU 0
+#endif
 
-#define  SUPORTED_CARDS  (CARD_TELES0 | CARD_TELES3 | CARD_AVM_A1 | CARD_ELSA \
-			 | CARD_IX1MICROR2 | CARD_DIEHLDIVA | CARD_ASUSCOM \
-			 | CARD_TELEINT | CARD_SEDLBAUER | CARD_SPORTSTER \
-			 | CARD_MIC | CARD_NETJET | CARD_TELES3C | CARD_AMD7930 \
-			 | CARD_NICCY | CARD_DBRI)
+#ifdef	CONFIG_HISAX_BKM_A4T
+#define	CARD_BKM_A4T 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_BKM_A4T 0
+#endif
+
+#ifdef	CONFIG_HISAX_SCT_QUADRO
+#define	CARD_SCT_QUADRO 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define CARD_SCT_QUADRO 0
+#endif
+
+#ifdef	CONFIG_HISAX_GAZEL
+#define  CARD_GAZEL 1
+#ifndef ISDN_CHIP_ISAC
+#define ISDN_CHIP_ISAC 1
+#endif
+#else
+#define  CARD_GAZEL  0
+#endif
 
 #define TEI_PER_CARD 0
 
@@ -883,25 +1219,38 @@
 #undef TEI_PER_CARD
 #define TEI_PER_CARD 1
 #define HISAX_EURO_SENDCOMPLETE 1
-#ifdef	CONFIG_HISAX_ML
+#define EXT_BEARER_CAPS 1
+#define HISAX_SEND_STD_LLC_IE 1
+#ifdef	CONFIG_HISAX_NO_SENDCOMPLETE
 #undef HISAX_EURO_SENDCOMPLETE
 #endif
+#ifdef	CONFIG_HISAX_NO_LLC
+#undef HISAX_SEND_STD_LLC_IE
+#endif
 #undef HISAX_DE_AOC
 #ifdef CONFIG_DE_AOC
 #define HISAX_DE_AOC 1
 #endif
 #endif
 
-#if TEI_PER_CARD
-#undef TEI_FIXED
-#endif
+/* L1 Debug */
+#define	L1_DEB_WARN		0x01
+#define	L1_DEB_INTSTAT		0x02
+#define	L1_DEB_ISAC		0x04
+#define	L1_DEB_ISAC_FIFO	0x08
+#define	L1_DEB_HSCX		0x10
+#define	L1_DEB_HSCX_FIFO	0x20
+#define	L1_DEB_LAPD	        0x40
+#define	L1_DEB_IPAC	        0x80
+#define	L1_DEB_RECEIVE_FRAME    0x100
+#define L1_DEB_MONITOR		0x200
+#define DEB_DLOG_HEX		0x400
+#define DEB_DLOG_VERBOSE	0x800
 
-#undef PTP_DATA_LINK
+#define L2FRAME_DEBUG
 
-#ifdef PTP_DATA_LINK
-#undef TEI_FIXED
-#define TEI_FIXED 0
-#define LAYER2_WATCHING
+#ifdef L2FRAME_DEBUG
+extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
 #endif
 
 struct IsdnCard {
@@ -911,17 +1260,26 @@
 	struct IsdnCardState *cs;
 };
 
-void setstack_isdnl2(struct PStack *st, char *debug_id);
-int HiSax_inithardware(int *);
-void HiSax_closehardware(void);
+void init_bcstate(struct IsdnCardState *cs, int bc);
 
 void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs);
 unsigned int random_ri(void);
-void setstack_isdnl3(struct PStack *st, struct Channel *chanp);
 void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st);
+void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
+
+void setstack_l1_B(struct PStack *st);
+
+void setstack_tei(struct PStack *st);
+void setstack_manager(struct PStack *st);
+
+void setstack_isdnl2(struct PStack *st, char *debug_id);
 void releasestack_isdnl2(struct PStack *st);
+void setstack_transl2(struct PStack *st);
+void releasestack_transl2(struct PStack *st);
+
+void setstack_l3dc(struct PStack *st, struct Channel *chanp);
+void setstack_l3bc(struct PStack *st, struct Channel *chanp);
 void releasestack_isdnl3(struct PStack *st);
-void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
 
 u_char *findie(u_char * p, int size, u_char ie, int wanted_set);
 int getcallref(u_char * p);
@@ -937,20 +1295,18 @@
 void FsmRestartTimer(struct FsmTimer *ft, int millisec, int event,
 	void *arg, int where);
 void FsmDelTimer(struct FsmTimer *ft, int where);
-void jiftime(char *s, long mark);
+int jiftime(char *s, long mark);
 
 int HiSax_command(isdn_ctrl * ic);
 int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb);
-void HiSax_putstatus(struct IsdnCardState *csta, char *buf);
+void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...);
+void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args);
 void HiSax_reportcard(int cardnr);
 int QuickHex(char *txt, u_char * p, int cnt);
-void LogFrame(struct IsdnCardState *sp, u_char * p, int size);
-void dlogframe(struct IsdnCardState *sp, u_char * p, int size, char *comment);
+void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
+void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
 void iecpy(u_char * dest, u_char * iestart, int ieoffset);
-void setstack_transl2(struct PStack *st);
-void releasestack_transl2(struct PStack *st);
-void setstack_tei(struct PStack *st);
-void setstack_manager(struct PStack *st);
+int discard_queue(struct sk_buff_head *q);
 #ifdef ISDN_CHIP_ISAC
 void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
 #endif	/* ISDN_CHIP_ISAC */
@@ -958,18 +1314,21 @@
 
 #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
 
-int ll_run(struct IsdnCardState *csta);
-void ll_stop(struct IsdnCardState *csta);
+int ll_run(struct IsdnCardState *cs);
+void ll_stop(struct IsdnCardState *cs);
 void CallcNew(void);
 void CallcFree(void);
-int CallcNewChan(struct IsdnCardState *csta);
-void CallcFreeChan(struct IsdnCardState *csta);
+int CallcNewChan(struct IsdnCardState *cs);
+void CallcFreeChan(struct IsdnCardState *cs);
 void Isdnl1New(void);
 void Isdnl1Free(void);
 void Isdnl2New(void);
 void Isdnl2Free(void);
-void init_tei(struct IsdnCardState *sp, int protocol);
-void release_tei(struct IsdnCardState *sp);
+void Isdnl3New(void);
+void Isdnl3Free(void);
+void init_tei(struct IsdnCardState *cs, int protocol);
+void release_tei(struct IsdnCardState *cs);
 char *HiSax_getrev(const char *revision);
 void TeiNew(void);
 void TeiFree(void);
+int certification_check(int output);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hscx.c linux.pre11.3/drivers/isdn/hisax/hscx.c
--- linux.vanilla/drivers/isdn/hisax/hscx.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/hscx.c	Mon Jul 19 23:59:34 1999
@@ -1,11 +1,43 @@
-/* $Id: hscx.c,v 1.7 1998/02/12 23:07:36 keil Exp $
+/* $Id: hscx.c,v 1.17 1999/07/01 08:11:41 keil Exp $
 
  * hscx.c   HSCX specific routines
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: hscx.c,v $
+ * Revision 1.17  1999/07/01 08:11:41  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.16  1998/11/15 23:54:48  keil
+ * changes from 2.0
+ *
+ * Revision 1.15  1998/08/20 13:50:42  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.14  1998/08/13 23:36:33  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.13  1998/06/26 22:03:28  keil
+ * send flags between hdlc frames
+ *
+ * Revision 1.12  1998/06/09 18:26:01  keil
+ * PH_DEACTIVATE B-channel every time signaled to higher layer
+ *
+ * Revision 1.11  1998/05/25 14:10:07  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 1.10  1998/05/25 12:57:59  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.9  1998/04/15 16:45:33  keil
+ * new init code
+ *
+ * Revision 1.8  1998/03/19 13:16:24  keil
+ * fix the correct release of the hscx
+ *
  * Revision 1.7  1998/02/12 23:07:36  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -30,6 +62,7 @@
 #define __NO_VERSION__
 #include "hisax.h"
 #include "hscx.h"
+#include "isac.h"
 #include "isdnl1.h"
 #include <linux/interrupt.h>
 
@@ -56,21 +89,20 @@
 modehscx(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	int hscx = bcs->channel;
+	int hscx = bcs->hw.hscx.hscx;
 
-	if (cs->debug & L1_DEB_HSCX) {
-		char tmp[40];
-		sprintf(tmp, "hscx %c mode %d ichan %d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "hscx %c mode %d ichan %d",
 			'A' + hscx, mode, bc);
-		debugl1(cs, tmp);
-	}
 	bcs->mode = mode;
-	cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, 0x85);
+	bcs->channel = bc;
 	cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF);
 	cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF);
 	cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF);
 	cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0);
 	cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0);
+	cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+		test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85);
 	cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30);
 	cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7);
 	cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7);
@@ -81,23 +113,25 @@
 
 	if (bc == 0) {
 		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX,
-			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f);
+			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
 		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR,
-			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : 0x2f);
+			      test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0);
 	} else {
-		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x3);
-		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x3);
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1);
+		cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1);
 	}
 	switch (mode) {
 		case (L1_MODE_NULL):
-			cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0xff);
-			cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0xff);
+			cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f);
+			cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f);
 			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84);
 			break;
 		case (L1_MODE_TRANS):
 			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4);
 			break;
 		case (L1_MODE_HDLC):
+			cs->BC_Write_Reg(cs, hscx, HSCX_CCR1,
+				test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d);
 			cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c);
 			break;
 	}
@@ -114,89 +148,106 @@
 	mark_bh(IMMEDIATE_BH);
 }
 
-static void
+void
 hscx_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct sk_buff *skb = arg;
 	long flags;
 
 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
 			save_flags(flags);
 			cli();
-			if (st->l1.bcs->hw.hscx.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
 				skb_queue_tail(&st->l1.bcs->squeue, skb);
 				restore_flags(flags);
 			} else {
-				st->l1.bcs->hw.hscx.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
 				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
 				st->l1.bcs->hw.hscx.count = 0;
 				restore_flags(flags);
 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 			}
 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.hscx.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
 				printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n");
 				break;
 			}
 			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
-			st->l1.bcs->hw.hscx.tx_skb = skb;
+			st->l1.bcs->tx_skb = skb;
 			st->l1.bcs->hw.hscx.count = 0;
 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 			break;
-		case (PH_PULL_REQ):
-			if (!st->l1.bcs->hw.hscx.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			modehscx(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
 	}
-
 }
 
 void
 close_hscxstate(struct BCState *bcs)
 {
-	struct sk_buff *skb;
-
-	modehscx(bcs, 0, 0);
+	modehscx(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
 		if (bcs->hw.hscx.rcvbuf) {
 			kfree(bcs->hw.hscx.rcvbuf);
 			bcs->hw.hscx.rcvbuf = NULL;
 		}
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
+		if (bcs->blog) {
+			kfree(bcs->blog);
+			bcs->blog = NULL;
 		}
-		if (bcs->hw.hscx.tx_skb) {
-			dev_kfree_skb(bcs->hw.hscx.tx_skb);
-			bcs->hw.hscx.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
 	}
 }
 
-static int
-open_hscxstate(struct IsdnCardState *cs,
-	       int bc)
+int
+open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	struct BCState *bcs = cs->bcs + bc;
-
 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
 		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
 			printk(KERN_WARNING
-			       "HiSax: No memory for hscx.rcvbuf\n");
+				"HiSax: No memory for hscx.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
 			return (1);
 		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+			return (2);
+		}
 		skb_queue_head_init(&bcs->rqueue);
 		skb_queue_head_init(&bcs->squeue);
 	}
-	bcs->hw.hscx.tx_skb = NULL;
+	bcs->tx_skb = NULL;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	bcs->event = 0;
 	bcs->hw.hscx.rcvidx = 0;
@@ -204,77 +255,78 @@
 	return (0);
 }
 
-static void
-hscx_manl1(struct PStack *st, int pr,
-	   void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			modehscx(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				modehscx(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
 int
 setstack_hscx(struct PStack *st, struct BCState *bcs)
 {
-	if (open_hscxstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+	if (open_hscxstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
 	st->l2.l2l1 = hscx_l2l1;
-	st->ma.manl1 = hscx_manl1;
 	setstack_manager(st);
 	bcs->st = st;
+	setstack_l1_B(st);
 	return (0);
 }
 
 HISAX_INITFUNC(void
 clear_pending_hscx_ints(struct IsdnCardState *cs))
 {
-	int val;
-	char tmp[64];
+	int val, eval;
 
 	val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA);
-	sprintf(tmp, "HSCX B ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX B ISTA %x", val);
 	if (val & 0x01) {
-		val = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
-		sprintf(tmp, "HSCX B EXIR %x", val);
-		debugl1(cs, tmp);
-	} else if (val & 0x02) {
-		val = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
-		sprintf(tmp, "HSCX A EXIR %x", val);
-		debugl1(cs, tmp);
+		eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR);
+		debugl1(cs, "HSCX B EXIR %x", eval);
+	}
+	if (val & 0x02) {
+		eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR);
+		debugl1(cs, "HSCX A EXIR %x", eval);
 	}
 	val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA);
-	sprintf(tmp, "HSCX A ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX A ISTA %x", val);
 	val = cs->BC_Read_Reg(cs, 1, HSCX_STAR);
-	sprintf(tmp, "HSCX B STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX B STAR %x", val);
 	val = cs->BC_Read_Reg(cs, 0, HSCX_STAR);
-	sprintf(tmp, "HSCX A STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "HSCX A STAR %x", val);
+	/* disable all IRQ */
 	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF);
 	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF);
-	cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
-	cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
 }
 
-HISAX_INITFUNC(void 
+HISAX_INITFUNC(void
 inithscx(struct IsdnCardState *cs))
 {
 	cs->bcs[0].BC_SetStack = setstack_hscx;
 	cs->bcs[1].BC_SetStack = setstack_hscx;
 	cs->bcs[0].BC_Close = close_hscxstate;
 	cs->bcs[1].BC_Close = close_hscxstate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
+	cs->bcs[0].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[0].hw.hscx.tsaxr1 = 3;
+	cs->bcs[1].hw.hscx.tsaxr0 = 0x2f;
+	cs->bcs[1].hw.hscx.tsaxr1 = 3;
 	modehscx(cs->bcs, 0, 0);
 	modehscx(cs->bcs + 1, 0, 0);
+}
+
+HISAX_INITFUNC(void
+inithscxisac(struct IsdnCardState *cs, int part))
+{
+	if (part & 1) {
+		clear_pending_isac_ints(cs);
+		clear_pending_hscx_ints(cs);
+		initisac(cs);
+		inithscx(cs);
+	}
+	if (part & 2) {
+		/* Reenable all IRQ */
+		cs->writeisac(cs, ISAC_MASK, 0);
+		cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0);
+		cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0);
+		/* RESET Receiver and Transmitter */
+		cs->writeisac(cs, ISAC_CMDR, 0x41);
+	}
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hscx.h linux.pre11.3/drivers/isdn/hisax/hscx.h
--- linux.vanilla/drivers/isdn/hisax/hscx.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/hscx.h	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: hscx.h,v 1.3 1997/07/27 21:38:35 keil Exp $
+/* $Id: hscx.h,v 1.4 1998/04/15 16:45:34 keil Exp $
 
  * hscx.h   HSCX specific defines
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: hscx.h,v $
+ * Revision 1.4  1998/04/15 16:45:34  keil
+ * new init code
+ *
  * Revision 1.3  1997/07/27 21:38:35  keil
  * new B-channel interface
  *
@@ -44,3 +47,4 @@
 extern void modehscx(struct BCState *bcs, int mode, int bc);
 extern void clear_pending_hscx_ints(struct IsdnCardState *cs);
 extern void inithscx(struct IsdnCardState *cs);
+extern void inithscxisac(struct IsdnCardState *cs, int part);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/hscx_irq.c linux.pre11.3/drivers/isdn/hisax/hscx_irq.c
--- linux.vanilla/drivers/isdn/hisax/hscx_irq.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/hscx_irq.c	Mon Jul 19 23:59:34 1999
@@ -1,12 +1,27 @@
-/* $Id: hscx_irq.c,v 1.7 1998/02/12 23:07:37 keil Exp $
+/* $Id: hscx_irq.c,v 1.12 1999/07/01 08:11:42 keil Exp $
 
  * hscx_irq.c     low level b-channel stuff for Siemens HSCX
  *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author     Karsten Keil (keil@isdn4linux.de)
  *
  * This is an include file for fast inline IRQ stuff
  *
  * $Log: hscx_irq.c,v $
+ * Revision 1.12  1999/07/01 08:11:42  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.11  1998/11/15 23:54:49  keil
+ * changes from 2.0
+ *
+ * Revision 1.10  1998/08/13 23:36:35  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.9  1998/06/24 14:44:51  keil
+ * Fix recovery of TX IRQ loss
+ *
+ * Revision 1.8  1998/04/10 10:35:22  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
  * Revision 1.7  1998/02/12 23:07:37  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -85,7 +100,7 @@
 	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
 		if (cs->debug & L1_DEB_WARN)
 			debugl1(cs, "hscx_empty_fifo: incoming packet too large");
-		WriteHSCXCMDR(cs, bcs->channel, 0x80);
+		WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
 		bcs->hw.hscx.rcvidx = 0;
 		return;
 	}
@@ -93,17 +108,16 @@
 	bcs->hw.hscx.rcvidx += count;
 	save_flags(flags);
 	cli();
-	READHSCXFIFO(cs, bcs->channel, ptr, count);
-	WriteHSCXCMDR(cs, bcs->channel, 0x80);
+	READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
 	restore_flags(flags);
 	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char tmp[256];
-		char *t = tmp;
+		char *t = bcs->blog;
 
 		t += sprintf(t, "hscx_empty_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', count);
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, bcs->blog);
 	}
 }
 
@@ -120,36 +134,35 @@
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hscx_fill_fifo");
 
-	if (!bcs->hw.hscx.tx_skb)
+	if (!bcs->tx_skb)
 		return;
-	if (bcs->hw.hscx.tx_skb->len <= 0)
+	if (bcs->tx_skb->len <= 0)
 		return;
 
 	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
-	if (bcs->hw.hscx.tx_skb->len > fifo_size) {
+	if (bcs->tx_skb->len > fifo_size) {
 		more = !0;
 		count = fifo_size;
 	} else
-		count = bcs->hw.hscx.tx_skb->len;
+		count = bcs->tx_skb->len;
 
-	waitforXFW(cs, bcs->channel);
+	waitforXFW(cs, bcs->hw.hscx.hscx);
 	save_flags(flags);
 	cli();
-	ptr = bcs->hw.hscx.tx_skb->data;
-	skb_pull(bcs->hw.hscx.tx_skb, count);
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt -= count;
 	bcs->hw.hscx.count += count;
-	WRITEHSCXFIFO(cs, bcs->channel, ptr, count);
-	WriteHSCXCMDR(cs, bcs->channel, more ? 0x8 : 0xa);
+	WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
 	restore_flags(flags);
 	if (cs->debug & L1_DEB_HSCX_FIFO) {
-		char tmp[256];
-		char *t = tmp;
+		char *t = bcs->blog;
 
 		t += sprintf(t, "hscx_fill_fifo %c cnt %d",
-			     bcs->channel ? 'B' : 'A', count);
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, bcs->blog);
 	}
 }
 
@@ -161,7 +174,6 @@
 	struct sk_buff *skb;
 	int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
 	int count;
-	char tmp[32];
 
 	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
 		return;
@@ -173,11 +185,9 @@
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "HSCX invalid frame");
 			if ((r & 0x40) && bcs->mode)
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "HSCX RDO mode=%d",
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX RDO mode=%d",
 						bcs->mode);
-					debugl1(cs, tmp);
-				}
 			if (!(r & 0x20))
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, "HSCX CRC error");
@@ -189,13 +199,12 @@
 				count = fifo_size;
 			hscx_empty_fifo(bcs, count);
 			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
-				if (cs->debug & L1_DEB_HSCX_FIFO) {
-					sprintf(tmp, "HX Frame %d", count);
-					debugl1(cs, tmp);
-				}
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
 				if (!(skb = dev_alloc_skb(count)))
 					printk(KERN_WARNING "HSCX: receive out of memory\n");
 				else {
+					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
 					skb_queue_tail(&bcs->rqueue, skb);
 				}
@@ -211,6 +220,7 @@
 			if (!(skb = dev_alloc_skb(fifo_size)))
 				printk(KERN_WARNING "HiSax: receive out of memory\n");
 			else {
+				SET_SKB_FREE(skb);
 				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
 				skb_queue_tail(&bcs->rqueue, skb);
 			}
@@ -219,20 +229,20 @@
 		}
 	}
 	if (val & 0x10) {	/* XPR */
-		if (bcs->hw.hscx.tx_skb) {
-			if (bcs->hw.hscx.tx_skb->len) {
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
 				hscx_fill_fifo(bcs);
 				return;
 			} else {
 				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->hw.hscx.tx_skb->pkt_type))
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
 					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
-				dev_kfree_skb(bcs->hw.hscx.tx_skb);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
 				bcs->hw.hscx.count = 0; 
-				bcs->hw.hscx.tx_skb = NULL;
+				bcs->tx_skb = NULL;
 			}
 		}
-		if ((bcs->hw.hscx.tx_skb = skb_dequeue(&bcs->squeue))) {
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 			bcs->hw.hscx.count = 0;
 			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
 			hscx_fill_fifo(bcs);
@@ -249,73 +259,60 @@
 
 	u_char exval;
 	struct BCState *bcs;
-	char tmp[32];
 
 	if (val & 0x01) {
 		bcs = cs->bcs + 1;
 		exval = READHSCX(cs, 1, HSCX_EXIR);
-		if (exval == 0x40) {
+		if (exval & 0x40) {
 			if (bcs->mode == 1)
 				hscx_fill_fifo(bcs);
 			else {
 				/* Here we lost an TX interrupt, so
 				   * restart transmitting the whole frame.
 				 */
-				if (bcs->hw.hscx.tx_skb) {
-					skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count);
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
 					bcs->tx_cnt += bcs->hw.hscx.count;
 					bcs->hw.hscx.count = 0;
 				}
-				WriteHSCXCMDR(cs, bcs->channel, 0x01);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "HSCX B EXIR %x Lost TX", exval);
-					debugl1(cs, tmp);
-				}
+				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
 			}
-		} else if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX B EXIR %x", exval);
-			debugl1(cs, tmp);
-		}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B EXIR %x", exval);
 	}
 	if (val & 0xf8) {
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX B interrupt %x", val);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX B interrupt %x", val);
 		hscx_interrupt(cs, val, 1);
 	}
 	if (val & 0x02) {
 		bcs = cs->bcs;
 		exval = READHSCX(cs, 0, HSCX_EXIR);
-		if (exval == 0x40) {
+		if (exval & 0x40) {
 			if (bcs->mode == L1_MODE_TRANS)
 				hscx_fill_fifo(bcs);
 			else {
 				/* Here we lost an TX interrupt, so
 				   * restart transmitting the whole frame.
 				 */
-				if (bcs->hw.hscx.tx_skb) {
-					skb_push(bcs->hw.hscx.tx_skb, bcs->hw.hscx.count);
+				if (bcs->tx_skb) {
+					skb_push(bcs->tx_skb, bcs->hw.hscx.count);
 					bcs->tx_cnt += bcs->hw.hscx.count;
 					bcs->hw.hscx.count = 0;
 				}
-				WriteHSCXCMDR(cs, bcs->channel, 0x01);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "HSCX A EXIR %x Lost TX", exval);
-					debugl1(cs, tmp);
-				}
+				WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
 			}
-		} else if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX A EXIR %x", exval);
-			debugl1(cs, tmp);
-		}
+		} else if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A EXIR %x", exval);
 	}
 	if (val & 0x04) {
 		exval = READHSCX(cs, 0, HSCX_ISTA);
-		if (cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp, "HSCX A interrupt %x", exval);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX A interrupt %x", exval);
 		hscx_interrupt(cs, exval, 0);
 	}
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/ipac.h linux.pre11.3/drivers/isdn/hisax/ipac.h
--- linux.vanilla/drivers/isdn/hisax/ipac.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/ipac.h	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: ipac.h,v 1.2 1997/10/29 18:51:21 keil Exp $
+/* $Id: ipac.h,v 1.3 1998/04/15 16:48:09 keil Exp $
 
  * ipac.h   IPAC specific defines
  *
@@ -6,6 +6,9 @@
  *
  *
  * $Log: ipac.h,v $
+ * Revision 1.3  1998/04/15 16:48:09  keil
+ * IPAC_ATX added
+ *
  * Revision 1.2  1997/10/29 18:51:21  keil
  * New files
  *
@@ -26,6 +29,7 @@
 #define IPAC_ACFG	0xC3
 #define IPAC_AOE	0xC4
 #define IPAC_ARX	0xC5
+#define IPAC_ATX	0xC5
 #define IPAC_PITA1	0xC6
 #define IPAC_PITA2	0xC7
 #define IPAC_POTA1	0xC8
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isac.c linux.pre11.3/drivers/isdn/hisax/isac.c
--- linux.vanilla/drivers/isdn/hisax/isac.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/isac.c	Mon Jul 19 23:59:34 1999
@@ -1,11 +1,43 @@
-/* $Id: isac.c,v 1.12 1998/02/12 23:07:40 keil Exp $
+/* $Id: isac.c,v 1.21 1999/07/12 21:05:17 keil Exp $
 
  * isac.c   ISAC specific routines
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
  *
  * $Log: isac.c,v $
+ * Revision 1.21  1999/07/12 21:05:17  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.20  1999/07/09 08:23:06  keil
+ * Fix ISAC lost TX IRQ handling
+ *
+ * Revision 1.19  1999/07/01 08:11:43  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.18  1998/11/15 23:54:51  keil
+ * changes from 2.0
+ *
+ * Revision 1.17  1998/08/13 23:36:37  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.16  1998/05/25 12:58:01  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.15  1998/04/15 16:45:32  keil
+ * new init code
+ *
+ * Revision 1.14  1998/04/10 10:35:26  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 1.13  1998/03/07 22:57:01  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 1.12  1998/02/12 23:07:40  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -47,6 +79,7 @@
 #define __NO_VERSION__
 #include "hisax.h"
 #include "isac.h"
+#include "arcofi.h"
 #include "isdnl1.h"
 #include <linux/interrupt.h>
 
@@ -63,60 +96,47 @@
 	int val;
 
 	val = cs->readisac(cs, ISAC_RBCH);
-	printk(KERN_INFO "%s ISAC version : %s\n", s, ISACVer[(val >> 5) & 3]);
+	printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]);
 }
 
 static void
 ph_command(struct IsdnCardState *cs, unsigned int command)
 {
-	if (cs->debug & L1_DEB_ISAC) {
-		char tmp[32];
-		sprintf(tmp, "ph_command %x", command);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "ph_command %x", command);
 	cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3);
 }
 
-static void
-manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
-	struct PStack *st;
-
-	st = cs->stlist;
-	while (st) {
-		st->ma.manl1(st, msg, arg);
-		st = st->next;
-	}
-}
 
 static void
 isac_new_ph(struct IsdnCardState *cs)
 {
-	switch (cs->ph_state) {
+	switch (cs->dc.isac.ph_state) {
 		case (ISAC_IND_RS):
 		case (ISAC_IND_EI):
 			ph_command(cs, ISAC_CMD_DUI);
-			manl1_msg(cs, PH_RESET_IND, NULL);
+			l1_msg(cs, HW_RESET | INDICATION, NULL);
 			break;
 		case (ISAC_IND_DID):
-			manl1_msg(cs, PH_DEACT_CNF, NULL);
+			l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
 			break;
 		case (ISAC_IND_DR):
-			manl1_msg(cs, PH_DEACT_IND, NULL);
+			l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
 			break;
 		case (ISAC_IND_PU):
-			manl1_msg(cs, PH_POWERUP_CNF, NULL);
+			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
 			break;
 		case (ISAC_IND_RSY):
-			manl1_msg(cs, PH_RSYNC_IND, NULL);
+			l1_msg(cs, HW_RSYNC | INDICATION, NULL);
 			break;
 		case (ISAC_IND_ARD):
-			manl1_msg(cs, PH_INFO2_IND, NULL);
+			l1_msg(cs, HW_INFO2 | INDICATION, NULL);
 			break;
 		case (ISAC_IND_AI8):
-			manl1_msg(cs, PH_I4_P8_IND, NULL);
+			l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
 			break;
 		case (ISAC_IND_AI10):
-			manl1_msg(cs, PH_I4_P10_IND, NULL);
+			l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
 			break;
 		default:
 			break;
@@ -130,13 +150,12 @@
 	
 	if (!cs)
 		return;
-
 	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
 		if (cs->debug)
 			debugl1(cs, "D-Channel Busy cleared");
 		stptr = cs->stlist;
 		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_CNF, NULL);
+			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
 			stptr = stptr->next;
 		}
 	}
@@ -146,14 +165,10 @@
 		DChannel_proc_rcv(cs);
 	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
 		DChannel_proc_xmt(cs);
-	if (test_and_clear_bit(D_RX_MON0, &cs->event))
-		test_and_set_bit(HW_MON0_TX_END, &cs->HW_Flags);
 	if (test_and_clear_bit(D_RX_MON1, &cs->event))
-		test_and_set_bit(HW_MON1_TX_END, &cs->HW_Flags);
-	if (test_and_clear_bit(D_TX_MON0, &cs->event))
-		test_and_set_bit(HW_MON0_RX_END, &cs->HW_Flags);
+		arcofi_fsm(cs, ARCOFI_RX_END, NULL);
 	if (test_and_clear_bit(D_TX_MON1, &cs->event))
-		test_and_set_bit(HW_MON1_RX_END, &cs->HW_Flags);
+		arcofi_fsm(cs, ARCOFI_TX_END, NULL);
 }
 
 void
@@ -165,13 +180,10 @@
 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
 		debugl1(cs, "isac_empty_fifo");
 
-	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN) {
-		if (cs->debug & L1_DEB_WARN) {
-			char tmp[40];
-			sprintf(tmp, "isac_empty_fifo overrun %d",
+	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "isac_empty_fifo overrun %d",
 				cs->rcvidx + count);
-			debugl1(cs, tmp);
-		}
 		cs->writeisac(cs, ISAC_CMDR, 0x80);
 		cs->rcvidx = 0;
 		return;
@@ -184,12 +196,11 @@
 	cs->writeisac(cs, ISAC_CMDR, 0x80);
 	restore_flags(flags);
 	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
+		char *t = cs->dlog;
 
 		t += sprintf(t, "isac_empty_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, cs->dlog);
 	}
 }
 
@@ -231,12 +242,11 @@
 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
 	add_timer(&cs->dbusytimer);
 	if (cs->debug & L1_DEB_ISAC_FIFO) {
-		char tmp[128];
-		char *t = tmp;
+		char *t = cs->dlog;
 
 		t += sprintf(t, "isac_fill_fifo cnt %d", count);
 		QuickHex(t, ptr, count);
-		debugl1(cs, tmp);
+		debugl1(cs, cs->dlog);
 	}
 }
 
@@ -255,12 +265,9 @@
 	struct sk_buff *skb;
 	unsigned int count;
 	long flags;
-	char tmp[32];
 
-	if (cs->debug & L1_DEB_ISAC) {
-		sprintf(tmp, "ISAC interrupt %x", val);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_ISAC)
+		debugl1(cs, "ISAC interrupt %x", val);
 	if (val & 0x80) {	/* RME */
 		exval = cs->readisac(cs, ISAC_RSTA);
 		if ((exval & 0x70) != 0x20) {
@@ -283,6 +290,7 @@
 				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
 					printk(KERN_WARNING "HiSax: D receive out of memory\n");
 				else {
+					SET_SKB_FREE(skb);
 					memcpy(skb_put(skb, count), cs->rcvbuf, count);
 					skb_queue_tail(&cs->rq, skb);
 				}
@@ -310,7 +318,7 @@
 				isac_fill_fifo(cs);
 				goto afterXPR;
 			} else {
-				dev_kfree_skb(cs->tx_skb);
+				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
 				cs->tx_cnt = 0;
 				cs->tx_skb = NULL;
 			}
@@ -323,12 +331,20 @@
 	}
       afterXPR:
 	if (val & 0x04) {	/* CISQ */
-		cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf;
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "ph_state change %x", cs->ph_state);
-			debugl1(cs, tmp);
+		exval = cs->readisac(cs, ISAC_CIR0);
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC CIR0 %02X", exval );
+		if (exval & 2) {
+			cs->dc.isac.ph_state = (exval >> 2) & 0xf;
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
+			isac_sched_event(cs, D_L1STATECHANGE);
+		}
+		if (exval & 1) {
+			exval = cs->readisac(cs, ISAC_CIR1);
+			if (cs->debug & L1_DEB_ISAC)
+				debugl1(cs, "ISAC CIR1 %02X", exval );
 		}
-		isac_sched_event(cs, D_L1STATECHANGE);
 	}
 	if (val & 0x02) {	/* SIN */
 		/* never */
@@ -337,131 +353,149 @@
 	}
 	if (val & 0x01) {	/* EXI */
 		exval = cs->readisac(cs, ISAC_EXIR);
-		if (cs->debug & L1_DEB_WARN) {
-			sprintf(tmp, "ISAC EXIR %02x", exval);
-			debugl1(cs, tmp);
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "ISAC EXIR %02x", exval);
+		if (exval & 0x80) {  /* XMR */
+			debugl1(cs, "ISAC XMR");
+			printk(KERN_WARNING "HiSax: ISAC XMR\n");
 		}
-		if (exval & 0x04) {
-			v1 = cs->readisac(cs, ISAC_MOSR);
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "ISAC MOSR %02x", v1);
-				debugl1(cs, tmp);
+		if (exval & 0x40) {  /* XDU */
+			debugl1(cs, "ISAC XDU");
+			printk(KERN_WARNING "HiSax: ISAC XDU\n");
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				isac_sched_event(cs, D_CLEARBUSY);
+			if (cs->tx_skb) { /* Restart frame */
+				skb_push(cs->tx_skb, cs->tx_cnt);
+				cs->tx_cnt = 0;
+				isac_fill_fifo(cs);
+			} else {
+				printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
+				debugl1(cs, "ISAC XDU no skb");
 			}
+		}
+		if (exval & 0x04) {  /* MOS */
+			v1 = cs->readisac(cs, ISAC_MOSR);
+			if (cs->debug & L1_DEB_MONITOR)
+				debugl1(cs, "ISAC MOSR %02x", v1);
 #if ARCOFI_USE
 			if (v1 & 0x08) {
-				if (!cs->mon_rx) {
-					if (!(cs->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
+				if (!cs->dc.isac.mon_rx) {
+					if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
 						if (cs->debug & L1_DEB_WARN)
 							debugl1(cs, "ISAC MON RX out of memory!");
-						cs->mocr &= 0xf0;
-						cs->mocr |= 0x0a;
-						cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+						cs->dc.isac.mocr &= 0xf0;
+						cs->dc.isac.mocr |= 0x0a;
+						cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 						goto afterMONR0;
 					} else
-						cs->mon_rxp = 0;
+						cs->dc.isac.mon_rxp = 0;
 				}
-				if (cs->mon_rxp >= MAX_MON_FRAME) {
-					cs->mocr &= 0xf0;
-					cs->mocr |= 0x0a;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					cs->mon_rxp = 0;
+				if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
+					cs->dc.isac.mocr &= 0xf0;
+					cs->dc.isac.mocr |= 0x0a;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ISAC MON RX overflow!");
 					goto afterMONR0;
 				}
-				cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC MOR0 %02x", cs->mon_rx[cs->mon_rxp -1]);
-					debugl1(cs, tmp);
-				}
-				if (cs->mon_rxp == 1) {
-					cs->mocr |= 0x04;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
+				if (cs->dc.isac.mon_rxp == 1) {
+					cs->dc.isac.mocr |= 0x04;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				}
 			}
 		      afterMONR0:
 			if (v1 & 0x80) {
-				if (!cs->mon_rx) {
-					if (!(cs->mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
+				if (!cs->dc.isac.mon_rx) {
+					if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
 						if (cs->debug & L1_DEB_WARN)
 							debugl1(cs, "ISAC MON RX out of memory!");
-						cs->mocr &= 0x0f;
-						cs->mocr |= 0xa0;
-						cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+						cs->dc.isac.mocr &= 0x0f;
+						cs->dc.isac.mocr |= 0xa0;
+						cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 						goto afterMONR1;
 					} else
-						cs->mon_rxp = 0;
+						cs->dc.isac.mon_rxp = 0;
 				}
-				if (cs->mon_rxp >= MAX_MON_FRAME) {
-					cs->mocr &= 0x0f;
-					cs->mocr |= 0xa0;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-					cs->mon_rxp = 0;
+				if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
+					cs->dc.isac.mocr &= 0x0f;
+					cs->dc.isac.mocr |= 0xa0;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mon_rxp = 0;
 					if (cs->debug & L1_DEB_WARN)
 						debugl1(cs, "ISAC MON RX overflow!");
 					goto afterMONR1;
 				}
-				cs->mon_rx[cs->mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC MOR1 %02x", cs->mon_rx[cs->mon_rxp -1]);
-					debugl1(cs, tmp);
-				}
-				if (cs->mon_rxp == 1) {
-					cs->mocr |= 0x40;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
-				}
+				cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]);
+				cs->dc.isac.mocr |= 0x40;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 			}
 		      afterMONR1:
 			if (v1 & 0x04) {
-				cs->mocr &= 0xf0;
-				cs->mocr |= 0x0a;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+				cs->dc.isac.mocr &= 0xf0;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->dc.isac.mocr |= 0x0a;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				isac_sched_event(cs, D_RX_MON0);
 			}
 			if (v1 & 0x40) {
-				cs->mocr &= 0x0f;
-				cs->mocr |= 0xa0;
-				cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+				cs->dc.isac.mocr &= 0x0f;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+				cs->dc.isac.mocr |= 0xa0;
+				cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
 				isac_sched_event(cs, D_RX_MON1);
 			}
 			if (v1 & 0x02) {
-				if (!cs->mon_tx) {
-					cs->mocr &= 0xf0;
-					cs->mocr |= 0x0a;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+				if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && 
+					(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && 
+					!(v1 & 0x08))) {
+					cs->dc.isac.mocr &= 0xf0;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mocr |= 0x0a;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					if (cs->dc.isac.mon_txc &&
+						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
+						isac_sched_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
-				if (cs->mon_txp >= cs->mon_txc) {
-					if (cs->mon_txc)
-						isac_sched_event(cs, D_TX_MON0);
+				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
+					isac_sched_event(cs, D_TX_MON0);
 					goto AfterMOX0;
 				}
 				cs->writeisac(cs, ISAC_MOX0,
-					cs->mon_tx[cs->mon_txp++]);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC %02x -> MOX0", cs->mon_tx[cs->mon_txp -1]);
-					debugl1(cs, tmp);
-				}
+					cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
 			}
 		      AfterMOX0:
 			if (v1 & 0x20) {
-				if (!cs->mon_tx) {
-					cs->mocr &= 0x0f;
-					cs->mocr |= 0xa0;
-					cs->writeisac(cs, ISAC_MOCR, cs->mocr);
+				if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && 
+					(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && 
+					!(v1 & 0x80))) {
+					cs->dc.isac.mocr &= 0x0f;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					cs->dc.isac.mocr |= 0xa0;
+					cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
+					if (cs->dc.isac.mon_txc &&
+						(cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
+						isac_sched_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
-				if (cs->mon_txp >= cs->mon_txc) {
-					if (cs->mon_txc)
-						isac_sched_event(cs, D_TX_MON1);
+				if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
+					isac_sched_event(cs, D_TX_MON1);
 					goto AfterMOX1;
 				}
 				cs->writeisac(cs, ISAC_MOX1,
-					cs->mon_tx[cs->mon_txp++]);
-				if (cs->debug & L1_DEB_WARN) {
-					sprintf(tmp, "ISAC %02x -> MOX1", cs->mon_tx[cs->mon_txp -1]);
-					debugl1(cs, tmp);
-				}
+					cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
+				if (cs->debug & L1_DEB_MONITOR)
+					debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]);
 			}
 		      AfterMOX1:
 #endif
@@ -470,14 +504,18 @@
 }
 
 static void
-ISAC_l2l1(struct PStack *st, int pr, void *arg)
+ISAC_l1hw(struct PStack *st, int pr, void *arg)
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
 	struct sk_buff *skb = arg;
-	char str[64];
+	int  val;
 
 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA |REQUEST):
+			if (cs->debug & DEB_DLOG_HEX)
+				LogFrame(cs, skb->data, skb->len);
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
 			if (cs->tx_skb) {
 				skb_queue_tail(&cs->sq, skb);
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -485,12 +523,6 @@
 					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
 #endif
 			} else {
-				if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
-					LogFrame(cs, skb->data, skb->len);
-					sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-					dlogframe(cs, skb->data + 4, skb->len - 4,
-						  str);
-				}
 				cs->tx_skb = skb;
 				cs->tx_cnt = 0;
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -500,19 +532,17 @@
 				isac_fill_fifo(cs);
 			}
 			break;
-		case (PH_PULL_IND):
+		case (PH_PULL |INDICATION):
 			if (cs->tx_skb) {
 				if (cs->debug & L1_DEB_WARN)
 					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
 				skb_queue_tail(&cs->sq, skb);
 				break;
 			}
-			if ((cs->dlogflag) && (!(skb->data[2] & 1))) {	/* I-FRAME */
+			if (cs->debug & DEB_DLOG_HEX)
 				LogFrame(cs, skb->data, skb->len);
-				sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
-				dlogframe(cs, skb->data + 4, skb->len - 4,
-					  str);
-			}
+			if (cs->debug & DEB_DLOG_VERBOSE)
+				dlogframe(cs, skb, 0);
 			cs->tx_skb = skb;
 			cs->tx_cnt = 0;
 #ifdef L2FRAME_DEBUG		/* psa */
@@ -521,46 +551,36 @@
 #endif
 			isac_fill_fifo(cs);
 			break;
-		case (PH_PULL_REQ):
+		case (PH_PULL | REQUEST):
 #ifdef L2FRAME_DEBUG		/* psa */
 			if (cs->debug & L1_DEB_LAPD)
 				debugl1(cs, "-> PH_REQUEST_PULL");
 #endif
 			if (!cs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
-	}
-}
-
-void
-isac_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
-{
-	u_char val;
-	char tmp[32];
-	
-	switch(msg) {
-		case PH_RESET_REQ:
-			if ((cs->ph_state == ISAC_IND_EI) ||
-				(cs->ph_state == ISAC_IND_DR) ||
-				(cs->ph_state == ISAC_IND_RS))
+		case (HW_RESET | REQUEST):
+			if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
+				(cs->dc.isac.ph_state == ISAC_IND_DR) ||
+				(cs->dc.isac.ph_state == ISAC_IND_RS))
 			        ph_command(cs, ISAC_CMD_TIM);
 			else
 				ph_command(cs, ISAC_CMD_RS);
 			break;
-		case PH_ENABLE_REQ:
+		case (HW_ENABLE | REQUEST):
 			ph_command(cs, ISAC_CMD_TIM);
 			break;
-		case PH_INFO3_REQ:
+		case (HW_INFO3 | REQUEST):
 			ph_command(cs, ISAC_CMD_AR8);
 			break;
-		case PH_TESTLOOP_REQ:
+		case (HW_TESTLOOP | REQUEST):
 			val = 0;
-			if (1 & (int) arg)
+			if (1 & (long) arg)
 				val |= 0x0c;
-			if (2 & (int) arg)
+			if (2 & (long) arg)
 				val |= 0x3;
 			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 				/* IOM 1 Mode */
@@ -580,11 +600,21 @@
 					cs->writeisac(cs, ISAC_ADF1, 0x0);
 			}
 			break;
-		default:
-			if (cs->debug & L1_DEB_WARN) {
-				sprintf(tmp, "isac_l1cmd unknown %4x", msg);
-				debugl1(cs, tmp);
+		case (HW_DEACTIVATE | RESPONSE):
+			discard_queue(&cs->rq);
+			discard_queue(&cs->sq);
+			if (cs->tx_skb) {
+				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+				cs->tx_skb = NULL;
 			}
+			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
+				del_timer(&cs->dbusytimer);
+			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
+				isac_sched_event(cs, D_CLEARBUSY);
+			break;
+		default:
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isac_l1hw unknown %04x", pr);
 			break;
 	}
 }
@@ -592,23 +622,53 @@
 void
 setstack_isac(struct PStack *st, struct IsdnCardState *cs)
 {
-	st->l2.l2l1 = ISAC_l2l1;
+	st->l1.l1hw = ISAC_l1hw;
+}
+
+void 
+DC_Close_isac(struct IsdnCardState *cs) {
+	if (cs->dc.isac.mon_rx) {
+		kfree(cs->dc.isac.mon_rx);
+		cs->dc.isac.mon_rx = NULL;
+	}
+	if (cs->dc.isac.mon_tx) {
+		kfree(cs->dc.isac.mon_tx);
+		cs->dc.isac.mon_tx = NULL;
+	}
 }
 
 static void
 dbusy_timer_handler(struct IsdnCardState *cs)
 {
 	struct PStack *stptr;
+	int	rbch, star;
 
 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
-		if (cs->debug)
-			debugl1(cs, "D-Channel Busy");
-		test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
-		stptr = cs->stlist;
-		
-		while (stptr != NULL) {
-			stptr->l1.l1l2(stptr, PH_PAUSE_IND, NULL);
-			stptr = stptr->next;
+		rbch = cs->readisac(cs, ISAC_RBCH);
+		star = cs->readisac(cs, ISAC_STAR);
+		if (cs->debug) 
+			debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
+				rbch, star);
+		if (rbch & ISAC_RBCH_XAC) { /* D-Channel Busy */
+			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
+			stptr = cs->stlist;
+			while (stptr != NULL) {
+				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
+				stptr = stptr->next;
+			}
+		} else {
+			/* discard frame; reset transceiver */
+			test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
+			if (cs->tx_skb) {
+				idev_kfree_skb(cs->tx_skb, FREE_WRITE);
+				cs->tx_cnt = 0;
+				cs->tx_skb = NULL;
+			} else {
+				printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n");
+				debugl1(cs, "D-Channel Busy no skb");
+			}
+			cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */
+			cs->irq_func(cs->irq, cs, NULL);
 		}
 	}
 }
@@ -617,13 +677,15 @@
 initisac(struct IsdnCardState *cs))
 {
 	cs->tqueue.routine = (void *) (void *) isac_bh;
-	cs->l1cmd = isac_l1cmd;
 	cs->setstack_d = setstack_isac;
+	cs->DC_Close = DC_Close_isac;
+	cs->dc.isac.mon_tx = NULL;
+	cs->dc.isac.mon_rx = NULL;
 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
 	cs->dbusytimer.data = (long) cs;
 	init_timer(&cs->dbusytimer);
   	cs->writeisac(cs, ISAC_MASK, 0xff);
-  	cs->mocr = 0xaa;
+  	cs->dc.isac.mocr = 0xaa;
 	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
 		/* IOM 1 Mode */
 		cs->writeisac(cs, ISAC_ADF2, 0x0);
@@ -633,7 +695,9 @@
 		cs->writeisac(cs, ISAC_MODE, 0xc9);
 	} else {
 		/* IOM 2 Mode */
-		cs->writeisac(cs, ISAC_ADF2, 0x80);
+		if (!cs->dc.isac.adf2)
+			cs->dc.isac.adf2 = 0x80;
+		cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2);
 		cs->writeisac(cs, ISAC_SQXR, 0x2f);
 		cs->writeisac(cs, ISAC_SPCR, 0x00);
 		cs->writeisac(cs, ISAC_STCR, 0x70);
@@ -648,35 +712,24 @@
 HISAX_INITFUNC(void
 clear_pending_isac_ints(struct IsdnCardState *cs))
 {
-	int val;
-	char tmp[64];
+	int val, eval;
 
 	val = cs->readisac(cs, ISAC_STAR);
-	sprintf(tmp, "ISAC STAR %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC STAR %x", val);
 	val = cs->readisac(cs, ISAC_MODE);
-	sprintf(tmp, "ISAC MODE %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC MODE %x", val);
 	val = cs->readisac(cs, ISAC_ADF2);
-	sprintf(tmp, "ISAC ADF2 %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC ADF2 %x", val);
 	val = cs->readisac(cs, ISAC_ISTA);
-	sprintf(tmp, "ISAC ISTA %x", val);
-	debugl1(cs, tmp);
+	debugl1(cs, "ISAC ISTA %x", val);
 	if (val & 0x01) {
-		val = cs->readisac(cs, ISAC_EXIR);
-		sprintf(tmp, "ISAC EXIR %x", val);
-		debugl1(cs, tmp);
-	} else if (val & 0x04) {
-		val = cs->readisac(cs, ISAC_CIR0);
-		sprintf(tmp, "ISAC CIR0 %x", val);
-		debugl1(cs, tmp);
-		cs->ph_state = (val >> 2) & 0xf;
-	} else {
-		cs->ph_state = (cs->readisac(cs, ISAC_CIX0) >> 2) & 0xf;
+		eval = cs->readisac(cs, ISAC_EXIR);
+		debugl1(cs, "ISAC EXIR %x", eval);
 	}
+	val = cs->readisac(cs, ISAC_CIR0);
+	debugl1(cs, "ISAC CIR0 %x", val);
+	cs->dc.isac.ph_state = (val >> 2) & 0xf;
 	isac_sched_event(cs, D_L1STATECHANGE);
+	/* Disable all IRQ */
 	cs->writeisac(cs, ISAC_MASK, 0xFF);
-	cs->writeisac(cs, ISAC_MASK, 0);
-	cs->writeisac(cs, ISAC_CMDR, 0x41);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isac.h linux.pre11.3/drivers/isdn/hisax/isac.h
--- linux.vanilla/drivers/isdn/hisax/isac.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/isac.h	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: isac.h,v 1.4 1997/10/29 19:09:34 keil Exp $
+/* $Id: isac.h,v 1.5 1998/05/25 12:58:03 keil Exp $
 
  * isac.h   ISAC specific defines
  *
@@ -6,6 +6,10 @@
  *
  *
  * $Log: isac.h,v $
+ * Revision 1.5  1998/05/25 12:58:03  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 1.4  1997/10/29 19:09:34  keil
  * new L1
  *
@@ -26,16 +30,18 @@
 #define ISAC_STAR 0x21
 #define ISAC_CMDR 0x21
 #define ISAC_EXIR 0x24
-#define ISAC_RBCH 0x2a
 #define ISAC_ADF2 0x39
 #define ISAC_SPCR 0x30
 #define ISAC_ADF1 0x38
 #define ISAC_CIR0 0x31
 #define ISAC_CIX0 0x31
+#define ISAC_CIR1 0x33
+#define ISAC_CIX1 0x33
 #define ISAC_STCR 0x37
 #define ISAC_MODE 0x22
 #define ISAC_RSTA 0x27
 #define ISAC_RBCL 0x25
+#define ISAC_RBCH 0x2A
 #define ISAC_TIMR 0x23
 #define ISAC_SQXR 0x3b
 #define ISAC_MOSR 0x3a
@@ -44,6 +50,8 @@
 #define ISAC_MOX0 0x32
 #define ISAC_MOR1 0x34
 #define ISAC_MOX1 0x34
+
+#define ISAC_RBCH_XAC 0x80
 
 #define ISAC_CMD_TIM	0x0
 #define ISAC_CMD_RS	0x1
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isar.c linux.pre11.3/drivers/isdn/hisax/isar.c
--- linux.vanilla/drivers/isdn/hisax/isar.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/isar.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,942 @@
+/* $Id: isar.c,v 1.3 1999/07/01 08:11:45 keil Exp $
+
+ * isar.c   ISAR (Siemens PSB 7110) specific routines
+ *
+ * Author       Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: isar.c,v $
+ * Revision 1.3  1999/07/01 08:11:45  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.2  1998/11/15 23:54:53  keil
+ * changes from 2.0
+ *
+ * Revision 1.1  1998/08/13 23:33:47  keil
+ * First version, only init
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isar.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+#define DBG_LOADFIRM	0
+#define DUMP_MBOXFRAME	2
+
+#define MIN(a,b) ((a<b)?a:b)
+
+void isar_setup(struct IsdnCardState *cs);
+
+static inline int
+waitforHIA(struct IsdnCardState *cs, int timeout)
+{
+
+	while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) {
+		udelay(1);
+		timeout--;
+	}
+	if (!timeout)
+		printk(KERN_WARNING "HiSax: ISAR waitforHIA timeout\n");
+	return(timeout);
+}
+
+
+int
+sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
+	u_char *msg)
+{
+	long flags;
+	int i;
+	
+	if (!waitforHIA(cs, 4000))
+		return(0);
+#if DUMP_MBOXFRAME
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len);
+#endif
+	save_flags(flags);
+	cli();
+	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg);
+	cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len);
+	cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0);
+	if (msg && len) {
+		cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]);
+		for (i=1; i<len; i++)
+			cs->BC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]);
+#if DUMP_MBOXFRAME>1
+		if (cs->debug & L1_DEB_HSCX_FIFO) {
+			char tmp[256], *t;
+			
+			i = len;
+			while (i>0) {
+				t = tmp;
+				t += sprintf(t, "sendmbox cnt %d", len);
+				QuickHex(t, &msg[len-i], (i>64) ? 64:i);
+				debugl1(cs, tmp);
+				i -= 64;
+			}
+		}
+#endif
+	}
+	cs->BC_Write_Reg(cs, 1, ISAR_HIS, his);
+	restore_flags(flags);
+	waitforHIA(cs, 10000);
+	return(1);
+}
+
+/* Call only with IRQ disabled !!! */
+inline void
+rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
+{
+	int i;
+
+	cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0);
+	if (msg && ireg->clsb) {
+		msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX);
+		for (i=1; i < ireg->clsb; i++)
+			 msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX);
+#if DUMP_MBOXFRAME>1
+		if (cs->debug & L1_DEB_HSCX_FIFO) {
+			char tmp[256], *t;
+			
+			i = ireg->clsb;
+			while (i>0) {
+				t = tmp;
+				t += sprintf(t, "rcv_mbox cnt %d", ireg->clsb);
+				QuickHex(t, &msg[ireg->clsb-i], (i>64) ? 64:i);
+				debugl1(cs, tmp);
+				i -= 64;
+			}
+		}
+#endif
+	}
+	cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+}
+
+/* Call only with IRQ disabled !!! */
+inline void
+get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
+{
+	ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);
+	ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H);
+	ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);
+#if DUMP_MBOXFRAME
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
+			ireg->clsb);
+#endif
+}
+
+int
+waitrecmsg(struct IsdnCardState *cs, u_char *len,
+	u_char *msg, int maxdelay)
+{
+	int timeout = 0;
+	long flags;
+	struct isar_reg *ir = cs->bcs[0].hw.isar.reg;
+	
+	
+	while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) &&
+		(timeout++ < maxdelay))
+		udelay(1);
+	if (timeout >= maxdelay) {
+		printk(KERN_WARNING"isar recmsg IRQSTA timeout\n");
+		return(0);
+	}
+	save_flags(flags);
+	cli();
+	get_irq_infos(cs, ir);
+	rcv_mbox(cs, ir, msg);
+	*len = ir->clsb;
+	restore_flags(flags);
+	return(1);
+}
+
+int
+ISARVersion(struct IsdnCardState *cs, char *s)
+{
+	int ver;
+	u_char msg[] = ISAR_MSG_HWVER;
+	u_char tmp[64];
+	u_char len;
+	int debug;
+
+	cs->cardmsg(cs, CARD_RESET,  NULL);
+	/* disable ISAR IRQ */
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+	debug = cs->debug;
+	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
+	if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg))
+		return(-1);
+	if (!waitrecmsg(cs, &len, tmp, 100000))
+		 return(-2);
+	cs->debug = debug;
+	if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) {
+		if (len == 1) {
+			ver = tmp[0] & 0xf;
+			printk(KERN_INFO "%s ISAR version %d\n", s, ver);
+			return(ver);
+		}
+		return(-3);
+	}
+	return(-4);
+}
+
+int
+isar_load_firmware(struct IsdnCardState *cs, u_char *buf)
+{
+	int ret, size, cnt, debug;
+	u_char len, nom, noc;
+	u_short sadr, left, *sp;
+	u_char *p = buf;
+	u_char *msg, *tmpmsg, *mp, tmp[64];
+	long flags;
+	struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
+	
+	struct {u_short sadr;
+		u_short len;
+		u_short d_key;
+	} blk_head;
+		
+#define	BLK_HEAD_SIZE 6
+	if (1 != (ret = ISARVersion(cs, "Testing"))) {
+		printk(KERN_ERR"isar_load_firmware wrong isar version %d\n", ret);
+		return(1);
+	}
+	debug = cs->debug;
+#if DBG_LOADFIRM<2
+	cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO);
+#endif
+	printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf);
+	if ((ret = verify_area(VERIFY_READ, (void *) p, sizeof(int)))) {
+		printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret);
+		return ret;
+	}
+	if ((ret = copy_from_user(&size, p, sizeof(int)))) {
+		printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
+		return ret;
+	}
+	p += sizeof(int);
+	printk(KERN_DEBUG"isar_load_firmware size: %d\n", size);
+	if ((ret = verify_area(VERIFY_READ, (void *) p, size))) {
+		printk(KERN_ERR"isar_load_firmware verify_area ret %d\n", ret);
+		return ret;
+	}
+	cnt = 0;
+	/* disable ISAR IRQ */
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+	if (!(msg = kmalloc(256, GFP_KERNEL))) {
+		printk(KERN_ERR"isar_load_firmware no buffer\n");
+		return (1);
+	}
+	if (!(tmpmsg = kmalloc(256, GFP_KERNEL))) {
+		printk(KERN_ERR"isar_load_firmware no tmp buffer\n");
+		kfree(msg);
+		return (1);
+	}
+	while (cnt < size) {
+		if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) {
+			printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
+			goto reterror;
+		}
+		cnt += BLK_HEAD_SIZE;
+		p += BLK_HEAD_SIZE;
+		printk(KERN_DEBUG"isar firmware block (%#x,%5d,%#x)\n",
+			blk_head.sadr, blk_head.len, blk_head.d_key & 0xff);
+		sadr = blk_head.sadr;
+		left = blk_head.len;
+		if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) {
+			printk(KERN_ERR"isar sendmsg dkey failed\n");
+			ret = 1;goto reterror;
+		}
+		if (!waitrecmsg(cs, &len, tmp, 100000)) {
+			printk(KERN_ERR"isar waitrecmsg dkey failed\n");
+			ret = 1;goto reterror;
+		}
+		if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) {
+			printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n",
+				ireg->iis, ireg->cmsb, len);
+			ret = 1;goto reterror;
+		}
+		while (left>0) {
+			noc = MIN(126, left);
+			nom = 2*noc;
+			mp  = msg;
+			*mp++ = sadr / 256;
+			*mp++ = sadr % 256;
+			left -= noc;
+			*mp++ = noc;
+			if ((ret = copy_from_user(tmpmsg, p, nom))) {
+				printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret);
+				goto reterror;
+			}
+			p += nom;
+			cnt += nom;
+			nom += 3;
+			sp = (u_short *)tmpmsg;
+#if DBG_LOADFIRM
+			printk(KERN_DEBUG"isar: load %3d words at %04x\n",
+				 noc, sadr);
+#endif
+			sadr += noc;
+			while(noc) {
+				*mp++ = *sp / 256;
+				*mp++ = *sp % 256;
+				sp++;
+				noc--;
+			}
+			if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) {
+				printk(KERN_ERR"isar sendmsg prog failed\n");
+				ret = 1;goto reterror;
+			}
+			if (!waitrecmsg(cs, &len, tmp, 100000)) {
+				printk(KERN_ERR"isar waitrecmsg prog failed\n");
+				ret = 1;goto reterror;
+			}
+			if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) {
+				printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n",
+					ireg->iis, ireg->cmsb, len);
+				ret = 1;goto reterror;
+			}
+		}
+		printk(KERN_DEBUG"isar firmware block %5d words loaded\n",
+			blk_head.len);
+	}
+	msg[0] = 0xff;
+	msg[1] = 0xfe;
+	ireg->bstat = 0;
+	if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) {
+		printk(KERN_ERR"isar sendmsg start dsp failed\n");
+		ret = 1;goto reterror;
+	}
+	if (!waitrecmsg(cs, &len, tmp, 100000)) {
+		printk(KERN_ERR"isar waitrecmsg start dsp failed\n");
+		ret = 1;goto reterror;
+	}
+	if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) {
+		printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n",
+			ireg->iis, ireg->cmsb, len);
+		ret = 1;goto reterror;
+	} else
+		printk(KERN_DEBUG"isar start dsp success\n");
+	/* NORMAL mode entered */
+	/* Enable IRQs of ISAR */
+	cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA);
+	save_flags(flags);
+	sti();
+	cnt = 1000; /* max 1s */
+	while ((!ireg->bstat) && cnt) {
+		udelay(1000);
+		cnt--;
+	}
+	if (!cnt) {
+		printk(KERN_ERR"isar no general status event received\n");
+		ret = 1;goto reterrflg;
+	} else {
+		printk(KERN_DEBUG"isar general status event %x\n",
+			ireg->bstat);
+	}
+	ireg->iis = 0;
+	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) {
+		printk(KERN_ERR"isar sendmsg self tst failed\n");
+		ret = 1;goto reterrflg;
+	}
+	cnt = 1000; /* max 10 ms */
+	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
+		udelay(10);
+		cnt--;
+	}
+	if (!cnt) {
+		printk(KERN_ERR"isar no self tst response\n");
+		ret = 1;goto reterrflg;
+	} else if ((ireg->cmsb == ISAR_CTRL_STST) && (ireg->clsb == 1)
+		&& (ireg->par[0] == 0)) {
+		printk(KERN_DEBUG"isar selftest OK\n");
+	} else {
+		printk(KERN_DEBUG"isar selftest not OK %x/%x/%x\n",
+			ireg->cmsb, ireg->clsb, ireg->par[0]);
+		ret = 1;goto reterror;
+	}
+	ireg->iis = 0;
+	if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) {
+		printk(KERN_ERR"isar RQST SVN failed\n");
+		ret = 1;goto reterror;
+	}
+	cnt = 10000; /* max 100 ms */
+	while ((ireg->iis != ISAR_IIS_DIAG) && cnt) {
+		udelay(10);
+		cnt--;
+	}
+	if (!cnt) {
+		printk(KERN_ERR"isar no SVN response\n");
+		ret = 1;goto reterrflg;
+	} else {
+		if ((ireg->cmsb == ISAR_CTRL_SWVER) && (ireg->clsb == 1))
+			printk(KERN_DEBUG"isar software version %#x\n",
+				ireg->par[0]);
+		else {
+			printk(KERN_ERR"isar wrong swver response (%x,%x) cnt(%d)\n",
+				ireg->cmsb, ireg->clsb, cnt);
+			ret = 1;goto reterrflg;
+		}
+	}
+	cs->debug = debug;
+	isar_setup(cs);
+	ret = 0;
+reterrflg:
+	restore_flags(flags);
+reterror:
+	cs->debug = debug;
+	if (ret)
+		/* disable ISAR IRQ */
+		cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0);
+	kfree(msg);
+	kfree(tmpmsg);
+	return(ret);
+}
+
+void
+isar_sched_event(struct BCState *bcs, int event)
+{
+	bcs->event |= 1 << event;
+	queue_task(&bcs->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
+}
+
+static inline void
+isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	u_char *ptr;
+	struct sk_buff *skb;
+	struct isar_reg *ireg = bcs->hw.isar.reg;
+	
+	if (!ireg->clsb) {
+		debugl1(cs, "isar zero len frame");
+		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+		return;
+	}
+	switch (bcs->mode) {
+	case L1_MODE_NULL:
+		debugl1(cs, "isar mode 0 spurious IIS_RDATA %x/%x/%x",
+			ireg->iis, ireg->cmsb, ireg->clsb);
+		printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n",
+			ireg->iis, ireg->cmsb, ireg->clsb);
+		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+		break;
+	case L1_MODE_TRANS:
+		if ((skb = dev_alloc_skb(ireg->clsb))) {
+			SET_SKB_FREE(skb);
+			rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb));
+			skb_queue_tail(&bcs->rqueue, skb);
+			isar_sched_event(bcs, B_RCVBUFREADY);
+		} else {
+			printk(KERN_WARNING "HiSax: skb out of memory\n");
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+		}
+		break;
+	case L1_MODE_HDLC:
+		if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isar_rcv_frame: incoming packet too large");
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			bcs->hw.isar.rcvidx = 0;
+		} else if (ireg->cmsb & HDLC_ERROR) {
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "isar frame error %x len %d",
+					ireg->cmsb, ireg->clsb);
+			bcs->hw.isar.rcvidx = 0;
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+		} else {
+			if (ireg->cmsb & HDLC_FSD)
+				bcs->hw.isar.rcvidx = 0;
+			ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
+			bcs->hw.isar.rcvidx += ireg->clsb;
+			rcv_mbox(cs, ireg, ptr);
+			if (ireg->cmsb & HDLC_FED) {
+				if (bcs->hw.isar.rcvidx < 3) { /* last 2 bytes are the FCS */
+					printk(KERN_WARNING "ISAR: HDLC frame too short(%d)\n",
+						bcs->hw.isar.rcvidx);
+				} else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx-2)))
+					printk(KERN_WARNING "ISAR: receive out of memory\n");
+				else {
+					SET_SKB_FREE(skb);
+					memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2),
+						bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2);
+					skb_queue_tail(&bcs->rqueue, skb);
+					isar_sched_event(bcs, B_RCVBUFREADY);
+				}
+			}
+		}
+		break;
+	default:
+		printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode);
+		cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+		break;
+	}
+}
+
+void
+isar_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int count;
+	u_char msb;
+	u_char *ptr;
+	long flags;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "isar_fill_fifo");
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+	if (!(bcs->hw.isar.reg->bstat & 
+		(bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2)))
+		return;
+	if (bcs->tx_skb->len > bcs->hw.isar.mml) {
+		msb = 0;
+		count = bcs->hw.isar.mml;
+	} else {
+		count = bcs->tx_skb->len;
+		msb = HDLC_FED;
+	}
+	if (!bcs->hw.isar.txcnt)
+		msb |= HDLC_FST;
+	save_flags(flags);
+	cli();
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.isar.txcnt += count;
+	switch (bcs->mode) {
+	case L1_MODE_NULL:
+		printk(KERN_ERR"isar_fill_fifo wrong mode 0\n");
+		break;
+	case L1_MODE_TRANS:
+		if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+			0, count, ptr)) {
+			if (cs->debug)
+				debugl1(cs, "isar bin data send dp%d failed",
+					bcs->hw.isar.dpath);
+		}
+		break;
+	case L1_MODE_HDLC:
+		if (!sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA,
+			msb, count, ptr)) {
+			if (cs->debug)
+				debugl1(cs, "isar hdlc data send dp%d failed",
+					bcs->hw.isar.dpath);
+		}
+		break;
+	default:
+		printk(KERN_ERR"isar_fill_fifo mode (%x)error\n", bcs->mode);
+		break;
+	}
+	restore_flags(flags);
+}
+
+inline
+struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
+{
+	if ((!dpath) || (dpath == 3))
+		return(NULL);
+	if (cs->bcs[0].hw.isar.dpath == dpath)
+		return(&cs->bcs[0]);
+	if (cs->bcs[1].hw.isar.dpath == dpath)
+		return(&cs->bcs[1]);
+	return(NULL);
+}
+
+inline void
+send_frames(struct BCState *bcs)
+{
+	if (bcs->tx_skb) {
+		if (bcs->tx_skb->len) {
+			isar_fill_fifo(bcs);
+			return;
+		} else {
+			if (bcs->st->lli.l1writewakeup &&
+				(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.isar.txcnt);
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->hw.isar.txcnt = 0; 
+			bcs->tx_skb = NULL;
+		}
+	}
+	if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+		bcs->hw.isar.txcnt = 0;
+		test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+		isar_fill_fifo(bcs);
+	} else {
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+		isar_sched_event(bcs, B_XMTBUFREADY);
+	}
+}
+
+inline void
+check_send(struct IsdnCardState *cs, u_char rdm)
+{
+	struct BCState *bcs;
+	
+	if (rdm & BSTAT_RDM1) {
+		if ((bcs = sel_bcs_isar(cs, 1))) {
+			if (bcs->mode) {
+				send_frames(bcs);
+			}
+		}
+	}
+	if (rdm & BSTAT_RDM2) {
+		if ((bcs = sel_bcs_isar(cs, 2))) {
+			if (bcs->mode) {
+				send_frames(bcs);
+			}
+		}
+	}
+	
+}
+
+static char debbuf[64];
+
+void
+isar_int_main(struct IsdnCardState *cs)
+{
+	long flags;
+	struct isar_reg *ireg = cs->bcs[0].hw.isar.reg;
+	struct BCState *bcs;
+
+	save_flags(flags);
+	cli();
+	get_irq_infos(cs, ireg);
+	switch (ireg->iis & ISAR_IIS_MSCMSD) {
+		case ISAR_IIS_RDATA:
+			if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) {
+				isar_rcv_frame(cs, bcs);
+			} else {
+				debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+				printk(KERN_WARNING"isar spurious IIS_RDATA %x/%x/%x\n",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+				cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			}
+			break;
+		case ISAR_IIS_GSTEV:
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			ireg->bstat |= ireg->cmsb;
+			check_send(cs, ireg->cmsb);
+			break;
+		case ISAR_IIS_BSTEV:
+			cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "Buffer STEV dpath%d msb(%x)",
+					ireg->iis>>6, ireg->cmsb);
+			break;
+		case ISAR_IIS_DIAG:
+		case ISAR_IIS_PSTRSP:
+		case ISAR_IIS_PSTEV:
+		case ISAR_IIS_BSTRSP:
+		case ISAR_IIS_IOM2RSP:
+			rcv_mbox(cs, ireg, (u_char *)ireg->par);
+			if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO))
+				== L1_DEB_HSCX) {
+				u_char *tp=debbuf;
+
+				tp += sprintf(debbuf, "msg iis(%x) msb(%x)",
+					ireg->iis, ireg->cmsb);
+				QuickHex(tp, (u_char *)ireg->par, ireg->clsb);
+				debugl1(cs, debbuf);
+			}
+			break;
+		default:
+			rcv_mbox(cs, ireg, debbuf);
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "unhandled msg iis(%x) ctrl(%x/%x)",
+					ireg->iis, ireg->cmsb, ireg->clsb);
+			break;
+	}
+	restore_flags(flags);
+}
+
+void
+setup_pump(struct BCState *bcs) {
+	struct IsdnCardState *cs = bcs->cs;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	
+	switch (bcs->mode) {
+		case L1_MODE_NULL:
+		case L1_MODE_TRANS:
+		case L1_MODE_HDLC:
+			if (!sendmsg(cs, dps | ISAR_HIS_PUMPCFG, PMOD_BYPASS, 0, NULL)) {
+				if (cs->debug)
+					debugl1(cs, "isar pump bypass cfg dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
+	}
+	if (!sendmsg(cs, dps | ISAR_HIS_PSTREQ, 0, 0, NULL)) {
+		if (cs->debug)
+			debugl1(cs, "isar pump status req dp%d failed",
+				bcs->hw.isar.dpath);
+	}
+}
+
+void
+setup_sart(struct BCState *bcs) {
+	struct IsdnCardState *cs = bcs->cs;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	
+	switch (bcs->mode) {
+		case L1_MODE_NULL:
+			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_DISABLE, 0, NULL)) {
+				if (cs->debug)
+					debugl1(cs, "isar sart disable dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
+		case L1_MODE_TRANS:
+			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_BINARY, 2, "\0\0")) {
+				if (cs->debug)
+					debugl1(cs, "isar sart binary dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
+		case L1_MODE_HDLC:
+			if (!sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, "\0")) {
+				if (cs->debug)
+					debugl1(cs, "isar sart binary dp%d failed",
+						bcs->hw.isar.dpath);
+			}
+			break;
+	}
+	if (!sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL)) {
+		if (cs->debug)
+			debugl1(cs, "isar buf stat req dp%d failed",
+				bcs->hw.isar.dpath);
+	}
+}
+
+void
+setup_iom2(struct BCState *bcs) {
+	struct IsdnCardState *cs = bcs->cs;
+	u_char dps = SET_DPS(bcs->hw.isar.dpath);
+	u_char cmsb = 0, msg[5] = {0x10,0,0,0,0};
+	
+	switch (bcs->mode) {
+		case L1_MODE_NULL:
+			/* dummy slot */
+			msg[1] = msg[3] = bcs->hw.isar.dpath + 2;
+			break;
+		case L1_MODE_TRANS:
+		case L1_MODE_HDLC:
+			cmsb = 0x80;
+			if (bcs->channel)
+				msg[1] = msg[3] = 1;
+			break;
+	}
+	if (!sendmsg(cs, dps | ISAR_HIS_IOM2CFG, cmsb, 5, msg)) {
+		if (cs->debug)
+			debugl1(cs, "isar iom2 dp%d failed", bcs->hw.isar.dpath);
+	}
+	if (!sendmsg(cs, dps | ISAR_HIS_IOM2REQ, 0, 0, NULL)) {
+		if (cs->debug)
+			debugl1(cs, "isar IOM2 cfg req dp%d failed",
+				bcs->hw.isar.dpath);
+	}
+}
+
+int
+modeisar(struct BCState *bcs, int mode, int bc)
+{
+	struct IsdnCardState *cs = bcs->cs;
+
+	/* Here we are selecting the best datapath for requested mode */
+	if(bcs->mode == L1_MODE_NULL) { /* New Setup */
+		bcs->channel = bc;
+		switch (mode) {
+			case L1_MODE_NULL: /* init */
+				break;
+			case L1_MODE_TRANS:
+			case L1_MODE_HDLC:
+				/* best is datapath 2 */
+				if (!test_and_set_bit(ISAR_DP2_USE, 
+					&bcs->hw.isar.reg->Flags))
+					bcs->hw.isar.dpath = 2;
+				else if (!test_and_set_bit(ISAR_DP1_USE,
+					&bcs->hw.isar.reg->Flags))
+					bcs->hw.isar.dpath = 1;
+				else {
+					printk(KERN_ERR"isar modeisar both pathes in use\n");
+					return(1);
+				}
+				break;
+		}
+	}
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "isar dp%d mode %d->%d ichan %d",
+			bcs->hw.isar.dpath, bcs->mode, mode, bc);
+	bcs->mode = mode;
+	setup_pump(bcs);
+	setup_sart(bcs);
+	setup_iom2(bcs);
+	if (bcs->mode == L1_MODE_NULL) {
+		/* Clear resources */
+		if (bcs->hw.isar.dpath == 1)
+			test_and_clear_bit(ISAR_DP1_USE, &bcs->hw.isar.reg->Flags);
+		else if (bcs->hw.isar.dpath == 2)
+			test_and_clear_bit(ISAR_DP2_USE, &bcs->hw.isar.reg->Flags);
+		bcs->hw.isar.dpath = 0;
+	}
+	return(0);
+}
+
+void
+isar_setup(struct IsdnCardState *cs)
+{
+	u_char msg;
+	int i;
+	
+	/* Dpath 1, 2 */
+	msg = 61;
+	for (i=0; i<2; i++) {
+		/* Buffer Config */
+		if (!sendmsg(cs, (i ? ISAR_HIS_DPS2 : ISAR_HIS_DPS1) |
+			ISAR_HIS_P12CFG, 4, 1, &msg)) {
+			if (cs->debug)
+				debugl1(cs, "isar P%dCFG failed", i+1);
+		}
+		cs->bcs[i].hw.isar.mml = msg;
+		cs->bcs[i].mode = 0;
+		cs->bcs[i].hw.isar.dpath = i + 1;
+		modeisar(&cs->bcs[i], 0, 0);
+	}
+}
+
+void
+isar_l2l1(struct PStack *st, int pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	long flags;
+
+	switch (pr) {
+		case (PH_DATA | REQUEST):
+			save_flags(flags);
+			cli();
+			if (st->l1.bcs->tx_skb) {
+				skb_queue_tail(&st->l1.bcs->squeue, skb);
+				restore_flags(flags);
+			} else {
+				st->l1.bcs->tx_skb = skb;
+				test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+				if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+					debugl1(st->l1.bcs->cs, "DRQ set BC_FLG_BUSY");
+				st->l1.bcs->hw.isar.txcnt = 0;
+				restore_flags(flags);
+				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			}
+			break;
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
+				printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n");
+				break;
+			}
+			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+				debugl1(st->l1.bcs->cs, "PUI set BC_FLG_BUSY");
+			st->l1.bcs->tx_skb = skb;
+			st->l1.bcs->hw.isar.txcnt = 0;
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+			break;
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
+				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+			} else
+				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			modeisar(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+				debugl1(st->l1.bcs->cs, "PDAC clear BC_FLG_BUSY");
+			modeisar(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
+	}
+}
+
+void
+close_isarstate(struct BCState *bcs)
+{
+	modeisar(bcs, 0, bcs->channel);
+	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (bcs->hw.isar.rcvbuf) {
+			kfree(bcs->hw.isar.rcvbuf);
+			bcs->hw.isar.rcvbuf = NULL;
+		}
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			if (bcs->cs->debug & L1_DEB_HSCX)
+				debugl1(bcs->cs, "closeisar clear BC_FLG_BUSY");
+		}
+	}
+}
+
+int
+open_isarstate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.isar.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for isar.rcvbuf\n");
+			return (1);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "openisar clear BC_FLG_BUSY");
+	bcs->event = 0;
+	bcs->hw.isar.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+int
+setstack_isar(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_isarstate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = isar_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+HISAX_INITFUNC(void 
+initisar(struct IsdnCardState *cs))
+{
+	cs->bcs[0].BC_SetStack = setstack_isar;
+	cs->bcs[1].BC_SetStack = setstack_isar;
+	cs->bcs[0].BC_Close = close_isarstate;
+	cs->bcs[1].BC_Close = close_isarstate;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isar.h linux.pre11.3/drivers/isdn/hisax/isar.h
--- linux.vanilla/drivers/isdn/hisax/isar.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/isar.h	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,95 @@
+/* $Id: isar.h,v 1.3 1999/07/01 08:11:46 keil Exp $
+ * isar.h   ISAR (Siemens PSB 7110) specific defines
+ *
+ * Author Karsten Keil (keil@isdn4linux.de)
+ *
+ *
+ * $Log: isar.h,v $
+ * Revision 1.3  1999/07/01 08:11:46  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.2  1998/11/15 23:54:54  keil
+ * changes from 2.0
+ *
+ * Revision 1.1  1998/08/13 23:33:48  keil
+ * First version, only init
+ *
+ *
+ */
+ 
+#define ISAR_IRQMSK	0x04
+#define ISAR_IRQSTA	0x04
+#define ISAR_IRQBIT	0x75
+#define ISAR_CTRL_H	0x61
+#define ISAR_CTRL_L	0x60
+#define ISAR_IIS	0x58
+#define ISAR_IIA	0x58
+#define ISAR_HIS	0x50
+#define ISAR_HIA	0x50
+#define ISAR_MBOX	0x4c
+#define ISAR_WADR	0x4a
+#define ISAR_RADR	0x48 
+
+#define ISAR_HIS_VNR	0x14
+#define ISAR_HIS_DKEY	0x02
+#define ISAR_HIS_FIRM	0x1e
+#define ISAR_HIS_STDSP  0x08
+#define ISAR_HIS_DIAG	0x05
+#define ISAR_HIS_P0CFG	0x3c
+#define ISAR_HIS_P12CFG	0x24
+#define ISAR_HIS_SARTCFG	0x25	
+#define ISAR_HIS_PUMPCFG	0x26	
+#define ISAR_HIS_IOM2CFG	0x27
+#define ISAR_HIS_IOM2REQ	0x07
+#define ISAR_HIS_IOM2CTRL	0x2b
+#define ISAR_HIS_BSTREQ	0x0c
+#define ISAR_HIS_PSTREQ	0x0e
+#define ISAR_HIS_SDATA	0x20
+#define ISAR_HIS_DPS1	0x40
+#define ISAR_HIS_DPS2	0x80
+#define SET_DPS(x)	((x<<6) & 0xc0)
+
+#define ISAR_IIS_MSCMSD 0x3f
+#define ISAR_IIS_VNR	0x15
+#define ISAR_IIS_DKEY	0x03
+#define ISAR_IIS_FIRM	0x1f
+#define ISAR_IIS_STDSP  0x09
+#define ISAR_IIS_DIAG	0x25
+#define ISAR_IIS_GSTEV	0x0
+#define ISAR_IIS_BSTEV	0x28
+#define ISAR_IIS_BSTRSP	0x2c
+#define ISAR_IIS_PSTRSP	0x2e
+#define ISAR_IIS_PSTEV	0x2a
+#define ISAR_IIS_IOM2RSP	0x27
+
+#define ISAR_IIS_RDATA	0x20
+#define ISAR_CTRL_SWVER	0x10
+#define ISAR_CTRL_STST	0x40
+
+#define ISAR_MSG_HWVER	{0x20, 0, 1}
+
+#define ISAR_DP1_USE	1
+#define ISAR_DP2_USE	2
+
+#define PMOD_BYPASS	7
+
+#define SMODE_DISABLE	0
+#define SMODE_HDLC	3
+#define SMODE_BINARY	4
+
+#define HDLC_FED	0x40
+#define HDLC_FSD	0x20
+#define HDLC_FST	0x20
+#define HDLC_ERROR	0x1c
+
+#define BSTAT_RDM0	0x1
+#define BSTAT_RDM1	0x2
+#define BSTAT_RDM2	0x4
+#define BSTAT_RDM3	0x8
+
+
+extern int ISARVersion(struct IsdnCardState *cs, char *s);
+extern int isar_load_firmware(struct IsdnCardState *cs, u_char *buf);
+extern void isar_int_main(struct IsdnCardState *cs);
+extern void initisar(struct IsdnCardState *cs);
+extern void isar_fill_fifo(struct BCState *bcs);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl1.c linux.pre11.3/drivers/isdn/hisax/isdnl1.c
--- linux.vanilla/drivers/isdn/hisax/isdnl1.c	Wed Mar 24 10:55:17 1999
+++ linux.pre11.3/drivers/isdn/hisax/isdnl1.c	Mon Jul 19 23:59:34 1999
@@ -1,9 +1,13 @@
-/* $Id: isdnl1.c,v 2.18 1998/02/12 23:07:42 keil Exp $
+/* $Id: isdnl1.c,v 2.34 1999/07/09 13:50:15 keil Exp $
 
  * isdnl1.c     common low level stuff for Siemens Chipsetbased isdn cards
  *              based on the teles driver from Jan den Ouden
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
  *
  * Thanks to    Jan den Ouden
  *              Fritz Elfert
@@ -11,6 +15,52 @@
  *
  *
  * $Log: isdnl1.c,v $
+ * Revision 2.34  1999/07/09 13:50:15  keil
+ * remove unused variable
+ *
+ * Revision 2.33  1999/07/09 13:34:33  keil
+ * remove debug code
+ *
+ * Revision 2.32  1999/07/01 08:11:47  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.31  1998/11/15 23:54:56  keil
+ * changes from 2.0
+ *
+ * Revision 2.30  1998/09/30 22:27:00  keil
+ * Add init of l1.Flags
+ *
+ * Revision 2.29  1998/09/27 23:54:43  keil
+ * cosmetics
+ *
+ * Revision 2.28  1998/09/27 12:52:23  keil
+ * Fix against segfault, if the driver cannot allocate an IRQ channel
+ *
+ * Revision 2.27  1998/08/13 23:36:39  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.26  1998/07/15 15:01:31  calle
+ * Support for AVM passive PCMCIA cards:
+ *    A1 PCMCIA, FRITZ!Card PCMCIA and FRITZ!Card PCMCIA 2.0
+ *
+ * Revision 2.25  1998/05/25 14:10:09  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.24  1998/05/25 12:58:04  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.22  1998/04/15 16:40:13  keil
+ * Add S0Box and Teles PCI support
+ * Fix cardnr overwrite bug
+ *
+ * Revision 2.21  1998/04/10 10:35:28  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.20  1998/03/09 23:19:27  keil
+ * Changes for PCMCIA
+ *
  * Revision 2.18  1998/02/12 23:07:42  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -79,102 +129,21 @@
  *
  */
 
-const char *l1_revision = "$Revision: 2.18 $";
+const char *l1_revision = "$Revision: 2.34 $";
 
 #define __NO_VERSION__
 #include <linux/config.h>
 #include "hisax.h"
 #include "isdnl1.h"
-#include <linux/kernel_stat.h>
-#if (LINUX_VERSION_CODE < 0x020150) /* 2.1.80 */
-#define kstat_irqs( PAR ) kstat.interrupts( (PAR) )
-#endif
-
 
+#define TIMER3_VALUE 7000
 
-#if CARD_TELES0
-extern int setup_teles0(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3
-extern int setup_teles3(struct IsdnCard *card);
-#endif
-
-#if CARD_AVM_A1
-extern int setup_avm_a1(struct IsdnCard *card);
-#endif
-
-#if CARD_ELSA
-extern int setup_elsa(struct IsdnCard *card);
-#endif
-
-#if CARD_IX1MICROR2
-extern int setup_ix1micro(struct IsdnCard *card);
-#endif
-
-#if CARD_DIEHLDIVA
-extern	int  setup_diva(struct IsdnCard *card);
-#endif
-
-#if CARD_ASUSCOM
-extern int setup_asuscom(struct IsdnCard *card);
-#endif
-
-#if CARD_TELEINT
-extern int setup_TeleInt(struct IsdnCard *card);
-#endif
-
-#if CARD_SEDLBAUER
-extern int setup_sedlbauer(struct IsdnCard *card);
-#endif
-
-#if CARD_SPORTSTER
-extern int setup_sportster(struct IsdnCard *card);
-#endif
-
-#if CARD_MIC
-extern int setup_mic(struct IsdnCard *card);
-#endif
-
-#if CARD_NETJET
-extern int setup_netjet(struct IsdnCard *card);
-#endif
-
-#if CARD_TELES3C
-extern int setup_t163c(struct IsdnCard *card);
-#endif
-
-#if CARD_AMD7930 || CARD_DBRI
-extern int setup_foreign(struct IsdnCard *card);
-#endif
-
-#if CARD_NICCY
-extern int setup_niccy(struct IsdnCard *card);
-#endif
-
-#define HISAX_STATUS_BUFSIZE 4096
-#define ISDN_CTRL_DEBUG 1
-#define INCLUDE_INLINE_FUNCS
-#include <linux/tqueue.h>
-#include <linux/interrupt.h>
-const char *CardType[] =
-{"No Card", "Teles 16.0", "Teles 8.0", "Teles 16.3", "Creatix/Teles PnP",
- "AVM A1", "Elsa ML", "Elsa Quickstep", "Teles PCMCIA", "ITK ix1-micro Rev.2",
- "Elsa PCMCIA", "Eicon.Diehl Diva", "ISDNLink", "TeleInt", "Teles 16.3c", 
- "Sedlbauer Speed Card", "USR Sportster", "ith mic Linux", "Elsa PCI",
- "Compaq ISA", "NETjet", "Teles PCI", "Sedlbauer Speed Star (PCMCIA)",
- "AMD 7930", "NICCY", "DBRI"
-};
-
-extern struct IsdnCard cards[];
-extern int nrcards;
-extern char *HiSax_id;
-extern struct IsdnBuffers *tracebuf;
-
-#define TIMER3_VALUE 7
+static
+struct Fsm l1fsm_b =
+{NULL, 0, 0, NULL, NULL};
 
 static
-struct Fsm l1fsm =
+struct Fsm l1fsm_d =
 {NULL, 0, 0, NULL, NULL};
 
 enum {
@@ -187,9 +156,9 @@
 	ST_L1_F8,
 };
 
-#define L1_STATE_COUNT (ST_L1_F8+1)
+#define L1D_STATE_COUNT (ST_L1_F8+1)
 
-static char *strL1State[] =
+static char *strL1DState[] =
 {
 	"ST_L1_F2",
 	"ST_L1_F3",
@@ -201,7 +170,25 @@
 };
 
 enum {
+	ST_L1_NULL,
+	ST_L1_WAIT_ACT,
+	ST_L1_WAIT_DEACT,
+	ST_L1_ACTIV,
+};
+
+#define L1B_STATE_COUNT (ST_L1_ACTIV+1)
+
+static char *strL1BState[] =
+{
+	"ST_L1_NULL",
+	"ST_L1_WAIT_ACT",
+	"ST_L1_WAIT_DEACT",
+	"ST_L1_ACTIV",
+};
+
+enum {
 	EV_PH_ACTIVATE,
+	EV_PH_DEACTIVATE,
 	EV_RESET_IND,
 	EV_DEACT_CNF,
 	EV_DEACT_IND,
@@ -219,6 +206,7 @@
 static char *strL1Event[] =
 {
 	"EV_PH_ACTIVATE",
+	"EV_PH_DEACTIVATE",
 	"EV_RESET_IND",
 	"EV_DEACT_CNF",
 	"EV_DEACT_IND",
@@ -231,154 +219,30 @@
 	"EV_TIMER3",
 };
 
-/*
- * Find card with given driverId
- */
-static inline struct IsdnCardState
-*hisax_findcard(int driverid)
-{
-	int i;
-
-	for (i = 0; i < nrcards; i++)
-		if (cards[i].cs)
-			if (cards[i].cs->myid == driverid)
-				return (cards[i].cs);
-	return (NULL);
-}
-
-int
-HiSax_readstatus(u_char * buf, int len, int user, int id, int channel)
-{
-	int count;
-	u_char *p;
-	struct IsdnCardState *csta = hisax_findcard(id);
-
-	if (csta) {
-		for (p = buf, count = 0; count < len; p++, count++) {
-			if (user)
-				put_user(*csta->status_read++, p);
-			else
-				*p++ = *csta->status_read++;
-			if (csta->status_read > csta->status_end)
-				csta->status_read = csta->status_buf;
-		}
-		return count;
-	} else {
-		printk(KERN_ERR
-		 "HiSax: if_readstatus called with invalid driverId!\n");
-		return -ENODEV;
-	}
-}
-
-#if ISDN_CTRL_DEBUG
 void
-HiSax_putstatus(struct IsdnCardState *csta, char *buf)
+debugl1(struct IsdnCardState *cs, char *fmt, ...)
 {
-	long flags;
-	int len, count, i;
-	u_char *p;
-	isdn_ctrl ic;
-
-	save_flags(flags);
-	cli();
-	count = 0;
-	len = strlen(buf);
-
-	if (!csta) {
-		printk(KERN_WARNING "HiSax: No CardStatus for message %s", buf);
-		restore_flags(flags);
-		return;
-	}
-	for (p = buf, i = len; i > 0; i--, p++) {
-		*csta->status_write++ = *p;
-		if (csta->status_write > csta->status_end)
-			csta->status_write = csta->status_buf;
-		count++;
-	}
-	restore_flags(flags);
-	if (count) {
-		ic.command = ISDN_STAT_STAVAIL;
-		ic.driver = csta->myid;
-		ic.arg = count;
-		csta->iif.statcallb(&ic);
-	}
-}
-#else
-#define KDEBUG_DEF
-#include "../kdebug.h"
-
-static int DbgLineNr=0,DbgSequenzNr=1;
-
-void
-HiSax_putstatus(struct IsdnCardState *csta, char *buf)
-{
-	char tmp[512];
+	va_list args;
+	char tmp[8];
 	
-	if (DbgLineNr==23)
-		DbgLineNr=0;
-	sprintf(tmp, "%5d %s",DbgSequenzNr++,buf);
-	gput_str(tmp,0,DbgLineNr++);
-}	
-#endif
-
-int
-ll_run(struct IsdnCardState *csta)
-{
-	long flags;
-	isdn_ctrl ic;
-
-	save_flags(flags);
-	cli();
-	ic.driver = csta->myid;
-	ic.command = ISDN_STAT_RUN;
-	csta->iif.statcallb(&ic);
-	restore_flags(flags);
-	return 0;
-}
-
-void
-ll_stop(struct IsdnCardState *csta)
-{
-	isdn_ctrl ic;
-
-	ic.command = ISDN_STAT_STOP;
-	ic.driver = csta->myid;
-	csta->iif.statcallb(&ic);
-	CallcFreeChan(csta);
-}
-
-static void
-ll_unload(struct IsdnCardState *csta)
-{
-	isdn_ctrl ic;
-
-	ic.command = ISDN_STAT_UNLOAD;
-	ic.driver = csta->myid;
-	csta->iif.statcallb(&ic);
-	if (csta->status_buf)
-		kfree(csta->status_buf);
-	csta->status_read = NULL;
-	csta->status_write = NULL;
-	csta->status_end = NULL;
-	kfree(csta->dlogspace);
-}
-
-void
-debugl1(struct IsdnCardState *cs, char *msg)
-{
-	char tmp[1024], tm[32];
-
-	jiftime(tm, jiffies);
-	sprintf(tmp, "%s Card %d %s\n", tm, cs->cardnr + 1, msg);
-	HiSax_putstatus(cs, tmp);
+	va_start(args, fmt);
+	sprintf(tmp, "Card%d ", cs->cardnr + 1);
+	VHiSax_putstatus(cs, tmp, fmt, args);
+	va_end(args);
 }
 
 static void
-l1m_debug(struct FsmInst *fi, char *s)
+l1m_debug(struct FsmInst *fi, char *fmt, ...)
 {
+	va_list args;
 	struct PStack *st = fi->userdata;
+	struct IsdnCardState *cs = st->l1.hardware;
+	char tmp[8];
 	
-	debugl1(st->l1.hardware, s);
+	va_start(args, fmt);
+	sprintf(tmp, "Card%d ", cs->cardnr + 1);
+	VHiSax_putstatus(cs, tmp, fmt, args);
+	va_end(args);
 }
 
 void
@@ -389,9 +253,9 @@
 	st = cs->stlist;
 	while (st) {
 		if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
+			st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 		else
-			st->l1.l1man(st, PH_ACTIVATE_IND, NULL);
+			st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL);
 		st = st->next;
 	}
 }
@@ -404,8 +268,8 @@
 	st = cs->stlist;
 	while (st) {
 		if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags))
-			st->l1.l1l2(st, PH_PAUSE_CNF, NULL);
-		st->l1.l1man(st, PH_DEACTIVATE_IND, NULL);
+			st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
+		st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL);
 		st = st->next;
 	}
 	test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags);
@@ -422,7 +286,7 @@
 	stptr = cs->stlist;
 	while (stptr != NULL)
 		if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) {
-			stptr->l1.l1l2(stptr, PH_PULL_CNF, NULL);
+			stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL);
 			break;
 		} else
 			stptr = stptr->next;
@@ -434,7 +298,6 @@
 	struct sk_buff *skb, *nskb;
 	struct PStack *stptr = cs->stlist;
 	int found, tei, sapi;
-	char tmp[64];
 
 	if (stptr)
 		if (test_bit(FLG_L1_ACTTIMER, &stptr->l1.Flags))
@@ -445,19 +308,27 @@
 			Logl2Frame(cs, skb, "PH_DATA", 1);
 #endif
 		stptr = cs->stlist;
+		if (skb->len<3) {
+			debugl1(cs, "D-channel frame too short(%d)",skb->len);
+			idev_kfree_skb(skb, FREE_READ);
+			return;
+		}
+		if ((skb->data[0] & 1) || !(skb->data[1] &1)) {
+			debugl1(cs, "D-channel frame wrong EA0/EA1");
+			idev_kfree_skb(skb, FREE_READ);
+			return;
+		}
 		sapi = skb->data[0] >> 2;
 		tei = skb->data[1] >> 1;
-
+		if (cs->debug & DEB_DLOG_HEX)
+			LogFrame(cs, skb->data, skb->len);
+		if (cs->debug & DEB_DLOG_VERBOSE)
+			dlogframe(cs, skb, 1);
 		if (tei == GROUP_TEI) {
-			if (sapi == CTRL_SAPI) {	/* sapi 0 */
-				if (cs->dlogflag) {
-					LogFrame(cs, skb->data, skb->len);
-					dlogframe(cs, skb->data + 3, skb->len - 3,
-						  "Q.931 frame network->user broadcast");
-				}
+			if (sapi == CTRL_SAPI) { /* sapi 0 */
 				while (stptr != NULL) {
 					if ((nskb = skb_clone(skb, GFP_ATOMIC)))
-						stptr->l1.l1l2(stptr, PH_DATA_IND, nskb);
+						stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb);
 					else
 						printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n");
 					stptr = stptr->next;
@@ -465,37 +336,24 @@
 			} else if (sapi == TEI_SAPI) {
 				while (stptr != NULL) {
 					if ((nskb = skb_clone(skb, GFP_ATOMIC)))
-						stptr->l1.l1tei(stptr, PH_DATA_IND, nskb);
+						stptr->l1.l1tei(stptr, PH_DATA | INDICATION, nskb);
 					else
 						printk(KERN_WARNING "HiSax: tei broadcast buffer shortage\n");
 					stptr = stptr->next;
 				}
 			}
-			dev_kfree_skb(skb);
-		} else if (sapi == CTRL_SAPI) {
+			idev_kfree_skb(skb, FREE_READ);
+		} else if (sapi == CTRL_SAPI) { /* sapi 0 */
 			found = 0;
 			while (stptr != NULL)
 				if (tei == stptr->l2.tei) {
-					stptr->l1.l1l2(stptr, PH_DATA_IND, skb);
+					stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb);
 					found = !0;
 					break;
 				} else
 					stptr = stptr->next;
-			if (!found) {
-				/* BD 10.10.95
-				 * Print out D-Channel msg not processed
-				 * by isdn4linux
-				 */
-
-				if ((!(skb->data[0] >> 2)) && (!(skb->data[2] & 0x01))) {
-					sprintf(tmp,
-						"Q.931 frame network->user with tei %d (not for us)",
-						skb->data[1] >> 1);
-					LogFrame(cs, skb->data, skb->len);
-					dlogframe(cs, skb->data + 4, skb->len - 4, tmp);
-				}
-				dev_kfree_skb(skb);
-			}
+			if (!found)
+				idev_kfree_skb(skb, FREE_READ);
 		}
 	}
 }
@@ -505,14 +363,18 @@
 {
 	struct PStack *st = bcs->st;
 
-	if (test_bit(BC_FLG_BUSY, &bcs->Flag))
+	if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {
+		debugl1(bcs->cs, "BC_BUSY Error");
 		return;
+	}
 
 	if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags))
-		st->l1.l1l2(st, PH_PULL_CNF, NULL);
-	if (!test_bit(BC_FLG_ACTIV, &bcs->Flag))
-		if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue)))
-			st->ma.manl1(st, PH_DEACTIVATE_CNF, 0);
+		st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+	if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) {
+		if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) {
+			st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
+		}
+	}
 }
 
 static void
@@ -520,8 +382,12 @@
 {
 	struct sk_buff *skb;
 
+	if (bcs->st->l1.l1m.state == ST_L1_WAIT_ACT) {
+		FsmDelTimer(&bcs->st->l1.timer, 4);
+		FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL);
+	}
 	while ((skb = skb_dequeue(&bcs->rqueue))) {
-		bcs->st->l1.l1l2(bcs->st, PH_DATA_IND, skb);
+		bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb);
 	}
 }
 
@@ -581,443 +447,6 @@
 	bcs->Flag = 0;
 }
 
-static void
-closecard(int cardnr)
-{
-	struct IsdnCardState *csta = cards[cardnr].cs;
-	struct sk_buff *skb;
-	
-	if (csta->bcs->BC_Close != NULL) { 
-		csta->bcs->BC_Close(csta->bcs + 1);
-		csta->bcs->BC_Close(csta->bcs);
-	}
-
-	if (csta->rcvbuf) {
-		kfree(csta->rcvbuf);
-		csta->rcvbuf = NULL;
-	}
-	while ((skb = skb_dequeue(&csta->rq))) {
-		dev_kfree_skb(skb);
-	}
-	while ((skb = skb_dequeue(&csta->sq))) {
-		dev_kfree_skb(skb);
-	}
-	if (csta->tx_skb) {
-		dev_kfree_skb(csta->tx_skb);
-		csta->tx_skb = NULL;
-	}
-	if (csta->mon_rx) {
-		kfree(csta->mon_rx);
-		csta->mon_rx = NULL;
-	}
-	if (csta->mon_tx) {
-		kfree(csta->mon_tx);
-		csta->mon_tx = NULL;
-	}
-	csta->cardmsg(csta, CARD_RELEASE, NULL);
-	del_timer(&csta->dbusytimer);
-	ll_unload(csta);
-}
-
-HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs))
-{
-	int irq_cnt, cnt = 3;
-	long flags;
-
-	save_flags(flags);
-	cli();
-	irq_cnt = kstat_irqs(cs->irq);
-	printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq,
-		irq_cnt);
-	if (cs->cardmsg(cs, CARD_SETIRQ, NULL)) {
-		printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n",
-			cs->irq);
-		return(1);
-	}
-	while (cnt) {
-		cs->cardmsg(cs, CARD_INIT, NULL);
-		sti();
-		current->state = TASK_INTERRUPTIBLE;
-		/* Timeout 10ms */
-		schedule_timeout((10 * HZ) / 1000);
-		restore_flags(flags);
-		printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ],
-			cs->irq, kstat_irqs(cs->irq));
-		if (kstat_irqs(cs->irq) == irq_cnt) {
-			printk(KERN_WARNING
-			       "%s: IRQ(%d) getting no interrupts during init %d\n",
-			       CardType[cs->typ], cs->irq, 4 - cnt);
-			if (cnt == 1) {
-				free_irq(cs->irq, cs);
-				return (2);
-			} else {
-				cs->cardmsg(cs, CARD_RESET, NULL);
-				cnt--;
-			}
-		} else {
-			cs->cardmsg(cs, CARD_TEST, NULL);
-			return(0);
-		}
-	}
-	restore_flags(flags);
-	return(3);
-}
-
-HISAX_INITFUNC(static int
-checkcard(int cardnr, char *id, int *busy_flag))
-{
-	long flags;
-	int ret = 0;
-	struct IsdnCard *card = cards + cardnr;
-	struct IsdnCardState *cs;
-
-	save_flags(flags);
-	cli();
-	if (!(cs = (struct IsdnCardState *)
-	      kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for IsdnCardState(card %d)\n",
-		       cardnr + 1);
-		restore_flags(flags);
-		return (0);
-	}
-	card->cs = cs;
-	cs->cardnr = cardnr;
-	cs->debug = L1_DEB_WARN;
-	cs->HW_Flags = 0;
-	cs->busy_flag = busy_flag;
-#if TEI_PER_CARD
-#else
-	test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
-	cs->protocol = card->protocol;
-
-	if ((card->typ > 0) && (card->typ < 31)) {
-		if (!((1 << card->typ) & SUPORTED_CARDS)) {
-			printk(KERN_WARNING
-			     "HiSax: Support for %s Card not selected\n",
-			       CardType[card->typ]);
-			restore_flags(flags);
-			return (0);
-		}
-	} else {
-		printk(KERN_WARNING
-		       "HiSax: Card Type %d out of range\n",
-		       card->typ);
-		restore_flags(flags);
-		return (0);
-	}
-	if (!(cs->dlogspace = kmalloc(4096, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for dlogspace(card %d)\n",
-		       cardnr + 1);
-		restore_flags(flags);
-		return (0);
-	}
-	if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for status_buf(card %d)\n",
-		       cardnr + 1);
-		kfree(cs->dlogspace);
-		restore_flags(flags);
-		return (0);
-	}
-	cs->stlist = NULL;
-	cs->dlogflag = 0;
-	cs->mon_tx = NULL;
-	cs->mon_rx = NULL;
-	cs->status_read = cs->status_buf;
-	cs->status_write = cs->status_buf;
-	cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1;
-	cs->typ = card->typ;
-	strcpy(cs->iif.id, id);
-	cs->iif.channels = 2;
-	cs->iif.maxbufsize = MAX_DATA_SIZE;
-	cs->iif.hl_hdrlen = MAX_HEADER_LEN;
-	cs->iif.features =
-	    ISDN_FEATURE_L2_X75I |
-	    ISDN_FEATURE_L2_HDLC |
-	    ISDN_FEATURE_L2_TRANS |
-	    ISDN_FEATURE_L3_TRANS |
-#ifdef	CONFIG_HISAX_1TR6
-	    ISDN_FEATURE_P_1TR6 |
-#endif
-#ifdef	CONFIG_HISAX_EURO
-	    ISDN_FEATURE_P_EURO |
-#endif
-#ifdef        CONFIG_HISAX_NI1
-	    ISDN_FEATURE_P_NI1 |
-#endif
-	    0;
-
-	cs->iif.command = HiSax_command;
-	cs->iif.writecmd = NULL;
-	cs->iif.writebuf_skb = HiSax_writebuf_skb;
-	cs->iif.readstat = HiSax_readstatus;
-	register_isdn(&cs->iif);
-	cs->myid = cs->iif.channels;
-	printk(KERN_INFO
-	       "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1,
-	       (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" :
-	       (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" :
-	       (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" :
-	       (card->protocol == ISDN_PTYPE_NI1) ? "NI1" :
-	       "NONE", cs->iif.id, cs->myid);
-	switch (card->typ) {
-#if CARD_TELES0
-		case ISDN_CTYPE_16_0:
-		case ISDN_CTYPE_8_0:
-			ret = setup_teles0(card);
-			break;
-#endif
-#if CARD_TELES3
-		case ISDN_CTYPE_16_3:
-		case ISDN_CTYPE_PNP:
-		case ISDN_CTYPE_TELESPCMCIA:
-		case ISDN_CTYPE_COMPAQ_ISA:
-			ret = setup_teles3(card);
-			break;
-#endif
-#if CARD_AVM_A1
-		case ISDN_CTYPE_A1:
-			ret = setup_avm_a1(card);
-			break;
-#endif
-#if CARD_ELSA
-		case ISDN_CTYPE_ELSA:
-		case ISDN_CTYPE_ELSA_PNP:
-		case ISDN_CTYPE_ELSA_PCMCIA:
-		case ISDN_CTYPE_ELSA_PCI:
-			ret = setup_elsa(card);
-			break;
-#endif
-#if CARD_IX1MICROR2
-		case ISDN_CTYPE_IX1MICROR2:
-			ret = setup_ix1micro(card);
-			break;
-#endif
-#if CARD_DIEHLDIVA
-		case ISDN_CTYPE_DIEHLDIVA:
-			ret = setup_diva(card);
-			break;
-#endif
-#if CARD_ASUSCOM
-		case ISDN_CTYPE_ASUSCOM:
-			ret = setup_asuscom(card);
-			break;
-#endif
-#if CARD_TELEINT
-		case ISDN_CTYPE_TELEINT:
-			ret = setup_TeleInt(card);
-			break;
-#endif
-#if CARD_SEDLBAUER
-		case ISDN_CTYPE_SEDLBAUER:
-		case ISDN_CTYPE_SEDLBAUER_PCMCIA:
-			ret = setup_sedlbauer(card);
-			break;
-#endif
-#if CARD_SPORTSTER
-		case ISDN_CTYPE_SPORTSTER:
-			ret = setup_sportster(card);
-			break;
-#endif
-#if CARD_MIC
-		case ISDN_CTYPE_MIC:
-			ret = setup_mic(card);
-			break;
-#endif
-#if CARD_NETJET
-		case ISDN_CTYPE_NETJET:
-			ret = setup_netjet(card);
-			break;
-#endif
-#if CARD_TELES3C
-		case ISDN_CTYPE_TELES3C:
-			ret = setup_t163c(card);
-			break;
-#endif
-#if CARD_NICCY
-		case ISDN_CTYPE_NICCY:
-			ret = setup_niccy(card);
-			break;
-#endif
-#if CARD_AMD7930 || CARD_DBRI
-		case ISDN_CTYPE_AMD7930:
-		case ISDN_CTYPE_DBRI:
-			ret = setup_foreign(card);
-			break;
-#endif
-		default:
-			printk(KERN_WARNING "HiSax: Unknown Card Typ %d\n",
-			       card->typ);
-			ll_unload(cs);
-			restore_flags(flags);
-			return (0);
-	}
-	if (!ret) {
-		ll_unload(cs);
-		restore_flags(flags);
-		return (0);
-	}
-	if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN, GFP_ATOMIC))) {
-		printk(KERN_WARNING
-		       "HiSax: No memory for isac rcvbuf\n");
-		return (1);
-	}
-	cs->rcvidx = 0;
-	cs->tx_skb = NULL;
-	cs->tx_cnt = 0;
-	cs->event = 0;
-	cs->tqueue.next = 0;
-	cs->tqueue.sync = 0;
-	cs->tqueue.data = cs;
-
-	skb_queue_head_init(&cs->rq);
-	skb_queue_head_init(&cs->sq);
-
-	init_bcstate(cs, 0);
-	init_bcstate(cs, 1);
-	ret = init_card(cs);
-	if (ret) {
-		closecard(cardnr);
-		restore_flags(flags);
-		return (0);
-	}
-	init_tei(cs, cs->protocol);
-	CallcNewChan(cs);
-	ll_run(cs);
-	cs->l1cmd(cs, PH_RESET_REQ, NULL);
-	restore_flags(flags);
-	return (1);
-}
-
-HISAX_INITFUNC(void
-HiSax_shiftcards(int idx))
-{
-	int i;
-
-	for (i = idx; i < 15; i++)
-		memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
-}
-
-HISAX_INITFUNC(int
-HiSax_inithardware(int *busy_flag))
-{
-	int foundcards = 0;
-	int i = 0;
-	int t = ',';
-	int flg = 0;
-	char *id;
-	char *next_id = HiSax_id;
-	char ids[20];
-
-	if (strchr(HiSax_id, ','))
-		t = ',';
-	else if (strchr(HiSax_id, '%'))
-		t = '%';
-
-	while (i < nrcards) {
-		if (cards[i].typ < 1)
-			break;
-		id = next_id;
-		if ((next_id = strchr(id, t))) {
-			*next_id++ = 0;
-			strcpy(ids, id);
-			flg = i + 1;
-		} else {
-			next_id = id;
-			if (flg >= i)
-				strcpy(ids, id);
-			else
-				sprintf(ids, "%s%d", id, i);
-		}
-		if (checkcard(i, ids, busy_flag)) {
-			foundcards++;
-			i++;
-		} else {
-			printk(KERN_WARNING "HiSax: Card %s not installed !\n",
-			       CardType[cards[i].typ]);
-			if (cards[i].cs)
-				kfree((void *) cards[i].cs);
-			cards[i].cs = NULL;
-			HiSax_shiftcards(i);
-		}
-	}
-	return foundcards;
-}
-
-void
-HiSax_closehardware(void)
-{
-	int i;
-	long flags;
-
-	save_flags(flags);
-	cli();
-	for (i = 0; i < nrcards; i++)
-		if (cards[i].cs) {
-			ll_stop(cards[i].cs);
-			release_tei(cards[i].cs);
-			closecard(i);
-			free_irq(cards[i].cs->irq, cards[i].cs);
-			kfree((void *) cards[i].cs);
-			cards[i].cs = NULL;
-		}
-	Isdnl1Free();
-	TeiFree();
-	Isdnl2Free();
-	CallcFree();
-	restore_flags(flags);
-}
-
-void
-HiSax_reportcard(int cardnr)
-{
-	struct IsdnCardState *cs = cards[cardnr].cs;
-	struct PStack *stptr;
-	struct l3_process *pc;
-	int j, i = 1;
-
-	printk(KERN_DEBUG "HiSax: reportcard No %d\n", cardnr + 1);
-	printk(KERN_DEBUG "HiSax: Type %s\n", CardType[cs->typ]);
-	printk(KERN_DEBUG "HiSax: debuglevel %x\n", cs->debug);
-	printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n",
-	       (ulong) & HiSax_reportcard);
-	printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs);
-	printk(KERN_DEBUG "HiSax: cs stl 0x%lX\n", (ulong) & (cs->stlist));
-	stptr = cs->stlist;
-	while (stptr != NULL) {
-		printk(KERN_DEBUG "HiSax: dst%d 0x%lX\n", i, (ulong) stptr);
-		printk(KERN_DEBUG "HiSax: dst%d stp 0x%lX\n", i, (ulong) stptr->l1.stlistp);
-		printk(KERN_DEBUG "HiSax:   tei %d sapi %d\n",
-		       stptr->l2.tei, stptr->l2.sap);
-		printk(KERN_DEBUG "HiSax:      man 0x%lX\n", (ulong) stptr->ma.layer);
-		pc = stptr->l3.proc;
-		while (pc) {
-			printk(KERN_DEBUG "HiSax: l3proc %x 0x%lX\n", pc->callref,
-			       (ulong) pc);
-			printk(KERN_DEBUG "HiSax:    state %d  st 0x%lX chan 0x%lX\n",
-			    pc->state, (ulong) pc->st, (ulong) pc->chan);
-			pc = pc->next;
-		}
-		stptr = stptr->next;
-		i++;
-	}
-	for (j = 0; j < 2; j++) {
-		printk(KERN_DEBUG "HiSax: ch%d 0x%lX\n", j,
-		       (ulong) & cs->channel[j]);
-		stptr = cs->channel[j].b_st;
-		i = 1;
-		while (stptr != NULL) {
-			printk(KERN_DEBUG "HiSax:  b_st%d 0x%lX\n", i, (ulong) stptr);
-			printk(KERN_DEBUG "HiSax:    man 0x%lX\n", (ulong) stptr->ma.layer);
-			stptr = stptr->next;
-			i++;
-		}
-	}
-}
-
 #ifdef L2FRAME_DEBUG		/* psa */
 
 char *
@@ -1052,7 +481,7 @@
 	}
 }
 
-static char tmp[20];
+static char tmpdeb[32];
 
 char *
 l2frames(u_char * ptr)
@@ -1061,7 +490,7 @@
 		case 1:
 		case 5:
 		case 9:
-			sprintf(tmp, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);
+			sprintf(tmpdeb, "%s[%d](nr %d)", l2cmd(ptr[2]), ptr[3] & 1, ptr[3] >> 1);
 			break;
 		case 0x6f:
 		case 0x0f:
@@ -1070,36 +499,33 @@
 		case 0x63:
 		case 0x87:
 		case 0xaf:
-			sprintf(tmp, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);
+			sprintf(tmpdeb, "%s[%d]", l2cmd(ptr[2]), (ptr[2] & 0x10) >> 4);
 			break;
 		default:
 			if (!(ptr[2] & 1)) {
-				sprintf(tmp, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);
+				sprintf(tmpdeb, "I[%d](ns %d, nr %d)", ptr[3] & 1, ptr[2] >> 1, ptr[3] >> 1);
 				break;
 			} else
 				return "invalid command";
 	}
 
 
-	return tmp;
+	return tmpdeb;
 }
 
 void
 Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir)
 {
-	char tmp[132];
 	u_char *ptr;
 
 	ptr = skb->data;
 
 	if (ptr[0] & 1 || !(ptr[1] & 1))
-		debugl1(cs, "Addres not LAPD");
-	else {
-		sprintf(tmp, "%s %s: %s%c (sapi %d, tei %d)",
+		debugl1(cs, "Address not LAPD");
+	else
+		debugl1(cs, "%s %s: %s%c (sapi %d, tei %d)",
 			(dir ? "<-" : "->"), buf, l2frames(ptr),
 			((ptr[0] & 2) >> 1) == dir ? 'C' : 'R', ptr[0] >> 2, ptr[1] >> 1);
-		debugl1(cs, tmp);
-	}
 }
 #endif
 
@@ -1113,11 +539,10 @@
 l1_deact_cnf(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
 
 	FsmChangeState(fi, ST_L1_F3);
 	if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
-		cs->l1cmd(cs, PH_ENABLE_REQ, NULL);
+		st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
 }
 
 static void
@@ -1126,24 +551,23 @@
 	struct PStack *st = fi->userdata;
 
 	FsmChangeState(fi, ST_L1_F3);
-	if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) {
+//	if (!test_bit(FLG_L1_T3RUN, &st->l1.Flags)) {
 		FsmDelTimer(&st->l1.timer, 1);
 		FsmAddTimer(&st->l1.timer, 550, EV_TIMER_DEACT, NULL, 2);
 		test_and_set_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
-	}
+//	}
 }
 
 static void
 l1_power_up(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
 
 	if (test_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) {
 		FsmChangeState(fi, ST_L1_F4);
-		cs->l1cmd(cs, PH_INFO3_REQ, NULL);
+		st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
 		FsmDelTimer(&st->l1.timer, 1);
-		FsmAddTimer(&st->l1.timer, TIMER3_VALUE * HZ, EV_TIMER3, NULL, 2);
+		FsmAddTimer(&st->l1.timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
 		test_and_set_bit(FLG_L1_T3RUN, &st->l1.Flags);
 	} else
 		FsmChangeState(fi, ST_L1_F3);
@@ -1165,20 +589,18 @@
 l1_info2_ind(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
 
 	FsmChangeState(fi, ST_L1_F6);
-	cs->l1cmd(cs, PH_INFO3_REQ, NULL);
+	st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
 }
 
 static void
 l1_info4_ind(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
 
 	FsmChangeState(fi, ST_L1_F7);
-	cs->l1cmd(cs, PH_INFO3_REQ, NULL);
+	st->l1.l1hw(st, HW_INFO3 | REQUEST, NULL);
 	if (test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags))
 		FsmDelTimer(&st->l1.timer, 4);
 	if (!test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) {
@@ -1193,50 +615,61 @@
 l1_timer3(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
-	
+
 	test_and_clear_bit(FLG_L1_T3RUN, &st->l1.Flags);	
-        if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
-        	L1deactivated(cs);
-        if (st->l1.l1m.state != ST_L1_F6)
-        	FsmChangeState(fi, ST_L1_F3);
+	if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags))
+		L1deactivated(st->l1.hardware);
+	if (st->l1.l1m.state != ST_L1_F6) {
+		FsmChangeState(fi, ST_L1_F3);
+		st->l1.l1hw(st, HW_ENABLE | REQUEST, NULL);
+	}
 }
 
 static void
 l1_timer_act(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
 	
 	test_and_clear_bit(FLG_L1_ACTTIMER, &st->l1.Flags);
 	test_and_set_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
-	L1activated(cs);
+	L1activated(st->l1.hardware);
 }
 
 static void
 l1_timer_deact(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
 	
 	test_and_clear_bit(FLG_L1_DEACTTIMER, &st->l1.Flags);
 	test_and_clear_bit(FLG_L1_ACTIVATED, &st->l1.Flags);
-	L1deactivated(cs);
-	cs->l1cmd(cs, PH_DEACT_ACK, NULL);
+	L1deactivated(st->l1.hardware);
+	st->l1.l1hw(st, HW_DEACTIVATE | RESPONSE, NULL);
 }
 
 static void
 l1_activate(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	struct IsdnCardState *cs = st->l1.hardware;
                 
-	cs->l1cmd(cs, PH_RESET_REQ, NULL);
+	st->l1.l1hw(st, HW_RESET | REQUEST, NULL);
 }
 
-static struct FsmNode L1FnList[] HISAX_INITDATA =
+static void
+l1_activate_no(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if ((!test_bit(FLG_L1_DEACTTIMER, &st->l1.Flags)) && (!test_bit(FLG_L1_T3RUN, &st->l1.Flags))) {
+		test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
+		L1deactivated(st->l1.hardware);
+	}
+}
+
+static struct FsmNode L1DFnList[] HISAX_INITDATA =
 {
 	{ST_L1_F3, EV_PH_ACTIVATE, l1_activate},
+	{ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no},
+	{ST_L1_F8, EV_PH_ACTIVATE, l1_activate_no},
 	{ST_L1_F3, EV_RESET_IND, l1_reset},
 	{ST_L1_F4, EV_RESET_IND, l1_reset},
 	{ST_L1_F5, EV_RESET_IND, l1_reset},
@@ -1280,86 +713,159 @@
 	{ST_L1_F8, EV_TIMER_DEACT, l1_timer_deact},
 };
 
-#define L1_FN_COUNT (sizeof(L1FnList)/sizeof(struct FsmNode))
+#define L1D_FN_COUNT (sizeof(L1DFnList)/sizeof(struct FsmNode))
+
+static void
+l1b_activate(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_WAIT_ACT);
+	FsmAddTimer(&st->l1.timer, st->l1.delay, EV_TIMER_ACT, NULL, 2);
+}
+
+static void
+l1b_deactivate(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_WAIT_DEACT);
+	FsmAddTimer(&st->l1.timer, 10, EV_TIMER_DEACT, NULL, 2);
+}
+
+static void
+l1b_timer_act(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_ACTIV);
+	st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
+}
+
+static void
+l1b_timer_deact(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_NULL);
+	st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL);
+}
+
+static struct FsmNode L1BFnList[] HISAX_INITDATA =
+{
+	{ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate},
+	{ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act},
+	{ST_L1_ACTIV, EV_PH_DEACTIVATE, l1b_deactivate},
+	{ST_L1_WAIT_DEACT, EV_TIMER_DEACT, l1b_timer_deact},
+};
+
+#define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode))
 
 HISAX_INITFUNC(void Isdnl1New(void))
 {
-	l1fsm.state_count = L1_STATE_COUNT;
-	l1fsm.event_count = L1_EVENT_COUNT;
-	l1fsm.strEvent = strL1Event;
-	l1fsm.strState = strL1State;
-	FsmNew(&l1fsm, L1FnList, L1_FN_COUNT);
+	l1fsm_d.state_count = L1D_STATE_COUNT;
+	l1fsm_d.event_count = L1_EVENT_COUNT;
+	l1fsm_d.strEvent = strL1Event;
+	l1fsm_d.strState = strL1DState;
+	FsmNew(&l1fsm_d, L1DFnList, L1D_FN_COUNT);
+	l1fsm_b.state_count = L1B_STATE_COUNT;
+	l1fsm_b.event_count = L1_EVENT_COUNT;
+	l1fsm_b.strEvent = strL1Event;
+	l1fsm_b.strState = strL1BState;
+	FsmNew(&l1fsm_b, L1BFnList, L1B_FN_COUNT);
 }
 
 void Isdnl1Free(void)
 {
-	FsmFree(&l1fsm);
+	FsmFree(&l1fsm_d);
+	FsmFree(&l1fsm_b);
 }
 
 static void
-dch_manl1(struct PStack *st, int pr,
-	   void *arg)
+dch_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
-	char tmp[32];
 
 	switch (pr) {
-		case PH_ACTIVATE_REQ:
-			if (cs->debug) {
-				sprintf(tmp, "PH_ACTIVATE_REQ %s",
-					strL1State[st->l1.l1m.state]);
-				debugl1(cs, tmp);
-			}
+		case (PH_DATA | REQUEST):
+		case (PH_PULL | REQUEST):
+		case (PH_PULL |INDICATION):
+			st->l1.l1hw(st, pr, arg);
+			break;
+		case (PH_ACTIVATE | REQUEST):
+			if (cs->debug)
+				debugl1(cs, "PH_ACTIVATE_REQ %s",
+					strL1DState[st->l1.l1m.state]);
 			if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags))
-				st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
+				st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
 			else {
 				test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags);
 				FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg);
 			}
 			break;
-		case PH_DEACTIVATE_REQ:
-			if (cs->debug) {
-				sprintf(tmp, "PH_DEACTIVATE_REQ %s",
-					strL1State[st->l1.l1m.state]);
-				debugl1(cs, tmp);
-			}
-			break;
-		case PH_TESTLOOP_REQ:
-			if (1 & (int) arg)
+		case (PH_TESTLOOP | REQUEST):
+			if (1 & (long) arg)
 				debugl1(cs, "PH_TEST_LOOP B1");
-			if (2 & (int) arg)
+			if (2 & (long) arg)
 				debugl1(cs, "PH_TEST_LOOP B2");
-			if (!(3 & (int) arg))
+			if (!(3 & (long) arg))
 				debugl1(cs, "PH_TEST_LOOP DISABLED");
-			cs->l1cmd(cs, PH_TESTLOOP_REQ, arg);
-			break;
-		case PH_RESET_IND:
-			FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
-			break;
-		case PH_DEACT_CNF:
-			FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
-			break;
-		case PH_DEACT_IND:
-			FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
-			break;
-		case PH_POWERUP_CNF:
-			FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
-			break;
-		case PH_RSYNC_IND:
-			FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
+			st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
 			break;
-		case PH_INFO2_IND:
-			FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
+		default:
+			if (cs->debug)
+				debugl1(cs, "dch_l2l1 msg %04X unhandled", pr);
 			break;
-		case PH_I4_P8_IND:
-		case PH_I4_P10_IND:
-			FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+	}
+}
+
+void
+l1_msg(struct IsdnCardState *cs, int pr, void *arg) {
+	struct PStack *st;
+
+	st = cs->stlist;
+	
+	while (st) {
+		switch(pr) {
+			case (HW_RESET | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_RESET_IND, arg);
+				break;
+			case (HW_DEACTIVATE | CONFIRM):
+				FsmEvent(&st->l1.l1m, EV_DEACT_CNF, arg);
+				break;
+			case (HW_DEACTIVATE | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_DEACT_IND, arg);
+				break;
+			case (HW_POWERUP | CONFIRM):
+				FsmEvent(&st->l1.l1m, EV_POWER_UP, arg);
+				break;
+			case (HW_RSYNC | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_RSYNC_IND, arg);
+				break;
+			case (HW_INFO2 | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_INFO2_IND, arg);
+				break;
+			case (HW_INFO4_P8 | INDICATION):
+			case (HW_INFO4_P10 | INDICATION):
+				FsmEvent(&st->l1.l1m, EV_INFO4_IND, arg);
+				break;
+			default:
+				if (cs->debug)
+					debugl1(cs, "l1msg %04X unhandled", pr);
+				break;
+		}
+		st = st->next;
+	}
+}
+
+void
+l1_msg_b(struct PStack *st, int pr, void *arg) {
+	switch(pr) {
+		case (PH_ACTIVATE | REQUEST):
+			FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, NULL);
 			break;
-		default:
-			if (cs->debug) {
-				sprintf(tmp, "dch_manl1 msg %04X unhandled", pr);
-				debugl1(cs, tmp);
-			}
+		case (PH_DEACTIVATE | REQUEST):
+			FsmEvent(&st->l1.l1m, EV_PH_DEACTIVATE, NULL);
 			break;
 	}
 }
@@ -1369,7 +875,7 @@
 {
 	st->l1.hardware = cs;
 	st->protocol = cs->protocol;
-	st->l1.l1m.fsm = &l1fsm;
+	st->l1.l1m.fsm = &l1fsm_d;
 	st->l1.l1m.state = ST_L1_F3;
 	st->l1.l1m.debug = cs->debug;
 	st->l1.l1m.userdata = st;
@@ -1379,7 +885,22 @@
 	setstack_tei(st);
 	setstack_manager(st);
 	st->l1.stlistp = &(cs->stlist);
-	st->ma.manl1 = dch_manl1;
+	st->l2.l2l1  = dch_l2l1;
 	st->l1.Flags = 0;
 	cs->setstack_d(st, cs);
+}
+
+void
+setstack_l1_B(struct PStack *st)
+{
+	struct IsdnCardState *cs = st->l1.hardware;
+
+	st->l1.l1m.fsm = &l1fsm_b;
+	st->l1.l1m.state = ST_L1_NULL;
+	st->l1.l1m.debug = cs->debug;
+	st->l1.l1m.userdata = st;
+	st->l1.l1m.userint = 0;
+	st->l1.l1m.printdebug = l1m_debug;
+	st->l1.Flags = 0;
+	FsmInitTimer(&st->l1.l1m, &st->l1.timer);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl1.h linux.pre11.3/drivers/isdn/hisax/isdnl1.h
--- linux.vanilla/drivers/isdn/hisax/isdnl1.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/isdnl1.h	Mon Jul 19 23:59:34 1999
@@ -1,6 +1,16 @@
-/* $Id: isdnl1.h,v 2.5 1998/02/02 13:36:58 keil Exp $
+/* $Id: isdnl1.h,v 2.8 1998/11/15 23:54:59 keil Exp $
 
  * $Log: isdnl1.h,v $
+ * Revision 2.8  1998/11/15 23:54:59  keil
+ * changes from 2.0
+ *
+ * Revision 2.7  1998/09/30 22:21:55  keil
+ * cosmetics
+ *
+ * Revision 2.6  1998/05/25 12:58:06  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 2.5  1998/02/02 13:36:58  keil
  * more debug
  *
@@ -22,21 +32,6 @@
  *
  */
 
-
-#define L2FRAME_DEBUG
-
-/* DEBUG Level */
-
-#define	L1_DEB_WARN		0x01
-#define	L1_DEB_INTSTAT		0x02
-#define	L1_DEB_ISAC		0x04
-#define	L1_DEB_ISAC_FIFO	0x08
-#define	L1_DEB_HSCX		0x10
-#define	L1_DEB_HSCX_FIFO	0x20
-#define	L1_DEB_LAPD	        0x40
-#define	L1_DEB_IPAC	        0x80
-#define	L1_DEB_RECEIVE_FRAME    0x100
-
 #define D_RCVBUFREADY	0
 #define D_XMTBUFREADY	1
 #define D_L1STATECHANGE	2
@@ -49,11 +44,12 @@
 #define B_RCVBUFREADY 0
 #define B_XMTBUFREADY 1
 
-extern void debugl1(struct IsdnCardState *sp, char *msg);
+extern void debugl1(struct IsdnCardState *cs, char *fmt, ...);
 extern void DChannel_proc_xmt(struct IsdnCardState *cs);
 extern void DChannel_proc_rcv(struct IsdnCardState *cs);
-
+extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg);
+extern void l1_msg_b(struct PStack *st, int pr, void *arg);
 
 #ifdef L2FRAME_DEBUG
-extern void Logl2Frame(struct IsdnCardState *sp, struct sk_buff *skb, char *buf, int dir);
+extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir);
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl2.c linux.pre11.3/drivers/isdn/hisax/isdnl2.c
--- linux.vanilla/drivers/isdn/hisax/isdnl2.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/isdnl2.c	Mon Jul 19 23:59:34 1999
@@ -1,12 +1,45 @@
-/* $Id: isdnl2.c,v 2.7 1998/02/12 23:07:47 keil Exp $
+/* $Id: isdnl2.c,v 2.17 1999/07/01 08:11:50 keil Exp $
 
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
  * Thanks to    Jan den Ouden
  *              Fritz Elfert
  *
  * $Log: isdnl2.c,v $
+ * Revision 2.17  1999/07/01 08:11:50  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.16  1998/11/15 23:55:01  keil
+ * changes from 2.0
+ *
+ * Revision 2.15  1998/08/13 23:36:42  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.14  1998/06/19 15:19:18  keil
+ * fix LAPB tx_cnt for none I-frames
+ *
+ * Revision 2.13  1998/06/18 23:17:20  keil
+ * LAPB bugfix
+ *
+ * Revision 2.12  1998/05/25 14:10:12  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.11  1998/05/25 12:58:08  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.9  1998/04/10 10:35:30  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
+ * Revision 2.8  1998/03/07 22:57:04  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 2.7  1998/02/12 23:07:47  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -25,7 +58,7 @@
  * Old stuff is still in the separate branch.
  *
  * Revision 2.2  1997/07/31 11:49:05  keil
- * Eroor handling for no TEI assign
+ * Error handling for no TEI assign
  *
  * Revision 2.1  1997/07/27 21:34:38  keil
  * cosmetics
@@ -41,9 +74,9 @@
 #include "hisax.h"
 #include "isdnl2.h"
 
-const char *l2_revision = "$Revision: 2.7 $";
+const char *l2_revision = "$Revision: 2.17 $";
 
-static void l2m_debug(struct FsmInst *fi, char *s);
+static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
 
 static
 struct Fsm l2fsm =
@@ -76,7 +109,7 @@
 
 enum {
 	EV_L2_UI,
-	EV_L2_SABMX,
+	EV_L2_SABME,
 	EV_L2_DISC,
 	EV_L2_DM,
 	EV_L2_UA,
@@ -86,23 +119,25 @@
 	EV_L2_DL_DATA,
 	EV_L2_ACK_PULL,
 	EV_L2_DL_UNIT_DATA,
-	EV_L2_DL_ESTABLISH,
-	EV_L2_DL_RELEASE,
+	EV_L2_DL_ESTABLISH_REQ,
+	EV_L2_DL_RELEASE_REQ,
 	EV_L2_MDL_ASSIGN,
 	EV_L2_MDL_REMOVE,
 	EV_L2_MDL_ERROR,
-	EV_L2_MDL_NOTEIPROC,
 	EV_L1_DEACTIVATE,
 	EV_L2_T200,
 	EV_L2_T203,
+	EV_L2_SET_OWN_BUSY,
+	EV_L2_CLEAR_OWN_BUSY,
+	EV_L2_FRAME_ERROR,
 };
 
-#define L2_EVENT_COUNT (EV_L2_T203+1)
+#define L2_EVENT_COUNT (EV_L2_FRAME_ERROR+1)
 
 static char *strL2Event[] =
 {
 	"EV_L2_UI",
-	"EV_L2_SABMX",
+	"EV_L2_SABME",
 	"EV_L2_DISC",
 	"EV_L2_DM",
 	"EV_L2_UA",
@@ -112,15 +147,17 @@
 	"EV_L2_DL_DATA",
 	"EV_L2_ACK_PULL",
 	"EV_L2_DL_UNIT_DATA",
-	"EV_L2_DL_ESTABLISH",
-	"EV_L2_DL_RELEASE",
+	"EV_L2_DL_ESTABLISH_REQ",
+	"EV_L2_DL_RELEASE_REQ",
 	"EV_L2_MDL_ASSIGN",
 	"EV_L2_MDL_REMOVE",
 	"EV_L2_MDL_ERROR",
-	"EV_L2_MDL_NOTEIPROC",
 	"EV_L1_DEACTIVATE",
 	"EV_L2_T200",
 	"EV_L2_T203",
+	"EV_L2_SET_OWN_BUSY",
+	"EV_L2_CLEAR_OWN_BUSY",
+	"EV_L2_FRAME_ERROR",
 };
 
 static int l2addrsize(struct Layer2 *l2);
@@ -134,51 +171,46 @@
 		l2->windowar[i] = NULL;
 }
 
-static void
-ReleaseWin(struct Layer2 *l2)
+static int
+freewin1(struct Layer2 *l2)
 {
 	int i, cnt = 0;
 
 	for (i = 0; i < MAX_WINDOW; i++) {
 		if (l2->windowar[i]) {
 			cnt++;
-			dev_kfree_skb(l2->windowar[i]);
+			idev_kfree_skb(l2->windowar[i], FREE_WRITE);
 			l2->windowar[i] = NULL;
 		}
 	}
-	if (cnt)
-		printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
+	return cnt;
 }
 
-inline int
-cansend(struct PStack *st)
+inline void
+freewin(struct PStack *st)
 {
-	int p1;
-
-	p1 = st->l2.vs - st->l2.va;
-	if (p1 < 0)
-		p1 += (test_bit(FLG_MOD128, &st->l2.flag) ? 128 : 8);
-	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
+	freewin1(&st->l2);
 }
 
 static void
-discard_i_queue(struct PStack *st)
+ReleaseWin(struct Layer2 *l2)
 {
-	struct sk_buff *skb;
+	int cnt;
 
-	while ((skb = skb_dequeue(&st->l2.i_queue))) {
-		dev_kfree_skb(skb);
-	}
+	if((cnt = freewin1(l2)))
+		printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
 }
 
-static void
-discard_ui_queue(struct PStack *st)
+inline unsigned int
+cansend(struct PStack *st)
 {
-	struct sk_buff *skb;
+	unsigned int p1;
 
-	while ((skb = skb_dequeue(&st->l2.ui_queue))) {
-		dev_kfree_skb(skb);
-	}
+	if(test_bit(FLG_MOD128, &st->l2.flag))
+		p1 = (st->l2.vs - st->l2.va) % 128;
+	else
+		p1 = (st->l2.vs - st->l2.va) % 8;
+	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
 }
 
 inline void
@@ -224,103 +256,209 @@
 	}
 }
 
-static void
-enqueue_ui(struct PStack *st,
-	   struct sk_buff *skb)
-{
-	st->l2.l2l1(st, PH_DATA_REQ, skb);
-}
-
-static void
+inline static void
 enqueue_super(struct PStack *st,
 	      struct sk_buff *skb)
 {
-	st->l2.l2l1(st, PH_DATA_REQ, skb);
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l1.bcs->tx_cnt += skb->len;
+	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
 }
 
+#define enqueue_ui(a, b) enqueue_super(a, b)
+
 inline int
-IsUI(u_char * data, int ext)
+IsUI(u_char * data)
 {
 	return ((data[0] & 0xef) == UI);
 }
 
 inline int
-IsUA(u_char * data, int ext)
+IsUA(u_char * data)
 {
 	return ((data[0] & 0xef) == UA);
 }
 
 inline int
-IsDM(u_char * data, int ext)
+IsDM(u_char * data)
 {
 	return ((data[0] & 0xef) == DM);
 }
 
 inline int
-IsDISC(u_char * data, int ext)
+IsDISC(u_char * data)
 {
 	return ((data[0] & 0xef) == DISC);
 }
 
 inline int
-IsRR(u_char * data, int ext)
+IsRR(u_char * data, struct PStack *st)
 {
-	if (ext)
+	if (test_bit(FLG_MOD128, &st->l2.flag))
 		return (data[0] == RR);
 	else
 		return ((data[0] & 0xf) == 1);
 }
 
 inline int
-IsSABMX(u_char * data, int ext)
+IsSFrame(u_char * data, struct PStack *st)
+{
+	register u_char d = *data;
+	
+	if (!test_bit(FLG_MOD128, &st->l2.flag))
+		d &= 0xf;
+	return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
+}
+
+inline int
+IsSABME(u_char * data, struct PStack *st)
 {
 	u_char d = data[0] & ~0x10;
 
-	return (ext ? d == SABME : d == SABM);
+	return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
 }
 
 inline int
-IsREJ(u_char * data, int ext)
+IsREJ(u_char * data, struct PStack *st)
 {
-	return (ext ? data[0] == REJ : (data[0] & 0xf) == REJ);
+	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
 }
 
 inline int
-IsFRMR(u_char * data, int ext)
+IsFRMR(u_char * data)
 {
 	return ((data[0] & 0xef) == FRMR);
 }
 
 inline int
-IsRNR(u_char * data, int ext)
+IsRNR(u_char * data, struct PStack *st)
 {
-	return (ext ? data[0] == RNR : (data[0] & 0xf) == RNR);
+	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
 }
 
-static int
-legalnr(struct PStack *st, int nr)
+int
+iframe_error(struct PStack *st, struct sk_buff *skb)
 {
-	struct Layer2 *l2 = &st->l2;
-	int lnr, lvs;
+	int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 1 : 0);
+	int rsp = *skb->data & 0x2;
+
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (rsp)
+		return 'L';
+
+
+	if (skb->len <= i)
+		return 'N';
+
+	if ((skb->len - i) > st->l2.maxlen)
+		return 'O';
+
+
+	return 0;
+}
+
+int
+super_error(struct PStack *st, struct sk_buff *skb)
+{
+	if (skb->len != l2addrsize(&st->l2) +
+	    (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1))
+		return 'N';
+
+	return 0;
+}
+
+int
+unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
+{
+	int rsp = (*skb->data & 0x2) >> 1;
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (rsp != wantrsp)
+		return 'L';
+
+	if (skb->len != l2addrsize(&st->l2) + 1)
+		return 'N';
+
+	return 0;
+}
+
+int
+UI_error(struct PStack *st, struct sk_buff *skb)
+{
+	int rsp = *skb->data & 0x2;
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (rsp)
+		return 'L';
+
+	if (skb->len > st->l2.maxlen + l2addrsize(&st->l2) + 1)
+		return 'O';
 
-	lvs = (l2->vs >= l2->va) ? l2->vs :
-	    (l2->vs + (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8));
-	lnr = (nr >= l2->va) ? nr : (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
-	return (lnr <= lvs);
+	return 0;
+}
+
+int
+FRMR_error(struct PStack *st, struct sk_buff *skb)
+{
+	int headers = l2addrsize(&st->l2) + 1;
+	u_char *datap = skb->data + headers;
+	int rsp = *skb->data & 0x2;
+
+	if (test_bit(FLG_ORIG, &st->l2.flag))
+		rsp = !rsp;
+
+	if (!rsp)
+		return 'L';
+
+	if (test_bit(FLG_MOD128, &st->l2.flag)) {
+		if (skb->len < headers + 5)
+			return 'N';
+		else
+			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x %2x %2x",
+				datap[0], datap[1], datap[2],
+				datap[3], datap[4]);
+	} else {
+		if (skb->len < headers + 3)
+			return 'N';
+		else
+			l2m_debug(&st->l2.l2m, "FRMR information %2x %2x %2x",
+				datap[0], datap[1], datap[2]);
+	}
+
+	return 0;
+}
+
+static unsigned int
+legalnr(struct PStack *st, unsigned int nr)
+{
+        struct Layer2 *l2 = &st->l2;
+
+	if(test_bit(FLG_MOD128, &l2->flag))
+		return ((nr - l2->va) % 128) <= ((l2->vs - l2->va) % 128);
+	else
+		return ((nr - l2->va) % 8) <= ((l2->vs - l2->va) % 8);
 }
 
 static void
-setva(struct PStack *st, int nr)
+setva(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
 	int len;
 
 	while (l2->va != nr) {
-		l2->va = (l2->va + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
+		(l2->va)++;
+		if(test_bit(FLG_MOD128, &l2->flag))
+			l2->va %= 128;
+		else
+			l2->va %= 8;
 		len = l2->windowar[l2->sow]->len;
 		if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type)
 			len = -1;
-		dev_kfree_skb(l2->windowar[l2->sow]);
+		idev_kfree_skb(l2->windowar[l2->sow], FREE_WRITE);
 		l2->windowar[l2->sow] = NULL;
 		l2->sow = (l2->sow + 1) % l2->window;
 		if (st->lli.l2writewakeup && (len >=0))
@@ -341,6 +479,7 @@
 		printk(KERN_WARNING "isdl2 can't alloc sbbuff for send_uframe\n");
 		return;
 	}
+	SET_SKB_FREE(skb);
 	memcpy(skb_put(skb, i), tmp, i);
 	enqueue_super(st, skb);
 }
@@ -354,7 +493,7 @@
 inline void
 FreeSkb(struct sk_buff *skb)
 {
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 }
 
 
@@ -368,6 +507,48 @@
 	return (PF);
 }
 
+inline void
+start_t200(struct PStack *st, int i)
+{
+	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
+	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+}
+
+inline void
+restart_t200(struct PStack *st, int i)
+{
+	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
+	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+}
+
+inline void
+stop_t200(struct PStack *st, int i)
+{
+	if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
+		FsmDelTimer(&st->l2.t200, i);
+}
+
+inline void
+st5_dl_release_l2l3(struct PStack *st)
+{
+		int pr;
+
+		if(test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
+			pr = DL_RELEASE | CONFIRM;
+		else
+			pr = DL_RELEASE | INDICATION;
+
+		st->l2.l2l3(st, pr, NULL);
+}
+
+inline void
+lapb_dl_release_l2l3(struct PStack *st, int f)
+{
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st->l2.l2l3(st, DL_RELEASE | f, NULL);
+}
+
 static void
 establishlink(struct FsmInst *fi)
 {
@@ -379,49 +560,91 @@
 	cmd = (test_bit(FLG_MOD128, &st->l2.flag) ? SABME : SABM) | 0x10;
 	send_uframe(st, cmd, CMD);
 	FsmDelTimer(&st->l2.t203, 1);
-	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 1);
-	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+	restart_t200(st, 1);
+	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
+	freewin(st);
 	FsmChangeState(fi, ST_L2_5);
 }
 
 static void
-l2_mdl_error(struct FsmInst *fi, int event, void *arg)
+l2_mdl_error_ua(struct FsmInst *fi, int event, void *arg)
 {
 	struct sk_buff *skb = arg;
 	struct PStack *st = fi->userdata;
 
-	switch (event) {
-		case EV_L2_UA:
-			if (get_PollFlagFree(st, skb))
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'C');
-			else
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'D');
-			break;
-		case EV_L2_DM:
-			if (get_PollFlagFree(st, skb))
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'B');
-			else {
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'E');
-				establishlink(fi);
-				test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
-			}
-			break;
+	if (get_PollFlagFree(st, skb))
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'C');
+	else
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'D');
+}
+
+static void
+l2_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
+{
+	struct sk_buff *skb = arg;
+	struct PStack *st = fi->userdata;
+
+	if (get_PollFlagFree(st, skb))
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
+	else {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
+		establishlink(fi);
+		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 	}
 }
 
 static void
-l2_dl_establish(struct FsmInst *fi, int event, void *arg)
+l2_st8_mdl_error_dm(struct FsmInst *fi, int event, void *arg)
 {
+	struct sk_buff *skb = arg;
 	struct PStack *st = fi->userdata;
-	int state = fi->state;
 
+	if (get_PollFlagFree(st, skb))
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'B');
+	else {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'E');
+	}
+	establishlink(fi);
+	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+}
+
+static void
+l2_go_st3(struct FsmInst *fi, int event, void *arg)
+{
 	FsmChangeState(fi, ST_L2_3); 
-	if (state == ST_L2_1)
-		st->l2.l2tei(st, MDL_ASSIGN_IND, NULL);
 }
 
 static void
-l2_send_ui(struct PStack *st)
+l2_mdl_assign(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L2_3); 
+	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+}
+
+static void
+l2_queue_ui_assign(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	skb_queue_tail(&st->l2.ui_queue, skb);
+	FsmChangeState(fi, ST_L2_2);
+	st->l2.l2tei(st, MDL_ASSIGN | INDICATION, NULL);
+}
+
+static void
+l2_queue_ui(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	skb_queue_tail(&st->l2.ui_queue, skb);
+}
+
+static void
+tx_ui(struct PStack *st)
 {
 	struct sk_buff *skb;
 	u_char header[MAX_HEADER_LEN];
@@ -436,18 +659,13 @@
 }
 
 static void
-l2_put_ui(struct FsmInst *fi, int event, void *arg)
+l2_send_ui(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
 
 	skb_queue_tail(&st->l2.ui_queue, skb);
-	if (fi->state == ST_L2_1) {
-		FsmChangeState(fi, ST_L2_2);
-		st->l2.l2tei(st, MDL_ASSIGN_IND, NULL);
-	}
-	if (fi->state > ST_L2_3)
-		l2_send_ui(st);
+	tx_ui(st);
 }
 
 static void
@@ -457,11 +675,12 @@
 	struct sk_buff *skb = arg;
 
 	skb_pull(skb, l2headersize(&st->l2, 1));
-	if (skb->len > st->l2.maxlen) { 
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
-		FreeSkb(skb);
-	} else
-		st->l2.l2l3(st, DL_UNIT_DATA, skb);
+	st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb);
+/*	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *		in states 1-3 for broadcast
+ */
+
+
 }
 
 static void
@@ -469,245 +688,243 @@
 {
 	struct PStack *st = fi->userdata;
 
-	if (fi->state != ST_L2_4)
-		discard_i_queue(st);
-	if (fi->state != ST_L2_5)
-		establishlink(fi);
+	establishlink(fi);
 	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
 }
 
 static void
-l2_dl_release(struct FsmInst *fi, int event, void *arg)
+l2_discard_i_setl3(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
-	if (fi->state == ST_L2_4) {
-		st->l2.l2man(st, DL_RELEASE, NULL);
-		return;
-	} else if (fi->state == ST_L2_5) {
-		test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
-		return;
-	}
-	discard_i_queue(st);
+	discard_queue(&st->l2.i_queue);
+	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
+	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
+}
+
+static void
+l2_l3_reestablish(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	establishlink(fi);
+	test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
+}
+
+static void
+l2_release(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+}
+
+static void
+l2_pend_rel(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	test_and_set_bit(FLG_PEND_REL, &st->l2.flag);
+}
+
+static void
+l2_disconnect(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	freewin(st);
 	FsmChangeState(fi, ST_L2_6);
 	st->l2.rc = 0;
 	send_uframe(st, DISC | 0x10, CMD);
 	FsmDelTimer(&st->l2.t203, 1);
-	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 2);
-	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+	restart_t200(st, 2);
 }
 
 static void
-l2_got_SABMX(struct FsmInst *fi, int event, void *arg)
+l2_start_multi(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int est = 1, state, rsp;
-	u_char PollFlag;
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+
+	clear_exception(&st->l2);
+	st->l2.vs = 0;
+	st->l2.va = 0;
+	st->l2.vr = 0;
+	st->l2.sow = 0;
+	FsmChangeState(fi, ST_L2_7);
+	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
+
+	st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
+}
+
+static void
+l2_send_UA(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+}
+
+static void
+l2_send_DM(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	send_uframe(st, DM | get_PollFlagFree(st, skb), RSP);
+}
+
+static void
+l2_restart_multi(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+	int est = 0, state;
 
 	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
-	if (rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlagFree(st, skb);
-	if (ST_L2_6 == state) {
-		send_uframe(st, DM | PollFlag, RSP);
-		return;
-	} else
-		send_uframe(st, UA | PollFlag, RSP);
-	if (ST_L2_5 == state)
-		return;
-	if (ST_L2_4 != state) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'F');
-		if (st->l2.vs != st->l2.va) {
-			discard_i_queue(st);
-			est = 1;
-		} else
-			est = 0;
+
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+
+	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'F');
+
+	if (st->l2.vs != st->l2.va) {
+		discard_queue(&st->l2.i_queue);
+		est = 1;
 	}
+
 	clear_exception(&st->l2);
 	st->l2.vs = 0;
 	st->l2.va = 0;
 	st->l2.vr = 0;
 	st->l2.sow = 0;
 	FsmChangeState(fi, ST_L2_7);
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 2);
-	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
+	stop_t200(st, 3);
+	FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3);
 
 	if (est)
-		st->l2.l2man(st, DL_ESTABLISH, NULL);
+		st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL);
 
-	if (ST_L2_8 == state)
+	if ((ST_L2_7==state) || (ST_L2_8 == state))
 		if (skb_queue_len(&st->l2.i_queue) && cansend(st))
-			st->l2.l2l1(st, PH_PULL_REQ, NULL);
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
-l2_got_disconn(struct FsmInst *fi, int event, void *arg)
+l2_stop_multi(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	u_char PollFlag, cmd = UA;
-	int state, rel = 1, cst = 1, rsp;
 
-	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
+	FsmChangeState(fi, ST_L2_4);
+	FsmDelTimer(&st->l2.t203, 3);
+	stop_t200(st, 4);
 
-	if (rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
+	send_uframe(st, UA | get_PollFlagFree(st, skb), RSP);
+
+	discard_queue(&st->l2.i_queue);
+	freewin(st);
+	lapb_dl_release_l2l3(st, INDICATION);
+}
+
+static void
+l2_connected(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+	int pr=-1;
+
+	if (!get_PollFlag(st, skb)) {
+		l2_mdl_error_ua(fi, event, arg);
 		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
+	}
+	FreeSkb(skb);
+
+	if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
+		l2_disconnect(fi, event, arg);
+
+	if (test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
+		pr = DL_ESTABLISH | CONFIRM;
+	} else if (st->l2.vs != st->l2.va) {
+		discard_queue(&st->l2.i_queue);
+		pr = DL_ESTABLISH | INDICATION;
+	}
+
+	stop_t200(st, 5);
+
+	st->l2.vr = 0;
+	st->l2.vs = 0;
+	st->l2.va = 0;
+	st->l2.sow = 0;
+	FsmChangeState(fi, ST_L2_7);
+	FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
+
+	if (pr != -1)
+		st->l2.l2l3(st, pr, NULL);
+
+	if (skb_queue_len(&st->l2.i_queue) && cansend(st))
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+}
+
+static void
+l2_released(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (!get_PollFlag(st, skb)) {
+		l2_mdl_error_ua(fi, event, arg);
 		return;
 	}
-	PollFlag = get_PollFlagFree(st, skb);
-	if ((state == ST_L2_4) || (state == ST_L2_5)) {
-		rel = 0;
-		cst = 0;
-		cmd = DM;
-	} else if (state == ST_L2_6) {
-		rel = 0;
-		cst = 0;
-	}
-	if (cst) {
-		FsmChangeState(fi, ST_L2_4);
-		FsmDelTimer(&st->l2.t203, 3);
-		if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag)) 
-			FsmDelTimer(&st->l2.t200, 2);
-	}
-	send_uframe(st, cmd | PollFlag, RSP);
-	if (rel)
-		st->l2.l2man(st, DL_RELEASE, NULL);
-}
+	FreeSkb(skb);
 
+	stop_t200(st, 6);
+	lapb_dl_release_l2l3(st, CONFIRM);
+	FsmChangeState(fi, ST_L2_4);
+}
 
 static void
-l2_got_ua(struct FsmInst *fi, int event, void *arg)
+l2_reestablish(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	u_char PollFlag, est = 1;
-	int state,rsp;
 
-	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
-
-	if (!rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		FreeSkb(skb);
-		if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlag(st, skb);
-	if (!PollFlag) {
-		l2_mdl_error(fi, event, arg);
-		return;
+	if (!get_PollFlagFree(st, skb)) {
+		establishlink(fi);
+		test_and_set_bit(FLG_L3_INIT, &st->l2.flag);
 	}
-	FreeSkb(skb);
+}
 
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 2);
-	if (fi->state == ST_L2_5) {
-		if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag)) {
-			discard_i_queue(st);
-			st->l2.rc = 0;
-			send_uframe(st, DISC | 0x10, CMD);
-			FsmChangeState(fi, ST_L2_6);
-			FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 4);
-			test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
-		} else {
-			if (!test_and_clear_bit(FLG_L3_INIT, &st->l2.flag)) {
-				if (st->l2.vs != st->l2.va)
-					discard_i_queue(st);
-				else
-					est = 0;
-			}
-			st->l2.vs = 0;
-			st->l2.va = 0;
-			st->l2.vr = 0;
-			st->l2.sow = 0;
-			FsmChangeState(fi, ST_L2_7);
-			FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4);
-			if (est)
-				st->l2.l2man(st, DL_ESTABLISH, NULL);
-		}
-	} else {		/* ST_L2_6 */
-		st->l2.l2man(st, DL_RELEASE, NULL);
+static void
+l2_st5_dm_release(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (get_PollFlagFree(st, skb)) {
+		stop_t200(st, 7);
+	 	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
+			discard_queue(&st->l2.i_queue);
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st5_dl_release_l2l3(st);
 		FsmChangeState(fi, ST_L2_4);
 	}
 }
 
 static void
-l2_got_dm(struct FsmInst *fi, int event, void *arg)
+l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	u_char PollFlag;
-	int state,rsp;
 
-	state = fi->state;
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &st->l2.flag))
-		rsp = !rsp;
-
-	if (!rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
-		FreeSkb(skb);
-		if ((state == ST_L2_7) || (state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}	
-	if (skb->len != (l2addrsize(&st->l2) + 1)) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		FreeSkb(skb);
-		if ((fi->state == ST_L2_7) || (fi->state == ST_L2_8))
-			establishlink(fi);
-		return;
-	}
-	PollFlag = get_PollFlagFree(st, skb);
-	if (!PollFlag) {
-		establishlink(fi);
-		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
-	} else {
-		if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-			FsmDelTimer(&st->l2.t200, 2);
-	 	if (fi->state == ST_L2_5 && !test_bit(FLG_L3_INIT, &st->l2.flag))
-			discard_i_queue(st);
-		st->l2.l2man(st, DL_RELEASE, NULL);
+	if (get_PollFlagFree(st, skb)) {
+		stop_t200(st, 8);
+		lapb_dl_release_l2l3(st, CONFIRM);
 		FsmChangeState(fi, ST_L2_4);
 	}
 }
@@ -731,6 +948,7 @@
 		printk(KERN_WARNING "isdl2 can't alloc sbbuff for enquiry_cr\n");
 		return;
 	}
+	SET_SKB_FREE(skb);
 	memcpy(skb_put(skb, i), tmp, i);
 	enqueue_super(st, skb);
 }
@@ -753,8 +971,7 @@
 	else
 		enquiry_cr(st, RR, CMD, 1);
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
-	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 12);
-	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+	start_t200(st, 9);
 }
 
 
@@ -763,42 +980,44 @@
 {
 	struct PStack *st = fi->userdata;
 
-	st->ma.layer(st, MDL_ERROR_IND, (void *) 'J');
+	st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'J');
 	establishlink(fi);
+	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 }
 
 static void
-invoke_retransmission(struct PStack *st, int nr)
+invoke_retransmission(struct PStack *st, unsigned int nr)
 {
 	struct Layer2 *l2 = &st->l2;
-	int p1;
-	long flags;
+	unsigned int p1;
 
 	if (l2->vs != nr) {
-		save_flags(flags);
-		cli();
 		while (l2->vs != nr) {
-			l2->vs = l2->vs - 1;
-			if (l2->vs < 0)
-				l2->vs += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
-			p1 = l2->vs - l2->va;
-			if (p1 < 0)
-				p1 += (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
+			(l2->vs)--;
+			if(test_bit(FLG_MOD128, &l2->flag)) {
+				l2->vs %= 128;
+				p1 = (l2->vs - l2->va) % 128;
+			} else {
+				l2->vs %= 8;
+				p1 = (l2->vs - l2->va) % 8;
+			}
 			p1 = (p1 + l2->sow) % l2->window;
+			if (test_bit(FLG_LAPB, &l2->flag))
+				st->l1.bcs->tx_cnt += l2->windowar[p1]->len + l2headersize(l2, 0);
 			skb_queue_head(&l2->i_queue, l2->windowar[p1]);
 			l2->windowar[p1] = NULL;
 		}
-		restore_flags(flags);
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	}
 }
 
 static void
-l2_got_st7_super(struct FsmInst *fi, int event, void *arg)
+l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int PollFlag, nr, rsp, typ = RR;
+	int PollFlag, rsp, typ = RR;
+	unsigned int nr;
 	struct Layer2 *l2 = &st->l2;
 
 	rsp = *skb->data & 0x2;
@@ -806,70 +1025,77 @@
 		rsp = !rsp;
 
 	skb_pull(skb, l2addrsize(l2));
-	if (IsRNR(skb->data, test_bit(FLG_MOD128, &l2->flag))) {
+	if (IsRNR(skb->data, st)) {
 		test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
 		typ = RNR;
 	} else
 		test_and_clear_bit(FLG_PEER_BUSY, &l2->flag);
-	if (IsREJ(skb->data, test_bit(FLG_MOD128, &l2->flag)))
+	if (IsREJ(skb->data, st))
 		typ = REJ;
+
 	if (test_bit(FLG_MOD128, &l2->flag)) {
-		if (skb->len == 2) {
-			PollFlag = (skb->data[1] & 0x1) == 0x1;
-			nr = skb->data[1] >> 1;
-		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[1] & 0x1) == 0x1;
+		nr = skb->data[1] >> 1;
 	} else {
-		if (skb->len == 1) {
-			PollFlag = (skb->data[0] & 0x10);
-			nr = (skb->data[0] >> 5) & 0x7;
-		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[0] & 0x10);
+		nr = (skb->data[0] >> 5) & 0x7;
 	}
 	FreeSkb(skb);
 
-	if ((!rsp) && PollFlag)
-		enquiry_response(st);
-	if (rsp && PollFlag)
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'A');
+	if (PollFlag) {
+		if (rsp)
+			st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'A');
+		else
+			enquiry_response(st);
+	}
 	if (legalnr(st, nr)) {
 		if (typ == REJ) {
 			setva(st, nr);
 			invoke_retransmission(st, nr);
-			if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-				FsmDelTimer(&st->l2.t200, 9);
+			stop_t200(st, 10);
 			if (FsmAddTimer(&st->l2.t203, st->l2.T203,
 					EV_L2_T203, NULL, 6))
 				l2m_debug(&st->l2.l2m, "Restart T203 ST7 REJ");
 		} else if ((nr == l2->vs) && (typ == RR)) {
 			setva(st, nr);
-			if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-				FsmDelTimer(&st->l2.t200, 9);
+			stop_t200(st, 11);
 			FsmRestartTimer(&st->l2.t203, st->l2.T203,
 					EV_L2_T203, NULL, 7);
 		} else if ((l2->va != nr) || (typ == RNR)) {
 			setva(st, nr);
-			FsmDelTimer(&st->l2.t203, 9);
-			FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 6);
-			test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
+			if(typ != RR) FsmDelTimer(&st->l2.t203, 9);
+			restart_t200(st, 12);
 		}
 		if (skb_queue_len(&st->l2.i_queue) && (typ == RR))
-			st->l2.l2l1(st, PH_PULL_REQ, NULL);
+			st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	} else
 		nrerrorrecovery(fi);
+}
 
-	if ((fi->userint & LC_FLUSH_WAIT) && rsp && !(skb_queue_len(&st->l2.i_queue))) {
-		fi->userint &= ~LC_FLUSH_WAIT;
-		st->l2.l2man(st, DL_FLUSH, NULL);
-	}
+static void
+l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
+	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
+		skb_queue_tail(&st->l2.i_queue, skb);
+	else
+		FreeSkb(skb);
+}
+
+static void
+l2_feed_i_pull(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
+	skb_queue_tail(&st->l2.i_queue, skb);
+	st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
@@ -880,10 +1106,7 @@
 
 	if (test_bit(FLG_LAPB, &st->l2.flag))
 		st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0);
-	if (!((fi->state == ST_L2_5) && test_bit(FLG_L3_INIT, &st->l2.flag)))
-		skb_queue_tail(&st->l2.i_queue, skb);
-	if (fi->state == ST_L2_7)
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+	skb_queue_tail(&st->l2.i_queue, skb);
 }
 
 static void
@@ -891,73 +1114,37 @@
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	struct IsdnCardState *sp = st->l1.hardware;
 	struct Layer2 *l2 = &(st->l2);
-	int PollFlag, ns, nr, i, hs, rsp;
-	char str[64];
-
-	rsp = *skb->data & 0x2;
-	if (test_bit(FLG_ORIG, &l2->flag))
-		rsp = !rsp;
+	int PollFlag, ns, i;
+	unsigned int nr;
 
-	if (rsp) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
-		FreeSkb(skb);
-		establishlink(fi);
-		return;
-	}	
 	i = l2addrsize(l2);
 	if (test_bit(FLG_MOD128, &l2->flag)) {
-		if (skb->len <= (i + 1)) {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		} else if ((skb->len - i - 1) > l2->maxlen) { 
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
 		PollFlag = ((skb->data[i + 1] & 0x1) == 0x1);
 		ns = skb->data[i] >> 1;
 		nr = (skb->data[i + 1] >> 1) & 0x7f;
 	} else {
-		if (skb->len <= i) {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		} else if ((skb->len - i) > l2->maxlen) { 
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'O');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
 		PollFlag = (skb->data[i] & 0x10);
 		ns = (skb->data[i] >> 1) & 0x7;
 		nr = (skb->data[i] >> 5) & 0x7;
 	}
 	if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
 		FreeSkb(skb);
-		enquiry_response(st);
+		if(PollFlag) enquiry_response(st);
 	} else if (l2->vr == ns) {
-		l2->vr = (l2->vr + 1) % (test_bit(FLG_MOD128, &l2->flag) ? 128 : 8);
+		(l2->vr)++;
+		if(test_bit(FLG_MOD128, &l2->flag))
+			l2->vr %= 128;
+		else
+			l2->vr %= 8;
 		test_and_clear_bit(FLG_REJEXC, &l2->flag);
-		if (test_bit(FLG_LAPD, &l2->flag))
-			if (sp->dlogflag) {
-				hs = l2headersize(l2, 0);
-				LogFrame(st->l1.hardware, skb->data, skb->len);
-				sprintf(str, "Q.931 frame network->user tei %d", st->l2.tei);
-				dlogframe(st->l1.hardware, skb->data + hs,
-					  skb->len - hs, str);
-			}
+
 		if (PollFlag)
 			enquiry_response(st);
 		else
 			test_and_set_bit(FLG_ACK_PEND, &l2->flag);
 		skb_pull(skb, l2headersize(l2, 0));
-		st->l2.l2l3(st, DL_DATA, skb);
+		st->l2.l2l3(st, DL_DATA | INDICATION, skb);
 	} else {
 		/* n(s)!=v(r) */
 		FreeSkb(skb);
@@ -971,26 +1158,22 @@
 	}
 
 	if (legalnr(st, nr)) {
-		setva(st, nr);
 		if (!test_bit(FLG_PEER_BUSY, &st->l2.flag) && (fi->state == ST_L2_7)) {
 			if (nr == st->l2.vs) {
-				if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-					FsmDelTimer(&st->l2.t200, 10);
+				stop_t200(st, 13);
 				FsmRestartTimer(&st->l2.t203, st->l2.T203,
 						EV_L2_T203, NULL, 7);
-			} else if (nr != st->l2.va) {
-				FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
-						NULL, 8);
-				test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
-			}
+			} else if (nr != st->l2.va)
+				restart_t200(st, 14);
 		}
+		setva(st, nr);
 	} else {
 		nrerrorrecovery(fi);
 		return;
 	}
 
 	if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7))
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 	if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag))
 		enquiry_cr(st, RR, RSP, 0);
 }
@@ -1000,7 +1183,7 @@
 {
 	struct PStack *st = fi->userdata;
 
-	st->l2.tei = (int) arg;
+	st->l2.tei = (long) arg;
 
 	if (fi->state == ST_L2_3) {
 		establishlink(fi);
@@ -1008,13 +1191,7 @@
 	} else
 		FsmChangeState(fi, ST_L2_4);
 	if (skb_queue_len(&st->l2.ui_queue))
-		l2_send_ui(st);
-}
-
-static void
-l2_no_tei(struct FsmInst *fi, int event, void *arg)
-{
-	FsmChangeState(fi, ST_L2_4);
+		tx_ui(st);
 }
 
 static void
@@ -1028,9 +1205,11 @@
 	} else if (st->l2.rc == st->l2.N200) {
 		FsmChangeState(fi, ST_L2_4);
 		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
-		discard_i_queue(st);
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'G');
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		discard_queue(&st->l2.i_queue);
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G');
+		if (test_bit(FLG_LAPB, &st->l2.flag))
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+		st5_dl_release_l2l3(st);
 	} else {
 		st->l2.rc++;
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
@@ -1049,8 +1228,9 @@
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
 	} else if (st->l2.rc == st->l2.N200) {
 		FsmChangeState(fi, ST_L2_4);
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'H');
-		st->l2.l2man(st, DL_RELEASE, NULL);
+		test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'H');
+		lapb_dl_release_l2l3(st, CONFIRM);
 	} else {
 		st->l2.rc++;
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200,
@@ -1060,7 +1240,7 @@
 }
 
 static void
-l2_st78_tout_200(struct FsmInst *fi, int event, void *arg)
+l2_st7_tout_200(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
@@ -1070,12 +1250,28 @@
 		return;
 	}
 	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
-	if (fi->state == ST_L2_7) {
-		st->l2.rc = 0;
-		FsmChangeState(fi, ST_L2_8);
+	st->l2.rc = 0;
+	FsmChangeState(fi, ST_L2_8);
+
+	transmit_enquiry(st);
+	st->l2.rc++;
+}
+
+static void
+l2_st8_tout_200(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if (test_bit(FLG_LAPD, &st->l2.flag) &&
+		test_bit(FLG_DCHAN_BUSY, &st->l2.flag)) {
+		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 9);
+		return;
 	}
+	test_and_clear_bit(FLG_T200_RUN, &st->l2.flag);
 	if (st->l2.rc == st->l2.N200) {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'I');
 		establishlink(fi);
+		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 	} else {
 		transmit_enquiry(st);
 		st->l2.rc++;
@@ -1104,7 +1300,9 @@
 	struct sk_buff *skb, *oskb;
 	struct Layer2 *l2 = &st->l2;
 	u_char header[MAX_HEADER_LEN];
-	int p1, i;
+	int i;
+	int unsigned p1;
+	long flags;
 
 	if (!cansend(st))
 		return;
@@ -1113,14 +1311,17 @@
 	if (!skb)
 		return;
 
-	p1 = l2->vs - l2->va;
-	if (p1 < 0)
-		p1 += test_bit(FLG_MOD128, &l2->flag) ? 128 : 8;
+	save_flags(flags);
+	cli();
+	if(test_bit(FLG_MOD128, &l2->flag))
+		p1 = (l2->vs - l2->va) % 128;
+	else
+		p1 = (l2->vs - l2->va) % 8;
 	p1 = (p1 + l2->sow) % l2->window;
 	if (l2->windowar[p1]) {
 		printk(KERN_WARNING "isdnl2 try overwrite ack queue entry %d\n",
 		       p1);
-		dev_kfree_skb(l2->windowar[p1]);
+		idev_kfree_skb(l2->windowar[p1], FREE_WRITE);
 	}
 	l2->windowar[p1] = skb_clone(skb, GFP_ATOMIC);
 
@@ -1134,6 +1335,8 @@
 		header[i++] = (l2->vr << 5) | (l2->vs << 1);
 		l2->vs = (l2->vs + 1) % 8;
 	}
+	restore_flags(flags);
+
 	p1 = skb->data - skb->head;
 	if (p1 >= i)
 		memcpy(skb_push(skb, i), header, i);
@@ -1142,89 +1345,74 @@
 		"isdl2 pull_iqueue skb header(%d/%d) too short\n", i, p1);
 		oskb = skb;
 		skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
+		SET_SKB_FREE(skb);
 		memcpy(skb_put(skb, i), header, i);
 		memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
 		FreeSkb(oskb);
 	}
-	st->l2.l2l1(st, PH_PULL_IND, skb);
+	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
 	if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) {
 		FsmDelTimer(&st->l2.t203, 13);
 		FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11);
 	}
 	if (skb_queue_len(&l2->i_queue) && cansend(st))
-		st->l2.l2l1(st, PH_PULL_REQ, NULL);
+		st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
 }
 
 static void
-l2_got_st8_super(struct FsmInst *fi, int event, void *arg)
+l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	int PollFlag, nr, rsp, rnr = 0;
+	int PollFlag, rsp, rnr = 0;
+	unsigned int nr;
 	struct Layer2 *l2 = &st->l2;
 
 	rsp = *skb->data & 0x2;
 	if (test_bit(FLG_ORIG, &l2->flag))
 		rsp = !rsp;
+
 	skb_pull(skb, l2addrsize(l2));
 
-	if (IsRNR(skb->data, test_bit(FLG_MOD128, &l2->flag))) {
+	if (IsRNR(skb->data, st)) {
 		test_and_set_bit(FLG_PEER_BUSY, &l2->flag);
 		rnr = 1;
 	} else
 		test_and_clear_bit(FLG_PEER_BUSY, &l2->flag);
+
 	if (test_bit(FLG_MOD128, &l2->flag)) {
-		if (skb->len == 2) {
-			PollFlag = (skb->data[1] & 0x1) == 0x1;
-			nr = skb->data[1] >> 1;
-		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[1] & 0x1) == 0x1;
+		nr = skb->data[1] >> 1;
 	} else {
-		if (skb->len == 1) {
-			PollFlag = (skb->data[0] & 0x10);
-			nr = (skb->data[0] >> 5) & 0x7;
-		} else {
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-			FreeSkb(skb);
-			establishlink(fi);
-			return;
-		}
+		PollFlag = (skb->data[0] & 0x10);
+		nr = (skb->data[0] >> 5) & 0x7;
 	}
 	FreeSkb(skb);
 
 	if (rsp && PollFlag) {
 		if (legalnr(st, nr)) {
-			setva(st, nr);
-			if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-				FsmDelTimer(&st->l2.t200, 7);
-			FsmDelTimer(&l2->t203, 8);
 			if (rnr) {
-				FsmRestartTimer(&l2->t200, l2->T200,
-						EV_L2_T200, NULL, 14);
-				test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
-			} else
+				restart_t200(st, 15);
+			} else {
+				stop_t200(st, 16);
 				FsmAddTimer(&l2->t203, l2->T203,
 					    EV_L2_T203, NULL, 5);
+				setva(st, nr);
+			}
 			invoke_retransmission(st, nr);
 			FsmChangeState(fi, ST_L2_7);
 			if (skb_queue_len(&l2->i_queue) && cansend(st))
-				st->l2.l2l1(st, PH_PULL_REQ, NULL);
-			else if (fi->userint & LC_FLUSH_WAIT) {
-				fi->userint &= ~LC_FLUSH_WAIT;
-				st->l2.l2man(st, DL_FLUSH, NULL);
-			}
-		}
+				st->l2.l2l1(st, PH_PULL | REQUEST, NULL);
+		} else
+			nrerrorrecovery(fi);
 	} else {
 		if (!rsp && PollFlag)
 			enquiry_response(st);
 		if (legalnr(st, nr)) {
 			setva(st, nr);
-		}
+		} else
+			nrerrorrecovery(fi);
 	}
 }
 
@@ -1233,30 +1421,12 @@
 {
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
-	char tmp[64];
 
 	skb_pull(skb, l2addrsize(&st->l2) + 1);
-	if (test_bit(FLG_MOD128, &st->l2.flag)) {
-		if (skb->len < 5)
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		else {
-			sprintf(tmp, "FRMR information %2x %2x %2x %2x %2x",
-				skb->data[0], skb->data[1], skb->data[2],
-				skb->data[3], skb->data[4]);
-			l2m_debug(&st->l2.l2m, tmp);
-		}
-	} else {
-		if (skb->len < 3)
-			st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
-		else {
-			sprintf(tmp, "FRMR information %2x %2x %2x",
-				skb->data[0], skb->data[1], skb->data[2]);
-			l2m_debug(&st->l2.l2m, tmp);
-		}
-	}
+
 	if (!(skb->data[0] & 1) || ((skb->data[0] & 3) == 1) ||		/* I or S */
-	    (IsUA(skb->data, 0) && (fi->state == ST_L2_7))) {
-		st->ma.layer(st, MDL_ERROR_IND, (void *) 'K');
+	    (IsUA(skb->data) && (fi->state == ST_L2_7))) {
+		st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'K');
 		establishlink(fi);
 		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 	}
@@ -1264,103 +1434,206 @@
 }
 
 static void
+l2_st24_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	st->l2.tei = -1;
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st3_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	st->l2.tei = -1;
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st5_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
+	st->l2.tei = -1;
+	stop_t200(st, 17);
+	st5_dl_release_l2l3(st);
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
+l2_st6_tei_remove(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	st->l2.tei = -1;
+	stop_t200(st, 18);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+	FsmChangeState(fi, ST_L2_1);
+}
+
+static void
 l2_tei_remove(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 
-	discard_i_queue(st);
-	discard_ui_queue(st);
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
 	st->l2.tei = -1;
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 18);
+	stop_t200(st, 17);
 	FsmDelTimer(&st->l2.t203, 19);
-	if (fi->state != ST_L2_4)
-		st->l2.l2man(st, DL_RELEASE, NULL);
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
 	FsmChangeState(fi, ST_L2_1);
 }
 
 static void
-l2_persistant_da(struct FsmInst *fi, int event, void *arg)
+l2_discard_i(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
 	
-	discard_i_queue(st);
-	discard_ui_queue(st);
-	if (test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
-		FsmDelTimer(&st->l2.t200, 18);
+	discard_queue(&st->l2.i_queue);
+}
+
+static void
+l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
+	stop_t200(st, 19);
+	st5_dl_release_l2l3(st);
+	FsmChangeState(fi, ST_L2_4);
+}
+
+static void
+l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.ui_queue);
+	stop_t200(st, 20);
+	st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL);
+	FsmChangeState(fi, ST_L2_4);
+}
+
+static void
+l2_persistant_da(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
+	freewin(st);
+	stop_t200(st, 19);
 	FsmDelTimer(&st->l2.t203, 19);
-	test_and_clear_bit(FLG_PEND_REL, &st->l2.flag);
-	clear_exception(&st->l2);
-	switch (fi->state) {
-		case ST_L2_3:
-			st->l2.l2man(st, DL_RELEASE, NULL);
-		case ST_L2_2:
-			FsmChangeState(fi, ST_L2_1);
-			break;
-		case ST_L2_5:
-		case ST_L2_6:
-		case ST_L2_7:
-		case ST_L2_8:
-			st->l2.l2man(st, DL_RELEASE, NULL);
-			FsmChangeState(fi, ST_L2_4);
-			break;
+	st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL);
+	FsmChangeState(fi, ST_L2_4);
+}
+
+static void
+l2_set_own_busy(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if(!test_and_set_bit(FLG_OWN_BUSY, &st->l2.flag)) {
+		enquiry_cr(st, RNR, RSP, 0);
+		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
+	}
+}
+
+static void
+l2_clear_own_busy(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	if(!test_and_clear_bit(FLG_OWN_BUSY, &st->l2.flag)) {
+		enquiry_cr(st, RR, RSP, 0);
+		test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
 	}
 }
 
+static void
+l2_frame_error(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
+}
+
+static void
+l2_frame_error_reest(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	st->ma.layer(st, MDL_ERROR | INDICATION, arg);
+	establishlink(fi);
+	test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
+}
+
 static struct FsmNode L2FnList[] HISAX_INITDATA =
 {
-	{ST_L2_1, EV_L2_MDL_NOTEIPROC, l2_no_tei},
-	{ST_L2_1, EV_L2_DL_ESTABLISH, l2_dl_establish},
-	{ST_L2_2, EV_L2_DL_ESTABLISH, l2_dl_establish},
-	{ST_L2_4, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_5, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_7, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_8, EV_L2_DL_ESTABLISH, l2_establish},
-	{ST_L2_4, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_5, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_7, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_8, EV_L2_DL_RELEASE, l2_dl_release},
-	{ST_L2_5, EV_L2_DL_DATA, l2_feed_iqueue},
-	{ST_L2_7, EV_L2_DL_DATA, l2_feed_iqueue},
+	{ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign},
+	{ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3},
+	{ST_L2_4, EV_L2_DL_ESTABLISH_REQ, l2_establish},
+	{ST_L2_5, EV_L2_DL_ESTABLISH_REQ, l2_discard_i_setl3},
+	{ST_L2_7, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
+	{ST_L2_8, EV_L2_DL_ESTABLISH_REQ, l2_l3_reestablish},
+	{ST_L2_4, EV_L2_DL_RELEASE_REQ, l2_release},
+	{ST_L2_5, EV_L2_DL_RELEASE_REQ, l2_pend_rel},
+	{ST_L2_7, EV_L2_DL_RELEASE_REQ, l2_disconnect},
+	{ST_L2_8, EV_L2_DL_RELEASE_REQ, l2_disconnect},
+	{ST_L2_5, EV_L2_DL_DATA, l2_feed_i_if_reest},
+	{ST_L2_7, EV_L2_DL_DATA, l2_feed_i_pull},
 	{ST_L2_8, EV_L2_DL_DATA, l2_feed_iqueue},
-	{ST_L2_1, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_2, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_3, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_4, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_5, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_6, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_7, EV_L2_DL_UNIT_DATA, l2_put_ui},
-	{ST_L2_8, EV_L2_DL_UNIT_DATA, l2_put_ui},
+	{ST_L2_1, EV_L2_DL_UNIT_DATA, l2_queue_ui_assign},
+	{ST_L2_2, EV_L2_DL_UNIT_DATA, l2_queue_ui},
+	{ST_L2_3, EV_L2_DL_UNIT_DATA, l2_queue_ui},
+	{ST_L2_4, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_5, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_6, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_7, EV_L2_DL_UNIT_DATA, l2_send_ui},
+	{ST_L2_8, EV_L2_DL_UNIT_DATA, l2_send_ui},
 	{ST_L2_1, EV_L2_MDL_ASSIGN, l2_got_tei},
 	{ST_L2_2, EV_L2_MDL_ASSIGN, l2_got_tei},
 	{ST_L2_3, EV_L2_MDL_ASSIGN, l2_got_tei},
-	{ST_L2_2, EV_L2_MDL_ERROR, l2_tei_remove},
-	{ST_L2_3, EV_L2_MDL_ERROR, l2_tei_remove},
-	{ST_L2_4, EV_L2_MDL_REMOVE, l2_tei_remove},
-	{ST_L2_5, EV_L2_MDL_REMOVE, l2_tei_remove},
-	{ST_L2_6, EV_L2_MDL_REMOVE, l2_tei_remove},
+	{ST_L2_2, EV_L2_MDL_ERROR, l2_st24_tei_remove},
+	{ST_L2_3, EV_L2_MDL_ERROR, l2_st3_tei_remove},
+	{ST_L2_4, EV_L2_MDL_REMOVE, l2_st24_tei_remove},
+	{ST_L2_5, EV_L2_MDL_REMOVE, l2_st5_tei_remove},
+	{ST_L2_6, EV_L2_MDL_REMOVE, l2_st6_tei_remove},
 	{ST_L2_7, EV_L2_MDL_REMOVE, l2_tei_remove},
 	{ST_L2_8, EV_L2_MDL_REMOVE, l2_tei_remove},
-	{ST_L2_4, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_5, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_6, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_7, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_8, EV_L2_SABMX, l2_got_SABMX},
-	{ST_L2_4, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_5, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_6, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_7, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_8, EV_L2_DISC, l2_got_disconn},
-	{ST_L2_4, EV_L2_UA, l2_mdl_error},
-	{ST_L2_5, EV_L2_UA, l2_got_ua},
-	{ST_L2_6, EV_L2_UA, l2_got_ua},
-	{ST_L2_7, EV_L2_UA, l2_mdl_error},
-	{ST_L2_8, EV_L2_UA, l2_mdl_error},
-	{ST_L2_4, EV_L2_DM, l2_got_dm},
-	{ST_L2_5, EV_L2_DM, l2_got_dm},
-	{ST_L2_6, EV_L2_DM, l2_got_dm},
-	{ST_L2_7, EV_L2_DM, l2_mdl_error},
-	{ST_L2_8, EV_L2_DM, l2_mdl_error},
+	{ST_L2_4, EV_L2_SABME, l2_start_multi},
+	{ST_L2_5, EV_L2_SABME, l2_send_UA},
+	{ST_L2_6, EV_L2_SABME, l2_send_DM},
+	{ST_L2_7, EV_L2_SABME, l2_restart_multi},
+	{ST_L2_8, EV_L2_SABME, l2_restart_multi},
+	{ST_L2_4, EV_L2_DISC, l2_send_DM},
+	{ST_L2_5, EV_L2_DISC, l2_send_DM},
+	{ST_L2_6, EV_L2_DISC, l2_send_UA},
+	{ST_L2_7, EV_L2_DISC, l2_stop_multi},
+	{ST_L2_8, EV_L2_DISC, l2_stop_multi},
+	{ST_L2_4, EV_L2_UA, l2_mdl_error_ua},
+	{ST_L2_5, EV_L2_UA, l2_connected},
+	{ST_L2_6, EV_L2_UA, l2_released},
+	{ST_L2_7, EV_L2_UA, l2_mdl_error_ua},
+	{ST_L2_8, EV_L2_UA, l2_mdl_error_ua},
+	{ST_L2_4, EV_L2_DM, l2_reestablish},
+	{ST_L2_5, EV_L2_DM, l2_st5_dm_release},
+	{ST_L2_6, EV_L2_DM, l2_st6_dm_release},
+	{ST_L2_7, EV_L2_DM, l2_mdl_error_dm},
+	{ST_L2_8, EV_L2_DM, l2_st8_mdl_error_dm},
 	{ST_L2_1, EV_L2_UI, l2_got_ui},
 	{ST_L2_2, EV_L2_UI, l2_got_ui},
 	{ST_L2_3, EV_L2_UI, l2_got_ui},
@@ -1371,21 +1644,30 @@
 	{ST_L2_8, EV_L2_UI, l2_got_ui},
 	{ST_L2_7, EV_L2_FRMR, l2_got_FRMR},
 	{ST_L2_8, EV_L2_FRMR, l2_got_FRMR},
-	{ST_L2_7, EV_L2_SUPER, l2_got_st7_super},
-	{ST_L2_8, EV_L2_SUPER, l2_got_st8_super},
+	{ST_L2_7, EV_L2_SUPER, l2_st7_got_super},
+	{ST_L2_8, EV_L2_SUPER, l2_st8_got_super},
 	{ST_L2_7, EV_L2_I, l2_got_iframe},
 	{ST_L2_8, EV_L2_I, l2_got_iframe},
 	{ST_L2_5, EV_L2_T200, l2_st5_tout_200},
 	{ST_L2_6, EV_L2_T200, l2_st6_tout_200},
-	{ST_L2_7, EV_L2_T200, l2_st78_tout_200},
-	{ST_L2_8, EV_L2_T200, l2_st78_tout_200},
+	{ST_L2_7, EV_L2_T200, l2_st7_tout_200},
+	{ST_L2_8, EV_L2_T200, l2_st8_tout_200},
 	{ST_L2_7, EV_L2_T203, l2_st7_tout_203},
 	{ST_L2_7, EV_L2_ACK_PULL, l2_pull_iqueue},
-	{ST_L2_2, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_3, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_4, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_5, EV_L1_DEACTIVATE, l2_persistant_da},
-	{ST_L2_6, EV_L1_DEACTIVATE, l2_persistant_da},
+	{ST_L2_7, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
+	{ST_L2_8, EV_L2_SET_OWN_BUSY, l2_set_own_busy},
+	{ST_L2_7, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
+	{ST_L2_8, EV_L2_CLEAR_OWN_BUSY, l2_clear_own_busy},
+	{ST_L2_4, EV_L2_FRAME_ERROR, l2_frame_error},
+	{ST_L2_5, EV_L2_FRAME_ERROR, l2_frame_error},
+	{ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error},
+	{ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest},
+	{ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest},
+	{ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove},
+	{ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove},
+	{ST_L2_4, EV_L1_DEACTIVATE, l2_discard_i},
+	{ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da},
+	{ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da},
 	{ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da},
 	{ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da},
 };
@@ -1398,52 +1680,79 @@
 	struct sk_buff *skb = arg;
 	u_char *datap;
 	int ret = 1, len;
+	int c = 0;
 
 	switch (pr) {
-		case (PH_DATA_IND):
+		case (PH_DATA | INDICATION):
 			datap = skb->data;
 			len = l2addrsize(&st->l2);
 			if (skb->len > len)
 				datap += len;
 			else {
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'N');
+				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
 				FreeSkb(skb);
 				return;
 			}
-			if (!(*datap & 1))	/* I-Frame */
-				ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
-			else if ((*datap & 3) == 1)	/* S-Frame */
-				ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
-			else if (IsUI(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
-			else if (IsSABMX(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_SABMX, skb);
-			else if (IsUA(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
-			else if (IsDISC(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
-			else if (IsDM(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
-			else if (IsFRMR(datap, test_bit(FLG_MOD128, &st->l2.flag)))
-				ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
-			else {
-				ret = 0;
-				st->ma.layer(st, MDL_ERROR_IND, (void *) 'L');
+			if (!(*datap & 1)) {	/* I-Frame */
+				if(!(c = iframe_error(st, skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_I, skb);
+			} else if (IsSFrame(datap, st)) {	/* S-Frame */
+				if(!(c = super_error(st, skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_SUPER, skb);
+			} else if (IsUI(datap)) {
+				if(!(c = UI_error(st, skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_UI, skb);
+			} else if (IsSABME(datap, st)) {
+				if(!(c = unnum_error(st, skb, CMD)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_SABME, skb);
+			} else if (IsUA(datap)) {
+				if(!(c = unnum_error(st, skb, RSP)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_UA, skb);
+			} else if (IsDISC(datap)) {
+				if(!(c = unnum_error(st, skb, CMD)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_DISC, skb);
+			} else if (IsDM(datap)) {
+				if(!(c = unnum_error(st, skb, RSP)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_DM, skb);
+			} else if (IsFRMR(datap)) {
+				if(!(c = FRMR_error(st,skb)))
+					ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
+			} else {
+				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
 				FreeSkb(skb);
+				ret = 0;
 			}
-			if (ret) {
+			if(c) {
 				FreeSkb(skb);
+				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) c);
+				ret = 0;
 			}
+			if (ret)
+				FreeSkb(skb);
 			break;
-		case (PH_PULL_CNF):
+		case (PH_PULL | CONFIRM):
 			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
 			break;
-		case (PH_PAUSE_IND):
+		case (PH_PAUSE | INDICATION):
 			test_and_set_bit(FLG_DCHAN_BUSY, &st->l2.flag);
 			break;
-		case (PH_PAUSE_CNF):
+		case (PH_PAUSE | CONFIRM):
 			test_and_clear_bit(FLG_DCHAN_BUSY, &st->l2.flag);
 			break;
+		case (PH_ACTIVATE | CONFIRM):
+		case (PH_ACTIVATE | INDICATION):
+			test_and_set_bit(FLG_L1_ACTIV, &st->l2.flag);
+			if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag))
+				FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
+			break;
+		case (PH_DEACTIVATE | INDICATION):
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(FLG_L1_ACTIV, &st->l2.flag);
+			FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
+			break;
+		default:
+			l2m_debug(&st->l2.l2m, "l2 unknown pr %04x", pr);
+			break;
 	}
 }
 
@@ -1451,45 +1760,43 @@
 isdnl2_l3l2(struct PStack *st, int pr, void *arg)
 {
 	switch (pr) {
-		case (DL_DATA):
+		case (DL_DATA | REQUEST):
 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_DATA, arg)) {
-				dev_kfree_skb((struct sk_buff *) arg);
+				idev_kfree_skb((struct sk_buff *) arg, FREE_READ);
 			}
 			break;
-		case (DL_UNIT_DATA):
+		case (DL_UNIT_DATA | REQUEST):
 			if (FsmEvent(&st->l2.l2m, EV_L2_DL_UNIT_DATA, arg)) {
-				dev_kfree_skb((struct sk_buff *) arg);
+				idev_kfree_skb((struct sk_buff *) arg, FREE_READ);
 			}
 			break;
-	}
-}
-
-static void
-isdnl2_manl2(struct PStack *st, int pr, void *arg)
-{
-	switch (pr) {
-		case (DL_ESTABLISH):
-			FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH, arg);
-			break;
-		case (DL_RELEASE):
-			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE, arg);
-			break;
-		case (MDL_NOTEIPROC):
-			FsmEvent(&st->l2.l2m, EV_L2_MDL_NOTEIPROC, NULL);
-			break;
-		case (DL_FLUSH):
-			(&st->l2.l2m)->userint |= LC_FLUSH_WAIT;
+		case (DL_ESTABLISH | REQUEST):
+			if (test_bit(FLG_L1_ACTIV, &st->l2.flag)) {
+				if (test_bit(FLG_LAPD, &st->l2.flag) ||
+					test_bit(FLG_ORIG, &st->l2.flag)) {
+					FsmEvent(&st->l2.l2m, EV_L2_DL_ESTABLISH_REQ, arg);
+				}
+			} else {
+				if (test_bit(FLG_LAPD, &st->l2.flag) ||
+					test_bit(FLG_ORIG, &st->l2.flag)) {
+					test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag);
+				}
+				st->l2.l2l1(st, PH_ACTIVATE, NULL);
+			}
 			break;
-		case (PH_DEACTIVATE_IND):
-			FsmEvent(&st->l2.l2m, EV_L1_DEACTIVATE, arg);
+		case (DL_RELEASE | REQUEST):
+			if (test_bit(FLG_LAPB, &st->l2.flag)) {
+				st->l2.l2l1(st, PH_DEACTIVATE, NULL);
+			}
+			FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg);
 			break;
-		case (MDL_ASSIGN_REQ):
+		case (MDL_ASSIGN | REQUEST):
 			FsmEvent(&st->l2.l2m, EV_L2_MDL_ASSIGN, arg);
 			break;
-		case (MDL_REMOVE_REQ):
+		case (MDL_REMOVE | REQUEST):
 			FsmEvent(&st->l2.l2m, EV_L2_MDL_REMOVE, arg);
 			break;
-		case (MDL_ERROR_REQ):
+		case (MDL_ERROR | RESPONSE):
 			FsmEvent(&st->l2.l2m, EV_L2_MDL_ERROR, arg);
 			break;
 	}
@@ -1498,22 +1805,22 @@
 void
 releasestack_isdnl2(struct PStack *st)
 {
-	FsmDelTimer(&st->l2.t200, 15);
+	FsmDelTimer(&st->l2.t200, 21);
 	FsmDelTimer(&st->l2.t203, 16);
-	discard_i_queue(st);
-	discard_ui_queue(st);
+	discard_queue(&st->l2.i_queue);
+	discard_queue(&st->l2.ui_queue);
 	ReleaseWin(&st->l2);
 }
 
 static void
-l2m_debug(struct FsmInst *fi, char *s)
+l2m_debug(struct FsmInst *fi, char *fmt, ...)
 {
+	va_list args;
 	struct PStack *st = fi->userdata;
-	char tm[32], str[256];
 
-	jiftime(tm, jiffies);
-	sprintf(str, "%s %s %s\n", tm, st->l2.debug_id, s);
-	HiSax_putstatus(st->l1.hardware, str);
+	va_start(args, fmt);
+	VHiSax_putstatus(st->l1.hardware, st->l2.debug_id, fmt, args);
+	va_end(args);
 }
 
 void
@@ -1521,7 +1828,6 @@
 {
 	st->l1.l1l2 = isdnl2_l1l2;
 	st->l3.l3l2 = isdnl2_l3l2;
-	st->ma.manl2 = isdnl2_manl2;
 
 	skb_queue_head_init(&st->l2.i_queue);
 	skb_queue_head_init(&st->l2.ui_queue);
@@ -1529,6 +1835,9 @@
 	st->l2.debug = 0;
 
 	st->l2.l2m.fsm = &l2fsm;
+	if (test_bit(FLG_LAPB, &st->l2.flag))
+		st->l2.l2m.state = ST_L2_4;
+	else
 	st->l2.l2m.state = ST_L2_1;
 	st->l2.l2m.debug = 0;
 	st->l2.l2m.userdata = st;
@@ -1540,9 +1849,27 @@
 	FsmInitTimer(&st->l2.l2m, &st->l2.t203);
 }
 
+static void
+transl2_l3l2(struct PStack *st, int pr, void *arg)
+{
+	switch (pr) {
+		case (DL_DATA | REQUEST):
+		case (DL_UNIT_DATA | REQUEST):
+			st->l2.l2l1(st, PH_DATA | REQUEST, arg);
+			break;
+		case (DL_ESTABLISH | REQUEST):
+			st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL);
+			break;
+		case (DL_RELEASE | REQUEST):
+			st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL);
+			break;
+	}
+}
+
 void
 setstack_transl2(struct PStack *st)
 {
+	st->l3.l3l2 = transl2_l3l2;
 }
 
 void
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl3.c linux.pre11.3/drivers/isdn/hisax/isdnl3.c
--- linux.vanilla/drivers/isdn/hisax/isdnl3.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/isdnl3.c	Mon Jul 19 23:59:34 1999
@@ -1,12 +1,30 @@
-/* $Id: isdnl3.c,v 2.5 1998/02/12 23:07:52 keil Exp $
+/* $Id: isdnl3.c,v 2.9 1999/07/01 08:11:53 keil Exp $
 
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
  * Thanks to    Jan den Ouden
  *              Fritz Elfert
  *
  * $Log: isdnl3.c,v $
+ * Revision 2.9  1999/07/01 08:11:53  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.8  1998/11/15 23:55:04  keil
+ * changes from 2.0
+ *
+ * Revision 2.7  1998/05/25 14:10:15  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.6  1998/05/25 12:58:11  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 2.5  1998/02/12 23:07:52  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -47,7 +65,64 @@
 #include "isdnl3.h"
 #include <linux/config.h>
 
-const char *l3_revision = "$Revision: 2.5 $";
+const char *l3_revision = "$Revision: 2.9 $";
+
+static
+struct Fsm l3fsm =
+{NULL, 0, 0, NULL, NULL};
+
+enum {
+	ST_L3_LC_REL,
+	ST_L3_LC_ESTAB_WAIT,
+	ST_L3_LC_REL_DELAY, 
+	ST_L3_LC_REL_WAIT,
+	ST_L3_LC_ESTAB,
+};
+
+#define L3_STATE_COUNT (ST_L3_LC_ESTAB+1)
+
+static char *strL3State[] =
+{
+	"ST_L3_LC_REL",
+	"ST_L3_LC_ESTAB_WAIT",
+	"ST_L3_LC_REL_DELAY",
+	"ST_L3_LC_REL_WAIT",
+	"ST_L3_LC_ESTAB",
+};
+
+enum {
+	EV_ESTABLISH_REQ,
+	EV_ESTABLISH_IND,
+	EV_ESTABLISH_CNF,
+	EV_RELEASE_REQ,
+	EV_RELEASE_CNF,
+	EV_RELEASE_IND,
+	EV_TIMEOUT,
+};
+
+#define L3_EVENT_COUNT (EV_TIMEOUT+1)
+
+static char *strL3Event[] =
+{
+	"EV_ESTABLISH_REQ",
+	"EV_ESTABLISH_IND",
+	"EV_ESTABLISH_CNF",
+	"EV_RELEASE_REQ",
+	"EV_RELEASE_CNF",
+	"EV_RELEASE_IND",
+	"EV_TIMEOUT",
+};
+
+static void
+l3m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+	va_list args;
+	struct PStack *st = fi->userdata;
+
+	va_start(args, fmt);
+	VHiSax_putstatus(st->l1.hardware, st->l3.debug_id, fmt, args);
+	va_end(args);
+}
 
 u_char *
 findie(u_char * p, int size, u_char ie, int wanted_set)
@@ -74,7 +149,14 @@
 		else {
 			if (codeset == wanted_set) {
 				if (*p == ie)
-					return (p);
+                                  { /* improved length check (Werner Cornelius) */
+                                    if ((pend - p) < 2) 
+                                      return(NULL); 
+                                    if (*(p+1) > (pend - (p+2))) 
+                                      return(NULL); 
+                                    return (p);
+                                  }           
+                                  
 				if (*p > ie)
 					return (NULL);
 			}
@@ -90,15 +172,15 @@
 int
 getcallref(u_char * p)
 {
-	int l, m = 1, cr = 0;
+	int l, cr = 0;
+
 	p++;			/* prot discr */
+	if (*p & 0xfe)		/* wrong callref BRI only 1 octet*/
+		return(-2);
 	l = 0xf & *p++;		/* callref length */
 	if (!l)			/* dummy CallRef */
 		return(-1);
-	while (l--) {
-		cr += m * (*p++);
-		m *= 8;
-	}
+	cr = *p++;
 	return (cr);
 }
 
@@ -115,25 +197,12 @@
 }
 
 void
-l3_debug(struct PStack *st, char *s)
-{
-	char str[256], tm[32];
-
-	jiftime(tm, jiffies);
-	sprintf(str, "%s l3 %s\n", tm, s);
-	HiSax_putstatus(st->l1.hardware, str);
-}
-
-void
 newl3state(struct l3_process *pc, int state)
 {
-	char tmp[80];
-
-	if (pc->debug & L3_DEB_STATE) {
-		sprintf(tmp, "newstate cr %d %d --> %d", pc->callref,
-			pc->state, state);
-		l3_debug(pc->st, tmp);
-	}
+	if (pc->debug & L3_DEB_STATE)
+		l3_debug(pc->st, "newstate cr %d %d --> %d", 
+			 pc->callref & 0x7F,
+			 pc->state, state);
 	pc->state = state;
 }
 
@@ -188,6 +257,7 @@
 		printk(KERN_WARNING "HiSax: No skb for D-channel\n");
 		return (NULL);
 	}
+	SET_SKB_FREE(skb);
 	skb_reserve(skb, MAX_HEADER_LEN);
 	return (skb);
 }
@@ -197,12 +267,19 @@
 {
 	struct sk_buff *skb = arg;
 
-	HiSax_putstatus(st->l1.hardware, "L3 no D protocol\n");
+	HiSax_putstatus(st->l1.hardware, "L3", "no D protocol");
 	if (skb) {
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 	}
 }
 
+static int
+no_l3_proto_spec(struct PStack *st, isdn_ctrl *ic)
+{
+	printk(KERN_WARNING "HiSax: no specific protocol handler for proto %lu\n",ic->arg & 0xFF);
+	return(-1);
+}
+
 #ifdef	CONFIG_HISAX_EURO
 extern void setstack_dss1(struct PStack *st);
 #endif
@@ -246,7 +323,7 @@
 		np->next = p;
 	}
 	p->next = NULL;
-	p->debug = L3_DEB_WARN;
+	p->debug = st->l3.debug;
 	p->callref = cr;
 	p->state = 0;
 	p->chan = NULL;
@@ -269,24 +346,47 @@
 			StopAllL3Timer(p);
 			if (pp)
 				pp->next = np->next;
-			else
-				p->st->l3.proc = np->next;
+			else if (!(p->st->l3.proc = np->next) &&
+				 !test_bit(FLG_PTP, &p->st->l2.flag))
+			         FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL);
 			kfree(p);
 			return;
 		}
 		pp = np;
 		np = np->next;
 	}
-	printk(KERN_ERR "HiSax internal L3 error CR not in list\n");
+	printk(KERN_ERR "HiSax internal L3 error CR(%d) not in list\n", p->callref);
+	l3_debug(p->st, "HiSax internal L3 error CR(%d) not in list", p->callref);
 };
 
+static void
+l3ml3p(struct PStack *st, int pr)
+{
+       struct l3_process *p = st->l3.proc;
+
+       while (p) {
+               st->l3.l3ml3(st, pr, p);
+               p = p->next;
+       }
+}
+
 void
-setstack_isdnl3(struct PStack *st, struct Channel *chanp)
+setstack_l3dc(struct PStack *st, struct Channel *chanp)
 {
 	char tmp[64];
 
 	st->l3.proc   = NULL;
 	st->l3.global = NULL;
+	skb_queue_head_init(&st->l3.squeue);
+	st->l3.l3m.fsm = &l3fsm;
+	st->l3.l3m.state = ST_L3_LC_REL;
+	st->l3.l3m.debug = 1;
+	st->l3.l3m.userdata = st;
+	st->l3.l3m.userint = 0;
+	st->l3.l3m.printdebug = l3m_debug;
+        FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer);
+	strcpy(st->l3.debug_id, "L3DC ");
+	st->lli.l4l3_proto = no_l3_proto_spec;
 
 #ifdef	CONFIG_HISAX_EURO
 	if (st->protocol == ISDN_PTYPE_EURO) {
@@ -306,10 +406,12 @@
 	if (st->protocol == ISDN_PTYPE_LEASED) {
 		st->lli.l4l3 = no_l3_proto;
 		st->l2.l2l3 = no_l3_proto;
+                st->l3.l3ml3 = no_l3_proto;
 		printk(KERN_INFO "HiSax: Leased line mode\n");
 	} else {
 		st->lli.l4l3 = no_l3_proto;
 		st->l2.l2l3 = no_l3_proto;
+                st->l3.l3ml3 = no_l3_proto;
 		sprintf(tmp, "protocol %s not supported",
 			(st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" :
 			(st->protocol == ISDN_PTYPE_EURO) ? "euro" :
@@ -321,6 +423,11 @@
 }
 
 void
+isdnl3_trans(struct PStack *st, int pr, void *arg) {
+	st->l3.l3l2(st, pr, arg);
+}
+
+void
 releasestack_isdnl3(struct PStack *st)
 {
 	while (st->l3.proc)
@@ -330,4 +437,174 @@
 		kfree(st->l3.global);
 		st->l3.global = NULL;
 	}
+	FsmDelTimer(&st->l3.l3m_timer, 54);
+	discard_queue(&st->l3.squeue);
+}
+
+void
+setstack_l3bc(struct PStack *st, struct Channel *chanp)
+{
+
+	st->l3.proc   = NULL;
+	st->l3.global = NULL;
+	skb_queue_head_init(&st->l3.squeue);
+	st->l3.l3m.fsm = &l3fsm;
+	st->l3.l3m.state = ST_L3_LC_REL;
+	st->l3.l3m.debug = 1;
+	st->l3.l3m.userdata = st;
+	st->l3.l3m.userint = 0;
+	st->l3.l3m.printdebug = l3m_debug;
+	strcpy(st->l3.debug_id, "L3BC ");
+	st->lli.l4l3 = isdnl3_trans;
+}
+
+#define DREL_TIMER_VALUE 40000
+
+static void
+lc_activate(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT);
+	st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL);
+}
+
+static void
+lc_connect(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	FsmChangeState(fi, ST_L3_LC_ESTAB);
+	while ((skb = skb_dequeue(&st->l3.squeue))) {
+		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
+	}
+	l3ml3p(st, DL_ESTABLISH | INDICATION);
+}
+
+static void
+lc_connected(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+	struct sk_buff *skb = arg;
+
+	FsmDelTimer(&st->l3.l3m_timer, 51);
+	FsmChangeState(fi, ST_L3_LC_ESTAB);
+	while ((skb = skb_dequeue(&st->l3.squeue))) {
+		st->l3.l3l2(st, DL_DATA | REQUEST, skb);
+	}
+	l3ml3p(st, DL_ESTABLISH | CONFIRM);
+}
+
+static void
+lc_start_delay(struct FsmInst *fi, int event, void *arg)
+{
+       struct PStack *st = fi->userdata;
+
+       FsmChangeState(fi, ST_L3_LC_REL_DELAY);
+       FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50);
+}
+
+static void
+lc_release_req(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmChangeState(fi, ST_L3_LC_REL_WAIT);
+	st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL);
+}
+
+static void
+lc_release_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct PStack *st = fi->userdata;
+
+	FsmDelTimer(&st->l3.l3m_timer, 52);
+	FsmChangeState(fi, ST_L3_LC_REL);
+	discard_queue(&st->l3.squeue);
+	l3ml3p(st, DL_RELEASE | INDICATION);
+}
+
+static void
+lc_release_cnf(struct FsmInst *fi, int event, void *arg)
+{
+       struct PStack *st = fi->userdata;
+
+        FsmChangeState(fi, ST_L3_LC_REL);
+        discard_queue(&st->l3.squeue);
+       l3ml3p(st, DL_RELEASE | CONFIRM);
+}
+
+
+/* *INDENT-OFF* */
+static struct FsmNode L3FnList[] HISAX_INITDATA =
+{
+	{ST_L3_LC_REL,		EV_ESTABLISH_REQ,	lc_activate},
+	{ST_L3_LC_REL,		EV_ESTABLISH_IND,	lc_connect},
+	{ST_L3_LC_REL,		EV_ESTABLISH_CNF,	lc_connect},
+	{ST_L3_LC_ESTAB_WAIT,	EV_ESTABLISH_CNF,	lc_connected},
+	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_REQ,		lc_start_delay},
+	{ST_L3_LC_ESTAB_WAIT,	EV_RELEASE_IND,		lc_release_ind},
+	{ST_L3_LC_ESTAB,	EV_RELEASE_IND,		lc_release_ind},
+	{ST_L3_LC_ESTAB,	EV_RELEASE_REQ,		lc_start_delay},
+        {ST_L3_LC_REL_DELAY,    EV_RELEASE_IND,         lc_release_ind},
+        {ST_L3_LC_REL_DELAY,    EV_ESTABLISH_REQ,       lc_connected},
+        {ST_L3_LC_REL_DELAY,    EV_TIMEOUT,             lc_release_req},
+	{ST_L3_LC_REL_WAIT,	EV_RELEASE_CNF,		lc_release_cnf},
+	{ST_L3_LC_REL_WAIT,	EV_ESTABLISH_REQ,	lc_activate},
+};
+/* *INDENT-ON* */
+
+#define L3_FN_COUNT (sizeof(L3FnList)/sizeof(struct FsmNode))
+
+void
+l3_msg(struct PStack *st, int pr, void *arg)
+{
+	
+	switch (pr) {
+		case (DL_DATA | REQUEST):
+			if (st->l3.l3m.state == ST_L3_LC_ESTAB) {
+				st->l3.l3l2(st, pr, arg);
+			} else {
+				struct sk_buff *skb = arg;
+
+				skb_queue_head(&st->l3.squeue, skb);
+				FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL); 
+			}
+			break;
+		case (DL_ESTABLISH | REQUEST):
+			FsmEvent(&st->l3.l3m, EV_ESTABLISH_REQ, NULL);
+			break;
+		case (DL_ESTABLISH | CONFIRM):
+			FsmEvent(&st->l3.l3m, EV_ESTABLISH_CNF, NULL);
+			break;
+		case (DL_ESTABLISH | INDICATION):
+			FsmEvent(&st->l3.l3m, EV_ESTABLISH_IND, NULL);
+			break;
+		case (DL_RELEASE | INDICATION):
+			FsmEvent(&st->l3.l3m, EV_RELEASE_IND, NULL);
+			break;
+		case (DL_RELEASE | CONFIRM):
+			FsmEvent(&st->l3.l3m, EV_RELEASE_CNF, NULL);
+			break;
+		case (DL_RELEASE | REQUEST):
+			FsmEvent(&st->l3.l3m, EV_RELEASE_REQ, NULL);
+			break;
+	}
+}
+
+HISAX_INITFUNC(void
+Isdnl3New(void))
+{
+	l3fsm.state_count = L3_STATE_COUNT;
+	l3fsm.event_count = L3_EVENT_COUNT;
+	l3fsm.strEvent = strL3Event;
+	l3fsm.strState = strL3State;
+	FsmNew(&l3fsm, L3FnList, L3_FN_COUNT);
+}
+
+void
+Isdnl3Free(void)
+{
+	FsmFree(&l3fsm);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isdnl3.h linux.pre11.3/drivers/isdn/hisax/isdnl3.h
--- linux.vanilla/drivers/isdn/hisax/isdnl3.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/isdnl3.h	Mon Jul 19 23:59:34 1999
@@ -1,6 +1,20 @@
-/* $Id: isdnl3.h,v 2.0 1997/07/27 21:15:42 keil Exp $
+/* $Id: isdnl3.h,v 2.4 1999/07/01 08:11:54 keil Exp $
 
  * $Log: isdnl3.h,v $
+ * Revision 2.4  1999/07/01 08:11:54  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.3  1998/11/15 23:55:06  keil
+ * changes from 2.0
+ *
+ * Revision 2.2  1998/05/25 14:10:17  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.1  1998/05/25 12:58:13  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 2.0  1997/07/27 21:15:42  keil
  * New Callref based layer3
  *
@@ -22,20 +36,23 @@
 #define SBIT(state) (1<<state)
 #define ALL_STATES  0x00ffffff
 
-#define	PROTO_DIS_EURO	0x08
+#define PROTO_DIS_EURO	0x08
 
 #define L3_DEB_WARN	0x01
-#define	L3_DEB_PROTERR	0x02
-#define	L3_DEB_STATE	0x04
-#define	L3_DEB_CHARGE	0x08
+#define L3_DEB_PROTERR	0x02
+#define L3_DEB_STATE	0x04
+#define L3_DEB_CHARGE	0x08
+#define L3_DEB_CHECK	0x10
+#define L3_DEB_SI	0x20
 
 struct stateentry {
 	int state;
-	u_char primitive;
+	int primitive;
 	void (*rout) (struct l3_process *, u_char, void *);
 };
 
-extern void l3_debug(struct PStack *st, char *s);
+#define l3_debug(st, fmt, args...) HiSax_putstatus(st->l1.hardware, "l3 ", fmt, ## args)
+
 extern void newl3state(struct l3_process *pc, int state);
 extern void L3InitTimer(struct l3_process *pc, struct L3Timer *t);
 extern void L3DelTimer(struct L3Timer *t);
@@ -45,3 +62,4 @@
 extern struct l3_process *new_l3_process(struct PStack *st, int cr);
 extern void release_l3_process(struct l3_process *p);
 extern struct l3_process *getl3proc(struct PStack *st, int cr);
+extern void l3_msg(struct PStack *st, int pr, void *arg);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/isurf.c linux.pre11.3/drivers/isdn/hisax/isurf.c
--- linux.vanilla/drivers/isdn/hisax/isurf.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/isurf.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,252 @@
+/* $Id: isurf.c,v 1.3 1999/07/12 21:05:18 keil Exp $
+
+ * isurf.c  low level stuff for Siemens I-Surf/I-Talk cards
+ *
+ * Author     Karsten Keil (keil@isdn4linux.de)
+ *
+ * $Log: isurf.c,v $
+ * Revision 1.3  1999/07/12 21:05:18  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:56  keil
+ * Initial version
+ *
+ *
+ *
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "isar.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+
+static const char *ISurf_revision = "$Revision: 1.3 $";
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+#define ISURF_ISAR_RESET	1
+#define ISURF_ISAC_RESET	2
+#define ISURF_ISAR_EA		4
+#define ISURF_ARCOFI_RESET	8
+#define ISURF_RESET (ISURF_ISAR_RESET | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET)
+
+#define ISURF_ISAR_OFFSET	0
+#define ISURF_ISAC_OFFSET	0x100
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readb(cs->hw.isurf.isac + offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writeb(value, cs->hw.isurf.isac + offset); mb();
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	register int i;
+	for (i = 0; i < size; i++)
+		data[i] = readb(cs->hw.isurf.isac);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	register int i;
+	for (i = 0; i < size; i++){
+		writeb(data[i], cs->hw.isurf.isac);mb();
+	}
+}
+
+/* ISAR access routines
+ * mode = 0 access with IRQ on
+ * mode = 1 access with IRQ off
+ * mode = 2 access with IRQ off and using last offset
+ */
+  
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
+{	
+	return(readb(cs->hw.isurf.isar + offset));
+}
+
+static void
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
+{
+	writeb(value, cs->hw.isurf.isar + offset);mb();
+}
+
+static void
+isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	int cnt = 5;
+
+	if (!cs) {
+		printk(KERN_WARNING "ISurf: Spurious interrupt!\n");
+		return;
+	}
+
+	val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
+      Start_ISAR:
+	if (val & ISAR_IRQSTA)
+		isar_int_main(cs);
+	val = readb(cs->hw.isurf.isac + ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readb(cs->hw.isurf.isar + ISAR_IRQBIT);
+	if ((val & ISAR_IRQSTA) && --cnt) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "ISAR IntStat after IntRoutine");
+		goto Start_ISAR;
+	}
+	val = readb(cs->hw.isurf.isac + ISAC_ISTA);
+	if (val && --cnt) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (!cnt)
+		printk(KERN_WARNING "ISurf IRQ LOOP\n");
+
+	writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
+	writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb();
+	writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb();
+	writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb();
+}
+
+void
+release_io_isurf(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.isurf.reset, 1);
+}
+
+static void
+reset_isurf(struct IsdnCardState *cs, u_char chips)
+{
+	long flags;
+
+	printk(KERN_INFO "ISurf: resetting card\n");
+
+	byteout(cs->hw.isurf.reset, chips); /* Reset On */
+	save_flags(flags);
+	sti();
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((10*HZ)/1000);
+	restore_flags(flags);
+}
+
+static int
+ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			reset_isurf(cs, ISURF_RESET);
+			return(0);
+		case CARD_RELEASE:
+			release_io_isurf(cs);
+			return(0);
+		case CARD_INIT:
+			clear_pending_isac_ints(cs);
+			writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb();
+			initisac(cs);
+			initisar(cs);
+			/* Reenable ISAC IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			/* RESET Receiver and Transmitter */
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
+			return(0);
+		case CARD_TEST:
+			return(0);
+		case CARD_LOAD_FIRM:
+			if (isar_load_firmware(cs, arg))
+				return(1);
+			ll_run(cs);
+			reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET |
+				ISURF_ARCOFI_RESET);
+			initisac(cs);
+			cs->writeisac(cs, ISAC_MASK, 0);
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
+			return(0);
+	}
+	return(0);
+}
+
+__initfunc(int
+setup_isurf(struct IsdnCard *card))
+{
+	int ver;
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, ISurf_revision);
+	printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp));
+	
+ 	if (cs->typ != ISDN_CTYPE_ISURF)
+ 		return(0);
+	if (card->para[1] && card->para[2]) {
+		cs->hw.isurf.reset = card->para[1];
+		cs->hw.isurf.isar = card->para[2] + ISURF_ISAR_OFFSET;
+		cs->hw.isurf.isac = card->para[2] + ISURF_ISAC_OFFSET;
+		cs->irq = card->para[0];
+	} else {
+		printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+			CardType[card->typ]);
+		return (0);
+	}
+	if (check_region(cs->hw.isurf.reset, 1)) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x already in use\n",
+			CardType[card->typ],
+			cs->hw.isurf.reset);
+			return (0);
+	} else {
+		request_region(cs->hw.isurf.reset, 1, "isurf isdn");
+	}
+
+	printk(KERN_INFO
+	       "ISurf: defined at 0x%x 0x%x IRQ %d\n",
+	       cs->hw.isurf.reset,
+	       cs->hw.isurf.isar,
+	       cs->irq);
+
+	cs->cardmsg = &ISurf_card_msg;
+	cs->irq_func = &isurf_interrupt;
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r;
+	cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r;
+	reset_isurf(cs, ISURF_RESET);
+	test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+	ISACVersion(cs, "ISurf:");
+	cs->BC_Read_Reg = &ReadISAR;
+	cs->BC_Write_Reg = &WriteISAR;
+	cs->BC_Send_Data = &isar_fill_fifo;
+	ver = ISARVersion(cs, "ISurf:");
+	if (ver < 0) {
+		printk(KERN_WARNING
+			"ISurf: wrong ISAR version (ret = %d)\n", ver);
+		release_io_isurf(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/ix1_micro.c linux.pre11.3/drivers/isdn/hisax/ix1_micro.c
--- linux.vanilla/drivers/isdn/hisax/ix1_micro.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/ix1_micro.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: ix1_micro.c,v 2.6 1998/02/11 17:28:09 keil Exp $
+/* $Id: ix1_micro.c,v 2.8 1999/07/12 21:05:19 keil Exp $
 
  * ix1_micro.c  low level stuff for ITK ix1-micro Rev.2 isdn cards
  *              derived from the original file teles3.c from Karsten Keil
@@ -11,6 +11,13 @@
  *              Beat Doebeli
  *
  * $Log: ix1_micro.c,v $
+ * Revision 2.8  1999/07/12 21:05:19  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.7  1998/04/15 16:44:31  keil
+ * new init code
+ *
  * Revision 2.6  1998/02/11 17:28:09  keil
  * Niccy PnP/PCI support
  *
@@ -81,7 +88,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.6 $";
+const char *ix1_revision = "$Revision: 2.8 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -196,7 +203,7 @@
 ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "IX1: Spurious interrupt!\n");
@@ -204,16 +211,12 @@
 	}
 	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -226,16 +229,12 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
-		writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
-	}
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0);
 }
 
 void
@@ -273,14 +272,8 @@
 		case CARD_RELEASE:
 			release_io_ix1micro(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &ix1micro_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -331,6 +324,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &ix1_card_msg;
+	cs->irq_func = &ix1micro_interrupt;
 	ISACVersion(cs, "ix1-Micro:");
 	if (HscxVersion(cs, "ix1-Micro:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/jade.c linux.pre11.3/drivers/isdn/hisax/jade.c
--- linux.vanilla/drivers/isdn/hisax/jade.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/jade.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,326 @@
+/* $Id: jade.c,v 1.2 1999/07/01 08:07:57 keil Exp $
+ *
+ * jade.c   JADE stuff (derived from original hscx.c)
+ *
+ * Author   Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: jade.c,v $
+ * Revision 1.2  1999/07/01 08:07:57  keil
+ * Initial version
+ *
+ *
+ */
+
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "hscx.h"
+#include "jade.h"
+#include "isdnl1.h"
+#include <linux/interrupt.h>
+
+
+HISAX_INITFUNC(int
+JadeVersion(struct IsdnCardState *cs, char *s))
+{
+    int ver,i;
+    int to = 50;
+    cs->BC_Write_Reg(cs, -1, 0x50, 0x19);
+    i=0;
+    while (to) {
+    	udelay(1);
+	ver = cs->BC_Read_Reg(cs, -1, 0x60);
+	to--;
+	if (ver)
+    	    break;
+	if (!to) {
+	    printk(KERN_INFO "%s JADE version not obtainable\n", s);
+    	    return (0);
+        }
+    }
+    /* Wait for the JADE */
+    udelay(10);
+    /* Read version */
+    ver = cs->BC_Read_Reg(cs, -1, 0x60);
+    printk(KERN_INFO "%s JADE version: %d\n", s, ver);
+    return (1);
+}
+
+/* Write to indirect accessible jade register set */
+static void
+jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
+{
+    int to = 50;
+    long flags;
+    u_char ret;
+    save_flags(flags);
+    cli();
+    /* Write the data */
+    cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value);
+    /* Say JADE we wanna write indirect reg 'reg' */
+    cs->BC_Write_Reg(cs, -1, COMM_JADE, reg);
+    to = 50;
+    /* Wait for RDY goes high */
+    while (to) {
+    	udelay(1);
+	ret = cs->BC_Read_Reg(cs, -1, COMM_JADE);
+	to--;
+	if (ret & 1)
+	    /* Got acknowledge */
+	    break;
+	if (!to) {
+	    restore_flags(flags);
+    	    printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value);
+	    return;
+	}
+    }
+    restore_flags(flags);
+}
+
+
+
+void
+modejade(struct BCState *bcs, int mode, int bc)
+{
+    struct IsdnCardState *cs = bcs->cs;
+    int jade = bcs->hw.hscx.hscx;
+
+    if (cs->debug & L1_DEB_HSCX) {
+	char tmp[40];
+	sprintf(tmp, "jade %c mode %d ichan %d",
+		'A' + jade, mode, bc);
+	debugl1(cs, tmp);
+    }
+    bcs->mode = mode;
+    bcs->channel = bc;
+	
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00));
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF));
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00);
+
+    jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08);
+    jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08);
+    jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00);
+    jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00);
+
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07);
+    cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07);
+
+    if (bc == 0) {
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00);
+    } else {
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04);
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04);
+    }
+    switch (mode) {
+	case (L1_MODE_NULL):
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO);
+		break;
+	case (L1_MODE_TRANS):
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC));
+		break;
+	case (L1_MODE_HDLC):
+		cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC));
+		break;
+    }
+    if (mode) {
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC));
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES);
+	/* Unmask ints */
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8);
+    }
+    else
+	/* Mask ints */
+	cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00);
+}
+
+void
+jade_sched_event(struct BCState *bcs, int event)
+{
+    bcs->event |= 1 << event;
+    queue_task(&bcs->tqueue, &tq_immediate);
+    mark_bh(IMMEDIATE_BH);
+}
+
+static void
+jade_l2l1(struct PStack *st, int pr, void *arg)
+{
+    struct sk_buff *skb = arg;
+    long flags;
+
+    switch (pr) {
+	case (PH_DATA | REQUEST):
+		save_flags(flags);
+		cli();
+		if (st->l1.bcs->tx_skb) {
+			skb_queue_tail(&st->l1.bcs->squeue, skb);
+			restore_flags(flags);
+		} else {
+			st->l1.bcs->tx_skb = skb;
+			test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			st->l1.bcs->hw.hscx.count = 0;
+			restore_flags(flags);
+			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+		}
+		break;
+	case (PH_PULL | INDICATION):
+		if (st->l1.bcs->tx_skb) {
+			printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n");
+			break;
+		}
+		test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+		st->l1.bcs->tx_skb = skb;
+		st->l1.bcs->hw.hscx.count = 0;
+		st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
+		break;
+	case (PH_PULL | REQUEST):
+		if (!st->l1.bcs->tx_skb) {
+		    test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		    st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
+		} else
+		    test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
+		break;
+	case (PH_ACTIVATE | REQUEST):
+		test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+		modejade(st->l1.bcs, st->l1.mode, st->l1.bc);
+		l1_msg_b(st, pr, arg);
+		break;
+	case (PH_DEACTIVATE | REQUEST):
+		l1_msg_b(st, pr, arg);
+		break;
+	case (PH_DEACTIVATE | CONFIRM):
+		test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+		test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+		modejade(st->l1.bcs, 0, st->l1.bc);
+		st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+		break;
+    }
+}
+
+void
+close_jadestate(struct BCState *bcs)
+{
+    modejade(bcs, 0, bcs->channel);
+    if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
+	if (bcs->hw.hscx.rcvbuf) {
+		kfree(bcs->hw.hscx.rcvbuf);
+		bcs->hw.hscx.rcvbuf = NULL;
+	}
+	if (bcs->blog) {
+		kfree(bcs->blog);
+		bcs->blog = NULL;
+	}
+	discard_queue(&bcs->rqueue);
+	discard_queue(&bcs->squeue);
+	if (bcs->tx_skb) {
+		idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+		bcs->tx_skb = NULL;
+		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	}
+    }
+}
+
+static int
+open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
+{
+	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
+		if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+			       "HiSax: No memory for hscx.rcvbuf\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			return (1);
+		}
+		if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
+			printk(KERN_WARNING
+				"HiSax: No memory for bcs->blog\n");
+			test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
+			kfree(bcs->hw.hscx.rcvbuf);
+			bcs->hw.hscx.rcvbuf = NULL;
+			return (2);
+		}
+		skb_queue_head_init(&bcs->rqueue);
+		skb_queue_head_init(&bcs->squeue);
+	}
+	bcs->tx_skb = NULL;
+	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+	bcs->event = 0;
+	bcs->hw.hscx.rcvidx = 0;
+	bcs->tx_cnt = 0;
+	return (0);
+}
+
+
+int
+setstack_jade(struct PStack *st, struct BCState *bcs)
+{
+	bcs->channel = st->l1.bc;
+	if (open_jadestate(st->l1.hardware, bcs))
+		return (-1);
+	st->l1.bcs = bcs;
+	st->l2.l2l1 = jade_l2l1;
+	setstack_manager(st);
+	bcs->st = st;
+	setstack_l1_B(st);
+	return (0);
+}
+
+HISAX_INITFUNC(void
+clear_pending_jade_ints(struct IsdnCardState *cs))
+{
+	int val;
+	char tmp[64];
+
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00);
+
+	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR);
+	sprintf(tmp, "jade B ISTA %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR);
+	sprintf(tmp, "jade A ISTA %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR);
+	sprintf(tmp, "jade B STAR %x", val);
+	debugl1(cs, tmp);
+	val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR);
+	sprintf(tmp, "jade A STAR %x", val);
+	debugl1(cs, tmp);
+	/* Unmask ints */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8);
+}
+
+HISAX_INITFUNC(void
+initjade(struct IsdnCardState *cs))
+{
+	cs->bcs[0].BC_SetStack = setstack_jade;
+	cs->bcs[1].BC_SetStack = setstack_jade;
+	cs->bcs[0].BC_Close = close_jadestate;
+	cs->bcs[1].BC_Close = close_jadestate;
+	cs->bcs[0].hw.hscx.hscx = 0;
+	cs->bcs[1].hw.hscx.hscx = 1;
+
+	/* Stop DSP audio tx/rx */
+	jade_write_indirect(cs, 0x11, 0x0f);
+	jade_write_indirect(cs, 0x17, 0x2f);
+
+	/* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO);
+	/* Power down, 1-Idle, RxTx least significant bit first */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00);
+	/* Mask all interrupts */
+	cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR,  0x00);
+	cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR,  0x00);
+	/* Setup host access to hdlc controller */
+	jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2));
+	/* Unmask HDLC int (don´t forget DSP int later on)*/
+	cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2));
+
+	/* once again TRANSPARENT */	
+	modejade(cs->bcs, 0, 0);
+	modejade(cs->bcs + 1, 0, 0);
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/jade.h linux.pre11.3/drivers/isdn/hisax/jade.h
--- linux.vanilla/drivers/isdn/hisax/jade.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/jade.h	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,137 @@
+/* $Id: jade.h,v 1.2 1999/07/01 08:07:58 keil Exp $
+ * jade.h   JADE specific defines
+ *
+ * Author   Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ *
+ * $Log: jade.h,v $
+ * Revision 1.2  1999/07/01 08:07:58  keil
+ * Initial version
+ *
+ *
+ */
+
+/* All Registers original Siemens Spec  */
+#ifndef	__JADE_H__
+#define	__JADE_H__
+
+/* Special registers for access to indirect accessible JADE regs */
+#define	DIRECT_IO_JADE	0x0000	/* Jade direct io access area */
+#define	COMM_JADE	0x0040	/* Jade communication area */	   	
+
+/********************************************************************/
+/* JADE-HDLC registers         									    */
+/********************************************************************/
+#define jade_HDLC_RFIFO	   				0x00				   /* R */
+#define jade_HDLC_XFIFO	   				0x00				   /* W */
+
+#define	jade_HDLC_STAR	   				0x20				   /* R */
+	#define	jadeSTAR_XDOV				0x80
+	#define	jadeSTAR_XFW 				0x40 /* Does not work*/
+	#define	jadeSTAR_XCEC 				0x20
+	#define	jadeSTAR_RCEC				0x10
+	#define	jadeSTAR_BSY 				0x08
+	#define	jadeSTAR_RNA 				0x04
+	#define	jadeSTAR_STR 				0x02
+	#define	jadeSTAR_STX				0x01
+
+#define	jade_HDLC_XCMD	   				0x20				   /* W */
+	#define	jadeXCMD_XF				0x80
+	#define	jadeXCMD_XME				0x40
+	#define	jadeXCMD_XRES				0x20
+	#define	jadeXCMD_STX				0x01
+
+#define	jade_HDLC_RSTA	   				0x21				   /* R */
+    #define	jadeRSTA_VFR				0x80
+    #define	jadeRSTA_RDO				0x40
+    #define	jadeRSTA_CRC				0x20
+    #define	jadeRSTA_RAB				0x10
+    #define	jadeRSTA_MASK			   	0xF0
+
+#define	jade_HDLC_MODE					0x22				   /* RW*/
+    #define	jadeMODE_TMO				0x80
+    #define	jadeMODE_RAC				0x40
+    #define	jadeMODE_XAC				0x20
+    #define	jadeMODE_TLP				0x10
+    #define	jadeMODE_ERFS				0x02
+    #define	jadeMODE_ETFS				0x01
+
+#define	jade_HDLC_RBCH					0x24				   /* R */
+
+#define	jade_HDLC_RBCL	 				0x25				   /* R */
+#define	jade_HDLC_RCMD	 				0x25				   /* W */
+	#define	jadeRCMD_RMC 				0x80
+	#define	jadeRCMD_RRES				0x40
+	#define	jadeRCMD_RMD				0x20
+	#define	jadeRCMD_STR				0x02
+
+#define	jade_HDLC_CCR0					0x26				   /* RW*/
+	#define	jadeCCR0_PU  				0x80
+	#define	jadeCCR0_ITF				0x40
+	#define	jadeCCR0_C32				0x20
+	#define	jadeCCR0_CRL				0x10
+	#define	jadeCCR0_RCRC				0x08
+	#define	jadeCCR0_XCRC				0x04
+	#define	jadeCCR0_RMSB				0x02
+	#define	jadeCCR0_XMSB				0x01
+
+#define	jade_HDLC_CCR1					0x27				   /* RW*/
+    #define	jadeCCR1_RCS0				0x80
+    #define	jadeCCR1_RCONT				0x40
+    #define	jadeCCR1_RFDIS				0x20
+    #define	jadeCCR1_XCS0				0x10
+    #define	jadeCCR1_XCONT				0x08
+    #define	jadeCCR1_XFDIS				0x04
+
+#define	jade_HDLC_TSAR					0x28				   /* RW*/
+#define	jade_HDLC_TSAX					0x29				   /* RW*/
+#define	jade_HDLC_RCCR					0x2A				   /* RW*/
+#define	jade_HDLC_XCCR					0x2B				   /* RW*/
+
+#define	jade_HDLC_ISR 					0x2C				   /* R */
+#define	jade_HDLC_IMR 					0x2C				   /* W */
+	#define	jadeISR_RME					0x80
+	#define	jadeISR_RPF					0x40
+	#define	jadeISR_RFO					0x20
+	#define	jadeISR_XPR					0x10
+	#define	jadeISR_XDU					0x08
+	#define	jadeISR_ALLS				0x04
+
+#define jade_INT            			0x75
+    #define jadeINT_HDLC1   			0x02
+    #define jadeINT_HDLC2   			0x01
+    #define jadeINT_DSP				0x04
+#define jade_INTR            			0x70
+
+/********************************************************************/
+/* Indirect accessible JADE registers of common interest		   	*/
+/********************************************************************/
+#define	jade_CHIPVERSIONNR				0x00 /* Does not work*/
+
+#define	jade_HDLCCNTRACCESS				0x10		
+	#define	jadeINDIRECT_HAH1			0x02
+	#define	jadeINDIRECT_HAH2			0x01
+
+#define	jade_HDLC1SERRXPATH				0x1D
+#define	jade_HDLC1SERTXPATH				0x1E
+#define	jade_HDLC2SERRXPATH				0x1F
+#define	jade_HDLC2SERTXPATH				0x20
+	#define	jadeINDIRECT_SLIN1			0x10
+	#define	jadeINDIRECT_SLIN0			0x08
+	#define	jadeINDIRECT_LMOD1			0x04
+	#define	jadeINDIRECT_LMOD0			0x02
+	#define	jadeINDIRECT_HHR			0x01
+	#define	jadeINDIRECT_HHX			0x01
+
+#define	jade_RXAUDIOCH1CFG				0x11
+#define	jade_RXAUDIOCH2CFG				0x14
+#define	jade_TXAUDIOCH1CFG				0x17
+#define	jade_TXAUDIOCH2CFG				0x1A
+
+extern int JadeVersion(struct IsdnCardState *cs, char *s);
+extern void jade_sched_event(struct BCState *bcs, int event);
+extern void modejade(struct BCState *bcs, int mode, int bc);
+extern void clear_pending_jade_ints(struct IsdnCardState *cs);
+extern void initjade(struct IsdnCardState *cs);
+
+#endif	/* __JADE_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/jade_irq.c linux.pre11.3/drivers/isdn/hisax/jade_irq.c
--- linux.vanilla/drivers/isdn/hisax/jade_irq.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/jade_irq.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,247 @@
+/* $Id: jade_irq.c,v 1.2 1999/07/01 08:07:59 keil Exp $
+ *
+ * jade_irq.c   Low level JADE IRQ stuff (derived from original hscx_irq.c)
+ *
+ * Author   Roland Klabunde (R.Klabunde@Berkom.de)
+ *
+ * $Log: jade_irq.c,v $
+ * Revision 1.2  1999/07/01 08:07:59  keil
+ * Initial version
+ *
+ *
+ */
+
+static inline void
+waitforCEC(struct IsdnCardState *cs, int jade, int reg)
+{
+  	int to = 50;
+  	int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC);
+  	while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) {
+  		udelay(1);
+  		to--;
+  	}
+  	if (!to)
+  		printk(KERN_WARNING "HiSax: waitforCEC (jade) timeout\n");
+}
+
+
+static inline void
+waitforXFW(struct IsdnCardState *cs, int jade)
+{
+  	/* Does not work on older jade versions, don't care */
+}
+
+static inline void
+WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	waitforCEC(cs, jade, reg);
+	WRITEJADE(cs, jade, reg, data);
+	restore_flags(flags);
+}
+
+
+
+static void
+jade_empty_fifo(struct BCState *bcs, int count)
+{
+	u_char *ptr;
+	struct IsdnCardState *cs = bcs->cs;
+	long flags;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "jade_empty_fifo");
+
+	if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
+		if (cs->debug & L1_DEB_WARN)
+			debugl1(cs, "jade_empty_fifo: incoming packet too large");
+		WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
+		bcs->hw.hscx.rcvidx = 0;
+		return;
+	}
+	ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
+	bcs->hw.hscx.rcvidx += count;
+	save_flags(flags);
+	cli();
+	READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC);
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "jade_empty_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+static void
+jade_fill_fifo(struct BCState *bcs)
+{
+	struct IsdnCardState *cs = bcs->cs;
+	int more, count;
+	int fifo_size = 32;
+	u_char *ptr;
+	long flags;
+
+	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+		debugl1(cs, "jade_fill_fifo");
+
+	if (!bcs->tx_skb)
+		return;
+	if (bcs->tx_skb->len <= 0)
+		return;
+
+	more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
+	if (bcs->tx_skb->len > fifo_size) {
+		more = !0;
+		count = fifo_size;
+	} else
+		count = bcs->tx_skb->len;
+
+	waitforXFW(cs, bcs->hw.hscx.hscx);
+	save_flags(flags);
+	cli();
+	ptr = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt -= count;
+	bcs->hw.hscx.count += count;
+	WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
+	WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME));
+	restore_flags(flags);
+	if (cs->debug & L1_DEB_HSCX_FIFO) {
+		char *t = bcs->blog;
+
+		t += sprintf(t, "jade_fill_fifo %c cnt %d",
+			     bcs->hw.hscx.hscx ? 'B' : 'A', count);
+		QuickHex(t, ptr, count);
+		debugl1(cs, bcs->blog);
+	}
+}
+
+
+static inline void
+jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade)
+{
+	u_char r;
+	struct BCState *bcs = cs->bcs + jade;
+	struct sk_buff *skb;
+	int fifo_size = 32;
+	int count;
+	int i_jade = (int) jade; /* To satisfy the compiler */
+	
+	if (!test_bit(BC_FLG_INIT, &bcs->Flag))
+		return;
+
+	if (val & 0x80) {	/* RME */
+		r = READJADE(cs, i_jade, jade_HDLC_RSTA);
+		if ((r & 0xf0) != 0xa0) {
+			if (!(r & 0x80))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "JADE %s invalid frame", (jade ? "B":"A"));
+			if ((r & 0x40) && bcs->mode)
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "JADE %c RDO mode=%d", 'A'+jade, bcs->mode);
+			if (!(r & 0x20))
+				if (cs->debug & L1_DEB_WARN)
+					debugl1(cs, "JADE %c CRC error", 'A'+jade);
+			WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC);
+		} else {
+			count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F;
+			if (count == 0)
+				count = fifo_size;
+			jade_empty_fifo(bcs, count);
+			if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
+				if (cs->debug & L1_DEB_HSCX_FIFO)
+					debugl1(cs, "HX Frame %d", count);
+				if (!(skb = dev_alloc_skb(count)))
+					printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A"));
+				else {
+					SET_SKB_FREE(skb);
+					memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
+					skb_queue_tail(&bcs->rqueue, skb);
+				}
+			}
+		}
+		bcs->hw.hscx.rcvidx = 0;
+		jade_sched_event(bcs, B_RCVBUFREADY);
+	}
+	if (val & 0x40) {	/* RPF */
+		jade_empty_fifo(bcs, fifo_size);
+		if (bcs->mode == L1_MODE_TRANS) {
+			/* receive audio data */
+			if (!(skb = dev_alloc_skb(fifo_size)))
+				printk(KERN_WARNING "HiSax: receive out of memory\n");
+			else {
+				SET_SKB_FREE(skb);
+				memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
+				skb_queue_tail(&bcs->rqueue, skb);
+			}
+			bcs->hw.hscx.rcvidx = 0;
+			jade_sched_event(bcs, B_RCVBUFREADY);
+		}
+	}
+	if (val & 0x10) {	/* XPR */
+		if (bcs->tx_skb) {
+			if (bcs->tx_skb->len) {
+				jade_fill_fifo(bcs);
+				return;
+			} else {
+				if (bcs->st->lli.l1writewakeup &&
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				bcs->hw.hscx.count = 0;
+				bcs->tx_skb = NULL;
+			}
+		}
+		if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
+			bcs->hw.hscx.count = 0;
+			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
+			jade_fill_fifo(bcs);
+		} else {
+			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
+			jade_sched_event(bcs, B_XMTBUFREADY);
+		}
+	}
+}
+
+static inline void
+jade_int_main(struct IsdnCardState *cs, u_char val, int jade)
+{
+	struct BCState *bcs;
+	bcs = cs->bcs + jade;
+	
+	if (val & jadeISR_RFO) {
+		/* handled with RDO */
+		val &= ~jadeISR_RFO;
+	}
+	if (val & jadeISR_XDU) {
+		/* relevant in HDLC mode only */
+		/* don't reset XPR here */
+		if (bcs->mode == 1)
+			jade_fill_fifo(bcs);
+		else {
+			/* Here we lost an TX interrupt, so
+			   * restart transmitting the whole frame.
+			 */
+			if (bcs->tx_skb) {
+			   	skb_push(bcs->tx_skb, bcs->hw.hscx.count);
+				bcs->tx_cnt += bcs->hw.hscx.count;
+				bcs->hw.hscx.count = 0;
+			}
+			WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES);
+			if (cs->debug & L1_DEB_WARN)
+				debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val);
+		}
+	}
+	if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "JADE %c interrupt %x", 'A'+jade, val);
+		jade_interrupt(cs, val, jade);
+	}
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3_1tr6.c linux.pre11.3/drivers/isdn/hisax/l3_1tr6.c
--- linux.vanilla/drivers/isdn/hisax/l3_1tr6.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/l3_1tr6.c	Mon Jul 19 23:59:34 1999
@@ -1,11 +1,32 @@
-/* $Id: l3_1tr6.c,v 2.4 1998/02/12 23:07:57 keil Exp $
+/* $Id: l3_1tr6.c,v 2.9 1999/07/01 08:11:55 keil Exp $
 
  *  German 1TR6 D-channel protocol
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
+ *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
  *
  *
  * $Log: l3_1tr6.c,v $
+ * Revision 2.9  1999/07/01 08:11:55  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.8  1998/11/15 23:55:08  keil
+ * changes from 2.0
+ *
+ * Revision 2.7  1998/08/13 23:36:45  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.6  1998/05/25 14:10:18  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.5  1998/05/25 12:58:14  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
  * Revision 2.4  1998/02/12 23:07:57  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -38,7 +59,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.4 $";
+const char *l3_1tr6_revision = "$Revision: 2.9 $";
 
 #define MsgHead(ptr, cref, mty, dis) \
 	*ptr++ = dis; \
@@ -56,66 +77,34 @@
 		return;
 	p = skb_put(skb, 4);
 	MsgHead(p, pc->callref, mt, pd);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 }
 
-static int
-l31tr6_check_messagetype_validity(int mt, int pd) {
-/* verify if a message type exists */
-
-	if (pd == PROTO_DIS_N0)
-		switch(mt) {
-		   case MT_N0_REG_IND:
-		   case MT_N0_CANC_IND:
-		   case MT_N0_FAC_STA:
-		   case MT_N0_STA_ACK:
-		   case MT_N0_STA_REJ:
-		   case MT_N0_FAC_INF:
-		   case MT_N0_INF_ACK:
-		   case MT_N0_INF_REJ:
-		   case MT_N0_CLOSE:
-		   case MT_N0_CLO_ACK:
-			return(1);
-		   default:
-			return(0);
-		}
-	else if (pd == PROTO_DIS_N1)
-		switch(mt) {
-		   case MT_N1_ESC:
-		   case MT_N1_ALERT:
-		   case MT_N1_CALL_SENT:
-		   case MT_N1_CONN:
-		   case MT_N1_CONN_ACK:
-		   case MT_N1_SETUP:
-		   case MT_N1_SETUP_ACK:
-		   case MT_N1_RES:
-		   case MT_N1_RES_ACK:
-		   case MT_N1_RES_REJ:
-		   case MT_N1_SUSP:
-		   case MT_N1_SUSP_ACK:
-		   case MT_N1_SUSP_REJ:
-		   case MT_N1_USER_INFO:
-		   case MT_N1_DET:
-		   case MT_N1_DISC:
-		   case MT_N1_REL:
-		   case MT_N1_REL_ACK:
-		   case MT_N1_CANC_ACK:
-		   case MT_N1_CANC_REJ:
-		   case MT_N1_CON_CON:
-		   case MT_N1_FAC:
-		   case MT_N1_FAC_ACK:
-		   case MT_N1_FAC_CAN:
-		   case MT_N1_FAC_REG:
-		   case MT_N1_FAC_REJ:
-		   case MT_N1_INFO:
-		   case MT_N1_REG_ACK:
-		   case MT_N1_REG_REJ:
-		   case MT_N1_STAT:
-		   	return (1);
-		   default:
-		   	return(0);
-		}
-	return(0);
+static void
+l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
+{
+	StopAllL3Timer(pc);
+	newl3state(pc, 19);
+	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
+	L3AddTimer(&pc->timer, T308, CC_T308_1);
+}
+
+static void
+l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+
+	idev_kfree_skb(skb, FREE_READ);
+	l3_1tr6_release_req(pc, 0, NULL);
+}
+
+static void
+l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb)
+{
+	idev_kfree_skb(skb, FREE_READ);
+	if (pc->st->l3.debug & L3_DEB_WARN)
+		l3_debug(pc->st, msg);
+	l3_1tr6_release_req(pc, 0, NULL);
 }
 
 static void
@@ -204,7 +193,7 @@
 	L3DelTimer(&pc->timer);
 	L3AddTimer(&pc->timer, T303, CC_T303);
 	newl3state(pc, 1);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 }
 
 static void
@@ -220,17 +209,29 @@
 	/* Channel Identification */
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		bcfound++;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without bchannel");
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "setup wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "setup wrong WE0_chanID", skb);
+			return;
+		}
+		if ((pc->para.bchannel = p[2] & 0x3))
+				bcfound++;
+	} else {
+		l3_1tr6_error(pc, "missing setup chanID", skb);
+		return;
+	}
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE6_serviceInd, 6))) {
 		pc->para.setup.si1 = p[2];
 		pc->para.setup.si2 = p[3];
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without service indicator");
+	} else {
+		l3_1tr6_error(pc, "missing setup SI", skb);
+		return;
+	}
 
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_destAddr, 0)))
@@ -250,7 +251,7 @@
 		if ((FAC_SPV == p[3]) || (FAC_Activate == p[3]))
 			pc->para.spv = 1;
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 
 	/* Signal all services, linklevel takes care of Service-Indicator */
 	if (bcfound) {
@@ -261,7 +262,7 @@
 			l3_debug(pc->st, tmp);
 		}
 		newl3state(pc, 6);
-		pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL);
+		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 	} else
 		release_l3_process(pc);
 }
@@ -276,12 +277,22 @@
 	p = skb->data;
 	newl3state(pc, 2);
 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "setup_ack wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "setup_ack wrong WE0_chanID", skb);
+			return;
+		}
 		pc->para.bchannel = p[2] & 0x3;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
-	dev_kfree_skb(skb);
+	} else {
+		l3_1tr6_error(pc, "missing setup_ack WE0_chanID", skb);
+		return;
+	}
+	idev_kfree_skb(skb, FREE_READ);
 	L3AddTimer(&pc->timer, T304, CC_T304);
-	pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
@@ -293,13 +304,27 @@
 	L3DelTimer(&pc->timer);
 	p = skb->data;
 	if ((p = findie(p, skb->len, WE0_chanID, 0))) {
+		if (p[1] != 1) {
+			l3_1tr6_error(pc, "call sent wrong chanID len", skb);
+			return;
+		}
+		if ((p[2] & 0xf4) != 0x80) {
+			l3_1tr6_error(pc, "call sent wrong WE0_chanID", skb);
+			return;
+		}
+		if ((pc->state == 2) && (pc->para.bchannel != (p[2] & 0x3))) {
+			l3_1tr6_error(pc, "call sent wrong chanID value", skb);
+			return;
+		}
 		pc->para.bchannel = p[2] & 0x3;
-	} else if (pc->st->l3.debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
-	dev_kfree_skb(skb);
+	} else {
+		l3_1tr6_error(pc, "missing call sent WE0_chanID", skb);
+		return;
+	}
+	idev_kfree_skb(skb, FREE_READ);
 	L3AddTimer(&pc->timer, T310, CC_T310);
 	newl3state(pc, 3);
-	pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
@@ -307,10 +332,10 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
-	pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
@@ -330,7 +355,7 @@
 		}
 		if (tmpcharge > pc->para.chargeinfo) {
 			pc->para.chargeinfo = tmpcharge;
-			pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -338,7 +363,7 @@
 		}
 	} else if (pc->st->l3.debug & L3_DEB_CHARGE)
 		l3_debug(pc->st, "charging info not found");
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 
 }
 
@@ -347,7 +372,7 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 }
 
 static void
@@ -356,10 +381,14 @@
 	struct sk_buff *skb = arg;
 
 	L3DelTimer(&pc->timer);	/* T310 */
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connect date", skb);
+		return;
+	}
 	newl3state(pc, 10);
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	pc->para.chargeinfo = 0;
-	pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
 static void
@@ -380,13 +409,16 @@
 			pc->para.cause = 0;
 			pc->para.loc = 0;
 		}
-	} else
-		pc->para.cause = -1;
-	dev_kfree_skb(skb);
+	} else {
+		pc->para.cause = NO_CAUSE;
+		l3_1tr6_error(pc, "missing REL cause", skb);
+		return;
+	}
+	idev_kfree_skb(skb, FREE_READ);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
 	l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1);
-	pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	release_l3_process(pc);
 }
 
@@ -395,11 +427,11 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 	StopAllL3Timer(pc);
 	newl3state(pc, 0);
-	pc->para.cause = -1;
-	pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL);
+	pc->para.cause = NO_CAUSE;
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
 	release_l3_process(pc);
 }
 
@@ -421,7 +453,7 @@
 		}
 		if (tmpcharge > pc->para.chargeinfo) {
 			pc->para.chargeinfo = tmpcharge;
-			pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
+			pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc);
 		}
 		if (pc->st->l3.debug & L3_DEB_CHARGE) {
 			sprintf(tmp, "charging info %d", pc->para.chargeinfo);
@@ -446,11 +478,15 @@
 	} else {
 		if (pc->st->l3.debug & L3_DEB_WARN)
 			l3_debug(pc->st, "cause not found");
-		pc->para.cause = -1;
+		pc->para.cause = NO_CAUSE;
 	}
-	dev_kfree_skb(skb);
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connack date", skb);
+		return;
+	}
+	idev_kfree_skb(skb, FREE_READ);
 	newl3state(pc, 12);
-	pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
 }
 
 
@@ -459,11 +495,15 @@
 {
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
+	if (!findie(skb->data, skb->len, WE6_date, 6)) {
+		l3_1tr6_error(pc, "missing connack date", skb);
+		return;
+	}
+	idev_kfree_skb(skb, FREE_READ);
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
 }
 
 static void
@@ -502,7 +542,7 @@
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3DelTimer(&pc->timer);
 	L3AddTimer(&pc->timer, T313, CC_T313);
 }
@@ -530,6 +570,9 @@
 		case 0x10:
 			clen = 0;
 			break;
+                case 0x11:
+                        cause = CAUSE_UserBusy;
+                        break;
 		case 0x15:
 			cause = CAUSE_CallRejected;
 			break;
@@ -545,20 +588,11 @@
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3AddTimer(&pc->timer, T305, CC_T305);
 }
 
 static void
-l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg)
-{
-	StopAllL3Timer(pc);
-	newl3state(pc, 19);
-	l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1);
-	L3AddTimer(&pc->timer, T308, CC_T308_1);
-}
-
-static void
 l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
@@ -567,8 +601,8 @@
 		l3_1tr6_setup_req(pc, pr, arg);
 	} else {
 		L3DelTimer(&pc->timer);
-		pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL);
-		release_l3_process(pc);
+		pc->para.cause = 0;
+		l3_1tr6_disconnect_req(pc, 0, NULL);
 	}
 }
 
@@ -578,7 +612,7 @@
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
@@ -592,7 +626,7 @@
 	u_char clen = 1;
 
 	L3DelTimer(&pc->timer);
-	if (pc->para.cause > 0)
+	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
 	/* Map DSS1 causes */
 	switch (cause & 0x7f) {
@@ -613,7 +647,7 @@
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
@@ -623,7 +657,7 @@
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
@@ -632,7 +666,7 @@
 	L3DelTimer(&pc->timer);
 	pc->para.cause = 0xE6;
 	l3_1tr6_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
 
 static void
@@ -648,29 +682,45 @@
 l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
 	release_l3_process(pc);
 }
+
+static void
+l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg)
+{
+        pc->para.cause = CAUSE_LocalProcErr;
+        l3_1tr6_disconnect_req(pc, pr, NULL);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
+}
+
+static void
+l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg)
+{
+        newl3state(pc, 0);
+        pc->para.cause = 0x1b;          /* Destination out of order */
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+        release_l3_process(pc);
+}
+
 /* *INDENT-OFF* */
 static struct stateentry downstl[] =
 {
 	{SBIT(0),
-	 CC_SETUP_REQ, l3_1tr6_setup_req},
+	 CC_SETUP | REQUEST, l3_1tr6_setup_req},
    	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) |
     	 SBIT(10),
-    	 CC_DISCONNECT_REQ, l3_1tr6_disconnect_req},
+    	 CC_DISCONNECT | REQUEST, l3_1tr6_disconnect_req},
 	{SBIT(12),
-	 CC_RELEASE_REQ, l3_1tr6_release_req},
-	{ALL_STATES,
-	 CC_DLRL, l3_1tr6_reset},
+	 CC_RELEASE | REQUEST, l3_1tr6_release_req},
 	{SBIT(6),
-	 CC_IGNORE, l3_1tr6_reset},
+	 CC_IGNORE | REQUEST, l3_1tr6_reset},
 	{SBIT(6),
-	 CC_REJECT_REQ, l3_1tr6_disconnect_req},
+	 CC_REJECT | REQUEST, l3_1tr6_disconnect_req},
 	{SBIT(6),
-	 CC_ALERTING_REQ, l3_1tr6_alert_req},
+	 CC_ALERTING | REQUEST, l3_1tr6_alert_req},
 	{SBIT(6) | SBIT(7),
-	 CC_SETUP_RSP, l3_1tr6_setup_rsp},
+	 CC_SETUP | RESPONSE, l3_1tr6_setup_rsp},
 	{SBIT(1),
 	 CC_T303, l3_1tr6_t303},
 	{SBIT(2),
@@ -687,12 +737,14 @@
 	 CC_T308_2, l3_1tr6_t308_2},
 };
 
-static int downstl_len = sizeof(downstl) /
-sizeof(struct stateentry);
+#define DOWNSTL_LEN \
+	(sizeof(downstl) / sizeof(struct stateentry))
 
 static struct stateentry datastln1[] =
 {
 	{SBIT(0),
+	 MT_N1_INVALID, l3_1tr6_invalid},
+	{SBIT(0),
 	 MT_N1_SETUP, l3_1tr6_setup},
 	{SBIT(1),
 	 MT_N1_SETUP_ACK, l3_1tr6_setup_ack},
@@ -711,18 +763,31 @@
 	{SBIT(10),
 	 MT_N1_INFO, l3_1tr6_info},
 	{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
-	 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
+	 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
 	 MT_N1_REL, l3_1tr6_rel},
 	{SBIT(19),
+	 MT_N1_REL, l3_1tr6_rel_ack},
+	{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) |
+	 SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17),
+	 MT_N1_REL_ACK, l3_1tr6_invalid},
+	{SBIT(19),
 	 MT_N1_REL_ACK, l3_1tr6_rel_ack}
 };
-/* *INDENT-ON* */
-
 
+#define DATASTLN1_LEN \
+	(sizeof(datastln1) / sizeof(struct stateentry))
 
-
-static int datastln1_len = sizeof(datastln1) /
-sizeof(struct stateentry);
+static struct stateentry manstatelist[] =
+{
+        {SBIT(2),
+         DL_ESTABLISH | INDICATION, l3_1tr6_dl_reset},
+        {ALL_STATES,
+         DL_RELEASE | INDICATION, l3_1tr6_dl_release},
+};
+ 
+#define MANSLLEN \
+        (sizeof(manstatelist) / sizeof(struct stateentry))
+/* *INDENT-ON* */
 
 static void
 up1tr6(struct PStack *st, int pr, void *arg)
@@ -732,22 +797,34 @@
 	struct sk_buff *skb = arg;
 	char tmp[80];
 
+	switch (pr) {
+		case (DL_DATA | INDICATION):
+		case (DL_UNIT_DATA | INDICATION):
+			break;
+		case (DL_ESTABLISH | CONFIRM):
+		case (DL_ESTABLISH | INDICATION):
+		case (DL_RELEASE | INDICATION):
+		case (DL_RELEASE | CONFIRM):
+			l3_msg(st, pr, arg);
+			return;
+			break;
+	}
 	if (skb->len < 4) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
 			sprintf(tmp, "up1tr6 len only %d", skb->len);
 			l3_debug(st, tmp);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	if ((skb->data[0] & 0xfe) != PROTO_DIS_N0) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
 			sprintf(tmp, "up1tr6%sunexpected discriminator %x message len %d",
-				(pr == DL_DATA) ? " " : "(broadcast) ",
+				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				skb->data[0], skb->len);
 			l3_debug(st, tmp);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	if (skb->data[1] != 1) {
@@ -755,43 +832,62 @@
 			sprintf(tmp, "up1tr6 CR len not 1");
 			l3_debug(st, tmp);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	cr = skb->data[2];
 	mt = skb->data[3];
 	if (skb->data[0] == PROTO_DIS_N0) {
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		if (st->l3.debug & L3_DEB_STATE) {
 			sprintf(tmp, "up1tr6%s N0 mt %x unhandled",
-			     (pr == DL_DATA) ? " " : "(broadcast) ", mt);
+			     (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ", mt);
 			l3_debug(st, tmp);
 		}
 	} else if (skb->data[0] == PROTO_DIS_N1) {
 		if (!(proc = getl3proc(st, cr))) {
-			if ((mt == MT_N1_SETUP) && (cr < 128)) {
+			if (mt == MT_N1_SETUP) { 
+				if (cr < 128) {
+					if (!(proc = new_l3_process(st, cr))) {
+						if (st->l3.debug & L3_DEB_PROTERR) {
+							sprintf(tmp, "up1tr6 no roc mem");
+							l3_debug(st, tmp);
+						}
+						idev_kfree_skb(skb, FREE_READ);
+						return;
+					}
+				} else {
+					idev_kfree_skb(skb, FREE_READ);
+					return;
+				}
+			} else if ((mt == MT_N1_REL) || (mt == MT_N1_REL_ACK) ||
+				(mt == MT_N1_CANC_ACK) || (mt == MT_N1_CANC_REJ) ||
+				(mt == MT_N1_REG_ACK) || (mt == MT_N1_REG_REJ) ||
+				(mt == MT_N1_SUSP_ACK) || (mt == MT_N1_RES_REJ) ||
+				(mt == MT_N1_INFO)) {
+				idev_kfree_skb(skb, FREE_READ);
+				return;
+			} else {
 				if (!(proc = new_l3_process(st, cr))) {
 					if (st->l3.debug & L3_DEB_PROTERR) {
 						sprintf(tmp, "up1tr6 no roc mem");
 						l3_debug(st, tmp);
 					}
-					dev_kfree_skb(skb);
+					idev_kfree_skb(skb, FREE_READ);
 					return;
 				}
-			} else {
-				dev_kfree_skb(skb);
-				return;
+				mt = MT_N1_INVALID;
 			}
 		}
-		for (i = 0; i < datastln1_len; i++)
+		for (i = 0; i < DATASTLN1_LEN; i++)
 			if ((mt == datastln1[i].primitive) &&
 			    ((1 << proc->state) & datastln1[i].state))
 				break;
-		if (i == datastln1_len) {
-			dev_kfree_skb(skb);
+		if (i == DATASTLN1_LEN) {
+			idev_kfree_skb(skb, FREE_READ);
 			if (st->l3.debug & L3_DEB_STATE) {
 				sprintf(tmp, "up1tr6%sstate %d mt %x unhandled",
-				  (pr == DL_DATA) ? " " : "(broadcast) ",
+				  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 					proc->state, mt);
 				l3_debug(st, tmp);
 			}
@@ -799,7 +895,7 @@
 		} else {
 			if (st->l3.debug & L3_DEB_STATE) {
 				sprintf(tmp, "up1tr6%sstate %d mt %x",
-				  (pr == DL_DATA) ? " " : "(broadcast) ",
+				  (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 					proc->state, mt);
 				l3_debug(st, tmp);
 			}
@@ -816,7 +912,10 @@
 	struct Channel *chan;
 	char tmp[80];
 
-	if (CC_SETUP_REQ == pr) {
+	if ((DL_ESTABLISH | REQUEST)== pr) {
+		l3_msg(st, pr, NULL);
+		return;
+	} else if ((CC_SETUP | REQUEST) == pr) {
 		chan = arg;
 		cr = newcallref();
 		cr |= 0x80;
@@ -832,11 +931,11 @@
 		proc = arg;
 	}
 
-	for (i = 0; i < downstl_len; i++)
+	for (i = 0; i < DOWNSTL_LEN; i++)
 		if ((pr == downstl[i].primitive) &&
 		    ((1 << proc->state) & downstl[i].state))
 			break;
-	if (i == downstl_len) {
+	if (i == DOWNSTL_LEN) {
 		if (st->l3.debug & L3_DEB_STATE) {
 			sprintf(tmp, "down1tr6 state %d prim %d unhandled",
 				proc->state, pr);
@@ -852,6 +951,34 @@
 	}
 }
 
+static void
+man1tr6(struct PStack *st, int pr, void *arg)
+{
+        int i;
+        struct l3_process *proc = arg;
+ 
+        if (!proc) {
+                printk(KERN_ERR "HiSax man1tr6 without proc pr=%04x\n", pr);
+                return;
+        }
+        for (i = 0; i < MANSLLEN; i++)
+                if ((pr == manstatelist[i].primitive) &&
+                    ((1 << proc->state) & manstatelist[i].state))
+                        break;
+        if (i == MANSLLEN) {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d man1tr6 state %d prim %d unhandled",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+        } else {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d man1tr6 state %d prim %d",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+                manstatelist[i].rout(proc, pr, arg);
+        }
+}
+ 
 void
 setstack_1tr6(struct PStack *st)
 {
@@ -859,6 +986,7 @@
 
 	st->lli.l4l3 = down1tr6;
 	st->l2.l2l3 = up1tr6;
+	st->l3.l3ml3 = man1tr6;
 	st->l3.N303 = 0;
 
 	strcpy(tmp, l3_1tr6_revision);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3_1tr6.h linux.pre11.3/drivers/isdn/hisax/l3_1tr6.h
--- linux.vanilla/drivers/isdn/hisax/l3_1tr6.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/l3_1tr6.h	Mon Jul 19 23:59:34 1999
@@ -1,8 +1,11 @@
-/* $Id: l3_1tr6.h,v 2.0 1997/07/27 21:15:47 keil Exp $
+/* $Id: l3_1tr6.h,v 2.1 1998/08/13 23:36:48 keil Exp $
  *
  *  German 1TR6 D-channel protocol defines
  *
  * $Log: l3_1tr6.h,v $
+ * Revision 2.1  1998/08/13 23:36:48  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
  * Revision 2.0  1997/07/27 21:15:47  keil
  * New Callref based layer3
  *
@@ -64,6 +67,7 @@
 #define MT_N1_REG_ACK 0x6C
 #define MT_N1_REG_REJ 0x6F
 #define MT_N1_STAT 0x63
+#define MT_N1_INVALID 0
 
 /*
  * W Elemente
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3dss1.c linux.pre11.3/drivers/isdn/hisax/l3dss1.c
--- linux.vanilla/drivers/isdn/hisax/l3dss1.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/l3dss1.c	Mon Jul 19 23:59:34 1999
@@ -1,14 +1,42 @@
-/* $Id: l3dss1.c,v 2.7 1998/02/12 23:08:01 keil Exp $
+/* $Id: l3dss1.c,v 2.14 1999/07/09 08:30:08 keil Exp $
 
  * EURO/DSS1 D-channel protocol
  *
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
  * Thanks to    Jan den Ouden
  *              Fritz Elfert
  *
  * $Log: l3dss1.c,v $
+ * Revision 2.14  1999/07/09 08:30:08  keil
+ * cosmetics
+ *
+ * Revision 2.13  1999/07/01 08:11:58  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.12  1998/11/15 23:55:10  keil
+ * changes from 2.0
+ *
+ * Revision 2.11  1998/08/13 23:36:51  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 2.10  1998/05/25 14:10:20  keil
+ * HiSax 3.0
+ * X.75 and leased are working again.
+ *
+ * Revision 2.9  1998/05/25 12:58:17  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8  1998/03/19 13:18:47  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
  * Revision 2.7  1998/02/12 23:08:01  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -50,119 +78,349 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.7 $";
+const char *dss1_revision = "$Revision: 2.14 $";
 
 #define EXT_BEARER_CAPS 1
 
 #define	MsgHead(ptr, cref, mty) \
 	*ptr++ = 0x8; \
-	*ptr++ = 0x1; \
-	*ptr++ = cref^0x80; \
+	if (cref == -1) { \
+		*ptr++ = 0x0; \
+	} else { \
+		*ptr++ = 0x1; \
+		*ptr++ = cref^0x80; \
+	} \
 	*ptr++ = mty
 
 
-#ifdef HISAX_DE_AOC
+/**********************************************/
+/* get a new invoke id for remote operations. */
+/* Only a return value != 0 is valid          */
+/**********************************************/
+static unsigned char new_invoke_id(struct PStack *p)
+{
+	unsigned char retval;
+	int flags,i;
+  
+	i = 32; /* maximum search depth */
+
+	save_flags(flags);
+	cli();
+
+	retval = p->prot.dss1.last_invoke_id + 1; /* try new id */
+	while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) {
+		p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8;
+		i--;
+	}  
+	if (i) {
+		while (p->prot.dss1.invoke_used[retval >> 3] & (1 << (retval & 7)))
+		retval++; 
+	} else
+		retval = 0;
+	p->prot.dss1.last_invoke_id = retval;
+	p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7));
+	restore_flags(flags);
+
+	return(retval);  
+} /* new_invoke_id */
+
+/*************************/
+/* free a used invoke id */
+/*************************/
+static void free_invoke_id(struct PStack *p, unsigned char id)
+{ int flags;
+
+  if (!id) return; /* 0 = invalid value */
+
+  save_flags(flags);
+  cli();
+  p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7));
+  restore_flags(flags);
+} /* free_invoke_id */  
+
+
+/**********************************************************/
+/* create a new l3 process and fill in dss1 specific data */
+/**********************************************************/
+static struct l3_process
+*dss1_new_l3_process(struct PStack *st, int cr)
+{  struct l3_process *proc;
+
+   if (!(proc = new_l3_process(st, cr))) 
+     return(NULL);
+
+   proc->prot.dss1.invoke_id = 0;
+   proc->prot.dss1.remote_operation = 0;
+   proc->prot.dss1.uus1_data[0] = '\0';
+   
+   return(proc);
+} /* dss1_new_l3_process */
+
+/************************************************/
+/* free a l3 process and all dss1 specific data */
+/************************************************/ 
+static void
+dss1_release_l3_process(struct l3_process *p)
+{
+   free_invoke_id(p->st,p->prot.dss1.invoke_id);
+   release_l3_process(p);
+} /* dss1_release_l3_process */
+ 
+/********************************************************/
+/* search a process with invoke id id and dummy callref */
+/********************************************************/
+static struct l3_process *
+l3dss1_search_dummy_proc(struct PStack *st, int id)
+{ struct l3_process *pc = st->l3.proc; /* start of processes */
+
+  if (!id) return(NULL);
+
+  while (pc)
+   { if ((pc->callref == -1) && (pc->prot.dss1.invoke_id == id))
+       return(pc);
+     pc = pc->next;
+   } 
+  return(NULL);
+} /* l3dss1_search_dummy_proc */
+
+/*******************************************************************/
+/* called when a facility message with a dummy callref is received */
+/* and a return result is delivered. id specifies the invoke id.   */
+/*******************************************************************/ 
+static void 
+l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs;
+  struct l3_process *pc = NULL; 
+
+  if ((pc = l3dss1_search_dummy_proc(st, id)))
+   { L3DelTimer(&pc->timer); /* remove timer */
+
+     cs = pc->st->l1.hardware;
+     ic.driver = cs->myid;
+     ic.command = ISDN_STAT_PROT;
+     ic.arg = DSS1_STAT_INVOKE_RES;
+     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
+     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
+     ic.parm.dss1_io.proc = pc->prot.dss1.proc;
+     ic.parm.dss1_io.timeout= 0;
+     ic.parm.dss1_io.datalen = nlen;
+     ic.parm.dss1_io.data = p;
+     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
+     pc->prot.dss1.invoke_id = 0; /* reset id */
+
+     cs->iif.statcallb(&ic);
+     dss1_release_l3_process(pc); 
+   }
+  else
+   l3_debug(st, "dummy return result id=0x%x result len=%d",id,nlen);
+} /* l3dss1_dummy_return_result */
+
+/*******************************************************************/
+/* called when a facility message with a dummy callref is received */
+/* and a return error is delivered. id specifies the invoke id.    */
+/*******************************************************************/ 
+static void 
+l3dss1_dummy_error_return(struct PStack *st, int id, ulong error)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs;
+  struct l3_process *pc = NULL; 
+
+  if ((pc = l3dss1_search_dummy_proc(st, id)))
+   { L3DelTimer(&pc->timer); /* remove timer */
+
+     cs = pc->st->l1.hardware;
+     ic.driver = cs->myid;
+     ic.command = ISDN_STAT_PROT;
+     ic.arg = DSS1_STAT_INVOKE_ERR;
+     ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
+     ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
+     ic.parm.dss1_io.proc = pc->prot.dss1.proc;
+     ic.parm.dss1_io.timeout= error;
+     ic.parm.dss1_io.datalen = 0;
+     ic.parm.dss1_io.data = NULL;
+     free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
+     pc->prot.dss1.invoke_id = 0; /* reset id */
+
+     cs->iif.statcallb(&ic);
+     dss1_release_l3_process(pc); 
+   }
+  else
+   l3_debug(st, "dummy return error id=0x%x error=0x%lx",id,error);
+} /* l3dss1_error_return */
+
+/*******************************************************************/
+/* called when a facility message with a dummy callref is received */
+/* and a invoke is delivered. id specifies the invoke id.          */
+/*******************************************************************/ 
+static void 
+l3dss1_dummy_invoke(struct PStack *st, int cr, int id, 
+                    int ident, u_char *p, u_char nlen)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs;
+  
+  l3_debug(st, "dummy invoke %s id=0x%x ident=0x%x datalen=%d",
+               (cr == -1) ? "local" : "broadcast",id,ident,nlen);
+  if (cr >= -1) return; /* ignore local data */
+
+  cs = st->l1.hardware;
+  ic.driver = cs->myid;
+  ic.command = ISDN_STAT_PROT;
+  ic.arg = DSS1_STAT_INVOKE_BRD;
+  ic.parm.dss1_io.hl_id = id;
+  ic.parm.dss1_io.ll_id = 0;
+  ic.parm.dss1_io.proc = ident;
+  ic.parm.dss1_io.timeout= 0;
+  ic.parm.dss1_io.datalen = nlen;
+  ic.parm.dss1_io.data = p;
+
+  cs->iif.statcallb(&ic);
+} /* l3dss1_dummy_invoke */
+
 static void
-l3dss1_parse_facility(struct l3_process *pc, u_char *p)
+l3dss1_parse_facility(struct PStack *st, struct l3_process *pc,
+                      int cr, u_char * p)
 {
 	int qd_len = 0;
-	char tmp[32];
+	unsigned char nlen = 0, ilen, cp_tag;
+	int ident, id;
+	ulong err_ret;
+
+	if (pc) 
+		st = pc->st; /* valid Stack */
+	else
+		if ((!st) || (cr >= 0)) return; /* neither pc nor st specified */
 
 	p++;
 	qd_len = *p++;
 	if (qd_len == 0) {
-		l3_debug(pc->st, "qd_len == 0");
+		l3_debug(st, "qd_len == 0");
 		return;
 	}
-	if((*p & 0x1F) != 0x11) {	/* Service discriminator, supplementary service */
-		l3_debug(pc->st, "supplementary service != 0x11");
+	if ((*p & 0x1F) != 0x11) {	/* Service discriminator, supplementary service */
+		l3_debug(st, "supplementary service != 0x11");
 		return;
 	}
-	while(qd_len > 0 && !(*p & 0x80)) {	/* extension ? */
-		p++; qd_len--;
-	} 
-	if(qd_len < 2) {
-		l3_debug(pc->st, "qd_len < 2");
-		return;
+	while (qd_len > 0 && !(*p & 0x80)) {	/* extension ? */
+		p++;
+		qd_len--;
 	}
-	p++; qd_len--;
-	if((*p & 0xE0) != 0xA0) {	/* class and form */
-		l3_debug(pc->st, "class and form != 0xA0");
+	if (qd_len < 2) {
+		l3_debug(st, "qd_len < 2");
 		return;
 	}
-	switch(*p & 0x1F) {		/* component tag */
-	    case 1: /* invoke */
-		{
-		    unsigned char nlen, ilen;
-		    int ident;
-    
-		    p++; qd_len--;
-		    if(qd_len < 1) {
-			    l3_debug(pc->st, "qd_len < 1");
-			    break;
-		    }
-		    if(*p & 0x80) { /* length format */
-			    l3_debug(pc->st, "*p & 0x80 length format");
-			    break;
-		    }
-		    nlen = *p++; qd_len--;
-		    if(qd_len < nlen) {
-			    l3_debug(pc->st, "qd_len < nlen");
-			    return;
-		    }
-		    qd_len -= nlen;
-    
-		    if(nlen < 2) {
-			    l3_debug(pc->st, "nlen < 2");
-			    return;
-		    }
-		    if(*p != 0x02) {	/* invoke identifier tag */
-			    l3_debug(pc->st, "invoke identifier tag !=0x02");
-			    return;
-		    }
-		    p++; nlen--;
-		    if(*p & 0x80) { /* length format */
-			    l3_debug(pc->st, "*p & 0x80 length format 2");
-			    break;
-		    }
-		    ilen = *p++; nlen--;
-		    if(ilen > nlen || ilen == 0) {
-			    l3_debug(pc->st, "ilen > nlen || ilen == 0");
-			    return;
-		    }
-		    nlen -= ilen;
-		    ident = 0;
-		    while(ilen > 0) {
-			    ident = (ident << 8) | (*p++ & 0xFF);	/* invoke identifier */
-			    ilen--;
-		    }
-    
-		    if(nlen < 2) {
-			    l3_debug(pc->st, "nlen < 2 22");
-			    return;
-		    }
-		    if(*p != 0x02)	{	/* operation value */ 
-			    l3_debug(pc->st, "operation value !=0x02");
-			    return;
-		    }
-		    p++; nlen--;
-		    ilen = *p++; nlen--;
-		    if(ilen > nlen || ilen == 0) {
-			    l3_debug(pc->st, "ilen > nlen || ilen == 0 22");
-			    return;
-		    }
-		    nlen -= ilen;
-		    ident = 0;
-		    while(ilen > 0) {
-			    ident = (ident << 8) | (*p++ & 0xFF);
-			    ilen--;
-		    }
-    
-    #define FOO1(s,a,b) \
+	p++;
+	qd_len--;
+	if ((*p & 0xE0) != 0xA0) {	/* class and form */
+		l3_debug(st, "class and form != 0xA0");
+		return;
+	}
+       
+        cp_tag = *p & 0x1F; /* remember tag value */
+
+        p++;
+	qd_len--;
+	if (qd_len < 1) 
+          { l3_debug(st, "qd_len < 1");
+	    return;
+	  }
+	if (*p & 0x80) 
+          { /* length format indefinite or limited */
+	    nlen = *p++ & 0x7F; /* number of len bytes or indefinite */
+            if ((qd_len-- < ((!nlen) ? 3 : (1 + nlen))) ||
+                (nlen > 1))   
+	     { l3_debug(st, "length format error or not implemented");
+	       return;
+             }
+            if (nlen == 1)
+	     { nlen = *p++; /* complete length */
+               qd_len--;
+             } 
+            else
+	     { qd_len -= 2; /* trailing null bytes */
+               if ((*(p+qd_len)) || (*(p+qd_len+1)))
+		{ l3_debug(st,"length format indefinite error");
+                  return;
+                }
+               nlen = qd_len;
+             }
+	  }
+        else
+	  { nlen = *p++;
+	    qd_len--;
+          } 
+	if (qd_len < nlen) 
+          { l3_debug(st, "qd_len < nlen");
+	    return;
+	  }
+	qd_len -= nlen;
+
+	if (nlen < 2) 
+          { l3_debug(st, "nlen < 2");
+	    return;
+	  }
+        if (*p != 0x02) 
+          {  /* invoke identifier tag */
+	     l3_debug(st, "invoke identifier tag !=0x02");
+	     return;
+	  }
+	p++;
+	nlen--;
+	if (*p & 0x80) 
+          { /* length format */
+	    l3_debug(st, "invoke id length format 2");
+	    return;
+	  }
+	ilen = *p++;
+	nlen--;
+	if (ilen > nlen || ilen == 0) 
+          { l3_debug(st, "ilen > nlen || ilen == 0");
+	    return;
+	  }
+	nlen -= ilen;
+	id = 0;
+	while (ilen > 0) 
+          { id = (id << 8) | (*p++ & 0xFF);	/* invoke identifier */
+	    ilen--;
+	  }
+
+	switch (cp_tag) {	/* component tag */
+		case 1:	/* invoke */
+				if (nlen < 2) {
+					l3_debug(st, "nlen < 2 22");
+					return;
+				}
+				if (*p != 0x02) {	/* operation value */
+					l3_debug(st, "operation value !=0x02");
+					return;
+				}
+				p++;
+				nlen--;
+				ilen = *p++;
+				nlen--;
+				if (ilen > nlen || ilen == 0) {
+					l3_debug(st, "ilen > nlen || ilen == 0 22");
+					return;
+				}
+				nlen -= ilen;
+				ident = 0;
+				while (ilen > 0) {
+					ident = (ident << 8) | (*p++ & 0xFF);
+					ilen--;
+				}
+
+                                if (!pc) 
+			         { l3dss1_dummy_invoke(st, cr, id, ident, p, nlen);
+                                   return;
+                                 } 
+#if HISAX_DE_AOC
+			{
+
+#define FOO1(s,a,b) \
 	    while(nlen > 1) {		\
 		    int ilen = p[1];	\
 		    if(nlen < ilen+2) {	\
-			    l3_debug(pc->st, "FOO1  nlen < ilen+2"); \
+			    l3_debug(st, "FOO1  nlen < ilen+2"); \
 			    return;		\
 		    }			\
 		    nlen -= ilen+2;		\
@@ -174,305 +432,824 @@
 			    p += ilen+2;	\
 		    }			\
 	    }
-			    
-		    switch(ident) {
-		    default:
-			    break;
-		    case 0x22: /* during */
-			    FOO1("1A",0x30,FOO1("1C",0xA1,FOO1("1D",0x30,FOO1("1E",0x02,({
-				    ident = 0;
-				    while(ilen > 0) {
-					    ident = (ident<<8) | *p++;
-					    ilen--;
-				    }
-				    if (ident > pc->para.chargeinfo) {
-					    pc->para.chargeinfo = ident;
-					    pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
-				    }
-				    if (pc->st->l3.debug & L3_DEB_CHARGE) {
-					    if (*(p+2) == 0) {
-						    sprintf(tmp, "charging info during %d", pc->para.chargeinfo);
-						    l3_debug(pc->st, tmp);
-					    }
-					    else {
-					    sprintf(tmp, "charging info final %d", pc->para.chargeinfo);
-					    l3_debug(pc->st, tmp);
-					    }
-				    }
-			    })))))
-			    break;
-		    case 0x24: /* final */
-			    FOO1("2A",0x30,FOO1("2B",0x30,FOO1("2C",0xA1,FOO1("2D",0x30,FOO1("2E",0x02,({
-				    ident = 0;
-				    while(ilen > 0) {
-					    ident = (ident<<8) | *p++;
-					    ilen--;
-				    }
-				    if (ident > pc->para.chargeinfo) {
-					    pc->para.chargeinfo = ident;
-					    pc->st->l3.l3l4(pc, CC_INFO_CHARGE, NULL);
-				    }
-				    if (pc->st->l3.debug & L3_DEB_CHARGE) {
-					    sprintf(tmp, "charging info final %d", pc->para.chargeinfo);
-					    l3_debug(pc->st, tmp);
-				    }
-			    }))))))
-		    break;
-		    }
-    #undef FOO1
-    
+
+				switch (ident) {
+					case 0x22:	/* during */
+						FOO1("1A", 0x30, FOO1("1C", 0xA1, FOO1("1D", 0x30, FOO1("1E", 0x02, ( {
+							       ident = 0;
+							nlen = (nlen)?nlen:0; /* Make gcc happy */
+							while (ilen > 0) {
+														     ident = (ident << 8) | *p++;
+								  ilen--;
+									}
+														     if (ident > pc->para.chargeinfo) {
+														     pc->para.chargeinfo = ident;
+														     st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
+									}
+														     if (st->l3.debug & L3_DEB_CHARGE) {
+														     if (*(p + 2) == 0) {
+														     l3_debug(st, "charging info during %d", pc->para.chargeinfo);
+									}
+								   else {
+														     l3_debug(st, "charging info final %d", pc->para.chargeinfo);
+									}
+									}
+									}
+								    )))))
+							break;
+					case 0x24:	/* final */
+						FOO1("2A", 0x30, FOO1("2B", 0x30, FOO1("2C", 0xA1, FOO1("2D", 0x30, FOO1("2E", 0x02, ( {
+							       ident = 0;
+							nlen = (nlen)?nlen:0; /* Make gcc happy */
+							while (ilen > 0) {
+																      ident = (ident << 8) | *p++;
+								  ilen--;
+									}
+																      if (ident > pc->para.chargeinfo) {
+																      pc->para.chargeinfo = ident;
+																      st->l3.l3l4(st, CC_CHARGE | INDICATION, pc);
+									}
+																      if (st->l3.debug & L3_DEB_CHARGE) {
+																      l3_debug(st, "charging info final %d", pc->para.chargeinfo);
+									}
+									}
+								   ))))))
+							break;
+					default:
+                                                       l3_debug(st, "invoke break invalid ident %02x",ident);
+						break;
+				}
+#undef FOO1
+
+			}
+#else  not HISAX_DE_AOC
+                        l3_debug(st, "invoke break");
+#endif not HISAX_DE_AOC 
+			break;
+		case 2:	/* return result */
+			 /* if no process available handle separately */ 
+                        if (!pc)
+			 { if (cr == -1) 
+                             l3dss1_dummy_return_result(st, id, p, nlen);
+                           return; 
+                         }   
+                        if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
+                          { /* Diversion successfull */
+                            free_invoke_id(st,pc->prot.dss1.invoke_id);
+                            pc->prot.dss1.remote_result = 0; /* success */     
+                            pc->prot.dss1.invoke_id = 0;
+                            pc->redir_result = pc->prot.dss1.remote_result; 
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);                                  } /* Diversion successfull */
+                        else
+                          l3_debug(st,"return error unknown identifier");
+			break;
+		case 3:	/* return error */
+                            err_ret = 0;
+	                    if (nlen < 2) 
+                              { l3_debug(st, "return error nlen < 2");
+	                        return;
+	                      }
+                            if (*p != 0x02) 
+                              { /* result tag */
+	                        l3_debug(st, "invoke error tag !=0x02");
+	                        return;
+	                      }
+	                    p++;
+	                    nlen--;
+	                    if (*p > 4) 
+                              { /* length format */
+	                        l3_debug(st, "invoke return errlen > 4 ");
+	                        return;
+	                      }
+	                    ilen = *p++;
+	                    nlen--;
+	                    if (ilen > nlen || ilen == 0) 
+                              { l3_debug(st, "error return ilen > nlen || ilen == 0");
+	                        return;
+	                       }
+	                    nlen -= ilen;
+	                    while (ilen > 0) 
+                             { err_ret = (err_ret << 8) | (*p++ & 0xFF);	/* error value */
+	                       ilen--;
+	                     }
+			 /* if no process available handle separately */ 
+                        if (!pc)
+			 { if (cr == -1)
+                             l3dss1_dummy_error_return(st, id, err_ret);
+                           return; 
+                         }   
+                        if ((pc->prot.dss1.invoke_id) && (pc->prot.dss1.invoke_id == id))
+                          { /* Deflection error */
+                            free_invoke_id(st,pc->prot.dss1.invoke_id);
+                            pc->prot.dss1.remote_result = err_ret; /* result */
+                            pc->prot.dss1.invoke_id = 0; 
+                            pc->redir_result = pc->prot.dss1.remote_result; 
+                            st->l3.l3l4(st, CC_REDIR | INDICATION, pc);  
+                          } /* Deflection error */
+                        else
+                          l3_debug(st,"return result unknown identifier");
+			break;
+		default:
+			l3_debug(st, "facility default break tag=0x%02x",cp_tag);
+			break;
+	}
+}
+
+static void
+l3dss1_message(struct l3_process *pc, u_char mt)
+{
+	struct sk_buff *skb;
+	u_char *p;
+
+	if (!(skb = l3_alloc_skb(4)))
+		return;
+	p = skb_put(skb, 4);
+	MsgHead(p, pc->callref, mt);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause)
+{
+	struct sk_buff *skb;
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
+
+	MsgHead(p, pc->callref, mt);
+	*p++ = IE_CAUSE;
+	*p++ = 0x2;
+	*p++ = 0x80;
+	*p++ = cause | 0x80;
+
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg)
+{
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
+	struct sk_buff *skb;
+
+	MsgHead(p, pc->callref, MT_STATUS);
+
+	*p++ = IE_CAUSE;
+	*p++ = 0x2;
+	*p++ = 0x80;
+	*p++ = pc->para.cause | 0x80;
+
+	*p++ = IE_CALL_STATE;
+	*p++ = 0x1;
+	*p++ = pc->state & 0x3f;
+
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
+{
+	/* This routine is called if here was no SETUP made (checks in dss1up and in
+	 * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
+	 * MT_STATUS_ENQUIRE in the NULL state is handled too
+	 */
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
+	struct sk_buff *skb;
+
+	switch (pc->para.cause) {
+		case 81:	/* invalid callreference */
+		case 88:	/* incomp destination */
+		case 96:	/* mandory IE missing */
+		case 100:       /* invalid IE contents */
+		case 101:	/* incompatible Callstate */
+			MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
+			*p++ = IE_CAUSE;
+			*p++ = 0x2;
+			*p++ = 0x80;
+			*p++ = pc->para.cause | 0x80;
+			break;
+		default:
+			printk(KERN_ERR "HiSax l3dss1_msg_without_setup wrong cause %d\n",
+				pc->para.cause);
+			return;
+	}
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+	dss1_release_l3_process(pc);
+}
+
+static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
+		IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
+static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
+		IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
+static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1, 
+		IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_CONNECT_PN,
+		IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
+static int ie_CONNECT_ACKNOWLEDGE[] = {IE_CHANNEL_ID, IE_DISPLAY, -1};
+static int ie_DISCONNECT[] = {IE_CAUSE | IE_MANDATORY, IE_FACILITY,
+		IE_PROGRESS, IE_DISPLAY, IE_USER_USER, -1};
+/* not used
+ * static int ie_INFORMATION[] = {IE_COMPLETE, IE_DISPLAY, IE_KEYPAD,
+ *		IE_CALLED_PN, -1};
+ */
+static int ie_NOTIFY[] = {IE_BEARER, IE_NOTIFY | IE_MANDATORY, IE_DISPLAY, -1};
+static int ie_PROGRESS[] = {IE_BEARER, IE_CAUSE, IE_FACILITY, IE_PROGRESS |
+		IE_MANDATORY, IE_DISPLAY, IE_HLC, IE_USER_USER, -1};
+static int ie_RELEASE[] = {IE_CAUSE | IE_MANDATORY_1, IE_FACILITY, IE_DISPLAY, IE_USER_USER, -1};
+/* a RELEASE_COMPLETE with errors don't require special actions 
+static int ie_RELEASE_COMPLETE[] = {IE_CAUSE | IE_MANDATORY_1, IE_DISPLAY, IE_USER_USER, -1};
+*/
+static int ie_RESUME_ACKNOWLEDGE[] = {IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY,
+		IE_DISPLAY, -1};
+static int ie_RESUME_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
+static int ie_SETUP[] = {IE_COMPLETE, IE_BEARER  | IE_MANDATORY,
+		IE_CHANNEL_ID| IE_MANDATORY, IE_FACILITY, IE_PROGRESS,
+		IE_NET_FAC, IE_DISPLAY, IE_KEYPAD, IE_CALLING_PN,
+		IE_CALLING_SUB, IE_CALLED_PN, IE_CALLED_SUB, IE_LLC, IE_USER_USER, -1};
+static int ie_SETUP_ACKNOWLEDGE[] = {IE_CHANNEL_ID | IE_MANDATORY, IE_FACILITY,
+		IE_PROGRESS, IE_DISPLAY, -1};
+static int ie_STATUS[] = {IE_CAUSE | IE_MANDATORY, IE_CALL_STATE |
+		IE_MANDATORY, IE_DISPLAY, -1};
+static int ie_STATUS_ENQUIRY[] = {IE_DISPLAY, -1};
+static int ie_SUSPEND_ACKNOWLEDGE[] = {IE_DISPLAY, IE_FACILITY, -1};
+static int ie_SUSPEND_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
+/* not used 
+ * static int ie_CONGESTION_CONTROL[] = {IE_CONGESTION | IE_MANDATORY,
+ *		IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
+ * static int ie_USER_INFORMATION[] = {IE_MORE_DATA, IE_USER_USER | IE_MANDATORY, -1};
+ * static int ie_RESTART[] = {IE_CHANNEL_ID, IE_DISPLAY, IE_RESTART_IND |
+ *		IE_MANDATORY, -1};
+ */
+static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
+static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
+static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
+
+struct ie_len {
+	int ie;
+	int len;
+};
+
+static
+struct ie_len max_ie_len[] = {
+	{IE_SEGMENT, 4},
+	{IE_BEARER, 12},
+	{IE_CAUSE, 32},
+	{IE_CALL_ID, 10},
+	{IE_CALL_STATE, 3},
+	{IE_CHANNEL_ID,	34},
+	{IE_FACILITY, 255},
+	{IE_PROGRESS, 4},
+	{IE_NET_FAC, 255},
+	{IE_NOTIFY, 3},
+	{IE_DISPLAY, 82},
+	{IE_DATE, 8},
+	{IE_KEYPAD, 34},
+	{IE_SIGNAL, 3},
+	{IE_INFORATE, 6},
+	{IE_E2E_TDELAY, 11},
+	{IE_TDELAY_SEL, 5},
+	{IE_PACK_BINPARA, 3},
+	{IE_PACK_WINSIZE, 4},
+	{IE_PACK_SIZE, 4},
+	{IE_CUG, 7},
+	{IE_REV_CHARGE, 3},
+	{IE_CALLING_PN, 24},
+	{IE_CALLING_SUB, 23},
+	{IE_CALLED_PN, 24},
+	{IE_CALLED_SUB, 23},
+	{IE_REDIR_NR, 255},
+	{IE_TRANS_SEL, 255},
+	{IE_RESTART_IND, 3},
+	{IE_LLC, 18},
+	{IE_HLC, 5},
+	{IE_USER_USER, 131},
+	{-1,0},
+};
+
+static int
+getmax_ie_len(u_char ie) {
+	int i = 0;
+	while (max_ie_len[i].ie != -1) {
+		if (max_ie_len[i].ie == ie)
+			return(max_ie_len[i].len);
+		i++;
+	}
+	return(255);
+}
+
+static int
+ie_in_set(struct l3_process *pc, u_char ie, int *checklist) {
+	int ret = 1;
+
+	while (*checklist != -1) {
+#if 0
+		if (pc->debug & L3_DEB_CHECK)
+			l3_debug(pc->st, "ie_in_set ie(%x) cl(%x)",
+				ie, *checklist);
+#endif
+		if ((*checklist & 0xff) == ie) {
+			if (ie & 0x80)
+				return(-ret);
+			else
+				return(ret);
+		}
+		ret++;
+		checklist++;
+	}
+	return(0);
+}
+
+static int
+check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist)
+{
+	int *cl = checklist;
+	u_char mt;
+	u_char *p, ie;
+	int l, newpos, oldpos;
+	int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0;
+	
+	p = skb->data;
+	/* skip cr */
+	p++;
+	l = (*p++) & 0xf;
+	p += l;
+	mt = *p++;
+	oldpos = 0;
+/* shift codeset procedure not implemented in the moment */
+	while ((p - skb->data) < skb->len) {
+		if ((newpos = ie_in_set(pc, *p, cl))) {
+			if (newpos > 0) {
+				if (newpos < oldpos)
+					err_seq++;
+				else
+					oldpos = newpos;
+			}
+		} else {
+			if (ie_in_set(pc, *p, comp_required))
+				err_compr++;
+			else
+				err_ureg++;
 		}
-	    break;
-	    case 2: /* return result */
-		    l3_debug(pc->st, "return result break");
-		    break;
-	    case 3: /* return error */
-		    l3_debug(pc->st, "return error break");
-		    break;
-	    default:
-		    l3_debug(pc->st, "default break");
-		    break;
-	}
-}
-#endif	
-
-static int 
-l3dss1_check_messagetype_validity(int mt) {
-/* verify if a message type exists */
-	switch(mt) {
+		ie = *p++;
+		if (newpos >= 0) {
+			l = *p++;
+			p += l;
+			l += 2;
+		} else
+			l = 1;
+		if (l > getmax_ie_len(ie))
+			err_len++;
+	}
+	if (err_compr | err_ureg | err_len | err_seq) {
+		if (pc->debug & L3_DEB_CHECK)
+			l3_debug(pc->st, "check_infoelements mt %x %d/%d/%d/%d",
+				mt, err_compr, err_ureg, err_len, err_seq);
+		if (err_compr)
+			return(ERR_IE_COMPREHENSION);
+		if (err_ureg)
+			return(ERR_IE_UNRECOGNIZED);
+		if (err_len)
+			return(ERR_IE_LENGTH);
+		if (err_seq)
+			return(ERR_IE_SEQUENCE);
+	} 
+	return(0);
+}
+
+/* verify if a message type exists and contain no IE error */
+static int
+l3dss1_check_messagetype_validity(struct l3_process *pc, int mt, void *arg)
+{
+	switch (mt) {
 		case MT_ALERTING:
 		case MT_CALL_PROCEEDING:
 		case MT_CONNECT:
 		case MT_CONNECT_ACKNOWLEDGE:
+		case MT_DISCONNECT:
+		case MT_INFORMATION:
+		case MT_FACILITY:
+		case MT_NOTIFY:
 		case MT_PROGRESS:
+		case MT_RELEASE:
+		case MT_RELEASE_COMPLETE:
 		case MT_SETUP:
 		case MT_SETUP_ACKNOWLEDGE:
-		case MT_RESUME:
 		case MT_RESUME_ACKNOWLEDGE:
 		case MT_RESUME_REJECT:
-		case MT_SUSPEND:
 		case MT_SUSPEND_ACKNOWLEDGE:
 		case MT_SUSPEND_REJECT:
 		case MT_USER_INFORMATION:
-		case MT_DISCONNECT:
-		case MT_RELEASE:
-		case MT_RELEASE_COMPLETE:
 		case MT_RESTART:
 		case MT_RESTART_ACKNOWLEDGE:
-		case MT_SEGMENT:
 		case MT_CONGESTION_CONTROL:
-		case MT_INFORMATION:
-		case MT_FACILITY:
-		case MT_NOTIFY:
 		case MT_STATUS:
 		case MT_STATUS_ENQUIRY:
+			if (pc->debug & L3_DEB_CHECK)
+				l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) OK", mt);
+			break;
+		case MT_RESUME: /* RESUME only in user->net */
+		case MT_SUSPEND: /* SUSPEND only in user->net */
+		default:
+			if (pc->debug & (L3_DEB_CHECK | L3_DEB_WARN))
+				l3_debug(pc->st, "l3dss1_check_messagetype_validity mt(%x) fail", mt);
+			pc->para.cause = 97;
+			l3dss1_status_send(pc, 0, NULL);
 			return(1);
+	}
+	return(0);
+}
+
+static void
+l3dss1_std_ie_err(struct l3_process *pc, int ret) {
+
+	if (pc->debug & L3_DEB_CHECK)
+		l3_debug(pc->st, "check_infoelements ret %d", ret);
+	switch(ret) {
+		case 0: 
+			break;
+		case ERR_IE_COMPREHENSION:
+			pc->para.cause = 96;
+			l3dss1_status_send(pc, 0, NULL);
+			break;
+		case ERR_IE_UNRECOGNIZED:
+			pc->para.cause = 99;
+			l3dss1_status_send(pc, 0, NULL);
+			break;
+		case ERR_IE_LENGTH:
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, 0, NULL);
+			break;
+		case ERR_IE_SEQUENCE:
 		default:
-			return(0);
+			break;
 	}
+}
+
+static int
+l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) {
+	u_char *p;
+
+	p = skb->data;
+	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
+		p++;
+		if (*p != 1) { /* len for BRI = 1 */
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "wrong chid len %d", *p);
+			return (-2);
+		}
+		p++;
+		if (*p & 0x60) { /* only base rate interface */
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "wrong chid %x", *p);
+			return (-3);
+		}
+		return(*p & 0x3);
+	} else
+		return(-1);
+}
+
+static int
+l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) {
+	u_char l, i=0;
+	u_char *p;
+
+	p = skb->data;
+	pc->para.cause = 31;
+	pc->para.loc = 0;
+	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
+		p++;
+		l = *p++;
+		if (l>30)
+			return(1);
+		if (l) {
+			pc->para.loc = *p++;
+			l--;
+		} else {
+			return(2);
+		}
+		if (l && !(pc->para.loc & 0x80)) {
+			l--;
+			p++; /* skip recommendation */
+		}
+		if (l) {
+			pc->para.cause = *p++;
+			l--;
+			if (!(pc->para.cause & 0x80))
+				return(3);
+		} else
+			return(4);
+		while (l && (i<6)) {
+			pc->para.diag[i++] = *p++;
+			l--;
+		}
+	} else
+		return(-1);
 	return(0);
 }
 
 static void
-l3dss1_message(struct l3_process *pc, u_char mt)
+l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd)
 {
 	struct sk_buff *skb;
-	u_char *p;
+	u_char tmp[16+40];
+	u_char *p = tmp;
+	int l;
 
-	if (!(skb = l3_alloc_skb(4)))
+	MsgHead(p, pc->callref, cmd);
+
+        if (pc->prot.dss1.uus1_data[0])
+	 { *p++ = IE_USER_USER; /* UUS info element */
+           *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
+           *p++ = 0x04; /* IA5 chars */
+           strcpy(p,pc->prot.dss1.uus1_data);
+           p += strlen(pc->prot.dss1.uus1_data);
+           pc->prot.dss1.uus1_data[0] = '\0';   
+         } 
+
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
 		return;
-	p = skb_put(skb, 4);
-	MsgHead(p, pc->callref, mt);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
-}
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+} /* l3dss1_msg_with_uus */
 
 static void
 l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	StopAllL3Timer(pc);
 	newl3state(pc, 19);
-	l3dss1_message(pc, MT_RELEASE);
+	if (!pc->prot.dss1.uus1_data[0]) 
+		l3dss1_message(pc, MT_RELEASE);
+	else
+		l3dss1_msg_with_uus(pc, MT_RELEASE);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
-static void
-l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
-{
-	u_char *p;
-	struct sk_buff *skb = arg;
-	int cause = -1;
+static void
+l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int ret;
+
+	if ((ret = l3dss1_get_cause(pc, skb))>0) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "RELCMPL get_cause ret(%d)",ret);
+	} else if (ret < 0)
+		pc->para.cause = NO_CAUSE;
+	StopAllL3Timer(pc);
+	newl3state(pc, 0);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc);
+	dss1_release_l3_process(pc);
+}
+
+#if EXT_BEARER_CAPS
+
+u_char *
+EncodeASyncParams(u_char * p, u_char si2)
+{				// 7c 06 88  90 21 42 00 bb
+
+	p[0] = p[1] = 0;
+	p[2] = 0x80;
+	if (si2 & 32)		// 7 data bits
+
+		p[2] += 16;
+	else			// 8 data bits
+
+		p[2] += 24;
+
+	if (si2 & 16)		// 2 stop bits
+
+		p[2] += 96;
+	else			// 1 stop bit
+
+		p[2] = 32;
+
+	if (si2 & 8)		// even parity
+
+		p[2] += 2;
+	else			// no parity
+
+		p[2] += 3;
+
+	switch (si2 & 0x07) {
+		case 0:
+			p[0] = 66;	// 1200 bit/s
+
+			break;
+		case 1:
+			p[0] = 88;	// 1200/75 bit/s
+
+			break;
+		case 2:
+			p[0] = 87;	// 75/1200 bit/s
+
+			break;
+		case 3:
+			p[0] = 67;	// 2400 bit/s
+
+			break;
+		case 4:
+			p[0] = 69;	// 4800 bit/s
+
+			break;
+		case 5:
+			p[0] = 72;	// 9600 bit/s
+
+			break;
+		case 6:
+			p[0] = 73;	// 14400 bit/s
+
+			break;
+		case 7:
+			p[0] = 75;	// 19200 bit/s
+
+			break;
+	}
+	return p + 3;
+}
+
+u_char
+EncodeSyncParams(u_char si2, u_char ai)
+{
+
+	switch (si2) {
+		case 0:
+			return ai + 2;	// 1200 bit/s
+
+		case 1:
+			return ai + 24;		// 1200/75 bit/s
+
+		case 2:
+			return ai + 23;		// 75/1200 bit/s
+
+		case 3:
+			return ai + 3;	// 2400 bit/s
+
+		case 4:
+			return ai + 5;	// 4800 bit/s
+
+		case 5:
+			return ai + 8;	// 9600 bit/s
+
+		case 6:
+			return ai + 9;	// 14400 bit/s
+
+		case 7:
+			return ai + 11;		// 19200 bit/s
+
+		case 8:
+			return ai + 14;		// 48000 bit/s
+
+		case 9:
+			return ai + 15;		// 56000 bit/s
+
+		case 15:
+			return ai + 40;		// negotiate bit/s
+
+		default:
+			break;
+	}
+	return ai;
+}
+
+
+static u_char
+DecodeASyncParams(u_char si2, u_char * p)
+{
+	u_char info;
+
+	switch (p[5]) {
+		case 66:	// 1200 bit/s
+
+			break;	// si2 don't change
+
+		case 88:	// 1200/75 bit/s
+
+			si2 += 1;
+			break;
+		case 87:	// 75/1200 bit/s
+
+			si2 += 2;
+			break;
+		case 67:	// 2400 bit/s
+
+			si2 += 3;
+			break;
+		case 69:	// 4800 bit/s
+
+			si2 += 4;
+			break;
+		case 72:	// 9600 bit/s
+
+			si2 += 5;
+			break;
+		case 73:	// 14400 bit/s
+
+			si2 += 6;
+			break;
+		case 75:	// 19200 bit/s
+
+			si2 += 7;
+			break;
+	}
+
+	info = p[7] & 0x7f;
+	if ((info & 16) && (!(info & 8)))	// 7 data bits
+
+		si2 += 32;	// else 8 data bits
+
+	if ((info & 96) == 96)	// 2 stop bits
+
+		si2 += 16;	// else 1 stop bit
+
+	if ((info & 2) && (!(info & 1)))	// even parity
+
+		si2 += 8;	// else no parity
+
+	return si2;
+}
+
+
+static u_char
+DecodeSyncParams(u_char si2, u_char info)
+{
+	info &= 0x7f;
+	switch (info) {
+		case 40:	// bit/s negotiation failed  ai := 165 not 175!
+
+			return si2 + 15;
+		case 15:	// 56000 bit/s failed, ai := 0 not 169 !
+
+			return si2 + 9;
+		case 14:	// 48000 bit/s
+
+			return si2 + 8;
+		case 11:	// 19200 bit/s
+
+			return si2 + 7;
+		case 9:	// 14400 bit/s
+
+			return si2 + 6;
+		case 8:	// 9600  bit/s
+
+			return si2 + 5;
+		case 5:	// 4800  bit/s
+
+			return si2 + 4;
+		case 3:	// 2400  bit/s
+
+			return si2 + 3;
+		case 23:	// 75/1200 bit/s
+
+			return si2 + 2;
+		case 24:	// 1200/75 bit/s
+
+			return si2 + 1;
+		default:	// 1200 bit/s
 
-	p = skb->data;
-	pc->para.loc = 0;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
+			return si2;
 	}
-	dev_kfree_skb(skb);
-	StopAllL3Timer(pc);
-	pc->para.cause = cause;
-	newl3state(pc, 0);
-	pc->st->l3.l3l4(pc, CC_RELEASE_CNF, NULL);
-	release_l3_process(pc);
 }
 
-#ifdef EXT_BEARER_CAPS
+static u_char
+DecodeSI2(struct sk_buff *skb)
+{
+	u_char *p;		//, *pend=skb->data + skb->len;
 
-u_char *EncodeASyncParams(u_char *p, u_char si2)
-{ // 7c 06 88  90 21 42 00 bb
+	if ((p = findie(skb->data, skb->len, 0x7c, 0))) {
+		switch (p[4] & 0x0f) {
+			case 0x01:
+				if (p[1] == 0x04)	// sync. Bitratenadaption
 
-  p[0] = p[1] = 0; p[2] = 0x80;
-  if (si2 & 32) // 7 data bits
-    p[2] += 16;
-  else          // 8 data bits
-    p[2] +=24;
-
-  if (si2 & 16) // 2 stop bits
-    p[2] += 96;
-  else          // 1 stop bit
-    p[2] = 32;
-
-  if (si2 & 8)  // even parity
-    p[2] += 2;
-  else          // no parity
-    p[2] += 3;
-
-  switch (si2 & 0x07)
-  {
-    case 0:     p[0] = 66;      // 1200 bit/s
-                break;
-    case 1:     p[0] = 88;      // 1200/75 bit/s
-                break;
-    case 2:     p[0] = 87;      // 75/1200 bit/s
-                break;
-    case 3:     p[0] = 67;      // 2400 bit/s
-                break;
-    case 4:     p[0] = 69;      // 4800 bit/s
-                break;
-    case 5:     p[0] = 72;      // 9600 bit/s
-                break;
-    case 6:     p[0] = 73;      // 14400 bit/s
-                break;
-    case 7:     p[0] = 75;      // 19200 bit/s
-                break;
-  }
-  return p+3;
-}
-
-u_char EncodeSyncParams(u_char si2, u_char ai)
-{
-
-  switch (si2)
-  {
-    case 0:     return ai + 2;  // 1200 bit/s
-    case 1:     return ai + 24; // 1200/75 bit/s
-    case 2:     return ai + 23; // 75/1200 bit/s
-    case 3:     return ai + 3;  // 2400 bit/s
-    case 4:     return ai + 5;  // 4800 bit/s
-    case 5:     return ai + 8;  // 9600 bit/s
-    case 6:     return ai + 9;  // 14400 bit/s
-    case 7:     return ai + 11; // 19200 bit/s
-    case 8:     return ai + 14; // 48000 bit/s
-    case 9:     return ai + 15; // 56000 bit/s
-    case 15:    return ai + 40; // negotiate bit/s
-    default:    break;
-  }
-  return ai;
-}
-
-
-static u_char DecodeASyncParams(u_char si2, u_char *p)
-{ u_char info;
-
-  switch (p[5])
-  {
-    case 66: // 1200 bit/s
-             break; // si2 bleibt gleich
-    case 88: // 1200/75 bit/s
-             si2 += 1;
-             break;
-    case 87: // 75/1200 bit/s
-             si2 += 2;
-             break;
-    case 67: // 2400 bit/s
-             si2 += 3;
-             break;
-    case 69: // 4800 bit/s
-             si2 += 4;
-             break;
-    case 72: // 9600 bit/s
-             si2 += 5;
-             break;
-    case 73: // 14400 bit/s
-             si2 += 6;
-             break;
-    case 75: // 19200 bit/s
-             si2 += 7;
-             break;
-  }
-
-  info = p[7] & 0x7f;
-  if ((info & 16) && (!(info & 8)))   // 7 data bits
-    si2 += 32;                        // else 8 data bits
-  if ((info & 96) == 96)              // 2 stop bits
-    si2 += 16;                        // else 1 stop bit
-  if ((info & 2) && (!(info & 1)))    // even parity
-    si2 += 8;                         // else no parity
-
-  return si2;
-}
-
-
-static u_char DecodeSyncParams(u_char si2, u_char info)
-{
-  info &= 0x7f;
-  switch (info)
-  {
-    case 40: // bit/s aushandeln  --- hat nicht geklappt, ai wird 165 statt 175!
-      return si2 + 15;
-    case 15: // 56000 bit/s --- hat nicht geklappt, ai wird 0 statt 169 !
-      return si2 + 9;
-    case 14: // 48000 bit/s
-      return si2 + 8;
-    case 11: // 19200 bit/s
-      return si2 + 7;
-    case 9:  // 14400 bit/s
-      return si2 + 6;
-    case 8:  // 9600  bit/s
-      return si2 + 5;
-    case 5:  // 4800  bit/s
-      return si2 + 4;
-    case 3:  // 2400  bit/s
-      return si2 + 3;
-    case 23: // 75/1200 bit/s
-      return si2 + 2;
-    case 24: // 1200/75 bit/s
-      return si2 + 1;
-    default: // 1200 bit/s
-      return si2;
-  }
-}
-
-static u_char DecodeSI2(struct sk_buff *skb)
-{ u_char *p; //, *pend=skb->data + skb->len;
-
-        if ((p = findie(skb->data, skb->len, 0x7c, 0)))
-        {
-          switch (p[4] & 0x0f)
-          {
-            case 0x01:  if (p[1] == 0x04) // sync. Bitratenadaption
-                          return DecodeSyncParams(160, p[5]); // V.110/X.30
-                        else if (p[1] == 0x06) // async. Bitratenadaption
-                          return DecodeASyncParams(192, p);   // V.110/X.30
-                        break;
-            case 0x08:  // if (p[5] == 0x02) // sync. Bitratenadaption
-                          return DecodeSyncParams(176, p[5]); // V.120
-                        break;
-          }
-        }
-        return 0;
+					return DecodeSyncParams(160, p[5]);	// V.110/X.30
+
+				else if (p[1] == 0x06)	// async. Bitratenadaption
+
+					return DecodeASyncParams(192, p);	// V.110/X.30
+
+				break;
+			case 0x08:	// if (p[5] == 0x02) // sync. Bitratenadaption
+
+				return DecodeSyncParams(176, p[5]);	// V.120
+
+				break;
+		}
+	}
+	return 0;
 }
 
 #endif
@@ -486,6 +1263,7 @@
 	u_char tmp[128];
 	u_char *p = tmp;
 	u_char channel = 0;
+        u_char send_keypad;
 	u_char screen = 0x80;
 	u_char *teln;
 	u_char *msn;
@@ -495,13 +1273,17 @@
 
 	MsgHead(p, pc->callref, MT_SETUP);
 
+	teln = pc->para.setup.phone;
+        send_keypad = (strchr(teln,'*') || strchr(teln,'#')) ? 1 : 0; 
 	/*
 	 * Set Bearer Capability, Map info from 1TR6-convention to EDSS1
 	 */
-#ifdef HISAX_EURO_SENDCOMPLETE
-	*p++ = 0xa1;		/* complete indicator */
+#if HISAX_EURO_SENDCOMPLETE
+	if (!send_keypad)
+	  *p++ = 0xa1;		/* complete indicator */
 #endif
-	switch (pc->para.setup.si1) {
+        if (!send_keypad)
+	  switch (pc->para.setup.si1) {
 		case 1:	/* Telephony                               */
 			*p++ = 0x4;	/* BC-IE-code                              */
 			*p++ = 0x3;	/* Length                                  */
@@ -517,12 +1299,26 @@
 			*p++ = 0x88;	/* Coding Std. CCITT, unrestr. dig. Inform. */
 			*p++ = 0x90;	/* Circuit-Mode 64kbps                      */
 			break;
-	}
+	  }
+	else {  *p++ = 0x4; /* assumptions for bearer services with keypad  */
+		*p++ = 0x3;
+		*p++ = 0x80;
+                *p++ = 0x90;
+                *p++ = 0xa3;
+		*p++ = 0x18; /* no specific channel */
+                *p++ = 0x01;
+                *p++ = 0x83;
+		*p++ = 0x2C; /* IE keypad */
+		*p++ = strlen(teln);
+		while (*teln)
+		  *p++ = (*teln++) & 0x7F;
+	  }
+	  
+       
 	/*
 	 * What about info2? Mapping to High-Layer-Compatibility?
 	 */
-	teln = pc->para.setup.phone;
-	if (*teln) {
+	if ((*teln) && (!send_keypad)) {
 		/* parse number for special things */
 		if (!isdigit(*teln)) {
 			switch (0x5f & *teln) {
@@ -542,7 +1338,8 @@
 				case 'D':
 					screen = 0x80;
 					break;
-				default:
+				
+			        default:
 					if (pc->debug & L3_DEB_WARN)
 						l3_debug(pc->st, "Wrong MSN Code");
 					break;
@@ -558,11 +1355,11 @@
 	msn = pc->para.setup.eazmsn;
 	sub = NULL;
 	sp = msn;
-	while (*sp) { 
+	while (*sp) {
 		if ('.' == *sp) {
 			sub = sp;
 			*sp = 0;
-		} else 
+		} else
 			sp++;
 	}
 	if (*msn) {
@@ -579,56 +1376,81 @@
 	}
 	if (sub) {
 		*sub++ = '.';
-		*p++ = 0x6d; /* Calling party subaddress */
- 		*p++ = strlen(sub) + 2;
+		*p++ = 0x6d;	/* Calling party subaddress */
+		*p++ = strlen(sub) + 2;
 		*p++ = 0x80;	/* NSAP coded */
 		*p++ = 0x50;	/* local IDI format */
- 		while (*sub)
+		while (*sub)
 			*p++ = *sub++ & 0x7f;
 	}
 	sub = NULL;
 	sp = teln;
-	while (*sp) { 
+	while (*sp) {
 		if ('.' == *sp) {
 			sub = sp;
 			*sp = 0;
-		} else 
+		} else
 			sp++;
 	}
-	*p++ = 0x70;
-	*p++ = strlen(teln) + 1;
-	/* Classify as AnyPref. */
-	*p++ = 0x81;		/* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
-	while (*teln)
-		*p++ = *teln++ & 0x7f;
-
-	if (sub) {
-		*sub++ = '.';
-		*p++ = 0x71; /* Called party subaddress */
- 		*p++ = strlen(sub) + 2;
-		*p++ = 0x80;	/* NSAP coded */
-		*p++ = 0x50;	/* local IDI format */
- 		while (*sub)
-			*p++ = *sub++ & 0x7f;
-	}
-
-#ifdef EXT_BEARER_CAPS
-        if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175))
-        { // sync. Bitratenadaption, V.110/X.30
-          *p++ = 0x7c; *p++ = 0x04; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21;
-          *p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
-        }
-        else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191))
-        { // sync. Bitratenadaption, V.120
-          *p++ = 0x7c; *p++ = 0x05; *p++ = 0x88; *p++ = 0x90; *p++ = 0x28;
-          *p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
-          *p++ = 0x82;
-        }
-        else if (pc->para.setup.si2 >= 192)
-        { // async. Bitratenadaption, V.110/X.30
-          *p++ = 0x7c; *p++ = 0x06; *p++ = 0x88; *p++ = 0x90; *p++ = 0x21;
-          p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
+	
+        if (!send_keypad) {      
+	  *p++ = 0x70;
+	  *p++ = strlen(teln) + 1;
+	  /* Classify as AnyPref. */
+	  *p++ = 0x81;		/* Ext = '1'B, Type = '000'B, Plan = '0001'B. */
+	  while (*teln)
+		  *p++ = *teln++ & 0x7f;
+
+	  if (sub) {
+		  *sub++ = '.';
+		  *p++ = 0x71;	/* Called party subaddress */
+		  *p++ = strlen(sub) + 2;
+		  *p++ = 0x80;	/* NSAP coded */
+		  *p++ = 0x50;	/* local IDI format */
+		  while (*sub)
+			  *p++ = *sub++ & 0x7f;
+	  }
         }
+#if EXT_BEARER_CAPS
+        if (send_keypad) { /* special handling independant of si2 */
+                *p++ = 0x7c;
+                *p++ = 0x03;
+                *p++ = 0x80;
+                *p++ = 0x90;
+                *p++ = 0xa3;
+	} else if ((pc->para.setup.si2 >= 160) && (pc->para.setup.si2 <= 175)) {	// sync. Bitratenadaption, V.110/X.30
+
+		*p++ = 0x7c;
+		*p++ = 0x04;
+		*p++ = 0x88;
+		*p++ = 0x90;
+		*p++ = 0x21;
+		*p++ = EncodeSyncParams(pc->para.setup.si2 - 160, 0x80);
+	} else if ((pc->para.setup.si2 >= 176) && (pc->para.setup.si2 <= 191)) {	// sync. Bitratenadaption, V.120
+
+		*p++ = 0x7c;
+		*p++ = 0x05;
+		*p++ = 0x88;
+		*p++ = 0x90;
+		*p++ = 0x28;
+		*p++ = EncodeSyncParams(pc->para.setup.si2 - 176, 0);
+		*p++ = 0x82;
+	} else if (pc->para.setup.si2 >= 192) {		// async. Bitratenadaption, V.110/X.30
+
+		*p++ = 0x7c;
+		*p++ = 0x06;
+		*p++ = 0x88;
+		*p++ = 0x90;
+		*p++ = 0x21;
+		p = EncodeASyncParams(p, pc->para.setup.si2 - 192);
+#if HISAX_SEND_STD_LLC_IE
+	} else {
+		*p++ = 0x7c;
+		*p++ = 0x02;
+		*p++ = 0x88;
+		*p++ = 0x90;
+#endif
+	}
 #endif
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
@@ -637,227 +1459,276 @@
 	L3DelTimer(&pc->timer);
 	L3AddTimer(&pc->timer, T303, CC_T303);
 	newl3state(pc, 1);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 }
 
 static void
 l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
+	int id, ret;
 
+	if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
+		if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "setup answer with wrong chid %x", id);
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, pr, NULL);
+			return;
+		}
+		pc->para.bchannel = id;
+	} else if (1 == pc->state) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "setup answer without chid (ret %d)", id);
+		pc->para.cause = 96;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	ret = check_infoelements(pc, skb, ie_CALL_PROCEEDING);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
-			l3_debug(pc->st, "setup answer without bchannel");
-	} else if (pc->debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
-	dev_kfree_skb(skb);
 	newl3state(pc, 3);
 	L3AddTimer(&pc->timer, T310, CC_T310);
-	pc->st->l3.l3l4(pc, CC_PROCEEDING_IND, NULL);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
+	pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc);
 }
 
 static void
 l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
+	int id, ret;
 
+	if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
+		if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "setup answer with wrong chid %x", id);
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, pr, NULL);
+			return;
+		}
+		pc->para.bchannel = id;
+	} else {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "setup answer without chid (ret %d)", id);
+		pc->para.cause = 96;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	ret = check_infoelements(pc, skb, ie_SETUP_ACKNOWLEDGE);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if ((!pc->para.bchannel) && (pc->debug & L3_DEB_WARN))
-			l3_debug(pc->st, "setup answer without bchannel");
-	} else if (pc->debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup answer without bchannel");
-	dev_kfree_skb(skb);
 	newl3state(pc, 2);
 	L3AddTimer(&pc->timer, T304, CC_T304);
-	pc->st->l3.l3l4(pc, CC_MORE_INFO, NULL);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
+	pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc);
 }
 
 static void
 l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	u_char *p;
+	int ret;
+	u_char cause = 0;
 
 	StopAllL3Timer(pc);
-	p = skb->data;
-	pc->para.loc = 0;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
-	}
-	dev_kfree_skb(skb);
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "DISC get_cause ret(%d)", ret);
+		if (ret < 0)
+			cause = 96;
+		else if (ret > 0)
+			cause = 100;
+	} 
+	if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
+		l3dss1_parse_facility(pc->st, pc, pc->callref, p);
+	ret = check_infoelements(pc, skb, ie_DISCONNECT);
+	if (ERR_IE_COMPREHENSION == ret)
+		cause = 96;
+	else if ((!cause) && (ERR_IE_UNRECOGNIZED == ret))
+		cause = 99;
+	ret = pc->state;
 	newl3state(pc, 12);
-	pc->para.cause = cause;
-	pc->st->l3.l3l4(pc, CC_DISCONNECT_IND, NULL);
+	if (cause)
+		newl3state(pc, 19);
+       	if (11 != ret)
+		pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc);
+       	else if (!cause)
+		   l3dss1_release_req(pc, pr, NULL);
+	if (cause) {
+		l3dss1_message_cause(pc, MT_RELEASE, cause);
+		L3AddTimer(&pc->timer, T308, CC_T308_1);
+	}
 }
 
 static void
 l3dss1_connect(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	int ret;
 
-	dev_kfree_skb(skb);
+	ret = check_infoelements(pc, skb, ie_CONNECT);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);	/* T310 */
 	newl3state(pc, 10);
 	pc->para.chargeinfo = 0;
-	pc->st->l3.l3l4(pc, CC_SETUP_CNF, NULL);
+	/* here should inserted COLP handling KKe */
+	if (ret)
+		l3dss1_std_ie_err(pc, ret);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc);
 }
 
 static void
 l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb = arg;
+	int ret;
 
-	dev_kfree_skb(skb);
+	ret = check_infoelements(pc, skb, ie_ALERTING);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
 	L3DelTimer(&pc->timer);	/* T304 */
 	newl3state(pc, 4);
-	pc->st->l3.l3l4(pc, CC_ALERTING_IND, NULL);
-}
-
-static void
-l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg)
-{
-  /* This routine is called if here was no SETUP made (checks in dss1up and in
-   * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code
-   * It is called after it is veryfied that Layer2 is up.
-   * The cause value is allready in pc->para.cause
-   * MT_STATUS_ENQUIRE in the NULL state is handled too
-   */
-	u_char tmp[16];
-	u_char *p=tmp;
-	int l;
-	struct sk_buff *skb;
-
-	switch (pc->para.cause) {
-	  case  81: /* 0x51 invalid callreference */
-	  case  96: /* 0x60 mandory IE missing */
-	  case 101: /* 0x65 incompatible Callstate */
-	  	MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
-		*p++ = IE_CAUSE;
-		*p++ = 0x2;
-		*p++ = 0x80;
-		*p++ = pc->para.cause | 0x80;
-		break;
-	  default:
-	  	printk(KERN_ERR "HiSax internal error l3dss1_msg_without_setup\n");
-	  	return;
-	}	
-	l = p - tmp;
-	if (!(skb = l3_alloc_skb(l)))
-		return;
-	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
-	release_l3_process(pc);
+	if (ret)
+		l3dss1_std_ie_err(pc, ret);
+	pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc);
 }
 
 static void
 l3dss1_setup(struct l3_process *pc, u_char pr, void *arg)
 {
-        u_char *p, *ptmp[8];
-	int i;
+	u_char *p;
 	int bcfound = 0;
 	char tmp[80];
 	struct sk_buff *skb = arg;
-
-	/* ETS 300-104 1.3.4 and 1.3.5
-	 * we need to detect unknown inform. element from 0 to 7
-	 */	
-	p = skb->data;
-	for(i = 0; i < 8; i++)
-		ptmp[i] = skb->data;
-	if (findie(ptmp[1], skb->len, 0x01, 0)
-	    || findie(ptmp[2], skb->len, 0x02, 0)
-	    || findie(ptmp[3], skb->len, 0x03, 0)
-	    || findie(ptmp[5], skb->len, 0x05, 0)
-	    || findie(ptmp[6], skb->len, 0x06, 0)
-	    || findie(ptmp[7], skb->len, 0x07, 0)) {
-	  	/* if ie is < 8 and not 0 nor 4, send RELEASE_COMPLETE 
-	  	 * cause 0x60
-	  	 */
-	  	pc->para.cause = 0x60;
-		dev_kfree_skb(skb);
-		if (pc->state == 0)
-			pc->st->l3.l3l4(pc, CC_ESTABLISH, NULL);
-		else
-			l3dss1_msg_without_setup(pc, pr, NULL);
-		return;
-	}
-
-	/*
-	 * Channel Identification
-	 */
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
-		pc->para.bchannel = p[2] & 0x3;
-		if (pc->para.bchannel)
-			bcfound++;
-		else if (pc->debug & L3_DEB_WARN)
-			l3_debug(pc->st, "setup without bchannel");
-	} else if (pc->debug & L3_DEB_WARN)
-		l3_debug(pc->st, "setup without bchannel");
+	int id;
+	int err = 0;
 
 	/*
-	   * Bearer Capabilities
+	 * Bearer Capabilities
 	 */
 	p = skb->data;
+	/* only the first occurence 'll be detected ! */
 	if ((p = findie(p, skb->len, 0x04, 0))) {
-		pc->para.setup.si2 = 0;
-		switch (p[2] & 0x1f) {
-			case 0x00:
-				/* Speech */
-			case 0x10:
-				/* 3.1 Khz audio */
-				pc->para.setup.si1 = 1;
-				break;
-			case 0x08:
-				/* Unrestricted digital information */
-				pc->para.setup.si1 = 7;
+		if ((p[1] < 2) || (p[1] > 11))
+			err = 1;
+		else {
+			pc->para.setup.si2 = 0;
+			switch (p[2] & 0x7f) {
+				case 0x00: /* Speech */
+				case 0x10: /* 3.1 Khz audio */
+					pc->para.setup.si1 = 1;
+					break;
+				case 0x08: /* Unrestricted digital information */
+					pc->para.setup.si1 = 7;
 /* JIM, 05.11.97 I wanna set service indicator 2 */
-#ifdef EXT_BEARER_CAPS
-                                pc->para.setup.si2 = DecodeSI2(skb);
-                                printk(KERN_DEBUG "HiSax: SI=%d, AI=%d\n",
-                                       pc->para.setup.si1, pc->para.setup.si2);
+#if EXT_BEARER_CAPS
+					pc->para.setup.si2 = DecodeSI2(skb);
+					if (pc->debug & L3_DEB_SI)
+						l3_debug(pc->st, "SI=%d, AI=%d",
+							pc->para.setup.si1,
+							pc->para.setup.si2);
 #endif
-				break;
-			case 0x09:
-				/* Restricted digital information */
-				pc->para.setup.si1 = 2;
-				break;
-			case 0x11:
-				/* Unrestr. digital information  with tones/announcements */
-				pc->para.setup.si1 = 3;
-				break;
-			case 0x18:
-				/* Video */
-				pc->para.setup.si1 = 4;
-				break;
-			default:
-				pc->para.setup.si1 = 0;
+					break;
+				case 0x09: /* Restricted digital information */
+					pc->para.setup.si1 = 2;
+					break;
+				case 0x11:
+					/* Unrestr. digital information  with 
+					 * tones/announcements ( or 7 kHz audio
+					 */
+					pc->para.setup.si1 = 3;
+					break;
+				case 0x18: /* Video */
+					pc->para.setup.si1 = 4;
+					break;
+				default:
+					err = 2;
+					break;
+			}
+			switch (p[3] & 0x7f) {
+				case 0x40: /* packed mode */
+					break;
+				case 0x10: /* 64 kbit */
+				case 0x11: /* 2*64 kbit */
+				case 0x13: /* 384 kbit */
+				case 0x15: /* 1536 kbit */
+				case 0x17: /* 1920 kbit */
+					pc->para.moderate = p[3] & 0x7f;
+					break;
+				default:
+					err = 3;
+					break;
+			}
+		}
+		if (err) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "setup with wrong bearer(l=%d:%x,%x)",
+					p[1], p[2], p[3]);
+			pc->para.cause = 100;
+			l3dss1_msg_without_setup(pc, pr, NULL);
+			return;
 		}
 	} else {
 		if (pc->debug & L3_DEB_WARN)
 			l3_debug(pc->st, "setup without bearer capabilities");
 		/* ETS 300-104 1.3.3 */
-	  	pc->para.cause = 0x60;
-		dev_kfree_skb(skb);
-		if (pc->state == 0)
-			pc->st->l3.l3l4(pc, CC_ESTABLISH, NULL);
-		else
-			l3dss1_msg_without_setup(pc, pr, NULL);
+		pc->para.cause = 96;
+		l3dss1_msg_without_setup(pc, pr, NULL);
 		return;
 	}
-
+	/*
+	 * Channel Identification
+	 */
+	if ((id = l3dss1_get_channel_id(pc, skb)) >= 0) {
+		if ((pc->para.bchannel = id)) {
+			if ((3 == id) && (0x10 == pc->para.moderate)) {
+				if (pc->debug & L3_DEB_WARN)
+					l3_debug(pc->st, "setup with wrong chid %x",
+						id);
+				pc->para.cause = 100;
+				l3dss1_msg_without_setup(pc, pr, NULL);
+				return;
+			}
+			bcfound++;
+		} else 
+                   { if (pc->debug & L3_DEB_WARN)
+			 l3_debug(pc->st, "setup without bchannel, call waiting");
+                     bcfound++;
+                   } 
+	} else {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "setup with wrong chid ret %d", id);
+		pc->para.cause = 96;
+		l3dss1_msg_without_setup(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+#if 1
+/* !!!!!! this check seems to be a problem ? info bugfix to Karsten */
+	err = check_infoelements(pc, skb, ie_SETUP);
+	if (ERR_IE_COMPREHENSION == err) {
+		pc->para.cause = 96;
+		l3dss1_msg_without_setup(pc, pr, NULL);
+		return;
+	}
+#endif
 	p = skb->data;
 	if ((p = findie(p, skb->len, 0x70, 0)))
 		iecpy(pc->para.setup.eazmsn, p, 1);
@@ -867,8 +1738,8 @@
 	p = skb->data;
 	if ((p = findie(p, skb->len, 0x71, 0))) {
 		/* Called party subaddress */
-		if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) {
-			tmp[0]='.';
+		if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
+			tmp[0] = '.';
 			iecpy(&tmp[1], p, 2);
 			strcat(pc->para.setup.eazmsn, tmp);
 		} else if (pc->debug & L3_DEB_WARN)
@@ -892,65 +1763,54 @@
 	p = skb->data;
 	if ((p = findie(p, skb->len, 0x6d, 0))) {
 		/* Calling party subaddress */
-		if ((p[1]>=2) && (p[2]==0x80) && (p[3]==0x50)) {
-			tmp[0]='.';
+		if ((p[1] >= 2) && (p[2] == 0x80) && (p[3] == 0x50)) {
+			tmp[0] = '.';
 			iecpy(&tmp[1], p, 2);
 			strcat(pc->para.setup.phone, tmp);
 		} else if (pc->debug & L3_DEB_WARN)
 			l3_debug(pc->st, "wrong calling subaddress");
 	}
 
-	dev_kfree_skb(skb);
-
+#if 0
 	if (bcfound) {
 		if ((pc->para.setup.si1 != 7) && (pc->debug & L3_DEB_WARN)) {
-			sprintf(tmp, "non-digital call: %s -> %s",
-				pc->para.setup.phone, pc->para.setup.eazmsn);
-			l3_debug(pc->st, tmp);
+			l3_debug(pc->st, "non-digital call: %s -> %s",
+			    pc->para.setup.phone, pc->para.setup.eazmsn);
+		}
+		if ((pc->para.setup.si1 != 7) &&
+		    test_bit(FLG_PTP, &pc->st->l2.flag)) {
+			pc->para.cause = 88; /* incompatible destination */
+			l3dss1_msg_without_setup(pc, pr, NULL);
+			return;
 		}
 		newl3state(pc, 6);
-		pc->st->l3.l3l4(pc, CC_SETUP_IND, NULL);
+		pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
 	} else
-		release_l3_process(pc);
+		dss1_release_l3_process(pc);
+#else
+	newl3state(pc, 6);
+	if (err) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, err);
+	pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc);
+#endif
 }
 
 static void
 l3dss1_reset(struct l3_process *pc, u_char pr, void *arg)
 {
-	release_l3_process(pc);
-}
-
-static void
-l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
-		 void *arg)
-{
-	newl3state(pc, 8);
-	l3dss1_message(pc, MT_CONNECT);
-	L3DelTimer(&pc->timer);
-	L3AddTimer(&pc->timer, T313, CC_T313);
-}
-
-static void
-l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
-{
-	struct sk_buff *skb = arg;
-
-	dev_kfree_skb(skb);
-	newl3state(pc, 10);
-	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_SETUP_COMPLETE_IND, NULL);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
-	u_char tmp[16];
+	u_char tmp[16+40];
 	u_char *p = tmp;
 	int l;
-	u_char cause = 0x10;
+	u_char cause = 16;
 
-	if (pc->para.cause > 0)
+	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
 
 	StopAllL3Timer(pc);
@@ -962,25 +1822,68 @@
 	*p++ = 0x80;
 	*p++ = cause | 0x80;
 
+        if (pc->prot.dss1.uus1_data[0])
+	 { *p++ = IE_USER_USER; /* UUS info element */
+           *p++ = strlen(pc->prot.dss1.uus1_data) + 1;
+           *p++ = 0x04; /* IA5 chars */
+           strcpy(p,pc->prot.dss1.uus1_data);
+           p += strlen(pc->prot.dss1.uus1_data);
+           pc->prot.dss1.uus1_data[0] = '\0';   
+         } 
+
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
 	newl3state(pc, 11);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3AddTimer(&pc->timer, T305, CC_T305);
 }
 
 static void
+l3dss1_setup_rsp(struct l3_process *pc, u_char pr,
+		 void *arg)
+{
+        if (!pc->para.bchannel) 
+	 { if (pc->debug & L3_DEB_WARN)
+	       l3_debug(pc->st, "D-chan connect for waiting call");
+           l3dss1_disconnect_req(pc, pr, arg);
+           return;
+         }
+	newl3state(pc, 8);
+	l3dss1_message(pc, MT_CONNECT);
+	L3DelTimer(&pc->timer);
+	L3AddTimer(&pc->timer, T313, CC_T313);
+}
+
+static void
+l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int ret;
+
+	ret = check_infoelements(pc, skb, ie_CONNECT_ACKNOWLEDGE);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
+	newl3state(pc, 10);
+	L3DelTimer(&pc->timer);
+	if (ret)
+		l3dss1_std_ie_err(pc, ret);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc);
+}
+
+static void
 l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg)
 {
 	struct sk_buff *skb;
 	u_char tmp[16];
 	u_char *p = tmp;
 	int l;
-	u_char cause = 0x95;
+	u_char cause = 21;
 
-	if (pc->para.cause > 0)
+	if (pc->para.cause != NO_CAUSE)
 		cause = pc->para.cause;
 
 	MsgHead(p, pc->callref, MT_RELEASE_COMPLETE);
@@ -988,47 +1891,50 @@
 	*p++ = IE_CAUSE;
 	*p++ = 0x2;
 	*p++ = 0x80;
-	*p++ = cause;
+	*p++ = cause | 0x80;
 
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
-	pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
-	release_l3_process(pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_release(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char *p;
 	struct sk_buff *skb = arg;
-	int cause = -1;
+	u_char *p;
+	int ret, cause=0;
 
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
-		p++;
-		if (*p++ == 2)
-			pc->para.loc = *p++;
-		cause = *p & 0x7f;
-	}
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
-#ifdef HISAX_DE_AOC
-	    l3dss1_parse_facility(pc,p);
-#else
-		p = NULL;
-#endif
-	}
-	dev_kfree_skb(skb);
 	StopAllL3Timer(pc);
-	pc->para.cause = cause;
-	l3dss1_message(pc, MT_RELEASE_COMPLETE);
-	pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+	if ((ret = l3dss1_get_cause(pc, skb))>0) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "REL get_cause ret(%d)", ret);
+	} else if (ret<0)
+		pc->para.cause = NO_CAUSE;
+	if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
+		l3dss1_parse_facility(pc->st, pc, pc->callref, p);
+	}
+	if ((ret<0) && (pc->state != 11))
+		cause = 96;
+	else if (ret>0)
+		cause = 100;
+	ret = check_infoelements(pc, skb, ie_RELEASE);
+	if (ERR_IE_COMPREHENSION == ret)
+		cause = 96;
+	else if ((ERR_IE_UNRECOGNIZED == ret) && (!cause))
+		cause = 99;  
+	if (cause)
+		l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause);
+	else
+		l3dss1_message(pc, MT_RELEASE_COMPLETE);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 	newl3state(pc, 0);
-	release_l3_process(pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
@@ -1036,66 +1942,350 @@
 		 void *arg)
 {
 	newl3state(pc, 7);
-	l3dss1_message(pc, MT_ALERTING);
+	if (!pc->prot.dss1.uus1_data[0]) 
+		l3dss1_message(pc, MT_ALERTING);
+	else
+		l3dss1_msg_with_uus(pc, MT_ALERTING); 
+}
+
+static void
+l3dss1_proceed_req(struct l3_process *pc, u_char pr,
+		   void *arg)
+{
+	newl3state(pc, 9);
+	l3dss1_message(pc, MT_CALL_PROCEEDING);
+	pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); 
+}
+
+/********************************************/
+/* deliver a incoming display message to HL */
+/********************************************/
+static void
+l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp)
+{       u_char len;
+        isdn_ctrl ic; 
+	struct IsdnCardState *cs;
+        char *p; 
+
+        if (*infp++ != IE_DISPLAY) return;
+        if ((len = *infp++) > 80) return; /* total length <= 82 */
+	if (!pc->chan) return;
+
+	p = ic.parm.display; 
+        while (len--)
+	  *p++ = *infp++;
+	*p = '\0';
+	ic.command = ISDN_STAT_DISPLAY;
+	cs = pc->st->l1.hardware;
+	ic.driver = cs->myid;
+	ic.arg = pc->chan->chan; 
+	cs->iif.statcallb(&ic);
+} /* l3dss1_deliver_display */
+
+
+static void
+l3dss1_progress(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int err = 0;
+	u_char *p;
+
+	if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) {
+		if (p[1] != 4) {
+			err = 1;
+			pc->para.cause = 100;
+		} else if (p[2] & 0x60) {
+			switch (p[2]) {
+				case 0x80:
+				case 0x81:
+				case 0x82:
+				case 0x84:
+				case 0x85:
+				case 0x87:
+				case 0x8a:
+					switch (p[3]) {
+						case 0x81:
+						case 0x82:
+						case 0x83:
+						case 0x84:
+						case 0x88:
+							break;
+						default:
+							err = 2;
+							pc->para.cause = 100;
+							break;
+					}
+					break;
+				default:
+					err = 3;
+					pc->para.cause = 100;
+					break;
+			}
+		}
+	} else {
+		pc->para.cause = 96;
+		err = 4;
+	}
+	if (err) {	
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "progress error %d", err);
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	err = check_infoelements(pc, skb, ie_PROGRESS);
+	if (err)
+		l3dss1_std_ie_err(pc, err);
+	if (ERR_IE_COMPREHENSION != err)
+		pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc);
+}
+
+static void
+l3dss1_notify(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int err = 0;
+	u_char *p;
+
+	if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) {
+		if (p[1] != 1) {
+			err = 1;
+			pc->para.cause = 100;
+		} else {
+			switch (p[2]) {
+				case 0x80:
+				case 0x81:
+				case 0x82:
+					break;
+				default:
+					pc->para.cause = 100;
+					err = 2;
+					break;
+			}
+		}
+	} else {
+		pc->para.cause = 96;
+		err = 3;
+	}
+	if (err) {	
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "notify error %d", err);
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	/* Now we are on none mandatory IEs */
+	err = check_infoelements(pc, skb, ie_NOTIFY);
+	if (err)
+		l3dss1_std_ie_err(pc, err);
+	if (ERR_IE_COMPREHENSION != err)
+		pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc);
 }
 
 static void
 l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg)
 {
-	u_char tmp[16];
-	u_char *p = tmp;
-	int l;
+	int ret;
 	struct sk_buff *skb = arg;
 
-	dev_kfree_skb(skb);
-
-	MsgHead(p, pc->callref, MT_STATUS);
-
-	*p++ = IE_CAUSE;
-	*p++ = 0x2;
-	*p++ = 0x80;
-	*p++ = 0x9E;		/* answer status enquire */
+	ret = check_infoelements(pc, skb, ie_STATUS_ENQUIRY);
+	l3dss1_std_ie_err(pc, ret);
 
-	*p++ = 0x14;		/* CallState */
-	*p++ = 0x1;
-	*p++ = pc->state & 0x3f;
+        idev_kfree_skb(skb, FREE_READ);
 
-	l = p - tmp;
-	if (!(skb = l3_alloc_skb(l)))
-		return;
-	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+        l3dss1_status_send(pc, 0x1E, NULL);   /* answer status enquire */
 }
 
-static void
-l3dss1_status_req(struct l3_process *pc, u_char pr, void *arg)
+/******************************/
+/* handle deflection requests */
+/******************************/
+static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg)
 {
-  /* ETS 300-104 7.4.1, 8.4.1, 10.3.1, 11.4.1, 12.4.1, 13.4.1, 14.4.1...
-     if setup has been made and a non expected message type is received, we must send MT_STATUS cause 0x62  */
-        u_char tmp[16];
+	struct sk_buff *skb;
+	u_char tmp[128];
 	u_char *p = tmp;
-	int l;
-	struct sk_buff *skb = arg;
+        u_char *subp;
+        u_char len_phone = 0;
+        u_char len_sub = 0;
+	int l; 
+
+
+        strcpy(pc->prot.dss1.uus1_data,pc->chan->setup.eazmsn); /* copy uus element if available */
+        if (!pc->chan->setup.phone[0])
+          { pc->para.cause = -1;
+            l3dss1_disconnect_req(pc,pr,arg); /* disconnect immediately */
+            return;
+          } /* only uus */
+ 
+        if (pc->prot.dss1.invoke_id) 
+          free_invoke_id(pc->st,pc->prot.dss1.invoke_id);
+ 
+        if (!(pc->prot.dss1.invoke_id = new_invoke_id(pc->st))) 
+          return;
+
+        MsgHead(p, pc->callref, MT_FACILITY);
+
+        for (subp = pc->chan->setup.phone; (*subp) && (*subp != '.'); subp++) len_phone++; /* len of phone number */
+        if (*subp++ == '.') len_sub = strlen(subp) + 2; /* length including info subadress element */ 
+
+	*p++ = 0x1c;   /* Facility info element */
+        *p++ = len_phone + len_sub + 2 + 2 + 8 + 3 + 3; /* length of element */
+        *p++ = 0x91;  /* remote operations protocol */
+        *p++ = 0xa1;  /* invoke component */
+	  
+        *p++ = len_phone + len_sub + 2 + 2 + 8 + 3; /* length of data */
+        *p++ = 0x02;  /* invoke id tag, integer */
+	*p++ = 0x01;  /* length */
+        *p++ = pc->prot.dss1.invoke_id;  /* invoke id */ 
+        *p++ = 0x02;  /* operation value tag, integer */
+	*p++ = 0x01;  /* length */
+        *p++ = 0x0D;  /* Call Deflect */
+	  
+        *p++ = 0x30;  /* sequence phone number */
+        *p++ = len_phone + 2 + 2 + 3 + len_sub; /* length */
+	  
+        *p++ = 0x30;  /* Deflected to UserNumber */
+        *p++ = len_phone+2+len_sub; /* length */
+        *p++ = 0x80; /* NumberDigits */
+	*p++ = len_phone; /* length */
+        for (l = 0; l < len_phone; l++)
+	 *p++ = pc->chan->setup.phone[l];
+
+        if (len_sub)
+	  { *p++ = 0x04; /* called party subadress */
+            *p++ = len_sub - 2;
+            while (*subp) *p++ = *subp++;
+          }
 
-	dev_kfree_skb(skb);
+        *p++ = 0x01; /* screening identifier */
+        *p++ = 0x01;
+        *p++ = pc->chan->setup.screen;
 
-	MsgHead(p, pc->callref, MT_STATUS);
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l))) return;
+	memcpy(skb_put(skb, l), tmp, l);
 
-	*p++ = IE_CAUSE;
-	*p++ = 0x2;
-	*p++ = 0x80;
-	*p++ = 0x62 | 0x80;		/* status sending */
+        l3_msg(pc->st, DL_DATA | REQUEST, skb);
+} /* l3dss1_redir_req */
 
-	*p++ = 0x14;		/* CallState */
-	*p++ = 0x1;
-	*p++ = pc->state & 0x3f;
+/********************************************/
+/* handle deflection request in early state */
+/********************************************/
+static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg)
+{
+  l3dss1_proceed_req(pc,pr,arg);
+  l3dss1_redir_req(pc,pr,arg);
+} /* l3dss1_redir_req_early */
+
+/***********************************************/
+/* handle special commands for this protocol.  */
+/* Examples are call independant services like */
+/* remote operations with dummy  callref.      */
+/***********************************************/
+static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
+{ u_char id;
+  u_char temp[265];
+  u_char *p = temp;
+  int i, l, proc_len; 
+  struct sk_buff *skb;
+  struct l3_process *pc = NULL;
+
+  switch (ic->arg)
+   { case DSS1_CMD_INVOKE:
+       if (ic->parm.dss1_io.datalen < 0) return(-2); /* invalid parameter */ 
+
+       for (proc_len = 1, i = ic->parm.dss1_io.proc >> 8; i; i++) 
+         i = i >> 8; /* add one byte */    
+       l = ic->parm.dss1_io.datalen + proc_len + 8; /* length excluding ie header */
+       if (l > 255) 
+         return(-2); /* too long */
+
+       if (!(id = new_invoke_id(st))) 
+         return(0); /* first get a invoke id -> return if no available */
+       
+       i = -1; 
+       MsgHead(p, i, MT_FACILITY); /* build message head */
+       *p++ = 0x1C; /* Facility IE */
+       *p++ = l; /* length of ie */
+       *p++ = 0x91; /* remote operations */
+       *p++ = 0xA1; /* invoke */
+       *p++ = l - 3; /* length of invoke */
+       *p++ = 0x02; /* invoke id tag */
+       *p++ = 0x01; /* length is 1 */
+       *p++ = id; /* invoke id */
+       *p++ = 0x02; /* operation */
+       *p++ = proc_len; /* length of operation */
+       
+       for (i = proc_len; i; i--)
+         *p++ = (ic->parm.dss1_io.proc >> (i-1)) & 0xFF;
+       memcpy(p, ic->parm.dss1_io.data, ic->parm.dss1_io.datalen); /* copy data */
+       l = (p - temp) + ic->parm.dss1_io.datalen; /* total length */         
+
+       if (ic->parm.dss1_io.timeout > 0)
+        if (!(pc = dss1_new_l3_process(st, -1)))
+          { free_invoke_id(st, id);
+            return(-2);
+          } 
+       pc->prot.dss1.ll_id = ic->parm.dss1_io.ll_id; /* remember id */ 
+       pc->prot.dss1.proc = ic->parm.dss1_io.proc; /* and procedure */
+
+       if (!(skb = l3_alloc_skb(l))) 
+         { free_invoke_id(st, id);
+           if (pc) dss1_release_l3_process(pc);
+           return(-2);
+         }
+       memcpy(skb_put(skb, l), temp, l);
+       
+       if (pc)
+        { pc->prot.dss1.invoke_id = id; /* remember id */
+          L3AddTimer(&pc->timer, ic->parm.dss1_io.timeout, CC_TDSS1_IO | REQUEST);
+        }
+       
+       l3_msg(st, DL_DATA | REQUEST, skb);
+       ic->parm.dss1_io.hl_id = id; /* return id */
+       return(0);
+
+     case DSS1_CMD_INVOKE_ABORT:
+       if ((pc = l3dss1_search_dummy_proc(st, ic->parm.dss1_io.hl_id)))
+	{ L3DelTimer(&pc->timer); /* remove timer */
+          dss1_release_l3_process(pc);
+          return(0); 
+        } 
+       else
+	{ l3_debug(st, "l3dss1_cmd_global abort unknown id");
+          return(-2);
+        } 
+       break;
+    
+     default: 
+       l3_debug(st, "l3dss1_cmd_global unknown cmd 0x%lx", ic->arg);
+       return(-1);  
+   } /* switch ic-> arg */
+  return(-1);
+} /* l3dss1_cmd_global */
+
+static void 
+l3dss1_io_timer(struct l3_process *pc)
+{ isdn_ctrl ic;
+  struct IsdnCardState *cs = pc->st->l1.hardware;
+
+  L3DelTimer(&pc->timer); /* remove timer */
+
+  ic.driver = cs->myid;
+  ic.command = ISDN_STAT_PROT;
+  ic.arg = DSS1_STAT_INVOKE_ERR;
+  ic.parm.dss1_io.hl_id = pc->prot.dss1.invoke_id;
+  ic.parm.dss1_io.ll_id = pc->prot.dss1.ll_id;
+  ic.parm.dss1_io.proc = pc->prot.dss1.proc;
+  ic.parm.dss1_io.timeout= -1;
+  ic.parm.dss1_io.datalen = 0;
+  ic.parm.dss1_io.data = NULL;
+  free_invoke_id(pc->st, pc->prot.dss1.invoke_id);
+  pc->prot.dss1.invoke_id = 0; /* reset id */
 
-	l = p - tmp;
-	if (!(skb = l3_alloc_skb(l)))
-		return;
-	memcpy(skb_put(skb, l), tmp, l);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
-}
+  cs->iif.statcallb(&ic);
+
+  dss1_release_l3_process(pc); 
+} /* l3dss1_io_timer */
 
 static void
 l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg)
@@ -1107,22 +2297,27 @@
 
 	if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
 		p++;
-		if (1== *p++)
+		if (1 == *p++)
 			callState = *p;
 	}
-	if(callState == 0) {
+	if (callState == 0) {
 		/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
 		 * set down layer 3 without sending any message
 		 */
-		pc->st->l3.l3l4(pc, CC_RELEASE_IND, NULL);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
 		newl3state(pc, 0);
-		release_l3_process(pc);
+		dss1_release_l3_process(pc);
 	} else {
-		pc->st->l3.l3l4(pc, CC_IGNORE, NULL);
+		pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc);
 	}
 }
 
 static void
+l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg)
+{
+}
+
+static void
 l3dss1_t303(struct l3_process *pc, u_char pr, void *arg)
 {
 	if (pc->N303 > 0) {
@@ -1131,8 +2326,8 @@
 		l3dss1_setup_req(pc, pr, arg);
 	} else {
 		L3DelTimer(&pc->timer);
-		pc->st->l3.l3l4(pc, CC_NOSETUP_RSP_ERR, NULL);
-		release_l3_process(pc);
+		pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc);
+		dss1_release_l3_process(pc);
 	}
 }
 
@@ -1140,9 +2335,9 @@
 l3dss1_t304(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0xE6;
+	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 
 }
 
@@ -1153,25 +2348,25 @@
 	u_char *p = tmp;
 	int l;
 	struct sk_buff *skb;
-	u_char cause = 0x90;
+	u_char cause = 16;
 
 	L3DelTimer(&pc->timer);
-	if (pc->para.cause > 0)
-		cause = pc->para.cause | 0x80;
+	if (pc->para.cause != NO_CAUSE)
+		cause = pc->para.cause;
 
 	MsgHead(p, pc->callref, MT_RELEASE);
 
 	*p++ = IE_CAUSE;
 	*p++ = 0x2;
 	*p++ = 0x80;
-	*p++ = cause;
+	*p++ = cause | 0x80;
 
 	l = p - tmp;
 	if (!(skb = l3_alloc_skb(l)))
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
 	newl3state(pc, 19);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
 	L3AddTimer(&pc->timer, T308, CC_T308_1);
 }
 
@@ -1179,18 +2374,18 @@
 l3dss1_t310(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0xE6;
+	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_SETUP_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
 }
 
 static void
 l3dss1_t313(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->para.cause = 0xE6;
+	pc->para.cause = 102;
 	l3dss1_disconnect_req(pc, pr, NULL);
-	pc->st->l3.l3l4(pc, CC_CONNECT_ERR, NULL);
+	pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc);
 }
 
 static void
@@ -1206,118 +2401,315 @@
 l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_RELEASE_ERR, NULL);
-	release_l3_process(pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc);
+	dss1_release_l3_process(pc);
+}
+
+static void
+l3dss1_t318(struct l3_process *pc, u_char pr, void *arg)
+{
+	L3DelTimer(&pc->timer);
+	pc->para.cause = 102;	/* Timer expiry */
+	pc->para.loc = 0;	/* local */
+	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
+	newl3state(pc, 19);
+	l3dss1_message(pc, MT_RELEASE);
+	L3AddTimer(&pc->timer, T308, CC_T308_1);
+}
+
+static void
+l3dss1_t319(struct l3_process *pc, u_char pr, void *arg)
+{
+	L3DelTimer(&pc->timer);
+	pc->para.cause = 102;	/* Timer expiry */
+	pc->para.loc = 0;	/* local */
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
+	newl3state(pc, 10);
 }
 
 static void
 l3dss1_restart(struct l3_process *pc, u_char pr, void *arg)
 {
 	L3DelTimer(&pc->timer);
-	pc->st->l3.l3l4(pc, CC_DLRL, NULL);
-	release_l3_process(pc);
+	pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+	dss1_release_l3_process(pc);
 }
 
 static void
 l3dss1_status(struct l3_process *pc, u_char pr, void *arg)
 {
 	u_char *p;
-	char tmp[64], *t;
-	int l;
 	struct sk_buff *skb = arg;
-	int cause, callState;
-
-	cause = callState = -1;
-	p = skb->data;
-	t = tmp;
-	if ((p = findie(p, skb->len, IE_CAUSE, 0))) {
+	int ret; 
+	u_char cause = 0, callState = 0;
+	
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "STATUS get_cause ret(%d)",ret);
+		if (ret < 0)
+			cause = 96;
+		else if (ret > 0)
+			cause = 100;
+	}
+	if ((p = findie(skb->data, skb->len, IE_CALL_STATE, 0))) {
 		p++;
-		l = *p++;
-		t += sprintf(t,"Status CR %x Cause:", pc->callref);
-		while (l--) {
-		        cause = *p;
-			t += sprintf(t," %2x",*p++);
-		}
+		if (1 == *p++) {
+			callState = *p;
+			if (!ie_in_set(pc, *p, l3_valid_states))
+				cause = 100;
+		} else
+			cause = 100;
 	} else
-		sprintf(t,"Status CR %x no Cause", pc->callref);
-	l3_debug(pc->st, tmp);
-	p = skb->data;
-	t = tmp;
-	t += sprintf(t,"Status state %x ", pc->state);
-	if ((p = findie(p, skb->len, IE_CALL_STATE, 0))) {
-		p++;
-		if (1== *p++) {
-		        callState = *p;
-			t += sprintf(t,"peer state %x" , *p);
-		}
+		cause = 96;
+	if (!cause) { /*  no error before */
+		ret = check_infoelements(pc, skb, ie_STATUS);
+		if (ERR_IE_COMPREHENSION == ret)
+			cause = 96;
+		else if (ERR_IE_UNRECOGNIZED == ret)
+			cause = 99;
+	}
+	if (cause) {
+		u_char tmp;
+		
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause);
+		tmp = pc->para.cause;
+		pc->para.cause = cause;
+		l3dss1_status_send(pc, 0, NULL);
+		if (cause == 99)
+			pc->para.cause = tmp;
 		else
-			t += sprintf(t,"peer state len error");
-	} else
-		sprintf(t,"no peer state");
-	l3_debug(pc->st, tmp);
-	if(((cause & 0x7f) == 0x6f) && (callState == 0)) {
-		/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... 
-		 * if received MT_STATUS with cause == 0x6f and call 
+			return;
+	}
+	cause = pc->para.cause;
+	if (((cause & 0x7f) == 111) && (callState == 0)) {
+		/* ETS 300-104 7.6.1, 8.6.1, 10.6.1...
+		 * if received MT_STATUS with cause == 111 and call
 		 * state == 0, then we must set down layer 3
 		 */
-		l3dss1_release_ind(pc, pr, arg);
-	} else
-		dev_kfree_skb(skb);
+		pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+		newl3state(pc, 0);
+		dss1_release_l3_process(pc);
+	}
 }
 
 static void
 l3dss1_facility(struct l3_process *pc, u_char pr, void *arg)
 {
-        u_char *p;
 	struct sk_buff *skb = arg;
+	int ret;
+	
+	ret = check_infoelements(pc, skb, ie_FACILITY);
+	l3dss1_std_ie_err(pc, ret);
+ 	  {
+		u_char *p;
+		if ((p = findie(skb->data, skb->len, IE_FACILITY, 0)))
+			l3dss1_parse_facility(pc->st, pc, pc->callref, p);
+	}
+}
 
-	p = skb->data;
-	if ((p = findie(p, skb->len, IE_FACILITY, 0))) {
-#ifdef HISAX_DE_AOC
-	    l3dss1_parse_facility(pc,p);
-#else
-		p = NULL;
-#endif
+static void
+l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb;
+	u_char tmp[32];
+	u_char *p = tmp;
+	u_char i, l;
+	u_char *msg = pc->chan->setup.phone;
+
+	MsgHead(p, pc->callref, MT_SUSPEND);
+
+	*p++ = IE_CALL_ID;
+	l = *msg++;
+	if (l && (l <= 10)) {	/* Max length 10 octets */
+		*p++ = l;
+		for (i = 0; i < l; i++)
+			*p++ = *msg++;
+	} else {
+		l3_debug(pc->st, "SUS wrong CALL_ID len %d", l);
+		return;
 	}
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+	newl3state(pc, 15);
+	L3AddTimer(&pc->timer, T319, CC_T319);
 }
 
+static void
+l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int ret;
+
+	L3DelTimer(&pc->timer);
+	newl3state(pc, 0);
+	pc->para.cause = NO_CAUSE;
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc);
+	/* We don't handle suspend_ack for IE errors now */
+	if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE)))
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "SUSPACK check ie(%d)",ret);
+	dss1_release_l3_process(pc);
+}
+
+static void
+l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int ret;
+
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "SUSP_REJ get_cause ret(%d)",ret);
+		if (ret < 0) 
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	ret = check_infoelements(pc, skb, ie_SUSPEND_REJECT);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
+	L3DelTimer(&pc->timer);
+	pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc);
+	newl3state(pc, 10);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
+}
+
+static void
+l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb;
+	u_char tmp[32];
+	u_char *p = tmp;
+	u_char i, l;
+	u_char *msg = pc->para.setup.phone;
+
+	MsgHead(p, pc->callref, MT_RESUME);
+
+	*p++ = IE_CALL_ID;
+	l = *msg++;
+	if (l && (l <= 10)) {	/* Max length 10 octets */
+		*p++ = l;
+		for (i = 0; i < l; i++)
+			*p++ = *msg++;
+	} else {
+		l3_debug(pc->st, "RES wrong CALL_ID len %d", l);
+		return;
+	}
+	l = p - tmp;
+	if (!(skb = l3_alloc_skb(l)))
+		return;
+	memcpy(skb_put(skb, l), tmp, l);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+	newl3state(pc, 17);
+	L3AddTimer(&pc->timer, T319, CC_T319);
+}
+
+static void
+l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int id, ret;
+
+	if ((id = l3dss1_get_channel_id(pc, skb)) > 0) {
+		if ((0 == id) || ((3 == id) && (0x10 == pc->para.moderate))) {
+			if (pc->debug & L3_DEB_WARN)
+				l3_debug(pc->st, "resume ack with wrong chid %x", id);
+			pc->para.cause = 100;
+			l3dss1_status_send(pc, pr, NULL);
+			return;
+		}
+		pc->para.bchannel = id;
+	} else if (1 == pc->state) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "resume ack without chid (ret %d)", id);
+		pc->para.cause = 96;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	ret = check_infoelements(pc, skb, ie_RESUME_ACKNOWLEDGE);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
+	L3DelTimer(&pc->timer);
+	pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc);
+	newl3state(pc, 10);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
+}
+
+static void
+l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg)
+{
+	struct sk_buff *skb = arg;
+	int ret;
+
+	if ((ret = l3dss1_get_cause(pc, skb))) {
+		if (pc->debug & L3_DEB_WARN)
+			l3_debug(pc->st, "RES_REJ get_cause ret(%d)",ret);
+		if (ret < 0) 
+			pc->para.cause = 96;
+		else
+			pc->para.cause = 100;
+		l3dss1_status_send(pc, pr, NULL);
+		return;
+	}
+	ret = check_infoelements(pc, skb, ie_RESUME_REJECT);
+	if (ERR_IE_COMPREHENSION == ret) {
+		l3dss1_std_ie_err(pc, ret);
+		return;
+	}
+	L3DelTimer(&pc->timer);
+	pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc);
+	newl3state(pc, 0);
+	if (ret) /* STATUS for none mandatory IE errors after actions are taken */
+		l3dss1_std_ie_err(pc, ret);
+	dss1_release_l3_process(pc);
+}
 
-	
 static void
 l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg)
 {
 	u_char tmp[32];
 	u_char *p;
-	u_char ri, chan=0;
+	u_char ri, ch = 0, chan = 0;
 	int l;
 	struct sk_buff *skb = arg;
 	struct l3_process *up;
-	
+
 	newl3state(pc, 2);
 	L3DelTimer(&pc->timer);
 	p = skb->data;
 	if ((p = findie(p, skb->len, IE_RESTART_IND, 0))) {
-	        ri = p[2];
-	        sprintf(tmp, "Restart %x", ri);
+		ri = p[2];
+		l3_debug(pc->st, "Restart %x", ri);
 	} else {
-		sprintf(tmp, "Restart without restart IE");
+		l3_debug(pc->st, "Restart without restart IE");
 		ri = 0x86;
 	}
-	l3_debug(pc->st, tmp);
 	p = skb->data;
 	if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) {
 		chan = p[2] & 3;
-		sprintf(tmp, "Restart for channel %d", chan);
-		l3_debug(pc->st, tmp);
+		ch = p[2];
+		if (pc->st->l3.debug)
+			l3_debug(pc->st, "Restart for channel %d", chan);
 	}
-	dev_kfree_skb(skb);
 	newl3state(pc, 2);
 	up = pc->st->l3.proc;
 	while (up) {
-		if ((ri & 7)==7)
-			up->st->lli.l4l3(up->st, CC_RESTART, up);
+		if ((ri & 7) == 7)
+			up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
 		else if (up->para.bchannel == chan)
-				up->st->lli.l4l3(up->st, CC_RESTART, up);
+			up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up);
 		up = up->next;
 	}
 	p = tmp;
@@ -1325,9 +2717,9 @@
 	if (chan) {
 		*p++ = IE_CHANNEL_ID;
 		*p++ = 1;
-		*p++ = chan | 0x80;
+		*p++ = ch | 0x80;
 	}
-	*p++ = 0x79; /* RESTART Ind */
+	*p++ = 0x79;		/* RESTART Ind */
 	*p++ = 1;
 	*p++ = ri;
 	l = p - tmp;
@@ -1335,32 +2727,75 @@
 		return;
 	memcpy(skb_put(skb, l), tmp, l);
 	newl3state(pc, 0);
-	pc->st->l3.l3l2(pc->st, DL_DATA, skb);
+	l3_msg(pc->st, DL_DATA | REQUEST, skb);
+}
+
+static void
+l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg)
+{
+        pc->para.cause = 0x29;          /* Temporary failure */
+        l3dss1_disconnect_req(pc, pr, NULL);
+        pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc);
+}
+
+static void
+l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg)
+{
+        newl3state(pc, 0);
+        pc->para.cause = 0x1b;          /* Destination out of order */
+        pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc);
+        release_l3_process(pc);
+}
+
+static void
+l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg)
+{
+        L3DelTimer(&pc->timer);
+        L3AddTimer(&pc->timer, T309, CC_T309);
+        l3_msg(pc->st, DL_ESTABLISH | REQUEST, NULL);
+}
+ 
+static void
+l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg)
+{
+        L3DelTimer(&pc->timer);
+ 
+        l3dss1_status_send(pc, 0x1F, NULL);   /* normal, unspecified */
 }
 
 /* *INDENT-OFF* */
 static struct stateentry downstatelist[] =
 {
 	{SBIT(0),
-	 CC_ESTABLISH, l3dss1_msg_without_setup},
+	 CC_SETUP | REQUEST, l3dss1_setup_req},
 	{SBIT(0),
-	 CC_SETUP_REQ, l3dss1_setup_req},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(10),
-	 CC_DISCONNECT_REQ, l3dss1_disconnect_req},
+	 CC_RESUME | REQUEST, l3dss1_resume_req},
+	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10),
+	 CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
 	{SBIT(12),
-	 CC_RELEASE_REQ, l3dss1_release_req},
+	 CC_RELEASE | REQUEST, l3dss1_release_req},
 	{ALL_STATES,
-	 CC_DLRL, l3dss1_reset},
-	{ALL_STATES,
-	 CC_RESTART, l3dss1_restart},
+	 CC_RESTART | REQUEST, l3dss1_restart},
 	{SBIT(6),
-	 CC_IGNORE, l3dss1_reset},
+	 CC_IGNORE | REQUEST, l3dss1_reset},
 	{SBIT(6),
-	 CC_REJECT_REQ, l3dss1_reject_req},
+	 CC_REJECT | REQUEST, l3dss1_reject_req},
 	{SBIT(6),
-	 CC_ALERTING_REQ, l3dss1_alert_req},
-	{SBIT(6) | SBIT(7),
-	 CC_SETUP_RSP, l3dss1_setup_rsp},
+	 CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
+	{SBIT(6) | SBIT(9),
+	 CC_ALERTING | REQUEST, l3dss1_alert_req},
+	{SBIT(6) | SBIT(7) | SBIT(9),
+	 CC_SETUP | RESPONSE, l3dss1_setup_rsp},
+	{SBIT(10),
+	 CC_SUSPEND | REQUEST, l3dss1_suspend_req},
+        {SBIT(6),
+         CC_PROCEED_SEND | REQUEST, l3dss1_proceed_req},
+        {SBIT(7) | SBIT(9),
+         CC_REDIR | REQUEST, l3dss1_redir_req},
+        {SBIT(6),
+         CC_REDIR | REQUEST, l3dss1_redir_req_early},
+        {SBIT(9) | SBIT(25),
+         CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
 	{SBIT(1),
 	 CC_T303, l3dss1_t303},
 	{SBIT(2),
@@ -1371,14 +2806,20 @@
 	 CC_T313, l3dss1_t313},
 	{SBIT(11),
 	 CC_T305, l3dss1_t305},
+	{SBIT(15),
+	 CC_T319, l3dss1_t319},
+	{SBIT(17),
+	 CC_T318, l3dss1_t318},
 	{SBIT(19),
 	 CC_T308_1, l3dss1_t308_1},
 	{SBIT(19),
 	 CC_T308_2, l3dss1_t308_2},
+	{SBIT(10),
+	 CC_T309, l3dss1_dl_release},
 };
 
-static int downsllen = sizeof(downstatelist) /
-sizeof(struct stateentry);
+#define DOWNSLLEN \
+	(sizeof(downstatelist) / sizeof(struct stateentry))
 
 static struct stateentry datastatelist[] =
 {
@@ -1394,90 +2835,109 @@
 	 MT_SETUP, l3dss1_setup},
 	{SBIT(1) | SBIT(2),
 	 MT_CALL_PROCEEDING, l3dss1_call_proc},
-	{SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_CALL_PROCEEDING, l3dss1_status_req},
 	{SBIT(1),
 	 MT_SETUP_ACKNOWLEDGE, l3dss1_setup_ack},
-	{SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_SETUP_ACKNOWLEDGE, l3dss1_status_req},
-	{SBIT(1) | SBIT(2) | SBIT(3),
+	{SBIT(2) | SBIT(3),
 	 MT_ALERTING, l3dss1_alerting},
-	{SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_ALERTING, l3dss1_status_req},
+	{SBIT(2) | SBIT(3),
+	 MT_PROGRESS, l3dss1_progress},
+	{SBIT(10) | SBIT(11) | SBIT(15),
+	 MT_NOTIFY, l3dss1_notify},
 	{SBIT(0) | SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
 	 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) | SBIT(19),
 	 MT_RELEASE_COMPLETE, l3dss1_release_cmpl},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10) |
-	 SBIT(11) | SBIT(12) | SBIT(15) | SBIT(17) /*| SBIT(19)*/,
+	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(12) | SBIT(15) /* | SBIT(17) | SBIT(19)*/,
 	 MT_RELEASE, l3dss1_release},
 	{SBIT(19),  MT_RELEASE, l3dss1_release_ind},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(10),
+	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(7) | SBIT(8) | SBIT(9) | SBIT(10) | SBIT(11) | SBIT(15),
 	 MT_DISCONNECT, l3dss1_disconnect},
-	{SBIT(11),
-	 MT_DISCONNECT, l3dss1_release_req},
+//	{SBIT(11),
+//	 MT_DISCONNECT, l3dss1_release_req},
+	{SBIT(19),
+	 MT_DISCONNECT, l3dss1_dummy},
 	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4),
 	 MT_CONNECT, l3dss1_connect},
-	{SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_CONNECT, l3dss1_status_req},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(11) | SBIT(19),
-	 MT_CONNECT_ACKNOWLEDGE, l3dss1_status_req},
 	{SBIT(8),
 	 MT_CONNECT_ACKNOWLEDGE, l3dss1_connect_ack},
-	{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(8) | SBIT(10) | SBIT(11) | SBIT(19),
-	 MT_INVALID, l3dss1_status_req},
+	{SBIT(15),
+	 MT_SUSPEND_ACKNOWLEDGE, l3dss1_suspend_ack},
+	{SBIT(15),
+	 MT_SUSPEND_REJECT, l3dss1_suspend_rej},
+	{SBIT(17),
+	 MT_RESUME_ACKNOWLEDGE, l3dss1_resume_ack},
+	{SBIT(17),
+	 MT_RESUME_REJECT, l3dss1_resume_rej},
 };
 
-static int datasllen = sizeof(datastatelist) / sizeof(struct stateentry);
+#define DATASLLEN \
+	(sizeof(datastatelist) / sizeof(struct stateentry))
 
 static struct stateentry globalmes_list[] =
 {
 	{ALL_STATES,
-         MT_STATUS, l3dss1_status},
+	 MT_STATUS, l3dss1_status},
 	{SBIT(0),
 	 MT_RESTART, l3dss1_global_restart},
 /*	{SBIT(1),
-	 MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},                                  
+	 MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
 */
 };
-static int globalm_len = sizeof(globalmes_list) / sizeof(struct stateentry);
+#define GLOBALM_LEN \
+	(sizeof(globalmes_list) / sizeof(struct stateentry))
 
-#if 0
-static struct stateentry globalcmd_list[] =
+static struct stateentry manstatelist[] =
 {
-	{ALL_STATES,
-         CC_STATUS, l3dss1_status_req},
-	{SBIT(0),
-	 CC_RESTART, l3dss1_restart_req},
+        {SBIT(2),
+         DL_ESTABLISH | INDICATION, l3dss1_dl_reset},
+        {SBIT(10),
+         DL_ESTABLISH | CONFIRM, l3dss1_dl_reest_status},
+        {SBIT(10),
+         DL_RELEASE | INDICATION, l3dss1_dl_reestablish},
+        {ALL_STATES,
+         DL_RELEASE | INDICATION, l3dss1_dl_release},
 };
 
-static int globalc_len = sizeof(globalcmd_list) / sizeof(struct stateentry);
-#endif
+#define MANSLLEN \
+        (sizeof(manstatelist) / sizeof(struct stateentry))
 /* *INDENT-ON* */
 
+
 static void
 global_handler(struct PStack *st, int mt, struct sk_buff *skb)
 {
+	u_char tmp[16];
+	u_char *p = tmp;
+	int l;
 	int i;
-	char tmp[64];
 	struct l3_process *proc = st->l3.global;
-	
-	for (i = 0; i < globalm_len; i++)
+
+	proc->callref = skb->data[2]; /* cr flag */
+	for (i = 0; i < GLOBALM_LEN; i++)
 		if ((mt == globalmes_list[i].primitive) &&
 		    ((1 << proc->state) & globalmes_list[i].state))
 			break;
-	if (i == globalm_len) {
-		dev_kfree_skb(skb);
+	if (i == GLOBALM_LEN) {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "dss1 global state %d mt %x unhandled",
+			l3_debug(st, "dss1 global state %d mt %x unhandled",
 				proc->state, mt);
-			l3_debug(st, tmp);
 		}
-		return;
+		MsgHead(p, proc->callref, MT_STATUS);
+		*p++ = IE_CAUSE;
+		*p++ = 0x2;
+		*p++ = 0x80;
+		*p++ = 81 |0x80;	/* invalid cr */
+		*p++ = 0x14;		/* CallState */
+		*p++ = 0x1;
+		*p++ = proc->state & 0x3f;
+		l = p - tmp;
+		if (!(skb = l3_alloc_skb(l)))
+			return;
+		memcpy(skb_put(skb, l), tmp, l);
+		l3_msg(proc->st, DL_DATA | REQUEST, skb);
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "dss1 global %d mt %x",
+			l3_debug(st, "dss1 global %d mt %x",
 				proc->state, mt);
-			l3_debug(st, tmp);
 		}
 		globalmes_list[i].rout(proc, mt, skb);
 	}
@@ -1488,124 +2948,166 @@
 {
 	int i, mt, cr, cause, callState;
 	char *ptr;
+	u_char *p;
 	struct sk_buff *skb = arg;
 	struct l3_process *proc;
-	char tmp[80];
+
+	switch (pr) {
+		case (DL_DATA | INDICATION):
+		case (DL_UNIT_DATA | INDICATION):
+			break;
+		case (DL_ESTABLISH | CONFIRM):
+		case (DL_ESTABLISH | INDICATION):
+		case (DL_RELEASE | INDICATION):
+		case (DL_RELEASE | CONFIRM):
+			l3_msg(st, pr, arg);
+			return;
+			break;
+                default:
+                        printk(KERN_ERR "HiSax dss1up unknown pr=%04x\n", pr);
+                        return;
+	}
+	if (skb->len < 3) {
+		l3_debug(st, "dss1up frame too short(%d)", skb->len);
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	}
 
 	if (skb->data[0] != PROTO_DIS_EURO) {
 		if (st->l3.debug & L3_DEB_PROTERR) {
-			sprintf(tmp, "dss1up%sunexpected discriminator %x message len %d",
-				(pr == DL_DATA) ? " " : "(broadcast) ",
-				skb->data[0], skb->len);
-			l3_debug(st, tmp);
+			l3_debug(st, "dss1up%sunexpected discriminator %x message len %d",
+				 (pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
+				 skb->data[0], skb->len);
 		}
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	}
 	cr = getcallref(skb->data);
+	if (skb->len < ((skb->data[1] & 0x0f) + 3)) {
+		l3_debug(st, "dss1up frame too short(%d)", skb->len);
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	}
 	mt = skb->data[skb->data[1] + 2];
-	if (!cr) {				/* Global CallRef */
+	if (st->l3.debug & L3_DEB_STATE)
+		l3_debug(st, "dss1up cr %d", cr);
+	if (cr == -2) {  /* wrong Callref */
+		if (st->l3.debug & L3_DEB_WARN)
+			l3_debug(st, "dss1up wrong Callref");
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	} else if (cr == -1) {	/* Dummy Callref */
+		if (mt == MT_FACILITY)
+			if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) {
+				l3dss1_parse_facility(st, NULL, 
+					(pr == (DL_DATA | INDICATION)) ? -1 : -2, p); 
+				idev_kfree_skb(skb, FREE_READ);
+				return;  
+			}
+		if (st->l3.debug & L3_DEB_WARN)
+			l3_debug(st, "dss1up dummy Callref (no facility msg or ie)");
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	} else if ((((skb->data[1] & 0x0f) == 1) && (0==(cr & 0x7f))) ||
+		(((skb->data[1] & 0x0f) == 2) && (0==(cr & 0x7fff)))) {	/* Global CallRef */
+		if (st->l3.debug & L3_DEB_STATE)
+			l3_debug(st, "dss1up Global CallRef");
 		global_handler(st, mt, skb);
-		return;
-	} else if (cr == -1) {			/* Dummy Callref */
-		dev_kfree_skb(skb);
+		idev_kfree_skb(skb, FREE_READ);
 		return;
 	} else if (!(proc = getl3proc(st, cr))) {
 		/* No transaction process exist, that means no call with
 		 * this callreference is active
 		 */
 		if (mt == MT_SETUP) {
-		/* Setup creates a new transaction process */
-			if (!(proc = new_l3_process(st, cr))) {
+			/* Setup creates a new transaction process */
+			if (!(proc = dss1_new_l3_process(st, cr))) {
 				/* May be to answer with RELEASE_COMPLETE and
 				 * CAUSE 0x2f "Resource unavailable", but this
 				 * need a new_l3_process too ... arghh
 				 */
-				dev_kfree_skb(skb);
+				idev_kfree_skb(skb, FREE_READ);
 				return;
 			}
 		} else if (mt == MT_STATUS) {
 			cause = 0;
-			if((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
-				  ptr++;
-				  if (*ptr++ == 2)
-				  	ptr++;
-				  cause = *ptr & 0x7f;
+			if ((ptr = findie(skb->data, skb->len, IE_CAUSE, 0)) != NULL) {
+				ptr++;
+				if (*ptr++ == 2)
+					ptr++;
+				cause = *ptr & 0x7f;
 			}
 			callState = 0;
-			if((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
+			if ((ptr = findie(skb->data, skb->len, IE_CALL_STATE, 0)) != NULL) {
 				ptr++;
 				if (*ptr++ == 2)
 					ptr++;
 				callState = *ptr;
 			}
-			if (callState == 0) {
-				/* ETS 300-104 part 2.4.1
-				 * if setup has not been made and a message type
-				 * MT_STATUS is received with call state == 0,
-				 * we must send nothing
-				 */
-				dev_kfree_skb(skb);
-				return;
-			} else {
+			/* ETS 300-104 part 2.4.1
+			 * if setup has not been made and a message type
+			 * MT_STATUS is received with call state == 0,
+			 * we must send nothing
+			 */
+			if (callState != 0) {
 				/* ETS 300-104 part 2.4.2
-				 * if setup has not been made and a message type 
+				 * if setup has not been made and a message type
 				 * MT_STATUS is received with call state != 0,
 				 * we must send MT_RELEASE_COMPLETE cause 101
 				 */
-				dev_kfree_skb(skb);
-				if ((proc = new_l3_process(st, cr))) {
-					proc->para.cause = 0x65; /* 101 */
-					proc->st->l3.l3l4(proc, CC_ESTABLISH, NULL);
+				if ((proc = dss1_new_l3_process(st, cr))) {
+					proc->para.cause = 101;
+					l3dss1_msg_without_setup(proc, 0, NULL);
 				}
-				return;
 			}
-		} else if (mt == MT_RELEASE_COMPLETE){
-			dev_kfree_skb(skb);
+			idev_kfree_skb(skb, FREE_READ);
+			return;
+		} else if (mt == MT_RELEASE_COMPLETE) {
+			idev_kfree_skb(skb, FREE_READ);
 			return;
 		} else {
 			/* ETS 300-104 part 2
-			 * if setup has not been made and a message type 
+			 * if setup has not been made and a message type
 			 * (except MT_SETUP and RELEASE_COMPLETE) is received,
 			 * we must send MT_RELEASE_COMPLETE cause 81 */
-			dev_kfree_skb(skb);
-			if ((proc = new_l3_process(st, cr))) {
-				proc->para.cause = 0x51; /* 81 */
-				proc->st->l3.l3l4(proc, CC_ESTABLISH, NULL);
+			idev_kfree_skb(skb, FREE_READ);
+			if ((proc = dss1_new_l3_process(st, cr))) {
+				proc->para.cause = 81;
+				l3dss1_msg_without_setup(proc, 0, NULL);
 			}
 			return;
 		}
-	} else if (!l3dss1_check_messagetype_validity(mt)) {
-		/* ETS 300-104 7.4.2, 8.4.2, 10.3.2, 11.4.2, 12.4.2, 13.4.2,
-		 * 14.4.2...
-		 * if setup has been made and invalid message type is received,
-		 * we must send MT_STATUS cause 0x62
-		 */
-		mt = MT_INVALID;  /* sorry, not clean, but do the right thing ;-) */
 	}
-
-	for (i = 0; i < datasllen; i++)
+	if (l3dss1_check_messagetype_validity(proc, mt, skb)) {
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	}
+	if ((p = findie(skb->data, skb->len, IE_DISPLAY, 0)) != NULL) 
+	  l3dss1_deliver_display(proc, pr, p); /* Display IE included */
+	for (i = 0; i < DATASLLEN; i++)
 		if ((mt == datastatelist[i].primitive) &&
 		    ((1 << proc->state) & datastatelist[i].state))
 			break;
-	if (i == datasllen) {
-		dev_kfree_skb(skb);
+	if (i == DATASLLEN) {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "dss1up%sstate %d mt %x unhandled",
-				(pr == DL_DATA) ? " " : "(broadcast) ",
+			l3_debug(st, "dss1up%sstate %d mt %#x unhandled",
+				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				proc->state, mt);
-			l3_debug(st, tmp);
 		}
-		return;
+		if ((MT_RELEASE_COMPLETE != mt) && (MT_RELEASE != mt)) {
+			proc->para.cause = 101;
+			l3dss1_status_send(proc, pr, skb);
+		}
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "dss1up%sstate %d mt %x",
-				(pr == DL_DATA) ? " " : "(broadcast) ",
+			l3_debug(st, "dss1up%sstate %d mt %x",
+				(pr == (DL_DATA | INDICATION)) ? " " : "(broadcast) ",
 				proc->state, mt);
-			l3_debug(st, tmp);
 		}
 		datastatelist[i].rout(proc, pr, skb);
 	}
+	idev_kfree_skb(skb, FREE_READ);
+	return;
 }
 
 static void
@@ -1614,13 +3116,15 @@
 	int i, cr;
 	struct l3_process *proc;
 	struct Channel *chan;
-	char tmp[80];
 
-	if (CC_SETUP_REQ == pr) {
+	if ((DL_ESTABLISH | REQUEST) == pr) {
+		l3_msg(st, pr, NULL);
+		return;
+	} else if (((CC_SETUP | REQUEST) == pr) || ((CC_RESUME | REQUEST) == pr)) {
 		chan = arg;
 		cr = newcallref();
 		cr |= 0x80;
-		if ((proc = new_l3_process(st, cr))) {
+		if ((proc = dss1_new_l3_process(st, cr))) {
 			proc->chan = chan;
 			chan->proc = proc;
 			proc->para.setup = chan->setup;
@@ -1630,37 +3134,78 @@
 		proc = arg;
 	}
 	if (!proc) {
-		printk(KERN_ERR "HiSax internal error dss1down without proc\n");
+		printk(KERN_ERR "HiSax dss1down without proc pr=%04x\n", pr);
 		return;
 	}
-	for (i = 0; i < downsllen; i++)
+
+	if ( pr == (CC_TDSS1_IO | REQUEST)) {
+		l3dss1_io_timer(proc); /* timer expires */ 
+		return;
+	}  
+
+	for (i = 0; i < DOWNSLLEN; i++)
 		if ((pr == downstatelist[i].primitive) &&
 		    ((1 << proc->state) & downstatelist[i].state))
 			break;
-	if (i == downsllen) {
+	if (i == DOWNSLLEN) {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "dss1down state %d prim %d unhandled",
+			l3_debug(st, "dss1down state %d prim %#x unhandled",
 				proc->state, pr);
-			l3_debug(st, tmp);
 		}
 	} else {
 		if (st->l3.debug & L3_DEB_STATE) {
-			sprintf(tmp, "dss1down state %d prim %d",
+			l3_debug(st, "dss1down state %d prim %#x",
 				proc->state, pr);
-			l3_debug(st, tmp);
 		}
 		downstatelist[i].rout(proc, pr, arg);
 	}
 }
 
+static void
+dss1man(struct PStack *st, int pr, void *arg)
+{
+        int i;
+        struct l3_process *proc = arg;
+ 
+        if (!proc) {
+                printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr);
+                return;
+        }
+        for (i = 0; i < MANSLLEN; i++)
+                if ((pr == manstatelist[i].primitive) &&
+                    ((1 << proc->state) & manstatelist[i].state))
+                        break;
+        if (i == MANSLLEN) {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d dss1man state %d prim %#x unhandled",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+        } else {
+                if (st->l3.debug & L3_DEB_STATE) {
+                        l3_debug(st, "cr %d dss1man state %d prim %#x",
+                                proc->callref & 0x7f, proc->state, pr);
+                }
+                manstatelist[i].rout(proc, pr, arg);
+        }
+}
+ 
 void
 setstack_dss1(struct PStack *st)
 {
 	char tmp[64];
+	int i;
 
 	st->lli.l4l3 = dss1down;
+	st->lli.l4l3_proto = l3dss1_cmd_global;
 	st->l2.l2l3 = dss1up;
+	st->l3.l3ml3 = dss1man;
 	st->l3.N303 = 1;
+	st->prot.dss1.last_invoke_id = 0;
+	st->prot.dss1.invoke_used[0] = 1; /* Bit 0 must always be set to 1 */
+	i = 1;
+	while (i < 32) 
+		st->prot.dss1.invoke_used[i++] = 0;   
+
 	if (!(st->l3.global = kmalloc(sizeof(struct l3_process), GFP_ATOMIC))) {
 		printk(KERN_ERR "HiSax can't get memory for dss1 global CR\n");
 	} else {
@@ -1670,8 +3215,15 @@
 		st->l3.global->debug = L3_DEB_WARN;
 		st->l3.global->st = st;
 		st->l3.global->N303 = 1;
+		st->l3.global->prot.dss1.invoke_id = 0; 
+
 		L3InitTimer(st->l3.global, &st->l3.global->timer);
 	}
 	strcpy(tmp, dss1_revision);
 	printk(KERN_INFO "HiSax: DSS1 Rev. %s\n", HiSax_getrev(tmp));
 }
+
+
+
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/l3dss1.h linux.pre11.3/drivers/isdn/hisax/l3dss1.h
--- linux.vanilla/drivers/isdn/hisax/l3dss1.h	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/l3dss1.h	Mon Jul 19 23:59:34 1999
@@ -1,8 +1,15 @@
-/* $Id: l3dss1.h,v 1.5 1998/02/02 13:34:30 keil Exp $
+/* $Id: l3dss1.h,v 1.7 1999/07/01 08:12:02 keil Exp $
  *
  *  DSS1 (Euro) D-channel protocol defines
  *
  * $Log: l3dss1.h,v $
+ * Revision 1.7  1999/07/01 08:12:02  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.6  1998/03/19 13:18:50  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
  * Revision 1.5  1998/02/02 13:34:30  keil
  * Support australian Microlink net and german AOCD
  *
@@ -21,10 +28,14 @@
  *
  *
  */
+
+#ifndef l3dss1_process
+
 #define T303	4000
 #define T304	30000
 #define T305	30000
 #define T308	4000
+#define T309	40000
 #define T310	30000
 #define T313	4000
 #define T318	4000
@@ -34,38 +45,99 @@
  * Message-Types
  */
 
-#define MT_ALERTING            0x01
-#define MT_CALL_PROCEEDING     0x02
-#define MT_CONNECT             0x07
-#define MT_CONNECT_ACKNOWLEDGE 0x0f
-#define MT_PROGRESS            0x03
-#define MT_SETUP               0x05
-#define MT_SETUP_ACKNOWLEDGE   0x0d
-#define MT_RESUME              0x26
-#define MT_RESUME_ACKNOWLEDGE  0x2e
-#define MT_RESUME_REJECT       0x22
-#define MT_SUSPEND             0x25
-#define MT_SUSPEND_ACKNOWLEDGE 0x2d
-#define MT_SUSPEND_REJECT      0x21
-#define MT_USER_INFORMATION    0x20
-#define MT_DISCONNECT          0x45
-#define MT_RELEASE             0x4d
-#define MT_RELEASE_COMPLETE    0x5a
-#define MT_RESTART             0x46
-#define MT_RESTART_ACKNOWLEDGE 0x4e
-#define MT_SEGMENT             0x60
-#define MT_CONGESTION_CONTROL  0x79
-#define MT_INFORMATION         0x7b
-#define MT_FACILITY            0x62
-#define MT_NOTIFY              0x6e
-#define MT_STATUS              0x7d
-#define MT_STATUS_ENQUIRY      0x75
-
-#define MT_INVALID             0xff
-
-#define IE_CAUSE               0x08
-#define IE_BEARER              0x04
-#define IE_FACILITY            0x1c
-#define IE_CALL_STATE          0x14
-#define IE_CHANNEL_ID          0x18
-#define IE_RESTART_IND         0x79
+#define MT_ALERTING		0x01
+#define MT_CALL_PROCEEDING	0x02
+#define MT_CONNECT		0x07
+#define MT_CONNECT_ACKNOWLEDGE	0x0f
+#define MT_PROGRESS		0x03
+#define MT_SETUP		0x05
+#define MT_SETUP_ACKNOWLEDGE	0x0d
+#define MT_RESUME		0x26
+#define MT_RESUME_ACKNOWLEDGE	0x2e
+#define MT_RESUME_REJECT	0x22
+#define MT_SUSPEND		0x25
+#define MT_SUSPEND_ACKNOWLEDGE	0x2d
+#define MT_SUSPEND_REJECT	0x21
+#define MT_USER_INFORMATION	0x20
+#define MT_DISCONNECT		0x45
+#define MT_RELEASE		0x4d
+#define MT_RELEASE_COMPLETE	0x5a
+#define MT_RESTART		0x46
+#define MT_RESTART_ACKNOWLEDGE	0x4e
+#define MT_SEGMENT		0x60
+#define MT_CONGESTION_CONTROL	0x79
+#define MT_INFORMATION		0x7b
+#define MT_FACILITY		0x62
+#define MT_NOTIFY		0x6e
+#define MT_STATUS		0x7d
+#define MT_STATUS_ENQUIRY	0x75
+
+#define IE_SEGMENT	0x00
+#define IE_BEARER	0x04
+#define IE_CAUSE	0x08
+#define IE_CALL_ID	0x10
+#define IE_CALL_STATE	0x14
+#define IE_CHANNEL_ID	0x18
+#define IE_FACILITY	0x1c
+#define IE_PROGRESS	0x1e
+#define IE_NET_FAC	0x20
+#define IE_NOTIFY	0x27
+#define IE_DISPLAY	0x28
+#define IE_DATE		0x29
+#define IE_KEYPAD	0x2c
+#define IE_SIGNAL	0x34
+#define IE_INFORATE	0x40
+#define IE_E2E_TDELAY	0x42
+#define IE_TDELAY_SEL	0x43
+#define IE_PACK_BINPARA	0x44
+#define IE_PACK_WINSIZE	0x45
+#define IE_PACK_SIZE	0x46
+#define IE_CUG		0x47
+#define	IE_REV_CHARGE	0x4a
+#define IE_CONNECT_PN	0x4c
+#define IE_CONNECT_SUB	0x4d
+#define IE_CALLING_PN	0x6c
+#define IE_CALLING_SUB	0x6d
+#define IE_CALLED_PN	0x70
+#define IE_CALLED_SUB	0x71
+#define IE_REDIR_NR	0x74
+#define IE_TRANS_SEL	0x78
+#define IE_RESTART_IND	0x79
+#define IE_LLC		0x7c
+#define IE_HLC		0x7d
+#define IE_USER_USER	0x7e
+#define IE_ESCAPE	0x7f
+#define IE_SHIFT	0x90
+#define IE_MORE_DATA	0xa0
+#define IE_COMPLETE	0xa1
+#define IE_CONGESTION	0xb0
+#define IE_REPEAT	0xd0
+
+#define IE_MANDATORY	0x0100
+/* mandatory not in every case */
+#define IE_MANDATORY_1	0x0200
+
+#define ERR_IE_COMPREHENSION	 1
+#define ERR_IE_UNRECOGNIZED	-1
+#define ERR_IE_LENGTH		-2
+#define ERR_IE_SEQUENCE		-3
+
+#else /* only l3dss1_process */
+
+/* l3dss1 specific data in l3 process */
+typedef struct
+  { unsigned char invoke_id; /* used invoke id in remote ops, 0 = not active */
+    ulong ll_id; /* remebered ll id */
+    u_char remote_operation; /* handled remote operation, 0 = not active */ 
+    int proc; /* rememered procedure */  
+    ulong remote_result; /* result of remote operation for statcallb */
+    char uus1_data[35]; /* data send during alerting or disconnect */
+  } dss1_proc_priv;
+
+/* l3dss1 specific data in protocol stack */
+typedef struct
+  { unsigned char last_invoke_id; /* last used value for invoking */
+    unsigned char invoke_used[32]; /* 256 bits for 256 values */
+  } dss1_stk_priv;        
+
+#endif /* only l3dss1_process */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/lmgr.c linux.pre11.3/drivers/isdn/hisax/lmgr.c
--- linux.vanilla/drivers/isdn/hisax/lmgr.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/lmgr.c	Mon Jul 19 23:59:34 1999
@@ -1,11 +1,24 @@
-/* $Id: lmgr.c,v 1.2 1997/10/29 19:09:34 keil Exp $
+/* $Id: lmgr.c,v 1.6 1999/07/01 08:12:04 keil Exp $
 
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *
  *
  *  Layermanagement module
  *
  * $Log: lmgr.c,v $
+ * Revision 1.6  1999/07/01 08:12:04  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.5  1998/11/15 23:55:12  keil
+ * changes from 2.0
+ *
+ * Revision 1.4  1998/05/25 12:58:19  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.3  1998/03/07 22:57:06  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 1.2  1997/10/29 19:09:34  keil
  * new L1
  *
@@ -26,7 +39,7 @@
 		case 'D':
 		case 'G':
 		case 'H':
-			st->l2.l2tei(st, MDL_ERROR_REQ, NULL);
+			st->l2.l2tei(st, MDL_ERROR | REQUEST, NULL);
 			break;
 	}
 }
@@ -34,17 +47,15 @@
 static void
 hisax_manager(struct PStack *st, int pr, void *arg)
 {
-	char tm[32], str[256];
-	int Code;
+	long Code;
 
 	switch (pr) {
-		case MDL_ERROR_IND:
-			Code = (int) arg;
-			jiftime(tm, jiffies);
-			sprintf(str, "%s manager: MDL_ERROR %c %s\n", tm,
-				Code, test_bit(FLG_LAPD, &st->l2.flag) ?
+		case (MDL_ERROR | INDICATION):
+			Code = (long) arg;
+			HiSax_putstatus(st->l1.hardware, "manager: MDL_ERROR",
+				" %c %s", (char)Code, 
+				test_bit(FLG_LAPD, &st->l2.flag) ?
 				"D-channel" : "B-channel");
-			HiSax_putstatus(st->l1.hardware, str);
 			if (test_bit(FLG_LAPD, &st->l2.flag))
 				error_handling_dchan(st, Code);
 			break;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/md5sums.asc linux.pre11.3/drivers/isdn/hisax/md5sums.asc
--- linux.vanilla/drivers/isdn/hisax/md5sums.asc	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/md5sums.asc	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,29 @@
+-----BEGIN PGP SIGNED MESSAGE-----
+
+# This are valid md5sums for certificated HiSax driver.
+# The certification is valid only if the md5sums of all files match.
+# The certification is valid only for ELSA QuickStep cards in the moment.
+# Read ../../../Documentation/isdn/HiSax.cert for more informations.
+# 
+7b86f7c9709d1a96f2591b76db297116  isac.c
+773fb8b13e20ef92c0bc991fea23c673  isdnl1.c
+f2ef2bc94883f818d0beb184688786bc  isdnl2.c
+c7b9992f966c645e0eea548b0d3655a0  isdnl3.c
+df3c2d2bc312af0689ed97a1fe7ad2df  tei.c
+94facb2403188ddfb6b83a890a5e7fa0  callc.c
+f3ec2a634f06074d16167aaba02b6dc1  cert.c
+e69680e894417b00949473ce38259e2a  l3dss1.c
+04082bae9726b7c34adb008d3752ac73  l3_1tr6.c
+6705bf924beeb147d80dc91fa0aa25ee  elsa.c
+# end of md5sums
+
+-----BEGIN PGP SIGNATURE-----
+Version: 2.6.3i
+Charset: noconv
+
+iQCVAwUBN3FBezpxHvX/mS9tAQGs9wQAk4pSCWvx5CMheSRedQ7nTtIoVQKPiAEx
+6/0DWE5hu5IsSOG4ZbLG/ISdad4OOZjWfMpeeIwsHVGVSspGvo9lpIMOS9EqEvr8
+I+kCrPQwKaEN675U2m0ofsELAPOyH2JICjKdbW+iipWI+6oqGta7aw/tbgDqykVr
+vz2L4uxmgUY=
+=r0Yz
+-----END PGP SIGNATURE-----
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/mic.c linux.pre11.3/drivers/isdn/hisax/mic.c
--- linux.vanilla/drivers/isdn/hisax/mic.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/mic.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: mic.c,v 1.6 1998/02/17 15:39:57 keil Exp $
+/* $Id: mic.c,v 1.8 1999/07/12 21:05:20 keil Exp $
 
  * mic.c  low level stuff for mic cards
  *
@@ -8,6 +8,13 @@
  *
  *
  * $Log: mic.c,v $
+ * Revision 1.8  1999/07/12 21:05:20  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.7  1998/04/15 16:44:32  keil
+ * new init code
+ *
  * Revision 1.6  1998/02/17 15:39:57  keil
  * fix reset problem
  *
@@ -37,7 +44,7 @@
 
 extern const char *CardType[];
 
-const char *mic_revision = "$Revision: 1.6 $";
+const char *mic_revision = "$Revision: 1.8 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -155,7 +162,7 @@
 mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "mic: Spurious interrupt!\n");
@@ -163,16 +170,12 @@
 	}
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -185,16 +188,12 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0);
 }
 
 void
@@ -215,15 +214,9 @@
 		case CARD_RELEASE:
 			release_io_mic(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &mic_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithscx(cs); /* /RTSA := ISAC RST */
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -273,6 +266,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &mic_card_msg;
+	cs->irq_func = &mic_interrupt;
 	ISACVersion(cs, "mic:");
 	if (HscxVersion(cs, "mic:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/netjet.c linux.pre11.3/drivers/isdn/hisax/netjet.c
--- linux.vanilla/drivers/isdn/hisax/netjet.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/hisax/netjet.c	Mon Jul 19 23:59:34 1999
@@ -1,13 +1,37 @@
-/* $Id: netjet.c,v 1.3 1998/02/12 23:08:05 keil Exp $
+/* $Id: netjet.c,v 1.10 1999/07/12 21:05:22 keil Exp $
 
  * netjet.c     low level stuff for Traverse Technologie NETJet ISDN cards
  *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author     Karsten Keil (keil@isdn4linux.de)
  *
  * Thanks to Traverse Technologie Australia for documents and informations
  *
  *
  * $Log: netjet.c,v $
+ * Revision 1.10  1999/07/12 21:05:22  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.9  1999/07/01 08:12:05  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.8  1998/11/15 23:55:14  keil
+ * changes from 2.0
+ *
+ * Revision 1.7  1998/09/30 22:24:48  keil
+ * Fix missing line in setstack*
+ *
+ * Revision 1.6  1998/08/13 23:36:54  keil
+ * HiSax 3.1 - don't work stable with current LinkLevel
+ *
+ * Revision 1.5  1998/05/25 12:58:21  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 1.4  1998/04/15 16:42:35  keil
+ * new init code
+ * new PCI init (2.1.94)
+ *
  * Revision 1.3  1998/02/12 23:08:05  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -25,15 +49,23 @@
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
 #include <linux/bios32.h>
+#endif
 #include <linux/interrupt.h>
-#define fcstab  ppp_crc16_table
 #include <linux/ppp_defs.h>
-extern __u16 ppp_crc16_table[256]; /* from ppp code */
+
+#ifndef bus_to_virt
+#define bus_to_virt (u_int *)
+#endif
+
+#ifndef virt_to_bus
+#define virt_to_bus (u_int)
+#endif
 
 extern const char *CardType[];
 
-const char *NETjet_revision = "$Revision: 1.3 $";
+const char *NETjet_revision = "$Revision: 1.10 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -62,6 +94,12 @@
 
 #define NETJET_ISAC_OFF	0xc0
 #define NETJET_ISACIRQ	0x10
+#define NETJET_IRQM0_READ	0x0c
+#define NETJET_IRQM0_READ_1	0x04
+#define NETJET_IRQM0_READ_2	0x08
+#define NETJET_IRQM0_WRITE	0x03
+#define NETJET_IRQM0_WRITE_1	0x01
+#define NETJET_IRQM0_WRITE_2	0x02
 
 #define NETJET_DMA_SIZE 512
 
@@ -115,6 +153,42 @@
 	insb(cs->hw.njet.isac, data, size);
 }
 
+__u16 fcstab[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
+};
+
 static void 
 WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size)
 {
@@ -146,25 +220,20 @@
 mode_tiger(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
-	char tmp[64];
 
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "Tiger mode %d bchan %d/%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "Tiger mode %d bchan %d/%d",
 			mode, bc, bcs->channel);
-		debugl1(cs, tmp);
-	}
 	bcs->mode = mode;
 	bcs->channel = bc;
 	switch (mode) {
 		case (L1_MODE_NULL):
 			fill_mem(bcs, bcs->hw.tiger.send,
 				NETJET_DMA_SIZE, bc, 0xff);
-			if (cs->debug & L1_DEB_HSCX) {
-				sprintf(tmp, "Tiger stat rec %d/%d send %d",
+			if (cs->debug & L1_DEB_HSCX)
+				debugl1(cs, "Tiger stat rec %d/%d send %d",
 					bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err,
 					bcs->hw.tiger.s_tot); 
-				debugl1(cs, tmp);
-			}
 			if ((cs->bcs[0].mode == L1_MODE_NULL) &&
 				(cs->bcs[1].mode == L1_MODE_NULL)) {
 				cs->hw.njet.dmactrl = 0;
@@ -197,16 +266,14 @@
 			test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
 			break;
 	}
-	if (cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp, "tiger: set %x %x %x  %x/%x  pulse=%d",
+	if (cs->debug & L1_DEB_HSCX)
+		debugl1(cs, "tiger: set %x %x %x  %x/%x  pulse=%d",
 			bytein(cs->hw.njet.base + NETJET_DMACTRL),
 			bytein(cs->hw.njet.base + NETJET_IRQMASK0),
 			bytein(cs->hw.njet.base + NETJET_IRQSTAT0),
 			inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
 			inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
 			bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-		debugl1(cs, tmp);
-	}
 }
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
@@ -266,7 +333,7 @@
 			val >>= 1;\
 		}
 
-static void make_raw_data(struct BCState *bcs) {
+static int make_raw_data(struct BCState *bcs) {
 	register u_int i,s_cnt=0;
 	register u_char j;
 	register u_char val;
@@ -274,13 +341,15 @@
 	register u_char s_val = 0;
 	register u_char bitcnt = 0;
 	u_int fcs;
-	char tmp[64];
-	
 	
+	if (!bcs->tx_skb) {
+		debugl1(bcs->cs, "tiger make_raw: NULL skb");
+		return(1);
+	}
 	bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE;
 	fcs = PPP_INITFCS;
-	for (i=0; i<bcs->hw.tiger.tx_skb->len; i++) {
-		val = bcs->hw.tiger.tx_skb->data[i];
+	for (i=0; i<bcs->tx_skb->len; i++) {
+		val = bcs->tx_skb->data[i];
 		fcs = PPP_FCS (fcs, val);
 		MAKE_RAW_BYTE;
 	}
@@ -303,11 +372,9 @@
 		}
 		val >>= 1;
 	}
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger make_raw: in %d out %d.%d",
-			bcs->hw.tiger.tx_skb->len, s_cnt, bitcnt);
-		debugl1(bcs->cs,tmp);
-	}
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d",
+			bcs->tx_skb->len, s_cnt, bitcnt);
 	if (bitcnt) {
 		while (8>bitcnt++) {
 			s_val >>= 1;
@@ -316,8 +383,9 @@
 		bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
 	}
 	bcs->hw.tiger.sendcnt = s_cnt;
-	bcs->tx_cnt -= bcs->hw.tiger.tx_skb->len;
+	bcs->tx_cnt -= bcs->tx_skb->len;
 	bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
+	return(0);
 }
 
 static void got_frame(struct BCState *bcs, int count) {
@@ -326,6 +394,7 @@
 	if (!(skb = dev_alloc_skb(count)))
 		printk(KERN_WARNING "TIGER: receive out of memory\n");
 	else {
+		SET_SKB_FREE(skb);
 		memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count);
 		skb_queue_tail(&bcs->rqueue, skb);
 	}
@@ -349,7 +418,6 @@
 	register u_char r_val = bcs->hw.tiger.r_val;
 	register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
 	u_int *p = buf;
-	char tmp[64];
         
 	for (i=0;i<cnt;i++) {
 		val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff);
@@ -370,11 +438,9 @@
 				} else {
 					r_one=0;
 					state= HDLC_FLAG_SEARCH;
-					if (bcs->cs->debug & L1_DEB_HSCX) {
-						sprintf(tmp,"tiger read_raw: zBit(%d,%d,%d) %x",
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x",
 							bcs->hw.tiger.r_tot,i,j,val);
-						debugl1(bcs->cs,tmp);
-					}
 				}
 			} else if (state == HDLC_FLAG_SEARCH) { 
 				if (val & 1) {
@@ -387,11 +453,9 @@
 						bitcnt=0;
 						r_val=0;
 						state=HDLC_FLAG_FOUND;
-						if (bcs->cs->debug & L1_DEB_HSCX) {
-							sprintf(tmp,"tiger read_raw: flag(%d,%d,%d) %x",
+						if (bcs->cs->debug & L1_DEB_HSCX)
+							debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x",
 								bcs->hw.tiger.r_tot,i,j,val);
-							debugl1(bcs->cs,tmp);
-						}
 					}
 					r_one=0;
 				}
@@ -425,12 +489,10 @@
 					bcs->hw.tiger.r_fcs = PPP_INITFCS;
 					bcs->hw.tiger.rcvbuf[0] = r_val;
 					bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
-					if (bcs->cs->debug & L1_DEB_HSCX) {
-						sprintf(tmp,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
 							bcs->hw.tiger.r_tot,i,j,r_val,val,
 							bcs->cs->hw.njet.irqstat0);
-						debugl1(bcs->cs,tmp);
-					}
 				}
 			} else if (state ==  HDLC_FRAME_FOUND) {
 				if (val & 1) {
@@ -453,11 +515,9 @@
 							state=HDLC_FLAG_SEARCH;
 							bcs->hw.tiger.r_err++;
 						} else {
-							if (bcs->cs->debug & L1_DEB_HSCX) {
-								sprintf(tmp,"tiger frame end(%d,%d): fcs(%x) i %x",
+							if (bcs->cs->debug & L1_DEB_HSCX)
+								debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x",
 									i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0);
-								debugl1(bcs->cs, tmp);
-							}
 							if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) {
 								got_frame(bcs, (bitcnt>>3)-3);
 							} else
@@ -509,7 +569,15 @@
 	u_int *p;
 	int cnt = NETJET_DMA_SIZE/2;
 	
-	if (cs->hw.njet.irqstat0 & 4)
+	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
+		debugl1(cs,"tiger warn read double dma %x/%x",
+			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+		return;
+	} else {
+		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ;
+		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ);
+	}	
+	if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1)
 		p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1;
 	else
 		p = cs->bcs[0].hw.tiger.rec + cnt - 1;
@@ -517,32 +585,28 @@
 		read_raw(cs->bcs, p, cnt);
 	if (cs->bcs[1].mode == L1_MODE_HDLC)
 		read_raw(cs->bcs + 1, p, cnt);
-	cs->hw.njet.irqstat0 &= 0xf3;
+	cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ;
 }
 
 static void write_raw(struct BCState *bcs, u_int *buf, int cnt);
 
 static void fill_dma(struct BCState *bcs)
 {
-	char tmp[64];
 	register u_int *p, *sp;
 	register int cnt;
 
-	if (!bcs->hw.tiger.tx_skb)
+	if (!bcs->tx_skb)
 		return;
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger fill_dma1: c%d %4x", bcs->channel,
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel,
 			bcs->Flag);
-			debugl1(bcs->cs,tmp);
-	}
 	if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
 		return;
-	make_raw_data(bcs);
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger fill_dma2: c%d %4x", bcs->channel,
+	if (make_raw_data(bcs))
+		return;		
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
 			bcs->Flag);
-			debugl1(bcs->cs,tmp);
-	}
 	if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
 		write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
@@ -582,17 +646,14 @@
 		}
 		write_raw(bcs, p, cnt);
 	}
-	if (bcs->cs->debug & L1_DEB_HSCX) {
-		sprintf(tmp,"tiger fill_dma3: c%d %4x", bcs->channel,
+	if (bcs->cs->debug & L1_DEB_HSCX)
+		debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel,
 			bcs->Flag);
-		debugl1(bcs->cs,tmp);
-	}
 }
 
 static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
 	u_int mask, val, *p=buf;
 	u_int i, s_cnt;
-	char tmp[64];
         
         if (cnt <= 0)
         	return;
@@ -617,26 +678,23 @@
 				p = bcs->hw.tiger.send;
 		}
 		bcs->hw.tiger.s_tot += s_cnt;
-		if (bcs->cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
-			(u_int)buf, (u_int)p, s_cnt, cnt, bcs->hw.tiger.sendcnt,
-			bcs->cs->hw.njet.irqstat0);
-			debugl1(bcs->cs,tmp);
-		}
+		if (bcs->cs->debug & L1_DEB_HSCX)
+			debugl1(bcs->cs,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
+				(u_int)buf, (u_int)p, s_cnt, cnt,
+				bcs->hw.tiger.sendcnt, bcs->cs->hw.njet.irqstat0);
 		if (bcs->cs->debug & L1_DEB_HSCX_FIFO)
 			printframe(bcs->cs, bcs->hw.tiger.sp, s_cnt, "snd");
 		bcs->hw.tiger.sp += s_cnt;
 		bcs->hw.tiger.sendp = p;
 		if (!bcs->hw.tiger.sendcnt) {
-			if (!bcs->hw.tiger.tx_skb) {
-				sprintf(tmp,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
-				debugl1(bcs->cs, tmp);
+			if (!bcs->tx_skb) {
+				debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
 			} else {
 				if (bcs->st->lli.l1writewakeup &&
-					(PACKET_NOACK != bcs->hw.tiger.tx_skb->pkt_type))
-					bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.tiger.tx_skb->len);
-				dev_kfree_skb(bcs->hw.tiger.tx_skb);
-				bcs->hw.tiger.tx_skb = NULL;
+					(PACKET_NOACK != bcs->tx_skb->pkt_type))
+					bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+				idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+				bcs->tx_skb = NULL;
 			}
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 			bcs->hw.tiger.free = cnt - s_cnt;
@@ -646,7 +704,7 @@
 				test_and_clear_bit(BC_FLG_HALF, &bcs->Flag);
 				test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag);
 			}
-			if ((bcs->hw.tiger.tx_skb = skb_dequeue(&bcs->squeue))) {
+			if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
 				fill_dma(bcs);
 			} else {
 				mask ^= 0xffffffff;
@@ -656,11 +714,9 @@
 						if (p>bcs->hw.tiger.s_end)
 							p = bcs->hw.tiger.send;
 					}
-					if (bcs->cs->debug & L1_DEB_HSCX) {
-						sprintf(tmp, "tiger write_raw: fill rest %d",
+					if (bcs->cs->debug & L1_DEB_HSCX)
+						debugl1(bcs->cs, "tiger write_raw: fill rest %d",
 							cnt - s_cnt);
-						debugl1(bcs->cs,tmp);
-					}
 				}
 				bcs->event |= 1 << B_XMTBUFREADY;
 				queue_task(&bcs->tqueue, &tq_immediate);
@@ -671,24 +727,28 @@
 		test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
 		fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
 		bcs->hw.tiger.free += cnt;
-		if (bcs->cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp,"tiger write_raw: fill half");
-			debugl1(bcs->cs,tmp);
-		}
+		if (bcs->cs->debug & L1_DEB_HSCX)
+			debugl1(bcs->cs,"tiger write_raw: fill half");
 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
 		test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
 		fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
-		if (bcs->cs->debug & L1_DEB_HSCX) {
-			sprintf(tmp,"tiger write_raw: fill full");
-			debugl1(bcs->cs,tmp);
-		}
+		if (bcs->cs->debug & L1_DEB_HSCX)
+			debugl1(bcs->cs,"tiger write_raw: fill full");
 	}
 }
 
 static void write_tiger(struct IsdnCardState *cs) {
 	u_int *p, cnt = NETJET_DMA_SIZE/2;
 	
-	if (cs->hw.njet.irqstat0  & 1)
+	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
+		debugl1(cs,"tiger warn write double dma %x/%x",
+			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
+		return;
+	} else {
+		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE;
+		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE);
+	}	
+	if (cs->hw.njet.irqstat0  & NETJET_IRQM0_WRITE_1)
 		p = cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1;
 	else
 		p = cs->bcs[0].hw.tiger.send + cnt - 1;
@@ -696,7 +756,7 @@
 		write_raw(cs->bcs, p, cnt);
 	if (cs->bcs[1].mode == L1_MODE_HDLC)
 		write_raw(cs->bcs + 1, p, cnt);
-	cs->hw.njet.irqstat0 &= 0xfc;
+	cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE;
 }
 
 static void
@@ -706,45 +766,58 @@
 	long flags;
 
 	switch (pr) {
-		case (PH_DATA_REQ):
+		case (PH_DATA | REQUEST):
 			save_flags(flags);
 			cli();
-			if (st->l1.bcs->hw.tiger.tx_skb) {
+			if (st->l1.bcs->tx_skb) {
 				skb_queue_tail(&st->l1.bcs->squeue, skb);
 				restore_flags(flags);
 			} else {
-				st->l1.bcs->hw.tiger.tx_skb = skb;
+				st->l1.bcs->tx_skb = skb;
 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 				restore_flags(flags);
 			}
 			break;
-		case (PH_PULL_IND):
-			if (st->l1.bcs->hw.tiger.tx_skb) {
+		case (PH_PULL | INDICATION):
+			if (st->l1.bcs->tx_skb) {
 				printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
 				break;
 			}
 			save_flags(flags);
 			cli();
-			st->l1.bcs->hw.tiger.tx_skb = skb;
+			st->l1.bcs->tx_skb = skb;
 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
 			restore_flags(flags);
 			break;
-		case (PH_PULL_REQ):
-			if (!st->l1.bcs->hw.tiger.tx_skb) {
+		case (PH_PULL | REQUEST):
+			if (!st->l1.bcs->tx_skb) {
 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
-				st->l1.l1l2(st, PH_PULL_CNF, NULL);
+				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
 			} else
 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
 			break;
+		case (PH_ACTIVATE | REQUEST):
+			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | REQUEST):
+			l1_msg_b(st, pr, arg);
+			break;
+		case (PH_DEACTIVATE | CONFIRM):
+			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+			mode_tiger(st->l1.bcs, 0, st->l1.bc);
+			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
+			break;
 	}
 }
 
+
 void
 close_tigerstate(struct BCState *bcs)
 {
-	struct sk_buff *skb;
-
-	mode_tiger(bcs, 0, 0);
+	mode_tiger(bcs, 0, bcs->channel);
 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
 		if (bcs->hw.tiger.rcvbuf) {
 			kfree(bcs->hw.tiger.rcvbuf);
@@ -754,32 +827,26 @@
 			kfree(bcs->hw.tiger.sendbuf);
 			bcs->hw.tiger.sendbuf = NULL;
 		}
-		while ((skb = skb_dequeue(&bcs->rqueue))) {
-			dev_kfree_skb(skb);
-		}
-		while ((skb = skb_dequeue(&bcs->squeue))) {
-			dev_kfree_skb(skb);
-		}
-		if (bcs->hw.tiger.tx_skb) {
-			dev_kfree_skb(bcs->hw.tiger.tx_skb);
-			bcs->hw.tiger.tx_skb = NULL;
+		discard_queue(&bcs->rqueue);
+		discard_queue(&bcs->squeue);
+		if (bcs->tx_skb) {
+			idev_kfree_skb(bcs->tx_skb, FREE_WRITE);
+			bcs->tx_skb = NULL;
 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 		}
 	}
 }
 
 static int
-open_tigerstate(struct IsdnCardState *cs, int bc)
+open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
-	struct BCState *bcs = cs->bcs + bc;
-
 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
-		if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_KERNEL))) {
+		if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
 			printk(KERN_WARNING
 			       "HiSax: No memory for tiger.rcvbuf\n");
 			return (1);
 		}
-		if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_KERNEL))) {
+		if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
 			printk(KERN_WARNING
 			       "HiSax: No memory for tiger.sendbuf\n");
 			return (1);
@@ -787,7 +854,7 @@
 		skb_queue_head_init(&bcs->rqueue);
 		skb_queue_head_init(&bcs->squeue);
 	}
-	bcs->hw.tiger.tx_skb = NULL;
+	bcs->tx_skb = NULL;
 	bcs->hw.tiger.sendcnt = 0;
 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
 	bcs->event = 0;
@@ -795,34 +862,17 @@
 	return (0);
 }
 
-static void
-tiger_manl1(struct PStack *st, int pr,
-	  void *arg)
-{
-	switch (pr) {
-		case (PH_ACTIVATE_REQ):
-			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
-			st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
-			break;
-		case (PH_DEACTIVATE_REQ):
-			if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
-				mode_tiger(st->l1.bcs, 0, 0);
-			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
-			break;
-	}
-}
-
 int
 setstack_tiger(struct PStack *st, struct BCState *bcs)
 {
-	if (open_tigerstate(st->l1.hardware, bcs->channel))
+	bcs->channel = st->l1.bc;
+	if (open_tigerstate(st->l1.hardware, bcs))
 		return (-1);
 	st->l1.bcs = bcs;
 	st->l2.l2l1 = tiger_l2l1;
-	st->ma.manl1 = tiger_manl1;
 	setstack_manager(st);
 	bcs->st = st;
+	setstack_l1_B(st);
 	return (0);
 }
 
@@ -830,8 +880,6 @@
 __initfunc(void
 inittiger(struct IsdnCardState *cs))
 {
-	char tmp[128];
-
 	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_SIZE * sizeof(unsigned int),
 		GFP_KERNEL | GFP_DMA))) {
 		printk(KERN_WARNING
@@ -845,9 +893,8 @@
 	cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
 	
 	memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
-	sprintf(tmp, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
+	debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
 		(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_SIZE - 1));
-	debugl1(cs, tmp);
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
 		cs->hw.njet.base + NETJET_DMA_READ_START);
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
@@ -860,9 +907,8 @@
 		       "HiSax: No memory for tiger.rec\n");
 		return;
 	}
-	sprintf(tmp, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
+	debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
 		(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1));
-	debugl1(cs, tmp);
 	cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
 	memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_SIZE * sizeof(unsigned int));
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
@@ -871,11 +917,10 @@
 		cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_SIZE - 1),
 		cs->hw.njet.base + NETJET_DMA_WRITE_END);
-	sprintf(tmp, "tiger: dmacfg  %x/%x  pulse=%d",
+	debugl1(cs, "tiger: dmacfg  %x/%x  pulse=%d",
 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
 		inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
 		bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-	debugl1(cs, tmp);
 	cs->hw.njet.last_is0 = 0;
 	cs->bcs[0].BC_SetStack = setstack_tiger;
 	cs->bcs[1].BC_SetStack = setstack_tiger;
@@ -906,8 +951,8 @@
 netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, sval, stat = 1;
-	char tmp[128];
+	u_char val, sval;
+	long flags;
 
 	if (!cs) {
 		printk(KERN_WARNING "NETjet: Spurious interrupt!\n");
@@ -916,49 +961,49 @@
 	if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) &
 		NETJET_ISACIRQ)) {
 		val = ReadISAC(cs, ISAC_ISTA);
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "tiger: i1 %x %x", sval, val);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "tiger: i1 %x %x", sval, val);
 		if (val) {
 			isac_interrupt(cs, val);
-			stat |= 2;
+			WriteISAC(cs, ISAC_MASK, 0xFF);
+			WriteISAC(cs, ISAC_MASK, 0x0);
 		}
 	}
-	if ((cs->hw.njet.irqstat0 = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
-/*		sprintf(tmp, "tiger: ist0 %x  %x %x  %x/%x  pulse=%d",
+	save_flags(flags);
+	cli();
+	if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) {
+		if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
+			restore_flags(flags);
+			return;
+		}
+		cs->hw.njet.irqstat0 = sval;
+		restore_flags(flags);
+/*		debugl1(cs, "tiger: ist0 %x  %x %x  %x/%x  pulse=%d",
 			sval, 
 			bytein(cs->hw.njet.base + NETJET_DMACTRL),
 			bytein(cs->hw.njet.base + NETJET_IRQMASK0),
 			inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
 			inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
 			bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
-		debugl1(cs, tmp);
 */
-		if (cs->hw.njet.last_is0 & cs->hw.njet.irqstat0 & 0xf) {
-			sprintf(tmp, "tiger: ist0 %x->%x irq lost",
-				cs->hw.njet.last_is0, cs->hw.njet.irqstat0);
-			debugl1(cs, tmp);
-		}
-		cs->hw.njet.last_is0 = cs->hw.njet.irqstat0;
 /*		cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30;
 */		byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0);
 /*		byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0);
-*/		if (cs->hw.njet.irqstat0 & 0x0c)
+*/		if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ)
 			read_tiger(cs);
-		if (cs->hw.njet.irqstat0 & 0x03)
+		if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE)
 			write_tiger(cs);
-	}
+		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
+	} else
+		restore_flags(flags);
+
 /*	if (!testcnt--) {
 		cs->hw.njet.dmactrl = 0;
 		byteout(cs->hw.njet.base + NETJET_DMACTRL,
 			cs->hw.njet.dmactrl);
 		byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
 	}
-*/	if (stat & 2) {
-		WriteISAC(cs, ISAC_MASK, 0xFF);
-		WriteISAC(cs, ISAC_MASK, 0x0);
-	}
+*/
 }
 
 static void
@@ -1004,13 +1049,12 @@
 		case CARD_RELEASE:
 			release_io_netjet(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &netjet_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inittiger(cs);
 			clear_pending_isac_ints(cs);
 			initisac(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -1018,9 +1062,11 @@
 	return(0);
 }
 
-
-
-static 	int pci_index __initdata = 0;
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *dev_netjet __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
 
 __initfunc(int
 setup_netjet(struct IsdnCard *card))
@@ -1029,15 +1075,40 @@
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 #if CONFIG_PCI
+#ifndef COMPAT_HAS_NEW_PCI
 	u_char pci_bus, pci_device_fn, pci_irq;
 	u_int pci_ioaddr, found;
 #endif
-
+#endif
 	strcpy(tmp, NETjet_revision);
 	printk(KERN_INFO "HiSax: Traverse Tech. NETjet driver Rev. %s\n", HiSax_getrev(tmp));
 	if (cs->typ != ISDN_CTYPE_NETJET)
 		return(0);
+	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
 #if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "Netjet: no PCI bus present\n");
+		return(0);
+	}
+	if ((dev_netjet = pci_find_device(PCI_VENDOR_TRAVERSE_TECH,
+		PCI_NETJET_ID,  dev_netjet))) {
+		cs->irq = dev_netjet->irq;
+		if (!cs->irq) {
+			printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
+			return(0);
+		}
+		cs->hw.njet.base = dev_netjet->base_address[0]
+			& PCI_BASE_ADDRESS_IO_MASK; 
+		if (!cs->hw.njet.base) {
+			printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
+			return(0);
+		}
+	} else {
+		printk(KERN_WARNING "NETjet: No PCI card found\n");
+		return(0);
+	}
+#else
 	found = 0;
 	for (; pci_index < 0xff; pci_index++) {
 		if (pcibios_find_device(PCI_VENDOR_TRAVERSE_TECH,
@@ -1045,7 +1116,7 @@
 			== PCIBIOS_SUCCESSFUL)
 			found = 1;
 		else
-			break;
+			continue;
 		/* get IRQ */
 		pcibios_read_config_byte(pci_bus, pci_device_fn,
 			PCI_INTERRUPT_LINE, &pci_irq);
@@ -1060,6 +1131,7 @@
 		printk(KERN_WARNING "NETjet: No PCI card found\n");
 		return(0);
 	}
+	pci_index++;
 	if (!pci_irq) {
 		printk(KERN_WARNING "NETjet: No IRQ for PCI card found\n");
 		return(0);
@@ -1068,11 +1140,11 @@
 		printk(KERN_WARNING "NETjet: No IO-Adr for PCI card found\n");
 		return(0);
 	}
-	pci_ioaddr &= ~3; /* remove io/mem flag */
-	cs->hw.njet.base = pci_ioaddr; 
-	cs->hw.njet.auxa = pci_ioaddr + NETJET_AUXDATA;
-	cs->hw.njet.isac = pci_ioaddr | NETJET_ISAC_OFF;
+	cs->hw.njet.base = pci_ioaddr & PCI_BASE_ADDRESS_IO_MASK; 
 	cs->irq = pci_irq;
+#endif /* COMPAT_HAS_NEW_PCI */
+	cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA;
+	cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF;
 	bytecnt = 256;
 #else
 	printk(KERN_WARNING "NETjet: NO_PCI_BIOS\n");
@@ -1101,6 +1173,8 @@
 	cs->BC_Write_Reg = &dummywr;
 	cs->BC_Send_Data = &fill_dma;
 	cs->cardmsg = &NETjet_card_msg;
+	cs->irq_func = &netjet_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
 	ISACVersion(cs, "NETjet:");
 	return (1);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/niccy.c linux.pre11.3/drivers/isdn/hisax/niccy.c
--- linux.vanilla/drivers/isdn/hisax/niccy.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/niccy.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: niccy.c,v 1.2 1998/02/11 17:31:04 keil Exp $
+/* $Id: niccy.c,v 1.6 1999/07/12 21:05:23 keil Exp $
 
  * niccy.c  low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
  *          compatible (SAGEM cybermodem)
@@ -8,24 +8,38 @@
  * Thanks to Dr. Neuhaus and SAGEM for informations
  *
  * $Log: niccy.c,v $
- * Revision 1.2  1998/02/11 17:31:04  keil
- * new file
+ * Revision 1.6  1999/07/12 21:05:23  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.5  1999/07/01 08:12:07  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
  *
+ * Revision 1.4  1998/04/16 19:16:48  keil
+ * need config.h
  *
+ * Revision 1.3  1998/04/15 16:42:59  keil
+ * new init code
+ *
+ * Revision 1.2  1998/02/11 17:31:04  keil
+ * new file
  *
  */
 
-#include <linux/config.h>
+
 #define __NO_VERSION__
+#include <linux/config.h>
 #include "hisax.h"
 #include "isac.h"
 #include "hscx.h"
 #include "isdnl1.h"
 #include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
 #include <linux/bios32.h>
+#endif
 
 extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.2 $";
+const char *niccy_revision = "$Revision: 1.6 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -44,6 +58,10 @@
 /* PCI stuff */
 #define PCI_VENDOR_DR_NEUHAUS	0x1267
 #define PCI_NICCY_ID		0x1016
+#define PCI_IRQ_CTRL_REG	0x38
+#define PCI_IRQ_ENABLE		0x1f00
+#define PCI_IRQ_DISABLE		0xff0000
+#define PCI_IRQ_ASSERT		0x800000
 
 static inline u_char
 readreg(unsigned int ale, unsigned int adr, u_char off)
@@ -146,24 +164,27 @@
 niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "Niccy: Spurious interrupt!\n");
 		return;
 	}
+	if (cs->subtyp == NICCY_PCI) {
+		int ival;
+		ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */
+			return;
+		outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+	}
 	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -176,24 +197,26 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
-		writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
-	}
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0);
 }
 
 void
 release_io_niccy(struct IsdnCardState *cs)
 {
-	if (cs->subtyp == NICCY_PCI)
+	if (cs->subtyp == NICCY_PCI) {
+		int val;
+		
+		val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		val &= PCI_IRQ_DISABLE;
+		outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+		release_region(cs->hw.niccy.cfg_reg, 0x80);
 		release_region(cs->hw.niccy.isac, 4);
-	else {
+	} else {
 		release_region(cs->hw.niccy.isac, 2);
 		release_region(cs->hw.niccy.isac_ale, 2);
 	}
@@ -202,7 +225,13 @@
 static void
 niccy_reset(struct IsdnCardState *cs)
 {
-	// No reset procedure known
+	int val, nval;
+	
+	val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+	nval = val | PCI_IRQ_ENABLE;
+	outl(nval, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG);
+
+	inithscxisac(cs, 3);
 }
 
 static int
@@ -215,14 +244,8 @@
 		case CARD_RELEASE:
 			release_io_niccy(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &niccy_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			niccy_reset(cs);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -230,7 +253,11 @@
 	return(0);
 }
 
-static 	int pci_index __initdata = 0;
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *niccy_dev __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
 
 __initfunc(int
 setup_niccy(struct IsdnCard *card))
@@ -272,8 +299,38 @@
 			request_region(cs->hw.niccy.isac_ale, 2, "niccy addr");
 	} else {
 #if CONFIG_PCI
-		u_char pci_bus, pci_device_fn, pci_irq;
 		u_int pci_ioaddr;
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "Niccy: no PCI bus present\n");
+			return(0);
+		}
+		cs->subtyp = 0;
+		if ((niccy_dev = pci_find_device(PCI_VENDOR_DR_NEUHAUS,
+			   PCI_NICCY_ID, niccy_dev))) {
+			/* get IRQ */
+			if (!niccy_dev->irq) {
+				printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->irq = niccy_dev->irq;
+			if (!niccy_dev->base_address[0]) {
+				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
+				return(0);
+			}
+			cs->hw.niccy.cfg_reg = niccy_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
+			if (!niccy_dev->base_address[1]) {
+				printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			pci_ioaddr = niccy_dev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+			cs->subtyp = NICCY_PCI;
+		} else {
+			printk(KERN_WARNING "Niccy: No PCI card found\n");
+			return(0);
+		}
+#else
+		u_char pci_bus, pci_device_fn, pci_irq;
 
 		cs->subtyp = 0;
 		for (; pci_index < 0xff; pci_index++) {
@@ -282,17 +339,22 @@
 			   == PCIBIOS_SUCCESSFUL)
 				cs->subtyp = NICCY_PCI;
 			else
-				break;
+				continue;
 			/* get IRQ */
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 				PCI_INTERRUPT_LINE, &pci_irq);
 
+			/* get IO pci AMCC address */
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_0, &pci_ioaddr);
+			if (!pci_ioaddr) {
+				printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
+				return(0);
+			}
+			cs->hw.niccy.cfg_reg = pci_ioaddr & ~3 ;
 			/* get IO address */
-			/* if it won't work try the other PCI addresses
-			 * PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5
-			 */
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
-				PCI_BASE_ADDRESS_2, &pci_ioaddr);
+				PCI_BASE_ADDRESS_1, &pci_ioaddr);
 			if (cs->subtyp)
 				break;
 		}
@@ -300,21 +362,23 @@
 			printk(KERN_WARNING "Niccy: No PCI card found\n");
 			return(0);
 		}
+		pci_index++;
 		if (!pci_irq) {
 			printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n");
 			return(0);
 		}
-
 		if (!pci_ioaddr) {
 			printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
 			return(0);
 		}
 		pci_ioaddr &= ~3; /* remove io/mem flag */
+		cs->irq = pci_irq;
+#endif /* COMPAT_HAS_NEW_PCI */
+		cs->irq_flags |= SA_SHIRQ;
 		cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA;
 		cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR;
 		cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA;
 		cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR;
-		cs->irq = pci_irq;
 		if (check_region((cs->hw.niccy.isac), 4)) {
 			printk(KERN_WARNING
 				"HiSax: %s data port %x-%x already in use\n",
@@ -324,6 +388,17 @@
 			return (0);
 		} else
 			request_region(cs->hw.niccy.isac, 4, "niccy");
+		if (check_region(cs->hw.niccy.cfg_reg, 0x80)) {
+			printk(KERN_WARNING
+			       "HiSax: %s pci port %x-%x already in use\n",
+				CardType[card->typ],
+				cs->hw.niccy.cfg_reg,
+				cs->hw.niccy.cfg_reg + 0x80);
+			release_region(cs->hw.niccy.isac, 4);
+			return (0);
+		} else {
+			request_region(cs->hw.niccy.cfg_reg, 0x80, "niccy pci");
+		}
 #else
 		printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n");
 		printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n");
@@ -334,7 +409,6 @@
 		"HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n",
 		CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI",
 		cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale);
-	niccy_reset(cs);
 	cs->readisac = &ReadISAC;
 	cs->writeisac = &WriteISAC;
 	cs->readisacfifo = &ReadISACfifo;
@@ -343,6 +417,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &niccy_card_msg;
+	cs->irq_func = &niccy_interrupt;
 	ISACVersion(cs, "Niccy:");
 	if (HscxVersion(cs, "Niccy:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/q931.c linux.pre11.3/drivers/isdn/hisax/q931.c
--- linux.vanilla/drivers/isdn/hisax/q931.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/q931.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: q931.c,v 1.6 1997/07/27 21:09:44 keil Exp $
+/* $Id: q931.c,v 1.7 1998/11/15 23:55:17 keil Exp $
 
  * q931.c       code to decode ITU Q.931 call control messages
  *
@@ -14,6 +14,9 @@
  *
  *
  * $Log: q931.c,v $
+ * Revision 1.7  1998/11/15 23:55:17  keil
+ * changes from 2.0
+ *
  * Revision 1.6  1997/07/27 21:09:44  keil
  * move functions to isdnl3.c
  *
@@ -159,7 +162,7 @@
 	{MT_N0_CLO_ACK, "CLOse ACKnowledge"}
 };
 
-int mt_n0_len = (sizeof(mt_n0) / sizeof(struct MessageType));
+#define MT_N0_LEN (sizeof(mt_n0) / sizeof(struct MessageType))
 
 static
 struct MessageType mt_n1[] =
@@ -196,7 +199,7 @@
 	{MT_N1_STAT, "STATus"}
 };
 
-int mt_n1_len = (sizeof(mt_n1) / sizeof(struct MessageType));
+#define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
 
 static struct MessageType fac_1tr6[] =
 {
@@ -220,9 +223,7 @@
 	{FAC_Rueckwechsel, "Rueckwechsel"},
 	{FAC_Umleitung, "Umleitung"}
 };
-int fac_1tr6_len = (sizeof(fac_1tr6) / sizeof(struct MessageType));
-
-
+#define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType))
 
 static int
 prbits(char *dest, u_char b, int start, int len)
@@ -925,7 +926,7 @@
 	{WE0_userInfo, "User Info", general}
 };
 
-static int we_0_len = (sizeof(we_0) / sizeof(struct InformationElement));
+#define WE_0_LEN (sizeof(we_0) / sizeof(struct InformationElement))
 
 static struct InformationElement we_6[] =
 {
@@ -937,7 +938,7 @@
 	{WE6_statusCalled, "Status Called", general},
 	{WE6_addTransAttr, "Additional Transmission Attributes", general}
 };
-static int we_6_len = (sizeof(we_6) / sizeof(struct InformationElement));
+#define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement))
 
 int
 QuickHex(char *txt, u_char * p, int cnt)
@@ -964,39 +965,92 @@
 }
 
 void
-LogFrame(struct IsdnCardState *sp, u_char * buf, int size)
+LogFrame(struct IsdnCardState *cs, u_char * buf, int size)
 {
 	char *dp;
 
 	if (size < 1)
 		return;
-	dp = sp->dlogspace;
-	if (size < 4096 / 3 - 10) {
-		dp += sprintf(dp, "HEX:");
+	dp = cs->dlog;
+	if (size < MAX_DLOG_SPACE / 3 - 10) {
+		*dp++ = 'H';
+		*dp++ = 'E';
+		*dp++ = 'X';
+		*dp++ = ':';
 		dp += QuickHex(dp, buf, size);
 		dp--;
 		*dp++ = '\n';
 		*dp = 0;
+		HiSax_putstatus(cs, NULL, cs->dlog);
 	} else
-		sprintf(dp, "LogFrame: warning Frame too big (%d)\n",
-			size);
-	HiSax_putstatus(sp, sp->dlogspace);
+		HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
 }
 
 void
-dlogframe(struct IsdnCardState *sp, u_char * buf, int size, char *comment)
+dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
 {
-	u_char *bend = buf + size;
+	u_char *bend, *buf;
 	char *dp;
 	unsigned char pd, cr_l, cr, mt;
-	int i, cs = 0, cs_old = 0, cs_fest = 0;
+	unsigned char sapi, tei, ftyp;
+	int i, cset = 0, cs_old = 0, cs_fest = 0;
+	int size, finish = 0;
 
-	if (size < 1)
+	if (skb->len < 3)
 		return;
 	/* display header */
-	dp = sp->dlogspace;
-	dp += sprintf(dp, "%s\n", comment);
-
+	dp = cs->dlog;
+	dp += jiftime(dp, jiffies);
+	*dp++ = ' ';
+	sapi = skb->data[0] >> 2;
+	tei  = skb->data[1] >> 1;
+	ftyp = skb->data[2];
+	buf = skb->data;
+	dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
+	size = skb->len;
+	
+	if (tei == GROUP_TEI) {
+		if (sapi == CTRL_SAPI) { /* sapi 0 */
+			if (ftyp == 3) {
+				dp += sprintf(dp, "broadcast\n");
+				buf += 3;
+				size -= 3;
+			} else {
+				dp += sprintf(dp, "no UI broadcast\n");
+				finish = 1;
+			}
+		} else if (sapi == TEI_SAPI) {
+			dp += sprintf(dp, "tei managment\n");
+			finish = 1;
+		} else {
+			dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi);
+			finish = 1;
+		}
+	} else {
+		if (sapi == CTRL_SAPI) {
+			if (!(ftyp & 1)) { /* IFrame */
+				dp += sprintf(dp, "with tei %d\n", tei);
+				buf += 4;
+				size -= 4;
+			} else {
+				dp += sprintf(dp, "SFrame with tei %d\n", tei);
+				finish = 1;
+			}
+		} else {
+			dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei);
+			finish = 1;
+		}
+	}
+	bend = skb->data + skb->len;
+	if (buf >= bend) {
+		dp += sprintf(dp, "frame too short\n");
+		finish = 1;
+	}
+	if (finish) {
+		*dp = 0;
+		HiSax_putstatus(cs, NULL, cs->dlog);
+		return;
+	}
 	if ((0xfe & buf[0]) == PROTO_DIS_N0) {	/* 1TR6 */
 		/* locate message type */
 		pd = *buf++;
@@ -1007,11 +1061,11 @@
 			cr = 0;
 		mt = *buf++;
 		if (pd == PROTO_DIS_N0) {	/* N0 */
-			for (i = 0; i < mt_n0_len; i++)
+			for (i = 0; i < MT_N0_LEN; i++)
 				if (mt_n0[i].nr == mt)
 					break;
 			/* display message type if it exists */
-			if (i == mt_n0_len)
+			if (i == MT_N0_LEN)
 				dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n",
 					      cr & 0x7f, (cr & 0x80) ? "called" : "caller",
 					      size, mt);
@@ -1020,11 +1074,11 @@
 					      cr & 0x7f, (cr & 0x80) ? "called" : "caller",
 					      size, mt_n0[i].descr);
 		} else {	/* N1 */
-			for (i = 0; i < mt_n1_len; i++)
+			for (i = 0; i < MT_N1_LEN; i++)
 				if (mt_n1[i].nr == mt)
 					break;
 			/* display message type if it exists */
-			if (i == mt_n1_len)
+			if (i == MT_N1_LEN)
 				dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n",
 					      cr & 0x7f, (cr & 0x80) ? "called" : "caller",
 					      size, mt);
@@ -1041,8 +1095,8 @@
 				switch ((*buf >> 4) & 7) {
 					case 1:
 						dp += sprintf(dp, "  Shift %x\n", *buf & 0xf);
-						cs_old = cs;
-						cs = *buf & 7;
+						cs_old = cset;
+						cset = *buf & 7;
 						cs_fest = *buf & 8;
 						break;
 					case 3:
@@ -1066,33 +1120,33 @@
 				continue;
 			}
 			/* No, locate it in the table */
-			if (cs == 0) {
-				for (i = 0; i < we_0_len; i++)
+			if (cset == 0) {
+				for (i = 0; i < WE_0_LEN; i++)
 					if (*buf == we_0[i].nr)
 						break;
 
 				/* When found, give appropriate msg */
-				if (i != we_0_len) {
+				if (i != WE_0_LEN) {
 					dp += sprintf(dp, "  %s\n", we_0[i].descr);
 					dp += we_0[i].f(dp, buf);
 				} else
-					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
-			} else if (cs == 6) {
-				for (i = 0; i < we_6_len; i++)
+					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
+			} else if (cset == 6) {
+				for (i = 0; i < WE_6_LEN; i++)
 					if (*buf == we_6[i].nr)
 						break;
 
 				/* When found, give appropriate msg */
-				if (i != we_6_len) {
+				if (i != WE_6_LEN) {
 					dp += sprintf(dp, "  %s\n", we_6[i].descr);
 					dp += we_6[i].f(dp, buf);
 				} else
-					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
+					dp += sprintf(dp, "  Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
 			} else
-				dp += sprintf(dp, "  Unknown Codeset %d attribute %x attribute size %d\n", cs, *buf, buf[1]);
+				dp += sprintf(dp, "  Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
 			/* Skip to next element */
 			if (cs_fest == 8) {
-				cs = cs_old;
+				cset = cs_old;
 				cs_old = 0;
 				cs_fest = 0;
 			}
@@ -1170,6 +1224,6 @@
 	} else {
 		dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
 	}
-	dp += sprintf(dp, "\n");
-	HiSax_putstatus(sp, sp->dlogspace);
+	*dp = 0;
+	HiSax_putstatus(cs, NULL, cs->dlog);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/rawhdlc.c linux.pre11.3/drivers/isdn/hisax/rawhdlc.c
--- linux.vanilla/drivers/isdn/hisax/rawhdlc.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/rawhdlc.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: rawhdlc.c,v 1.2 1998/02/09 10:53:51 keil Exp $
+/* $Id: rawhdlc.c,v 1.3 1998/06/17 19:51:21 he Exp $
 
  * rawhdlc.c     support routines for cards that don't support HDLC
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/s0box.c linux.pre11.3/drivers/isdn/hisax/s0box.c
--- linux.vanilla/drivers/isdn/hisax/s0box.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/s0box.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,267 @@
+/* $Id: s0box.c,v 2.2 1999/07/12 21:05:25 keil Exp $
+
+ * s0box.c      low level stuff for Creatix S0BOX
+ *
+ * Author       S0BOX specific stuff: Enrik Berkhan (enrik@starfleet.inka.de)
+ *
+ *
+ */
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+const char *s0box_revision = "$Revision: 2.2 $";
+
+static inline void
+writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	outb_p(0x1c,padr+2);
+	outb_p(0x14,padr+2);
+	outb_p((addr+off)&0x7f,padr);
+	outb_p(0x16,padr+2);
+	outb_p(val,padr);
+	outb_p(0x17,padr+2);
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	restore_flags(flags);
+}
+
+static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf,
+			 0, 0, 0, 0, 0, 0, 0, 0,
+			 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ;
+
+static inline u_char
+readreg(unsigned int padr, signed int addr, u_char off) {
+	register u_char n1, n2;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	outb_p(0x1c,padr+2);
+	outb_p(0x14,padr+2);
+	outb_p((addr+off)|0x80,padr);
+	outb_p(0x16,padr+2);
+	outb_p(0x17,padr+2);
+	n1 = (inb_p(padr+1) >> 3) & 0x17;
+	outb_p(0x16,padr+2);
+	n2 = (inb_p(padr+1) >> 3) & 0x17;
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	restore_flags(flags);
+	return nibtab[n1] | (nibtab[n2] << 4);
+}
+
+static inline void
+read_fifo(unsigned int padr, signed int adr, u_char * data, int size)
+{
+	int i;
+	register u_char n1, n2;
+	
+	outb_p(0x1c, padr+2);
+	outb_p(0x14, padr+2);
+	outb_p(adr|0x80, padr);
+	outb_p(0x16, padr+2);
+	for (i=0; i<size; i++) {
+		outb_p(0x17, padr+2);
+		n1 = (inb_p(padr+1) >> 3) & 0x17;
+		outb_p(0x16,padr+2);
+		n2 = (inb_p(padr+1) >> 3) & 0x17;
+		*(data++)=nibtab[n1] | (nibtab[n2] << 4);
+	}
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	return;
+}
+
+static inline void
+write_fifo(unsigned int padr, signed int adr, u_char * data, int size)
+{
+	int i;
+	outb_p(0x1c, padr+2);
+	outb_p(0x14, padr+2);
+	outb_p(adr&0x7f, padr);
+	for (i=0; i<size; i++) {
+		outb_p(0x16, padr+2);
+		outb_p(*(data++), padr);
+		outb_p(0x17, padr+2);
+	}
+	outb_p(0x14,padr+2);
+	outb_p(0x1c,padr+2);
+	return;
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg)
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 5
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	int count = 0;
+
+	if (!cs) {
+		printk(KERN_WARNING "Teles: Spurious interrupt!\n");
+		return;
+	}
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	count++;
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA);
+	if (val && count < MAXCOUNT) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (count >= MAXCOUNT)
+		printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
+}
+
+void
+release_io_s0box(struct IsdnCardState *cs)
+{
+	release_region(cs->hw.teles3.cfg_reg, 8);
+}
+
+static int
+S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			break;
+		case CARD_RELEASE:
+			release_io_s0box(cs);
+			break;
+		case CARD_INIT:
+			inithscxisac(cs, 3);
+			break;
+		case CARD_TEST:
+			break;
+	}
+	return(0);
+}
+
+__initfunc(int
+setup_s0box(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, s0box_revision);
+	printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_S0BOX)
+		return (0);
+
+	cs->hw.teles3.cfg_reg = card->para[1];
+	cs->hw.teles3.hscx[0] = -0x20;
+	cs->hw.teles3.hscx[1] = 0x0;
+	cs->hw.teles3.isac = 0x20;
+	cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e;
+	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
+	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
+	cs->irq = card->para[0];
+	if (check_region(cs->hw.teles3.cfg_reg,8)) {
+		printk(KERN_WARNING
+		       "HiSax: %s ports %x-%x already in use\n",
+		       CardType[cs->typ],
+                       cs->hw.teles3.cfg_reg,
+                       cs->hw.teles3.cfg_reg + 7);
+		return 0;
+	} else
+		request_region(cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O");
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d isac:0x%x  cfg:0x%x\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles3.isac, cs->hw.teles3.cfg_reg);
+	printk(KERN_INFO
+	       "HiSax: hscx A:0x%x  hscx B:0x%x\n",
+	       cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]);
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &S0Box_card_msg;
+	cs->irq_func = &s0box_interrupt;
+	ISACVersion(cs, "S0Box:");
+	if (HscxVersion(cs, "S0Box:")) {
+		printk(KERN_WARNING
+		       "S0Box: wrong HSCX versions check IO address\n");
+		release_io_s0box(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/saphir.c linux.pre11.3/drivers/isdn/hisax/saphir.c
--- linux.vanilla/drivers/isdn/hisax/saphir.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/saphir.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,326 @@
+/* $Id: saphir.c,v 1.3 1999/07/12 21:05:26 keil Exp $
+
+ * saphir.c low level stuff for HST Saphir 1
+ *
+ * Author     Karsten Keil (keil@isdn4linux.de)
+ *
+ * Thanks to    HST High Soft Tech GmbH
+ *
+ *
+ * $Log: saphir.c,v $
+ * Revision 1.3  1999/07/12 21:05:26  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.2  1999/07/01 08:07:55  keil
+ * Initial version
+ *
+ *
+ */
+
+
+#define __NO_VERSION__
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+
+extern const char *CardType[];
+static char *saphir_rev = "$Revision: 1.3 $";
+
+#define byteout(addr,val) outb(val,addr)
+#define bytein(addr) inb(addr)
+
+#define ISAC_DATA	0
+#define HSCX_DATA	1
+#define ADDRESS_REG	2
+#define IRQ_REG		3
+#define SPARE_REG	4
+#define RESET_REG	5
+
+static inline u_char
+readreg(unsigned int ale, unsigned int adr, u_char off)
+{
+	register u_char ret;
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(ale, off);
+	ret = bytein(adr);
+	restore_flags(flags);
+	return (ret);
+}
+
+static inline void
+readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo read without cli because it's allready done  */
+
+	byteout(ale, off);
+	insb(adr, data, size);
+}
+
+
+static inline void
+writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+{
+	long flags;
+
+	save_flags(flags);
+	cli();
+	byteout(ale, off);
+	byteout(adr, data);
+	restore_flags(flags);
+}
+
+static inline void
+writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+{
+	/* fifo write without cli because it's allready done  */
+	byteout(ale, off);
+	outsb(adr, data, size);
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
+		offset + (hscx ? 0x40 : 0)));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx,
+		offset + (hscx ? 0x40 : 0), value);
+}
+
+#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0))
+#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data)
+
+#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \
+		cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+
+	if (!cs) {
+		printk(KERN_WARNING "saphir: Spurious interrupt!\n");
+		return;
+	}
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
+      Start_HSCX:
+	if (val)
+		hscx_int_main(cs, val);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40);
+	if (val) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "HSCX IntStat after IntRoutine");
+		goto Start_HSCX;
+	}
+	val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA);
+	if (val) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	/* Watchdog */
+	if (cs->hw.saphir.timer.function) {
+		del_timer(&cs->hw.saphir.timer);
+		cs->hw.saphir.timer.expires = jiffies + 1*HZ;
+		add_timer(&cs->hw.saphir.timer);
+	} else
+		printk(KERN_WARNING "saphir: Spurious timer!\n");
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0);
+	writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0);
+}
+
+static void
+SaphirWatchDog(struct IsdnCardState *cs)
+{
+        /* 5 sec WatchDog, so read at least every 4 sec */
+	cs->readisac(cs, ISAC_RBCH);
+	del_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.expires = jiffies + 1*HZ;
+	add_timer(&cs->hw.saphir.timer);
+}
+
+void
+release_io_saphir(struct IsdnCardState *cs)
+{
+	long flags;
+	
+	save_flags(flags);
+	cli();
+	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
+	del_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.function = NULL;
+	restore_flags(flags);
+	if (cs->hw.saphir.cfg_reg)
+		release_region(cs->hw.saphir.cfg_reg, 6);
+}
+
+static int
+saphir_reset(struct IsdnCardState *cs)
+{
+	long flags;
+	u_char irq_val;
+
+	switch(cs->irq) {
+		case 5: irq_val = 0;
+			break;
+		case 3: irq_val = 1;
+			break;
+		case 11:
+			irq_val = 2;
+			break;
+		case 12:
+			irq_val = 3;
+			break;
+		case 15:
+			irq_val = 4;
+			break;
+		default:
+			printk(KERN_WARNING "HiSax: saphir wrong IRQ %d\n",
+				cs->irq);
+			return (1);
+	}
+	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
+	save_flags(flags);
+	sti();
+	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
+	byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0);
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((30*HZ)/1000);	/* Timeout 30ms */
+	restore_flags(flags);
+	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val);
+	byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02);
+	return (0);
+}
+
+static int
+saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			saphir_reset(cs);
+			return(0);
+		case CARD_RELEASE:
+			release_io_saphir(cs);
+			return(0);
+		case CARD_INIT:
+			inithscxisac(cs, 3);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+
+__initfunc(int
+setup_saphir(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+
+	strcpy(tmp, saphir_rev);
+	printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_HSTSAPHIR)
+		return (0);
+
+	/* IO-Ports */
+	cs->hw.saphir.cfg_reg = card->para[1];
+	cs->hw.saphir.isac = card->para[1] + ISAC_DATA;
+	cs->hw.saphir.hscx = card->para[1] + HSCX_DATA;
+	cs->hw.saphir.ale = card->para[1] + ADDRESS_REG;
+	cs->irq = card->para[0];
+	if (check_region((cs->hw.saphir.cfg_reg), 6)) {
+		printk(KERN_WARNING
+			"HiSax: %s config port %x-%x already in use\n",
+			CardType[card->typ],
+			cs->hw.saphir.cfg_reg,
+			cs->hw.saphir.cfg_reg + 5);
+		return (0);
+	} else
+		request_region(cs->hw.saphir.cfg_reg,6, "saphir");
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d io:0x%X\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.saphir.cfg_reg);
+
+	cs->hw.saphir.timer.function = (void *) SaphirWatchDog;
+	cs->hw.saphir.timer.data = (long) cs;
+	init_timer(&cs->hw.saphir.timer);
+	cs->hw.saphir.timer.expires = jiffies + 4*HZ;
+	add_timer(&cs->hw.saphir.timer);
+	if (saphir_reset(cs)) {
+		release_io_saphir(cs);
+		return (0);
+	}
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &saphir_card_msg;
+	cs->irq_func = &saphir_interrupt;
+	ISACVersion(cs, "saphir:");
+	if (HscxVersion(cs, "saphir:")) {
+		printk(KERN_WARNING
+		    "saphir: wrong HSCX versions check IO address\n");
+		release_io_saphir(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/sedlbauer.c linux.pre11.3/drivers/isdn/hisax/sedlbauer.c
--- linux.vanilla/drivers/isdn/hisax/sedlbauer.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/hisax/sedlbauer.c	Mon Jul 19 23:59:34 1999
@@ -1,11 +1,14 @@
-/* $Id: sedlbauer.c,v 1.6 1998/02/09 18:46:06 keil Exp $
+/* $Id: sedlbauer.c,v 1.11 1999/07/12 21:05:27 keil Exp $
 
  * sedlbauer.c  low level stuff for Sedlbauer cards
- *              includes Support for the Sedlbauer Speed Star 
- *              derived from the original file dynalink.c from Karsten Keil
+ *              includes support for the Sedlbauer speed star (speed star II),
+ *              support for the Sedlbauer speed fax+,
+ *              support for the Sedlbauer ISDN-Controller PC/104 and
+ *              support for the Sedlbauer speed pci
+ *              derived from the original file asuscom.c from Karsten Keil
  *
  * Copyright (C) 1997,1998 Marcus Niemann (for the modifications to
- *                                         the original file dynalink.c)
+ *                                         the original file asuscom.c)
  *
  * Author     Marcus Niemann (niemann@www-bib.fh-bielefeld.de)
  *
@@ -14,6 +17,22 @@
  *            Edgar Toernig
  *
  * $Log: sedlbauer.c,v $
+ * Revision 1.11  1999/07/12 21:05:27  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.10  1999/07/01 08:12:09  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.9  1998/11/15 23:55:20  keil
+ * changes from 2.0
+ *
+ * Revision 1.8  1998/08/13 23:34:51  keil
+ * starting speedfax+ (ISAR) support
+ *
+ * Revision 1.7  1998/04/15 16:44:33  keil
+ * new init code
+ *
  * Revision 1.6  1998/02/09 18:46:06  keil
  * Support for Sedlbauer PCMCIA (Marcus Niemann)
  *
@@ -35,36 +54,94 @@
  *
  */
 
+/* Supported cards:
+ * Card:	Chip:		Configuration:	Comment:
+ * ---------------------------------------------------------------------
+ * Speed Card	ISAC_HSCX	DIP-SWITCH
+ * Speed Win	ISAC_HSCX	ISAPNP
+ * Speed Fax+	ISAC_ISAR	ISAPNP		#HDLC works#
+ * Speed Star	ISAC_HSCX	CARDMGR
+ * Speed Win2	IPAC		ISAPNP
+ * ISDN PC/104	IPAC		DIP-SWITCH
+ * Speed Star2	IPAC		CARDMGR
+ * Speed PCI	IPAC		PNP		
+ *
+ * Important:
+ * For the sedlbauer speed fax+ to work properly you have to download 
+ * the firmware onto the card.
+ * For example: hisaxctrl <DriverID> 9 ISAR.BIN
+*/
+
+#define SEDLBAUER_PCI 1
+
 #define __NO_VERSION__
+#include <linux/config.h>
 #include "hisax.h"
 #include "isac.h"
+#include "ipac.h"
 #include "hscx.h"
+#include "isar.h"
 #include "isdnl1.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.6 $";
+const char *Sedlbauer_revision = "$Revision: 1.11 $";
 
 const char *Sedlbauer_Types[] =
-{"None", "Speed Card", "Speed Win", "Speed Star"};
+	{"None", "speed card/win", "speed star", "speed fax+", 
+	"speed win II / ISDN PC/104", "speed star II", "speed pci"};
+
+#ifdef SEDLBAUER_PCI
+#define PCI_VENDOR_SEDLBAUER	0xe159
+#define PCI_SPEEDPCI_ID	0x02
+#endif
  
-#define SEDL_SPEED_CARD 1
-#define SEDL_SPEED_WIN  2
-#define SEDL_SPEED_STAR 3
+#define SEDL_SPEED_CARD_WIN	1
+#define SEDL_SPEED_STAR 	2
+#define SEDL_SPEED_FAX		3
+#define SEDL_SPEED_WIN2_PC104 	4
+#define SEDL_SPEED_STAR2 	5
+#define SEDL_SPEED_PCI   	6
+
+#define SEDL_CHIP_TEST		0
+#define SEDL_CHIP_ISAC_HSCX	1
+#define SEDL_CHIP_ISAC_ISAR	2
+#define SEDL_CHIP_IPAC		3
+
+#define SEDL_BUS_ISA		1
+#define SEDL_BUS_PCI		2
+#define	SEDL_BUS_PCMCIA		3
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
 
-#define SEDL_RESET_ON	0
-#define SEDL_RESET_OFF	1
-#define SEDL_ISAC	2
-#define SEDL_HSCX	3
-#define SEDL_ADR	4
-
-#define SEDL_PCMCIA_RESET	0
-#define SEDL_PCMCIA_ISAC	1
-#define SEDL_PCMCIA_HSCX	2
-#define SEDL_PCMCIA_ADR		4
+#define SEDL_HSCX_ISA_RESET_ON	0
+#define SEDL_HSCX_ISA_RESET_OFF	1
+#define SEDL_HSCX_ISA_ISAC	2
+#define SEDL_HSCX_ISA_HSCX	3
+#define SEDL_HSCX_ISA_ADR	4
+
+#define SEDL_HSCX_PCMCIA_RESET	0
+#define SEDL_HSCX_PCMCIA_ISAC	1
+#define SEDL_HSCX_PCMCIA_HSCX	2
+#define SEDL_HSCX_PCMCIA_ADR	4
+
+#define SEDL_ISAR_ISA_ISAC		4
+#define SEDL_ISAR_ISA_ISAR		6
+#define SEDL_ISAR_ISA_ADR		8
+#define SEDL_ISAR_ISA_ISAR_RESET_ON	10
+#define SEDL_ISAR_ISA_ISAR_RESET_OFF	12
+
+#define SEDL_IPAC_ANY_ADR 	0
+#define SEDL_IPAC_ANY_IPAC	2
+
+#define SEDL_IPAC_PCI_BASE	0
+#define SEDL_IPAC_PCI_ADR	0xc0
+#define SEDL_IPAC_PCI_IPAC	0xc8
 
 #define SEDL_RESET      0x3	/* same as DOS driver */
 
@@ -139,6 +216,29 @@
 }
 
 static u_char
+ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset)
+{
+        return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80));}
+
+static void
+WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+        writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value);
+}
+
+static void
+ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+        readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
+}
+
+static void
+WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size)
+{
+        writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size);
+}
+
+static u_char
 ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
 {
 	return (readreg(cs->hw.sedl.adr,
@@ -152,6 +252,34 @@
 		 cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value);
 }
 
+/* ISAR access routines
+ * mode = 0 access with IRQ on
+ * mode = 1 access with IRQ off
+ * mode = 2 access with IRQ off and using last offset
+ */
+  
+static u_char
+ReadISAR(struct IsdnCardState *cs, int mode, u_char offset)
+{	
+	if (mode == 0)
+		return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset));
+	else if (mode == 1)
+		byteout(cs->hw.sedl.adr, offset);
+	return(bytein(cs->hw.sedl.hscx));
+}
+
+static void
+WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value)
+{
+	if (mode == 0)
+		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value);
+	else {
+		if (mode == 1)
+			byteout(cs->hw.sedl.adr, offset);
+		byteout(cs->hw.sedl.hscx, value);
+	}
+}
+
 /*
  * fast interrupt HSCX stuff goes here
  */
@@ -173,14 +301,14 @@
 sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
 		return;
 	}
 
-        if ((cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) && (*cs->busy_flag == 1)) {
+	if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) {
           /* The card tends to generate interrupts while being removed
              causing us to just crash the kernel. bad. */
           printk(KERN_WARNING "Sedlbauer: card not available!\n");
@@ -189,16 +317,12 @@
 
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
 	if (val) {
 		if (cs->debug & L1_DEB_HSCX)
@@ -211,23 +335,109 @@
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0);
+}
+
+static void
+sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char ista, val, icnt = 5;
+
+	if (!cs) {
+		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+		return;
+	}
+	ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+Start_IPAC:
+	if (cs->debug & L1_DEB_IPAC)
+		debugl1(cs, "IPAC ISTA %02X", ista);
+	if (ista & 0x0f) {
+		val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40);
+		if (ista & 0x01)
+			val |= 0x01;
+		if (ista & 0x04)
+			val |= 0x02;
+		if (ista & 0x08)
+			val |= 0x04;
+		if (val)
+			hscx_int_main(cs, val);
+	}
+	if (ista & 0x20) {
+		val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80);
+		if (val) {
+			isac_interrupt(cs, val);
+		}
+	}
+	if (ista & 0x10) {
+		val = 0x01;
+		isac_interrupt(cs, val);
 	}
+	ista  = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA);
+	if ((ista & 0x3f) && icnt) {
+		icnt--;
+		goto Start_IPAC;
+	}
+	if (!icnt)
+		printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0);
+}
+
+static void
+sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
+{
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+	int cnt = 5;
+
+	if (!cs) {
+		printk(KERN_WARNING "Sedlbauer: Spurious interrupt!\n");
+		return;
+	}
+
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+      Start_ISAR:
+	if (val & ISAR_IRQSTA)
+		isar_int_main(cs);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+      Start_ISAC:
+	if (val)
+		isac_interrupt(cs, val);
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT);
+	if ((val & ISAR_IRQSTA) && --cnt) {
+		if (cs->debug & L1_DEB_HSCX)
+			debugl1(cs, "ISAR IntStat after IntRoutine");
+		goto Start_ISAR;
+	}
+	val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA);
+	if (val && --cnt) {
+		if (cs->debug & L1_DEB_ISAC)
+			debugl1(cs, "ISAC IntStat after IntRoutine");
+		goto Start_ISAC;
+	}
+	if (!cnt)
+		printk(KERN_WARNING "Sedlbauer IRQ LOOP\n");
+
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK);
 }
 
 void
 release_io_sedlbauer(struct IsdnCardState *cs)
 {
-	int bytecnt = 8;
+	int bytecnt = (cs->subtyp == SEDL_SPEED_FAX) ? 16 : 8;
 
+	if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+		bytecnt = 256;
+	}
 	if (cs->hw.sedl.cfg_reg)
 		release_region(cs->hw.sedl.cfg_reg, bytecnt);
 }
@@ -237,16 +447,36 @@
 {
 	long flags;
 
-	if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA) {
-		byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
-		save_flags(flags);
-		sti();
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-		byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
-		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(1);
-		restore_flags(flags);
+	printk(KERN_INFO "Sedlbauer: resetting card\n");
+
+	if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) &&
+	   (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) {
+		if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20);
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((10*HZ)/1000);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0);
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((10*HZ)/1000);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0);
+			writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12);
+			restore_flags(flags);
+		} else {		
+			byteout(cs->hw.sedl.reset_on, SEDL_RESET);	/* Reset On */
+			save_flags(flags);
+			sti();
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((10*HZ)/1000);
+			byteout(cs->hw.sedl.reset_off, 0);	/* Reset Off */
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout((10*HZ)/1000);
+			restore_flags(flags);
+		}
 	}
 }
 
@@ -260,95 +490,274 @@
 		case CARD_RELEASE:
 			release_io_sedlbauer(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &sedlbauer_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				clear_pending_isac_ints(cs);
+				writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx,
+					ISAR_IRQBIT, 0);
+				initisac(cs);
+				initisar(cs);
+				/* Reenable all IRQ */
+				cs->writeisac(cs, ISAC_MASK, 0);
+				/* RESET Receiver and Transmitter */
+				cs->writeisac(cs, ISAC_CMDR, 0x41);
+			} else {
+				inithscxisac(cs, 3);
+			}
 			return(0);
 		case CARD_TEST:
 			return(0);
+		case CARD_LOAD_FIRM:
+			if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+				if (isar_load_firmware(cs, arg))
+					return(1);
+				else 
+					ll_run(cs);
+			}
+			return(0);
 	}
 	return(0);
 }
 
+
+#ifdef SEDLBAUER_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *dev_sedl __initdata = NULL;
+#else
+static  int pci_index __initdata = 0;
+#endif
+#endif
+
 __initfunc(int
 setup_sedlbauer(struct IsdnCard *card))
 {
-	int bytecnt;
+	int bytecnt, ver, val;
 	struct IsdnCardState *cs = card->cs;
 	char tmp[64];
 
 	strcpy(tmp, Sedlbauer_revision);
 	printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp));
+	
  	if (cs->typ == ISDN_CTYPE_SEDLBAUER) {
- 		cs->subtyp = SEDL_SPEED_CARD;
+ 		cs->subtyp = SEDL_SPEED_CARD_WIN;
+		cs->hw.sedl.bus = SEDL_BUS_ISA;
+		cs->hw.sedl.chip = SEDL_CHIP_TEST;
  	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) {	
  		cs->subtyp = SEDL_SPEED_STAR;
+		cs->hw.sedl.bus = SEDL_BUS_PCMCIA;
+		cs->hw.sedl.chip = SEDL_CHIP_TEST;
+ 	} else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) {	
+ 		cs->subtyp = SEDL_SPEED_FAX;
+		cs->hw.sedl.bus = SEDL_BUS_ISA;
+		cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
  	} else
 		return (0);
 
 	bytecnt = 8;
-	cs->hw.sedl.cfg_reg = card->para[1];
-	cs->irq = card->para[0];
-	if (cs->subtyp == SEDL_SPEED_STAR) {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_ISAC;
-		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_HSCX;
-		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
-		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_PCMCIA_RESET;
+	if (card->para[1]) {
+		cs->hw.sedl.cfg_reg = card->para[1];
+		cs->irq = card->para[0];
+		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+			bytecnt = 16;
+		}
 	} else {
-		cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ADR;
-		cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAC;
-		cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX;
-		cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_RESET_ON;
-		cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_RESET_OFF;
-	}
-        
-	/* In case of the sedlbauer pcmcia card, this region is in use,
+/* Probe for Sedlbauer speed pci */
+#if SEDLBAUER_PCI
+#if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+		if (!pci_present()) {
+			printk(KERN_ERR "FritzPCI: no PCI bus present\n");
+			return(0);
+		}
+		if ((dev_sedl = pci_find_device(PCI_VENDOR_SEDLBAUER,
+				PCI_SPEEDPCI_ID, dev_sedl))) {
+			cs->irq = dev_sedl->irq;
+			if (!cs->irq) {
+				printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+				return(0);
+			}
+			cs->hw.sedl.cfg_reg = dev_sedl->base_address[0] &
+				PCI_BASE_ADDRESS_IO_MASK; 
+		} else {
+			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+			return(0);
+		}
+#else
+		for (; pci_index < 255; pci_index++) {
+			unsigned char pci_bus, pci_device_fn;
+			unsigned int ioaddr;
+			unsigned char irq;
+
+			if (pcibios_find_device (PCI_VENDOR_SEDLBAUER,
+						PCI_SPEEDPCI_ID, pci_index,
+						&pci_bus, &pci_device_fn) != 0) {
+				continue;
+			}
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+					PCI_INTERRUPT_LINE, &irq);
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+					PCI_BASE_ADDRESS_0, &ioaddr);
+			cs->irq = irq;
+			cs->hw.sedl.cfg_reg = ioaddr & PCI_BASE_ADDRESS_IO_MASK; 
+			if (!cs->hw.sedl.cfg_reg) {
+				printk(KERN_WARNING "Sedlbauer: No IO-Adr for PCI card found\n");
+				return(0);
+			}
+			break;
+		}	
+		if (pci_index == 255) {
+			printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+			return(0);
+		}
+		pci_index++;
+#endif /* COMPAT_HAS_NEW_PCI */
+		 cs->irq_flags |= SA_SHIRQ;
+		cs->hw.sedl.bus = SEDL_BUS_PCI;
+		cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		cs->subtyp = SEDL_SPEED_PCI;
+		bytecnt = 256;
+		byteout(cs->hw.sedl.cfg_reg, 0xff);
+		byteout(cs->hw.sedl.cfg_reg, 0x00);
+		byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+		byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
+#else
+		printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n");
+		return (0);
+#endif /* CONFIG_PCI */
+#endif /* SEDLBAUER_PCI */
+	}	
+	
+       	/* In case of the sedlbauer pcmcia card, this region is in use,
            reserved for us by the card manager. So we do not check it
            here, it would fail. */
-	if (cs->typ != ISDN_CTYPE_SEDLBAUER_PCMCIA &&
-	   check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
+	if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA &&
+		check_region((cs->hw.sedl.cfg_reg), bytecnt)) {
 		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.sedl.cfg_reg,
-		       cs->hw.sedl.cfg_reg + bytecnt);
-		return (0);
+			"HiSax: %s config port %x-%x already in use\n",
+			CardType[card->typ],
+			cs->hw.sedl.cfg_reg,
+			cs->hw.sedl.cfg_reg + bytecnt);
+			return (0);
 	} else {
 		request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn");
 	}
 
 	printk(KERN_INFO
-	       "Sedlbauer: defined at 0x%x IRQ %d\n",
+	       "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n",
 	       cs->hw.sedl.cfg_reg,
+	       cs->hw.sedl.cfg_reg + bytecnt,
 	       cs->irq);
-	printk(KERN_WARNING
-		       "Sedlbauer %s uses ports 0x%x-0x%x\n",
-		       Sedlbauer_Types[cs->subtyp],
-		       cs->hw.sedl.cfg_reg,
-		       cs->hw.sedl.cfg_reg + bytecnt);
 
-	printk(KERN_INFO "Sedlbauer: resetting card\n");
-	reset_sedlbauer(cs);
-	cs->readisac = &ReadISAC;
-	cs->writeisac = &WriteISAC;
-	cs->readisacfifo = &ReadISACfifo;
-	cs->writeisacfifo = &WriteISACfifo;
 	cs->BC_Read_Reg = &ReadHSCX;
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Sedl_card_msg;
-	ISACVersion(cs, "Sedlbauer:");
-	if (HscxVersion(cs, "Sedlbauer:")) {
-		printk(KERN_WARNING
-		    "Sedlbauer: wrong HSCX versions check IO address\n");
-		release_io_sedlbauer(cs);
-		return (0);
+
+/*
+ * testing ISA and PCMCIA Cards for IPAC, default is ISAC 
+ * do not test for PCI card, because ports are different
+ * and PCI card uses only IPAC (for the moment)
+ */	
+	if (cs->hw.sedl.bus != SEDL_BUS_PCI) {
+		val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR,
+        	        cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID);
+	        if (val == 1) {
+		/* IPAC */
+                	cs->subtyp = SEDL_SPEED_WIN2_PC104;
+			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+				cs->subtyp = SEDL_SPEED_STAR2;
+			}
+			cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+		} else {
+		/* ISAC_HSCX oder ISAC_ISAR */
+			if (cs->hw.sedl.chip == SEDL_CHIP_TEST) {
+				cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX;
+			}
+		}
+	}
+
+/*
+ * hw.sedl.chip is now properly set
+ */
+	printk(KERN_INFO "Sedlbauer: %s detected\n",
+		Sedlbauer_Types[cs->subtyp]);
+
+
+	if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) {
+	/* IPAC */
+		if (cs->hw.sedl.bus == SEDL_BUS_PCI) {
+	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR;
+        	        cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+                	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC;
+		} else {
+	                cs->hw.sedl.adr  = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR;
+        	        cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+                	cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC;
+		}
+                test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+                cs->readisac = &ReadISAC_IPAC;
+                cs->writeisac = &WriteISAC_IPAC;
+                cs->readisacfifo = &ReadISACfifo_IPAC;
+                cs->writeisacfifo = &WriteISACfifo_IPAC;
+                cs->irq_func = &sedlbauer_interrupt_ipac;
+
+		val = readreg(cs->hw.sedl.adr,cs->hw.sedl.isac, IPAC_ID);
+                printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val);
+		reset_sedlbauer(cs);
+	} else {
+	/* ISAC_HSCX oder ISAC_ISAR */
+		cs->readisac = &ReadISAC;
+		cs->writeisac = &WriteISAC;
+		cs->readisacfifo = &ReadISACfifo;
+		cs->writeisacfifo = &WriteISACfifo;
+		if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) {
+			cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR;
+			cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC;
+			cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR;
+			cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON;
+			cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF;
+			cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar;
+			cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar;
+			test_and_set_bit(HW_ISAR, &cs->HW_Flags);
+			cs->irq_func = &sedlbauer_interrupt_isar;
+	
+			ISACVersion(cs, "Sedlbauer:");
+		
+			cs->BC_Read_Reg = &ReadISAR;
+			cs->BC_Write_Reg = &WriteISAR;
+			cs->BC_Send_Data = &isar_fill_fifo;
+			ver = ISARVersion(cs, "Sedlbauer:");
+			if (ver < 0) {
+				printk(KERN_WARNING
+					"Sedlbauer: wrong ISAR version (ret = %d)\n", ver);
+				release_io_sedlbauer(cs);
+				return (0);
+			}
+		} else {
+			if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET;
+			} else {
+				cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR;
+				cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC;
+				cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX;
+				cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON;
+				cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF;
+			}
+			cs->irq_func = &sedlbauer_interrupt;
+			ISACVersion(cs, "Sedlbauer:");
+		
+			if (HscxVersion(cs, "Sedlbauer:")) {
+				printk(KERN_WARNING
+					"Sedlbauer: wrong HSCX versions check IO address\n");
+				release_io_sedlbauer(cs);
+				return (0);
+			}
+			reset_sedlbauer(cs);
+		}
 	}
 	return (1);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/sportster.c linux.pre11.3/drivers/isdn/hisax/sportster.c
--- linux.vanilla/drivers/isdn/hisax/sportster.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/hisax/sportster.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: sportster.c,v 1.5 1998/02/02 13:29:46 keil Exp $
+/* $Id: sportster.c,v 1.9 1999/07/12 21:05:29 keil Exp $
 
  * sportster.c     low level stuff for USR Sportster internal TA
  *
@@ -7,6 +7,19 @@
  * Thanks to Christian "naddy" Weisgerber (3Com, US Robotics) for documentation
  *
  * $Log: sportster.c,v $
+ * Revision 1.9  1999/07/12 21:05:29  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.8  1999/07/01 08:12:10  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.7  1998/11/15 23:55:22  keil
+ * changes from 2.0
+ *
+ * Revision 1.6  1998/04/15 16:44:35  keil
+ * new init code
+ *
  * Revision 1.5  1998/02/02 13:29:46  keil
  * fast io
  *
@@ -30,7 +43,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.5 $";
+const char *sportster_revision = "$Revision: 1.9 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -165,11 +178,11 @@
 	save_flags(flags);
 	sti();
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
 	cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */
 	byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
 
@@ -183,16 +196,11 @@
 		case CARD_RELEASE:
 			release_io_sportster(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &sportster_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 1);
 			cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */
 			byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq);
+			inithscxisac(cs, 2);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -278,6 +286,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Sportster_card_msg;
+	cs->irq_func = &sportster_interrupt;
 	ISACVersion(cs, "Sportster:");
 	if (HscxVersion(cs, "Sportster:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/tei.c linux.pre11.3/drivers/isdn/hisax/tei.c
--- linux.vanilla/drivers/isdn/hisax/tei.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/hisax/tei.c	Mon Jul 19 23:59:34 1999
@@ -1,12 +1,37 @@
-/* $Id: tei.c,v 2.7 1998/02/12 23:08:11 keil Exp $
+/* $Id: tei.c,v 2.12 1999/07/01 08:12:11 keil Exp $
 
- * Author       Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
+ *		This file is (c) under GNU PUBLIC LICENSE
+ *		For changes and modifications please read
+ *		../../../Documentation/isdn/HiSax.cert
+ *
  * Thanks to    Jan den Ouden
  *              Fritz Elfert
  *
  * $Log: tei.c,v $
+ * Revision 2.12  1999/07/01 08:12:11  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.11  1998/11/15 23:55:24  keil
+ * changes from 2.0
+ *
+ * Revision 2.10  1998/05/25 14:08:10  keil
+ * HiSax 3.0
+ * fixed X.75 and leased line to work again
+ * Point2Point and fixed TEI are runtime options now:
+ *    hisaxctrl <id> 7 1  set PTP
+ *    hisaxctrl <id> 8 <TEIVALUE *2 >
+ *    set fixed TEI to TEIVALUE (0-63)
+ *
+ * Revision 2.9  1998/05/25 12:58:23  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.8  1998/03/07 22:57:07  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 2.7  1998/02/12 23:08:11  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -50,7 +75,7 @@
 #include "isdnl2.h"
 #include <linux/random.h>
 
-const char *tei_revision = "$Revision: 2.7 $";
+const char *tei_revision = "$Revision: 2.12 $";
 
 #define ID_REQUEST	1
 #define ID_ASSIGNED	2
@@ -141,6 +166,7 @@
 		printk(KERN_WARNING "HiSax: No skb for TEI manager\n");
 		return;
 	}
+	SET_SKB_FREE(skb);
 	bp = skb_put(skb, 3);
 	bp[0] = (TEI_SAPI << 2);
 	bp[1] = (GROUP_TEI << 1) | 0x1;
@@ -151,26 +177,24 @@
 	bp[2] = ri & 0xff;
 	bp[3] = m_id;
 	bp[4] = (tei << 1) | 1;
-	st->l2.l2l1(st, PH_DATA_REQ, skb);
+	st->l2.l2l1(st, PH_DATA | REQUEST, skb);
 }
 
 static void
 tei_id_request(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	char tmp[64];
 
 	if (st->l2.tei != -1) {
-		sprintf(tmp, "assign request for allready asigned tei %d",
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"assign request for allready asigned tei %d",
 			st->l2.tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
 		return;
 	}
 	st->ma.ri = random_ri();
-	if (st->ma.debug) {
-		sprintf(tmp, "assign request ri %d", st->ma.ri);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"assign request ri %d", st->ma.ri);
 	put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
 	FsmChangeState(&st->ma.tei_m, ST_TEI_IDREQ);
 	FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 1);
@@ -184,26 +208,24 @@
 	struct sk_buff *skb = arg;
 	struct IsdnCardState *cs;
 	int ri, tei;
-	char tmp[64];
 
 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity assign ri %d tei %d", ri, tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity assign ri %d tei %d", ri, tei);
 	if ((ost = findtei(st, tei))) {		/* same tei is in use */
 		if (ri != ost->ma.ri) {
-			sprintf(tmp, "possible duplicate assignment tei %d", tei);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-			ost->l2.l2tei(ost, MDL_ERROR_REQ, NULL);
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"possible duplicate assignment tei %d", tei);
+			ost->l2.l2tei(ost, MDL_ERROR | RESPONSE, NULL);
 		}
 	} else if (ri == st->ma.ri) {
 		FsmDelTimer(&st->ma.t202, 1);
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
-		st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) tei);
+		st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_ASSIGN_REQ, NULL);
+		cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
 	}
 }
 
@@ -213,14 +235,12 @@
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
 	int ri, tei;
-	char tmp[64];
 
 	ri = ((unsigned int) skb->data[1] << 8) + skb->data[2];
 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity denied ri %d tei %d", ri, tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity denied ri %d tei %d", ri, tei);
 }
 
 static void
@@ -229,13 +249,11 @@
 	struct PStack *st = fi->userdata;
 	struct sk_buff *skb = arg;
 	int tei;
-	char tmp[64];
 
 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity check req tei %d", tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity check req tei %d", tei);
 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
 		FsmDelTimer(&st->ma.t202, 4);
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
@@ -250,19 +268,17 @@
 	struct sk_buff *skb = arg;
 	struct IsdnCardState *cs;
 	int tei;
-	char tmp[64];
 
 	tei = skb->data[4] >> 1;
-	if (st->ma.debug) {
-		sprintf(tmp, "identity remove tei %d", tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"identity remove tei %d", tei);
 	if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) {
 		FsmDelTimer(&st->ma.t202, 5);
 		FsmChangeState(&st->ma.tei_m, ST_TEI_NOP);
-		st->ma.manl2(st, MDL_REMOVE_REQ, 0);
+		st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 	}
 }
 
@@ -270,12 +286,10 @@
 tei_id_verify(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	char tmp[64];
 
-	if (st->ma.debug) {
-		sprintf(tmp, "id verify request for tei %d", st->l2.tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-	}
+	if (st->ma.debug)
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"id verify request for tei %d", st->l2.tei);
 	put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
 	FsmChangeState(&st->ma.tei_m, ST_TEI_IDVERIFY);
 	FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 2);
@@ -286,24 +300,21 @@
 tei_id_req_tout(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	char tmp[64];
 	struct IsdnCardState *cs;
 
 	if (--st->ma.N202) {
 		st->ma.ri = random_ri();
-		if (st->ma.debug) {
-			sprintf(tmp, "assign req(%d) ri %d",
-				4 - st->ma.N202, st->ma.ri);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		}
+		if (st->ma.debug)
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"assign req(%d) ri %d", 4 - st->ma.N202,
+				st->ma.ri);
 		put_tei_msg(st, ID_REQUEST, st->ma.ri, 127);
 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3);
 	} else {
-		sprintf(tmp, "assign req failed");
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		st->ma.manl2(st, MDL_ERROR_IND, 0);
+		st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed");
+		st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 		FsmChangeState(fi, ST_TEI_NOP);
 	}
 }
@@ -312,23 +323,21 @@
 tei_id_ver_tout(struct FsmInst *fi, int event, void *arg)
 {
 	struct PStack *st = fi->userdata;
-	char tmp[64];
 	struct IsdnCardState *cs;
 
 	if (--st->ma.N202) {
-		if (st->ma.debug) {
-			sprintf(tmp, "id verify req(%d) for tei %d",
+		if (st->ma.debug)
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"id verify req(%d) for tei %d",
 				3 - st->ma.N202, st->l2.tei);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		}
 		put_tei_msg(st, ID_VERIFY, 0, st->l2.tei);
 		FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 4);
 	} else {
-		sprintf(tmp, "verify req for tei %d failed", st->l2.tei);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		st->ma.manl2(st, MDL_REMOVE_REQ, 0);
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"verify req for tei %d failed", st->l2.tei);
+		st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0);
 		cs = (struct IsdnCardState *) st->l1.hardware;
-		cs->cardmsg(cs, MDL_REMOVE_REQ, NULL);
+		cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL);
 		FsmChangeState(fi, ST_TEI_NOP);
 	}
 }
@@ -338,31 +347,34 @@
 {
 	struct sk_buff *skb = arg;
 	int mt;
-	char tmp[64];
 
-	if (pr == PH_DATA_IND) {
+	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+		idev_kfree_skb(skb, FREE_READ);
+		return;
+	}
+
+	if (pr == (PH_DATA | INDICATION)) {
 		if (skb->len < 3) {
-			sprintf(tmp, "short mgr frame %d/3", skb->len);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-		} else if (((skb->data[0] >> 2) != TEI_SAPI) ||
-			   ((skb->data[1] >> 1) != GROUP_TEI)) {
-			sprintf(tmp, "wrong mgr sapi/tei %x/%x",
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"short mgr frame %ld/3", skb->len);
+		} else if ((skb->data[0] != ((TEI_SAPI << 2) | 2)) ||
+			   (skb->data[1] != ((GROUP_TEI << 1) | 1))) {
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"wrong mgr sapi/tei %x/%x",
 				skb->data[0], skb->data[1]);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
 		} else if ((skb->data[2] & 0xef) != UI) {
-			sprintf(tmp, "mgr frame is not ui %x",
-				skb->data[2]);
-			st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+			st->ma.tei_m.printdebug(&st->ma.tei_m,
+				"mgr frame is not ui %x", skb->data[2]);
 		} else {
 			skb_pull(skb, 3);
 			if (skb->len < 5) {
-				sprintf(tmp, "short mgr frame %d/5", skb->len);
-				st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+				st->ma.tei_m.printdebug(&st->ma.tei_m,
+					"short mgr frame %ld/5", skb->len);
 			} else if (skb->data[0] != TEI_ENTITY_ID) {
 				/* wrong management entity identifier, ignore */
-				sprintf(tmp, "tei handler wrong entity id %x\n",
+				st->ma.tei_m.printdebug(&st->ma.tei_m,
+					"tei handler wrong entity id %x",
 					skb->data[0]);
-				st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
 			} else {
 				mt = skb->data[3];
 				if (mt == ID_ASSIGNED)
@@ -374,36 +386,39 @@
 				else if (mt == ID_REMOVE)
 					FsmEvent(&st->ma.tei_m, EV_REMOVE, skb);
 				else {
-					sprintf(tmp, "tei handler wrong mt %x\n",
-						mt);
-					st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+					st->ma.tei_m.printdebug(&st->ma.tei_m,
+						"tei handler wrong mt %x\n", mt);
 				}
 			}
 		}
 	} else {
-		sprintf(tmp, "tei handler wrong pr %x\n", pr);
-		st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
+		st->ma.tei_m.printdebug(&st->ma.tei_m,
+			"tei handler wrong pr %x\n", pr);
 	}
-	dev_kfree_skb(skb);
+	idev_kfree_skb(skb, FREE_READ);
 }
 
 static void
 tei_l2tei(struct PStack *st, int pr, void *arg)
 {
+	struct IsdnCardState *cs;
+
+	if (test_bit(FLG_FIXED_TEI, &st->l2.flag)) {
+		if (pr == (MDL_ASSIGN | INDICATION)) {
+			if (st->ma.debug)
+				st->ma.tei_m.printdebug(&st->ma.tei_m,
+					"fixed assign tei %d", st->l2.tei);
+			st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei);
+			cs = (struct IsdnCardState *) st->l1.hardware;
+			cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL);
+		}
+		return;
+	}
 	switch (pr) {
-		case (MDL_ASSIGN_IND):
-#ifdef TEI_FIXED
-			if (st->ma.debug) {
-				char tmp[64];
-				sprintf(tmp, "fixed assign tei %d", TEI_FIXED);
-				st->ma.tei_m.printdebug(&st->ma.tei_m, tmp);
-			}
-			st->ma.manl2(st, MDL_ASSIGN_REQ, (void *) (int) TEI_FIXED);
-#else
+		case (MDL_ASSIGN | INDICATION):
 			FsmEvent(&st->ma.tei_m, EV_IDREQ, arg);
-#endif
 			break;
-		case (MDL_ERROR_REQ):
+		case (MDL_ERROR | REQUEST):
 			FsmEvent(&st->ma.tei_m, EV_VERIFY, arg);
 			break;
 		default:
@@ -412,14 +427,14 @@
 }
 
 static void
-tei_debug(struct FsmInst *fi, char *s)
+tei_debug(struct FsmInst *fi, char *fmt, ...)
 {
+	va_list args;
 	struct PStack *st = fi->userdata;
-	char tm[32], str[256];
 
-	jiftime(tm, jiffies);
-	sprintf(str, "%s Tei %s\n", tm, s);
-	HiSax_putstatus(st->l1.hardware, str);
+	va_start(args, fmt);
+	VHiSax_putstatus(st->l1.hardware, "tei ", fmt, args);
+	va_end(args);
 }
 
 void
@@ -439,9 +454,8 @@
 }
 
 void
-init_tei(struct IsdnCardState *sp, int protocol)
+init_tei(struct IsdnCardState *cs, int protocol)
 {
-
 }
 
 void
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teleint.c linux.pre11.3/drivers/isdn/hisax/teleint.c
--- linux.vanilla/drivers/isdn/hisax/teleint.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/hisax/teleint.c	Mon Jul 19 23:59:34 1999
@@ -1,11 +1,24 @@
-/* $Id: teleint.c,v 1.5 1998/02/02 13:40:47 keil Exp $
+/* $Id: teleint.c,v 1.9 1999/07/12 21:05:30 keil Exp $
 
  * teleint.c     low level stuff for TeleInt isdn cards
  *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
+ * Author     Karsten Keil (keil@isdn4linux.de)
  *
  *
  * $Log: teleint.c,v $
+ * Revision 1.9  1999/07/12 21:05:30  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 1.8  1999/07/01 08:12:12  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 1.7  1998/11/15 23:55:26  keil
+ * changes from 2.0
+ *
+ * Revision 1.6  1998/04/15 16:45:31  keil
+ * new init code
+ *
  * Revision 1.5  1998/02/02 13:40:47  keil
  * fast io
  *
@@ -32,7 +45,7 @@
 
 extern const char *CardType[];
 
-const char *TeleInt_revision = "$Revision: 1.5 $";
+const char *TeleInt_revision = "$Revision: 1.9 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -64,17 +77,20 @@
 readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
 	register u_char ret;
-	int max_delay = 2000;
+	register int max_delay = 20000;
+	register int i;
+	
 	byteout(ale, off);
-
-	ret = HFC_BUSY & bytein(ale);
-	while (ret && --max_delay)
+	for (i = 0; i<size; i++) {
 		ret = HFC_BUSY & bytein(ale);
-	if (!max_delay) {
-		printk(KERN_WARNING "TeleInt Busy not inaktive\n");
-		return;
+		while (ret && --max_delay)
+			ret = HFC_BUSY & bytein(ale);
+		if (!max_delay) {
+			printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+			return;
+		}
+		data[i] = bytein(adr);
 	}
-	insb(adr, data, size);
 }
 
 
@@ -104,18 +120,21 @@
 writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
 {
 	register u_char ret;
-	int max_delay = 2000;
-
+	register int max_delay = 20000;
+	register int i;
+	
 	/* fifo write without cli because it's allready done  */
 	byteout(ale, off);
-	ret = HFC_BUSY & bytein(ale);
-	while (ret && --max_delay)
+	for (i = 0; i<size; i++) {
 		ret = HFC_BUSY & bytein(ale);
-	if (!max_delay) {
-		printk(KERN_WARNING "TeleInt Busy not inaktive\n");
-		return;
+		while (ret && --max_delay)
+			ret = HFC_BUSY & bytein(ale);
+		if (!max_delay) {
+			printk(KERN_WARNING "TeleInt Busy not inaktive\n");
+			return;
+		}
+		byteout(adr, data[i]);
 	}
-	outsb(adr, data, size);
 }
 
 /* Interface functions */
@@ -157,11 +176,8 @@
 		cs->hw.hfc.cip = reg;
 		byteout(cs->hw.hfc.addr | 1, reg);
 		ret = bytein(cs->hw.hfc.addr);
-		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
-			char tmp[32];
-			sprintf(tmp, "hfc RD %02x %02x", reg, ret);
-			debugl1(cs, tmp);
-		}
+		if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+			debugl1(cs, "hfc RD %02x %02x", reg, ret);
 	} else
 		ret = bytein(cs->hw.hfc.addr | 1);
 	return (ret);
@@ -174,18 +190,15 @@
 	cs->hw.hfc.cip = reg;
 	if (data)
 		byteout(cs->hw.hfc.addr, value);
-	if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2)) {
-		char tmp[32];
-		sprintf(tmp, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
-		debugl1(cs, tmp);
-	}
+	if (cs->debug & L1_DEB_HSCX_FIFO && (data != 2))
+		debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value);
 }
 
 static void
 TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 
 	if (!cs) {
 		printk(KERN_WARNING "TeleInt: Spurious interrupt!\n");
@@ -193,20 +206,16 @@
 	}
 	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA);
 	if (val) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 2) {
-		writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
-		writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF);
+	writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0);
 }
 
 static void
@@ -246,11 +255,11 @@
 	save_flags(flags);
 	sti();
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(3);
+	schedule_timeout((30*HZ)/1000);
 	cs->hw.hfc.cirm &= ~HFC_RESET;
 	byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm);	/* Reset Off */
 	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
+	schedule_timeout((10*HZ)/1000);
 	restore_flags(flags);
 }
 
@@ -264,13 +273,13 @@
 		case CARD_RELEASE:
 			release_io_TeleInt(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &TeleInt_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
 			inithfc(cs);
 			clear_pending_isac_ints(cs);
 			initisac(cs);
+			/* Reenable all IRQ */
+			cs->writeisac(cs, ISAC_MASK, 0);
+			cs->writeisac(cs, ISAC_CMDR, 0x41);
 			cs->hw.hfc.timer.expires = jiffies + 1;
 			add_timer(&cs->hw.hfc.timer);
 			return(0);
@@ -356,6 +365,7 @@
 	cs->BC_Read_Reg = &ReadHFC;
 	cs->BC_Write_Reg = &WriteHFC;
 	cs->cardmsg = &TeleInt_card_msg;
+	cs->irq_func = &TeleInt_interrupt;
 	ISACVersion(cs, "TeleInt:");
 	return (1);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teles0.c linux.pre11.3/drivers/isdn/hisax/teles0.c
--- linux.vanilla/drivers/isdn/hisax/teles0.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/teles0.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: teles0.c,v 2.6 1998/02/03 23:27:47 keil Exp $
+/* $Id: teles0.c,v 2.9 1999/07/12 21:05:31 keil Exp $
 
  * teles0.c     low level stuff for Teles Memory IO isdn cards
  *              based on the teles driver from Jan den Ouden
@@ -10,6 +10,16 @@
  *              Beat Doebeli
  *
  * $Log: teles0.c,v $
+ * Revision 2.9  1999/07/12 21:05:31  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.8  1998/04/15 16:44:28  keil
+ * new init code
+ *
+ * Revision 2.7  1998/03/07 22:57:08  tsbogend
+ * made HiSax working on Linux/Alpha
+ *
  * Revision 2.6  1998/02/03 23:27:47  keil
  * IRQ 9
  *
@@ -48,7 +58,7 @@
 
 extern const char *CardType[];
 
-const char *teles0_revision = "$Revision: 2.6 $";
+const char *teles0_revision = "$Revision: 2.9 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -62,7 +72,7 @@
 static inline void
 writeisac(unsigned int adr, u_char off, u_char data)
 {
-	writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off);
+	writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb();
 }
 
 
@@ -77,14 +87,14 @@
 writehscx(unsigned int adr, int hscx, u_char off, u_char data)
 {
 	writeb(data, adr + (hscx ? 0x1c0 : 0x180) +
-	       ((off & 1) ? 0x1ff : 0) + off);
+	       ((off & 1) ? 0x1ff : 0) + off); mb();
 }
 
 static inline void
 read_fifo_isac(unsigned int adr, u_char * data, int size)
 {
 	register int i;
-	register u_char *ad = (u_char *) (adr + 0x100);
+	register u_char *ad = (u_char *) ((long)adr + 0x100);
 	for (i = 0; i < size; i++)
 		data[i] = readb(ad);
 }
@@ -93,16 +103,17 @@
 write_fifo_isac(unsigned int adr, u_char * data, int size)
 {
 	register int i;
-	register u_char *ad = (u_char *) (adr + 0x100);
-	for (i = 0; i < size; i++)
-		writeb(data[i], ad);
+	register u_char *ad = (u_char *) ((long)adr + 0x100);
+	for (i = 0; i < size; i++) {
+		writeb(data[i], ad); mb();
+	}
 }
 
 static inline void
 read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
 {
 	register int i;
-	register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
+	register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
 	for (i = 0; i < size; i++)
 		data[i] = readb(ad);
 }
@@ -111,9 +122,10 @@
 write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
 {
 	int i;
-	register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180));
-	for (i = 0; i < size; i++)
-		writeb(data[i], ad);
+	register u_char *ad = (u_char *) ((long)adr + (hscx ? 0x1c0 : 0x180));
+	for (i = 0; i < size; i++) {
+		writeb(data[i], ad); mb();
+	}
 }
 
 /* Interface functions */
@@ -169,7 +181,7 @@
 teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 	int count = 0;
 
 	if (!cs) {
@@ -178,39 +190,31 @@
 	}
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	count++;
 	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
-	if (val && count < 20) {
+	if (val && count < 5) {
 		if (cs->debug & L1_DEB_HSCX)
 			debugl1(cs, "HSCX IntStat after IntRoutine");
 		goto Start_HSCX;
 	}
 	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
-	if (val && count < 20) {
+	if (val && count < 5) {
 		if (cs->debug & L1_DEB_ISAC)
 			debugl1(cs, "ISAC IntStat after IntRoutine");
 		goto Start_ISAC;
 	}
-	if (stat & 1) {
-		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
-		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
-		writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
-		writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
-		writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
-	}
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
 }
 
 void
@@ -264,9 +268,9 @@
 		byteout(cs->hw.teles0.cfg_reg + 4, cfval | 1);
 		HZDELAY(HZ / 10 + 1);
 	}
-	writeb(0, cs->hw.teles0.membase + 0x80);
+	writeb(0, cs->hw.teles0.membase + 0x80); mb();
 	HZDELAY(HZ / 5 + 1);
-	writeb(1, cs->hw.teles0.membase + 0x80);
+	writeb(1, cs->hw.teles0.membase + 0x80); mb();
 	HZDELAY(HZ / 5 + 1);
 	restore_flags(flags);
 	return(0);
@@ -282,14 +286,8 @@
 		case CARD_RELEASE:
 			release_io_teles0(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &teles0_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -377,6 +375,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Teles_card_msg;
+	cs->irq_func = &teles0_interrupt;
 	ISACVersion(cs, "Teles0:");
 	if (HscxVersion(cs, "Teles0:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teles3.c linux.pre11.3/drivers/isdn/hisax/teles3.c
--- linux.vanilla/drivers/isdn/hisax/teles3.c	Sun Nov  8 15:08:09 1998
+++ linux.pre11.3/drivers/isdn/hisax/teles3.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.7 1998/02/02 13:29:48 keil Exp $
+/* $Id: teles3.c,v 2.12 1999/07/12 21:05:32 keil Exp $
 
  * teles3.c     low level stuff for Teles 16.3 & PNP isdn cards
  *
@@ -11,6 +11,22 @@
  *              Beat Doebeli
  *
  * $Log: teles3.c,v $
+ * Revision 2.12  1999/07/12 21:05:32  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.11  1999/07/01 08:12:14  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.10  1999/02/15 14:37:15  cpetig
+ * oops, missed something in last commit
+ *
+ * Revision 2.9  1999/02/15 14:11:02  cpetig
+ * fixed a bug with Teles PCMCIA, it doesn't have a config register
+ *
+ * Revision 2.8  1998/04/15 16:44:30  keil
+ * new init code
+ *
  * Revision 2.7  1998/02/02 13:29:48  keil
  * fast io
  *
@@ -69,7 +85,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.7 $";
+const char *teles3_revision = "$Revision: 2.12 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -151,9 +167,9 @@
 static void
 teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
-#define MAXCOUNT 20
+#define MAXCOUNT 5
 	struct IsdnCardState *cs = dev_id;
-	u_char val, stat = 0;
+	u_char val;
 	int count = 0;
 
 	if (!cs) {
@@ -162,16 +178,12 @@
 	}
 	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
       Start_HSCX:
-	if (val) {
+	if (val)
 		hscx_int_main(cs, val);
-		stat |= 1;
-	}
 	val = readreg(cs->hw.teles3.isac, ISAC_ISTA);
       Start_ISAC:
-	if (val) {
+	if (val)
 		isac_interrupt(cs, val);
-		stat |= 2;
-	}
 	count++;
 	val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA);
 	if (val && count < MAXCOUNT) {
@@ -187,16 +199,12 @@
 	}
 	if (count >= MAXCOUNT)
 		printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count);
-	if (stat & 1) {
-		writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
-		writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
-		writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
-		writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
-	}
-	if (stat & 2) {
-		writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
-		writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
-	}
+	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF);
+	writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF);
+	writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0);
+	writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0);
+	writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0);
 }
 
 inline static void
@@ -213,9 +221,9 @@
 void
 release_io_teles3(struct IsdnCardState *cs)
 {
-	if (cs->typ == ISDN_CTYPE_TELESPCMCIA)
-		release_region(cs->hw.teles3.cfg_reg, 97);
-	else {
+	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
+		release_region(cs->hw.teles3.hscx[0], 97);
+	} else {
 		if (cs->hw.teles3.cfg_reg) {
 			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
 				release_region(cs->hw.teles3.cfg_reg, 1);
@@ -301,14 +309,8 @@
 		case CARD_RELEASE:
 			release_io_teles3(cs);
 			return(0);
-		case CARD_SETIRQ:
-			return(request_irq(cs->irq, &teles3_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
 		case CARD_INIT:
-			clear_pending_isac_ints(cs);
-			clear_pending_hscx_ints(cs);
-			initisac(cs);
-			inithscx(cs);
+			inithscxisac(cs, 3);
 			return(0);
 		case CARD_TEST:
 			return(0);
@@ -342,7 +344,7 @@
 		cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20;
 		cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820;
 	} else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		cs->hw.teles3.cfg_reg = card->para[1];
+		cs->hw.teles3.cfg_reg = 0;
 		cs->hw.teles3.hscx[0] = card->para[1] - 0x20;
 		cs->hw.teles3.hscx[1] = card->para[1];
 		cs->hw.teles3.isac = card->para[1] + 0x20;
@@ -362,12 +364,12 @@
 	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (check_region((cs->hw.teles3.cfg_reg), 97)) {
+		if (check_region((cs->hw.teles3.hscx[0]), 97)) {
 			printk(KERN_WARNING
 			       "HiSax: %s ports %x-%x already in use\n",
 			       CardType[cs->typ],
-			       cs->hw.teles3.cfg_reg,
-			       cs->hw.teles3.cfg_reg + 96);
+			       cs->hw.teles3.hscx[0],
+			       cs->hw.teles3.hscx[0] + 96);
 			return (0);
 		} else
 			request_region(cs->hw.teles3.hscx[0], 97, "HiSax Teles PCMCIA");
@@ -492,6 +494,7 @@
 	cs->BC_Write_Reg = &WriteHSCX;
 	cs->BC_Send_Data = &hscx_fill_fifo;
 	cs->cardmsg = &Teles_card_msg;
+	cs->irq_func = &teles3_interrupt;
 	ISACVersion(cs, "Teles3:");
 	if (HscxVersion(cs, "Teles3:")) {
 		printk(KERN_WARNING
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/teles3c.c linux.pre11.3/drivers/isdn/hisax/teles3c.c
--- linux.vanilla/drivers/isdn/hisax/teles3c.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/hisax/teles3c.c	Mon Jul 19 23:59:34 1999
@@ -1,196 +0,0 @@
-/* $Id: teles3c.c,v 1.2 1998/02/02 13:27:07 keil Exp $
-
- * teles3c.c     low level stuff for teles 16.3c
- *
- * Author     Karsten Keil (keil@temic-ech.spacenet.de)
- *
- *
- * $Log: teles3c.c,v $
- * Revision 1.2  1998/02/02 13:27:07  keil
- * New
- *
- *
- *
- */
-
-#define __NO_VERSION__
-#include "hisax.h"
-#include "hfc_2bds0.h"
-#include "isdnl1.h"
-
-extern const char *CardType[];
-
-const char *teles163c_revision = "$Revision: 1.2 $";
-
-static void
-t163c_interrupt(int intno, void *dev_id, struct pt_regs *regs)
-{
-	struct IsdnCardState *cs = dev_id;
-	u_char val, stat;
-	char tmp[32];
-
-	if (!cs) {
-		printk(KERN_WARNING "teles3c: Spurious interrupt!\n");
-		return;
-	}
-	if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & 
-		(stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) {
-		val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1);
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "teles3c: stat(%02x) s1(%02x)", stat, val);
-			debugl1(cs, tmp);
-		}
-		hfc2bds0_interrupt(cs, val);
-	} else {
-		if (cs->debug & L1_DEB_ISAC) {
-			sprintf(tmp, "teles3c: irq_no_irq stat(%02x)", stat);
-			debugl1(cs, tmp);
-		}
-	}
-}
-
-static void
-t163c_Timer(struct IsdnCardState *cs)
-{
-	cs->hw.hfcD.timer.expires = jiffies + 75;
-	/* WD RESET */
-/*	WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt | 0x80);
-	add_timer(&cs->hw.hfcD.timer);
-*/
-}
-
-void
-release_io_t163c(struct IsdnCardState *cs)
-{
-	release2bds0(cs);
-	del_timer(&cs->hw.hfcD.timer);
-	if (cs->hw.hfcD.addr)
-		release_region(cs->hw.hfcD.addr, 2);
-}
-
-static void
-reset_t163c(struct IsdnCardState *cs)
-{
-	long flags;
-
-	printk(KERN_INFO "teles3c: resetting card\n");
-	cs->hw.hfcD.cirm = HFCD_RESET | HFCD_MEM8K;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset On */
-	save_flags(flags);
-	sti();
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(3);
-	cs->hw.hfcD.cirm = HFCD_MEM8K;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* Reset Off */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(1);
-	cs->hw.hfcD.cirm |= HFCD_INTB;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm);	/* INT B */
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e);
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */
-	cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt);
-	cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE;
-	cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS |
-		HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC |
-		HFCD_INTS_DREC | HFCD_INTS_L1STATE;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1);
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2);
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */
-	udelay(10);
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */
-	cs->hw.hfcD.mst_m = 0;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, HFCD_MASTER); /* HFC Master */
-	cs->hw.hfcD.sctrl = 0;
-	cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl);
-	restore_flags(flags);
-}
-
-static int
-t163c_card_msg(struct IsdnCardState *cs, int mt, void *arg)
-{
-	long flags;
-	char tmp[32];
-
-	if (cs->debug & L1_DEB_ISAC) {
-		
-		sprintf(tmp, "teles3c: card_msg %x", mt);
-		debugl1(cs, tmp);
-	}
-	switch (mt) {
-		case CARD_RESET:
-			reset_t163c(cs);
-			return(0);
-		case CARD_RELEASE:
-			release_io_t163c(cs);
-			return(0);
-		case CARD_SETIRQ:
-			cs->hw.hfcD.timer.expires = jiffies + 75;
-			add_timer(&cs->hw.hfcD.timer);
-			return(request_irq(cs->irq, &t163c_interrupt,
-					I4L_IRQ_FLAG, "HiSax", cs));
-		case CARD_INIT:
-			init2bds0(cs);
-			save_flags(flags);
-			sti();
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout((80*HZ)/1000);
-			cs->hw.hfcD.ctmt |= HFCD_TIM800;
-			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); 
-			cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
-			restore_flags(flags);
-			return(0);
-		case CARD_TEST:
-			return(0);
-	}
-	return(0);
-}
-
-__initfunc(int
-setup_t163c(struct IsdnCard *card))
-{
-	struct IsdnCardState *cs = card->cs;
-	char tmp[64];
-
-	strcpy(tmp, teles163c_revision);
-	printk(KERN_INFO "HiSax: Teles 16.3c driver Rev. %s\n", HiSax_getrev(tmp));
-	if (cs->typ != ISDN_CTYPE_TELES3C)
-		return (0);
-	cs->debug = 0xff;
-	cs->hw.hfcD.addr = card->para[1] & 0xfffe;
-	cs->irq = card->para[0];
-	cs->hw.hfcD.cip = 0;
-	cs->hw.hfcD.int_s1 = 0;
-	cs->hw.hfcD.send = NULL;
-	cs->bcs[0].hw.hfc.send = NULL;
-	cs->bcs[1].hw.hfc.send = NULL;
-	cs->hw.hfcD.bfifosize = 1024 + 512;
-	cs->hw.hfcD.dfifosize = 512;
-	cs->ph_state = 0;
-	cs->hw.hfcD.fifo = 255;
-	if (check_region((cs->hw.hfcD.addr), 2)) {
-		printk(KERN_WARNING
-		       "HiSax: %s config port %x-%x already in use\n",
-		       CardType[card->typ],
-		       cs->hw.hfcD.addr,
-		       cs->hw.hfcD.addr + 2);
-		return (0);
-	} else {
-		request_region(cs->hw.hfcD.addr, 2, "teles3c isdn");
-	}
-	/* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */
-	outb(0x00, cs->hw.hfcD.addr);
-	outb(0x56, cs->hw.hfcD.addr | 1);
-	printk(KERN_INFO
-	       "teles3c: defined at 0x%x IRQ %d HZ %d\n",
-	       cs->hw.hfcD.addr,
-	       cs->irq, HZ);
-
-	set_cs_func(cs);
-	cs->hw.hfcD.timer.function = (void *) t163c_Timer;
-	cs->hw.hfcD.timer.data = (long) cs;
-	init_timer(&cs->hw.hfcD.timer);
-	reset_t163c(cs);
-	cs->cardmsg = &t163c_card_msg;
-	return (1);
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/hisax/telespci.c linux.pre11.3/drivers/isdn/hisax/telespci.c
--- linux.vanilla/drivers/isdn/hisax/telespci.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/hisax/telespci.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,406 @@
+/* $Id: telespci.c,v 2.7 1999/07/12 21:05:34 keil Exp $
+
+ * telespci.c     low level stuff for Teles PCI isdn cards
+ *
+ * Author       Ton van Rosmalen 
+ *              Karsten Keil (keil@temic-ech.spacenet.de)
+ *
+ *
+ * $Log: telespci.c,v $
+ * Revision 2.7  1999/07/12 21:05:34  keil
+ * fix race in IRQ handling
+ * added watchdog for lost IRQs
+ *
+ * Revision 2.6  1999/07/01 08:12:15  keil
+ * Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
+ *
+ * Revision 2.5  1998/11/15 23:55:28  keil
+ * changes from 2.0
+ *
+ * Revision 2.4  1998/10/05 09:38:08  keil
+ * Fix register addressing
+ *
+ * Revision 2.3  1998/05/25 12:58:26  keil
+ * HiSax golden code from certification, Don't use !!!
+ * No leased lines, no X75, but many changes.
+ *
+ * Revision 2.1  1998/04/15 16:38:23  keil
+ * Add S0Box and Teles PCI support
+ *
+ *
+ */
+#define __NO_VERSION__
+#include <linux/config.h>
+#include "hisax.h"
+#include "isac.h"
+#include "hscx.h"
+#include "isdnl1.h"
+#include <linux/pci.h>
+#ifndef COMPAT_HAS_NEW_PCI
+#include <linux/bios32.h>
+#endif
+
+extern const char *CardType[];
+const char *telespci_revision = "$Revision: 2.7 $";
+
+#define ZORAN_PO_RQ_PEN	0x02000000
+#define ZORAN_PO_WR	0x00800000
+#define ZORAN_PO_GID0	0x00000000
+#define ZORAN_PO_GID1	0x00100000
+#define ZORAN_PO_GREG0	0x00000000
+#define ZORAN_PO_GREG1	0x00010000
+#define ZORAN_PO_DMASK	0xFF
+
+#define WRITE_ADDR_ISAC	(ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0)
+#define READ_DATA_ISAC	(ZORAN_PO_GID0 | ZORAN_PO_GREG1)
+#define WRITE_DATA_ISAC	(ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1)
+#define WRITE_ADDR_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG0)
+#define READ_DATA_HSCX	(ZORAN_PO_GID1 | ZORAN_PO_GREG1)
+#define WRITE_DATA_HSCX	(ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1)
+
+#define ZORAN_WAIT_NOBUSY	do { \
+					portdata = readl(adr + 0x200); \
+				} while (portdata & ZORAN_PO_RQ_PEN)
+
+static inline u_char
+readisac(unsigned int adr, u_char off)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	
+	/* set address for ISAC */
+	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	
+	/* read data from ISAC */
+	writel(READ_DATA_ISAC, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	return((u_char)(portdata & ZORAN_PO_DMASK));
+}
+
+static inline void
+writeisac(unsigned int adr, u_char off, u_char data)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	
+	/* set address for ISAC */
+	writel(WRITE_ADDR_ISAC | off, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+
+	/* write data to ISAC */
+	writel(WRITE_DATA_ISAC | data, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+}
+
+static inline u_char
+readhscx(unsigned int adr, int hscx, u_char off)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	/* set address for HSCX */
+	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	
+	/* read data from HSCX */
+	writel(READ_DATA_HSCX, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+	return ((u_char)(portdata & ZORAN_PO_DMASK));
+}
+
+static inline void
+writehscx(unsigned int adr, int hscx, u_char off, u_char data)
+{
+	register unsigned int portdata;
+
+	ZORAN_WAIT_NOBUSY;
+	/* set address for HSCX */
+	writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+
+	/* write data to HSCX */
+	writel(WRITE_DATA_HSCX | data, adr + 0x200);
+	ZORAN_WAIT_NOBUSY;
+}
+
+static inline void
+read_fifo_isac(unsigned int adr, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* read data from ISAC */
+	for (i = 0; i < size; i++) {
+		/* set address for ISAC fifo */
+		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(READ_DATA_ISAC, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		data[i] = (u_char)(portdata & ZORAN_PO_DMASK);
+	}
+}
+
+static void
+write_fifo_isac(unsigned int adr, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* write data to ISAC */
+	for (i = 0; i < size; i++) {
+		/* set address for ISAC fifo */
+		writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(WRITE_DATA_ISAC | data[i], adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+	}
+}
+
+static inline void
+read_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
+{
+	register unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* read data from HSCX */
+	for (i = 0; i < size; i++) {
+		/* set address for HSCX fifo */
+		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(READ_DATA_HSCX, adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		data[i] = (u_char) (portdata & ZORAN_PO_DMASK);
+	}
+}
+
+static inline void
+write_fifo_hscx(unsigned int adr, int hscx, u_char * data, int size)
+{
+	unsigned int portdata;
+	register int i;
+
+	ZORAN_WAIT_NOBUSY;
+	/* write data to HSCX */
+	for (i = 0; i < size; i++) {
+		/* set address for HSCX fifo */
+		writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		writel(WRITE_DATA_HSCX | data[i], adr + 0x200);
+		ZORAN_WAIT_NOBUSY;
+		udelay(10);
+	}
+}
+
+/* Interface functions */
+
+static u_char
+ReadISAC(struct IsdnCardState *cs, u_char offset)
+{
+	return (readisac(cs->hw.teles0.membase, offset));
+}
+
+static void
+WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
+{
+	writeisac(cs->hw.teles0.membase, offset, value);
+}
+
+static void
+ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	read_fifo_isac(cs->hw.teles0.membase, data, size);
+}
+
+static void
+WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
+{
+	write_fifo_isac(cs->hw.teles0.membase, data, size);
+}
+
+static u_char
+ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset)
+{
+	return (readhscx(cs->hw.teles0.membase, hscx, offset));
+}
+
+static void
+WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+{
+	writehscx(cs->hw.teles0.membase, hscx, offset, value);
+}
+
+/*
+ * fast interrupt HSCX stuff goes here
+ */
+
+#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg)
+#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data)
+#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt)
+
+#include "hscx_irq.c"
+
+static void
+telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+#define MAXCOUNT 20
+	struct IsdnCardState *cs = dev_id;
+	u_char val;
+
+	if (!cs) {
+		printk(KERN_WARNING "TelesPCI: Spurious interrupt!\n");
+		return;
+	}
+	val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA);
+	if (val)
+		hscx_int_main(cs, val);
+	val = readisac(cs->hw.teles0.membase, ISAC_ISTA);
+	if (val)
+		isac_interrupt(cs, val);
+	/* Clear interrupt register for Zoran PCI controller */
+	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
+
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF);
+	writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0);
+	writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0);
+}
+
+void
+release_io_telespci(struct IsdnCardState *cs)
+{
+	iounmap((void *)cs->hw.teles0.membase);
+}
+
+static int
+TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg)
+{
+	switch (mt) {
+		case CARD_RESET:
+			return(0);
+		case CARD_RELEASE:
+			release_io_telespci(cs);
+			return(0);
+		case CARD_INIT:
+			inithscxisac(cs, 3);
+			return(0);
+		case CARD_TEST:
+			return(0);
+	}
+	return(0);
+}
+
+#ifdef COMPAT_HAS_NEW_PCI
+static 	struct pci_dev *dev_tel __initdata = NULL;
+#else
+static 	int pci_index __initdata = 0;
+#endif
+
+__initfunc(int
+setup_telespci(struct IsdnCard *card))
+{
+	struct IsdnCardState *cs = card->cs;
+	char tmp[64];
+#ifndef COMPAT_HAS_NEW_PCI
+	u_char pci_bus, pci_device_fn, pci_irq;
+	u_int pci_memaddr;
+	u_char found = 0;
+#endif
+
+	strcpy(tmp, telespci_revision);
+	printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp));
+	if (cs->typ != ISDN_CTYPE_TELESPCI)
+		return (0);
+#if CONFIG_PCI
+#ifdef COMPAT_HAS_NEW_PCI
+	if (!pci_present()) {
+		printk(KERN_ERR "TelesPCI: no PCI bus present\n");
+		return(0);
+	}
+	if ((dev_tel = pci_find_device (0x11DE, 0x6120, dev_tel))) {
+		cs->irq = dev_tel->irq;
+		if (!cs->irq) {
+			printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
+			return(0);
+		}
+		cs->hw.teles0.membase = (u_int) ioremap(dev_tel->base_address[0],
+			PAGE_SIZE);
+		printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
+			dev_tel->base_address[0], dev_tel->irq);
+	} else {
+		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
+		return(0);
+	}
+#else
+	for (; pci_index < 0xff; pci_index++) {
+		if (pcibios_find_device (0x11DE, 0x6120,
+			pci_index, &pci_bus, &pci_device_fn)
+			== PCIBIOS_SUCCESSFUL) {
+			found = 1;
+		} else {
+			break;
+		}
+		pcibios_read_config_dword(pci_bus, pci_device_fn,
+				PCI_BASE_ADDRESS_0, &pci_memaddr);
+		pcibios_read_config_byte(pci_bus, pci_device_fn,
+				PCI_INTERRUPT_LINE, &pci_irq);
+
+		printk(KERN_INFO "Found: Zoran, base-address: 0x%x,"
+			" irq: 0x%x\n", pci_memaddr, pci_irq);
+		break;
+	}
+	if (!found) {
+		printk(KERN_WARNING "TelesPCI: No PCI card found\n");
+		return(0);
+	}
+	pci_index++;
+	cs->irq = pci_irq;
+	cs->hw.teles0.membase = (u_int) vremap(pci_memaddr, PAGE_SIZE);
+#endif /* COMPAT_HAS_NEW_PCI */
+#else
+	printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n");
+	printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n");
+	return (0);
+#endif /* CONFIG_PCI */
+
+	/* Initialize Zoran PCI controller */
+	writel(0x00000000, cs->hw.teles0.membase + 0x28);
+	writel(0x01000000, cs->hw.teles0.membase + 0x28);
+	writel(0x01000000, cs->hw.teles0.membase + 0x28);
+	writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C);
+	writel(0x70000000, cs->hw.teles0.membase + 0x3C);
+	writel(0x61000000, cs->hw.teles0.membase + 0x40);
+	/* writel(0x00800000, cs->hw.teles0.membase + 0x200); */
+
+	printk(KERN_INFO
+	       "HiSax: %s config irq:%d mem:%x\n",
+	       CardType[cs->typ], cs->irq,
+	       cs->hw.teles0.membase);
+
+	cs->readisac = &ReadISAC;
+	cs->writeisac = &WriteISAC;
+	cs->readisacfifo = &ReadISACfifo;
+	cs->writeisacfifo = &WriteISACfifo;
+	cs->BC_Read_Reg = &ReadHSCX;
+	cs->BC_Write_Reg = &WriteHSCX;
+	cs->BC_Send_Data = &hscx_fill_fifo;
+	cs->cardmsg = &TelesPCI_card_msg;
+	cs->irq_func = &telespci_interrupt;
+	cs->irq_flags |= SA_SHIRQ;
+	ISACVersion(cs, "TelesPCI:");
+	if (HscxVersion(cs, "TelesPCI:")) {
+		printk(KERN_WARNING
+		 "TelesPCI: wrong HSCX versions check IO/MEM addresses\n");
+		release_io_telespci(cs);
+		return (0);
+	}
+	return (1);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/icn/icn.c linux.pre11.3/drivers/isdn/icn/icn.c
--- linux.vanilla/drivers/isdn/icn/icn.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/icn/icn.c	Mon Jul 19 23:59:34 1999
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.49 1998/02/13 11:14:15 keil Exp $
+/* $Id: icn.c,v 1.57 1999/07/06 16:15:30 detabc Exp $
 
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,29 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: icn.c,v $
+ * Revision 1.57  1999/07/06 16:15:30  detabc
+ * remove unused messages
+ *
+ * Revision 1.56  1999/04/12 13:15:07  fritz
+ * Fixed a cast.
+ *
+ * Revision 1.55  1999/04/12 12:34:02  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.54  1999/01/05 18:29:39  he
+ * merged remaining schedule_timeout() changes from 2.1.127
+ *
+ * Revision 1.53  1998/06/17 19:51:28  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.52  1998/05/20 19:29:58  tsbogend
+ * fixed bug introduced by changes for new BSENT callback
+ *
+ * Revision 1.51  1998/03/07 22:29:55  fritz
+ * Adapted Detlef's chenges for 2.1.
+ *
  * Revision 1.49  1998/02/13 11:14:15  keil
  * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
  *
@@ -209,7 +232,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.49 $";
+*revision = "$Revision: 1.57 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -232,10 +255,10 @@
 	cli();
 	card->xlen[channel] = 0;
 	card->sndcount[channel] = 0;
-	if (card->xskb[channel]) {
+	if ((skb = card->xskb[channel])) {
 		card->xskb[channel] = NULL;
 		restore_flags(flags);
-		dev_kfree_skb(card->xskb[channel]);
+		dev_kfree_skb(skb);
 	} else
 		restore_flags(flags);
 }
@@ -529,6 +552,11 @@
 					cmd.parm.length = card->xlen[channel];
 					card->interface.statcallb(&cmd);
 				}
+			} else {
+				save_flags(flags);
+				cli();
+				card->xskb[channel] = skb;
+				restore_flags(flags);
 			}
 			card->xmit_lock[channel] = 0;
 			if (!icn_trymaplock_channel(card, mch))
@@ -580,8 +608,11 @@
 {
 	{"BCON_",          ISDN_STAT_BCONN, 1},	/* B-Channel connected        */
 	{"BDIS_",          ISDN_STAT_BHUP,  2},	/* B-Channel disconnected     */
-	{"DCON_",          ISDN_STAT_DCONN, 0},	/* D-Channel connected        */
-	{"DDIS_",          ISDN_STAT_DHUP,  0},	/* D-Channel disconnected     */
+	/*
+	** add d-channel connect and disconnect support to link-level
+	*/
+	{"DCON_",          ISDN_STAT_DCONN, 10},	/* D-Channel connected        */
+	{"DDIS_",          ISDN_STAT_DHUP,  11},	/* D-Channel disconnected     */
 	{"DCAL_I",         ISDN_STAT_ICALL, 3},	/* Incoming call dialup-line  */
 	{"DSCA_I",         ISDN_STAT_ICALL, 3},	/* Incoming call 1TR6-SPV     */
 	{"FCALL",          ISDN_STAT_ICALL, 4},	/* Leased line connection up  */
@@ -630,7 +661,33 @@
 	cmd.driver = card->myid;
 	cmd.arg = channel;
 	switch (action) {
+	case 11:
+			save_flags(flags);
+			cli();
+			icn_free_queue(card,channel);
+			card->rcvidx[channel] = 0;
+
+			if (card->flags & 
+			    ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) {
+				
+				isdn_ctrl ncmd;
+				
+				card->flags &= ~((channel)?
+						 ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE);
+				
+				memset(&ncmd, 0, sizeof(ncmd));
+				
+				ncmd.driver = card->myid;
+				ncmd.arg = channel;
+				ncmd.command = ISDN_STAT_BHUP;
+				restore_flags(flags);
+				card->interface.statcallb(&cmd);
+			} else
+				restore_flags(flags);
+			
+			break;
 		case 1:
+			icn_free_queue(card,channel);
 			card->flags |= (channel) ?
 			    ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE;
 			break;
@@ -1539,7 +1596,7 @@
 						c->parm.num[0] ? "N" : "ALL", c->parm.num);
 				} else
 					sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
-						c->parm.num[0] ? c->parm.num : "0123456789");
+						c->parm.num[0] ? (char *)(c->parm.num) : "0123456789");
 				i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
 			}
 			break;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/icn/icn.h linux.pre11.3/drivers/isdn/icn/icn.h
--- linux.vanilla/drivers/isdn/icn/icn.h	Sat Jan  9 21:50:38 1999
+++ linux.pre11.3/drivers/isdn/icn/icn.h	Mon Jul 19 23:59:34 1999
@@ -318,9 +318,9 @@
 #ifdef MODULE
 MODULE_AUTHOR("Fritz Elfert");
 MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port address of first card");
+MODULE_PARM_DESC(portbase, "Port adress of first card");
 MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory address of all cards");
+MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
 MODULE_PARM(icn_id, "s");
 MODULE_PARM_DESC(icn_id, "ID-String of first card");
 MODULE_PARM(icn_id2, "s");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_audio.c linux.pre11.3/drivers/isdn/isdn_audio.c
--- linux.vanilla/drivers/isdn/isdn_audio.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/isdn_audio.c	Mon Jul 19 23:59:34 1999
@@ -1,9 +1,10 @@
-/* $Id: isdn_audio.c,v 1.10 1998/02/20 17:09:40 fritz Exp $
+/* $Id: isdn_audio.c,v 1.14 1999/07/11 17:14:06 armin Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
  * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
+ * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,6 +21,26 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_audio.c,v $
+ * Revision 1.14  1999/07/11 17:14:06  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.13  1999/04/12 12:33:09  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.12  1998/07/26 18:48:43  armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.11  1998/04/10 10:35:10  paul
+ * fixed (silly?) warnings from egcs on Alpha.
+ *
  * Revision 1.10  1998/02/20 17:09:40  fritz
  * Changes for recent kernels.
  *
@@ -61,7 +82,7 @@
 #include "isdn_audio.h"
 #include "isdn_common.h"
 
-char *isdn_audio_revision = "$Revision: 1.10 $";
+char *isdn_audio_revision = "$Revision: 1.14 $";
 
 /*
  * Misc. lookup-tables.
@@ -276,7 +297,7 @@
 isdn_audio_tlookup(const char *table, char *buff, unsigned long n)
 {
 	while (n--)
-		*buff++ = table[*buff];
+		*buff++ = table[*(unsigned char *)buff];
 }
 #endif
 
@@ -659,4 +680,106 @@
 		}
 		len -= c;
 	}
+}
+
+silence_state *
+isdn_audio_silence_init(silence_state * s)
+{
+	if (!s)
+		s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
+	if (s) {
+		s->idx = 0;
+		s->state = 0;
+	}
+	return s;
+}
+
+void
+isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
+{
+	silence_state *s = info->silence_state;
+	int i;
+	signed char c;
+
+	if (!info->emu.vpar[1]) return;
+
+	for (i = 0; i < len; i++) {
+		if (fmt)
+		    c = isdn_audio_alaw_to_ulaw[*buf++];
+			else
+		    c = *buf++;
+
+		if (c > 0) c -= 128;
+		c = abs(c);
+
+		if (c > (info->emu.vpar[1] * 4)) { 
+			s->idx = 0;
+			s->state = 1; 
+		} else {
+			if (s->idx < 210000) s->idx++; 
+		}
+	}
+}
+
+void
+isdn_audio_put_dle_code(modem_info * info, u_char code)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	int di;
+	int ch;
+	char *p;
+
+	skb = dev_alloc_skb(2);
+	if (!skb) {
+		printk(KERN_WARNING
+		  "isdn_audio: Could not alloc skb for ttyI%d\n",
+		       info->line);
+		return;
+	}
+	p = (char *) skb_put(skb, 2);
+	p[0] = 0x10;
+	p[1] = code;
+	if (skb_headroom(skb) < sizeof(isdn_audio_skb)) {
+		printk(KERN_WARNING
+		       "isdn_audio: insufficient skb_headroom, dropping\n");
+		kfree_skb(skb);
+		return;
+	}
+	ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
+	ISDN_AUDIO_SKB_LOCK(skb) = 0;
+	save_flags(flags);
+	cli();
+	di = info->isdn_driver;
+	ch = info->isdn_channel;
+	__skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
+	dev->drv[di]->rcvcount[ch] += 2;
+	restore_flags(flags);
+	/* Schedule dequeuing */
+	if ((dev->modempoll) && (info->rcvsched))
+		isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
+	wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
+}
+
+void
+isdn_audio_eval_silence(modem_info * info)
+{
+	silence_state *s = info->silence_state;
+	char what;
+
+	what = ' ';
+
+	if (s->idx > (info->emu.vpar[2] * 800)) { 
+		s->idx = 0;
+		if (!s->state) {	/* silence from beginning of rec */ 
+			what = 's';
+		} else {
+			what = 'q';
+		}
+	}
+		if ((what == 's') || (what == 'q')) {
+			printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
+				(what=='s') ? "silence":"quiet");
+			isdn_audio_put_dle_code(info, what);
+		} 
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_audio.h linux.pre11.3/drivers/isdn/isdn_audio.h
--- linux.vanilla/drivers/isdn/isdn_audio.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/isdn_audio.h	Mon Jul 19 23:59:34 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_audio.h,v 1.5 1997/02/03 22:45:21 fritz Exp $
+/* $Id: isdn_audio.h,v 1.8 1999/07/11 17:14:07 armin Exp $
 
  * Linux ISDN subsystem, audio conversion and compression (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,23 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_audio.h,v $
+ * Revision 1.8  1999/07/11 17:14:07  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.7  1999/04/12 12:33:11  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.6  1998/07/26 18:48:44  armin
+ * Added silence detection in voice receive mode.
+ *
  * Revision 1.5  1997/02/03 22:45:21  fritz
  * Reformatted according CodingStyle
  *
@@ -51,6 +68,11 @@
 	int buf[DTMF_NPOINTS];
 } dtmf_state;
 
+typedef struct silence_state {
+	int state;
+	unsigned int idx;
+} silence_state;
+
 extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long);
 extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
 extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
@@ -60,3 +82,7 @@
 extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
 extern void isdn_audio_eval_dtmf(modem_info *);
 dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
+extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
+extern void isdn_audio_eval_silence(modem_info *);
+silence_state *isdn_audio_silence_init(silence_state *);
+extern void isdn_audio_put_dle_code(modem_info *, u_char);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_bsdcomp.c linux.pre11.3/drivers/isdn/isdn_bsdcomp.c
--- linux.vanilla/drivers/isdn/isdn_bsdcomp.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/isdn_bsdcomp.c	Mon Jul 19 23:59:34 1999
@@ -0,0 +1,934 @@
+/*
+ * BSD compression module
+ *
+ * Patched version for ISDN syncPPP written 1997/1998 by Michael Hipp
+ * The whole module is now SKB based.
+ *
+ * Compile with:
+ *  gcc -O2 -I/usr/src/linux/include -D__KERNEL__ -DMODULE -c isdn_bsdcomp.c
+ */
+
+/*
+ * Original copyright notice:
+ *
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * 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.
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the University of
+ *	California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#ifndef MODULE
+#error This file must be compiled as a module.
+#endif
+
+#include <linux/module.h>
+
+#include <linux/kernel.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/tty.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 <asm/bitops.h>
+#include <asm/segment.h>
+#include <asm/byteorder.h>
+#include <asm/types.h>
+
+#include <linux/if.h>
+
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/ioctl.h>
+
+#include <linux/ppp_defs.h>
+
+#include <linux/isdn.h>
+#include <linux/isdn_ppp.h>
+/* #include <linux/netprotocol.h> */
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/if_arp.h>
+#include <linux/ppp-comp.h>
+
+#include "isdn_ppp.h"
+
+#define BSD_VERSION(x)	((x) >> 5)
+#define BSD_NBITS(x)	((x) & 0x1F)
+
+#define BSD_CURRENT_VERSION	1
+
+#define DEBUG 1
+
+/*
+ * A dictionary for doing BSD compress.
+ */
+
+struct bsd_dict {
+	u32 fcode;
+	u16 codem1;		/* output of hash table -1 */
+	u16 cptr;		/* map code to hash table entry */
+};
+
+struct bsd_db {
+	int            totlen;		/* length of this structure */
+	unsigned int   hsize;		/* size of the hash table */
+	unsigned char  hshift;		/* used in hash function */
+	unsigned char  n_bits;		/* current bits/code */
+	unsigned char  maxbits;		/* maximum bits/code */
+	unsigned char  debug;		/* non-zero if debug desired */
+	unsigned char  unit;		/* ppp unit number */
+	u16 seqno;          		/* sequence # of next packet */
+	unsigned int   mru;		/* size of receive (decompress) bufr */
+	unsigned int   maxmaxcode;	/* largest valid code */
+	unsigned int   max_ent;		/* largest code in use */
+	unsigned int   in_count;	/* uncompressed bytes, aged */
+	unsigned int   bytes_out;	/* compressed bytes, aged */
+	unsigned int   ratio;		/* recent compression ratio */
+	unsigned int   checkpoint;	/* when to next check the ratio */
+	unsigned int   clear_count;	/* times dictionary cleared */
+	unsigned int   incomp_count;	/* incompressible packets */
+	unsigned int   incomp_bytes;	/* incompressible bytes */
+	unsigned int   uncomp_count;	/* uncompressed packets */
+	unsigned int   uncomp_bytes;	/* uncompressed bytes */
+	unsigned int   comp_count;	/* compressed packets */
+	unsigned int   comp_bytes;	/* compressed bytes */
+	unsigned short  *lens;		/* array of lengths of codes */
+	struct bsd_dict *dict;		/* dictionary */
+	int xmit;
+};
+
+#define BSD_OVHD	2		/* BSD compress overhead/packet */
+#define MIN_BSD_BITS	9
+#define BSD_INIT_BITS	MIN_BSD_BITS
+#define MAX_BSD_BITS	15
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define CLEAR	256			/* table clear output code */
+#define FIRST	257			/* first free entry */
+#define LAST	255
+
+#define MAXCODE(b)	((1 << (b)) - 1)
+#define BADCODEM1	MAXCODE(MAX_BSD_BITS);
+
+#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
+					 ^ (unsigned long)(prefix))
+#define BSD_KEY(prefix,suffix)		((((unsigned long)(suffix)) << 16) \
+					 + (unsigned long)(prefix))
+
+#define CHECK_GAP	10000		/* Ratio check interval */
+
+#define RATIO_SCALE_LOG	8
+#define RATIO_SCALE	(1<<RATIO_SCALE_LOG)
+#define RATIO_MAX	(0x7fffffff>>RATIO_SCALE_LOG)
+
+/*
+ * clear the dictionary
+ */
+
+static void bsd_clear(struct bsd_db *db)
+{
+	db->clear_count++;
+	db->max_ent      = FIRST-1;
+	db->n_bits       = BSD_INIT_BITS;
+	db->bytes_out    = 0;
+	db->in_count     = 0;
+	db->incomp_count = 0;
+	db->ratio	     = 0;
+	db->checkpoint   = CHECK_GAP;
+}
+
+/*
+ * If the dictionary is full, then see if it is time to reset it.
+ *
+ * Compute the compression ratio using fixed-point arithmetic
+ * with 8 fractional bits.
+ *
+ * Since we have an infinite stream instead of a single file,
+ * watch only the local compression ratio.
+ *
+ * Since both peers must reset the dictionary at the same time even in
+ * the absence of CLEAR codes (while packets are incompressible), they
+ * must compute the same ratio.
+ */
+static int bsd_check (struct bsd_db *db)	/* 1=output CLEAR */
+{
+    unsigned int new_ratio;
+
+    if (db->in_count >= db->checkpoint)
+      {
+	/* age the ratio by limiting the size of the counts */
+	if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
+	  {
+	    db->in_count  -= (db->in_count  >> 2);
+	    db->bytes_out -= (db->bytes_out >> 2);
+	  }
+	
+	db->checkpoint = db->in_count + CHECK_GAP;
+	
+	if (db->max_ent >= db->maxmaxcode)
+	  {
+	    /* Reset the dictionary only if the ratio is worse,
+	     * or if it looks as if it has been poisoned
+	     * by incompressible data.
+	     *
+	     * This does not overflow, because
+	     *	db->in_count <= RATIO_MAX.
+	     */
+
+	    new_ratio = db->in_count << RATIO_SCALE_LOG;
+	    if (db->bytes_out != 0)
+	      {
+		new_ratio /= db->bytes_out;
+	      }
+	    
+	    if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
+	      {
+		bsd_clear (db);
+		return 1;
+	      }
+	    db->ratio = new_ratio;
+	  }
+      }
+    return 0;
+}
+
+/*
+ * Return statistics.
+ */
+
+static void bsd_stats (void *state, struct compstat *stats)
+{
+	struct bsd_db *db = (struct bsd_db *) state;
+    
+	stats->unc_bytes    = db->uncomp_bytes;
+	stats->unc_packets  = db->uncomp_count;
+	stats->comp_bytes   = db->comp_bytes;
+	stats->comp_packets = db->comp_count;
+	stats->inc_bytes    = db->incomp_bytes;
+	stats->inc_packets  = db->incomp_count;
+	stats->in_count     = db->in_count;
+	stats->bytes_out    = db->bytes_out;
+}
+
+/*
+ * Reset state, as on a CCP ResetReq.
+ */
+static void bsd_reset (void *state,unsigned char code, unsigned char id,
+			unsigned char *data, unsigned len,
+			struct isdn_ppp_resetparams *rsparm)
+{
+	struct bsd_db *db = (struct bsd_db *) state;
+
+	bsd_clear(db);
+	db->seqno       = 0;
+	db->clear_count = 0;
+}
+
+/*
+ * Release the compression structure
+ */
+static void bsd_free (void *state)
+{
+	struct bsd_db *db = (struct bsd_db *) state;
+
+	if (db) {
+		/*
+		 * Release the dictionary
+		 */
+		if (db->dict) {
+			vfree (db->dict);
+			db->dict = NULL;
+		}
+
+		/*
+		 * Release the string buffer
+		 */
+		if (db->lens) {
+			vfree (db->lens);
+			db->lens = NULL;
+		}
+
+		/*
+		 * Finally release the structure itself.
+		 */
+		kfree (db);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+
+/*
+ * Allocate space for a (de) compressor.
+ */
+static void *bsd_alloc (struct isdn_ppp_comp_data *data)
+{
+	int bits;
+	unsigned int hsize, hshift, maxmaxcode;
+	struct bsd_db *db;
+	int decomp;
+
+	static unsigned int htab[][2] = {
+		{ 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , 
+		{ 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 } 
+	};
+		
+	if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
+		|| BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
+		return NULL;
+
+	bits = BSD_NBITS(data->options[0]);
+
+	if(bits < 9 || bits > 15)
+		return NULL;
+
+	hsize = htab[bits-9][0];
+	hshift = htab[bits-9][1];
+	
+	/*
+	 * Allocate the main control structure for this instance.
+	 */
+	maxmaxcode = MAXCODE(bits);
+	db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL);
+	if (!db)
+		return NULL;
+
+	memset (db, 0, sizeof(struct bsd_db));
+
+	db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
+	decomp = db->xmit ? 0 : 1;
+
+	/*
+	 * Allocate space for the dictionary. This may be more than one page in
+	 * length.
+	 */
+	db->dict = (struct bsd_dict *) vmalloc (hsize * sizeof (struct bsd_dict));
+	if (!db->dict) {
+		bsd_free (db);
+		return NULL;
+	}
+
+	MOD_INC_USE_COUNT;
+
+	/*
+	 * If this is the compression buffer then there is no length data.
+	 * For decompression, the length information is needed as well.
+	 */
+	if (!decomp)
+		db->lens = NULL;
+	else {
+		db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
+			sizeof (db->lens[0]));
+		if (!db->lens) {
+			bsd_free (db); /* calls MOD_DEC_USE_COUNT; */
+			return (NULL);
+		}
+	}
+
+	/*
+	 * Initialize the data information for the compression code
+	 */
+	db->totlen     = sizeof (struct bsd_db) + (sizeof (struct bsd_dict) * hsize);
+	db->hsize      = hsize;
+	db->hshift     = hshift;
+	db->maxmaxcode = maxmaxcode;
+	db->maxbits    = bits;
+
+	return (void *) db;
+}
+
+/*
+ * Initialize the database.
+ */
+static int bsd_init (void *state, struct isdn_ppp_comp_data *data, int unit, int debug)
+{
+	struct bsd_db *db = state;
+	int indx;
+	int decomp;
+
+	if(!state || !data) {
+		printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n",unit,(long)state,(long)data);
+		return 0;
+	}
+
+	decomp = db->xmit ? 0 : 1;
+    
+	if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
+		|| (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
+		|| (BSD_NBITS(data->options[0]) != db->maxbits)
+		|| (decomp && db->lens == NULL)) {
+		printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n",data->optlen,data->num,data->options[0],decomp,(unsigned long)db->lens);
+		return 0;
+	}
+
+	if (decomp)
+		for(indx=LAST;indx>=0;indx--)
+			db->lens[indx] = 1;
+
+	indx = db->hsize;
+	while (indx-- != 0) {
+		db->dict[indx].codem1 = BADCODEM1;
+		db->dict[indx].cptr   = 0;
+	}
+
+	db->unit = unit;
+	db->mru  = 0;
+
+	db->debug = 1;
+    
+	bsd_reset(db,0,0,NULL,0,NULL);
+    
+	return 1;
+}
+
+/*
+ * Obtain pointers to the various structures in the compression tables
+ */
+
+#define dict_ptrx(p,idx) &(p->dict[idx])
+#define lens_ptrx(p,idx) &(p->lens[idx])
+
+#ifdef DEBUG
+static unsigned short *lens_ptr(struct bsd_db *db, int idx)
+{
+	if ((unsigned int) idx > (unsigned int) db->maxmaxcode) {
+		printk (KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx);
+		idx = 0;
+	}
+	return lens_ptrx (db, idx);
+}
+
+static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
+{
+	if ((unsigned int) idx >= (unsigned int) db->hsize) {
+		printk (KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx);
+		idx = 0;
+	}
+	return dict_ptrx (db, idx);
+}
+
+#else
+#define lens_ptr(db,idx) lens_ptrx(db,idx)
+#define dict_ptr(db,idx) dict_ptrx(db,idx)
+#endif
+
+/*
+ * compress a packet
+ */
+static int bsd_compress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,int proto)
+{
+	struct bsd_db *db;
+	int hshift;
+	unsigned int max_ent;
+	unsigned int n_bits;
+	unsigned int bitno;
+	unsigned long accm;
+	int ent;
+	unsigned long fcode;
+	struct bsd_dict *dictp;
+	unsigned char c;
+	int hval,disp,ilen,mxcode;
+	unsigned char *rptr = skb_in->data;
+	int isize = skb_in->len;
+
+#define OUTPUT(ent)			\
+  {					\
+    bitno -= n_bits;			\
+    accm |= ((ent) << bitno);		\
+    do	{				\
+        if(skb_out && skb_tailroom(skb_out) > 0) 	\
+      		*(skb_put(skb_out,1)) = (unsigned char) (accm>>24); \
+	accm <<= 8;			\
+	bitno += 8;			\
+    } while (bitno <= 24);		\
+  }
+
+	/*
+	 * If the protocol is not in the range we're interested in,
+	 * just return without compressing the packet.  If it is,
+	 * the protocol becomes the first byte to compress.
+	 */
+	printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
+	
+	ent = proto;
+	if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) )
+		return 0;
+
+	db      = (struct bsd_db *) state;
+	hshift  = db->hshift;
+	max_ent = db->max_ent;
+	n_bits  = db->n_bits;
+	bitno   = 32;
+	accm    = 0;
+	mxcode  = MAXCODE (n_bits);
+	
+	/* This is the PPP header information */
+	if(skb_out && skb_tailroom(skb_out) >= 2) {
+		char *v = skb_put(skb_out,2);
+		/* we only push our own data on the header,
+		  AC,PC and protos is pushed by caller  */
+		v[0] = db->seqno >> 8;
+		v[1] = db->seqno;
+	}
+
+	ilen   = ++isize; /* This is off by one, but that is what is in draft! */
+
+	while (--ilen > 0) {
+		c     = *rptr++;
+		fcode = BSD_KEY  (ent, c);
+		hval  = BSD_HASH (ent, c, hshift);
+		dictp = dict_ptr (db, hval);
+	
+		/* Validate and then check the entry. */
+		if (dictp->codem1 >= max_ent)
+			goto nomatch;
+
+		if (dictp->fcode == fcode) {
+			ent = dictp->codem1 + 1;
+			continue;	/* found (prefix,suffix) */
+		}
+	
+		/* continue probing until a match or invalid entry */
+		disp = (hval == 0) ? 1 : hval;
+
+		do {
+			hval += disp;
+			if (hval >= db->hsize)
+				hval -= db->hsize;
+			dictp = dict_ptr (db, hval);
+			if (dictp->codem1 >= max_ent)
+				goto nomatch;
+		} while (dictp->fcode != fcode);
+
+		ent = dictp->codem1 + 1;	/* finally found (prefix,suffix) */
+		continue;
+	
+nomatch:
+		OUTPUT(ent);		/* output the prefix */
+	
+		/* code -> hashtable */
+		if (max_ent < db->maxmaxcode) {
+			struct bsd_dict *dictp2;
+			struct bsd_dict *dictp3;
+			int indx;
+
+			/* expand code size if needed */
+			if (max_ent >= mxcode) {
+				db->n_bits = ++n_bits;
+				mxcode = MAXCODE (n_bits);
+			}
+	    
+			/* 
+			 * Invalidate old hash table entry using
+			 * this code, and then take it over.
+			 */
+			dictp2 = dict_ptr (db, max_ent + 1);
+			indx   = dictp2->cptr;
+			dictp3 = dict_ptr (db, indx);
+
+			if (dictp3->codem1 == max_ent)
+				dictp3->codem1 = BADCODEM1;
+
+			dictp2->cptr   = hval;
+			dictp->codem1  = max_ent;
+			dictp->fcode = fcode;
+			db->max_ent    = ++max_ent;
+
+			if (db->lens) {
+				unsigned short *len1 = lens_ptr (db, max_ent);
+				unsigned short *len2 = lens_ptr (db, ent);
+				*len1 = *len2 + 1;
+			}
+		}
+		ent = c;
+	}
+    
+	OUTPUT(ent);		/* output the last code */
+
+	if(skb_out)
+		db->bytes_out    += skb_out->len; /* Do not count bytes from here */
+	db->uncomp_bytes += isize;
+	db->in_count     += isize;
+	++db->uncomp_count;
+	++db->seqno;
+
+	if (bitno < 32)
+		++db->bytes_out; /* must be set before calling bsd_check */
+
+	/*
+	 * Generate the clear command if needed
+	 */
+
+	if (bsd_check(db))
+		OUTPUT (CLEAR);
+
+	/*
+	 * Pad dribble bits of last code with ones.
+	 * Do not emit a completely useless byte of ones.
+	 */
+	if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0) 
+		*(skb_put(skb_out,1)) = (unsigned char) ((accm | (0xff << (bitno-8))) >> 24);
+    
+	/*
+	 * Increase code size if we would have without the packet
+	 * boundary because the decompressor will do so.
+	 */
+	if (max_ent >= mxcode && max_ent < db->maxmaxcode)
+		db->n_bits++;
+
+	/* If output length is too large then this is an incompressible frame. */
+	if (!skb_out || (skb_out && skb_out->len >= skb_in->len) ) {
+		++db->incomp_count;
+		db->incomp_bytes += isize;
+		return 0;
+	}
+
+	/* Count the number of compressed frames */
+	++db->comp_count;
+	db->comp_bytes += skb_out->len;
+	return skb_out->len;
+
+#undef OUTPUT
+}
+
+/*
+ * Update the "BSD Compress" dictionary on the receiver for
+ * incompressible data by pretending to compress the incoming data.
+ */
+static void bsd_incomp (void *state, struct sk_buff *skb_in,int proto)
+{
+	bsd_compress (state, skb_in, NULL, proto);
+}
+
+/*
+ * Decompress "BSD Compress".
+ */
+static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,
+			   struct isdn_ppp_resetparams *rsparm)
+{
+	struct bsd_db *db;
+	unsigned int max_ent;
+	unsigned long accm;
+	unsigned int bitno;		/* 1st valid bit in accm */
+	unsigned int n_bits;
+	unsigned int tgtbitno;	/* bitno when we have a code */
+	struct bsd_dict *dictp;
+	int seq;
+	unsigned int incode;
+	unsigned int oldcode;
+	unsigned int finchar;
+	unsigned char *p,*ibuf;
+	int ilen;
+	int codelen;
+	int extra;
+
+	db       = (struct bsd_db *) state;
+	max_ent  = db->max_ent;
+	accm     = 0;
+	bitno    = 32;		/* 1st valid bit in accm */
+	n_bits   = db->n_bits;
+	tgtbitno = 32 - n_bits;	/* bitno when we have a code */
+
+	printk(KERN_DEBUG "bsd_decompress called\n");
+
+	if(!skb_in || !skb_out) {
+		printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
+		return DECOMP_ERROR;
+	}
+    
+	/*
+	 * Get the sequence number.
+	 */
+	if( (p = skb_pull(skb_in,2)) == NULL) {
+		return DECOMP_ERROR;
+	}
+	p-=2;
+	seq   = (p[0] << 8) + p[1];
+	ilen  = skb_in->len;
+	ibuf = skb_in->data;
+
+	/*
+	 * Check the sequence number and give up if it differs from
+	 * the value we're expecting.
+	 */
+	if (seq != db->seqno) {
+		if (db->debug) {
+			printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n",
+				db->unit, seq, db->seqno - 1);
+		}
+		return DECOMP_ERROR;
+	}
+
+	++db->seqno;
+	db->bytes_out += ilen;
+
+	if(skb_tailroom(skb_out) > 0)
+		*(skb_put(skb_out,1)) = 0;
+	else
+		return DECOMP_ERR_NOMEM;
+    
+	oldcode = CLEAR;
+
+	/*
+	 * Keep the checkpoint correctly so that incompressible packets
+	 * clear the dictionary at the proper times.
+	 */
+
+	for (;;) {
+		if (ilen-- <= 0) {
+			db->in_count += (skb_out->len - 1); /* don't count the header */
+			break;
+		}
+
+		/*
+		 * Accumulate bytes until we have a complete code.
+		 * Then get the next code, relying on the 32-bit,
+		 * unsigned accm to mask the result.
+		 */
+
+		bitno -= 8;
+		accm  |= *ibuf++ << bitno;
+		if (tgtbitno < bitno)
+			continue;
+
+		incode = accm >> tgtbitno;
+		accm <<= n_bits;
+		bitno += n_bits;
+
+		/*
+		 * The dictionary must only be cleared at the end of a packet.
+		 */
+	
+		if (incode == CLEAR) {
+			if (ilen > 0) {
+				if (db->debug)
+					printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit);
+				return DECOMP_FATALERROR;	/* probably a bug */
+			}
+			bsd_clear(db);
+			break;
+		}
+
+		if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
+			|| (incode > max_ent && oldcode == CLEAR)) {
+			if (db->debug) {
+				printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
+					db->unit, incode, oldcode);
+				printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n",
+					max_ent, skb_out->len, db->seqno);
+			}
+			return DECOMP_FATALERROR;	/* probably a bug */
+		}
+	
+		/* Special case for KwKwK string. */
+		if (incode > max_ent) {
+			finchar = oldcode;
+			extra   = 1;
+		} else {
+			finchar = incode;
+			extra   = 0;
+		}
+
+		codelen = *(lens_ptr (db, finchar));
+		if( skb_tailroom(skb_out) < codelen + extra) {
+			if (db->debug) {
+				printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit);
+#ifdef DEBUG
+				printk(KERN_DEBUG "  len=%d, finchar=0x%x, codelen=%d,skblen=%d\n",
+					ilen, finchar, codelen, skb_out->len);
+#endif
+			}
+			return DECOMP_FATALERROR;
+		}
+
+		/*
+		 * Decode this code and install it in the decompressed buffer.
+		 */
+
+		p     = skb_put(skb_out,codelen);
+		p += codelen;
+		while (finchar > LAST) {
+			struct bsd_dict *dictp2 = dict_ptr (db, finchar);
+	    
+			dictp = dict_ptr (db, dictp2->cptr);
+
+#ifdef DEBUG
+			if (--codelen <= 0 || dictp->codem1 != finchar-1) {
+				if (codelen <= 0) {
+					printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit);
+					printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent);
+				} else {
+					if (dictp->codem1 != finchar-1) {
+						printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",db->unit, incode, finchar);
+						printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1);
+					}
+				}
+				return DECOMP_FATALERROR;
+			}
+#endif
+
+			{
+				u32 fcode = dictp->fcode;
+				*--p    = (fcode >> 16) & 0xff;
+				finchar = fcode & 0xffff;
+			}
+		}
+		*--p = finchar;
+	
+#ifdef DEBUG
+		if (--codelen != 0)
+			printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent);
+#endif
+	
+		if (extra)		/* the KwKwK case again */
+			*(skb_put(skb_out,1)) = finchar;
+	
+		/*
+		 * If not first code in a packet, and
+		 * if not out of code space, then allocate a new code.
+		 *
+		 * Keep the hash table correct so it can be used
+		 * with uncompressed packets.
+		 */
+		if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
+			struct bsd_dict *dictp2, *dictp3;
+			u16  *lens1,  *lens2;
+			unsigned long fcode;
+			int hval, disp, indx;
+	    
+			fcode = BSD_KEY(oldcode,finchar);
+			hval  = BSD_HASH(oldcode,finchar,db->hshift);
+			dictp = dict_ptr (db, hval);
+	    
+			/* look for a free hash table entry */
+			if (dictp->codem1 < max_ent) {
+				disp = (hval == 0) ? 1 : hval;
+				do {
+					hval += disp;
+					if (hval >= db->hsize)
+						hval -= db->hsize;
+					dictp = dict_ptr (db, hval);
+				} while (dictp->codem1 < max_ent);
+			}
+	    
+			/*
+			 * Invalidate previous hash table entry
+			 * assigned this code, and then take it over
+			 */
+
+			dictp2 = dict_ptr (db, max_ent + 1);
+			indx   = dictp2->cptr;
+			dictp3 = dict_ptr (db, indx);
+
+			if (dictp3->codem1 == max_ent)
+				dictp3->codem1 = BADCODEM1;
+
+			dictp2->cptr   = hval;
+			dictp->codem1  = max_ent;
+			dictp->fcode = fcode;
+			db->max_ent    = ++max_ent;
+
+			/* Update the length of this string. */
+			lens1  = lens_ptr (db, max_ent);
+			lens2  = lens_ptr (db, oldcode);
+			*lens1 = *lens2 + 1;
+	    
+			/* Expand code size if needed. */
+			if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
+				db->n_bits = ++n_bits;
+				tgtbitno   = 32-n_bits;
+			}
+		}
+		oldcode = incode;
+	}
+
+	++db->comp_count;
+	++db->uncomp_count;
+	db->comp_bytes   += skb_in->len - BSD_OVHD;
+	db->uncomp_bytes += skb_out->len;
+
+	if (bsd_check(db)) {
+		if (db->debug)
+			printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
+				db->unit, db->seqno - 1);
+	}
+	return skb_out->len;
+}
+
+/*************************************************************
+ * Table of addresses for the BSD compression module
+ *************************************************************/
+
+static struct isdn_ppp_compressor ippp_bsd_compress = {
+	NULL,NULL,		/* prev,next: overwritten by isdn_ppp */
+	CI_BSD_COMPRESS,	/* compress_proto */
+	bsd_alloc,		/* alloc */
+	bsd_free,		/* free */
+	bsd_init,		/* init */
+	bsd_reset,		/* reset */
+	bsd_compress,		/* compress */
+	bsd_decompress,		/* decompress */
+	bsd_incomp,		/* incomp */
+	bsd_stats		/* comp_stat */
+};
+
+/*************************************************************
+ * Module support routines
+ *************************************************************/
+
+int init_module(void)
+{
+	int answer = isdn_ppp_register_compressor (&ippp_bsd_compress);
+	if (answer == 0)
+		printk (KERN_INFO "PPP BSD Compression module registered\n");
+	return answer;
+}
+
+void cleanup_module(void)
+{
+	isdn_ppp_unregister_compressor (&ippp_bsd_compress);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_cards.c linux.pre11.3/drivers/isdn/isdn_cards.c
--- linux.vanilla/drivers/isdn/isdn_cards.c	Sun Nov  8 15:08:07 1998
+++ linux.pre11.3/drivers/isdn/isdn_cards.c	Mon Jul 19 23:59:34 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_cards.c,v 1.7 1998/02/20 17:24:28 fritz Exp $
+/* $Id: isdn_cards.c,v 1.9 1999/04/12 12:33:11 fritz Exp $
 
  * Linux ISDN subsystem, initialization for non-modularized drivers.
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_cards.c,v $
+ * Revision 1.9  1999/04/12 12:33:11  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.8  1999/03/29 11:13:23  armin
+ * Added eicon driver init.
+ *
  * Revision 1.7  1998/02/20 17:24:28  fritz
  * Added ACT2000 init.
  *
@@ -56,6 +62,10 @@
 extern void pcbit_init(void);
 #endif
 
+#ifdef CONFIG_ISDN_DRV_EICON
+extern void eicon_init(void);
+#endif
+
 #ifdef CONFIG_ISDN_DRV_AVMB1
 extern void avmb1_init(void);
 extern void capi_init(void);
@@ -87,5 +97,8 @@
 #endif
 #if CONFIG_ISDN_DRV_ACT2000
 	act2000_init();
+#endif
+#if CONFIG_ISDN_DRV_EICON
+	eicon_init();
 #endif
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_cards.h linux.pre11.3/drivers/isdn/isdn_cards.h
--- linux.vanilla/drivers/isdn/isdn_cards.h	Sun Nov  8 15:08:07 1998
+++ linux.pre11.3/drivers/isdn/isdn_cards.h	Mon Jul 19 23:59:34 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_cards.h,v 1.2 1997/02/03 23:31:55 fritz Exp $
+/* $Id: isdn_cards.h,v 1.3 1999/04/12 12:33:13 fritz Exp $
 
  * Linux ISDN subsystem, initialization for non-modularized drivers.
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_cards.h,v $
+ * Revision 1.3  1999/04/12 12:33:13  fritz
+ * Changes from 2.0 tree.
+ *
  * Revision 1.2  1997/02/03 23:31:55  fritz
  * Reformatted according CodingStyle
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_common.c linux.pre11.3/drivers/isdn/isdn_common.c
--- linux.vanilla/drivers/isdn/isdn_common.c	Sun Jan 24 19:55:34 1999
+++ linux.pre11.3/drivers/isdn/isdn_common.c	Mon Jul 19 23:59:35 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.c,v 1.55 1998/02/23 23:35:32 fritz Exp $
+/* $Id: isdn_common.c,v 1.83 1999/07/13 21:02:05 werner Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
@@ -20,11 +20,111 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
  * $Log: isdn_common.c,v $
+ * Revision 1.83  1999/07/13 21:02:05  werner
+ * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH)
+ *
+ * Revision 1.82  1999/07/12 21:06:50  werner
+ * Fixed problem when loading more than one driver temporary
+ *
+ * Revision 1.81  1999/07/11 17:14:09  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.80  1999/07/07 10:14:00  detabc
+ * remove unused messages
+ *
+ * Revision 1.79  1999/07/05 23:51:30  werner
+ * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl
+ * hisaxctrl id 10 <nr. of chans 0-2>
+ *
+ * Revision 1.78  1999/07/05 20:21:15  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.77  1999/07/01 08:29:50  keil
+ * compatibility to 2.3 kernel
+ *
+ * Revision 1.76  1999/06/29 16:16:44  calle
+ * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again.
+ * Also right unlocking (ISDN_CMD_UNLOCK) is done now.
+ * isdnlog should check returncode of read(2) calls.
+ *
+ * Revision 1.75  1999/04/18 14:06:47  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.74  1999/04/12 13:16:45  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.73  1999/04/12 12:33:15  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.72  1999/03/02 12:04:44  armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.71  1999/01/28 09:10:43  armin
+ * Fixed bad while-loop in isdn_readbch().
+ *
+ * Revision 1.70  1999/01/15 19:58:54  he
+ * removed compatibiltity macro
+ *
+ * Revision 1.69  1998/09/07 21:59:58  he
+ * flush method for 2.1.118 and above
+ * updated IIOCTLNETGPN
+ *
+ * Revision 1.68  1998/08/31 21:09:45  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
+ * Revision 1.67  1998/06/26 15:12:21  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.66  1998/06/17 19:50:41  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ *
+ * Revision 1.62  1998/04/14 16:28:43  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.61  1998/03/22 18:50:46  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.60  1998/03/19 13:18:18  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ * Revision 1.59  1998/03/09 17:46:23  he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.58  1998/03/07 22:35:24  fritz
+ * Starting generic module support (Nothing usable yet).
+ *
+ * Revision 1.57  1998/03/07 18:21:01  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.56  1998/02/25 17:49:38  he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
  * Revision 1.55  1998/02/23 23:35:32  fritz
  * Eliminated some compiler warnings.
  *
@@ -261,6 +361,9 @@
 #ifdef CONFIG_ISDN_AUDIO
 #include "isdn_audio.h"
 #endif
+#ifdef CONFIG_ISDN_DIVERSION
+#include <linux/isdn_divertif.h>
+#endif CONFIG_ISDN_DIVERSION
 #include "isdn_v110.h"
 #include "isdn_cards.h"
 
@@ -269,7 +372,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.55 $";
+static char *isdn_revision = "$Revision: 1.83 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -285,18 +388,46 @@
 #endif
 extern char *isdn_v110_revision;
 
+#ifdef CONFIG_ISDN_DIVERSION
+isdn_divert_if *divert_if = NULL; /* interface to diversion module */
+#endif CONFIG_ISDN_DIVERSION
+
+
 static int isdn_writebuf_stub(int, int, const u_char *, int, int);
 
 void
 isdn_MOD_INC_USE_COUNT(void)
 {
+	int i;
+
 	MOD_INC_USE_COUNT;
+	for (i = 0; i < dev->drivers; i++) {
+		isdn_ctrl cmd;
+
+		cmd.driver = i;
+		cmd.arg = 0;
+		cmd.command = ISDN_CMD_LOCK;
+		isdn_command(&cmd);
+		dev->drv[i]->locks++;
+	}
 }
 
 void
 isdn_MOD_DEC_USE_COUNT(void)
 {
+	int i;
+
 	MOD_DEC_USE_COUNT;
+	for (i = 0; i < dev->drivers; i++)
+		if (dev->drv[i]->locks > 0) {
+			isdn_ctrl cmd;
+
+			cmd.driver = i;
+			cmd.arg = 0;
+			cmd.command = ISDN_CMD_UNLOCK;
+			isdn_command(&cmd);
+			dev->drv[i]->locks--;
+		}
 }
 
 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
@@ -312,6 +443,82 @@
 }
 #endif
 
+/*
+ * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
+ * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
+ */
+static int
+isdn_star(char *s, char *p)
+{
+	while (isdn_wildmat(s, p)) {
+		if (*++s == '\0')
+			return (2);
+	}
+	return (0);
+}
+
+/*
+ * Shell-type Pattern-matching for incoming caller-Ids
+ * This function gets a string in s and checks, if it matches the pattern
+ * given in p.
+ *
+ * Return:
+ *   0 = match.
+ *   1 = no match.
+ *   2 = no match. Would eventually match, if s would be longer.
+ *
+ * Possible Patterns:
+ *
+ * '?'     matches one character
+ * '*'     matches zero or more characters
+ * [xyz]   matches the set of characters in brackets.
+ * [^xyz]  matches any single character not in the set of characters
+ */
+
+int
+isdn_wildmat(char *s, char *p)
+{
+	register int last;
+	register int matched;
+	register int reverse;
+	register int nostar = 1;
+
+	for (; *p; s++, p++)
+		switch (*p) {
+			case '\\':
+				/*
+				 * Literal match with following character,
+				 * fall through.
+				 */
+				p++;
+			default:
+				if (*s != *p)
+					return (*s == '\0')?2:1;
+				continue;
+			case '?':
+				/* Match anything. */
+				if (*s == '\0')
+					return (2);
+				continue;
+			case '*':
+				nostar = 0;	
+				/* Trailing star matches everything. */
+				return (*++p ? isdn_star(s, p) : 0);
+			case '[':
+				/* [^....] means inverse character class. */
+				if ((reverse = (p[1] == '^')))
+					p++;
+				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
+					/* This next line requires a good C compiler. */
+					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
+						matched = 1;
+				if (matched == reverse)
+					return (1);
+				continue;
+		}
+	return (*s == '\0')?0:nostar;
+}
+
 static void
 isdn_free_queue(struct sk_buff_head *queue)
 {
@@ -345,7 +552,6 @@
 isdn_timer_funct(ulong dummy)
 {
 	int tf = dev->tflags;
-
 	if (tf & ISDN_TIMER_FAST) {
 		if (tf & ISDN_TIMER_MODEMREAD)
 			isdn_tty_readmodem();
@@ -374,13 +580,16 @@
 				if (tf & ISDN_TIMER_KEEPALIVE)
 					isdn_net_slarp_out();
 			}
+			if (tf & ISDN_TIMER_CARRIER)
+				isdn_tty_carrier_timeout();
 #if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
 			if (tf & ISDN_TIMER_IPPP)
 				isdn_ppp_timer_timeout();
 #endif
 		}
 	}
-	if (tf) {
+	if (tf) 
+	{
 		int flags;
 
 		save_flags(flags);
@@ -506,6 +715,29 @@
 	isdn_command(&cmd);
 }
 
+/*
+ * Begin of a CAPI like LL<->HL interface, currently used only for 
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include "avmb1/capicmd.h"  /* this should be moved in a common place */
+
+int
+isdn_capi_rec_hl_msg(capi_msg *cm) {
+	
+	int di;
+	int ch;
+	
+	di = (cm->adr.Controller & 0x7f) -1;
+	ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
+	switch(cm->Command) {
+		case CAPI_FACILITY:
+			/* in the moment only handled in tty */
+			return(isdn_tty_capi_facility(cm));
+		default:
+			return(-1);
+	}
+}
+
 static int
 isdn_status_callback(isdn_ctrl * c)
 {
@@ -540,13 +772,13 @@
 			wake_up_interruptible(&dev->drv[di]->st_waitq);
 			break;
 		case ISDN_STAT_RUN:
-			dev->drv[di]->running = 1;
+			dev->drv[di]->flags |= DRV_FLAG_RUNNING;
 			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 				if (dev->drvmap[i] == di)
 					isdn_all_eaz(di, dev->chanmap[i]);
 			break;
 		case ISDN_STAT_STOP:
-			dev->drv[di]->running = 0;
+			dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
 			break;
 		case ISDN_STAT_ICALL:
 			if (i < 0)
@@ -562,19 +794,23 @@
 				return 0;
 			}
 			/* Try to find a network-interface which will accept incoming call */
-			cmd.driver = di;
-			cmd.arg = c->arg;
-			cmd.command = ISDN_CMD_LOCK;
-			isdn_command(&cmd);
-			r = isdn_net_find_icall(di, c->arg, i, c->parm.setup);
+			r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup));
 			switch (r) {
 				case 0:
 					/* No network-device replies.
-					 * Try ttyI's
+					 * Try ttyI's.
+					 * These return 0 on no match, 1 on match and
+					 * 3 on eventually match, if CID is longer.
 					 */
-					if (isdn_tty_find_icall(di, c->arg, c->parm.setup) >= 0)
-						retval = 1;
-					else if (dev->drv[di]->reject_bus) {
+                                        if (c->command == ISDN_STAT_ICALL)
+					  if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval);
+#ifdef CONFIG_ISDN_DIVERSION 
+                                         if (divert_if)
+                 	                  if ((retval = divert_if->stat_callback(c))) 
+					    return(retval); /* processed */
+#endif CONFIG_ISDN_DIVERSION                        
+					if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
+						/* No tty responding */
 						cmd.driver = di;
 						cmd.arg = c->arg;
 						cmd.command = ISDN_CMD_HANGUP;
@@ -606,13 +842,14 @@
 					/* ... then start callback. */
 					isdn_net_dial();
 					break;
+				case 5:
+					/* Number would eventually match, if longer */
+					retval = 3;
+					break;
 			}
-			if (retval != 1) {
-				cmd.driver = di;
-				cmd.arg = c->arg;
-				cmd.command = ISDN_CMD_UNLOCK;
-				isdn_command(&cmd);
-			}
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
+#endif
 			return retval;
 			break;
 		case ISDN_STAT_CINF:
@@ -634,6 +871,20 @@
 			printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
 			       dev->drvid[di], c->arg, c->parm.num);
 			isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif CONFIG_ISDN_DIVERSION
+			break;
+		case ISDN_STAT_DISPLAY:
+#ifdef ISDN_DEBUG_STATCALLB
+			printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
+#endif
+			isdn_tty_stat_callback(i, c);
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif CONFIG_ISDN_DIVERSION
 			break;
 		case ISDN_STAT_DCONN:
 			if (i < 0)
@@ -664,7 +915,7 @@
 #endif
 			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 				return 0;
-			dev->drv[di]->flags &= ~(1 << (c->arg));
+			dev->drv[di]->online &= ~(1 << (c->arg));
 			isdn_info_update();
 			/* Signal hangup to network-devices */
 			if (isdn_net_stat_callback(i, c))
@@ -672,6 +923,11 @@
 			isdn_v110_stat_callback(i, c);
 			if (isdn_tty_stat_callback(i, c))
 				break;
+#ifdef CONFIG_ISDN_DIVERSION
+                        if (divert_if)
+                         divert_if->stat_callback(c); 
+#endif CONFIG_ISDN_DIVERSION
+			break;
 			break;
 		case ISDN_STAT_BCONN:
 			if (i < 0)
@@ -682,7 +938,7 @@
 			/* Signal B-channel-connect to network-devices */
 			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 				return 0;
-			dev->drv[di]->flags |= (1 << (c->arg));
+			dev->drv[di]->online |= (1 << (c->arg));
 			isdn_info_update();
 			if (isdn_net_stat_callback(i, c))
 				break;
@@ -698,7 +954,7 @@
 #endif
 			if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 				return 0;
-			dev->drv[di]->flags &= ~(1 << (c->arg));
+			dev->drv[di]->online &= ~(1 << (c->arg));
 			isdn_info_update();
 #ifdef CONFIG_ISDN_X25
 			/* Signal hangup to network-devices */
@@ -723,8 +979,38 @@
 				break;
 			break;
 		case ISDN_STAT_ADDCH:
+			if (isdn_add_channels(dev->drv[di], di, c->arg, 1))
+				return -1;
+			isdn_info_update();
+			break;
+		case ISDN_STAT_DISCH:
+			save_flags(flags);
+			cli();
+			for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+				if ((dev->drvmap[i] == di) &&
+				    (dev->chanmap[i] == c->arg)) {
+				    if (c->parm.num[0])
+				      dev->usage[i] &= ~ISDN_USAGE_DISABLED;
+				    else
+				      if (USG_NONE(dev->usage[i])) {
+					dev->usage[i] |= ISDN_USAGE_DISABLED;
+				      }
+				      else 
+					retval = -1;
+				    break;
+				}
+			restore_flags(flags);
+			isdn_info_update();
 			break;
 		case ISDN_STAT_UNLOAD:
+			while (dev->drv[di]->locks > 0) {
+				isdn_ctrl cmd;
+				cmd.driver = di;
+				cmd.arg = 0;
+				cmd.command = ISDN_CMD_UNLOCK;
+				isdn_command(&cmd);
+				dev->drv[di]->locks--;
+			}
 			save_flags(flags);
 			cli();
 			isdn_tty_stat_callback(i, c);
@@ -732,6 +1018,7 @@
 				if (dev->drvmap[i] == di) {
 					dev->drvmap[i] = -1;
 					dev->chanmap[i] = -1;
+					dev->usage[i] &= ~ISDN_USAGE_DISABLED;
 				}
 			dev->drivers--;
 			dev->channels -= dev->drv[di]->channels;
@@ -741,7 +1028,9 @@
 				isdn_free_queue(&dev->drv[di]->rpqueue[i]);
 			kfree(dev->drv[di]->rpqueue);
 			kfree(dev->drv[di]->rcv_waitq);
+#ifndef COMPAT_HAS_NEW_WAITQ
 			kfree(dev->drv[di]->snd_waitq);
+#endif
 			kfree(dev->drv[di]);
 			dev->drv[di] = NULL;
 			dev->drvid[di][0] = '\0';
@@ -750,6 +1039,19 @@
 			return 0;
 		case ISDN_STAT_L1ERR:
 			break;
+		case CAPI_PUT_MESSAGE:
+			return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
+#ifdef CONFIG_ISDN_AUDIO
+		case ISDN_STAT_AUDIO:
+			isdn_tty_stat_callback(i, c);
+			break;
+#endif
+#ifdef CONFIG_ISDN_DIVERSION
+	        case ISDN_STAT_PROT:
+	        case ISDN_STAT_REDIR:
+                        if (divert_if)
+                          return(divert_if->stat_callback(c));
+#endif CONFIG_ISDN_DIVERSION
 		default:
 			return -1;
 	}
@@ -785,7 +1087,11 @@
  * of the mapping (di,ch)<->minor, happen during the sleep? --he 
  */
 int
+#ifdef COMPAT_HAS_NEW_WAITQ
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
+#else
 isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
+#endif
 {
 	int left;
 	int count;
@@ -819,7 +1125,8 @@
 
 			dflag = 0;
 			count_pull = count_put = 0;
-			while ((count_pull < skb->len) && (left-- > 0)) {
+			while ((count_pull < skb->len) && (left > 0)) {
+				left--;
 				if (dev->drv[di]->DLEflag & DLEmask) {
 					*cp++ = DLE;
 					dev->drv[di]->DLEflag &= ~DLEmask;
@@ -894,8 +1201,6 @@
 	return (dev->chanmap[minor]);
 }
 
-#define INF_DV 0x01             /* Data version for /dev/isdninfo */
-
 static char *
 isdn_statstr(void)
 {
@@ -931,7 +1236,7 @@
 	p = istatbuf + strlen(istatbuf);
 	for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
 		if (dev->drv[i]) {
-			sprintf(p, "%ld ", dev->drv[i]->flags);
+			sprintf(p, "%ld ", dev->drv[i]->online);
 			p = istatbuf + strlen(istatbuf);
 		} else {
 			sprintf(p, "? ");
@@ -997,7 +1302,7 @@
 		drvidx = isdn_minor2drv(minor);
 		if (drvidx < 0)
 			return -ENODEV;
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
 			return -ENODEV;
 		chidx = isdn_minor2chan(minor);
 		if(  ! (p = kmalloc(count,GFP_KERNEL))  ) return -ENOMEM;
@@ -1067,7 +1372,7 @@
 		drvidx = isdn_minor2drv(minor);
 		if (drvidx < 0)
 			return -ENODEV;
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
 			return -ENODEV;
 		chidx = isdn_minor2chan(minor);
 		while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count)
@@ -1081,7 +1386,7 @@
 		/*
 		 * We want to use the isdnctrl device to load the firmware
 		 *
-		 if (!dev->drv[drvidx]->running)
+		 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
 		 return -ENODEV;
 		 */
 		if (dev->drv[drvidx]->interface->writecmd)
@@ -1113,11 +1418,11 @@
 		return mask;
 	}
 	if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
-		poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
 		if (drvidx < 0) {
-			printk(KERN_ERR "isdn_common: isdn_poll 1 -> what the hell\n");
-			return POLLERR;
+			/* driver deregistered while file open */
+		        return POLLHUP;
 		}
+		poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
 		mask = POLLOUT | POLLWRNORM;
 		if (dev->drv[drvidx]->stavail) {
 			mask |= POLLIN | POLLRDNORM;
@@ -1132,143 +1437,6 @@
 	return POLLERR;
 }
 
-/* 
- * This accesses user space with interrupts off, but is not needed by
- * any of the isdn4k-util programs anyway. Thus, in contrast to your
- * first impression after looking at the code, fixing is trival!*/
-#if 0 
-static int
-isdn_set_allcfg(char *src)
-{
-	int ret;
-	int i;
-	ulong flags;
-	isdn_net_ioctl_cfg cfg;
-	isdn_net_ioctl_phone phone;
-
-	if ((ret = isdn_net_rmall()))
-		return ret;
-	if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT;
-	save_flags(flags);
-	cli();
-	src += sizeof(int);
-	while (i) {
-		int phone_len;
-		int out_flag;
-
-		if (copy_from_user((char *) &cfg, src, sizeof(cfg))) {
-			restore_flags(flags);
-			return -EFAULT;
-		}
-		src += sizeof(cfg);
-		if (!isdn_net_new(cfg.name, NULL)) {
-			restore_flags(flags);
-			return -EIO;
-		}
-		if ((ret = isdn_net_setcfg(&cfg))) {
-			restore_flags(flags);
-			return ret;
-		}
-		phone_len = out_flag = 0;
-		while (out_flag < 2) {
-			if ((ret = verify_area(VERIFY_READ, src, 1))) {
-				restore_flags(flags);
-				return ret;
-			}
-			get_user(phone.phone[phone_len], src++);
-			if ((phone.phone[phone_len] == ' ') ||
-			    (phone.phone[phone_len] == '\0')) {
-				if (phone_len) {
-					phone.phone[phone_len] = '\0';
-					strcpy(phone.name, cfg.name);
-					phone.outgoing = out_flag;
-					if ((ret = isdn_net_addphone(&phone))) {
-						restore_flags(flags);
-						return ret;
-					}
-				} else
-					out_flag++;
-				phone_len = 0;
-			}
-			if (++phone_len >= sizeof(phone.phone))
-				printk(KERN_WARNING
-				       "%s: IIOCSETSET phone number too long, ignored\n",
-				       cfg.name);
-		}
-		i--;
-	}
-	restore_flags(flags);
-	return 0;
-}
-
-static int
-isdn_get_allcfg(char *dest)
-{
-	isdn_net_ioctl_cfg cfg;
-	isdn_net_ioctl_phone phone;
-	isdn_net_dev *p;
-	ulong flags;
-	int ret;
-
-	/* Walk through netdev-chain */
-	save_flags(flags);
-	cli();
-	p = dev->netdev;
-	while (p) {
-		isdn_net_local *lp = p->local;
-
-		if ((ret = verify_area(VERIFY_WRITE, (void *) dest, sizeof(cfg) + 200))) {
-			restore_flags(flags);
-			return ret;
-		}
-		strcpy(cfg.eaz, lp->msn);
-		cfg.exclusive = lp->exclusive;
-		if (lp->pre_device >= 0) {
-			sprintf(cfg.drvid, "%s,%d", dev->drvid[lp->pre_device],
-				lp->pre_channel);
-		} else
-			cfg.drvid[0] = '\0';
-		cfg.onhtime = lp->onhtime;
-		cfg.charge = lp->charge;
-		cfg.l2_proto = lp->l2_proto;
-		cfg.l3_proto = lp->l3_proto;
-		cfg.p_encap = lp->p_encap;
-		cfg.secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
-		cfg.callback = (lp->flags & ISDN_NET_CALLBACK) ? 1 : 0;
-		cfg.chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
-		cfg.ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
-		cfg.chargeint = lp->chargeint;
-		if (copy_to_user(dest, lp->name, 10)) {
-			restore_flags(flags);
-			return -EFAULT;
-		}
-		dest += 10;
-		if (copy_to_user(dest, (char *) &cfg, sizeof(cfg))) {
-			restore_flags(flags);
-			return -EFAULT;
-		}
-		dest += sizeof(cfg);
-		strcpy(phone.name, lp->name);
-		phone.outgoing = 0;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-			restore_flags(flags);
-			return ret;
-		} else
-			dest += ret;
-		strcpy(phone.name, lp->name);
-		phone.outgoing = 1;
-		if ((ret = isdn_net_getphones(&phone, dest)) < 0) {
-			restore_flags(flags);
-			return ret;
-		} else
-			dest += ret;
-		put_user(0, dest);
-		p = p->next;
-	}
-	restore_flags(flags);
-	return 0;
-}
-#endif
 
 static int
 isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1316,6 +1484,17 @@
 				} else
 					return -EINVAL;
 				break;
+#ifdef CONFIG_NETDEVICES
+			case IIOCNETGPN:
+				/* Get peer phone number of a connected 
+				 * isdn network interface */
+				if (arg) {
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+				} else
+					return -EINVAL;
+#endif
 			default:
 				return -EINVAL;
 		}
@@ -1327,7 +1506,7 @@
 		if (drvidx < 0)
 			return -ENODEV;
 		chidx = isdn_minor2chan(minor);
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
 			return -ENODEV;
 		return 0;
 	}
@@ -1513,26 +1692,11 @@
 				}
 				if (drvidx == -1)
 					return -ENODEV;
-				dev->drv[drvidx]->reject_bus = iocts.arg;
-				return 0;
-#if 0
-			case IIOCGETSET:
-				/* Get complete setup (all network-interfaces and profile-
-				   settings of all tty-devices */
-				if (arg)
-					return (isdn_get_allcfg((char *) arg));
-				else
-					return -EINVAL;
-				break;
-			case IIOCSETSET:
-				/* Set complete setup (all network-interfaces and profile-
-				   settings of all tty-devices */
-				if (arg)
-					return (isdn_set_allcfg((char *) arg));
+				if (iocts.arg)
+					dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
 				else
-					return -EINVAL;
-				break;
-#endif
+					dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
+				return 0;
 			case IIOCSIGPRF:
 				dev->profd = current;
 				return 0;
@@ -1544,7 +1708,7 @@
 					int i;
 
 					if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-					(ISDN_MODEM_ANZREG + ISDN_MSNLEN)
+					(ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN)
 						   * ISDN_MAX_CHANNELS)))
 						return ret;
 
@@ -1556,8 +1720,11 @@
 						if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
 							return -EFAULT;
 						p += ISDN_MSNLEN;
+						if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
+							return -EFAULT;
+						p += ISDN_LMSNLEN;
 					}
-					return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
+					return (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
 				} else
 					return -EINVAL;
 				break;
@@ -1721,7 +1888,6 @@
 	uint minor = MINOR(ino->i_rdev);
 	int drvidx;
 	int chidx;
-	isdn_ctrl c;
 
 	if (minor == ISDN_MINOR_STATUS) {
 		infostruct *p;
@@ -1744,31 +1910,25 @@
 		if (drvidx < 0)
 			return -ENODEV;
 		chidx = isdn_minor2chan(minor);
-		if (!dev->drv[drvidx]->running)
+		if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
 			return -ENODEV;
-		if (!(dev->drv[drvidx]->flags & (1 << chidx)))
+		if (!(dev->drv[drvidx]->online & (1 << chidx)))
 			return -ENODEV;
-		c.command = ISDN_CMD_LOCK;
-		c.driver = drvidx;
-		isdn_command(&c);
-		MOD_INC_USE_COUNT;
+		isdn_MOD_INC_USE_COUNT();
 		return 0;
 	}
 	if (minor <= ISDN_MINOR_CTRLMAX) {
 		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
 		if (drvidx < 0)
 			return -ENODEV;
-		c.command = ISDN_CMD_LOCK;
-		c.driver = drvidx;
-		MOD_INC_USE_COUNT;
-		isdn_command(&c);
+		isdn_MOD_INC_USE_COUNT();
 		return 0;
 	}
 #ifdef CONFIG_ISDN_PPP
 	if (minor <= ISDN_MINOR_PPPMAX) {
 		int ret;
 		if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep)))
-			MOD_INC_USE_COUNT;
+			isdn_MOD_INC_USE_COUNT();
 		return ret;
 	}
 #endif
@@ -1779,13 +1939,12 @@
 isdn_close(struct inode *ino, struct file *filep)
 {
 	uint minor = MINOR(ino->i_rdev);
-	int drvidx;
-	isdn_ctrl c;
 
-	MOD_DEC_USE_COUNT;
 	if (minor == ISDN_MINOR_STATUS) {
 		infostruct *p = dev->infochain;
 		infostruct *q = NULL;
+
+		MOD_DEC_USE_COUNT;
 		while (p) {
 			if (p->private == (char *) &(filep->private_data)) {
 				if (q)
@@ -1801,24 +1960,12 @@
 		printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
 		return 0;
 	}
-	if (minor < ISDN_MINOR_CTRL) {
-		drvidx = isdn_minor2drv(minor);
-		if (drvidx < 0)
-			return 0;
-		c.command = ISDN_CMD_UNLOCK;
-		c.driver = drvidx;
-		isdn_command(&c);
+	isdn_MOD_DEC_USE_COUNT();
+	if (minor < ISDN_MINOR_CTRL)
 		return 0;
-	}
 	if (minor <= ISDN_MINOR_CTRLMAX) {
-		drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-		if (drvidx < 0)
-			return 0;
 		if (dev->profd == current)
 			dev->profd = NULL;
-		c.command = ISDN_CMD_UNLOCK;
-		c.driver = drvidx;
-		isdn_command(&c);
 		return 0;
 	}
 #ifdef CONFIG_ISDN_PPP
@@ -1872,7 +2019,6 @@
 	ulong flags;
 	ulong features;
 	ulong vfeatures;
-	isdn_ctrl cmd;
 
 	save_flags(flags);
 	cli();
@@ -1890,7 +2036,9 @@
 			if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
 			((pre_dev != d) || (pre_chan != dev->chanmap[i])))
 				continue;
-			if ((dev->drv[d]->running)) {
+			if (dev->usage[i] & ISDN_USAGE_DISABLED)
+			        continue; /* usage not allowed */
+			if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
 				if (((dev->drv[d]->interface->features & features) == features) ||
 				    (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
 				     (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
@@ -1898,10 +2046,6 @@
 						dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
 						dev->usage[i] |= usage;
 						isdn_info_update();
-						cmd.driver = d;
-						cmd.arg = 0;
-						cmd.command = ISDN_CMD_LOCK;
-						isdn_command(&cmd);
 						restore_flags(flags);
 						return i;
 					} else {
@@ -1909,10 +2053,6 @@
 							dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
 							dev->usage[i] |= usage;
 							isdn_info_update();
-							cmd.driver = d;
-							cmd.arg = 0;
-							cmd.command = ISDN_CMD_LOCK;
-							isdn_command(&cmd);
 							restore_flags(flags);
 							return i;
 						}
@@ -1932,7 +2072,6 @@
 {
 	int i;
 	ulong flags;
-	isdn_ctrl cmd;
 
 	save_flags(flags);
 	cli();
@@ -1946,12 +2085,6 @@
 			dev->obytes[i] = 0;
 			isdn_info_update();
 			isdn_free_queue(&dev->drv[di]->rpqueue[ch]);
-			cmd.driver = di;
-			cmd.arg = ch;
-			cmd.command = ISDN_CMD_UNLOCK;
-			restore_flags(flags);
-			isdn_command(&cmd);
-			return;
 		}
 	restore_flags(flags);
 }
@@ -1996,7 +2129,6 @@
 		copy_from_user(skb_put(skb, len), buf, len);
 	else
 		memcpy(skb_put(skb, len), buf, len);
-
 	ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
 	if (ret <= 0)
 		dev_kfree_skb(skb);
@@ -2052,19 +2184,233 @@
 	return ret;
 }
 
+int
+register_isdn_module(isdn_module *m) {
+#if 0
+	isdn_module_list **pp = &dev->modules;
+	isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL);
+
+	if (!new) {
+		printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n");
+		return -1;
+	}
+	while (*pp && (*pp)->orig != m)
+		pp = &(*pp)->next;
+	if (*pp != NULL) {
+		printk(KERN_WARNING "isdn: Module %s already registered\n", m->name);
+		return -1;
+	}
+	while (*pp && ((*pp)->module.priority < m->priority))
+		pp = &(*pp)->next;
+	new->next = *pp;
+	new->orig = m;
+	new->module = *m;
+ 
+	*pp = new;
+#endif
+	return 0;
+}
+
+int
+unregister_isdn_module(isdn_module *m) {
+#if 0
+	isdn_module_list **pp = &dev->modules;
+
+	while (*pp && *pp != m)
+		pp = &(*pp)->next;
+	if (*pp == NULL) {
+		printk(KERN_WARNING "isdn: Module %s not found\n", m->name);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+int
+isdn_add_channels(driver *d, int drvidx, int n, int adding)
+{
+	int j, k, m;
+	ulong flags;
+
+#ifdef COMPAT_HAS_NEW_WAITQ
+	init_waitqueue_head(&d->st_waitq);
+#endif
+	if (d->flags & DRV_FLAG_RUNNING)
+		return -1;
+       	if (n < 1) return 0;
+
+	m = (adding) ? d->channels + n : n;
+
+	if (dev->channels + n > ISDN_MAX_CHANNELS) {
+		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
+		       ISDN_MAX_CHANNELS);
+		return -1;
+	}
+
+	if ((adding) && (d->rcverr))
+		kfree(d->rcverr);
+	if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
+		return -1;
+	}
+	memset((char *) d->rcverr, 0, sizeof(int) * m);
+
+	if ((adding) && (d->rcvcount))
+		kfree(d->rcvcount);
+	if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
+		if (!adding) kfree(d->rcverr);
+		return -1;
+	}
+	memset((char *) d->rcvcount, 0, sizeof(int) * m);
+
+	if ((adding) && (d->rpqueue)) {
+		for (j = 0; j < d->channels; j++)
+			isdn_free_queue(&d->rpqueue[j]);
+		kfree(d->rpqueue);
+	}
+	if (!(d->rpqueue =
+	      (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
+		if (!adding) {
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1; 
+	}
+	for (j = 0; j < m; j++) {
+		skb_queue_head_init(&d->rpqueue[j]);
+	}
+
+	if ((adding) && (d->rcv_waitq))
+		kfree(d->rcv_waitq);
+#ifdef COMPAT_HAS_NEW_WAITQ
+	d->rcv_waitq = (wait_queue_head_t *)
+		kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
+	if (!d->rcv_waitq) {
+#else
+	if (!(d->rcv_waitq = (struct wait_queue **)
+	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
+#endif
+		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
+		if (!adding) {
+			kfree(d->rpqueue);
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1;
+	}
+#ifdef COMPAT_HAS_NEW_WAITQ
+	d->snd_waitq = d->rcv_waitq + m;
+	for (j = 0; j < m; j++) {
+		init_waitqueue_head(&d->rcv_waitq[m]);
+		init_waitqueue_head(&d->snd_waitq[m]);
+	}
+#else
+	memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m);
+
+	if ((adding) && (d->snd_waitq))
+		kfree(d->snd_waitq);
+	if (!(d->snd_waitq = (struct wait_queue **)
+	      kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) {
+		printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
+		if (!adding) {
+			kfree(d->rcv_waitq);
+			kfree(d->rpqueue);
+			kfree(d->rcvcount);
+			kfree(d->rcverr);
+		}
+		return -1;
+	}
+	memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m);
+#endif
+
+	dev->channels += n;
+	save_flags(flags);
+	cli();
+	for (j = d->channels; j < m; j++)
+		for (k = 0; k < ISDN_MAX_CHANNELS; k++)
+			if (dev->chanmap[k] < 0) {
+				dev->chanmap[k] = j;
+				dev->drvmap[k] = drvidx;
+				break;
+			}
+	restore_flags(flags);
+	d->channels = m;
+	return 0;
+}
+
 /*
  * Low-level-driver registration
  */
 
+
+#ifdef CONFIG_ISDN_DIVERSION
+extern isdn_divert_if *divert_if;
+
+static char *map_drvname(int di)
+{
+  if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) 
+    return(NULL);
+  return(dev->drvid[di]); /* driver name */
+} /* map_drvname */
+
+static int map_namedrv(char *id)
+{  int i;
+
+   for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+    { if (!strcmp(dev->drvid[i],id)) 
+        return(i);
+    }
+   return(-1);
+} /* map_namedrv */
+
+int DIVERT_REG_NAME(isdn_divert_if *i_div)
+{
+  if (i_div->if_magic != DIVERT_IF_MAGIC) 
+    return(DIVERT_VER_ERR);
+  switch (i_div->cmd)
+    {
+      case DIVERT_CMD_REL:
+        if (divert_if != i_div) 
+          return(DIVERT_REL_ERR);
+        divert_if = NULL; /* free interface */
+        MOD_DEC_USE_COUNT;
+        return(DIVERT_NO_ERR);
+
+      case DIVERT_CMD_REG:
+        if (divert_if) 
+          return(DIVERT_REG_ERR);
+        i_div->ll_cmd = isdn_command; /* set command function */
+        i_div->drv_to_name = map_drvname; 
+        i_div->name_to_drv = map_namedrv; 
+        MOD_INC_USE_COUNT;
+        divert_if = i_div; /* remember interface */
+        return(DIVERT_NO_ERR);
+
+      default:
+        return(DIVERT_CMD_ERR);   
+    }
+} /* DIVERT_REG_NAME */
+
+EXPORT_SYMBOL(DIVERT_REG_NAME);
+
+#endif CONFIG_ISDN_DIVERSION
+
+
 EXPORT_SYMBOL(register_isdn);
+EXPORT_SYMBOL(register_isdn_module);
+EXPORT_SYMBOL(unregister_isdn_module);
+#ifdef CONFIG_ISDN_PPP
+EXPORT_SYMBOL(isdn_ppp_register_compressor);
+EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
+#endif
 
 int
 register_isdn(isdn_if * i)
 {
 	driver *d;
-	int n,
-	 j,
-	 k;
+	int j;
 	ulong flags;
 	int drvidx;
 
@@ -2073,12 +2419,6 @@
 		       ISDN_MAX_DRIVERS);
 		return 0;
 	}
-	n = i->channels;
-	if (dev->channels + n > ISDN_MAX_CHANNELS) {
-		printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
-		       ISDN_MAX_CHANNELS);
-		return 0;
-	}
 	if (!i->writebuf_skb) {
 		printk(KERN_WARNING "register_isdn: No write routine given.\n");
 		return 0;
@@ -2088,64 +2428,22 @@
 		return 0;
 	}
 	memset((char *) d, 0, sizeof(driver));
-	if (!(d->rcverr = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
-		kfree(d);
-		return 0;
-	}
-	memset((char *) d->rcverr, 0, sizeof(int) * n);
-	if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	memset((char *) d->rcvcount, 0, sizeof(int) * n);
-	if (!(d->rpqueue =
-	      (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
-		kfree(d->rcvcount);
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	for (j = 0; j < n; j++) {
-		skb_queue_head_init(&d->rpqueue[j]);
-	}
-	if (!(d->rcv_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
-		kfree(d->rpqueue);
-		kfree(d->rcvcount);
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * n);
-	if (!(d->snd_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
-		kfree(d->rcv_waitq);
-		kfree(d->rpqueue);
-		kfree(d->rcvcount);
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
-	}
-	memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * n);
-	d->channels = n;
-	d->loaded = 1;
+
 	d->maxbufsize = i->maxbufsize;
 	d->pktcount = 0;
 	d->stavail = 0;
-	d->running = 0;
-	d->flags = 0;
+	d->flags = DRV_FLAG_LOADED;
+	d->online = 0;
 	d->interface = i;
+	d->channels = 0;
 	for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
 		if (!dev->drv[drvidx])
 			break;
+	if (isdn_add_channels(d, drvidx, i->channels, 0)) {
+		kfree(d);
+		return 0;
+	}
 	i->channels = drvidx;
-
 	i->rcvcallb_skb = isdn_receive_skb_callback;
 	i->statcallb = isdn_status_callback;
 	if (!strlen(i->id))
@@ -2155,15 +2453,7 @@
 	for (j = 0; j < drvidx; j++)
 		if (!strcmp(i->id, dev->drvid[j]))
 			sprintf(i->id, "line%d", drvidx);
-	for (j = 0; j < n; j++)
-		for (k = 0; k < ISDN_MAX_CHANNELS; k++)
-			if (dev->chanmap[k] < 0) {
-				dev->chanmap[k] = j;
-				dev->drvmap[k] = drvidx;
-				break;
-			}
 	dev->drv[drvidx] = d;
-	dev->channels += n;
 	strcpy(dev->drvid[drvidx], i->id);
 	isdn_info_update();
 	dev->drivers++;
@@ -2215,12 +2505,21 @@
 	memset((char *) dev, 0, sizeof(isdn_dev));
 	init_timer(&dev->timer);
 	dev->timer.function = isdn_timer_funct;
+#ifdef COMPAT_HAS_NEW_WAITQ
+	init_MUTEX(&dev->sem);
+	init_waitqueue_head(&dev->info_waitq);
+#else
 	dev->sem = MUTEX;
+#endif
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		dev->drvmap[i] = -1;
 		dev->chanmap[i] = -1;
 		dev->m_idx[i] = -1;
 		strcpy(dev->num[i], "???");
+#ifdef COMPAT_HAS_NEW_WAITQ
+		init_waitqueue_head(&dev->mdm.info[i].open_wait);
+		init_waitqueue_head(&dev->mdm.info[i].close_wait);
+#endif
 	}
 	if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
 		printk(KERN_WARNING "isdn: Could not register control devices\n");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_common.h linux.pre11.3/drivers/isdn/isdn_common.h
--- linux.vanilla/drivers/isdn/isdn_common.h	Sun Jan 24 19:55:34 1999
+++ linux.pre11.3/drivers/isdn/isdn_common.h	Mon Jul 19 23:59:35 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_common.h,v 1.9 1998/02/20 17:19:01 fritz Exp $
+/* $Id: isdn_common.h,v 1.16 1999/07/01 08:29:54 keil Exp $
 
  * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
@@ -20,11 +20,39 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
  * $Log: isdn_common.h,v $
+ * Revision 1.16  1999/07/01 08:29:54  keil
+ * compatibility to 2.3 kernel
+ *
+ * Revision 1.15  1999/04/18 14:06:50  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.14  1999/04/12 12:33:18  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.13  1999/03/02 12:04:47  armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.12  1998/06/26 15:12:27  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.11  1998/04/14 16:28:47  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.10  1998/03/07 18:21:03  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
  * Revision 1.9  1998/02/20 17:19:01  fritz
  * Added common stub for sending commands to lowlevel.
  *
@@ -90,10 +118,16 @@
 extern void isdn_timer_ctrl(int tf, int onoff);
 extern void isdn_unexclusive_channel(int di, int ch);
 extern int isdn_getnum(char **);
+#ifdef COMPAT_HAS_NEW_WAITQ
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
+#else
 extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
+#endif
 extern int isdn_get_free_channel(int, int, int, int, int);
 extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int register_isdn(isdn_if * i);
+extern int isdn_wildmat(char *, char *);
+extern int isdn_add_channels(driver *, int, int, int);
 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
 extern void isdn_dumppkt(char *, u_char *, int, int);
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_concap.c linux.pre11.3/drivers/isdn/isdn_concap.c
--- linux.vanilla/drivers/isdn/isdn_concap.c	Sun Nov  8 15:08:10 1998
+++ linux.pre11.3/drivers/isdn/isdn_concap.c	Mon Jul 19 23:59:35 1999
@@ -1,10 +1,21 @@
-/* $Id: isdn_concap.c,v 1.2 1998/01/31 22:49:21 keil Exp $
+/* $Id: isdn_concap.c,v 1.5 1998/10/30 18:44:48 he Exp $
  
  * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
  * stuff goes here. Stuff that depends only on the concap protocol goes to
  * another -- protocol specific -- source file.
  *
  * $Log: isdn_concap.c,v $
+ * Revision 1.5  1998/10/30 18:44:48  he
+ * pass return value from isdn_net_dial_req for dialmode change
+ *
+ * Revision 1.4  1998/10/30 17:55:24  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.3  1998/05/26 22:39:22  he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
  * Revision 1.2  1998/01/31 22:49:21  keil
  * correct comments
  *
@@ -20,14 +31,9 @@
 #include <linux/concap.h>
 #include "isdn_concap.h"
 
-/* The declaration of this (or a plublic variant thereof) should really go
-   in linux/isdn.h. But we really need it here (and isdn_ppp, like us, also
-   refers to that private function currently owned by isdn_net.c) */
-extern int isdn_net_force_dial_lp(isdn_net_local *);
-
 
 /* The following set of device service operations are for encapsulation
-   protocols that require for reliable datalink sematics. That means:
+   protocols that require for reliable datalink semantics. That means:
 
    - before any data is to be submitted the connection must explicitly
      be set up.
@@ -66,9 +72,9 @@
 	IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name);
 
 	/* dial ... */
-	ret = isdn_net_force_dial_lp( lp );
+	ret = isdn_net_dial_req( lp );
 	if ( ret ) IX25DEBUG("dialing failed\n");
-	return 0;
+	return ret;
 }
 
 int isdn_concap_dl_disconn_req(struct concap_proto *concap)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_net.c linux.pre11.3/drivers/isdn/isdn_net.c
--- linux.vanilla/drivers/isdn/isdn_net.c	Sun Jan 24 19:55:34 1999
+++ linux.pre11.3/drivers/isdn/isdn_net.c	Mon Jul 19 23:59:35 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_net.c,v 1.55 1998/02/23 19:38:22 fritz Exp $
+/* $Id: isdn_net.c,v 1.88 1999/07/07 10:13:31 detabc Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
@@ -20,11 +20,105 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
  * $Log: isdn_net.c,v $
+ * Revision 1.88  1999/07/07 10:13:31  detabc
+ * remove unused messages
+ *
+ * Revision 1.87  1999/07/06 07:53:53  calle
+ * calls to dev_alloc_skb waste 16 bytes of memory, if we calculate the
+ * right header space for the lowlevel driver. using alloc_skb instead.
+ *
+ * Revision 1.86  1999/06/09 10:12:05  paul
+ * thinko in previous patch
+ *
+ * Revision 1.85  1999/06/07 19:42:39  paul
+ * isdn_net_getpeer() fixed to return correct `outgoing' flag
+ *
+ * Revision 1.84  1999/04/18 14:06:55  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.83  1999/04/12 12:33:23  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.82  1999/01/17 00:55:58  he
+ * added mark_bh in BCONN statcallb and cleaned up some dead code
+ *
+ * Revision 1.81  1999/01/15 16:36:52  he
+ * replaced icmp_send() by dst_link_failure()
+ *
+ * Revision 1.80  1998/12/01 13:06:22  paul
+ * Also huptimeout with dialmode == manual
+ *
+ * Revision 1.79  1998/10/30 17:55:27  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.78  1998/10/26 18:20:46  he
+ * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up
+ * on incoming call not matching the first interface)
+ *
+ * Revision 1.77  1998/10/23 10:18:44  paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.76  1998/09/07 22:00:05  he
+ * flush method for 2.1.118 and above
+ * updated IIOCTLNETGPN
+ *
+ * Revision 1.75  1998/08/31 21:09:50  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
+ * Revision 1.74  1998/07/30 11:28:32  paul
+ * printk message only appeared when status is off and interface is rawIP,
+ * which is confusing for people who don't know about "isdnctrl status <if> on".
+ *
+ * Revision 1.73  1998/06/26 22:01:37  keil
+ * tx_queue_len = 5 was too small
+ *
+ * Revision 1.72  1998/06/26 15:12:31  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.71  1998/06/18 22:43:08  fritz
+ * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at cleanup.
+ *
+ * Revision 1.70  1998/06/17 19:50:49  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.69  1998/06/09 12:27:37  cal
+ * Changed default of local netdev flags: ISDN_NET_STOPPED is default now,
+ * so autodial is suppressed for that device until it is switched on using
+ * 'isdnctrl status dev-name on'.
+ *
+ *
+ *
+ * Revision 1.66  1998/05/26 22:39:24  he
+ * sync'ed with 2.1.102 where appropriate (CAPABILITY changes)
+ * concap typo
+ * cleared dev.tbusy in isdn_net BCONN status callback
+ *
+ * Revision 1.61  1998/04/16 19:19:42  keil
+ * Fix from vger (tx max qlength)
+ *
+ * Revision 1.60  1998/04/14 16:28:49  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.59  1998/03/07 22:37:33  fritz
+ * Bugfix: restore_flags missing.
+ *
+ * Revision 1.58  1998/03/07 18:21:05  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.57  1998/02/25 18:31:13  fritz
+ * Added debugging output in adjust_header.
+ *
+ * Revision 1.56  1998/02/25 17:49:42  he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
  * Revision 1.55  1998/02/23 19:38:22  fritz
  * Corrected check for modified feature-flags.
  *
@@ -248,9 +342,7 @@
 #include <linux/isdn.h>
 #include <net/arp.h>
 #include <net/dst.h>
-#ifndef DEV_NUMBUFFS
 #include <net/pkt_sched.h>
-#endif
 #include <linux/inetdevice.h>
 #include "isdn_common.h"
 #include "isdn_net.h"
@@ -265,14 +357,10 @@
 /* Prototypes */
 
 int isdn_net_force_dial_lp(isdn_net_local *);
-static int isdn_net_wildmat(char *s, char *p);
 static int isdn_net_start_xmit(struct sk_buff *, struct device *);
 static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
-#ifdef DEV_NUMBUFFS
-static void dev_purge_queues(struct device *dev);	/* move this to net/core/dev.c */
-#endif
 
-char *isdn_net_revision = "$Revision: 1.55 $";
+char *isdn_net_revision = "$Revision: 1.88 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -293,16 +381,21 @@
 		
 		dst_link_failure(skb);
 	}
+	else {  /* dial not triggered by rawIP packet */
+		printk(KERN_DEBUG "isdn_net: %s: %s\n",
+			   dev->name,
+			   (reason != NULL) ? reason : "reason unknown");
+	}
 }
 
 static void
 isdn_net_reset(struct device *dev)
 {
 #ifdef CONFIG_ISDN_X25
-	struct concap_device_ops * dops = 
+	struct concap_device_ops * dops =
 		( (isdn_net_local *) dev->priv ) -> dops;
-	struct concap_proto * cprot = 
-		( (isdn_net_local *) dev->priv ) -> netdev -> cprot; 
+	struct concap_proto * cprot =
+		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
 #endif
 	ulong flags;
 
@@ -311,7 +404,7 @@
 	dev->interrupt = 0;
 	dev->tbusy = 0;
 #ifdef CONFIG_ISDN_X25
-	if( cprot && cprot -> pops && dops ) 
+	if( cprot && cprot -> pops && dops )
 		cprot -> pops -> restart ( cprot, dev, dops );
 #endif
 	restore_flags(flags);
@@ -338,7 +431,7 @@
 		if (ifa != NULL)
 			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
 	}
- 
+
 	/* If this interface has slaves, start them also */
 
 	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
@@ -362,6 +455,7 @@
 
 	save_flags(flags);
 	cli();
+	lp->flags |= ISDN_NET_CONNECTED;
 	lp->isdn_device = dev->drvmap[idx];
 	lp->isdn_channel = dev->chanmap[idx];
 	dev->rx_netdev[idx] = lp->netdev;
@@ -387,10 +481,6 @@
 		dev_kfree_skb(lp->sav_skb);
 		lp->sav_skb = NULL;
 	}
-#ifdef DEV_NUMBUFFS
-	if (!lp->master)        /* purge only for master device */
-		dev_purge_queues(&lp->netdev->dev);
-#else
 	if (!lp->master) {	/* reset only master device */
 		/* Moral equivalent of dev_purge_queues():
 		   BEWARE! This chunk of code cannot be called from hardware
@@ -398,7 +488,6 @@
 		 */
 		qdisc_reset(lp->netdev->dev.qdisc);
 	}
-#endif
 	lp->dialstate = 0;
 	dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
 	dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
@@ -444,7 +533,13 @@
 		if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
 			anymore = 1;
 			l->huptimer++;
-			if ((l->onhtime) && (l->huptimer > l->onhtime)) {
+			/*
+			 * if there is some dialmode where timeout-hangup
+			 * should _not_ be done, check for that here
+			 */
+			if ((l->onhtime) &&
+			    (l->huptimer > l->onhtime))
+			{
 				if (l->hupflags & ISDN_MANCHARGE &&
 				    l->hupflags & ISDN_CHARGEHUP) {
 					while (jiffies - l->chargetime > l->chargeint)
@@ -469,6 +564,11 @@
 				} else if (l->hupflags & ISDN_INHUP)
 					isdn_net_hangup(&p->dev);
 			}
+
+			if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
+				isdn_net_hangup(&p->dev);
+				break;
+			}
 		}
 		p = (isdn_net_dev *) p->next;
 	}
@@ -487,7 +587,7 @@
 {
 	isdn_net_dev *p = dev->st_netdev[idx];
 	int cmd = c->command;
-	
+
 	if (p) {
 		isdn_net_local *lp = p->local;
 #ifdef CONFIG_ISDN_X25
@@ -538,23 +638,12 @@
 				   failed. If there are generic encap protocol
 				   receiver routines signal the closure of
 				   the link*/
-				
-				if( !(lp->flags & ISDN_NET_CONNECTED) 
+
+				if( !(lp->flags & ISDN_NET_CONNECTED)
 				    && pops && pops -> disconn_ind )
 					pops -> disconn_ind(cprot);
 #endif /* CONFIG_ISDN_X25 */
 				if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
-					lp->flags &= ~ISDN_NET_CONNECTED;
-					if (lp->first_skb) {
-						dev_kfree_skb(lp->first_skb);
-						lp->first_skb = NULL;
-					}
-					if (lp->sav_skb) {
-						dev_kfree_skb(lp->sav_skb);
-						lp->sav_skb = NULL;
-					}
-					isdn_free_channel(lp->isdn_device, lp->isdn_channel,
-							  ISDN_USAGE_NET);
 #ifdef CONFIG_ISDN_PPP
 					isdn_ppp_free(lp);
 #endif
@@ -562,10 +651,7 @@
 					printk(KERN_INFO "%s: remote hangup\n", lp->name);
 					printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
 					       lp->charge);
-					lp->isdn_device = -1;
-					lp->isdn_channel = -1;
-					dev->st_netdev[idx] = NULL;
-					dev->rx_netdev[idx] = NULL;
+					isdn_net_unbind_channel(lp);
 					return 1;
 				}
 				break;
@@ -607,6 +693,11 @@
 						lp->chargetime = jiffies;
 						printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
 						lp->name, lp->chargetime);
+
+						/* reset dial-timeout */
+						lp->dialstarted = 0;
+						lp->dialwait_timer = 0;
+
 						/* Immediately send first skb to speed up arp */
 #ifdef CONFIG_ISDN_PPP
 						if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
@@ -617,13 +708,13 @@
 						if( pops )
 							if( pops->connect_ind)
 								pops->connect_ind(cprot);
-
 #endif /* CONFIG_ISDN_X25 */
 						if (lp->first_skb) {
-							
+
 							if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
 								lp->first_skb = NULL;
-						} else {
+						}
+						else {
 							/*
 							 * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
 							 * With an empty lp->first_skb, we need to do this ourselves
@@ -721,6 +812,13 @@
 					break;
 				}
 				anymore = 1;
+
+				if(lp->dialtimeout > 0)
+					if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
+						lp->dialstarted = jiffies;
+						lp->dialwait_timer = 0;
+					}
+
 				lp->dialstate++;
 				/* Fall through */
 			case 2:
@@ -735,12 +833,22 @@
 				lp->dialretry = 0;
 				anymore = 1;
 				lp->dialstate++;
-				/* Falls through */
+				/* Fall through */
 			case 3:
 				/* Setup interface, dial current phone-number, switch to next number.
 				 * If list of phone-numbers is exhausted, increment
 				 * retry-counter.
 				 */
+				if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
+					char *s;
+					if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+						s = "dial suppressed: isdn system stopped";
+					else
+						s = "dial suppressed: dialmode `off'";
+					isdn_net_unreachable(&p->dev, lp->first_skb, s);
+					isdn_net_hangup(&p->dev);
+					break;
+				}
 				cmd.driver = lp->isdn_device;
 				cmd.command = ISDN_CMD_SETL2;
 				cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
@@ -765,6 +873,16 @@
 					lp->dialstate = 4;
 					printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
 				} else {
+					if(lp->dialtimeout > 0)
+						if(jiffies > (lp->dialstarted + lp->dialtimeout)) {
+							restore_flags(flags);
+							lp->dialwait_timer = jiffies + lp->dialwait;
+							lp->dialstarted = 0;
+							isdn_net_unreachable(&p->dev, lp->first_skb, "dial: timed out");
+							isdn_net_hangup(&p->dev);
+							break;
+						}
+
 					sprintf(cmd.parm.setup.phone, "%s", lp->dial->num);
 					/*
 					 * Switch to next number or back to start if at end of list.
@@ -772,6 +890,17 @@
 					if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
 						lp->dial = lp->phone[1];
 						lp->dialretry++;
+
+						if (lp->dialretry > lp->dialmax) {
+							restore_flags(flags);
+							if (lp->dialtimeout == 0) {
+								lp->dialwait_timer = jiffies + lp->dialwait;
+								lp->dialstarted = 0;
+								isdn_net_unreachable(&p->dev, lp->first_skb, "dial: tried all numbers dialmax times");
+							}
+							isdn_net_hangup(&p->dev);
+							break;
+						}
 					}
 					restore_flags(flags);
 					cmd.driver = lp->isdn_device;
@@ -786,7 +915,7 @@
 						isdn_info_update();
 					}
 					printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
-					       lp->dialretry - 1, cmd.parm.setup.phone);
+					       lp->dialretry, cmd.parm.setup.phone);
 					lp->dtimer = 0;
 #ifdef ISDN_DEBUG_NET_DIAL
 					printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
@@ -810,15 +939,11 @@
 				break;
 			case 4:
 				/* Wait for D-Channel-connect.
-				 * If timeout and max retries not
-				 * reached, switch back to state 3.
+				 * If timeout, switch back to state 3.
+				 * Dialmax-handling moved to state 3.
 				 */
-				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) {
-					if (lp->dialretry < lp->dialmax) {
-						lp->dialstate = 3;
-					} else
-						isdn_net_hangup(&p->dev);
-				}
+				if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
+					lp->dialstate = 3;
 				anymore = 1;
 				break;
 			case 5:
@@ -895,7 +1020,8 @@
 				/* Remote does callback. Hangup after cbdelay, then wait for incoming
 				 * call (in state 4).
 				 */
-				if (lp->dtimer++ > lp->cbdelay) {
+				if (lp->dtimer++ > lp->cbdelay)
+				{
 					printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
 					lp->dtimer = 0;
 					lp->dialstate = 4;
@@ -930,7 +1056,6 @@
 #endif
 
 	if (lp->flags & ISDN_NET_CONNECTED) {
-		lp->flags &= ~ISDN_NET_CONNECTED;
 		printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
 #ifdef CONFIG_ISDN_PPP
 		isdn_ppp_free(lp);
@@ -938,7 +1063,7 @@
 #ifdef CONFIG_ISDN_X25
 		/* try if there are generic encap protocol
 		   receiver routines and signal the closure of
-		   the link */		
+		   the link */
 		if( pops && pops -> disconn_ind )
 		  pops -> disconn_ind(cprot);
 #endif /* CONFIG_ISDN_X25 */
@@ -968,7 +1093,7 @@
 	char addinfo[100];
 
 	addinfo[0] = '\0';
-	/* This check stolen from 2.1.72 dev_queue_xmit_nit() */ 
+	/* This check stolen from 2.1.72 dev_queue_xmit_nit() */
 	if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) {
 		/* fall back to old isdn_net_log_packet method() */
 		char * buf = skb->data;
@@ -1062,20 +1187,17 @@
 	if (ret == len) {
 		lp->transcount += len;
 		clear_bit(0, (void *) &(ndev->tbusy));
-		mark_bh(NET_BH);
 		return 0;
 	}
 	if (ret < 0) {
 		dev_kfree_skb(skb);
 		lp->stats.tx_errors++;
 		clear_bit(0, (void *) &(ndev->tbusy));
-		mark_bh(NET_BH);
 		return 0;
 	}
 	return 1;
 }
 
-
 /*
  *  Helper function for isdn_net_start_xmit.
  *  When called, the connection is already established.
@@ -1150,9 +1272,11 @@
 	if (!skb)
 		return;
 	if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
-		ulong pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
-		if (pullsize)
+		int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
+		if (pullsize > 0) {
+			printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
 			skb_pull(skb, pullsize);
+		}
 	}
 }
 
@@ -1166,7 +1290,7 @@
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 #ifdef CONFIG_ISDN_X25
-	struct concap_proto * cprot = lp -> netdev -> cprot; 
+	struct concap_proto * cprot = lp -> netdev -> cprot;
 #endif
 
 	if (ndev->tbusy) {
@@ -1179,7 +1303,7 @@
 	ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
 #ifdef CONFIG_ISDN_X25
 /* At this point hard_start_xmit() passes control to the encapsulation
-   protocol (if present). 
+   protocol (if present).
    For X.25 auto-dialing is completly bypassed because:
    - It does not conform with the semantics of a reliable datalink
      service as needed by X.25 PLP.
@@ -1205,17 +1329,46 @@
 #endif
 		if (!(lp->flags & ISDN_NET_CONNECTED)) {
 			int chi;
+			/* only do autodial if allowed by config */
+			if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
+				isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
+				dev_kfree_skb(skb);
+				ndev->tbusy = 0;
+				return 0;
+			}
 			if (lp->phone[1]) {
 				ulong flags;
 				save_flags(flags);
 				cli();
+
+				if(lp->dialwait_timer <= 0)
+					if(lp->dialstarted > 0 && lp->dialtimeout > 0 && jiffies < lp->dialstarted + lp->dialtimeout + lp->dialwait)
+						lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
+
+				if(lp->dialwait_timer > 0) {
+					if(jiffies < lp->dialwait_timer) {
+						isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
+						dev_kfree_skb(skb);
+						ndev->tbusy = 0;
+						restore_flags(flags);
+						return 0;
+					} else
+						lp->dialwait_timer = 0;
+				}
+
 				/* Grab a free ISDN-Channel */
-				if ((chi =
+				if (((chi =
 				     isdn_get_free_channel(ISDN_USAGE_NET,
 							   lp->l2_proto,
 							   lp->l3_proto,
 							   lp->pre_device,
-						 lp->pre_channel)) < 0) {
+						 lp->pre_channel)) < 0) &&
+					((chi =
+				     isdn_get_free_channel(ISDN_USAGE_NET,
+							   lp->l2_proto,
+							   lp->l3_proto,
+							   lp->pre_device,
+						 lp->pre_channel^1)) < 0)) {
 					restore_flags(flags);
 					isdn_net_unreachable(ndev, skb,
 							   "No channel");
@@ -1227,7 +1380,6 @@
 				if (dev->net_verbose)
 					isdn_net_log_skb(skb, lp);
 				lp->dialstate = 1;
-				lp->flags |= ISDN_NET_CONNECTED;
 				/* Connect interface with channel */
 				isdn_net_bind_channel(lp, chi);
 #ifdef CONFIG_ISDN_PPP
@@ -1290,8 +1442,8 @@
 {
 	struct device *p;
 #ifdef CONFIG_ISDN_X25
-	struct concap_proto * cprot = 
-		( (isdn_net_local *) dev->priv ) -> netdev -> cprot; 
+	struct concap_proto * cprot =
+		( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
 	/* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
 #endif
 
@@ -1304,9 +1456,9 @@
 		/* If this interface has slaves, stop them also */
 		while (p) {
 #ifdef CONFIG_ISDN_X25
-			cprot = ( (isdn_net_local *) p->priv ) 
-				-> netdev -> cprot; 
-			if( cprot && cprot -> pops ) 
+			cprot = ( (isdn_net_local *) p->priv )
+				-> netdev -> cprot;
+			if( cprot && cprot -> pops )
 				cprot -> pops -> close( cprot );
 #endif
 			isdn_net_hangup(p);
@@ -1387,12 +1539,12 @@
 isdn_net_slarp_send(isdn_net_local *lp, int is_reply)
 {
 	unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
-	struct sk_buff *skb = dev_alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp));
+	struct sk_buff *skb = alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp), GFP_ATOMIC);
 	unsigned long t = (jiffies / HZ * 1000000);
 	int len;
 	cisco_hdr *ch;
 	cisco_slarp *s;
-	
+
 	if (!skb) {
 		printk(KERN_WARNING
 		       "%s: Could not allocate SLARP reply\n", lp->name);
@@ -1406,7 +1558,7 @@
 	s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp));
 	if (is_reply) {
 		s->code = htonl(CISCO_SLARP_REPLY);
- 		memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
+		memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32));
 		memset(&s->slarp.reply.netmask, 0, sizeof(__u32));
 	} else {
 		lp->cisco_myseq++;
@@ -1589,7 +1741,7 @@
 		default:
 #ifdef CONFIG_ISDN_X25
 		  /* try if there are generic sync_device receiver routines */
-			if(cprot) if(cprot -> pops) 
+			if(cprot) if(cprot -> pops)
 				if( cprot -> pops -> data_ind){
 					cprot -> pops -> data_ind(cprot,skb);
 					return;
@@ -1600,6 +1752,7 @@
 			kfree_skb(skb);
 			return;
 	}
+
 	netif_rx(skb);
 	return;
 }
@@ -1788,16 +1941,12 @@
 	ndev->type = ARPHRD_ETHER;
 	ndev->addr_len = ETH_ALEN;
 
-	ndev->tx_queue_len = 10; /* for clients without MPPP 5 is better.  */
+	/* for clients with MPPP maybe higher values better */
+	ndev->tx_queue_len = 30;
 
 	for (i = 0; i < ETH_ALEN; i++)
 		ndev->broadcast[i] = 0xff;
 
-#ifdef DEV_NUMBUFFS
-	for (i = 0; i < DEV_NUMBUFFS; i++)
-		skb_queue_head_init(&ndev->buffs[i]);
-#endif
-
 	/* The ISDN-specific entries in the device structure. */
 	ndev->open = &isdn_net_open;
 	ndev->hard_start_xmit = &isdn_net_start_xmit;
@@ -1813,86 +1962,15 @@
 				max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
 
 	ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
-
 	ndev->stop = &isdn_net_close;
 	ndev->get_stats = &isdn_net_get_stats;
 	ndev->rebuild_header = &isdn_net_rebuild_header;
-
 #ifdef CONFIG_ISDN_PPP
 	ndev->do_ioctl = isdn_ppp_dev_ioctl;
 #endif
 	return 0;
 }
 
-/*
- * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
- * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
- */
-
-static int
-isdn_net_Star(char *s, char *p)
-{
-	while (isdn_net_wildmat(s, p) == 0)
-		if (*++s == '\0')
-			return (0);
-	return (1);
-}
-
-/*
- * Shell-type Pattern-matching for incoming caller-Ids
- * This function gets a string in s and checks, if it matches the pattern
- * given in p. It returns 1 on success, 0 otherwise.
- *
- * Possible Patterns:
- *
- * '?'     matches one character
- * '*'     matches zero or more characters
- * [xyz]   matches the set of characters in brackets.
- * [^xyz]  matches any single character not in the set of characters
- */
-
-static int
-isdn_net_wildmat(char *s, char *p)
-{
-	register int last;
-	register int matched;
-	register int reverse;
-
-	for (; *p; s++, p++)
-		switch (*p) {
-			case '\\':
-				/*
-				 * Literal match with following character,
-				 * fall through.
-				 */
-				p++;
-			default:
-				if (*s != *p)
-					return (0);
-				continue;
-			case '?':
-				/* Match anything. */
-				if (*s == '\0')
-					return (0);
-				continue;
-			case '*':
-				/* Trailing star matches everything. */
-				return (*++p ? isdn_net_Star(s, p) : 1);
-			case '[':
-				/* [^....] means inverse character class. */
-				if ((reverse = (p[1] == '^')))
-					p++;
-				for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
-					/* This next line requires a good C compiler. */
-					if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
-						matched = 1;
-				if (matched == reverse)
-					return (0);
-				continue;
-		}
-	return (*s == '\0');
-}
-
 static void
 isdn_net_swapbind(int drvidx)
 {
@@ -1945,6 +2023,8 @@
  *               2 = Reject call, wait cbdelay, then call back
  *               3 = Reject call
  *               4 = Wait cbdelay, then call back
+ *               5 = No appropriate interface for this call,
+ *                   would eventually match if CID was longer.
  */
 int
 isdn_net_find_icall(int di, int ch, int idx, setup_parm setup)
@@ -1953,6 +2033,7 @@
 	int si1;
 	int si2;
 	int ematch;
+	int wret;
 	int swapped;
 	int sidx = 0;
 	isdn_net_dev *p;
@@ -1987,13 +2068,13 @@
 	}
 	n = (isdn_net_phone *) 0;
 	p = dev->netdev;
-	ematch = 0;
+	ematch = wret = swapped = 0;
 #ifdef ISDN_DEBUG_NET_ICALL
 	printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
 	       dev->usage[idx]);
 #endif
-	swapped = 0;
 	while (p) {
+		int matchret;
 		isdn_net_local *lp = p->local;
 
 		/* If last check has triggered as binding-swap, revert it */
@@ -2006,18 +2087,22 @@
 				break;
 		}
 		swapped = 0;
-		if (!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz))
+		if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di))))
 			ematch = 1;
+		/* Remember if more numbers eventually can match */
+		if (matchret > wret)
+			wret = matchret;
 #ifdef ISDN_DEBUG_NET_ICALL
 		printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
 		       lp->name, lp->msn, lp->flags, lp->dialstate);
 #endif
-		if ((!strcmp(isdn_map_eaz2msn(lp->msn, di), eaz)) &&	/* EAZ is matching   */
-		    (((!(lp->flags & ISDN_NET_CONNECTED)) &&	/* but not connected */
-		      (USG_NONE(dev->usage[idx]))) ||	/* and ch. unused or */
-		     ((((lp->dialstate == 4) || (lp->dialstate == 12)) &&	/* if dialing        */
-		       (!(lp->flags & ISDN_NET_CALLBACK)))	/* but no callback   */
-		     ))) {
+		if ((!matchret) &&                                        /* EAZ is matching   */
+		    (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */
+		      (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */
+		     ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing        */
+		       (!(lp->flags & ISDN_NET_CALLBACK)))                /* but no callback   */
+		     )))
+			 {
 #ifdef ISDN_DEBUG_NET_ICALL
 			printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
 			       lp->pre_device, lp->pre_channel);
@@ -2085,8 +2170,6 @@
 #ifdef ISDN_DEBUG_NET_ICALL
 						printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
 #endif
-						p = (isdn_net_dev *) p->next;
-						continue;
 					}
 				}
 			}
@@ -2096,7 +2179,7 @@
 			n = lp->phone[0];
 			if (lp->flags & ISDN_NET_SECURE) {
 				while (n) {
-					if (isdn_net_wildmat(nr, n->num))
+					if (!isdn_wildmat(nr, n->num))
 						break;
 					n = (isdn_net_phone *) n->next;
 				}
@@ -2105,7 +2188,21 @@
 #ifdef ISDN_DEBUG_NET_ICALL
 				printk(KERN_DEBUG "n_fi: match3\n");
 #endif
-				/* Here we got an interface matched, now see if it is up.
+				/* matching interface found */
+
+				/*
+				 * Is the state STOPPED?
+				 * If so, no dialin is allowed,
+				 * so reject actively.
+				 * */
+				if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+					restore_flags(flags);
+					printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
+					       lp->name);
+					return 3;
+				}
+				/*
+				 * Is the interface up?
 				 * If not, reject the call actively.
 				 */
 				if (!p->dev.start) {
@@ -2140,6 +2237,17 @@
 				}
 				if (lp->flags & ISDN_NET_CALLBACK) {
 					int chi;
+					/*
+					 * Is the state MANUAL?
+					 * If so, no callback can be made,
+					 * so reject actively.
+					 * */
+					if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
+						restore_flags(flags);
+						printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
+						       lp->name);
+						return 3;
+					}
 					printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
 					       lp->name, nr, eaz);
 					if (lp->phone[1]) {
@@ -2155,7 +2263,6 @@
 						/* Setup dialstate. */
 						lp->dtimer = 0;
 						lp->dialstate = 11;
-						lp->flags |= ISDN_NET_CONNECTED;
 						/* Connect interface with channel */
 						isdn_net_bind_channel(lp, chi);
 #ifdef CONFIG_ISDN_PPP
@@ -2217,10 +2324,10 @@
 		p = (isdn_net_dev *) p->next;
 	}
 	/* If none of configured EAZ/MSN matched and not verbose, be silent */
-	if (ematch || dev->net_verbose)
+	if (!ematch || dev->net_verbose)
 		printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
 	restore_flags(flags);
-	return 0;
+	return (wret == 2)?5:0;
 }
 
 /*
@@ -2253,6 +2360,7 @@
 			ulong flags;
 			save_flags(flags);
 			cli();
+
 			/* Grab a free ISDN-Channel */
 			if ((chi = isdn_get_free_channel(ISDN_USAGE_NET, lp->l2_proto,
 							 lp->l3_proto,
@@ -2263,7 +2371,6 @@
 				return -EAGAIN;
 			}
 			lp->dialstate = 1;
-			lp->flags |= ISDN_NET_CONNECTED;
 			/* Connect interface with channel */
 			isdn_net_bind_channel(lp, chi);
 #ifdef CONFIG_ISDN_PPP
@@ -2285,6 +2392,20 @@
 }
 
 /*
+ * This is called from certain upper protocol layers (multilink ppp
+ * and x25iface encapsulation module) that want to initiate dialing
+ * themselves.
+ */
+int
+isdn_net_dial_req(isdn_net_local * lp)
+{
+	/* is there a better error code? */
+	if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
+
+	return isdn_net_force_dial_lp(lp);
+}
+
+/*
  * Force a net-interface to dial out.
  * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
  */
@@ -2383,8 +2504,13 @@
 	netdev->local->onhtime = 10;	/* Default hangup-time for saving costs
 	   of those who forget configuring this */
 	netdev->local->dialmax = 1;
-	netdev->local->flags = ISDN_NET_CBHUP;	/* Hangup before Callback */
+	netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;	/* Hangup before Callback, manual dial */
 	netdev->local->cbdelay = 25;	/* Wait 5 secs before Callback */
+	netdev->local->dialtimeout = -1;  /* Infinite Dial-Timeout */
+	netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
+	netdev->local->dialstarted = 0;   /* Jiffies of last dial-start */
+	netdev->local->dialwait_timer = 0;  /* Jiffies of earliest next dial-start */
+
 	/* Put into to netdev-chain */
 	netdev->next = (void *) dev->netdev;
 	dev->netdev = netdev;
@@ -2465,7 +2591,7 @@
 			save_flags(flags);
 			cli(); /* avoid races with incoming events trying to
 				  call cprot->pops methods */
-			if( cprot && cprot -> pops ) 
+			if( cprot && cprot -> pops )
 				cprot -> pops -> proto_del ( cprot );
 			p -> cprot = NULL;
 			lp -> dops = NULL;
@@ -2479,7 +2605,7 @@
 			p -> cprot = isdn_concap_new( cfg -> p_encap );
 			/* p -> cprot == NULL now if p_encap is not supported
 			   by means of the concap_proto mechanism */
-			/* the protocol is not configured yet; this will 
+			/* the protocol is not configured yet; this will
 			   happen later when isdn_net_reset() is called */
 #endif
 		}
@@ -2508,7 +2634,7 @@
 			if( cfg->p_encap >= 0 &&
 			    cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
 				break;
-			printk(KERN_WARNING 
+			printk(KERN_WARNING
 			       "%s: encapsulation protocol %d not supported\n",
 			       p->local->name, cfg->p_encap);
 			return -EINVAL;
@@ -2583,6 +2709,8 @@
 		lp->triggercps = cfg->triggercps;
 		lp->slavedelay = cfg->slavedelay * HZ;
 		lp->pppbind = cfg->pppbind;
+		lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
+		lp->dialwait = cfg->dialwait * HZ;
 		if (cfg->secure)
 			lp->flags |= ISDN_NET_SECURE;
 		else
@@ -2604,6 +2732,16 @@
 				lp->flags &= ~ISDN_NET_CALLBACK;
 				break;
 		}
+		lp->flags &= ~ISDN_NET_DIALMODE_MASK;	/* first all bits off */
+		if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
+			/* old isdnctrl version, where only 0 or 1 is given */
+			printk(KERN_WARNING
+			     "Old isdnctrl version detected! Please update.\n");
+			lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
+		}
+		else {
+			lp->flags |= cfg->dialmode;  /* turn on selected bits */
+		}
 		if (cfg->chargehup)
 			lp->hupflags |= ISDN_CHARGEHUP;
 		else
@@ -2671,6 +2809,7 @@
 		if (lp->flags & ISDN_NET_CBOUT)
 			cfg->callback = 2;
 		cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
+		cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
 		cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
 		cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
 		cfg->cbdelay = lp->cbdelay;
@@ -2680,6 +2819,8 @@
 		cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
 		    (lp->chargeint / HZ) : 0;
 		cfg->pppbind = lp->pppbind;
+		cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
+		cfg->dialwait = lp->dialwait / HZ;
 		if (lp->slave)
 			strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
 		else
@@ -2749,9 +2890,37 @@
 }
 
 /*
- * Delete a phone-number from an interface.
+ * Copy a string containing the peer's phone number of a connected interface
+ * to user space.
  */
+int
+isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer)
+{
+	isdn_net_dev *p = isdn_net_findif(phone->name);
+	int ch, dv, idx;
 
+	if (!p) return -ENODEV;
+	/*
+	 * Theoretical race: while this executes, the remote number might
+	 * become invalid (hang up) or change (new connection), resulting
+         * in (partially) wrong number copied to user. This race
+	 * currently ignored.
+	 */
+	ch = p->local->isdn_channel;
+	dv = p->local->isdn_device;
+	if(ch<0 && dv<0) return -ENOTCONN;
+	idx = isdn_dc2minor(dv, ch);
+	if (idx<0) return -ENODEV;
+	/* for pre-bound channels, we need this extra check */
+	if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
+	strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
+	phone->outgoing=USG_OUTGOING(dev->usage[idx]);
+	if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
+	return 0;
+}
+/*
+ * Delete a phone-number from an interface.
+ */
 int
 isdn_net_delphone(isdn_net_ioctl_phone * phone)
 {
@@ -2957,21 +3126,3 @@
 	restore_flags(flags);
 	return 0;
 }
-
-#ifdef DEV_NUMBUFFS
-/*
- * helper function to flush device queues
- * the better place would be net/core/dev.c
- */
-static void
-dev_purge_queues(struct device *dev)
-{
-	int i;
-	for (i = 0; i < DEV_NUMBUFFS; i++) {
-		struct sk_buff *skb;
-		while ((skb = skb_dequeue(&dev->buffs[i])))
-			dev_kfree_skb(skb);
-	}
-
-}
-#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_net.h linux.pre11.3/drivers/isdn/isdn_net.h
--- linux.vanilla/drivers/isdn/isdn_net.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/isdn_net.h	Mon Jul 19 23:59:35 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_net.h,v 1.6 1997/10/09 21:28:54 fritz Exp $
+/* $Id: isdn_net.h,v 1.9 1999/04/12 12:33:27 fritz Exp $
 
  * header for Linux ISDN subsystem, network related functions (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
  *
@@ -21,6 +21,16 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.h,v $
+ * Revision 1.9  1999/04/12 12:33:27  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.8  1998/10/30 17:55:33  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.7  1998/08/31 21:09:55  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
  * Revision 1.6  1997/10/09 21:28:54  fritz
  * New HL<->LL interface:
  *   New BSENT callback with nr. of bytes included.
@@ -99,6 +109,7 @@
 extern int isdn_net_getcfg(isdn_net_ioctl_cfg *);
 extern int isdn_net_addphone(isdn_net_ioctl_phone *);
 extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *);
+extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *);
 extern int isdn_net_delphone(isdn_net_ioctl_phone *);
 extern int isdn_net_find_icall(int, int, int, setup_parm);
 extern void isdn_net_hangup(struct device *);
@@ -111,3 +122,4 @@
 			     struct sk_buff *);
 extern int isdn_net_rcv_skb(int, struct sk_buff *);
 extern void isdn_net_slarp_out(void);
+extern int isdn_net_dial_req(isdn_net_local *);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_ppp.c linux.pre11.3/drivers/isdn/isdn_ppp.c
--- linux.vanilla/drivers/isdn/isdn_ppp.c	Sun Jan 24 19:55:34 1999
+++ linux.pre11.3/drivers/isdn/isdn_ppp.c	Mon Jul 19 23:59:35 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.33 1998/02/20 17:11:54 fritz Exp $
+/* $Id: isdn_ppp.c,v 1.49 1999/07/06 07:47:11 calle Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -18,11 +18,58 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.49  1999/07/06 07:47:11  calle
+ * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the
+ *  	hdrlen the driver want. So I changed dev_alloc_skb calls
+ *         to alloc_skb and skb_reserve.
+ *
+ * Revision 1.48  1999/07/01 08:29:56  keil
+ * compatibility to 2.3 kernel
+ *
+ * Revision 1.47  1999/04/18 14:06:59  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.46  1999/04/12 12:33:35  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.45  1998/12/30 17:48:24  paul
+ * fixed syncPPP callback out
+ *
+ * Revision 1.44  1998/10/30 17:55:34  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.43  1998/10/29 17:23:54  hipp
+ * Minor MPPP fixes, verboser logging.
+ *
+ * Revision 1.42  1998/07/20 11:30:07  hipp
+ * Readded compression check
+ *
+ * Revision 1.41  1998/07/08 16:50:57  hipp
+ * Compression changes
+ *
+ * Revision 1.40  1998/04/06 19:07:27  hipp
+ * added check, whether compression is enabled.
+ *
+ * Revision 1.39  1998/03/25 22:46:53  hipp
+ * Some additional CCP changes.
+ *
+ * Revision 1.38  1998/03/24 16:33:06  hipp
+ * More CCP changes. BSD compression now "works" on a local loopback link.
+ * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
+ *
+ * Revision 1.37  1998/03/22 18:50:49  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.36  1998/03/09 17:46:30  he
+ * merged in 2.1.89 changes
+ *
+ * Revision 1.35  1998/03/07 18:21:11  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
+ * Revision 1.34  1998/02/25 17:49:48  he
+ * Changed return codes caused be failing copy_{to,from}_user to -EFAULT
+ *
  * Revision 1.33  1998/02/20 17:11:54  fritz
  * Changes for recent kernels.
  *
@@ -157,13 +204,16 @@
  * experimental for dynamic addressing: readdress IP frames
  */
 #undef ISDN_SYNCPPP_READDRESS
+#define CONFIG_ISDN_CCP 1
 
 #include <linux/config.h>
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/version.h>
-#include <linux/isdn.h>
 #include <linux/poll.h>
+#include <linux/isdn.h>
+#include <linux/ppp-comp.h>
+
 #include "isdn_common.h"
 #include "isdn_ppp.h"
 #include "isdn_net.h"
@@ -180,13 +230,33 @@
 static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
 				 struct sk_buff *skb, int proto);
 static int isdn_ppp_if_get_unit(char *namebuf);
-static int isdn_ppp_set_compressor(struct ippp_struct *is,int num);
+static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
 static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
-				struct ippp_struct *,struct ippp_struct *);
+				struct ippp_struct *,struct ippp_struct *,int proto);
 static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
-				struct sk_buff *skb);
+				struct sk_buff *skb,int proto);
 static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
 	struct ippp_struct *is,struct ippp_struct *master,int type);
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+	 struct sk_buff *skb);
+
+/* New CCP stuff */
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+				    unsigned char code, unsigned char id,
+				    unsigned char *data, int len);
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+					  unsigned char id);
+static void isdn_ppp_ccp_timer_callback(unsigned long closure);
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+						      unsigned char id);
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+				     struct isdn_ppp_resetparams *rp);
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+					unsigned char id);
+
+
 
 #ifdef CONFIG_ISDN_MPP
 static int isdn_ppp_bundle(struct ippp_struct *, int unit);
@@ -199,18 +269,16 @@
 static void isdn_ppp_free_mpqueue(isdn_net_dev *);
 #endif
 
-char *isdn_ppp_revision = "$Revision: 1.33 $";
+char *isdn_ppp_revision = "$Revision: 1.49 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 static struct isdn_ppp_compressor *ipc_head = NULL;
 
-extern int isdn_net_force_dial_lp(isdn_net_local *);
-
 /*
  * frame log (debug)
  */
 static void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen)
+isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
 {
 	int cnt,
 	 j,
@@ -223,13 +291,14 @@
 	for (i = 0, cnt = 0; cnt < maxlen; i++) {
 		for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
 			sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
-		printk(KERN_DEBUG "%s[%d]: %s\n", info, i, buf);
+		printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
 	}
 }
 
 /*
  * unbind isdn_net_local <=> ippp-device
  * note: it can happen, that we hangup/free the master before the slaves
+ *       in this case we bind another lp to the master device
  */
 int
 isdn_ppp_free(isdn_net_local * lp)
@@ -267,8 +336,7 @@
 	if ((is->state & IPPP_CONNECT))
 		isdn_ppp_closewait(lp->ppp_slot);	/* force wakeup on ippp device */
 	else if (is->state & IPPP_ASSIGNED)
-		is->state = IPPP_OPEN;	/* fallback to 'OPEN but not ASSIGEND' staet */
-
+		is->state = IPPP_OPEN;	/* fallback to 'OPEN but not ASSIGNED' state */
 
 	if (is->debug & 0x1)
 		printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
@@ -320,14 +388,16 @@
 			}
 		}
 	} else {
-		for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-			if (ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == IPPP_OPEN)
+		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+			if (ippp_table[i]->minor == lp->pppbind &&
+			    (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
 				break;
+		}
 	}
 
 	if (i >= ISDN_MAX_CHANNELS) {
 		restore_flags(flags);
-		printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
+		printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
 		return -1;
 	}
 	unit = isdn_ppp_if_get_unit(lp->name);	/* get unit number from interface name .. ugly! */
@@ -336,6 +406,15 @@
 		return -1;
 	}
 	lp->ppp_slot = i;
+
+	/* reset some values */
+	lp->netdev->ib.bundled = 0;
+	lp->netdev->ib.next_num = 0;
+	lp->netdev->ib.modify = 0;
+	lp->netdev->ib.last = NULL;
+	lp->netdev->ib.min = 0;
+	lp->netdev->ib.sq = NULL;
+
 	is = ippp_table[i];
 	is->lp = lp;
 	is->unit = unit;
@@ -359,7 +438,9 @@
 
 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
 
+#ifndef COMPAT_HAS_NEW_WAITQ
 	if (ippp_table[lp->ppp_slot]->wq)
+#endif
 		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
 }
 
@@ -377,7 +458,11 @@
 		return 0;
 	is = ippp_table[slot];
 
+#ifdef COMPAT_HAS_NEW_WAITQ
+	if (is->state)
+#else
 	if (is->state && is->wq)
+#endif
 		wake_up_interruptible(&is->wq);
 
 	is->state = IPPP_CLOSEWAIT;
@@ -418,14 +503,19 @@
 	}
 	is = file->private_data = ippp_table[slot];
 
+#if 0
 	if (is->debug & 0x1)
+#endif
 		printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
 
 	/* compression stuff */
-	is->compressor = NULL;
-	is->decomp_stat = is->comp_stat = NULL;
-	is->link_compressor = NULL;
-	is->link_decomp_stat = is->link_comp_stat = NULL;
+	is->link_compressor   = is->compressor = NULL;
+	is->link_decompressor = is->decompressor = NULL;
+	is->link_comp_stat    = is->comp_stat = NULL;
+	is->link_decomp_stat  = is->decomp_stat = NULL;
+	is->compflags = 0;
+
+	is->reset = isdn_ppp_ccp_reset_alloc(is);
 
 	is->lp = NULL;
 	is->mp_seqno = 0;       /* MP sequence number */
@@ -437,8 +527,11 @@
 	is->mru = 1524;         /* MRU, default 1524 */
 	is->maxcid = 16;        /* VJ: maxcid */
 	is->tk = current;
+#ifdef COMPAT_HAS_NEW_WAITQ
+	init_waitqueue_head(&is->wq);
+#else
 	is->wq = NULL;          /* read() wait queue */
-	is->wq1 = NULL;         /* select() wait queue */
+#endif
 	is->first = is->rq + NUM_RCV_BUFFS - 1;	/* receive queue */
 	is->last = is->rq;
 	is->minor = min;
@@ -491,10 +584,30 @@
 	is->last = is->rq;
 
 #ifdef CONFIG_ISDN_PPP_VJ
+/* TODO: if this was the previous master: link the slcomp to the new master */
 	slhc_free(is->slcomp);
 	is->slcomp = NULL;
 #endif
 
+/* TODO: if this was the previous master: link the the stuff to the new master */
+	if(is->comp_stat)
+		is->compressor->free(is->comp_stat);
+	if(is->link_comp_stat)
+		is->link_compressor->free(is->link_comp_stat);
+	if(is->link_decomp_stat)
+		is->link_decompressor->free(is->link_decomp_stat);
+	if(is->decomp_stat)
+		is->decompressor->free(is->decomp_stat);
+        is->compressor   = is->link_compressor   = NULL;
+        is->decompressor = is->link_decompressor = NULL;
+	is->comp_stat    = is->link_comp_stat    = NULL;
+        is->decomp_stat  = is->link_decomp_stat  = NULL;
+
+	if(is->reset)
+		kfree(is->reset);
+	is->reset = NULL;
+
+	/* this slot is ready for new connections */
 	is->state = 0;
 }
 
@@ -505,7 +618,7 @@
 get_arg(void *b, void *val, int len)
 {
 	if (len <= 0)
-		len = sizeof(unsigned long);
+		len = sizeof(void *);
 	if (copy_from_user((void *) val, b, len))
 		return -EFAULT;
 	return 0;
@@ -515,15 +628,12 @@
  * set arg .. ioctl helper
  */
 static int
-set_arg(void *b, unsigned long val, void *str)
+set_arg(void *b, void *val,int len)
 {
-	if (!str) {
-		if (copy_to_user(b, (void *) &val, 4))
-			return -EFAULT;
-	} else {
-		if (copy_to_user(b, str, val))
-			return -EFAULT;
-	}
+	if(len <= 0)
+		len = sizeof(void *);
+	if (copy_to_user(b, (void *) val, len))
+		return -EFAULT;
 	return 0;
 }
 
@@ -534,9 +644,10 @@
 isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	unsigned long val;
-	int num,r;
+	int r,i,j;
 	struct ippp_struct *is;
 	isdn_net_local *lp;
+	struct isdn_ppp_comp_data data;
 
 	is = (struct ippp_struct *) file->private_data;
 	lp = is->lp;
@@ -552,7 +663,7 @@
 #ifdef CONFIG_ISDN_MPP
 			if (!(is->state & IPPP_CONNECT))
 				return -EINVAL;
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
 				return r;
 			printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
 			       (int) min, (int) is->unit, (int) val);
@@ -562,24 +673,30 @@
 #endif
 			break;
 		case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-			if ((r = set_arg((void *) arg, is->unit, NULL)))
+			if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
+				return r;
+			break;
+		case PPPIOCGIFNAME:
+			if(!lp)
+				return -EINVAL;
+			if ((r = set_arg((void *) arg, lp->name,strlen(lp->name))))
 				return r;
 			break;
 		case PPPIOCGMPFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, is->mpppcfg, NULL)))
+			if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
 				return r;
 			break;
 		case PPPIOCSMPFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
 				return r;
 			is->mpppcfg = val;
 			break;
 		case PPPIOCGFLAGS:	/* get configuration flags */
-			if ((r = set_arg((void *) arg, is->pppcfg, NULL)))
+			if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
 				return r;
 			break;
 		case PPPIOCSFLAGS:	/* set configuration flags */
-			if ((r = get_arg((void *) arg, &val, 0))) {
+			if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
 				return r;
 			}
 			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
@@ -598,12 +715,12 @@
 			if (lp) {
 				struct ppp_idle pidle;
 				pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
-				if ((r = set_arg((void *) arg, sizeof(struct ppp_idle), &pidle)))
+				if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
 					 return r;
 			}
 			break;
 		case PPPIOCSMRU:	/* set receive unit size for PPP */
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
 				return r;
 			is->mru = val;
 			break;
@@ -612,7 +729,7 @@
 		case PPPIOCSMPMTU:
 			break;
 		case PPPIOCSMAXCID:	/* set the maximum compression slot id */
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
 				return r;
 			val++;
 			if (is->maxcid != val) {
@@ -635,31 +752,33 @@
 			}
 			break;
 		case PPPIOCGDEBUG:
-			if ((r = set_arg((void *) arg, is->debug, 0)))
+			if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
 				return r;
 			break;
 		case PPPIOCSDEBUG:
-			if ((r = get_arg((void *) arg, &val, 0)))
+			if ((r = get_arg((void *) arg, &val, sizeof(val) )))
 				return r;
 			is->debug = val;
 			break;
 		case PPPIOCGCOMPRESSORS:
 			{
-				unsigned long protos = 0;
+				unsigned long protos[8] = {0,};
 				struct isdn_ppp_compressor *ipc = ipc_head;
 				while(ipc) {
-					protos |= (0x1<<ipc->num);
+					j = ipc->num / (sizeof(long)*8);
+					i = ipc->num % (sizeof(long)*8);
+					if(j < 8)
+						protos[j] |= (0x1<<i);
 					ipc = ipc->next;
 				}
-				if ((r = set_arg((void *) arg, protos, 0)))
+				if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
 					return r;
 			}
 			break;
 		case PPPIOCSCOMPRESSOR:
-			if ((r = get_arg((void *) arg, &num, sizeof(int))))
+			if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
 				return r;
-			return isdn_ppp_set_compressor(is, num);
-			break;
+			return isdn_ppp_set_compressor(is, &data);
 		case PPPIOCGCALLINFO:
 			{
 				struct pppcallinfo pci;
@@ -678,7 +797,7 @@
 					if(lp->flags & ISDN_NET_CALLBACK)
 						pci.calltype |= CALLTYPE_CALLBACK;
 				}
-				return set_arg((void *)arg,sizeof(struct pppcallinfo),&pci);
+				return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
 			}
 		default:
 			break;
@@ -701,9 +820,12 @@
 		printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
 				MINOR(file->f_dentry->d_inode->i_rdev));
 
+	/* just registers wait_queue hook. This doesn't really wait. */
 	poll_wait(file, &is->wq, wait);
 
 	if (!(is->state & IPPP_OPEN)) {
+		if(is->state == IPPP_CLOSEWAIT)
+			return POLLHUP;
 		printk(KERN_DEBUG "isdn_ppp: device not open\n");
 		return POLLERR;
 	}
@@ -777,7 +899,9 @@
 	is->last = bl->next;
 	restore_flags(flags);
 
+#ifndef COMPAT_HAS_NEW_WAITQ
 	if (is->wq)
+#endif
 		wake_up_interruptible(&is->wq);
 
 	return len;
@@ -864,21 +988,33 @@
 		if (lp->isdn_device < 0 || lp->isdn_channel < 0)
 			return 0;
 
-		if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
+		if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
+			lp->dialstate == 0 &&
 		    (lp->flags & ISDN_NET_CONNECTED)) {
+			unsigned short hl;
 			int cnt;
 			struct sk_buff *skb;
-			skb = dev_alloc_skb(count);
+			/*
+			 * we need to reserve enought space in front of
+			 * sk_buff. old call to dev_alloc_skb only reserved
+			 * 16 bytes, now we are looking what the driver want
+			 */
+			hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+			skb = alloc_skb(hl+count, GFP_ATOMIC);
 			if (!skb) {
 				printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
 				return count;
 			}
+			skb_reserve(skb, hl);
 			if (copy_from_user(skb_put(skb, count), buf, count))
 				return -EFAULT;
 			if (is->debug & 0x40) {
 				printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
-				isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
+				isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
 			}
+
+			isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
+
 			if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
 				if (lp->sav_skb) {
 					dev_kfree_skb(lp->sav_skb);
@@ -962,8 +1098,9 @@
 	is = ippp_table[lp->ppp_slot];
 
 	if (is->debug & 0x4) {
-		printk(KERN_DEBUG "ippp_receive: len: %d\n", (int) skb->len);
-		isdn_ppp_frame_log("receive", skb->data, skb->len, 32);
+		printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
+		       (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);
+		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
 	}
 	if (net_dev->local->master) {
 		printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
@@ -981,13 +1118,18 @@
 #ifdef CONFIG_ISDN_MPP
 	if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
 		int sqno_end;
-		
-		if(proto == PPP_LINK_COMP) {
-			printk(KERN_DEBUG "received single link compressed frame\n");
-			skb = isdn_ppp_decompress(skb,is,NULL);
-			if(!skb)
-				return;
-			proto = isdn_ppp_strip_proto(skb);
+
+		if(is->compflags & SC_LINK_DECOMP_ON) {	
+			if(proto == PPP_LINK_COMP) {
+				if(is->debug & 0x10)
+					printk(KERN_DEBUG "received single link compressed frame\n");
+				skb = isdn_ppp_decompress(skb,is,NULL,proto);
+				if(!skb)
+					return;
+				proto = isdn_ppp_strip_proto(skb);
+			}
+			else
+				isdn_ppp_decompress(skb,is,NULL,proto);
 		}
 
 		if (proto == PPP_MP) {
@@ -1054,7 +1196,8 @@
 				}
 				min_sqno &= mask;
 				for (lpq = net_dev->queue;;) {
-					ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
+					if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0)
+						ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
 					lpq = lpq->next;
 					if (lpq == net_dev->queue)
 						break;
@@ -1149,17 +1292,31 @@
 
 	if (is->debug & 0x10) {
 		printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
-		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32);
+		isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
 	}
 
 	if(proto == PPP_COMP) {
 		if(!lp->master)
-			skb = isdn_ppp_decompress(skb,is,is);
+			skb = isdn_ppp_decompress(skb,is,is,proto);
 		else
-			skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]);
-		if(!skb)
+			skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
+
+		if(!skb) {
+			printk(KERN_DEBUG "ippp: compressed frame discarded!\n");
 			return;
+		}
+
 		proto = isdn_ppp_strip_proto(skb);
+		if (is->debug & 0x10) {
+			printk(KERN_DEBUG "RPostDecomp, skb %d %04x\n", (int) skb->len, proto);
+			isdn_ppp_frame_log("R-Decomp", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
+		}
+	}
+	else if(is->compflags & SC_DECOMP_ON)  { /* If decomp is ON */
+		if(!lp->master)
+			isdn_ppp_decompress(skb,is,is,proto);
+		else
+			isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto);
 	}
 
 	switch (proto) {
@@ -1226,7 +1383,13 @@
 #endif
 			break;
 		case PPP_CCP:
-			isdn_ppp_receive_ccp(net_dev,lp,skb);
+		case PPP_LINK_CCP:
+			isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
+			/* Dont pop up ResetReq/Ack stuff to the daemon any
+			   longer - the job is done already */
+			if(skb->data[0] == CCP_RESETREQ ||
+			   skb->data[0] == CCP_RESETACK)
+				break;
 			/* fall through */
 		default:
 			isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);	/* push data to pppd device */
@@ -1234,10 +1397,10 @@
 			return;
 	}
 
+ 	/* Reset hangup-timer */
+ 	lp->huptimer = 0;
 	netif_rx(skb);
 	/* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */
-	/* Reset hangup-timer */
-	lp->huptimer = 0;
 
 	return;
 }
@@ -1269,9 +1432,9 @@
  */
 
 int
-isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
+isdn_ppp_xmit(struct sk_buff *skb, struct device *netdev)
 {
-	struct device *mdev = ((isdn_net_local *) (dev->priv))->master;	/* get master (for redundancy) */
+	struct device *mdev = ((isdn_net_local *) (netdev->priv))->master;	/* get master (for redundancy) */
 	isdn_net_local *lp,*mlp;
 	isdn_net_dev *nd;
 	unsigned int proto = PPP_IP;     /* 0x21 */
@@ -1280,8 +1443,8 @@
 	if (mdev)
 		mlp = (isdn_net_local *) (mdev->priv);
 	else {
-		mdev = dev;
-		mlp = (isdn_net_local *) (dev->priv);
+		mdev = netdev;
+		mlp = (isdn_net_local *) (netdev->priv);
 	}
 	nd = mlp->netdev;       /* get master lp */
 	ipts = ippp_table[mlp->ppp_slot];
@@ -1294,7 +1457,7 @@
 			ipts->old_pa_dstaddr = mdev->pa_dstaddr;
 #endif
 		if (ipts->debug & 0x1)
-			printk(KERN_INFO "%s: IP frame delayed.\n", dev->name);
+			printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
 		return 1;
 	}
 
@@ -1338,7 +1501,6 @@
 		lp = nlp;
 	}
 	ipt = ippp_table[lp->ppp_slot];
-
 	lp->huptimer = 0;
 
 	/*
@@ -1354,16 +1516,25 @@
 
 	if (ipt->debug & 0x4)
 		printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
+        if (ipts->debug & 0x40)
+                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);
 
 #ifdef CONFIG_ISDN_PPP_VJ
 	if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes, but check this again */
 		struct sk_buff *new_skb;
-
-		new_skb = dev_alloc_skb(skb->len);
+	        unsigned short hl;
+		/*
+		 * we need to reserve enought space in front of
+		 * sk_buff. old call to dev_alloc_skb only reserved
+		 * 16 bytes, now we are looking what the driver want.
+		 */
+		hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
+		new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
 		if (new_skb) {
 			u_char *buf;
 			int pktlen;
 
+			skb_reserve(new_skb, hl);
 			new_skb->dev = skb->dev;
 			skb_put(new_skb, skb->len);
 			buf = skb->data;
@@ -1393,10 +1564,11 @@
 	}
 #endif
 
-    /*
-     * normal or bundle compression
-     */
-	skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+	/*
+	 * normal (single link) or bundle compression
+	 */
+	if(ipts->compflags & SC_COMP_ON)
+		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
 
 	if (ipt->debug & 0x24)
 		printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
@@ -1430,9 +1602,10 @@
 #endif
 
 	/*
-	 * 'link' compression 
+	 * 'link in bundle' compression  ...
 	 */
-	skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+	if(ipt->compflags & SC_LINK_COMP_ON)
+		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
 
 	if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
 		unsigned char *data = isdn_ppp_skb_push(&skb,1);
@@ -1459,11 +1632,11 @@
 
 	if (ipts->debug & 0x40) {
 		printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
-		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
+		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
 	}
-	if (isdn_net_send_skb(dev, lp, skb)) {
+	if (isdn_net_send_skb(netdev, lp, skb)) {
 		if (lp->sav_skb) {	/* whole sav_skb processing with disabled IRQs ?? */
-			printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", dev->name);
+			printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name);
 			dev_kfree_skb(skb);
 		} else
 			lp->sav_skb = skb;
@@ -1473,6 +1646,12 @@
 
 #ifdef CONFIG_ISDN_MPP
 
+/*
+ * free SQ queue
+ * -------------
+ * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames,
+ * that can't be delivered, because there is an outstanding earlier frame
+ */
 static void
 isdn_ppp_free_sqqueue(isdn_net_dev * p)
 {
@@ -1489,6 +1668,12 @@
 
 }
 
+/*
+ * free MP queue
+ * -------------
+ * Note: The MP queue holds all frame fragments of frames, that can't be
+ * reassembled, because there is at least one missing fragment.
+ */
 static void 
 isdn_ppp_free_mpqueue(isdn_net_dev * p)
 {
@@ -1550,7 +1735,9 @@
 	return 0;
 }
 
-
+/*
+ * Mask sequence numbers in MP queue
+ */
 static void
 isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
 {
@@ -1561,6 +1748,11 @@
 	}
 }
 
+/*
+ * put a fragment at the right place into the MP queue 
+ * Also checks, whether this fragment completes a frame. In this case
+ * the fragments are copied together into one SKB
+ */
 static int
 isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno)
 {
@@ -1761,13 +1953,11 @@
 		slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp);
 #endif
 }
+#endif
 
 /*
  * a buffered packet timed-out?
  */
-
-#endif
-
 void
 isdn_ppp_timer_timeout(void)
 {
@@ -1939,7 +2129,7 @@
 	if (!sdev)
 		return 2;
 
-	isdn_net_force_dial_lp((isdn_net_local *) sdev->priv);
+	isdn_net_dial_req((isdn_net_local *) sdev->priv);
 	return 0;
 #else
 	return -1;
@@ -1980,47 +2170,440 @@
 /*
  * PPP compression stuff
  */
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master)
+
+
+/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
+   generate a CCP Reset-Request or tear down CCP altogether */
+
+static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
+{
+	isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
+}
+
+/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
+   but absolutely nontrivial. The most abstruse problem we are facing is
+   that the generation, reception and all the handling of timeouts and
+   resends including proper request id management should be entirely left
+   to the (de)compressor, but indeed is not covered by the current API to
+   the (de)compressor. The API is a prototype version from PPP where only
+   some (de)compressors have yet been implemented and all of them are
+   rather simple in their reset handling. Especially, their is only one
+   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
+   not have parameters. For this very special case it was sufficient to
+   just return an error code from the decompressor and have a single
+   reset() entry to communicate all the necessary information between
+   the framework and the (de)compressor. Bad enough, LZS is different
+   (and any other compressor may be different, too). It has multiple
+   histories (eventually) and needs to Reset each of them independently
+   and thus uses multiple outstanding Acks and history numbers as an
+   additional parameter to Reqs/Acks.
+   All that makes it harder to port the reset state engine into the
+   kernel because it is not just the same simple one as in (i)pppd but
+   it must be able to pass additional parameters and have multiple out-
+   standing Acks. We are trying to achieve the impossible by handling
+   reset transactions independent by their id. The id MUST change when
+   the data portion changes, thus any (de)compressor who uses more than
+   one resettable state must provide and recognize individual ids for
+   each individual reset transaction. The framework itself does _only_
+   differentiate them by id, because it has no other semantics like the
+   (de)compressor might.
+   This looks like a major redesign of the interface would be nice,
+   but I don't have an idea how to do it better. */
+
+/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
+   getting that lengthy because there is no simple "send-this-frame-out"
+   function above but every wrapper does a bit different. Hope I guess
+   correct in this hack... */
+
+static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
+				    unsigned char code, unsigned char id,
+				    unsigned char *data, int len)
+{
+	struct sk_buff *skb;
+	unsigned char *p;
+	int count;
+	int cnt = 0;
+	isdn_net_local *lp = is->lp;
+
+	/* Alloc large enough skb */
+	skb = dev_alloc_skb(len + 16);
+	if(!skb) {
+		printk(KERN_WARNING
+		       "ippp: CCP cannot send reset - out of memory\n");
+		return;
+	}
+
+	/* We may need to stuff an address and control field first */
+	if(!(is->pppcfg & SC_COMP_AC)) {
+		p = skb_put(skb, 2);
+		*p++ = 0xff;
+		*p++ = 0x03;
+	}
+
+	/* Stuff proto, code, id and length */
+	p = skb_put(skb, 6);
+	*p++ = (proto >> 8);
+	*p++ = (proto & 0xff);
+	*p++ = code;
+	*p++ = id;
+	cnt = 4 + len;
+	*p++ = (cnt >> 8);
+	*p++ = (cnt & 0xff);
+
+	/* Now stuff remaining bytes */
+	if(len) {
+		p = skb_put(skb, len);
+		memcpy(p, data, len);
+	}
+
+	/* skb is now ready for xmit */
+	printk(KERN_DEBUG "Sending CCP Frame:\n");
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+	/* Just ripped from isdn_ppp_write. Dunno whether it makes sense,
+	   especially dunno what the sav_skb stuff is good for. */
+
+	count = skb->len;
+	if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel,
+					  1, skb)) != count) {
+		if (lp->sav_skb) {
+			dev_kfree_skb(lp->sav_skb);
+			printk(KERN_INFO
+			       "isdn_ppp_write: freeing sav_skb (%d,%d)!\n",
+			       cnt, count);
+		} else
+			printk(KERN_INFO
+			       "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n",
+			       cnt, count);
+		lp->sav_skb = skb;
+	}
+}
+
+/* Allocate the reset state vector */
+static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
+{
+	struct ippp_ccp_reset *r;
+	printk(KERN_DEBUG "ippp_ccp: allocating reset data structure\n");
+	r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+	if(!r)
+		return NULL;
+	memset(r, 0, sizeof(struct ippp_ccp_reset));
+	is->reset = r;
+	return r;
+}
+
+/* Free a given state and clear everything up for later reallocation */
+static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
+					  unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	if(is->reset->rs[id]) {
+		printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
+		rs = is->reset->rs[id];
+		/* Make sure the kernel will not call back later */
+		if(rs->ta)
+			del_timer(&rs->timer);
+		is->reset->rs[id] = NULL;
+		kfree(rs);
+	} else {
+		printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
+	}
+}
+
+/* The timer callback function which is called when a ResetReq has timed out,
+   aka has never been answered by a ResetAck */
+static void isdn_ppp_ccp_timer_callback(unsigned long closure)
+{
+	struct ippp_ccp_reset_state *rs =
+		(struct ippp_ccp_reset_state *)closure;
+
+	if(!rs) {
+		printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
+		return;
+	}
+	if(rs->ta && rs->state == CCPResetSentReq) {
+		/* We are correct here */
+		printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
+		       rs->id);
+		if(!rs->expra) {
+			/* Hmm, there is no Ack really expected. We can clean
+			   up the state now, it will be reallocated if the
+			   decompressor insists on another reset */
+			rs->ta = 0;
+			isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
+			return;
+		}
+		/* Push it again */
+		isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
+					rs->data, rs->dlen);
+		/* Restart timer */
+		rs->timer.expires = jiffies + HZ*5;
+		add_timer(&rs->timer);
+	} else {
+		printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
+		       rs->state);
+	}
+}
+
+/* Allocate a new reset transaction state */
+static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
+						      unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs;
+	if(is->reset->rs[id]) {
+		printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
+		       id);
+		return NULL;
+	} else {
+		rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+		if(!rs)
+			return NULL;
+		memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
+		rs->state = CCPResetIdle;
+		rs->is = is;
+		rs->id = id;
+		rs->timer.data = (unsigned long)rs;
+		rs->timer.function = isdn_ppp_ccp_timer_callback;
+		is->reset->rs[id] = rs;
+	}
+	return rs;
+}
+
+
+/* A decompressor wants a reset with a set of parameters - do what is
+   necessary to fulfill it */
+static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
+				     struct isdn_ppp_resetparams *rp)
+{
+	struct ippp_ccp_reset_state *rs;
+
+	if(rp->valid) {
+		/* The decompressor defines parameters by itself */
+		if(rp->rsend) {
+			/* And he wants us to send a request */
+			if(!(rp->idval)) {
+				printk(KERN_ERR "ippp_ccp: decompressor must"
+				       " specify reset id\n");
+				return;
+			}
+			if(is->reset->rs[rp->id]) {
+				/* There is already a transaction in existence
+				   for this id. May be still waiting for a
+				   Ack or may be wrong. */
+				rs = is->reset->rs[rp->id];
+				if(rs->state == CCPResetSentReq && rs->ta) {
+					printk(KERN_DEBUG "ippp_ccp: reset"
+					       " trans still in progress"
+					       " for id %d\n", rp->id);
+				} else {
+					printk(KERN_WARNING "ippp_ccp: reset"
+					       " trans in wrong state %d for"
+					       " id %d\n", rs->state, rp->id);
+				}
+			} else {
+				/* Ok, this is a new transaction */
+				printk(KERN_DEBUG "ippp_ccp: new trans for id"
+				       " %d to be started\n", rp->id);
+				rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
+				if(!rs) {
+					printk(KERN_ERR "ippp_ccp: out of mem"
+					       " allocing ccp trans\n");
+					return;
+				}
+				rs->state = CCPResetSentReq;
+				rs->expra = rp->expra;
+				if(rp->dtval) {
+					rs->dlen = rp->dlen;
+					memcpy(rs->data, rp->data, rp->dlen);
+				}
+				/* HACK TODO - add link comp here */
+				isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
+							CCP_RESETREQ, rs->id,
+							rs->data, rs->dlen);
+				/* Start the timer */
+				rs->timer.expires = jiffies + 5*HZ;
+				add_timer(&rs->timer);
+				rs->ta = 1;
+			}
+		} else {
+			printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
+		}
+	} else {
+		/* The reset params are invalid. The decompressor does not
+		   care about them, so we just send the minimal requests
+		   and increase ids only when an Ack is received for a
+		   given id */
+		if(is->reset->rs[is->reset->lastid]) {
+			/* There is already a transaction in existence
+			   for this id. May be still waiting for a
+			   Ack or may be wrong. */
+			rs = is->reset->rs[is->reset->lastid];
+			if(rs->state == CCPResetSentReq && rs->ta) {
+				printk(KERN_DEBUG "ippp_ccp: reset"
+				       " trans still in progress"
+				       " for id %d\n", rp->id);
+			} else {
+				printk(KERN_WARNING "ippp_ccp: reset"
+				       " trans in wrong state %d for"
+				       " id %d\n", rs->state, rp->id);
+			}
+		} else {
+			printk(KERN_DEBUG "ippp_ccp: new trans for id"
+			       " %d to be started\n", is->reset->lastid);
+			rs = isdn_ppp_ccp_reset_alloc_state(is,
+							    is->reset->lastid);
+			if(!rs) {
+				printk(KERN_ERR "ippp_ccp: out of mem"
+				       " allocing ccp trans\n");
+				return;
+			}
+			rs->state = CCPResetSentReq;
+			/* We always expect an Ack if the decompressor doesnt
+			   know	better */
+			rs->expra = 1;
+			rs->dlen = 0;
+			/* HACK TODO - add link comp here */
+			isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
+						rs->id, NULL, 0);
+			/* Start the timer */
+			rs->timer.expires = jiffies + 5*HZ;
+			add_timer(&rs->timer);
+			rs->ta = 1;
+		}
+	}
+}
+
+/* An Ack was received for this id. This means we stop the timer and clean
+   up the state prior to calling the decompressors reset routine. */
+static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
+					unsigned char id)
+{
+	struct ippp_ccp_reset_state *rs = is->reset->rs[id];
+
+	if(rs) {
+		if(rs->ta && rs->state == CCPResetSentReq) {
+			/* Great, we are correct */
+			if(!rs->expra)
+				printk(KERN_DEBUG "ippp_ccp: ResetAck received"
+				       " for id %d but not expected\n", id);
+		} else {
+			printk(KERN_INFO "ippp_ccp: ResetAck received out of"
+			       "sync for id %d\n", id);
+		}
+		if(rs->ta) {
+			rs->ta = 0;
+			del_timer(&rs->timer);
+		}
+		isdn_ppp_ccp_reset_free_state(is, id);
+	} else {
+		printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
+		       " %d\n", id);
+	}
+	/* Make sure the simple reset stuff uses a new id next time */
+	is->reset->lastid++;
+}
+
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
+	int proto)
 {
-#if 1
-	printk(KERN_ERR "compression not included!\n");
-	dev_kfree_skb(skb);
-	return NULL;
+#ifndef CONFIG_ISDN_CCP
+	if(proto == PPP_COMP || proto == PPP_LINK_COMP) {
+		printk(KERN_ERR "isdn_ppp: Ouch! Compression not included!\n");
+		dev_kfree_skb(skb);
+		return NULL;
+	}
+	return skb;
 #else
+	void *stat = NULL;
+	struct isdn_ppp_compressor *ipc = NULL;
+	struct sk_buff *skb_out;
+	int len;
+	struct ippp_struct *ri;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
+
 	if(!master) {
 		/* 
-		 * single link compression 
+		 * single link decompression 
 		 */
-		if(!is->link_compressor) {
-			printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+		if(!is->link_decompressor) {
+			printk(KERN_ERR "ippp: no link decompressor defined!\n");
 			dev_kfree_skb(skb);
 			return NULL;
 		}
 		if(!is->link_decomp_stat) {
-			printk(KERN_DEBUG "ippp: initialize link compressor\n");
+			printk(KERN_DEBUG "ippp: no link decompressor data allocated\n");
+			dev_kfree_skb(skb);
+			return NULL;
 		}
-/*
-		-> decompress link
-*/
-    }
+		stat = is->link_decomp_stat;
+		ipc = is->link_decompressor;
+		ri = is;
+	}
 	else {
 		/*
 		 * 'normal' or bundle-compression 
 		 */
-		if(!master->compressor) {
-			printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+		if(!master->decompressor) {
+			printk(KERN_ERR "ippp: no decompressor defined!\n");
 			dev_kfree_skb(skb);
 			return NULL;
 		}
 		if(!master->decomp_stat) {
-#if 0
-			master->decomp_stat = (master->compressor->decomp_alloc)( .. );
-#endif
-			printk(KERN_DEBUG "ippp: initialize compressor\n");
+			printk(KERN_DEBUG "ippp: no decompressor data allocated\n");
+			dev_kfree_skb(skb);
+			return NULL;
 		}
+		stat = master->decomp_stat;
+		ipc = master->decompressor;
+		ri = master;
+	}
+
+	/*
+	printk(KERN_DEBUG "ippp: Decompress valid!\n");
+	*/
+
+	if((master && proto == PPP_COMP) || (!master && proto == PPP_LINK_COMP) ) {
+		/* Set up reset params for the decompressor */
+		memset(&rsparm, 0, sizeof(rsparm));
+		rsparm.data = rsdata;
+		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
+
+/* !!!HACK,HACK,HACK!!! 2048 is only assumed */
+		skb_out = dev_alloc_skb(2048);
+		len = ipc->decompress(stat,skb,skb_out, &rsparm);
+		dev_kfree_skb(skb);
+		if(len <= 0) {
+		  /* Ok, some error */
+		  switch(len) {
+		  case DECOMP_ERROR:
+		    ri->pppcfg |= SC_DC_ERROR;
+		    printk(KERN_INFO "ippp: decomp wants reset %s params\n",
+			   rsparm.valid ? "with" : "without");
+
+		    isdn_ppp_ccp_reset_trans(ri, &rsparm);
+
+		    break;
+		  case DECOMP_FATALERROR:
+		    ri->pppcfg |= SC_DC_FERROR;
+		    /* Kick ipppd to recognize the error */
+		    isdn_ppp_ccp_kickup(ri);
+		    break;
+		  }
+		  /* Did I see a leak here ? */
+		  dev_kfree_skb(skb_out);
+		  return NULL;
+		}
+		return skb_out;
+	}
+	else {
+		/*
+		printk(KERN_DEBUG "isdn_ppp: [%d] Calling incomp with this frame!\n",is->unit);
+		*/
+		ipc->incomp(stat,skb,proto);
+		return skb;
 	}
-	
-	return skb;
 #endif
 }
 
@@ -2034,19 +2617,29 @@
 static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
 	struct ippp_struct *is,struct ippp_struct *master,int type)
 {
-#if 1	
-	return skb_in;
-#else
     int ret;
     int new_proto;
     struct isdn_ppp_compressor *compressor;
     void *stat;
     struct sk_buff *skb_out;
 
+#ifdef CONFIG_ISDN_CCP
+	/* we do not compress control protocols */
+    if(*proto < 0 || *proto > 0x3fff) {
+#else
+    {
+#endif
+      return skb_in;
+    }
+
 	if(type) { /* type=1 => Link compression */
+#if 0
 		compressor = is->link_compressor;
 		stat = is->link_comp_stat;
 		new_proto = PPP_LINK_COMP;
+#else
+		return skb_in;
+#endif
 	}
 	else {
 		if(!master) {
@@ -2061,15 +2654,16 @@
 	}
 
 	if(!compressor) {
-		printk(KERN_ERR "No compressor set!\n");
+		printk(KERN_ERR "isdn_ppp: No compressor set!\n");
 		return skb_in;
 	}
 	if(!stat) {
-		/* init here ? */
+		printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
 		return skb_in;
 	}
 
-	skb_out = dev_alloc_skb(skb_in->len);
+	/* Allow for at least 150 % expansion (for now) */
+	skb_out = dev_alloc_skb(skb_in->len + skb_in->len/2 + 32);
 	if(!skb_out)
 		return skb_in;
 
@@ -2082,24 +2676,225 @@
 	dev_kfree_skb(skb_in);
 	*proto = new_proto;
 	return skb_out;
-#endif
-
 }
 
 /*
  * we received a CCP frame .. 
- * not a clean solution, but we SHOULD handle a few cased in the kernel
+ * not a clean solution, but we MUST handle a few cases in the kernel
  */
 static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
-	 struct sk_buff *skb)
+	 struct sk_buff *skb,int proto)
 {
-#if 0
-	printk(KERN_DEBUG "isdn_ppp_receive_cpp: %02x %02x %02x %02x %02x %02x %02x %02x\n",
-		skb->data[0],skb->data[1],skb->data[2],skb->data[3],
-		skb->data[4],skb->data[5],skb->data[6],skb->data[7] );
-#endif
+	struct ippp_struct *is = ippp_table[lp->ppp_slot];
+	struct ippp_struct *mis;
+	int len;
+	struct isdn_ppp_resetparams rsparm;
+	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
+
+	printk(KERN_DEBUG "Received CCP frame from peer\n");
+	isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+	if(lp->master)
+		mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
+	else
+		mis = is;
+
+	switch(skb->data[0]) {
+	case CCP_CONFREQ:
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+		if(proto == PPP_CCP)
+			mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);		
+		else
+			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);		
+		break;
+	case CCP_CONFACK:
+		/* if we RECEIVE an ackowledge we enable the decompressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Enable decompression here!\n");
+		if(proto == PPP_CCP)
+			mis->compflags |= SC_DECOMP_ON;
+		else
+			is->compflags |= SC_LINK_DECOMP_ON;
+		break;
+
+	case CCP_RESETACK:
+		printk(KERN_DEBUG "Received ResetAck from peer\n");
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+
+		if(proto == PPP_CCP) {
+			/* If a reset Ack was outstanding for this id, then
+			   clean up the state engine */
+			isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
+			if(mis->decompressor && mis->decomp_stat)
+				mis->decompressor->
+					reset(mis->decomp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, NULL);
+			/* TODO: This is not easy to decide here */
+			mis->compflags &= ~SC_DECOMP_DISCARD;
+			mis->pppcfg &= ~SC_DC_ERROR;
+		}
+		else {
+			isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
+			if(is->link_decompressor && is->link_decomp_stat)
+				is->link_decompressor->
+					reset(is->link_decomp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, NULL);
+			/* TODO: neither here */
+			is->compflags &= ~SC_LINK_DECOMP_DISCARD;
+			is->pppcfg &= ~SC_DC_ERROR;
+		}
+		break;
+
+	case CCP_RESETREQ:
+		printk(KERN_DEBUG "Received ResetReq from peer\n");
+		/* Receiving a ResetReq means we must reset our compressor */
+		/* Set up reset params for the reset entry */
+		memset(&rsparm, 0, sizeof(rsparm));
+		rsparm.data = rsdata;
+		rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; 
+		/* Isolate data length */
+		len = (skb->data[2] << 8) | skb->data[3];
+		len -= 4;
+		if(proto == PPP_CCP) {
+			if(mis->compressor && mis->comp_stat)
+				mis->compressor->
+					reset(mis->comp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, &rsparm);
+		}
+		else {
+			if(is->link_compressor && is->link_comp_stat)
+				is->link_compressor->
+					reset(is->link_comp_stat,
+					      skb->data[0],
+					      skb->data[1],
+					      len ? &skb->data[4] : NULL,
+					      len, &rsparm);
+		}
+		/* Ack the Req as specified by rsparm */
+		if(rsparm.valid) {
+			/* Compressor reset handler decided how to answer */
+			if(rsparm.rsend) {
+				/* We should send a Frame */
+				isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+							rsparm.idval ? rsparm.id
+							: skb->data[1],
+							rsparm.dtval ?
+							rsparm.data : NULL,
+							rsparm.dtval ?
+							rsparm.dlen : 0);
+			} else {
+				printk(KERN_DEBUG "ResetAck suppressed\n");
+			}
+		} else {
+			/* We answer with a straight reflected Ack */
+			isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
+						skb->data[1],
+						len ? &skb->data[4] : NULL,
+						len);
+		}
+		break;
+	}
+}
+
+
+/*
+ * Daemon sends a CCP frame ...
+ */
+
+/* TODO: Clean this up with new Reset semantics */
+
+static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
+{
+	struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
+	int proto;
+	unsigned char *data;
+
+	if(!skb || skb->len < 3)
+		return;
+
+	/* Daemon may send with or without address and control field comp */
+	data = skb->data;
+	if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
+		data += 2;
+		if(skb->len < 5)
+			return;
+	}
+
+	proto = ((int)data[0]<<8)+data[1];
+	if(proto != PPP_CCP && proto != PPP_LINK_CCP)
+		return;
+
+	printk(KERN_DEBUG "Received CCP frame from daemon:\n");
+	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+
+        if(lp->master)
+                mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
+        else
+                mis = is;
+	
+	if(mis != is)
+		printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
+	
+        switch(data[2]) {
+	case CCP_CONFREQ:
+	case CCP_TERMREQ:
+	case CCP_TERMACK:
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Disable (de)compression here!\n");
+		if(proto == PPP_CCP)
+			is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
+		else
+			is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
+		break;
+	case CCP_CONFACK:
+		/* if we SEND an ackowledge we can/must enable the compressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Enable compression here!\n");
+		if(proto == PPP_CCP)
+			is->compflags |= SC_COMP_ON;
+		else
+			is->compflags |= SC_LINK_COMP_ON;
+		break;
+	case CCP_RESETACK:
+		/* If we send a ACK we should reset our compressor */
+		if(is->debug & 0x10)
+			printk(KERN_DEBUG "Reset decompression state here!\n");
+		printk(KERN_DEBUG "ResetAck from daemon passed by\n");
+		if(proto == PPP_CCP) {
+			/* link to master? */
+			if(is->compressor && is->comp_stat)
+				is->compressor->reset(is->comp_stat, 0, 0,
+						      NULL, 0, NULL);
+			is->compflags &= ~SC_COMP_DISCARD;	
+		}
+		else {
+			if(is->link_compressor && is->link_comp_stat)
+				is->link_compressor->reset(is->link_comp_stat,
+							   0, 0, NULL, 0, NULL);
+			is->compflags &= ~SC_LINK_COMP_DISCARD;	
+		}
+		break;
+	case CCP_RESETREQ:
+		/* Just let it pass by */
+		printk(KERN_DEBUG "ResetReq from daemon passed by\n");
+		break;
+	}
 }
 
+
 int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
 {
 	ipc->next = ipc_head;
@@ -2123,32 +2918,67 @@
 	return 0;
 }
 
-static int isdn_ppp_set_compressor(struct ippp_struct *is,int num)
+static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
 {
 	struct isdn_ppp_compressor *ipc = ipc_head;
+	int ret;
+	void *stat;
+	int num = data->num;
+
+	if(is->debug & 0x10)
+		printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
+			(data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
 
 	while(ipc) {
 		if(ipc->num == num) {
-			return 0;	
-			is->compressor = ipc;
-			is->link_compressor = ipc;
+			stat = ipc->alloc(data);
+			if(stat) {
+				ret = ipc->init(stat,data,is->unit,0);
+				if(!ret) {
+					printk(KERN_ERR "Can't init (de)compression!\n");
+					ipc->free(stat);
+					stat = NULL;
+					break;
+				}
+			}
+			else {
+				printk(KERN_ERR "Can't alloc (de)compression!\n");
+				break;
+			}
+
+                        if(data->flags & IPPP_COMP_FLAG_XMIT) {
+				if(data->flags & IPPP_COMP_FLAG_LINK) {
+					if(is->link_comp_stat)
+						is->link_compressor->free(is->link_comp_stat);
+					is->link_comp_stat = stat;
+                                	is->link_compressor = ipc;
+				}
+				else {
+					if(is->comp_stat)
+						is->compressor->free(is->comp_stat);
+					is->comp_stat = stat;
+                                	is->compressor = ipc;
+				}
+			}
+                        else {
+				if(data->flags & IPPP_COMP_FLAG_LINK) {
+					if(is->link_decomp_stat)
+						is->link_decompressor->free(is->link_decomp_stat);
+					is->link_decomp_stat = stat;
+        	                        is->link_decompressor = ipc;
+				}
+				else {
+					if(is->decomp_stat)
+						is->decompressor->free(is->decomp_stat);
+					is->decomp_stat = stat;
+        	                        is->decompressor = ipc;
+				}
+			}
+			return 0;
 		}
 		ipc = ipc->next;
 	}
 	return -EINVAL;
 }
-
-
-#if 0
-static struct symbol_table isdn_ppp_syms =
-{
-#include <linux/symtab_begin.h>
-	X(isdn_ppp_register_compressor),
-	X(isdn_ppp_unregister_compressor),
-#include <linux/symtab_end.h>
-};
-#endif
-
-
 
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_ppp.h linux.pre11.3/drivers/isdn/isdn_ppp.h
--- linux.vanilla/drivers/isdn/isdn_ppp.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/isdn_ppp.h	Mon Jul 19 23:59:35 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.h,v 1.12 1998/01/31 22:07:48 keil Exp $
+/* $Id: isdn_ppp.h,v 1.13 1998/03/22 18:50:50 hipp Exp $
 
  * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.h,v $
+ * Revision 1.13  1998/03/22 18:50:50  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
  * Revision 1.12  1998/01/31 22:07:48  keil
  * changes for newer kernels
  *
@@ -83,6 +86,9 @@
 extern void isdn_ppp_release(int, struct file *);
 extern int isdn_ppp_dial_slave(char *);
 extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
+
+extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
+extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
 
 #define IPPP_OPEN	0x01
 #define IPPP_CONNECT	0x02
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_syms.c linux.pre11.3/drivers/isdn/isdn_syms.c
--- linux.vanilla/drivers/isdn/isdn_syms.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/isdn/isdn_syms.c	Mon Jul 19 23:59:35 1999
@@ -0,0 +1,114 @@
+/* $Id: isdn_syms.c,v 1.3.2.1 1999/04/22 21:09:37 werner Exp $
+
+ * Linux ISDN subsystem, exported symbols (linklevel).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * $Log: isdn_syms.c,v $
+ * Revision 1.3.2.1  1999/04/22 21:09:37  werner
+ * Added support for dss1 diversion services
+ *
+ * Revision 1.3  1997/02/16 01:02:47  fritz
+ * Added GPL-Header, Id and Log
+ *
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#ifndef __GENKSYMS__      /* Don't want genksyms report unneeded structs */
+#include <linux/isdn.h>
+#endif
+#include "isdn_common.h"
+#ifdef CONFIG_ISDN_DIVERSION
+  #include <linux/isdn_divertif.h>
+extern isdn_divert_if *divert_if;
+
+static char *map_drvname(int di)
+{
+  if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) 
+    return(NULL);
+  return(dev->drvid[di]); /* driver name */
+} /* map_drvname */
+
+static int map_namedrv(char *id)
+{  int i;
+
+   for (i = 0; i < ISDN_MAX_DRIVERS; i++)
+    { if (!strcmp(dev->drvid[i],id)) 
+        return(i);
+    }
+   return(-1);
+} /* map_namedrv */
+
+int DIVERT_REG_NAME(isdn_divert_if *i_div)
+{
+  if (i_div->if_magic != DIVERT_IF_MAGIC) 
+    return(DIVERT_VER_ERR);
+  switch (i_div->cmd)
+    {
+      case DIVERT_CMD_REL:
+        if (divert_if != i_div) 
+          return(DIVERT_REL_ERR);
+        divert_if = NULL; /* free interface */
+        MOD_DEC_USE_COUNT;
+        return(DIVERT_NO_ERR);
+
+      case DIVERT_CMD_REG:
+        if (divert_if) 
+          return(DIVERT_REG_ERR);
+        i_div->ll_cmd = isdn_command; /* set command function */
+        i_div->drv_to_name = map_drvname; 
+        i_div->name_to_drv = map_namedrv; 
+        MOD_INC_USE_COUNT;
+        divert_if = i_div; /* remember interface */
+        return(DIVERT_NO_ERR);
+
+      default:
+        return(DIVERT_CMD_ERR);   
+    }
+} /* DIVERT_REG_NAME */
+
+#endif CONFIG_ISDN_DIVERSION
+
+#if (LINUX_VERSION_CODE < 0x020111)
+static int has_exported;
+
+static struct symbol_table isdn_syms = {
+#include <linux/symtab_begin.h>
+        X(register_isdn),
+#ifdef CONFIG_ISDN_DIVERSION
+        X(DIVERT_REG_NAME),
+#endif CONFIG_ISDN_DIVERSION
+#include <linux/symtab_end.h>
+};
+
+void
+isdn_export_syms(void)
+{
+	if (has_exported)
+		return;
+        register_symtab(&isdn_syms);
+        has_exported = 1;
+}
+
+#else
+
+EXPORT_SYMBOL(register_isdn);
+#ifdef CONFIG_ISDN_DIVERSION
+  EXPORT(DIVERT_REG_NAME);
+#endif CONFIG_ISDN_DIVERSION
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_tty.c linux.pre11.3/drivers/isdn/isdn_tty.c
--- linux.vanilla/drivers/isdn/isdn_tty.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/isdn_tty.c	Mon Jul 19 23:59:35 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_tty.c,v 1.47 1998/02/22 19:44:14 fritz Exp $
+/* $Id: isdn_tty.c,v 1.68 1999/07/11 17:51:51 armin Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,84 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.68  1999/07/11 17:51:51  armin
+ * Bugfix, "-" was missing for AT&L settings.
+ *
+ * Revision 1.67  1999/07/11 17:14:12  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.66  1999/07/07 10:13:46  detabc
+ * remove unused messages
+ *
+ * Revision 1.65  1999/07/04 21:01:59  werner
+ * Added support for keypad and display (ported from 2.0)
+ *
+ * Revision 1.64  1999/07/01 08:30:00  keil
+ * compatibility to 2.3 kernel
+ *
+ * Revision 1.63  1999/04/12 12:33:39  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.62  1999/03/02 12:04:48  armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.61  1999/01/27 22:53:11  he
+ * minor updates (spellings, jiffies wrap around in isdn_tty)
+ *
+ * Revision 1.60  1998/11/15 23:57:32  keil
+ * changes for 2.1.127
+ *
+ * Revision 1.59  1998/08/20 13:50:15  keil
+ * More support for hybrid modem (not working yet)
+ *
+ * Revision 1.58  1998/07/26 18:48:45  armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.57  1998/06/26 15:12:36  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.56  1998/06/18 23:31:51  fritz
+ * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
+ * Removed direct-senddown feature in isdn_tty_write because it will
+ * never succeed with locking and is useless anyway.
+ *
+ * Revision 1.55  1998/06/17 19:50:55  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ *
+ *
+ * Revision 1.52  1998/03/19 13:18:21  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
+ *
+ * Revision 1.49  1998/03/08 00:01:59  fritz
+ * Bugfix: Lowlevel module usage and channel usage were not
+ *         reset on NO DCHANNEL.
+ *
+ * Revision 1.48  1998/03/07 12:28:15  tsbogend
+ * fixed kernel unaligned traps on Linux/Alpha
+ *
  * Revision 1.47  1998/02/22 19:44:14  fritz
  * Bugfixes and improvements regarding V.110, V.110 now running.
  *
@@ -236,7 +314,6 @@
 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
 static void isdn_tty_modem_reset_regs(modem_info *, int);
 static void isdn_tty_cmd_ATA(modem_info *);
-static void isdn_tty_at_cout(char *, modem_info *);
 static void isdn_tty_flush_buffer(struct tty_struct *);
 static void isdn_tty_modem_result(int, modem_info *);
 #ifdef CONFIG_ISDN_AUDIO
@@ -254,62 +331,8 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.47 $";
+char *isdn_tty_revision = "$Revision: 1.68 $";
 
-#define DLE 0x10
-#define ETX 0x03
-#define DC4 0x14
-
-/*
- * Definition of some special Registers of AT-Emulator
- */
-#define REG_RINGATA   0
-#define REG_RINGCNT   1
-#define REG_ESC       2
-#define REG_CR        3
-#define REG_LF        4
-#define REG_BS        5
-
-#define REG_RESP     12
-#define BIT_RESP      1
-#define REG_RESPNUM  12
-#define BIT_RESPNUM   2
-#define REG_ECHO     12
-#define BIT_ECHO      4
-#define REG_DCD      12
-#define BIT_DCD       8
-#define REG_CTS      12
-#define BIT_CTS      16
-#define REG_DTRR     12
-#define BIT_DTRR     32
-#define REG_DSR      12
-#define BIT_DSR      64
-#define REG_CPPP     12
-#define BIT_CPPP    128
-
-#define REG_DELXMT   13
-#define BIT_DELXMT    1
-#define REG_T70      13
-#define BIT_T70       2
-#define BIT_T70_EXT  32
-#define REG_DTRHUP   13
-#define BIT_DTRHUP    4
-#define REG_RESPXT   13
-#define BIT_RESPXT    8
-#define REG_CIDONCE  13
-#define BIT_CIDONCE  16
-#define REG_RUNG     13
-#define BIT_RUNG     64
-
-#define REG_L2PROT   14
-#define REG_L3PROT   15
-#define REG_PSIZE    16
-#define REG_WSIZE    17
-#define REG_SI1      18
-#define REG_SI2      19
-#define REG_SI1I     20
-#define REG_PLAN     21
-#define REG_SCREEN   22
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
  * to stuff incoming data directly into a tty's flip-buffer. This
@@ -389,6 +412,8 @@
 				r = 0;
 #ifdef CONFIG_ISDN_AUDIO
 				isdn_audio_eval_dtmf(info);
+				if ((info->vonline & 1) && (info->emu.vpar[1]))
+					isdn_audio_eval_silence(info);
 #endif
 				if ((tty = info->tty)) {
 					if (info->mcr & UART_MCR_RTS) {
@@ -443,8 +468,10 @@
 #ifdef CONFIG_ISDN_AUDIO
 	ifmt = 1;
 	
-	if (info->vonline)
+	if ((info->vonline) && (!info->emu.vpar[4]))
 		isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
+	if ((info->vonline & 1) && (info->emu.vpar[1]))
+		isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
 #endif
 	if ((info->online < 2)
 #ifdef CONFIG_ISDN_AUDIO
@@ -566,8 +593,8 @@
 					   info->isdn_channel, 1, skb)) == len) {
 		struct tty_struct *tty = info->tty;
 		info->send_outstanding++;
-		info->msr |= UART_MSR_CTS;
-		info->lsr |= UART_LSR_TEMT;
+		info->msr &= ~UART_MSR_CTS;
+		info->lsr &= ~UART_LSR_TEMT;
 		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 		    tty->ldisc.write_wakeup)
 			(tty->ldisc.write_wakeup) (tty);
@@ -579,8 +606,6 @@
 		dev_kfree_skb(skb);
 		return;
 	}
-	if (slen)
-		skb_pull(skb, slen);
 	skb_queue_head(&info->xmit_queue, skb);
 }
 
@@ -702,7 +727,6 @@
 	int audio_len;
 #endif
 	struct sk_buff *skb;
-	unsigned long flags;
 
 #ifdef CONFIG_ISDN_AUDIO
 	if (info->vonline & 4) {
@@ -717,18 +741,20 @@
 		}
 	}
 #endif
-	save_flags(flags);
-	cli();
-	if (!(buflen = info->xmit_count)) {
-		restore_flags(flags);
+	if (!(buflen = info->xmit_count))
 		return;
-	}
-	if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
+ 	if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
 		info->msr &= ~UART_MSR_CTS;
-	info->lsr &= ~UART_LSR_TEMT;
+	info->lsr &= ~UART_LSR_TEMT;	
+	/* info->xmit_count is modified here and in isdn_tty_write().
+	 * So we return here if isdn_tty_write() is in the
+	 * critical section.
+	 */
+	atomic_inc(&info->xmit_lock);
+	if (!(atomic_dec_and_test(&info->xmit_lock)))
+		return;
 	if (info->isdn_driver < 0) {
 		info->xmit_count = 0;
-		restore_flags(flags);
 		return;
 	}
 	skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
@@ -742,7 +768,6 @@
 	skb = dev_alloc_skb(skb_res + buflen);
 #endif
 	if (!skb) {
-		restore_flags(flags);
 		printk(KERN_WARNING
 		       "isdn_tty: Out of memory in ttyI%d senddown\n",
 		       info->line);
@@ -751,7 +776,6 @@
 	skb_reserve(skb, skb_res);
 	memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
 	info->xmit_count = 0;
-	restore_flags(flags);
 #ifdef CONFIG_ISDN_AUDIO
 	if (info->vonline & 2) {
 		/* For now, ifmt is fixed to 1 (alaw), since this
@@ -859,7 +883,7 @@
 			break;
 		}
 #ifdef CONFIG_ISDN_AUDIO
-	if (si == 1) {
+	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
 		l2 = ISDN_PROTO_L2_TRANS;
 		usg = ISDN_USAGE_VOICE;
 	}
@@ -907,9 +931,11 @@
 		cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
 		cmd.command = ISDN_CMD_DIAL;
 		info->dialing = 1;
+		info->emu.carrierwait = 0;
 		strcpy(dev->num[i], n);
 		isdn_info_update();
 		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	}
 }
 
@@ -938,10 +964,16 @@
 	}
 #ifdef CONFIG_ISDN_AUDIO
 	info->vonline = 0;
+	info->emu.vpar[4] = 0;
+	info->emu.vpar[5] = 8;
 	if (info->dtmf_state) {
 		kfree(info->dtmf_state);
 		info->dtmf_state = NULL;
 	}
+	if (info->silence_state) {
+		kfree(info->silence_state);
+		info->silence_state = NULL;
+	}
 	if (info->adpcms) {
 		kfree(info->adpcms);
 		info->adpcms = NULL;
@@ -965,8 +997,9 @@
 		}
 		isdn_all_eaz(info->isdn_driver, info->isdn_channel);
 		info->emu.mdmreg[REG_RINGCNT] = 0;
-		usage = (info->emu.mdmreg[REG_SI1I] == 1) ?
-		    ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
+		usage = ((info->emu.mdmreg[REG_SI1I] != 1) || 
+		    (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ?
+			ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
 		isdn_free_channel(info->isdn_driver, info->isdn_channel,
 				  usage);
 	}
@@ -978,6 +1011,226 @@
 	}
 }
 
+/*
+ * Begin of a CAPI like interface, currently used only for 
+ * supplementary service (CAPI 2.0 part III)
+ */
+#include "avmb1/capicmd.h"  /* this should be moved in a common place */
+
+int
+isdn_tty_capi_facility(capi_msg *cm) {
+	return(-1); /* dummy */
+}
+
+/* isdn_tty_suspend() tries to suspend the current tty connection
+ */
+static void
+isdn_tty_suspend(char *id, modem_info * info, atemu * m)
+{
+	isdn_ctrl cmd;
+	
+	int l;
+
+	if (!info)
+		return;
+
+#ifdef ISDN_DEBUG_MODEM_SERVICES
+	printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
+#endif
+	l = strlen(id);
+	if ((info->isdn_driver >= 0) && l) {
+		cmd.parm.cmsg.Length = l+17;
+		cmd.parm.cmsg.Command = CAPI_FACILITY;
+		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
+		cmd.parm.cmsg.para[1] = 0;
+		cmd.parm.cmsg.para[2] = l + 3;
+		cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
+		cmd.parm.cmsg.para[4] = 0;
+		cmd.parm.cmsg.para[5] = l;
+		strncpy(&cmd.parm.cmsg.para[6], id, l);
+		cmd.command = CAPI_PUT_MESSAGE;
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		isdn_command(&cmd);
+	}
+}
+
+/* isdn_tty_resume() tries to resume a suspended call
+ * setup of the lower levels before that. unfortunatly here is no
+ * checking for compatibility of used protocols implemented by Q931
+ * It does the same things like isdn_tty_dial, the last command
+ * is different, may be we can merge it.
+ */
+
+static void
+isdn_tty_resume(char *id, modem_info * info, atemu * m)
+{
+	int usg = ISDN_USAGE_MODEM;
+	int si = 7;
+	int l2 = m->mdmreg[REG_L2PROT];
+	isdn_ctrl cmd;
+	ulong flags;
+	int i;
+	int j;
+	int l;
+
+	l = strlen(id);
+	if (!l) {
+		isdn_tty_modem_result(4, info);
+		return;
+	}
+	for (j = 7; j >= 0; j--)
+		if (m->mdmreg[REG_SI1] & (1 << j)) {
+			si = bit2si[j];
+			break;
+		}
+#ifdef CONFIG_ISDN_AUDIO
+	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+		l2 = ISDN_PROTO_L2_TRANS;
+		usg = ISDN_USAGE_VOICE;
+	}
+#endif
+	m->mdmreg[REG_SI1I] = si2bit[si];
+	save_flags(flags);
+	cli();
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	if (i < 0) {
+		restore_flags(flags);
+		isdn_tty_modem_result(6, info);
+	} else {
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
+		info->last_dir = 1;
+//		strcpy(info->last_num, n);
+		isdn_info_update();
+		restore_flags(flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
+		info->last_l2 = l2;
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.parm.cmsg.Length = l+17;
+		cmd.parm.cmsg.Command = CAPI_FACILITY;
+		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+		cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
+		cmd.parm.cmsg.para[1] = 0;
+		cmd.parm.cmsg.para[2] = l+3;
+		cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
+		cmd.parm.cmsg.para[4] = 0;
+		cmd.parm.cmsg.para[5] = l;
+		strncpy(&cmd.parm.cmsg.para[6], id, l);
+		cmd.command =CAPI_PUT_MESSAGE;
+/*		info->dialing = 1;
+		strcpy(dev->num[i], n);
+		isdn_info_update();
+*/
+		isdn_command(&cmd);
+	}
+}
+
+/* isdn_tty_send_msg() sends a message to a HL driver
+ * This is used for hybrid modem cards to send AT commands to it
+ */
+
+static void
+isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
+{
+	int usg = ISDN_USAGE_MODEM;
+	int si = 7;
+	int l2 = m->mdmreg[REG_L2PROT];
+	isdn_ctrl cmd;
+	ulong flags;
+	int i;
+	int j;
+	int l;
+
+	l = strlen(msg);
+	if (!l) {
+		isdn_tty_modem_result(4, info);
+		return;
+	}
+	for (j = 7; j >= 0; j--)
+		if (m->mdmreg[REG_SI1] & (1 << j)) {
+			si = bit2si[j];
+			break;
+		}
+#ifdef CONFIG_ISDN_AUDIO
+	if ((si == 1) && (l2 != ISDN_PROTO_L2_MODEM)) {
+		l2 = ISDN_PROTO_L2_TRANS;
+		usg = ISDN_USAGE_VOICE;
+	}
+#endif
+	m->mdmreg[REG_SI1I] = si2bit[si];
+	save_flags(flags);
+	cli();
+	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1);
+	if (i < 0) {
+		restore_flags(flags);
+		isdn_tty_modem_result(6, info);
+	} else {
+		info->isdn_driver = dev->drvmap[i];
+		info->isdn_channel = dev->chanmap[i];
+		info->drv_index = i;
+		dev->m_idx[i] = info->line;
+		dev->usage[i] |= ISDN_USAGE_OUTGOING;
+		info->last_dir = 1;
+		isdn_info_update();
+		restore_flags(flags);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.command = ISDN_CMD_CLREAZ;
+		isdn_command(&cmd);
+		strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETEAZ;
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL2;
+		info->last_l2 = l2;
+		cmd.arg = info->isdn_channel + (l2 << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.command = ISDN_CMD_SETL3;
+		cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
+		isdn_command(&cmd);
+		cmd.driver = info->isdn_driver;
+		cmd.arg = info->isdn_channel;
+		cmd.parm.cmsg.Length = l+14;
+		cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
+		cmd.parm.cmsg.Subcommand = CAPI_REQ;
+		cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
+		cmd.parm.cmsg.para[0] = l+1;
+		strncpy(&cmd.parm.cmsg.para[1], msg, l);
+		cmd.parm.cmsg.para[l+1] = 0xd;
+		cmd.command =CAPI_PUT_MESSAGE;
+/*		info->dialing = 1;
+		strcpy(dev->num[i], n);
+		isdn_info_update();
+*/
+		isdn_command(&cmd);
+	}
+}
+
 static inline int
 isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine)
 {
@@ -1138,15 +1391,16 @@
 {
 	int c;
 	int total = 0;
-	ulong flags;
 	modem_info *info = (modem_info *) tty->driver_data;
 
 	if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write"))
 		return 0;
 	if (!tty)
 		return 0;
-	save_flags(flags);
-	cli();
+	if (from_user)
+		down(&info->write_sem);
+	/* See isdn_tty_senddown() */
+	atomic_inc(&info->xmit_lock);
 	while (1) {
 		c = MIN(count, info->xmit_size - info->xmit_count);
 		if (info->isdn_driver >= 0)
@@ -1205,10 +1459,6 @@
 			} else
 #endif
 				info->xmit_count += c;
-			if (m->mdmreg[REG_DELXMT] & BIT_DELXMT) {
-				isdn_tty_senddown(info);
-				isdn_tty_tint(info);
-			}
 		} else {
 			info->msr |= UART_MSR_CTS;
 			info->lsr |= UART_LSR_TEMT;
@@ -1228,7 +1478,9 @@
 	}
 	if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
 		isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
-	restore_flags(flags);
+	atomic_dec(&info->xmit_lock);
+	if (from_user)
+		up(&info->write_sem);
 	return total;
 }
 
@@ -1359,7 +1611,7 @@
 	status = info->lsr;
 	restore_flags(flags);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	put_user(result, (ulong *) value);
+	put_user(result, (uint *) value);
 	return 0;
 }
 
@@ -1383,7 +1635,7 @@
 	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
 	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
 	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	put_user(result, (ulong *) value);
+	put_user(result, (uint *) value);
 	return 0;
 }
 
@@ -1567,8 +1819,12 @@
 static int
 isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
 {
+#ifdef COMPAT_HAS_NEW_WAITQ
+	DECLARE_WAITQUEUE(wait, NULL);
+#else
 	struct wait_queue wait =
 	{current, NULL};
+#endif
 	int do_clocal = 0;
 	unsigned long flags;
 	int retval;
@@ -1891,7 +2147,9 @@
 	m->profile[18] = 4;
 	m->profile[19] = 0;
 	m->profile[20] = 0;
+	m->profile[23] = 0;
 	m->pmsn[0] = '\0';
+	m->plmsn[0] = '\0';
 }
 
 #ifdef CONFIG_ISDN_AUDIO
@@ -1902,6 +2160,8 @@
 	m->vpar[1] = 0;         /* Silence detection level (0 = none      ) */
 	m->vpar[2] = 70;        /* Silence interval        (7 sec.        ) */
 	m->vpar[3] = 2;         /* Compression type        (1 = ADPCM-2   ) */
+	m->vpar[4] = 0;		/* DTMF detection level    (0 = softcode  ) */
+	m->vpar[5] = 8;		/* DTMF interval           (8 * 5 ms.     ) */
 }
 #endif
 
@@ -1912,6 +2172,7 @@
 	if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
 		memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
 		memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
+		memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
 		info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
 	}
 #ifdef CONFIG_ISDN_AUDIO
@@ -1925,6 +2186,7 @@
 {
 	memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
 	memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
+	memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
 	if (dev->profd)
 		send_sig(SIGIO, dev->profd, 1);
 }
@@ -1988,6 +2250,11 @@
 	}
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		info = &m->info[i];
+#ifdef COMPAT_HAS_NEW_WAITQ
+		init_MUTEX(&info->write_sem);
+#else
+		info->write_sem = MUTEX;
+#endif
 		sprintf(info->last_cause, "0000");
 		sprintf(info->last_num, "none");
 		info->last_dir = 0;
@@ -2004,9 +2271,14 @@
 		info->blocked_open = 0;
 		info->callout_termios = m->cua_modem.init_termios;
 		info->normal_termios = m->tty_modem.init_termios;
+#ifdef COMPAT_HAS_NEW_WAITQ
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
+#else
 		info->open_wait = 0;
 		info->close_wait = 0;
 		info->isdn_driver = -1;
+#endif
 		info->isdn_channel = -1;
 		info->drv_index = -1;
 		info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
@@ -2024,25 +2296,67 @@
 	return 0;
 }
 
+static int
+isdn_tty_match_icall(char *cid, atemu *emu, int di)
+{
+#ifdef ISDN_DEBUG_MODEM_ICALL
+	printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
+	       emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
+	       emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
+#endif
+	if (strlen(emu->lmsn)) {
+		char *p = emu->lmsn;
+		char *q;
+		int  tmp;
+		int  ret = 0;
+
+		while (1) {
+			if ((q = strchr(p, ';')))
+				*q = '\0';
+			if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret)
+				ret = tmp;
+#ifdef ISDN_DEBUG_MODEM_ICALL
+			printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
+			       p, isdn_map_eaz2msn(emu->msn, di), tmp);
+#endif
+			if (q) {
+				*q = ';';
+				p = q;
+				p++;
+			}
+			if (!tmp)
+				return 0;
+			if (!q)
+				break;
+		}
+		return ret;
+	} else
+		return isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di));
+}
+
 /*
  * An incoming call-request has arrived.
  * Search the tty-devices for an appropriate device and bind
  * it to the ISDN-Channel.
- * Return Index to dev->mdm or -1 if none found.
+ * Return:
+ *
+ *  0 = No matching device found.
+ *  1 = A matching device found.
+ *  3 = No match found, but eventually would match, if
+ *      CID is longer.
  */
 int
 isdn_tty_find_icall(int di, int ch, setup_parm setup)
 {
 	char *eaz;
 	int i;
+	int wret;
 	int idx;
 	int si1;
 	int si2;
 	char nr[32];
 	ulong flags;
 
-	save_flags(flags);
-	cli();
 	if (!setup.phone[0]) {
 		nr[0] = '0';
 		nr[1] = '\0';
@@ -2059,17 +2373,14 @@
 #ifdef ISDN_DEBUG_MODEM_ICALL
 	printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
 #endif
+	wret = 0;
+	save_flags(flags);
+	cli();
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		modem_info *info = &dev->mdm.info[i];
-#ifdef ISDN_DEBUG_MODEM_ICALL
-		printk(KERN_DEBUG "m_fi: i=%d msn=%s mmsn=%s mreg18=%d mreg19=%d\n", i,
-		       info->emu.msn, isdn_map_eaz2msn(info->emu.msn, di),
-		       info->emu.mdmreg[REG_SI1], info->emu.mdmreg[REG_SI2]);
-#endif
-		if ((!strcmp(isdn_map_eaz2msn(info->emu.msn, di),
-			     eaz)) &&	                          /* EAZ is matching */
-		    (info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
-		    (info->emu.mdmreg[REG_SI2] == si2)) {	  /* SI2 is matching */
+
+		if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
+		    (info->emu.mdmreg[REG_SI2] == si2))	{         /* SI2 is matching */
 			idx = isdn_dc2minor(di, ch);
 #ifdef ISDN_DEBUG_MODEM_ICALL
 			printk(KERN_DEBUG "m_fi: match1\n");
@@ -2081,34 +2392,42 @@
 #ifndef FIX_FILE_TRANSFER
 				(info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
 #endif
-			    (info->isdn_driver == -1) &&
-			    (info->isdn_channel == -1) &&
-			    (USG_NONE(dev->usage[idx]))) {
-				info->isdn_driver = di;
-				info->isdn_channel = ch;
-				info->drv_index = idx;
-				dev->m_idx[idx] = info->line;
-				dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
-				dev->usage[idx] |= (si1 == 1) ? ISDN_USAGE_VOICE : ISDN_USAGE_MODEM;
-				strcpy(dev->num[idx], nr);
-				info->emu.mdmreg[REG_SI1I] = si2bit[si1];
-				info->emu.mdmreg[REG_PLAN] = setup.plan;
-				info->emu.mdmreg[REG_SCREEN] = setup.screen;
-				isdn_info_update();
-				restore_flags(flags);
-				printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
-				       info->line);
-				info->msr |= UART_MSR_RI;
-				isdn_tty_modem_result(2, info);
-				isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
-				return info->line;
+				(info->isdn_driver == -1) &&
+				(info->isdn_channel == -1) &&
+				(USG_NONE(dev->usage[idx]))) {
+				int matchret;
+
+				if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
+					wret = matchret;
+				if (!matchret) {                  /* EAZ is matching */
+					info->isdn_driver = di;
+					info->isdn_channel = ch;
+					info->drv_index = idx;
+					dev->m_idx[idx] = info->line;
+					dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
+					dev->usage[idx] |= ((si1 != 1) || (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) ? 
+						ISDN_USAGE_MODEM : ISDN_USAGE_VOICE;
+					strcpy(dev->num[idx], nr);
+					strcpy(info->emu.cpn, eaz);
+					info->emu.mdmreg[REG_SI1I] = si2bit[si1];
+					info->emu.mdmreg[REG_PLAN] = setup.plan;
+					info->emu.mdmreg[REG_SCREEN] = setup.screen;
+					isdn_info_update();
+					restore_flags(flags);
+					printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
+					       info->line);
+					info->msr |= UART_MSR_RI;
+					isdn_tty_modem_result(2, info);
+					isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
+					return 1;
+				}
 			}
 		}
 	}
-	printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
-	       dev->drv[di]->reject_bus ? "rejected" : "ignored");
 	restore_flags(flags);
-	return -1;
+	printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
+	       ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");
+	return (wret == 2)?3:0;
 }
 
 #define TTY_IS_ACTIVE(info) \
@@ -2129,7 +2448,7 @@
                         case ISDN_STAT_CINF:
                                 printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
                                 info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
-                                if (e == c->parm.num)
+                                if (e == (char *)c->parm.num)
 					info->emu.charge = 0;
 				
                                 break;			
@@ -2154,6 +2473,19 @@
 				/* Signal cause to tty-device */
 				strncpy(info->last_cause, c->parm.num, 5);
 				return 1;
+			case ISDN_STAT_DISPLAY:
+#ifdef ISDN_TTY_STAT_DEBUG
+				printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);
+#endif
+				/* Signal display to tty-device */
+				if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && 
+					!(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {
+				  isdn_tty_at_cout("\r\n", info);
+				  isdn_tty_at_cout("DISPLAY: ", info);
+				  isdn_tty_at_cout(c->parm.display, info);
+				  isdn_tty_at_cout("\r\n", info);
+				}
+				return 1;
 			case ISDN_STAT_DCONN:
 #ifdef ISDN_TTY_STAT_DEBUG
 				printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
@@ -2170,10 +2502,11 @@
 				printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
 #endif
 				if (TTY_IS_ACTIVE(info)) {
-					if (info->dialing == 1) {
-						info->dialing = 0;
+					if (info->dialing == 1) 
 						isdn_tty_modem_result(7, info);
-					}
+					if (info->dialing > 1) 
+						isdn_tty_modem_result(3, info);
+					info->dialing = 0;
 #ifdef ISDN_DEBUG_MODEM_HUP
 					printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
 #endif
@@ -2192,14 +2525,20 @@
 				if (TTY_IS_ACTIVE(info)) {
 					info->msr |= UART_MSR_DCD;
 					info->emu.charge = 0;
-					if (info->dialing) {
-						info->dialing = 0;
+					if (info->dialing & 0xf)
 						info->last_dir = 1;
-					} else
+					else
 						info->last_dir = 0;
+					info->dialing = 0;
 					info->rcvsched = 1;
-					if (USG_MODEM(dev->usage[i]))
-						isdn_tty_modem_result(5, info);
+					if (USG_MODEM(dev->usage[i])) {
+						if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
+							strcpy(info->emu.connmsg, c->parm.num);
+							isdn_tty_modem_result(1, info);
+						}
+						else
+							isdn_tty_modem_result(5, info);
+					}
 					if (USG_VOICE(dev->usage[i]))
 						isdn_tty_modem_result(11, info);
 					return 1;
@@ -2229,11 +2568,7 @@
 						sprintf(info->last_cause, "0000");
 						isdn_tty_modem_result(6, info);
 					}
-					info->msr &= ~UART_MSR_DCD;
-					if (info->online) {
-						isdn_tty_modem_result(3, info);
-						info->online = 0;
-					}
+					isdn_tty_modem_hup(info, 0);
 					return 1;
 				}
 				break;
@@ -2249,6 +2584,20 @@
 					}
 				}
 				return 1;
+#ifdef CONFIG_ISDN_AUDIO
+			case ISDN_STAT_AUDIO:
+				if (TTY_IS_ACTIVE(info)) {
+					switch(c->parm.num[0]) {
+						case ISDN_AUDIO_DTMF:
+							if (info->vonline) {
+								isdn_audio_put_dle_code(info,
+									c->parm.num[1]);
+							}
+							break;
+					}
+				}
+				break;
+#endif
 		}
 	}
 	return 0;
@@ -2258,13 +2607,13 @@
  Modem-Emulator-Routines
  *********************************************************************/
 
-#define cmdchar(c) ((c>' ')&&(c<=0x7f))
+#define cmdchar(c) ((c>=' ')&&(c<=0x7f))
 
 /*
  * Put a message from the AT-emulator into receive-buffer of tty,
  * convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
  */
-static void
+void
 isdn_tty_at_cout(char *msg, modem_info * info)
 {
 	struct tty_struct *tty;
@@ -2394,7 +2743,7 @@
 	 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
 	 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
 	ulong flags;
-	char s[10];
+	char s[ISDN_MSNLEN+10];
 
 	switch (code) {
 		case 2:
@@ -2474,7 +2823,20 @@
 			}
 			isdn_tty_at_cout(msg[code], info);
 			switch (code) {
+				case 1:
+					switch (m->mdmreg[REG_L2PROT]) {
+						case ISDN_PROTO_L2_MODEM:
+							isdn_tty_at_cout(" ", info);
+							isdn_tty_at_cout(m->connmsg, info);
+							break;
+					}
+					break;
 				case 2:
+					/* Append CPN, if enabled */
+					if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
+						sprintf(s, "/%s", m->cpn);
+						isdn_tty_at_cout(s, info);
+					}
 					/* Print CID only once, _after_ 1.st RING */
 					if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
 					    (m->mdmreg[REG_RINGCNT] == 1)) {
@@ -2561,7 +2923,9 @@
 static void
 isdn_tty_get_msnstr(char *n, char **p)
 {
-	while ((*p[0] >= '0' && *p[0] <= '9') || (*p[0] == ','))
+	while ((*p[0] >= '0' && *p[0] <= '9') ||
+	       /* Why a comma ??? */
+	       (*p[0] == ','))
 		*n++ = *p[0]++;
 	*n = '\0';
 }
@@ -2576,8 +2940,9 @@
 	int limit=39;	/* MUST match the size in isdn_tty_parse to avoid
 				buffer overflow */
 
-	while (strchr("0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
-		if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first))
+	while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
+		if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
+		    (*p == '*') || (*p == '#'))
 			*q++ = *p;
 		p++;
 		if(!--limit)
@@ -2627,6 +2992,12 @@
 		case ISDN_PROTO_L2_TRANS:
 			isdn_tty_at_cout("transparent", info);
 			break;
+		case ISDN_PROTO_L2_MODEM:
+			isdn_tty_at_cout("modem", info);
+			break;
+		case ISDN_PROTO_L2_FAX:
+			isdn_tty_at_cout("fax", info);
+			break;
 		default:
 			isdn_tty_at_cout("unknown", info);
 			break;
@@ -2669,6 +3040,8 @@
 	int i;
 	char rb[100];
 
+#define MAXRB (sizeof(rb) - 1)
+
 	switch (*p[0]) {
 		case 'B':
 			/* &B - Set Buffersize */
@@ -2720,6 +3093,15 @@
 			isdn_tty_reset_profile(m);
 			isdn_tty_modem_reset_regs(info, 1);
 			break;
+		case 'L':
+			/* &L -Set Numbers to listen on */
+			p[0]++;
+			i = 0;
+			while ((strchr("0123456789,-*[]?;", *p[0])) &&
+			       (i < ISDN_LMSNLEN) && *p[0])
+				m->lmsn[i++] = *p[0]++;
+			m->lmsn[i] = '\0';
+			break;
 		case 'R':
 			/* &R - Set V.110 bitrate adaption */
 			p[0]++;
@@ -2775,6 +3157,11 @@
 			sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
 				strlen(m->msn) ? m->msn : "None");
 			isdn_tty_at_cout(rb, info);
+			if (strlen(m->lmsn)) {
+				isdn_tty_at_cout("\r\nListen: ", info);
+				isdn_tty_at_cout(m->lmsn, info);
+				isdn_tty_at_cout("\r\n", info);
+			}
 			break;
 		case 'W':
 			/* &W - Write Profile */
@@ -2867,7 +3254,7 @@
 	int bval;
 
 	mreg = isdn_getnum(p);
-	if (mreg < 0 || mreg > ISDN_MODEM_ANZREG)
+	if (mreg < 0 || mreg >= ISDN_MODEM_ANZREG)
 		PARSE_ERROR1;
 	switch (*p[0]) {
 		case '=':
@@ -2940,9 +3327,10 @@
 #ifdef CONFIG_ISDN_AUDIO
 		/* If more than one bit set in reg18, autoselect Layer2 */
 		if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
-			if (m->mdmreg[REG_SI1I] == 1)
-				l2 = ISDN_PROTO_L2_TRANS;
-			else
+			if (m->mdmreg[REG_SI1I] == 1) {
+				if (l2 != ISDN_PROTO_L2_MODEM)
+					l2 = ISDN_PROTO_L2_TRANS;
+			} else
 				l2 = ISDN_PROTO_L2_X75I;
 		}
 #endif
@@ -2958,7 +3346,10 @@
 		cmd.driver = info->isdn_driver;
 		cmd.arg = info->isdn_channel;
 		cmd.command = ISDN_CMD_ACCEPTD;
+		info->dialing = 16;
+		info->emu.carrierwait = 0;
 		isdn_command(&cmd);
+		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	} else
 		isdn_tty_modem_result(8, info);
 }
@@ -3133,8 +3524,9 @@
 isdn_tty_cmd_PLUSV(char **p, modem_info * info)
 {
 	atemu *m = &info->emu;
+	isdn_ctrl cmd;
 	static char *vcmd[] =
-	{"NH", "IP", "LS", "RX", "SD", "SM", "TX", NULL};
+	{"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL};
 	int i;
 	int par1;
 	int par2;
@@ -3222,6 +3614,11 @@
 				printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
 				PARSE_ERROR1;
 			}
+			info->silence_state = isdn_audio_silence_init(info->silence_state);
+			if (!info->silence_state) {
+				printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
+				PARSE_ERROR1;
+			}
 			if (m->vpar[3] < 5) {
 				info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
 				if (!info->adpcmr) {
@@ -3248,31 +3645,27 @@
 					break;
 				case '=':
 					p[0]++;
-					switch (*p[0]) {
-						case '0':
-						case '1':
-						case '2':
-						case '3':
-							par1 = isdn_getnum(p);
-							if ((par1 < 0) || (par1 > 31))
-								PARSE_ERROR1;
-							if (*p[0] != ',')
-								PARSE_ERROR1;
-							p[0]++;
-							par2 = isdn_getnum(p);
-							if ((par2 < 0) || (par2 > 255))
-								PARSE_ERROR1;
-							m->vpar[1] = par1;
-							m->vpar[2] = par2;
-							break;
-						case '?':
-							p[0]++;
-							isdn_tty_at_cout("\r\n<0-31>,<0-255>",
-								   info);
-							break;
-						default:
+					if ((*p[0]>='0') && (*p[0]<='9')) {
+						par1 = isdn_getnum(p);
+						if ((par1 < 0) || (par1 > 31))
 							PARSE_ERROR1;
-					}
+						if (*p[0] != ',')
+							PARSE_ERROR1;
+						p[0]++;
+						par2 = isdn_getnum(p);
+						if ((par2 < 0) || (par2 > 255))
+							PARSE_ERROR1;
+						m->vpar[1] = par1;
+						m->vpar[2] = par2;
+						break;
+					} else 
+					if (*p[0] == '?') {
+						p[0]++;
+						isdn_tty_at_cout("\r\n<0-31>,<0-255>",
+							   info);
+						break;
+					} else
+					PARSE_ERROR1;
 					break;
 				default:
 					PARSE_ERROR1;
@@ -3309,9 +3702,9 @@
 								   info);
 							isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
 								   info);
-							isdn_tty_at_cout("5;ALAW;8;0;(8000)",
+							isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n",
 								   info);
-							isdn_tty_at_cout("6;ULAW;8;0;(8000)",
+							isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n",
 								   info);
 							break;
 						default:
@@ -3350,6 +3743,52 @@
 			isdn_tty_modem_result(1, info);
 			return 0;
 			break;
+		case 7:
+			/* AT+VDD - DTMF detection */
+			switch (*p[0]) {
+				case '?':
+					p[0]++;
+					sprintf(rs, "\r\n<%d>,<%d>",
+						m->vpar[4],
+						m->vpar[5]);
+					isdn_tty_at_cout(rs, info);
+					break;
+				case '=':
+					p[0]++;
+					if ((*p[0]>='0') && (*p[0]<='9')) {
+						if (info->online != 1)
+							PARSE_ERROR1;
+						par1 = isdn_getnum(p);
+						if ((par1 < 0) || (par1 > 15))
+							PARSE_ERROR1;
+						if (*p[0] != ',')
+							PARSE_ERROR1;
+						p[0]++;
+						par2 = isdn_getnum(p);
+						if ((par2 < 0) || (par2 > 255))
+							PARSE_ERROR1;
+						m->vpar[4] = par1;
+						m->vpar[5] = par2;
+						cmd.driver = info->isdn_driver;
+						cmd.command = ISDN_CMD_AUDIO;
+						cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
+						cmd.parm.num[0] = par1;
+						cmd.parm.num[1] = par2;
+						isdn_command(&cmd);
+						break;
+					} else
+					if (*p[0] == '?') {
+						p[0]++;
+						isdn_tty_at_cout("\r\n<0-15>,<0-255>",
+							info);
+						break;
+					} else
+					PARSE_ERROR1;
+					break;
+				default:
+					PARSE_ERROR1;
+			}
+			break;
 		default:
 			PARSE_ERROR1;
 	}
@@ -3372,6 +3811,9 @@
 #endif
 	for (p = &m->mdmcmd[2]; *p;) {
 		switch (*p) {
+			case ' ':
+				p++;
+				break;
 			case 'A':
 				/* A - Accept incoming call */
 				p++;
@@ -3446,7 +3888,7 @@
 				p++;
 				if (info->msr & UART_MSR_DCD)
 					/* if B-Channel is up */
-					isdn_tty_modem_result(5, info);
+					isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? 1:5, info);
 				else
 					isdn_tty_modem_result(3, info);
 				return;
@@ -3487,29 +3929,46 @@
 			case 'Z':
 				/* Z - Load Registers from Profile */
 				p++;
+				if (info->msr & UART_MSR_DCD) {
+					info->online = 0;
+					isdn_tty_on_hook(info);
+				}
 				isdn_tty_modem_reset_regs(info, 1);
 				break;
-#ifdef CONFIG_ISDN_AUDIO
 			case '+':
 				p++;
 				switch (*p) {
+#ifdef CONFIG_ISDN_AUDIO
 					case 'F':
 						p++;
 						if (isdn_tty_cmd_PLUSF(&p, info))
 							return;
 						break;
 					case 'V':
-						if (!(m->mdmreg[REG_SI1] & 1))
+						if ((!(m->mdmreg[REG_SI1] & 1)) ||
+							(m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
 							PARSE_ERROR;
 						p++;
 						if (isdn_tty_cmd_PLUSV(&p, info))
 							return;
 						break;
+#endif                          /* CONFIG_ISDN_AUDIO */
+					case 'S':	/* SUSPEND */
+						p++;
+						isdn_tty_get_msnstr(ds, &p);
+						isdn_tty_suspend(ds, info, m);
+						break;
+					case 'R':	/* RESUME */
+						isdn_tty_get_msnstr(ds, &p);
+						isdn_tty_resume(ds, info, m);
+					case 'M':	/* MESSAGE */
+						p++;
+						isdn_tty_send_msg(info, m, p);
+						break;
 					default:
 						PARSE_ERROR;
 				}
 				break;
-#endif                          /* CONFIG_ISDN_AUDIO */
 			case '&':
 				p++;
 				if (isdn_tty_cmd_ATand(&p, info))
@@ -3562,7 +4021,7 @@
 				eb[1] = 0;
 				isdn_tty_at_cout(eb, info);
 			}
-			if (m->mdmcmdl >= 2)
+			if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2))))
 				isdn_tty_parse_at(info);
 			m->mdmcmdl = 0;
 			continue;
@@ -3588,15 +4047,16 @@
 				switch (m->mdmcmdl) {
 					case 0:
 						if (c == 'A')
-							m->mdmcmd[m->mdmcmdl++] = c;
+							m->mdmcmd[m->mdmcmdl] = c;
 						break;
 					case 1:
 						if (c == 'T')
-							m->mdmcmd[m->mdmcmdl++] = c;
+							m->mdmcmd[m->mdmcmdl] = c;
 						break;
 					default:
-						m->mdmcmd[m->mdmcmdl++] = c;
+						m->mdmcmd[m->mdmcmdl] = c;
 				}
+				m->mdmcmd[++m->mdmcmdl] = 0;
 			}
 		}
 	}
@@ -3673,4 +4133,29 @@
 		}
 	}
 	isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
+}
+
+/*
+ * Check all channels if we have a 'no carrier' timeout.
+ * Timeout value is set by Register S7.
+ */
+void
+isdn_tty_carrier_timeout(void)
+{
+	int ton = 0;
+	int i;
+
+	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+		modem_info *info = &dev->mdm.info[i];
+		if (info->dialing) {
+			if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
+				info->dialing = 0;
+				isdn_tty_modem_result(3, info);
+				isdn_tty_modem_hup(info, 1);
+			}
+			else
+				ton = 1;
+		}
+	}
+	isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_tty.h linux.pre11.3/drivers/isdn/isdn_tty.h
--- linux.vanilla/drivers/isdn/isdn_tty.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/isdn_tty.h	Mon Jul 19 23:59:35 1999
@@ -1,8 +1,8 @@
-/* $Id: isdn_tty.h,v 1.10 1997/03/02 14:29:26 fritz Exp $
+/* $Id: isdn_tty.h,v 1.14 1999/07/11 17:14:15 armin Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
+ * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
  * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
  *
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,35 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.h,v $
+ * Revision 1.14  1999/07/11 17:14:15  armin
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ * Moved "Add CPN to RING message" to new register S23,
+ * "Display message" is now correct on register S13 bit 7.
+ * New audio command AT+VDD implemented (deactivate DTMF decoder and
+ * activate possible existing hardware/DSP decoder).
+ * Moved some tty defines to .h file.
+ * Made whitespace possible in AT command line.
+ * Some AT-emulator output bugfixes.
+ * First Fax G3 implementations.
+ *
+ * Revision 1.13  1999/04/12 12:33:46  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.12  1999/03/02 12:04:51  armin
+ * -added ISDN_STAT_ADDCH to increase supported channels after
+ *  register_isdn().
+ * -ttyI now goes on-hook on ATZ when B-Ch is connected.
+ * -added timer-function for register S7 (Wait for Carrier).
+ * -analog modem (ISDN_PROTO_L2_MODEM) implementations.
+ * -on L2_MODEM a string will be appended to the CONNECT-Message,
+ *  which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN.
+ * -variable "dialing" used for ATA also, for interrupting call
+ *  establishment and register S7.
+ *
+ * Revision 1.11  1998/03/19 13:18:27  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
  * Revision 1.10  1997/03/02 14:29:26  fritz
  * More ttyI related cleanup.
  *
@@ -54,8 +83,71 @@
  *
  */
 
+
+#define DLE 0x10
+#define ETX 0x03
+#define DC4 0x14
+
+
+/*
+ * Definition of some special Registers of AT-Emulator
+ */
+#define REG_RINGATA   0
+#define REG_RINGCNT   1
+#define REG_ESC       2
+#define REG_CR        3
+#define REG_LF        4
+#define REG_BS        5
+
+#define REG_WAITC     7
+
+#define REG_RESP     12
+#define BIT_RESP      1
+#define REG_RESPNUM  12
+#define BIT_RESPNUM   2
+#define REG_ECHO     12
+#define BIT_ECHO      4
+#define REG_DCD      12
+#define BIT_DCD       8
+#define REG_CTS      12
+#define BIT_CTS      16
+#define REG_DTRR     12
+#define BIT_DTRR     32
+#define REG_DSR      12
+#define BIT_DSR      64
+#define REG_CPPP     12
+#define BIT_CPPP    128
+
+#define REG_T70      13
+#define BIT_T70       2
+#define BIT_T70_EXT  32
+#define REG_DTRHUP   13
+#define BIT_DTRHUP    4
+#define REG_RESPXT   13
+#define BIT_RESPXT    8
+#define REG_CIDONCE  13
+#define BIT_CIDONCE  16
+#define REG_RUNG     13
+#define BIT_RUNG     64
+#define REG_DISPLAY  13
+#define BIT_DISPLAY 128
+
+#define REG_L2PROT   14
+#define REG_L3PROT   15
+#define REG_PSIZE    16
+#define REG_WSIZE    17
+#define REG_SI1      18
+#define REG_SI2      19
+#define REG_SI1I     20
+#define REG_PLAN     21
+#define REG_SCREEN   22
+
+#define REG_CPN      23
+#define BIT_CPN       1
+
 extern void isdn_tty_modem_escape(void);
 extern void isdn_tty_modem_ring(void);
+extern void isdn_tty_carrier_timeout(void);
 extern void isdn_tty_modem_xmit(void);
 extern int isdn_tty_modem_init(void);
 extern void isdn_tty_readmodem(void);
@@ -63,3 +155,5 @@
 extern void isdn_tty_cleanup_xmit(modem_info *);
 extern int isdn_tty_stat_callback(int, isdn_ctrl *);
 extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
+extern int isdn_tty_capi_facility(capi_msg *cm); 
+extern void isdn_tty_at_cout(char *, modem_info *);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdn_x25iface.c linux.pre11.3/drivers/isdn/isdn_x25iface.c
--- linux.vanilla/drivers/isdn/isdn_x25iface.c	Sat Jan  9 21:50:38 1999
+++ linux.pre11.3/drivers/isdn/isdn_x25iface.c	Mon Jul 19 23:59:35 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn_x25iface.c,v 1.3 1998/02/20 17:25:20 fritz Exp $
+/* $Id: isdn_x25iface.c,v 1.6 1999/01/27 22:53:19 he Exp $
  * stuff needed to support the Linux X.25 PLP code on top of devices that
  * can provide a lab_b service using the concap_proto mechanism.
  * This module supports a network interface wich provides lapb_sematics
@@ -10,6 +10,17 @@
  * goes to another -- device related -- concap_proto support source file.
  *
  * $Log: isdn_x25iface.c,v $
+ * Revision 1.6  1999/01/27 22:53:19  he
+ * minor updates (spellings, jiffies wrap around in isdn_tty)
+ *
+ * Revision 1.5  1998/10/30 17:55:39  he
+ * dialmode for x25iface and multulink ppp
+ *
+ * Revision 1.4  1998/06/17 19:51:00  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
  * Revision 1.3  1998/02/20 17:25:20  fritz
  * Changes for recent kernels.
  *
@@ -302,7 +313,12 @@
 	case 0x01: /* dl_connect request */
 		if( *state == WAN_DISCONNECTED ){
 			*state = WAN_CONNECTING;
-		        cprot -> dops -> connect_req(cprot);
+		        ret = cprot -> dops -> connect_req(cprot);
+			if(ret){
+				/* reset state and notify upper layer about
+				 * immidiatly failed attempts */
+				isdn_x25iface_disconn_ind(cprot);
+			}
 		} else {
 			illegal_state_warn( *state, firstbyte );
 		}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdnloop/isdnloop.c linux.pre11.3/drivers/isdn/isdnloop/isdnloop.c
--- linux.vanilla/drivers/isdn/isdnloop/isdnloop.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/isdnloop/isdnloop.c	Mon Jul 19 23:59:35 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.c,v 1.4 1998/02/24 21:39:05 he Exp $
+/* $Id: isdnloop.c,v 1.8 1998/11/18 18:59:43 armin Exp $
 
  * ISDN low-level module implementing a dummy loop driver.
  *
@@ -19,6 +19,20 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdnloop.c,v $
+ * Revision 1.8  1998/11/18 18:59:43  armin
+ * changes for 2.1.127
+ *
+ * Revision 1.7  1998/10/30 18:58:03  he
+ * typecast to suppress a compiler warning
+ *
+ * Revision 1.6  1998/06/17 19:51:37  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.5  1998/04/14 20:59:32  he
+ * merged 2.1.94 changes
+ *
  * Revision 1.4  1998/02/24 21:39:05  he
  * L2_PROT_X25DTE / DCE
  * additional state 17 and new internal signal messages "BCON_I"
@@ -42,7 +56,7 @@
 #include "isdnloop.h"
 
 static char
-*revision = "$Revision: 1.4 $";
+*revision = "$Revision: 1.8 $";
 
 static int isdnloop_addcard(char *);
 
@@ -1312,7 +1326,7 @@
 							c->parm.num[0] ? "N" : "ALL", c->parm.num);
 					} else
 						sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
-							c->parm.num[0] ? c->parm.num : "0123456789");
+							c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");
 					i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
 				}
 				break;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/isdnloop/isdnloop.h linux.pre11.3/drivers/isdn/isdnloop/isdnloop.h
--- linux.vanilla/drivers/isdn/isdnloop/isdnloop.h	Sun Nov  8 15:08:10 1998
+++ linux.pre11.3/drivers/isdn/isdnloop/isdnloop.h	Mon Jul 19 23:59:35 1999
@@ -1,4 +1,4 @@
-/* $Id: isdnloop.h,v 1.2 1997/10/01 09:22:07 fritz Exp $
+/* $Id: isdnloop.h,v 1.3 1998/04/14 20:59:35 he Exp $
 
  * Loopback lowlevel module for testing of linklevel.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdnloop.h,v $
+ * Revision 1.3  1998/04/14 20:59:35  he
+ * merged 2.1.94 changes
+ *
  * Revision 1.2  1997/10/01 09:22:07  fritz
  * Removed old compatibility stuff for 2.0.X kernels.
  * From now on, this code is for 2.1.X ONLY!
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/pcbit/callbacks.c linux.pre11.3/drivers/isdn/pcbit/callbacks.c
--- linux.vanilla/drivers/isdn/pcbit/callbacks.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/pcbit/callbacks.c	Mon Jul 19 23:59:35 1999
@@ -11,6 +11,13 @@
  *        callbacks for the FSM
  */
 
+/*
+ * Fix: 19981230 - Carlos Morgado <chbm@techie.com>
+ * Port of Nelson Escravana's <nelson.escravana@usa.net> fix to CalledPN 
+ * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
+ */
+
+
 #define __NO_VERSION__
 
 #include <linux/module.h>
@@ -164,12 +171,24 @@
          *  ictl.num >= strlen() + strlen() + 5
          */
 
+	if (cbdata->data.setup.CallingPN == NULL) {
+		printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n");
+		strcpy(ictl.parm.setup.phone, "0");
+	}
+	else {
 		strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN);
+	}
+	if (cbdata->data.setup.CalledPN == NULL) {
+		printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n");
+		strcpy(ictl.parm.setup.eazmsn, "0");
+	}
+	else {
 		strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN);
-		ictl.parm.setup.si1 = 7;
-		ictl.parm.setup.si2 = 0;
-		ictl.parm.setup.plan = 0;
-		ictl.parm.setup.screen = 0;
+	}
+	ictl.parm.setup.si1 = 7;
+	ictl.parm.setup.si2 = 0;
+	ictl.parm.setup.plan = 0;
+	ictl.parm.setup.screen = 0;
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "statstr: %s\n", ictl.num);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/pcbit/drv.c linux.pre11.3/drivers/isdn/pcbit/drv.c
--- linux.vanilla/drivers/isdn/pcbit/drv.c	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/pcbit/drv.c	Mon Jul 19 23:59:35 1999
@@ -86,6 +86,9 @@
 
 	dev_pcbit[board] = dev;
 	memset(dev, 0, sizeof(struct pcbit_dev));
+#ifdef COMPAT_HAS_NEW_WAITQ
+	init_waitqueue_head(&dev->set_running_wq);
+#endif
 
 	if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF )
 		dev->sh_mem = (unsigned char*) mem_base;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/pcbit/pcbit.h linux.pre11.3/drivers/isdn/pcbit/pcbit.h
--- linux.vanilla/drivers/isdn/pcbit/pcbit.h	Sun Nov  8 15:08:08 1998
+++ linux.pre11.3/drivers/isdn/pcbit/pcbit.h	Mon Jul 19 23:59:35 1999
@@ -68,7 +68,11 @@
 	struct frame_buf *write_queue;
 
 	/* Protocol start */
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t set_running_wq;
+#else
 	struct wait_queue *set_running_wq;
+#endif
 	struct timer_list set_running_timer;
 
 	struct timer_list error_recover_timer;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/isdn/sc/message.c linux.pre11.3/drivers/isdn/sc/message.c
--- linux.vanilla/drivers/isdn/sc/message.c	Sun Nov  8 15:10:15 1998
+++ linux.pre11.3/drivers/isdn/sc/message.c	Mon Jul 19 23:59:35 1999
@@ -1,5 +1,5 @@
 /*
- *  $Id: message.c,v 1.3 1998/01/31 22:10:55 keil Exp $
+ *  $Id: message.c,v 1.4 1999/01/05 18:29:47 he Exp $
  *  Copyright (C) 1996  SpellCaster Telecommunications Inc.
  *
  *  message.c - functions for sending and receiving control messages
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Config.in linux.pre11.3/drivers/net/Config.in
--- linux.vanilla/drivers/net/Config.in	Tue Jun 15 16:49:49 1999
+++ linux.pre11.3/drivers/net/Config.in	Mon Jul 19 23:27:25 1999
@@ -2,6 +2,9 @@
 # Network device configuration
 #
 
+mainmenu_option next_comment
+comment 'ARCnet devices'
+
 tristate 'ARCnet support' CONFIG_ARCNET
 if [ "$CONFIG_ARCNET" != "n" ]; then
   bool '  Enable arc0e (ARCnet "Ether-Encap" packet format)' CONFIG_ARCNET_ETH
@@ -12,6 +15,8 @@
   dep_tristate '  ARCnet COM20020 chipset driver' CONFIG_ARCNET_COM20020 $CONFIG_ARCNET
 fi
 
+endmenu
+
 tristate 'Dummy net driver support' CONFIG_DUMMY
 tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -22,6 +27,10 @@
 #
 #	Ethernet
 #
+
+mainmenu_option next_comment
+comment 'Ethernet (10 or 100Mbit)'
+
 bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
 if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
   if [ "$CONFIG_ARM" = "y" ]; then
@@ -42,7 +51,7 @@
     tristate 'Hydra support' CONFIG_HYDRA
   fi
   if [ "$CONFIG_MIPS_JAZZ" = "y" ]; then
-    bool 'MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC
+    tristate 'MIPS JAZZ onboard SONIC Ethernet support' CONFIG_MIPS_JAZZ_SONIC
   fi
   bool '3COM cards' CONFIG_NET_VENDOR_3COM
   if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
@@ -82,18 +91,15 @@
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
       tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN
-      tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC
   fi
   bool 'Other ISA cards' CONFIG_NET_ISA
   if [ "$CONFIG_NET_ISA" = "y" ]; then
-    tristate 'AT1700/1720 support' CONFIG_AT1700
+    tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
     tristate 'Cabletron E21xx support' CONFIG_E2100
     tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
     tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
     tristate 'EtherExpress 16 support' CONFIG_EEXPRESS
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
-    fi
+    tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
     tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
     tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
     tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
@@ -103,7 +109,7 @@
     fi
     tristate 'NE2000/NE1000 support' CONFIG_NE2000
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      bool 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
+      tristate 'SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
     fi
     bool 'SK_G16 support' CONFIG_SK_G16
   fi
@@ -115,6 +121,7 @@
   if [ "$CONFIG_NET_EISA" = "y" ]; then
     tristate 'AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC
       tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200
     fi
 
@@ -145,6 +152,8 @@
   fi
 fi
 
+endmenu
+
 bool 'FDDI driver support' CONFIG_FDDI
 if [ "$CONFIG_FDDI" = "y" ]; then
   bool 'Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
@@ -153,25 +162,20 @@
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'HIPPI driver support (EXPERIMENTAL)' CONFIG_HIPPI
   if [ "$CONFIG_HIPPI" = "y" ]; then
-    bool 'CERN HIPPI PCI adapter support' CONFIG_CERN_HIPPI
-    bool 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER
+    tristate 'Essential RoadRunner HIPPI PCI adapter support' CONFIG_ROADRUNNER
     if [ "$CONFIG_ROADRUNNER" != "n" ]; then
       bool '  Use large TX/RX rings' CONFIG_ROADRUNNER_LARGE_RINGS
     fi
   fi
 fi
 
-tristate 'Frame relay DLCI support' CONFIG_DLCI
-if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then
-  int '  Max open DLCI' CONFIG_DLCI_COUNT 24
-  int '  Max DLCI per device' CONFIG_DLCI_MAX 8
-  dep_tristate '  SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
-fi
-
 #
 # AppleTalk
 #
+
 if [ "$CONFIG_ATALK" != "n" ]; then
+  mainmenu_option next_comment
+  comment 'Appletalk devices'
   dep_tristate 'Apple/Farallon LocalTalk PC support' CONFIG_LTPC $CONFIG_ATALK
   dep_tristate 'COPS LocalTalk PC support' CONFIG_COPS $CONFIG_ATALK
   if [ "$CONFIG_COPS" != "n" ]; then
@@ -183,6 +187,7 @@
      bool 'IP to Appletalk-IP Encapsulation support' CONFIG_IPDDP_ENCAP
      bool 'Appletalk-IP to IP Decapsulation support' CONFIG_IPDDP_DECAP
   fi
+  endmenu
 fi
 
 if [ ! "$CONFIG_PARPORT" = "n" ]; then
@@ -203,23 +208,38 @@
 
 bool 'Wireless LAN (non-hamradio)' CONFIG_NET_RADIO
 if [ "$CONFIG_NET_RADIO" = "y" ]; then
-  tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
+  dep_tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP $CONFIG_INET
   tristate 'AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+  tristate 'Aironet Arlan 655 & IC2200 DS support' CONFIG_ARLAN
+
 fi
 
+mainmenu_option next_comment
+comment 'Token ring devices'
+
 bool 'Token Ring driver support' CONFIG_TR
 if [ "$CONFIG_TR" = "y" ]; then
   tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR
 #  tristate 'IBM Lanstreamer PCI adaptor support' CONFIG_IBMLS
+  tristate 'IBM Olympic chipset PCI adapter support' CONFIG_IBMOL
   tristate 'SysKonnect adapter support' CONFIG_SKTR
 fi
 
+endmenu
+
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
   tristate 'Traffic Shaper (EXPERIMENTAL)' CONFIG_SHAPER
 fi
+
 #
 # WAN drivers support
 #
+
+mainmenu_option next_comment
+comment 'Wan interfaces'
+
+
 # There is no way to detect a comtrol sv11 - force it modular for now.
 #
 dep_tristate 'Comtrol Hostess SV-11 support' CONFIG_HOSTESS_SV11 m
@@ -227,8 +247,22 @@
 # The COSA/SRP driver has not been tested as non-modular yet.
 #
 dep_tristate 'COSA/SRP sync serial boards support' CONFIG_COSA m
-tristate 'Red Creek Hardware VPN (EXPERIMENTAL)' CONFIG_RCPCI
 #
+# There is no way to detect a Sealevel board. Force it modular
+#
+dep_tristate 'Sealevel Systems 4021 support' CONFIG_SEALEVEL_4021 m
+
+tristate 'Frame relay DLCI support' CONFIG_DLCI
+if [ "$CONFIG_DLCI" != "n" ]; then
+  int '  Max open DLCI' CONFIG_DLCI_COUNT 24
+  int '  Max DLCI per device' CONFIG_DLCI_MAX 8
+  dep_tristate '  SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
+fi
+
+#
+#	Wan router core.
+#
+
 if [ "$CONFIG_WAN_ROUTER" != "n" ]; then
   bool 'WAN drivers' CONFIG_WAN_DRIVERS
   if [ "$CONFIG_WAN_DRIVERS" = "y" ]; then
@@ -238,14 +272,18 @@
       bool '  WANPIPE X.25 support' CONFIG_WANPIPE_X25
       bool '  WANPIPE Frame Relay support' CONFIG_WANPIPE_FR
       bool '  WANPIPE PPP support' CONFIG_WANPIPE_PPP
+  #    bool '  WANPIPE Cisco HDLC support' CONFIG_WANPIPE_CHDLC
     fi
   fi
 fi
+
+endmenu
+
 #
 # X.25 network drivers
 #
 if [ "$CONFIG_X25" != "n" ]; then
-if [ "$CONFIG_LAPB" != "n" ]; then
+if [ "$CONFIG_LAPB" = "y" -o "$CONFIG_LAPB" = "m" ]; then
     dep_tristate 'LAPB over Ethernet driver' CONFIG_LAPBETHER $CONFIG_LAPB
     dep_tristate 'X.25 async driver' CONFIG_X25_ASY $CONFIG_LAPB
 fi
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Makefile linux.pre11.3/drivers/net/Makefile
--- linux.vanilla/drivers/net/Makefile	Tue Jun 15 16:49:49 1999
+++ linux.pre11.3/drivers/net/Makefile	Mon Jul 19 23:27:25 1999
@@ -67,6 +67,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_IBMOL),y)
+L_OBJS += olympic.o
+else
+  ifeq ($(CONFIG_IBMOL),m)
+  M_OBJS += olympic.o
+  endif
+endif
+
 ifeq ($(CONFIG_SKTR),y)
 L_OBJS += sktr.o
 else
@@ -143,14 +151,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_ETHERH),y)
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_ETHERH),m)
-  CONFIG_8390_MODULE = y
-  endif
-endif
-
 ifeq ($(CONFIG_WD80x3),y)
 L_OBJS += wd.o
 CONFIG_8390_BUILTIN = y
@@ -171,14 +171,6 @@
   endif
 endif
 
-ifeq ($(CONFIG_ETHERH),y)
-CONFIG_8390_BUILTIN = y
-else
-  ifeq ($(CONFIG_ETHERH),m)
-  CONFIG_8390_MODULE = y
-  endif
-endif
-
 ifeq ($(CONFIG_NE2K_PCI),y)
 L_OBJS += ne2k-pci.o
 CONFIG_8390_BUILTIN = y
@@ -438,6 +430,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SUNBMAC),y)
+L_OBJS += sunbmac.o
+else
+  ifeq ($(CONFIG_SUNBMAC),m)
+  M_OBJS += sunbmac.o
+  endif
+endif
+
 ifeq ($(CONFIG_MYRI_SBUS),y)
 L_OBJS += myri_sbus.o
 else
@@ -582,6 +582,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_ARLAN),y)
+LX_OBJS += arlan.o arlan-proc.o
+else
+  ifeq ($(CONFIG_ARLAN),m)
+  MX_OBJS += arlan.o arlan-proc.o
+  endif
+endif
+
 ifeq ($(CONFIG_TLAN),y)
 L_OBJS += tlan.o
 else
@@ -780,6 +788,19 @@
   endif
 endif
 
+ifeq ($(CONFIG_SEALEVEL_4021),y)
+L_OBJS += sealevel.o
+CONFIG_85230_BUILTIN = y
+CONFIG_SYNCPPP_BUILTIN = y
+else
+  ifeq ($(CONFIG_SEALEVEL_4021),m)
+  CONFIG_85230_MODULE = y
+  CONFIG_SYNCPPP_MODULE = y
+  M_OBJS += sealevel.o
+  endif
+endif
+
+
 ifeq ($(CONFIG_COSA),y)
 L_OBJS += cosa.o
 CONFIG_SYNCPPP_BUILTIN = y
@@ -892,10 +913,26 @@
 endif
 
 ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y)
-L_OBJS += sonic.o
+L_OBJS += jazzsonic.o
 else
   ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m)
-    M_OBJS += sonic.o
+  M_OBJS += jazzsonic.o
+  endif
+endif
+
+ifeq ($(CONFIG_BAGETLANCE),y)
+L_OBJS += bagetlance.o
+else
+  ifeq ($(CONFIG_BAGETLANCE),m)
+  M_OBJS += bagetlance.o
+  endif
+endif
+
+ifeq ($(CONFIG_DECLANCE),y)
+L_OBJS += declance.o
+else
+  ifeq ($(CONFIG_DECLANCE),m)
+  M_OBJS += declance.o
   endif
 endif
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/Space.c linux.pre11.3/drivers/net/Space.c
--- linux.vanilla/drivers/net/Space.c	Tue Jun 15 16:49:49 1999
+++ linux.pre11.3/drivers/net/Space.c	Tue Jul 20 00:45:35 1999
@@ -67,6 +67,7 @@
 extern int de4x5_probe(struct device *);
 extern int el1_probe(struct device *);
 extern int wavelan_probe(struct device *);
+extern int arlan_probe(struct device *);
 extern int el16_probe(struct device *);
 extern int elmc_probe(struct device *);
 extern int skmca_probe(struct device *);
@@ -111,6 +112,8 @@
 extern int epic100_probe(struct device *dev);
 extern int rtl8139_probe(struct device *dev);
 extern int hplance_probe(struct device *dev);
+extern int bagetlance_probe(struct device *);
+extern int dec_lance_probe(struct device *);
 extern int via_rhine_probe(struct device *dev);
 extern int tc515_probe(struct device *dev);
 extern int lance_probe(struct device *dev);
@@ -357,6 +360,9 @@
 #ifdef CONFIG_WAVELAN		/* WaveLAN */
 	{wavelan_probe, 0},
 #endif
+#ifdef CONFIG_ARLAN		/* Aironet */
+	{arlan_probe, 0},
+#endif
 #ifdef CONFIG_EL16		/* 3c507 */
 	{el16_probe, 0},
 #endif
@@ -443,6 +449,12 @@
 #ifdef CONFIG_MIPS_JAZZ_SONIC
 	{sonic_probe, 0},
 #endif
+#ifdef CONFIG_DECLANCE		/* DECstation on-board controller */
+	{dec_lance_probe, 0},   /* and maybe TURBOchannel option boards */
+#endif
+#ifdef CONFIG_BAGETLANCE        /* Lance-based Baget ethernet boards */
+        {bagetlance_probe, 0},
+#endif
 	{NULL, 0},
 };
 
@@ -668,6 +680,14 @@
 #define NEXT_DEV (&mkiss_bootstrap)
 #endif	/* MKISS */
   
+#if defined(CONFIG_YAM)
+extern int yam_init(struct device *);
+static struct device yam_bootstrap = {
+  "yam", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, yam_init, };
+#undef NEXT_DEV
+#define NEXT_DEV (&yam_bootstrap)
+#endif	/* CONFIG_YAM */
+  
 #if defined(CONFIG_STRIP)
 extern int strip_init_ctrl_dev(struct device *);
 static struct device strip_bootstrap = {
@@ -711,6 +731,7 @@
 #ifdef CONFIG_TR
 /* Token-ring device probe */
 extern int ibmtr_probe(struct device *);
+extern int olympic_probe(struct device *);
 
 static int
 trif_probe(struct device *dev)
@@ -718,6 +739,9 @@
     if (1
 #ifdef CONFIG_IBMTR
 	&& ibmtr_probe(dev)
+#endif
+#ifdef CONFIG_IBMOL
+	&& olympic_probe(dev)
 #endif
 #ifdef CONFIG_SKTR
 	&& sktr_probe(dev)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arcnet.c linux.pre11.3/drivers/net/arcnet.c
--- linux.vanilla/drivers/net/arcnet.c	Sun Nov  8 15:07:21 1998
+++ linux.pre11.3/drivers/net/arcnet.c	Mon Jul 19 23:59:55 1999
@@ -471,9 +471,16 @@
 
 #ifdef CONFIG_ARCNET_1051
   /* Initialize the RFC1051-encap protocol driver */
-  lp->sdev=(struct device *)kmalloc(sizeof(struct device),GFP_KERNEL);
+  lp->sdev=(struct device *)kmalloc(sizeof(struct device)+10,GFP_KERNEL);
+  if(lp->sdev = NULL)
+  {
+  	if(lp->edev)
+  		kfree(lp->edev);
+  	lp->edev=NULL;
+  	return -ENOMEM;
+  }
   memcpy(lp->sdev,dev,sizeof(struct device));
-  lp->sdev->name=(char *)kmalloc(10,GFP_KERNEL);
+  lp->sdev->name=(char *)(lp+1);
   sprintf(lp->sdev->name,"%ss",dev->name);
   lp->sdev->init=arcnetS_init;
   register_netdevice(lp->sdev);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arlan-proc.c linux.pre11.3/drivers/net/arlan-proc.c
--- linux.vanilla/drivers/net/arlan-proc.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/arlan-proc.c	Mon Jul 19 23:59:55 1999
@@ -0,0 +1,1059 @@
+#include <linux/config.h>
+#include "arlan.h"
+
+#ifdef CONFIG_PROC_FS
+
+
+#include <linux/sysctl.h>
+#include <linux/version.h>
+
+/* void enableReceive(struct device* dev);
+*/
+
+static  int	arlan_command(struct device * dev, int command);
+
+
+#define ARLAN_STR_SIZE 	0x2ff0
+#define DEV_ARLAN_INFO 	1
+#define DEV_ARLAN 	1
+#define SARLG(type,var) {\
+	pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n", #var, READSHMB(priva->card->var));	\
+	}
+
+#define SARLBN(type,var,nn) {\
+	pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x",#var);\
+	for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\
+	pos += sprintf(arlan_drive_info+pos, "\n");	\
+	}
+
+#define SARLBNpln(type,var,nn) {\
+	for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\
+	}
+
+#define SARLSTR(var,nn) {\
+	char tmpStr[400];\
+	int  tmpLn = nn;\
+	if (nn > 399 ) tmpLn = 399; \
+	memcpy(tmpStr,(char *) priva->conf->var,tmpLn);\
+	tmpStr[tmpLn] = 0; \
+	pos += sprintf(arlan_drive_info+pos, "%s\t=\t%s \n",#var,priva->conf->var);\
+	}
+
+#define SARLUC(var)  	SARLG(u_char, var)
+#define SARLUCN(var,nn) SARLBN(u_char,var, nn)
+#define SARLUS(var)	SARLG(u_short, var)
+#define SARLUSN(var,nn)	SARLBN(u_short,var, nn)
+#define SARLUI(var)	SARLG(u_int, var)
+
+#define SARLUSA(var) {\
+	u_short tmpVar;\
+	memcpy(&tmpVar, (short *) priva->conf->var,2); \
+	pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\
+}
+
+#define SARLUIA(var) {\
+	u_int tmpVar;\
+	memcpy(&tmpVar, (int* )priva->conf->var,4); \
+	pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\
+}
+
+
+const char *arlan_diagnostic_info_string(struct device *dev)
+{
+
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+	u_char diagnosticInfo;
+
+	READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char);
+
+	switch (diagnosticInfo)
+	{
+		case 0xFF:
+			return "Diagnostic info is OK";
+		case 0xFE:
+			return "ERROR EPROM Checksum error ";
+		case 0xFD:
+			return "ERROR Local Ram Test Failed ";
+		case 0xFC:
+			return "ERROR SCC failure ";
+		case 0xFB:
+			return "ERROR BackBone failure ";
+		case 0xFA:
+			return "ERROR tranceiver not found ";
+		case 0xF9:
+			return "ERROR no more address space ";
+		case 0xF8:
+			return "ERROR Checksum error  ";
+		case 0xF7:
+			return "ERROR Missing SS Code";
+		case 0xF6:
+			return "ERROR Invalid config format";
+		case 0xF5:
+			return "ERROR Reserved errorcode F5";
+		case 0xF4:
+			return "ERROR Invalid spreading code/channel number";
+		case 0xF3:
+			return "ERROR Load Code Error";
+		case 0xF2:
+			return "ERROR Reserver errorcode F2 ";
+		case 0xF1:
+			return "ERROR Invalid command receivec by LAN card ";
+		case 0xF0:
+			return "ERROR Invalid parameter found in command ";
+		case 0xEF:
+			return "ERROR On-chip timer failure ";
+		case 0xEE:
+			return "ERROR T410 timer failure ";
+		case 0xED:
+			return "ERROR Too Many TxEnable commands ";
+		case 0xEC:
+			return "ERROR EEPROM error on radio module ";
+		default:
+			return "ERROR unknown Diagnostic info reply code ";
+	  }
+};
+
+static const char *arlan_hardware_type_string(struct device *dev)
+{
+	u_char hardwareType;
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+	READSHM(hardwareType, arlan->hardwareType, u_char);
+	switch (hardwareType)
+	{
+		case 0x00:
+			return "type A450";
+		case 0x01:
+			return "type A650 ";
+		case 0x04:
+			return "type TMA coproc";
+		case 0x0D:
+			return "type A650E ";
+		case 0x18:
+			return "type TMA coproc Australian";
+		case 0x19:
+			return "type A650A ";
+		case 0x26:
+			return "type TMA coproc European";
+		case 0x2E:
+			return "type A655 ";
+		case 0x2F:
+			return "type A655A ";
+		case 0x30:
+			return "type A655E ";
+		case 0x0B:
+			return "type A670 ";
+		case 0x0C:
+			return "type A670E ";
+		case 0x2D:
+			return "type A670A ";
+		case 0x0F:
+			return "type A411T";
+		case 0x16:
+			return "type A411TA";
+		case 0x1B:
+			return "type A440T";
+		case 0x1C:
+			return "type A412T";
+		case 0x1E:
+			return "type A412TA";
+		case 0x22:
+			return "type A411TE";
+		case 0x24:
+			return "type A412TE";
+		case 0x27:
+			return "type A671T ";
+		case 0x29:
+			return "type A671TA ";
+		case 0x2B:
+			return "type A671TE ";
+		case 0x31:
+			return "type A415T ";
+		case 0x33:
+			return "type A415TA ";
+		case 0x35:
+			return "type A415TE ";
+		case 0x37:
+			return "type A672";
+		case 0x39:
+			return "type A672A ";
+		case 0x3B:
+			return "type A672T";
+		case 0x6B:
+			return "type IC2200";
+		default:
+			return "type A672T";
+	}
+}
+
+static void arlan_print_diagnostic_info(struct device *dev)
+{
+	int i;
+	u_char diagnosticInfo;
+	u_short diagnosticOffset;
+	u_char hardwareType;
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+	//  ARLAN_DEBUG_ENTRY("arlan_print_diagnostic_info");
+
+	if (READSHMB(arlan->configuredStatusFlag) == 0)
+		printk("Arlan: Card NOT configured\n");
+	else
+		printk("Arlan: Card is configured\n");
+
+	READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char);
+	READSHM(diagnosticOffset, arlan->diagnosticOffset, u_short);
+
+	printk(KERN_INFO "%s\n", arlan_diagnostic_info_string(dev));
+
+	if (diagnosticInfo != 0xff)
+		printk("%s arlan: Diagnostic Offset %d \n", dev->name, diagnosticOffset);
+
+	printk("arlan: LAN CODE ID = ");
+	for (i = 0; i < 6; i++)
+		DEBUGSHM(1, "%03d:", arlan->lanCardNodeId[i], u_char);
+	printk("\n");
+
+	printk("arlan: Arlan BroadCast address  = ");
+	for (i = 0; i < 6; i++)
+		DEBUGSHM(1, "%03d:", arlan->broadcastAddress[i], u_char);
+	printk("\n");
+
+	READSHM(hardwareType, arlan->hardwareType, u_char);
+	printk(KERN_INFO "%s\n", arlan_hardware_type_string(dev));
+
+
+	DEBUGSHM(1, "arlan: channelNumber=%d\n", arlan->channelNumber, u_char);
+	DEBUGSHM(1, "arlan: channelSet=%d\n", arlan->channelSet, u_char);
+	DEBUGSHM(1, "arlan: spreadingCode=%d\n", arlan->spreadingCode, u_char);
+	DEBUGSHM(1, "arlan: radioNodeId=%d\n", arlan->radioNodeId, u_short);
+	DEBUGSHM(1, "arlan: SID	=%d\n", arlan->SID, u_short);
+	DEBUGSHM(1, "arlan: rxOffset=%d\n", arlan->rxOffset, u_short);
+
+	DEBUGSHM(1, "arlan: registration mode is %d\n", arlan->registrationMode, u_char);
+
+	printk("arlan: name= ");
+	IFDEBUG(1)
+	
+	for (i = 0; i < 16; i++)
+	{
+		char c;
+		READSHM(c, arlan->name[i], char);
+		if (c)
+			printk("%c", c);
+	}
+	printk("\n");
+
+//   ARLAN_DEBUG_EXIT("arlan_print_diagnostic_info");
+
+}
+
+
+/******************************		TEST 	MEMORY	**************/
+
+static int arlan_hw_test_memory(struct device *dev)
+{
+	u_char *ptr;
+	int i;
+	int memlen = sizeof(struct arlan_shmem) - 0xF;	/* avoid control register */
+	volatile char *arlan_mem = (char *) (dev->mem_start);
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+	char pattern;
+
+	ptr = NULL;
+
+	/* hold card in reset state */
+	setHardwareReset(dev);
+
+	/* test memory */
+	pattern = 0;
+	for (i = 0; i < memlen; i++)
+		WRITESHM(arlan_mem[i], ((u_char) pattern++), u_char);
+
+	pattern = 0;
+	for (i = 0; i < memlen; i++)
+	{
+		char res;
+		READSHM(res, arlan_mem[i], char);
+		if (res != pattern++)
+		{
+			printk(KERN_ERR "Arlan driver memory test 1 failed \n");
+			return -1;
+		}
+	}
+
+	pattern = 0;
+	for (i = 0; i < memlen; i++)
+		WRITESHM(arlan_mem[i], ~(pattern++), char);
+
+	pattern = 0;
+	for (i = 0; i < memlen; i++)
+	{
+		char res;
+		READSHM(res, arlan_mem[i], char);
+		if (res != ~(pattern++))
+		{
+			printk(KERN_ERR "Arlan driver memory test 2 failed \n");
+			return -1;
+		}
+	}
+
+	/* zero memory */
+	for (i = 0; i < memlen; i++)
+		WRITESHM(arlan_mem[i], 0x00, char);
+
+	IFDEBUG(1) printk(KERN_INFO "Arlan: memory tests ok\n");
+
+	/* set reset flag and then release reset */
+	WRITESHM(arlan->resetFlag, 0xff, u_char);
+
+	clearChannelAttention(dev);
+	clearHardwareReset(dev);
+
+	/* wait for reset flag to become zero, we'll wait for two seconds */
+	if (arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW))
+	{
+		printk(KERN_ERR "%s arlan: failed to come back from memory test\n", dev->name);
+		return -1;
+	}
+	return 0;
+}
+
+
+static int arlan_setup_card_by_book(struct device *dev)
+{
+	u_char irqLevel, configuredStatusFlag;
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+//	ARLAN_DEBUG_ENTRY("arlan_setup_card");
+
+	READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char);
+
+	IFDEBUG(10)
+	if (configuredStatusFlag != 0)
+		IFDEBUG(10) printk("arlan: CARD IS CONFIGURED\n");
+	else
+		IFDEBUG(10) printk("arlan: card is NOT configured\n");
+
+	if (testMemory || (READSHMB(arlan->diagnosticInfo) != 0xff))
+		if (arlan_hw_test_memory(dev))
+			return -1;
+
+	DEBUGSHM(4, "arlan configuredStatus = %d \n", arlan->configuredStatusFlag, u_char);
+	DEBUGSHM(4, "arlan driver diagnostic: 0x%2x\n", arlan->diagnosticInfo, u_char);
+
+	/* issue nop command - no interupt */
+	arlan_command(dev, ARLAN_COMMAND_NOOP);
+	if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0)
+		return -1;
+
+	IFDEBUG(50) printk("1st Noop successfully executed !!\n");
+
+	/* try to turn on the arlan interrupts */
+	clearClearInterrupt(dev);
+	setClearInterrupt(dev);
+	setInterruptEnable(dev);
+
+	/* issue nop command - with interrupt */
+
+	arlan_command(dev, ARLAN_COMMAND_NOOPINT);
+	if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0)
+		return -1;
+
+
+	IFDEBUG(50) printk("2nd Noop successfully executed !!\n");
+
+	READSHM(irqLevel, arlan->irqLevel, u_char)
+	
+	if (irqLevel != dev->irq)
+	{
+		IFDEBUG(1) printk(KERN_WARNING "arlan dip switches set irq to %d\n", irqLevel);
+		printk(KERN_WARNING "device driver irq set to %d - does not match\n", dev->irq);
+		dev->irq = irqLevel;
+	}
+	else
+		IFDEBUG(2) printk("irq level is OK\n");
+
+
+	IFDEBUG(3) arlan_print_diagnostic_info(dev);
+
+	arlan_command(dev, ARLAN_COMMAND_CONF);
+
+	READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char);
+	if (configuredStatusFlag == 0)
+	{
+		printk(KERN_WARNING "arlan configure failed\n");
+		return -1;
+	}
+	arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW);
+	arlan_command(dev, ARLAN_COMMAND_RX);
+	arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW);
+	printk(KERN_NOTICE "%s: arlan driver version %s loaded\n",
+	       dev->name, arlan_version);
+
+//	ARLAN_DEBUG_EXIT("arlan_setup_card");
+
+	return 0;		/* no errors */
+}
+
+
+#ifdef ARLAN_PROC_INTERFACE
+#ifdef ARLAN_PROC_SHM_DUMP
+
+static char arlan_drive_info[ARLAN_STR_SIZE] = "A655\n\0";
+
+static int arlan_sysctl_info(ctl_table * ctl, int write, struct file *filp,
+		      void *buffer, size_t * lenp)
+{
+	int i;
+	int retv, pos, devnum;
+	struct arlan_private *priva = NULL;
+	struct device *dev;
+	pos = 0;
+	if (write)
+	{
+		printk("wrirte: ");
+		for (i = 0; i < 100; i++)
+			printk("adi %x \n", arlan_drive_info[i]);
+	}
+	if (ctl->procname == NULL || arlan_drive_info == NULL)
+	{
+		printk(KERN_WARNING " procname is NULL in sysctl_table or arlan_drive_info is NULL \n at arlan module\n ");
+		return -1;
+	}
+	devnum = ctl->procname[5] - '0';
+	if (devnum < 0 || devnum > MAX_ARLANS - 1)
+	{
+		printk(KERN_WARNING "too strange devnum in procfs parse\n ");
+		return -1;
+	}
+	else if (arlan_device[devnum] == NULL)
+	{
+		if (ctl->procname)
+			pos += sprintf(arlan_drive_info + pos, "\t%s\n\n", ctl->procname);
+		pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+		goto final;
+	}
+	else
+		priva = arlan_device[devnum]->priv;
+
+	if (priva == NULL)
+	{
+		printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+		return -1;
+	}
+	dev = arlan_device[devnum];
+
+	memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+
+	pos = sprintf(arlan_drive_info, "Arlan  info \n");
+	/* Header Signature */
+	SARLSTR(textRegion, 48);
+	SARLUC(resetFlag);
+	pos += sprintf(arlan_drive_info + pos, "diagnosticInfo\t=\t%s \n", arlan_diagnostic_info_string(dev));
+	SARLUC(diagnosticInfo);
+	SARLUS(diagnosticOffset);
+	SARLUCN(_1, 12);
+	SARLUCN(lanCardNodeId, 6);
+	SARLUCN(broadcastAddress, 6);
+	pos += sprintf(arlan_drive_info + pos, "hardwareType =\t  %s \n", arlan_hardware_type_string(dev));
+	SARLUC(hardwareType);
+	SARLUC(majorHardwareVersion);
+	SARLUC(minorHardwareVersion);
+	SARLUC(radioModule);
+	SARLUC(defaultChannelSet);
+	SARLUCN(_2, 47);
+
+	/* Control/Status Block - 0x0080 */
+	SARLUC(interruptInProgress);
+	SARLUC(cntrlRegImage);
+
+	SARLUCN(_3, 14);
+	SARLUC(commandByte);
+	SARLUCN(commandParameter, 15);
+
+	/* Receive Status - 0x00a0 */
+	SARLUC(rxStatus);
+	SARLUC(rxFrmType);
+	SARLUS(rxOffset);
+	SARLUS(rxLength);
+	SARLUCN(rxSrc, 6);
+	SARLUC(rxBroadcastFlag);
+	SARLUC(rxQuality);
+	SARLUC(scrambled);
+	SARLUCN(_4, 1);
+
+	/* Transmit Status - 0x00b0 */
+	SARLUC(txStatus);
+	SARLUC(txAckQuality);
+	SARLUC(numRetries);
+	SARLUCN(_5, 14);
+	SARLUCN(registeredRouter, 6);
+	SARLUCN(backboneRouter, 6);
+	SARLUC(registrationStatus);
+	SARLUC(configuredStatusFlag);
+	SARLUCN(_6, 1);
+	SARLUCN(ultimateDestAddress, 6);
+	SARLUCN(immedDestAddress, 6);
+	SARLUCN(immedSrcAddress, 6);
+	SARLUS(rxSequenceNumber);
+	SARLUC(assignedLocaltalkAddress);
+	SARLUCN(_7, 27);
+
+	/* System Parameter Block */
+
+	/* - Driver Parameters (Novell Specific) */
+
+	SARLUS(txTimeout);
+	SARLUS(transportTime);
+	SARLUCN(_8, 4);
+
+	/* - Configuration Parameters */
+	SARLUC(irqLevel);
+	SARLUC(spreadingCode);
+	SARLUC(channelSet);
+	SARLUC(channelNumber);
+	SARLUS(radioNodeId);
+	SARLUCN(_9, 2);
+	SARLUC(scramblingDisable);
+	SARLUC(radioType);
+	SARLUS(routerId);
+	SARLUCN(_10, 9);
+	SARLUC(txAttenuation);
+	SARLUIA(systemId);
+	SARLUS(globalChecksum);
+	SARLUCN(_11, 4);
+	SARLUS(maxDatagramSize);
+	SARLUS(maxFrameSize);
+	SARLUC(maxRetries);
+	SARLUC(receiveMode);
+	SARLUC(priority);
+	SARLUC(rootOrRepeater);
+	SARLUCN(specifiedRouter, 6);
+	SARLUS(fastPollPeriod);
+	SARLUC(pollDecay);
+	SARLUSA(fastPollDelay);
+	SARLUC(arlThreshold);
+	SARLUC(arlDecay);
+	SARLUCN(_12, 1);
+	SARLUS(specRouterTimeout);
+	SARLUCN(_13, 5);
+
+	/* Scrambled Area */
+	SARLUIA(SID);
+	SARLUCN(encryptionKey, 12);
+	SARLUIA(_14);
+	SARLUSA(waitTime);
+	SARLUSA(lParameter);
+	SARLUCN(_15, 3);
+	SARLUS(headerSize);
+	SARLUS(sectionChecksum);
+
+	SARLUC(registrationMode);
+	SARLUC(registrationFill);
+	SARLUS(pollPeriod);
+	SARLUS(refreshPeriod);
+	SARLSTR(name, 16);
+	SARLUCN(NID, 6);
+	SARLUC(localTalkAddress);
+	SARLUC(codeFormat);
+	SARLUC(numChannels);
+	SARLUC(channel1);
+	SARLUC(channel2);
+	SARLUC(channel3);
+	SARLUC(channel4);
+	SARLUCN(SSCode, 59);
+
+/*      SARLUCN( _16, 0x140);
+ */
+	/* Statistics Block - 0x0300 */
+	SARLUC(hostcpuLock);
+	SARLUC(lancpuLock);
+	SARLUCN(resetTime, 18);
+	SARLUIA(numDatagramsTransmitted);
+	SARLUIA(numReTransmissions);
+	SARLUIA(numFramesDiscarded);
+	SARLUIA(numDatagramsReceived);
+	SARLUIA(numDuplicateReceivedFrames);
+	SARLUIA(numDatagramsDiscarded);
+	SARLUS(maxNumReTransmitDatagram);
+	SARLUS(maxNumReTransmitFrames);
+	SARLUS(maxNumConsecutiveDuplicateFrames);
+	/* misaligned here so we have to go to characters */
+	SARLUIA(numBytesTransmitted);
+	SARLUIA(numBytesReceived);
+	SARLUIA(numCRCErrors);
+	SARLUIA(numLengthErrors);
+	SARLUIA(numAbortErrors);
+	SARLUIA(numTXUnderruns);
+	SARLUIA(numRXOverruns);
+	SARLUIA(numHoldOffs);
+	SARLUIA(numFramesTransmitted);
+	SARLUIA(numFramesReceived);
+	SARLUIA(numReceiveFramesLost);
+	SARLUIA(numRXBufferOverflows);
+	SARLUIA(numFramesDiscardedAddrMismatch);
+	SARLUIA(numFramesDiscardedSIDMismatch);
+	SARLUIA(numPollsTransmistted);
+	SARLUIA(numPollAcknowledges);
+	SARLUIA(numStatusTimeouts);
+	SARLUIA(numNACKReceived);
+	SARLUS(auxCmd);
+	SARLUCN(dumpPtr, 4);
+	SARLUC(dumpVal);
+	SARLUC(wireTest);
+	
+	/* next 4 seems too long for procfs, over single page ?
+	SARLUCN( _17, 0x86);
+	SARLUCN( txBuffer, 0x800);
+	SARLUCN( rxBuffer,  0x800); 
+	SARLUCN( _18, 0x0bff);
+	 */
+
+	pos += sprintf(arlan_drive_info + pos, "rxRing\t=\t0x");
+	for (i = 0; i < 0x50; i++)
+		pos += sprintf(arlan_drive_info + pos, "%02x", ((char *) priva->conf)[priva->conf->rxOffset + i]);
+	pos += sprintf(arlan_drive_info + pos, "\n");
+
+	SARLUC(configStatus);
+	SARLUC(_22);
+	SARLUC(progIOCtrl);
+	SARLUC(shareMBase);
+	SARLUC(controlRegister);
+
+	pos += sprintf(arlan_drive_info + pos, " total %d chars\n", pos);
+	if (ctl)
+		if (ctl->procname)
+			pos += sprintf(arlan_drive_info + pos, " driver name : %s\n", ctl->procname);
+final:
+	*lenp = pos;
+
+	if (!write)
+		retv = proc_dostring(ctl, write, filp, buffer, lenp);
+	else
+	{
+		*lenp = 0;
+		return -1;
+	}
+	return retv;
+}
+
+
+static int arlan_sysctl_info161719(ctl_table * ctl, int write, struct file *filp,
+			    void *buffer, size_t * lenp)
+{
+	int i;
+	int retv, pos, devnum;
+	struct arlan_private *priva = NULL;
+
+	pos = 0;
+	devnum = ctl->procname[5] - '0';
+	if (arlan_device[devnum] == NULL)
+	{
+		pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+		goto final;
+	}
+	else
+		priva = arlan_device[devnum]->priv;
+	if (priva == NULL)
+	{
+		printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+		return -1;
+	}
+	memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+	SARLUCN(_16, 0xC0);
+	SARLUCN(_17, 0x6A);
+	SARLUCN(_18, 14);
+	SARLUCN(_19, 0x86);
+	SARLUCN(_21, 0x3fd);
+
+final:
+	*lenp = pos;
+	retv = proc_dostring(ctl, write, filp, buffer, lenp);
+	return retv;
+}
+
+static int arlan_sysctl_infotxRing(ctl_table * ctl, int write, struct file *filp,
+			    void *buffer, size_t * lenp)
+{
+	int i;
+	int retv, pos, devnum;
+	struct arlan_private *priva = NULL;
+
+	pos = 0;
+	devnum = ctl->procname[5] - '0';
+	if (arlan_device[devnum] == NULL)
+	{
+		  pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+		  goto final;
+	}
+	else
+		priva = arlan_device[devnum]->priv;
+	if (priva == NULL)
+	{
+		printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+		return -1;
+	}
+	memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+	SARLBNpln(u_char, txBuffer, 0x800);
+final:
+	*lenp = pos;
+	retv = proc_dostring(ctl, write, filp, buffer, lenp);
+	return retv;
+}
+
+static int arlan_sysctl_inforxRing(ctl_table * ctl, int write, struct file *filp,
+			    void *buffer, size_t * lenp)
+{
+	int i;
+	int retv, pos, devnum;
+	struct arlan_private *priva = NULL;
+
+	pos = 0;
+	devnum = ctl->procname[5] - '0';
+	if (arlan_device[devnum] == NULL)
+	{
+		  pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+		  goto final;
+	} else
+		priva = arlan_device[devnum]->priv;
+	if (priva == NULL)
+	{
+		printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+		return -1;
+	}
+	memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+	SARLBNpln(u_char, rxBuffer, 0x800);
+final:
+	*lenp = pos;
+	retv = proc_dostring(ctl, write, filp, buffer, lenp);
+	return retv;
+}
+
+static int arlan_sysctl_info18(ctl_table * ctl, int write, struct file *filp,
+			void *buffer, size_t * lenp)
+{
+	int i;
+	int retv, pos, devnum;
+	struct arlan_private *priva = NULL;
+
+	pos = 0;
+	devnum = ctl->procname[5] - '0';
+	if (arlan_device[devnum] == NULL)
+	{
+		pos += sprintf(arlan_drive_info + pos, "No device found here \n");
+		goto final;
+	}
+	else
+		priva = arlan_device[devnum]->priv;
+	if (priva == NULL)
+	{
+		printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n ");
+		return -1;
+	}
+	memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem));
+	SARLBNpln(u_char, _18, 0x800);
+
+final:
+	*lenp = pos;
+	retv = proc_dostring(ctl, write, filp, buffer, lenp);
+	return retv;
+}
+
+
+#endif				/* #ifdef ARLAN_PROC_SHM_DUMP */
+
+
+static char conf_reset_result[200];
+
+static int arlan_configure(ctl_table * ctl, int write, struct file *filp,
+		    void *buffer, size_t * lenp)
+{
+	int pos = 0;
+	int devnum = ctl->procname[6] - '0';
+	struct arlan_private *priv;
+
+	if (devnum < 0 || devnum > MAX_ARLANS - 1)
+	{
+		  printk(KERN_WARNING "too strange devnum in procfs parse\n ");
+		  return -1;
+	}
+	else if (arlan_device[devnum] != NULL)
+	{
+		  priv = arlan_device[devnum]->priv;
+
+		  arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_CONF);
+	}
+	else
+		return -1;
+
+	*lenp = pos;
+	return proc_dostring(ctl, write, filp, buffer, lenp);
+}
+
+int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp,
+		       void *buffer, size_t * lenp)
+{
+	int pos = 0;
+	int devnum = ctl->procname[5] - '0';
+	struct arlan_private *priv;
+
+	if (devnum < 0 || devnum > MAX_ARLANS - 1)
+	{
+		  printk(KERN_WARNING "too strange devnum in procfs parse\n ");
+		  return -1;
+	}
+	else if (arlan_device[devnum] != NULL)
+	{
+		priv = arlan_device[devnum]->priv;
+		arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_RESET);
+
+	} else
+		return -1;
+	*lenp = pos + 3;
+	return proc_dostring(ctl, write, filp, buffer, lenp);
+}
+
+
+/* Place files in /proc/sys/dev/arlan */
+#define CTBLN(num,card,nam) \
+        {num , #nam, &(arlan_conf[card].nam), \
+         sizeof(int), 0600, NULL, &proc_dointvec}
+
+
+#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\
+	CTBLN(1,cardNo,spreadingCode),\
+	CTBLN(2,cardNo, channelNumber),\
+	CTBLN(3,cardNo, scramblingDisable),\
+	CTBLN(4,cardNo, txAttenuation),\
+	CTBLN(5,cardNo, systemId), \
+	CTBLN(6,cardNo, maxDatagramSize),\
+	CTBLN(7,cardNo, maxFrameSize),\
+	CTBLN(8,cardNo, maxRetries),\
+	CTBLN(9,cardNo, receiveMode),\
+	CTBLN(10,cardNo, priority),\
+	CTBLN(11,cardNo, rootOrRepeater),\
+	CTBLN(12,cardNo, SID),\
+	CTBLN(13,cardNo, registrationMode),\
+	CTBLN(14,cardNo, registrationFill),\
+	CTBLN(15,cardNo, localTalkAddress),\
+	CTBLN(16,cardNo, codeFormat),\
+	CTBLN(17,cardNo, numChannels),\
+	CTBLN(18,cardNo, channel1),\
+	CTBLN(19,cardNo, channel2),\
+	CTBLN(20,cardNo, channel3),\
+	CTBLN(21,cardNo, channel4),\
+	CTBLN(22,cardNo, txClear),\
+	CTBLN(23,cardNo, txRetries),\
+	CTBLN(24,cardNo, txRouting),\
+	CTBLN(25,cardNo, txScrambled),\
+	CTBLN(26,cardNo, rxParameter),\
+	CTBLN(27,cardNo, txTimeoutMs),\
+	CTBLN(28,cardNo, waitCardTimeout),\
+	CTBLN(29,cardNo, channelSet), \
+	{30, "name", arlan_conf[cardNo].siteName, \
+                16, 0600, NULL, &proc_dostring},\
+	CTBLN(31,cardNo,waitTime),\
+	CTBLN(32,cardNo,lParameter),\
+	CTBLN(33,cardNo,_15),\
+	CTBLN(34,cardNo,headerSize),\
+	CTBLN(35,cardNo,async),\
+	CTBLN(36,cardNo,tx_delay_ms),\
+	CTBLN(37,cardNo,retries),\
+	CTBLN(38,cardNo,ReTransmitPacketMaxSize),\
+	CTBLN(39,cardNo,waitReTransmitPacketMaxSize),\
+	CTBLN(40,cardNo,fastReTransCount),\
+	CTBLN(41,cardNo,driverRetransmissions),\
+	CTBLN(42,cardNo,txAckTimeoutMs),\
+	CTBLN(43,cardNo,registrationInterrupts),\
+	CTBLN(44,cardNo,hardwareType),\
+	CTBLN(45,cardNo,radioType),\
+	CTBLN(46,cardNo,writeEEPROM),\
+	CTBLN(47,cardNo,writeRadioType),\
+	{48, "entry_exit_debug", &arlan_entry_and_exit_debug, \
+                sizeof(int), 0600, NULL, &proc_dointvec},\
+	{49, "debug", &arlan_debug, \
+                sizeof(int), 0600, NULL, &proc_dointvec},\
+	CTBLN(50,cardNo,in_speed),\
+	CTBLN(51,cardNo,out_speed),\
+	CTBLN(52,cardNo,in_speed10),\
+	CTBLN(53,cardNo,out_speed10),\
+	CTBLN(54,cardNo,in_speed_max),\
+	CTBLN(55,cardNo,out_speed_max),\
+	CTBLN(56,cardNo,measure_rate),\
+	CTBLN(57,cardNo,pre_Command_Wait),\
+	CTBLN(58,cardNo,rx_tweak1),\
+	CTBLN(59,cardNo,rx_tweak2),\
+	CTBLN(60,cardNo,tx_queue_len),\
+
+
+
+static ctl_table arlan_conf_table0[] =
+{
+	ARLAN_SYSCTL_TABLE_TOTAL(0)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+	{150, "arlan0-txRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+	{151, "arlan0-rxRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+	{152, "arlan0-18", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+	{153, "arlan0-ring", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+	{154, "arlan0-shm-cpy", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+	{155, "config0", &conf_reset_result, \
+	 100, 0400, NULL, &arlan_configure}, \
+	{156, "reset0", &conf_reset_result, \
+	 100, 0400, NULL, &arlan_sysctl_reset}, \
+	{0}
+};
+
+static ctl_table arlan_conf_table1[] =
+{
+
+	ARLAN_SYSCTL_TABLE_TOTAL(1)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+	{150, "arlan1-txRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+	{151, "arlan1-rxRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+	{152, "arlan1-18", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+	{153, "arlan1-ring", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+	{154, "arlan1-shm-cpy", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+	{155, "config1", &conf_reset_result,
+	 100, 0400, NULL, &arlan_configure},
+	{156, "reset1", &conf_reset_result,
+	 100, 0400, NULL, &arlan_sysctl_reset},
+	{0}
+};
+
+static ctl_table arlan_conf_table2[] =
+{
+
+	ARLAN_SYSCTL_TABLE_TOTAL(2)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+	{150, "arlan2-txRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+	{151, "arlan2-rxRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+	{152, "arlan2-18", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+	{153, "arlan2-ring", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+	{154, "arlan2-shm-cpy", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+	{155, "config2", &conf_reset_result,
+	 100, 0400, NULL, &arlan_configure},
+	{156, "reset2", &conf_reset_result,
+	 100, 0400, NULL, &arlan_sysctl_reset},
+	{0}
+};
+
+static ctl_table arlan_conf_table3[] =
+{
+
+	ARLAN_SYSCTL_TABLE_TOTAL(3)
+
+#ifdef ARLAN_PROC_SHM_DUMP
+	{150, "arlan3-txRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_infotxRing},
+	{151, "arlan3-rxRing", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_inforxRing},
+	{152, "arlan3-18", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info18},
+	{153, "arlan3-ring", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info161719},
+	{154, "arlan3-shm-cpy", &arlan_drive_info,
+	 ARLAN_STR_SIZE, 0400, NULL, &arlan_sysctl_info},
+#endif
+	{155, "config3", &conf_reset_result,
+	 100, 0400, NULL, &arlan_configure},
+	{156, "reset3", &conf_reset_result,
+	 100, 0400, NULL, &arlan_sysctl_reset},
+	{0}
+};
+
+
+
+static ctl_table arlan_table[] =
+{
+	{0, "arlan0", NULL, 0, 0600, arlan_conf_table0},
+	{0, "arlan1", NULL, 0, 0600, arlan_conf_table1},
+	{0, "arlan2", NULL, 0, 0600, arlan_conf_table2},
+	{0, "arlan3", NULL, 0, 0600, arlan_conf_table3},
+	{0}
+};
+
+#else
+
+static ctl_table arlan_table[MAX_ARLANS + 1] =
+{
+	{0}
+};
+#endif
+#endif
+
+static int mmtu = 1234;
+
+static ctl_table arlan_root_table[] =
+{
+	{254, "arlan", NULL, 0, 0555, arlan_table},
+	{0}
+};
+
+/* Make sure that /proc/sys/dev is there */
+static ctl_table arlan_device_root_table[] =
+{
+	{CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table},
+	{0}
+};
+
+
+
+static struct ctl_table_header *arlan_device_sysctl_header = NULL;
+
+int init_arlan_proc(void)
+{
+
+	int i = 0;
+	if (arlan_device_sysctl_header)
+		return 0;
+	for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++)
+		arlan_table[i].ctl_name = i + 1;
+	arlan_device_sysctl_header = register_sysctl_table(arlan_root_table, 0);
+	if (!arlan_device_sysctl_header)
+		return -1;
+
+	return 0;
+
+};
+
+
+
+#ifdef MODULE
+
+int init_module(void)
+{
+
+	return init_arlan_proc();
+};
+
+void cleanup_module(void)
+{
+	unregister_sysctl_table(arlan_device_sysctl_header);
+	arlan_device_sysctl_header = NULL;
+
+	return;
+};
+
+#endif				// MODULE
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arlan.c linux.pre11.3/drivers/net/arlan.c
--- linux.vanilla/drivers/net/arlan.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/arlan.c	Mon Jul 19 23:59:55 1999
@@ -0,0 +1,2080 @@
+/*
+ *  Copyright (C) 1997 Cullen Jennings
+ *  Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500        
+ *  Gnu Public License applies
+ * This module provides support for the Arlan 655 card made by Aironet
+ */
+
+
+#include <linux/config.h>
+#include "arlan.h"
+
+static const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee  Oct'98, http://www.ylenurme.ee/~elmer/655/";
+
+struct device *arlan_device[MAX_ARLANS];
+int last_arlan = 0;
+
+static int SID = SIDUNKNOWN;
+static int radioNodeId = radioNodeIdUNKNOWN;
+static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
+static char *siteName = siteNameUNKNOWN;
+static int irq = irqUNKNOWN;
+static int mem = memUNKNOWN;
+static int arlan_debug = debugUNKNOWN;
+static int probe = probeUNKNOWN;
+static int numDevices = numDevicesUNKNOWN;
+static int testMemory = testMemoryUNKNOWN;
+static int spreadingCode = spreadingCodeUNKNOWN;
+static int channelNumber = channelNumberUNKNOWN;
+static int channelSet = channelSetUNKNOWN;
+static int systemId = systemIdUNKNOWN;
+static int registrationMode = registrationModeUNKNOWN;
+static int txScrambled = 1;
+static int keyStart = 0;
+static int mdebug = 0;
+static int tx_delay_ms = 0;
+static int retries = 5;
+static int async = 1;
+static int tx_queue_len = 1;
+static int arlan_entry_debug = 0;
+static int arlan_exit_debug = 0;
+static int arlan_entry_and_exit_debug = 0;
+static int arlan_EEPROM_bad = 0;
+
+#if LINUX_VERSION_CODE > 0x20100
+MODULE_PARM(irq, "i");
+MODULE_PARM(mem, "i");
+MODULE_PARM(probe, "i");
+MODULE_PARM(arlan_debug, "i");
+MODULE_PARM(numDevices, "i");
+MODULE_PARM(testMemory, "i");
+MODULE_PARM(spreadingCode, "i");
+MODULE_PARM(channelNumber, "i");
+MODULE_PARM(channelSet, "i");
+MODULE_PARM(systemId, "i");
+MODULE_PARM(registrationMode, "i");
+MODULE_PARM(radioNodeId, "i");
+MODULE_PARM(SID, "i");
+MODULE_PARM(txScrambled, "i");
+MODULE_PARM(keyStart, "i");
+MODULE_PARM(mdebug, "i");
+MODULE_PARM(tx_delay_ms, "i");
+MODULE_PARM(retries, "i");
+MODULE_PARM(async, "i");
+MODULE_PARM(tx_queue_len, "i");
+MODULE_PARM(arlan_entry_debug, "i");
+MODULE_PARM(arlan_exit_debug, "i");
+MODULE_PARM(arlan_entry_and_exit_debug, "i");
+MODULE_PARM(arlan_EEPROM_bad, "i");
+
+EXPORT_SYMBOL(arlan_device);
+EXPORT_SYMBOL(last_arlan);
+
+
+//        #warning kernel 2.1.110 tested
+#define myATOMIC_INIT(a,b) atomic_set(&(a),b)
+#define __initfunctio(a)                __initfunc(a)
+
+#else
+#define test_and_set_bit	set_bit
+#define __initfunctio(a)        a
+#if LINUX_VERSION_CODE != 0x20024
+ //        #warning kernel  2.0.36  tested
+#endif
+#define myATOMIC_INIT(a,b) a = b;
+
+#endif
+
+struct arlan_conf_stru arlan_conf[MAX_ARLANS];
+int arlans_found = 0;
+
+static  int 	arlan_probe_here(struct device *dev, int ioaddr);
+static  int 	arlan_open(struct device *dev);
+static  int 	arlan_tx(struct sk_buff *skb, struct device *dev);
+static  void 	arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static  int 	arlan_close(struct device *dev);
+static  struct enet_statistics *
+		arlan_statistics		(struct device *dev);
+static  void 	arlan_set_multicast		(struct device *dev);
+static  int 	arlan_hw_tx			(struct device* dev, char *buf, int length );
+static  int	arlan_hw_config			(struct device * dev);
+static  void 	arlan_tx_done_interrupt		(struct device * dev, int status);
+static  void	arlan_rx_interrupt		(struct device * dev, u_char rxStatus, u_short, u_short);
+static  void	arlan_process_interrupt		(struct device * dev);
+static  int	arlan_command(struct device * dev, int command);
+
+EXPORT_SYMBOL(arlan_command);
+
+extern inline long long arlan_time(void)
+{
+	struct timeval timev;
+	do_gettimeofday(&timev);
+	return ((long long) timev.tv_sec * 1000000 + timev.tv_usec);
+};
+
+#ifdef ARLAN_ENTRY_EXIT_DEBUGING
+#define ARLAN_DEBUG_ENTRY(name) \
+	{\
+	struct timeval timev;\
+	do_gettimeofday(&timev);\
+		if (arlan_entry_debug || arlan_entry_and_exit_debug)\
+			printk("--->>>" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec));\
+	}
+#define ARLAN_DEBUG_EXIT(name) \
+	{\
+	struct timeval timev;\
+	do_gettimeofday(&timev);\
+		if (arlan_exit_debug || arlan_entry_and_exit_debug)\
+			printk("<<<---" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec) );\
+	}
+#else
+#define ARLAN_DEBUG_ENTRY(name)
+#define ARLAN_DEBUG_EXIT(name)
+#endif
+
+
+#define arlan_interrupt_ack(dev)\
+        clearClearInterrupt(dev);\
+        setClearInterrupt(dev);
+
+
+#define ARLAN_COMMAND_LOCK(dev) \
+	if (atomic_dec_and_test(&((struct arlan_private * )dev->priv)->card_users))\
+   		arlan_wait_command_complete_short(dev,__LINE__);
+#define ARLAN_COMMAND_UNLOCK(dev) \
+	atomic_inc(&((struct arlan_private * )dev->priv)->card_users);
+
+
+#define ARLAN_COMMAND_INC(dev) \
+ 	{((struct arlan_private *) dev->priv)->under_command++;}
+#define ARLAN_COMMAND_ZERO(dev) \
+ 	{((struct arlan_private *) dev->priv)->under_command =0;}
+#define ARLAN_UNDER_COMMAND(dev)\
+	(((struct arlan_private *) dev->priv)->under_command)
+
+#define ARLAN_COMMAND_START(dev) ARLAN_COMMAND_INC(dev)
+#define ARLAN_COMMAND_END(dev) ARLAN_COMMAND_ZERO(dev)
+#define ARLAN_TOGGLE_START(dev)\
+ 	{((struct arlan_private *) dev->priv)->under_toggle++;}
+#define ARLAN_TOGGLE_END(dev)\
+ 	{((struct arlan_private *) dev->priv)->under_toggle=0;}
+#define ARLAN_UNDER_TOGGLE(dev)\
+ 	(((struct arlan_private *) dev->priv)->under_toggle)
+
+
+
+extern inline int arlan_drop_tx(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	priv->stats.tx_errors++;
+	if (priv->Conf->tx_delay_ms)
+	{
+		priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1;
+	}
+	else
+	{
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_TX;
+		TXHEAD(dev).offset = 0;
+		TXTAIL(dev).offset = 0;
+		priv->txLast = 0;
+		priv->txOffset = 0;
+		priv->bad = 0;
+		if (!priv->under_reset && !priv->under_config)
+		{
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
+		}
+	}
+	return 1;
+};
+
+
+static int arlan_command(struct device *dev, int command_p)
+{
+
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	int udelayed = 0;
+	int i = 0;
+	long long time_mks = arlan_time();
+
+	ARLAN_DEBUG_ENTRY("arlan_command");
+
+	if (priv->card_polling_interval)
+		priv->card_polling_interval = 1;
+
+	if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+		printk(KERN_DEBUG "arlan_command, %lx lock %x  commandByte %x waiting %x incoming %x \n",
+		jiffies, priv->command_lock, READSHMB(arlan->commandByte),
+		       priv->waiting_command_mask, command_p);
+
+	priv->waiting_command_mask |= command_p;
+
+	if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
+		if (jiffies - priv->lastReset < 5 * HZ)
+			priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET;
+
+	if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ACK)
+	{
+		arlan_interrupt_ack(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ACK;
+	}
+	if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ENABLE)
+	{
+		setInterruptEnable(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ENABLE;
+	}
+
+	/* Card access serializing lock */
+
+	if (test_and_set_bit(0, (void *) &priv->command_lock))
+	{
+		if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+			printk(KERN_DEBUG "arlan_command: entered when command locked \n");
+		goto command_busy_end;
+	}
+	/* Check cards status and waiting */
+
+	if (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW))
+	{
+		while (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW))
+		{
+			if (READSHMB(arlan->resetFlag) ||
+				READSHMB(arlan->commandByte))	/* || 
+								   (readControlRegister(dev) & ARLAN_ACCESS))
+								 */
+				udelay(40);
+			else
+				priv->waiting_command_mask &= ~(ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW);
+
+			udelayed++;
+
+			if (priv->waiting_command_mask & ARLAN_COMMAND_LONG_WAIT_NOW)
+			{
+				if (udelayed * 40 > 1000000)
+				{
+					printk(KERN_ERR "%s long wait too long \n", dev->name);
+					priv->waiting_command_mask |= ARLAN_COMMAND_RESET;
+					break;
+				}
+			}
+			else if (priv->waiting_command_mask & ARLAN_COMMAND_WAIT_NOW)
+			{
+				if (udelayed * 40 > 1000)
+				{
+					printk(KERN_ERR "%s short wait too long \n", dev->name);
+					goto bad_end;
+				}
+			}
+		}
+	}
+	else
+	{
+		i = 0;
+		while ((READSHMB(arlan->resetFlag) ||
+			READSHMB(arlan->commandByte)) &&
+			conf->pre_Command_Wait > (i++) * 10)
+			udelay(10);
+
+
+		if ((READSHMB(arlan->resetFlag) ||
+			READSHMB(arlan->commandByte)) &&
+			!(priv->waiting_command_mask & ARLAN_COMMAND_RESET))
+		{
+			goto card_busy_end;
+		}
+	}
+	if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
+	{
+		priv->under_reset = 1;
+		dev->start = 0;
+	}
+	if (priv->waiting_command_mask & ARLAN_COMMAND_CONF)
+	{
+		priv->under_config = 1;
+		dev->start = 0;
+	}
+
+	/* Issuing command */
+	arlan_lock_card_access(dev);
+	if (priv->waiting_command_mask & ARLAN_COMMAND_POWERUP)
+	{
+	//     if (readControlRegister(dev) & (ARLAN_ACCESS && ARLAN_POWER))
+		setPowerOn(dev);
+		arlan_interrupt_lancpu(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERUP;
+		priv->waiting_command_mask |= ARLAN_COMMAND_RESET;
+		priv->card_polling_interval = HZ / 10;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_ACTIVATE)
+	{
+		WRITESHMB(arlan->commandByte, ARLAN_COM_ACTIVATE);
+		arlan_interrupt_lancpu(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_ACTIVATE;
+		priv->card_polling_interval = HZ / 10;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_RX_ABORT)
+	{
+		if (priv->rx_command_given)
+		{
+			WRITESHMB(arlan->commandByte, ARLAN_COM_RX_ABORT);
+			arlan_interrupt_lancpu(dev);
+			priv->rx_command_given = 0;
+		}
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_RX_ABORT;
+		priv->card_polling_interval = 1;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_TX_ABORT)
+	{
+		if (priv->tx_command_given)
+		{
+			WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ABORT);
+			arlan_interrupt_lancpu(dev);
+			priv->tx_command_given = 0;
+		}
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_TX_ABORT;
+		priv->card_polling_interval = 1;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET)
+	{
+		arlan_drop_tx(dev);
+		if (priv->tx_command_given || priv->rx_command_given)
+		{
+			printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
+		};
+		if (arlan_debug & ARLAN_DEBUG_RESET)
+			printk(KERN_ERR "%s: Doing chip reset\n", dev->name);
+		priv->lastReset = jiffies;
+		WRITESHM(arlan->commandByte, 0, u_char);
+		/* hold card in reset state */
+		setHardwareReset(dev);
+		/* set reset flag and then release reset */
+		WRITESHM(arlan->resetFlag, 0xff, u_char);
+		clearChannelAttention(dev);
+		clearHardwareReset(dev);
+		priv->numResets++;
+		priv->card_polling_interval = HZ / 4;
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET;
+		priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;
+//		priv->waiting_command_mask |= ARLAN_COMMAND_INT_RENABLE; 
+//		priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RACK)
+	{
+		clearHardwareReset(dev);
+		clearClearInterrupt(dev);
+		setClearInterrupt(dev);
+		setInterruptEnable(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RACK;
+		priv->waiting_command_mask |= ARLAN_COMMAND_CONF;
+		priv->under_config = 1;
+		priv->under_reset = 0;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RENABLE)
+	{
+		setInterruptEnable(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RENABLE;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF)
+	{
+		if (priv->tx_command_given || priv->rx_command_given)
+		{
+			printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name);
+		}
+		dev->start = 0;
+		arlan_drop_tx(dev);
+		setInterruptEnable(dev);
+		arlan_hw_config(dev);
+		arlan_interrupt_lancpu(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF;
+		priv->card_polling_interval = HZ / 10;
+//		priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK;   
+//		priv->waiting_command_mask |= ARLAN_COMMAND_INT_ENABLE; 
+		priv->waiting_command_mask |= ARLAN_COMMAND_CONF_WAIT;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF_WAIT)
+	{
+		if (READSHMB(arlan->configuredStatusFlag) != 0 &&
+			READSHMB(arlan->diagnosticInfo) == 0xff)
+		{
+			priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT;
+			priv->waiting_command_mask |= ARLAN_COMMAND_RX;
+			priv->card_polling_interval = HZ / 10;
+			priv->tx_command_given = 0;
+			priv->under_config = 0;
+			if (dev->tbusy || !dev->start)
+			{
+				dev->tbusy = 0;
+				dev->start = 1;
+				mark_bh(NET_BH);
+			};
+		}
+		else
+		{
+			priv->card_polling_interval = 1;
+			if (arlan_debug & ARLAN_DEBUG_TIMING)
+				printk(KERN_ERR "configure delayed \n");
+		}
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_RX)
+	{
+		if (!registrationBad(dev))
+		{
+			setInterruptEnable(dev);
+			memset_io((void *) arlan->commandParameter, 0, 0xf);
+			WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE);
+			WRITESHMB(arlan->commandParameter[0], conf->rxParameter);
+			arlan_interrupt_lancpu(dev);
+			priv->rx_command_given;
+			priv->last_rx_time = arlan_time();
+			priv->waiting_command_mask &= ~ARLAN_COMMAND_RX;
+			priv->card_polling_interval = 1;
+		}
+		else
+			priv->card_polling_interval = 2;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_TX)
+	{
+		if (!test_and_set_bit(0, (void *) &priv->tx_command_given))
+		{
+			if ((time_mks - priv->last_tx_time > conf->rx_tweak1) ||
+				(time_mks - priv->last_rx_int_ack_time < conf->rx_tweak2))
+			{
+				setInterruptEnable(dev);
+				memset_io((void *) arlan->commandParameter, 0, 0xf);
+				WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ENABLE | ARLAN_COM_INT);
+				memcpy_toio((void *) arlan->commandParameter, &TXLAST(dev), 14);
+//				for ( i=1 ; i < 15 ; i++) printk("%02x:",READSHMB(arlan->commandParameter[i]));
+				priv->last_command_was_rx = 0;
+				priv->tx_last_sent = jiffies;
+				arlan_interrupt_lancpu(dev);
+				priv->last_tx_time = arlan_time();
+				priv->tx_command_given = 1;
+				priv->waiting_command_mask &= ~ARLAN_COMMAND_TX;
+				priv->card_polling_interval = 1;
+			}
+			else
+			{
+				priv->tx_command_given = 0;
+				priv->card_polling_interval = 1;
+			}
+		} 
+		else if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+			printk(KERN_ERR "tx command when tx chain locked \n");
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOPINT)
+	{
+		{
+			WRITESHMB(arlan->commandByte, ARLAN_COM_NOP | ARLAN_COM_INT);
+		}
+		arlan_interrupt_lancpu(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOPINT;
+		priv->card_polling_interval = HZ / 3;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOP)
+	{
+		WRITESHMB(arlan->commandByte, ARLAN_COM_NOP);
+		arlan_interrupt_lancpu(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOP;
+		priv->card_polling_interval = HZ / 3;
+	}
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_SLOW_POLL)
+	{
+		WRITESHMB(arlan->commandByte, ARLAN_COM_GOTO_SLOW_POLL);
+		arlan_interrupt_lancpu(dev);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_SLOW_POLL;
+		priv->card_polling_interval = HZ / 3;
+	} 
+	else if (priv->waiting_command_mask & ARLAN_COMMAND_POWERDOWN)
+	{
+		setPowerOff(dev);
+		if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+			printk(KERN_WARNING "%s: Arlan Going Standby\n", dev->name);
+		priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERDOWN;
+		priv->card_polling_interval = 3 * HZ;
+	}
+	arlan_unlock_card_access(dev);
+	for (i = 0; READSHMB(arlan->commandByte) && i < 20; i++)
+		udelay(10);
+	if (READSHMB(arlan->commandByte))
+		if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+			printk(KERN_ERR "card busy leaving command %x \n", priv->waiting_command_mask);
+
+	priv->command_lock = 0;
+	ARLAN_DEBUG_EXIT("arlan_command");
+	priv->last_command_buff_free_time = jiffies;
+	return 0;
+
+card_busy_end:
+	if (jiffies - priv->last_command_buff_free_time > HZ)
+		priv->waiting_command_mask |= ARLAN_COMMAND_CLEAN_AND_RESET;
+
+	if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+		printk(KERN_ERR "%s arlan_command card busy end \n", dev->name);
+	priv->command_lock = 0;
+	ARLAN_DEBUG_EXIT("arlan_command");
+	return 1;
+
+bad_end:
+	printk(KERN_ERR "%s arlan_command bad end \n", dev->name);
+
+	priv->command_lock = 0;
+	ARLAN_DEBUG_EXIT("arlan_command");
+
+	return -1;
+
+command_busy_end:
+	if (arlan_debug & ARLAN_DEBUG_CARD_STATE)
+		printk(KERN_ERR "%s arlan_command command busy end \n", dev->name);
+	ARLAN_DEBUG_EXIT("arlan_command");
+	return 2;
+
+};
+
+extern inline void arlan_command_process(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	int times = 0;
+	while (priv->waiting_command_mask && times < 8)
+	{
+		if (priv->waiting_command_mask)
+		{
+			if (arlan_command(dev, 0))
+				break;
+			times++;
+		}
+		/* if long command, we wont repeat trying */ ;
+		if (priv->card_polling_interval > 1)
+			break;
+		times++;
+	}
+}
+
+
+extern inline void arlan_retransmit_now(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+
+	ARLAN_DEBUG_ENTRY("arlan_retransmit_now");
+	if (TXLAST(dev).offset == 0)
+	{
+		if (TXHEAD(dev).offset)
+		{
+			priv->txLast = 0;
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to head \n");
+
+		}
+		else if (TXTAIL(dev).offset)
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to tail \n");
+			priv->txLast = 1;
+		}
+		else
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "ReTransmit buff empty");
+		priv->txOffset = 0;
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+		return;
+
+	}
+	arlan_command(dev, ARLAN_COMMAND_TX);
+
+	priv->nof_tx++;
+
+	priv->Conf->driverRetransmissions++;
+	priv->retransmissions++;
+
+	IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("Retransmit %d bytes \n", TXLAST(dev).length);
+
+	ARLAN_DEBUG_EXIT("arlan_retransmit_now");
+}
+
+
+
+static void arlan_registration_timer(unsigned long data)
+{
+	struct device *dev = (struct device *) data;
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+
+	int lostTime = ((int) (jiffies - priv->registrationLastSeen)) * 1000 / HZ;
+	int bh_mark_needed = 0;
+	int next_tick = 1;
+
+
+	priv->timer_chain_active = 1;
+
+
+	if (registrationBad(dev))
+	{
+		//debug=100;
+		priv->registrationLostCount++;
+		if (lostTime > 7000 && lostTime < 7200)
+		{
+			printk(KERN_NOTICE "%s registration Lost \n", dev->name);
+		}
+		if (lostTime / priv->reRegisterExp > 2000)
+			arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF);
+		if (lostTime / (priv->reRegisterExp) > 3500)
+			arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
+		if (priv->reRegisterExp < 400)
+			priv->reRegisterExp += 2;
+		if (lostTime > 7200)
+		{
+			next_tick = HZ;
+			arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
+		}
+	}
+	else
+	{
+		if (priv->Conf->registrationMode && lostTime > 10000 &&
+			priv->registrationLostCount)
+		{
+			printk(KERN_NOTICE "%s registration is back after %d milliseconds\n", dev->name,
+				((int) (jiffies - priv->registrationLastSeen) * 1000) / HZ);
+		}
+		priv->registrationLastSeen = jiffies;
+		priv->registrationLostCount = 0;
+		priv->reRegisterExp = 1;
+		if (dev->start == 0)
+		{
+			dev->start = 1;
+			mark_bh(NET_BH);
+		}
+	}
+
+
+	if (!registrationBad(dev) && priv->ReTransmitRequested)
+	{
+		IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+			printk(KERN_ERR "Retranmit from timer \n");
+		priv->ReTransmitRequested = 0;
+		arlan_retransmit_now(dev);
+	}
+	if (!registrationBad(dev) &&
+		priv->tx_done_delayed < jiffies &&
+		priv->tx_done_delayed != 0)
+	{
+		TXLAST(dev).offset = 0;
+		if (priv->txLast)
+			priv->txLast = 0;
+		else if (TXTAIL(dev).offset)
+			priv->txLast = 1;
+		if (TXLAST(dev).offset)
+		{
+			arlan_retransmit_now(dev);
+			dev->trans_start = jiffies;
+		}
+		if (!(TXHEAD(dev).offset && TXTAIL(dev).offset))
+		{
+			priv->txOffset = 0;
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
+		}
+		priv->tx_done_delayed = 0;
+		bh_mark_needed = 1;
+	}
+	if (bh_mark_needed)
+	{
+		priv->txOffset = 0;
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+	}
+	arlan_process_interrupt(dev);
+
+	if (next_tick < priv->card_polling_interval)
+		next_tick = priv->card_polling_interval;
+
+	priv->timer_chain_active = 0;
+	priv->timer.expires = jiffies + next_tick;
+
+	add_timer(&priv->timer);
+}
+
+
+
+
+static void arlan_print_registers(struct device *dev, int line)
+{
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+	u_char hostcpuLock, lancpuLock, controlRegister, cntrlRegImage,
+		txStatus, rxStatus, interruptInProgress, commandByte;
+
+
+	ARLAN_DEBUG_ENTRY("arlan_print_registers");
+	READSHM(interruptInProgress, arlan->interruptInProgress, u_char);
+	READSHM(hostcpuLock, arlan->hostcpuLock, u_char);
+	READSHM(lancpuLock, arlan->lancpuLock, u_char);
+	READSHM(controlRegister, arlan->controlRegister, u_char);
+	READSHM(cntrlRegImage, arlan->cntrlRegImage, u_char);
+	READSHM(txStatus, arlan->txStatus, u_char);
+	READSHM(rxStatus, arlan->rxStatus, u_char);
+	READSHM(commandByte, arlan->commandByte, u_char);
+
+	printk(KERN_WARNING "line %04d IP %02x HL %02x LL %02x CB %02x CR %02x CRI %02x TX %02x RX %02x\n",
+		line, interruptInProgress, hostcpuLock, lancpuLock, commandByte,
+		controlRegister, cntrlRegImage, txStatus, rxStatus);
+
+	ARLAN_DEBUG_EXIT("arlan_print_registers");
+}
+
+
+static int arlan_hw_tx(struct device *dev, char *buf, int length)
+{
+	int i;
+
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	volatile struct arlan_shmem *arlan = priv->card;
+	struct arlan_conf_stru *conf = priv->Conf;
+
+	int tailStarts = 0x800;
+	int headEnds = 0x0;
+
+
+	ARLAN_DEBUG_ENTRY("arlan_hw_tx");
+	if (TXHEAD(dev).offset)
+		headEnds = (((TXHEAD(dev).offset + TXHEAD(dev).length - (((int) arlan->txBuffer) - ((int) arlan))) / 64) + 1) * 64;
+	if (TXTAIL(dev).offset)
+		tailStarts = 0x800 - (((TXTAIL(dev).offset - (((int) arlan->txBuffer) - ((int) arlan))) / 64) + 2) * 64;
+
+
+	if (!TXHEAD(dev).offset && length < tailStarts)
+	{
+		IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+			printk(KERN_ERR "TXHEAD insert, tailStart %d\n", tailStarts);
+
+		TXHEAD(dev).offset =
+			(((int) arlan->txBuffer) - ((int) arlan));
+		TXHEAD(dev).length = length - ARLAN_FAKE_HDR_LEN;
+		for (i = 0; i < 6; i++)
+			TXHEAD(dev).dest[i] = buf[i];
+		TXHEAD(dev).clear = conf->txClear;
+		TXHEAD(dev).retries = conf->txRetries;	/* 0 is use default */
+		TXHEAD(dev).routing = conf->txRouting;
+		TXHEAD(dev).scrambled = conf->txScrambled;
+		memcpy_toio(((char *) arlan + TXHEAD(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXHEAD(dev).length);
+	}
+	else if (!TXTAIL(dev).offset && length < (0x800 - headEnds))
+	{
+		IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+			printk(KERN_ERR "TXTAIL insert, headEnd %d\n", headEnds);
+
+		TXTAIL(dev).offset =
+			(((int) arlan->txBuffer) - ((int) arlan)) + 0x800 - (length / 64 + 2) * 64;
+		TXTAIL(dev).length = length - ARLAN_FAKE_HDR_LEN;
+		for (i = 0; i < 6; i++)
+			TXTAIL(dev).dest[i] = buf[i];
+		TXTAIL(dev).clear = conf->txClear;
+		TXTAIL(dev).retries = conf->txRetries;
+		TXTAIL(dev).routing = conf->txRouting;
+		TXTAIL(dev).scrambled = conf->txScrambled;
+		memcpy_toio(((char *) arlan + TXTAIL(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXTAIL(dev).length);
+	}
+	else
+	{
+		dev->tbusy = 1;
+		return -1;
+		IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+			printk(KERN_ERR "TX TAIL & HEAD full, return, tailStart %d headEnd %d\n", tailStarts, headEnds);
+	}
+	priv->out_bytes += length;
+	priv->out_bytes10 += length;
+	if (conf->measure_rate < 1)
+		conf->measure_rate = 1;
+	if (jiffies - priv->out_time > conf->measure_rate * HZ)
+	{
+		conf->out_speed = priv->out_bytes / conf->measure_rate;
+		priv->out_bytes = 0;
+		priv->out_time = jiffies;
+	}
+	if (jiffies - priv->out_time10 > conf->measure_rate * HZ * 10)
+	{
+		conf->out_speed10 = priv->out_bytes10 / (10 * conf->measure_rate);
+		priv->out_bytes10 = 0;
+		priv->out_time10 = jiffies;
+	}
+	if (TXHEAD(dev).offset && TXTAIL(dev).offset)
+	{
+		dev->tbusy = 1;
+		return 0;
+	}
+	else
+		dev->tbusy = 0;
+
+
+	IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
+		printk(KERN_WARNING "%s Transmit t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name,
+		   (unsigned char) buf[0], (unsigned char) buf[1], (unsigned char) buf[2], (unsigned char) buf[3],
+		   (unsigned char) buf[4], (unsigned char) buf[5], (unsigned char) buf[6], (unsigned char) buf[7],
+		   (unsigned char) buf[8], (unsigned char) buf[9], (unsigned char) buf[10], (unsigned char) buf[11]);
+
+	IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "TX command prepare for buffer %d\n", priv->txLast);
+
+	arlan_command(dev, ARLAN_COMMAND_TX);
+
+	priv->last_command_was_rx = 0;
+	priv->tx_last_sent = jiffies;
+	priv->nof_tx++;
+
+	IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("%s TX Qued %d bytes \n", dev->name, length);
+
+	ARLAN_DEBUG_EXIT("arlan_hw_tx");
+
+	return 0;
+}
+
+
+static int arlan_hw_config(struct device *dev)
+{
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+
+	ARLAN_DEBUG_ENTRY("arlan_hw_config");
+
+	printk(KERN_NOTICE "%s arlan configure called \n", dev->name);
+	if (arlan_EEPROM_bad)
+		printk(KERN_NOTICE "arlan configure with eeprom bad option \n");
+
+
+	WRITESHM(arlan->spreadingCode, conf->spreadingCode, u_char);
+	WRITESHM(arlan->channelSet, conf->channelSet, u_char);
+
+	if (arlan_EEPROM_bad)
+		WRITESHM(arlan->defaultChannelSet, conf->channelSet, u_char);
+
+	WRITESHM(arlan->channelNumber, conf->channelNumber, u_char);
+
+	WRITESHM(arlan->scramblingDisable, conf->scramblingDisable, u_char);
+	WRITESHM(arlan->txAttenuation, conf->txAttenuation, u_char);
+
+	WRITESHM(arlan->systemId, conf->systemId, u_int);
+
+	WRITESHM(arlan->maxRetries, conf->maxRetries, u_char);
+	WRITESHM(arlan->receiveMode, conf->receiveMode, u_char);
+	WRITESHM(arlan->priority, conf->priority, u_char);
+	WRITESHM(arlan->rootOrRepeater, conf->rootOrRepeater, u_char);
+	WRITESHM(arlan->SID, conf->SID, u_int);
+
+	WRITESHM(arlan->registrationMode, conf->registrationMode, u_char);
+
+	WRITESHM(arlan->registrationFill, conf->registrationFill, u_char);
+	WRITESHM(arlan->localTalkAddress, conf->localTalkAddress, u_char);
+	WRITESHM(arlan->codeFormat, conf->codeFormat, u_char);
+	WRITESHM(arlan->numChannels, conf->numChannels, u_char);
+	WRITESHM(arlan->channel1, conf->channel1, u_char);
+	WRITESHM(arlan->channel2, conf->channel2, u_char);
+	WRITESHM(arlan->channel3, conf->channel3, u_char);
+	WRITESHM(arlan->channel4, conf->channel4, u_char);
+	WRITESHM(arlan->radioNodeId, conf->radioNodeId, u_short);
+	WRITESHM(arlan->SID, conf->SID, u_int);
+	WRITESHM(arlan->waitTime, conf->waitTime, u_short);
+	WRITESHM(arlan->lParameter, conf->lParameter, u_short);
+	memcpy_toio(&(arlan->_15), &(conf->_15), 3);
+	WRITESHM(arlan->_15, conf->_15, u_short);
+	WRITESHM(arlan->headerSize, conf->headerSize, u_short);
+	if (arlan_EEPROM_bad)
+		WRITESHM(arlan->hardwareType, conf->hardwareType, u_char);
+	WRITESHM(arlan->radioType, conf->radioType, u_char);
+	if (arlan_EEPROM_bad)
+		WRITESHM(arlan->radioModule, conf->radioType, u_char);
+
+	memcpy_toio(arlan->encryptionKey + keyStart, encryptionKey, 8);
+	memcpy_toio(arlan->name, conf->siteName, 16);
+
+	WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_CONF);	/* do configure */
+	memset_io(arlan->commandParameter, 0, 0xf);	/* 0xf */
+	memset_io(arlan->commandParameter + 1, 0, 2);
+	if (conf->writeEEPROM)
+	{
+		  memset_io(arlan->commandParameter, conf->writeEEPROM, 1);
+//		conf->writeEEPROM=0;
+	}
+	if (conf->registrationMode && conf->registrationInterrupts)
+		memset_io(arlan->commandParameter + 3, 1, 1);
+	else
+		memset_io(arlan->commandParameter + 3, 0, 1);
+
+	priv->irq_test_done = 0;
+
+	if (conf->tx_queue_len)
+		dev->tx_queue_len = conf->tx_queue_len;
+	udelay(100);
+
+	ARLAN_DEBUG_EXIT("arlan_hw_config");
+	return 0;
+}
+
+
+static int arlan_read_card_configuration(struct device *dev)
+{
+	u_char tlx415;
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+
+	ARLAN_DEBUG_ENTRY("arlan_read_card_configuration");
+
+	if (radioNodeId == radioNodeIdUNKNOWN)
+	{
+		READSHM(conf->radioNodeId, arlan->radioNodeId, u_short);
+	}
+	else
+		conf->radioNodeId = radioNodeId;
+		
+	if (SID == SIDUNKNOWN)
+	{
+		READSHM(conf->SID, arlan->SID, u_int);
+	}
+	else conf->SID = SID;
+		
+	if (spreadingCode == spreadingCodeUNKNOWN)
+	{
+		  READSHM(conf->spreadingCode, arlan->spreadingCode, u_char);
+	}
+	else
+		conf->spreadingCode = spreadingCode;
+		
+	if (channelSet == channelSetUNKNOWN)
+	{
+		READSHM(conf->channelSet, arlan->channelSet, u_char);
+	}
+	else conf->channelSet = channelSet;
+
+	if (channelNumber == channelNumberUNKNOWN)
+	{
+		READSHM(conf->channelNumber, arlan->channelNumber, u_char);
+	}
+	else conf->channelNumber = channelNumber;
+	
+	READSHM(conf->scramblingDisable, arlan->scramblingDisable, u_char);
+	READSHM(conf->txAttenuation, arlan->txAttenuation, u_char);
+	
+	if (systemId == systemIdUNKNOWN)
+	{
+		READSHM(conf->systemId, arlan->systemId, u_int);
+	} 
+	else conf->systemId = systemId;
+	
+	READSHM(conf->maxDatagramSize, arlan->maxDatagramSize, u_short);
+	READSHM(conf->maxFrameSize, arlan->maxFrameSize, u_short);
+	READSHM(conf->maxRetries, arlan->maxRetries, u_char);
+	READSHM(conf->receiveMode, arlan->receiveMode, u_char);
+	READSHM(conf->priority, arlan->priority, u_char);
+	READSHM(conf->rootOrRepeater, arlan->rootOrRepeater, u_char);
+
+	if (SID == SIDUNKNOWN)
+	{
+		  READSHM(conf->SID, arlan->SID, u_int);
+	}
+	else conf->SID = SID;
+	
+	if (registrationMode == registrationModeUNKNOWN)
+	{
+		  READSHM(conf->registrationMode, arlan->registrationMode, u_char);
+	}
+	else conf->registrationMode = registrationMode;
+	
+	READSHM(conf->registrationFill, arlan->registrationFill, u_char);
+	READSHM(conf->localTalkAddress, arlan->localTalkAddress, u_char);
+	READSHM(conf->codeFormat, arlan->codeFormat, u_char);
+	READSHM(conf->numChannels, arlan->numChannels, u_char);
+	READSHM(conf->channel1, arlan->channel1, u_char);
+	READSHM(conf->channel2, arlan->channel2, u_char);
+	READSHM(conf->channel3, arlan->channel3, u_char);
+	READSHM(conf->channel4, arlan->channel4, u_char);
+	READSHM(conf->waitTime, arlan->waitTime, u_short);
+	READSHM(conf->lParameter, arlan->lParameter, u_short);
+	READSHM(conf->_15, arlan->_15, u_short);
+	READSHM(conf->headerSize, arlan->headerSize, u_short);
+	READSHM(conf->hardwareType, arlan->hardwareType, u_char);
+	READSHM(conf->radioType, arlan->radioModule, u_char);
+	
+	if (conf->radioType == 0)
+		conf->radioType = 0xc;
+
+	WRITESHM(arlan->configStatus, 0xA5, u_char);
+	READSHM(tlx415, arlan->configStatus, u_char);
+	
+	if (tlx415 != 0xA5)
+		printk(KERN_INFO "%s tlx415 chip \n", dev->name);
+	
+	conf->txClear = 0;
+	conf->txRetries = 1;
+	conf->txRouting = 1;
+	conf->txScrambled = 0;
+	conf->rxParameter = 1;
+	conf->txTimeoutMs = 4000;
+	conf->waitCardTimeout = 100000;
+	conf->receiveMode = ARLAN_RCV_CLEAN;
+	memcpy_fromio(conf->siteName, arlan->name, 16);
+	conf->siteName[16] = '\0';
+	conf->retries = retries;
+	conf->tx_delay_ms = tx_delay_ms;
+	conf->async = async;
+	conf->ReTransmitPacketMaxSize = 200;
+	conf->waitReTransmitPacketMaxSize = 200;
+	conf->txAckTimeoutMs = 900;
+	conf->fastReTransCount = 3;
+
+	ARLAN_DEBUG_EXIT("arlan_read_card_configuration");
+
+	return 0;
+}
+
+
+static int lastFoundAt = 0xbe000;
+
+
+/*
+ * This is the real probe routine. Linux has a history of friendly device
+ * probes on the ISA bus. A good device probes avoids doing writes, and
+ * verifies that the correct device exists and functions.
+ */
+
+__initfunctio(static int arlan_check_fingerprint(int memaddr))
+{
+	static char probeText[] = "TELESYSTEM SLW INC.    ARLAN \0";
+	char tempBuf[49];
+	volatile struct arlan_shmem *arlan = (struct arlan_shmem *) memaddr;
+
+	ARLAN_DEBUG_ENTRY("arlan_check_fingerprint");
+	memcpy_fromio(tempBuf, arlan->textRegion, 29);
+	tempBuf[30] = 0;
+
+	/* check for card at this address */
+	if (0 != strncmp(tempBuf, probeText, 29))
+		return -ENODEV;
+
+//   printk(KERN_INFO "arlan found at 0x%x \n",memaddr);
+	ARLAN_DEBUG_EXIT("arlan_check_fingerprint");
+
+	return 0;
+
+
+}
+
+__initfunctio(int arlan_probe_everywhere(struct device *dev))
+{
+	int m;
+	int probed = 0;
+	int found = 0;
+
+	ARLAN_DEBUG_ENTRY("arlan_probe_everywhere");
+	if (mem != 0 && numDevices == 1)	/* Check a single specified location. */
+	{
+		if (arlan_probe_here(dev, mem) == 0)
+			return 0;
+		else
+			return -ENODEV;
+	}
+	for (m = lastFoundAt + 0x2000; m <= 0xDE000; m += 0x2000)
+	{
+		if (arlan_probe_here(dev, m) == 0)
+		{
+			found++;
+			lastFoundAt = m;
+			break;
+		}
+		probed++;
+	}
+	if (found == 0 && probed != 0)
+	{
+		if (lastFoundAt == 0xbe000)
+			printk(KERN_ERR "arlan: No Arlan devices found \n");
+		return ENODEV;
+	}
+	else
+		return 0;
+
+	ARLAN_DEBUG_EXIT("arlan_probe_everywhere");
+
+	return ENODEV;
+}
+
+__initfunctio(int arlan_find_devices(void))
+{
+	int m;
+	int found = 0;
+
+	ARLAN_DEBUG_ENTRY("arlan_find_devices");
+	if (mem != 0 && numDevices == 1)	/* Check a single specified location. */
+		return 1;
+	for (m = 0xc000; m <= 0xDE000; m += 0x2000)
+	{
+		if (arlan_check_fingerprint(m) == 0)
+			found++;
+	}
+	ARLAN_DEBUG_EXIT("arlan_find_devices");
+
+	return found;
+}
+
+
+static int arlan_change_mtu(struct device *dev, int new_mtu)
+{
+	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+
+	ARLAN_DEBUG_ENTRY("arlan_change_mtu");
+	if ((new_mtu < 68) || (new_mtu > 2032))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	if (new_mtu < 256)
+		new_mtu = 256;	/* cards book suggests 1600 */
+	conf->maxDatagramSize = new_mtu;
+	conf->maxFrameSize = new_mtu + 48;
+
+	arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF);
+	printk(KERN_NOTICE "%s mtu changed to %d \n", dev->name, new_mtu);
+
+	ARLAN_DEBUG_EXIT("arlan_change_mtu");
+
+	return 0;
+}
+
+static int arlan_mac_addr(struct device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+
+
+	ARLAN_DEBUG_ENTRY("arlan_mac_addr");
+	return -EINVAL;
+
+	if (dev->start)
+		return -EBUSY;
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	ARLAN_DEBUG_EXIT("arlan_mac_addr");
+	return 0;
+}
+
+
+
+
+__initfunctio(static int
+	      arlan_allocate_device(int num, struct device *devs))
+{
+
+	struct device *dev;
+
+	ARLAN_DEBUG_ENTRY("arlan_allocate_device");
+
+	if (!devs)
+		dev = init_etherdev(0, sizeof(struct arlan_private));
+	else
+	{
+		dev = devs;
+		dev->priv = kmalloc(sizeof(struct arlan_private), GFP_KERNEL);
+	};
+
+	if (dev == NULL || dev->priv == NULL)
+	{
+		printk(KERN_CRIT "init_etherdev failed ");
+		return 0;
+	}
+	((struct arlan_private *) dev->priv)->conf =
+	    kmalloc(sizeof(struct arlan_shmem), GFP_KERNEL);
+
+	if (dev == NULL || dev->priv == NULL ||
+	    ((struct arlan_private *) dev->priv)->conf == NULL)
+	{
+		return 0;
+		printk(KERN_CRIT " No memory at arlan_allocate_device \n");
+	}
+	/* Fill in the 'dev' fields. */
+	dev->base_addr = 0;
+	dev->mem_start = 0;
+	dev->mem_end = 0;
+	dev->mtu = 1500;
+	dev->flags = 0;		/* IFF_BROADCAST & IFF_MULTICAST & IFF_PROMISC; */
+	dev->irq = 0;
+	dev->dma = 0;
+	dev->tx_queue_len = tx_queue_len;
+	ether_setup(dev);
+	dev->tx_queue_len = tx_queue_len;
+	dev->open = arlan_open;
+	dev->stop = arlan_close;
+	dev->hard_start_xmit = arlan_tx;
+	dev->get_stats = arlan_statistics;
+	dev->set_multicast_list = arlan_set_multicast;
+	dev->change_mtu = arlan_change_mtu;
+	dev->set_mac_address = arlan_mac_addr;
+	((struct arlan_private *) dev->priv)->irq_test_done = 0;
+	arlan_device[num] = dev;
+	((struct arlan_private *) arlan_device[num]->priv)->Conf = &(arlan_conf[num]);
+
+	((struct arlan_private *) dev->priv)->Conf->pre_Command_Wait = 40;
+	((struct arlan_private *) dev->priv)->Conf->rx_tweak1 = 30;
+	((struct arlan_private *) dev->priv)->Conf->rx_tweak2 = 0;
+
+	ARLAN_DEBUG_EXIT("arlan_allocate_device");
+	return (int) dev;
+}
+
+
+__initfunctio(int arlan_probe_here(struct device *dev, int memaddr))
+{
+	volatile struct arlan_shmem *arlan;
+
+	ARLAN_DEBUG_ENTRY("arlan_probe_here");
+
+	if (arlan_check_fingerprint(memaddr))
+		return -ENODEV;
+
+	printk(KERN_NOTICE "%s: Arlan found at %#5x, \n ", dev->name, memaddr);
+
+	if (!arlan_allocate_device(arlans_found, dev))
+		return -1;
+
+	((struct arlan_private *) dev->priv)->card = (struct arlan_shmem *) memaddr;
+	arlan = (void *) memaddr;
+
+	dev->mem_start = memaddr;
+	dev->mem_end = memaddr + 0x1FFF;
+
+	if (dev->irq < 2)
+	{
+		READSHM(dev->irq, arlan->irqLevel, u_char);
+	} else if (dev->irq == 2)
+		dev->irq = 9;
+
+	arlan_read_card_configuration(dev);
+
+	ARLAN_DEBUG_EXIT("arlan_probe_here");
+	return 0;
+}
+
+
+
+
+static int arlan_open(struct device *dev)
+{
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	volatile struct arlan_shmem *arlan = priv->card;
+	int ret = 0;
+
+	ARLAN_DEBUG_ENTRY("arlan_open");
+
+	if (dev->mem_start == 0)
+		ret = arlan_probe_everywhere(dev);
+	if (ret != 0)
+		return ret;
+
+	arlan = ((struct arlan_private *) dev->priv)->card;
+
+	if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev))
+	{
+		printk(KERN_ERR "%s: unable to get IRQ %d .\n",
+			dev->name, dev->irq);
+		return -EAGAIN;
+	}
+	arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW);
+
+	priv->bad = 0;
+	priv->lastReset = 0;
+	priv->reset = 0;
+	priv->open_time = jiffies;
+	memcpy_fromio(dev->dev_addr, arlan->lanCardNodeId, 6);
+	memset(dev->broadcast, 0xff, 6);
+	dev->tbusy = 1;
+	priv->txOffset = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+	dev->tx_queue_len = tx_queue_len;
+	init_timer(&priv->timer);
+	priv->timer.expires = jiffies + HZ / 10;
+	priv->timer.data = (unsigned long) dev;
+	priv->timer.function = &arlan_registration_timer;	/* timer handler */
+	priv->interrupt_processing_active = 0;
+	priv->command_lock = 0;
+	add_timer(&priv->timer);
+
+	priv->card_lock = MUTEX;
+	myATOMIC_INIT(priv->card_users, 1);	/* damn 2.0.33 */
+	priv->registrationLostCount = 0;
+	priv->registrationLastSeen = jiffies;
+	priv->txLast = 0;
+	priv->tx_command_given = 0;
+
+	priv->reRegisterExp = 1;
+	priv->nof_tx = 0;
+	priv->nof_tx_ack = 0;
+	priv->last_command_was_rx = 0;
+	priv->tx_last_sent = jiffies - 1;
+	priv->tx_last_cleared = jiffies;
+	priv->Conf->writeEEPROM = 0;
+	priv->Conf->registrationInterrupts = 1;
+
+	dev->tbusy = 0;
+
+	MOD_INC_USE_COUNT;
+#ifdef CONFIG_PROC_FS
+#ifndef MODULE
+	if (arlan_device[0])
+		init_arlan_proc();
+#endif
+#endif
+	ARLAN_DEBUG_EXIT("arlan_open");
+	return 0;
+}
+
+
+
+
+static int arlan_tx(struct sk_buff *skb, struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+
+	ARLAN_DEBUG_ENTRY("arlan_tx");
+
+	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;
+
+		if (((tickssofar * 1000) / HZ) * 2 > conf->txTimeoutMs)
+			arlan_command(dev, ARLAN_COMMAND_TX_ABORT);
+
+		if (((tickssofar * 1000) / HZ) < conf->txTimeoutMs)
+		{
+			// up(&priv->card_lock);
+			goto bad_end;
+		}
+		printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name);
+		/* Try to restart the adaptor. */
+		arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
+		dev->trans_start = jiffies;
+		goto bad_end;
+
+	}
+	/*
+	 * 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_ERR "%s: Transmitter access conflict.\n",
+			dev->name);
+	}
+	else
+	{
+		short length;
+		unsigned char *buf;
+		
+		/*
+		 * If some higher layer thinks we've missed an tx-done interrupt
+		 * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
+		 * itself.
+		 */
+
+		length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+		buf = skb->data;
+
+		if (priv->txOffset + length + 0x12 > 0x800)
+			printk(KERN_ERR "TX RING overflow \n");
+
+		if (arlan_hw_tx(dev, buf, length) == -1)
+			goto bad_end;
+
+		dev->trans_start = jiffies;
+	}
+	dev_kfree_skb(skb);
+
+	arlan_process_interrupt(dev);
+	priv->tx_chain_active = 0;
+	ARLAN_DEBUG_EXIT("arlan_tx");
+	return 0;
+
+bad_end:
+	arlan_process_interrupt(dev);
+	priv->tx_chain_active = 0;
+	ARLAN_DEBUG_EXIT("arlan_tx");
+	return 1;
+}
+
+
+extern inline int DoNotReTransmitCrap(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	if (TXLAST(dev).length < priv->Conf->ReTransmitPacketMaxSize)
+		return 1;
+	return 0;
+
+}
+
+extern inline int DoNotWaitReTransmitCrap(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	if (TXLAST(dev).length < priv->Conf->waitReTransmitPacketMaxSize)
+		return 1;
+	return 0;
+}
+
+extern inline void arlan_queue_retransmit(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	ARLAN_DEBUG_ENTRY("arlan_queue_retransmit");
+
+	if (DoNotWaitReTransmitCrap(dev))
+	{
+		  arlan_drop_tx(dev);
+	} else
+		priv->ReTransmitRequested++;
+
+	ARLAN_DEBUG_EXIT("arlan_queue_retransmit");
+};
+
+extern inline void RetryOrFail(struct device *dev)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	ARLAN_DEBUG_ENTRY("RetryOrFail");
+
+	if (priv->retransmissions > priv->Conf->retries ||
+	    DoNotReTransmitCrap(dev))
+	{
+		arlan_drop_tx(dev);
+	}
+	else if (priv->bad <= priv->Conf->fastReTransCount)
+	{
+		arlan_retransmit_now(dev);
+	}
+	else arlan_queue_retransmit(dev);
+
+	ARLAN_DEBUG_EXIT("RetryOrFail");
+}
+
+
+static void arlan_tx_done_interrupt(struct device *dev, int status)
+{
+	struct arlan_private *priv = ((struct arlan_private *) dev->priv);
+
+	ARLAN_DEBUG_ENTRY("arlan_tx_done_interrupt");
+
+	priv->tx_last_cleared = jiffies;
+	priv->tx_command_given = 0;
+	priv->nof_tx_ack++;
+	switch (status)
+	{
+		case 1:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit OK\n");
+			priv->stats.tx_packets++;
+			priv->bad = 0;
+			priv->reset = 0;
+			priv->retransmissions = 0;
+			if (priv->Conf->tx_delay_ms)
+			{
+				priv->tx_done_delayed = jiffies + (priv->Conf->tx_delay_ms * HZ) / 1000 + 1;;
+			}
+			else
+			{
+				TXLAST(dev).offset = 0;
+				if (priv->txLast)
+					priv->txLast = 0;
+				else if (TXTAIL(dev).offset)
+					priv->txLast = 1;
+				if (TXLAST(dev).offset)
+				{
+					arlan_retransmit_now(dev);
+					dev->trans_start = jiffies;
+				}
+				if (!TXHEAD(dev).offset || !TXTAIL(dev).offset)
+				{
+					priv->txOffset = 0;
+					dev->tbusy = 0;
+					mark_bh(NET_BH);
+				}
+			}
+		}
+		break;
+		
+		case 2:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit timed out\n");
+			priv->bad += 1;
+			//arlan_queue_retransmit(dev);
+			RetryOrFail(dev);
+		}
+		break;
+
+		case 3:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit max retries\n");
+			priv->bad += 1;
+			priv->reset = 0;
+			//arlan_queue_retransmit(dev);
+			RetryOrFail(dev);
+		}
+		break;
+		
+		case 4:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit aborted\n");
+			priv->bad += 1;
+			arlan_queue_retransmit(dev);
+			//RetryOrFail(dev);
+		}
+		break;
+
+		case 5:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit not registered\n");
+			priv->bad += 1;
+			//debug=101;
+			arlan_queue_retransmit(dev);
+		}
+		break;
+
+		case 6:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN) 
+				printk("arlan intr: transmit destination full\n");
+			priv->bad += 1;
+			priv->reset = 0;
+			//arlan_drop_tx(dev);
+			arlan_queue_retransmit(dev);
+		}
+		break;
+
+		case 7:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit unknown ack\n");
+			priv->bad += 1;
+			priv->reset = 0;
+			arlan_queue_retransmit(dev);
+		}
+		break;
+		
+		case 8:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit dest mail box full\n");
+			priv->bad += 1;
+			priv->reset = 0;
+			//arlan_drop_tx(dev);
+			arlan_queue_retransmit(dev);
+		}
+		break;
+
+		case 9:
+		{
+			IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
+				printk("arlan intr: transmit root dest not reg.\n");
+			priv->bad += 1;
+			priv->reset = 1;
+			//arlan_drop_tx(dev);
+			arlan_queue_retransmit(dev);
+		}
+		break;
+
+		default:
+		{
+			printk(KERN_ERR "arlan intr: transmit status unknown\n");
+			priv->bad += 1;
+			priv->reset = 1;
+			arlan_drop_tx(dev);
+		}
+	}
+
+	ARLAN_DEBUG_EXIT("arlan_tx_done_interrupt");
+}
+
+
+static void arlan_rx_interrupt(struct device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len)
+{
+	char *skbtmp;
+	int i = 0;
+
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	volatile struct arlan_shmem *arlan = priv->card;
+	struct arlan_conf_stru *conf = priv->Conf;
+
+
+	ARLAN_DEBUG_ENTRY("arlan_rx_interrupt");
+	// by spec,   not                WRITESHMB(arlan->rxStatus,0x00);
+	// prohibited here              arlan_command(dev, ARLAN_COMMAND_RX);
+
+	if (pkt_len < 10 || pkt_len > 2048)
+	{
+		printk(KERN_WARNING "%s: got too short or long packet, len %d \n", dev->name, pkt_len);
+		return;
+	}
+	if (rxOffset + pkt_len > 0x2000)
+	{
+		printk("%s: got too long packet, len %d offset %x\n", dev->name, pkt_len, rxOffset);
+		return;
+	}
+	priv->in_bytes += pkt_len;
+	priv->in_bytes10 += pkt_len;
+	if (conf->measure_rate < 1)
+		conf->measure_rate = 1;
+	if (jiffies - priv->in_time > conf->measure_rate * HZ)
+	{
+		conf->in_speed = priv->in_bytes / conf->measure_rate;
+		priv->in_bytes = 0;
+		priv->in_time = jiffies;
+	}
+	if (jiffies - priv->in_time10 > conf->measure_rate * HZ * 10)
+	{
+		conf->in_speed10 = priv->in_bytes10 / (10 * conf->measure_rate);
+		priv->in_bytes10 = 0;
+		priv->in_time10 = jiffies;
+	}
+	DEBUGSHM(1, "arlan rcv pkt rxStatus= %d ", arlan->rxStatus, u_char);
+	switch (rxStatus)
+	{
+		case 1:
+		case 2:
+		case 3:
+		{
+			/* Malloc up new buffer. */
+			struct sk_buff *skb;
+
+			DEBUGSHM(50, "arlan recv pkt offs=%d\n", arlan->rxOffset, u_short);
+			DEBUGSHM(1, "arlan rxFrmType = %d \n", arlan->rxFrmType, u_char);
+			DEBUGSHM(1, KERN_INFO "arlan rx scrambled = %d \n", arlan->scrambled, u_char);
+
+			/* here we do multicast filtering to avoid slow 8-bit memcopy */
+#ifdef ARLAN_MULTICAST
+			if (!(dev->flags & IFF_ALLMULTI) &&
+				!(dev->flags & IFF_PROMISC) &&
+				dev->mc_list)
+			{
+				char hw_dst_addr[6];
+				struct dev_mc_list *dmi = dev->mc_list;
+				int i;
+
+				memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6);
+				if (hw_dst_addr[0] == 0x01)
+				{
+					if (mdebug)
+						if (hw_dst_addr[1] == 0x00)
+							printk(KERN_ERR "%s mcast 0x0100 \n", dev->name);
+						else if (hw_dst_addr[1] == 0x40)
+							printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name);
+					while (dmi)
+					{							if (dmi->dmi_addrlen == 6)
+						{
+							if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP)
+								printk(KERN_ERR "%s mcl %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name,
+										 dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
+										 dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
+							for (i = 0; i < 6; i++)
+								if (dmi->dmi_addr[i] != hw_dst_addr[i])
+									break;
+							if (i == 6)
+								break;
+						}
+						else
+							printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name);
+						dmi = dmi->next;
+					}
+					/* we reach here if multicast filtering is on and packet 
+					 * is multicast and not for receive */
+					goto end_of_interupt;
+				}
+			}
+#endif				// ARLAN_MULTICAST
+			/* multicast filtering ends here */
+			pkt_len += ARLAN_FAKE_HDR_LEN;
+
+			skb = dev_alloc_skb(pkt_len + 4);
+			if (skb == NULL)
+			{
+				printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name);
+				priv->stats.rx_dropped++;
+				break;
+			}
+			skb_reserve(skb, 2);
+			skb->dev = dev;
+			skbtmp = skb_put(skb, pkt_len);
+
+			memcpy_fromio(skbtmp + ARLAN_FAKE_HDR_LEN, ((char *) arlan) + rxOffset, pkt_len - ARLAN_FAKE_HDR_LEN);
+			memcpy_fromio(skbtmp, arlan->ultimateDestAddress, 6);
+			memcpy_fromio(skbtmp + 6, arlan->rxSrc, 6);
+			WRITESHMB(arlan->rxStatus, 0x00);
+			arlan_command(dev, ARLAN_COMMAND_RX);
+
+			IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
+			{
+				char immedDestAddress[6];
+				char immedSrcAddress[6];
+				memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6);
+				memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6);
+
+				printk(KERN_WARNING "%s t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x imd %2x:%2x:%2x:%2x:%2x:%2x ims %2x:%2x:%2x:%2x:%2x:%2x\n", dev->name,
+					(unsigned char) skbtmp[0], (unsigned char) skbtmp[1], (unsigned char) skbtmp[2], (unsigned char) skbtmp[3],
+					(unsigned char) skbtmp[4], (unsigned char) skbtmp[5], (unsigned char) skbtmp[6], (unsigned char) skbtmp[7],
+					(unsigned char) skbtmp[8], (unsigned char) skbtmp[9], (unsigned char) skbtmp[10], (unsigned char) skbtmp[11],
+					immedDestAddress[0], immedDestAddress[1], immedDestAddress[2],
+					immedDestAddress[3], immedDestAddress[4], immedDestAddress[5],
+					immedSrcAddress[0], immedSrcAddress[1], immedSrcAddress[2],
+					immedSrcAddress[3], immedSrcAddress[4], immedSrcAddress[5]);
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
+				if (skb->protocol != 0x608 && skb->protocol != 0x8)
+				{
+					for (i = 0; i <= 22; i++)
+						printk("%02x:", (u_char) skbtmp[i + 12]);
+					printk(KERN_ERR "\n");
+					printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol);
+				}
+			netif_rx(skb);
+			priv->stats.rx_packets++;
+		}
+		break;
+		
+		default:
+			printk(KERN_ERR "arlan intr: recieved unknown status\n");
+			priv->stats.rx_crc_errors++;
+			break;
+	}
+	ARLAN_DEBUG_EXIT("arlan_rx_interrupt");
+}
+
+static void arlan_process_interrupt(struct device *dev)
+{
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	volatile struct arlan_shmem *arlan = priv->card;
+	u_char rxStatus = READSHMB(arlan->rxStatus);
+	u_char txStatus = READSHMB(arlan->txStatus);
+	u_short rxOffset = READSHMS(arlan->rxOffset);
+	u_short pkt_len = READSHMS(arlan->rxLength);
+	int interrupt_count = 0;
+
+	ARLAN_DEBUG_ENTRY("arlan_process_interrupt");
+
+	if (test_and_set_bit(0, (void *) &priv->interrupt_processing_active))
+	{
+		if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS)
+			printk(KERN_ERR "interrupt chain reentering \n");
+		goto end_int_process;
+	}
+	while ((rxStatus || txStatus || priv->interrupt_ack_requested)
+			&& (interrupt_count < 5))
+	{
+		if (rxStatus)
+			priv->last_rx_int_ack_time = arlan_time();
+
+		arlan_command(dev, ARLAN_COMMAND_INT_ACK);
+		arlan_command(dev, ARLAN_COMMAND_INT_ENABLE);
+		
+		IFDEBUG(ARLAN_DEBUG_INTERRUPT)
+			printk(KERN_ERR "%s:  got IRQ rx %x tx %x comm %x rxOff %x rxLen %x \n",
+					dev->name, rxStatus, txStatus, READSHMB(arlan->commandByte),
+					rxOffset, pkt_len);
+
+		if (rxStatus == 0 && txStatus == 0)
+		{
+			priv->last_command_was_rx = 0;
+			if (priv->irq_test_done)
+			{
+				if (!registrationBad(dev))
+					IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_ERR "%s unknown interrupt(nop? regLost ?) reason tx %d rx %d ",
+										    dev->name, txStatus, rxStatus);
+			} else {
+				IFDEBUG(ARLAN_DEBUG_INTERRUPT)
+					printk(KERN_INFO "%s irq $%d test OK \n", dev->name, dev->irq);
+
+			}
+			priv->interrupt_ack_requested = 0;
+			goto ends;
+		}
+		if (txStatus != 0)
+		{
+			WRITESHMB(arlan->txStatus, 0x00);
+			arlan_tx_done_interrupt(dev, txStatus);
+			goto ends;
+		}
+		if (rxStatus == 1 || rxStatus == 2)
+		{		/* a packet waiting */
+			arlan_rx_interrupt(dev, rxStatus, rxOffset, pkt_len);
+			goto ends;
+		}
+		if (rxStatus > 2 && rxStatus < 0xff)
+		{
+			priv->last_command_was_rx = 0;
+			WRITESHMB(arlan->rxStatus, 0x00);
+			printk(KERN_ERR "%s unknown rxStatus reason tx %d rx %d ",
+				dev->name, txStatus, rxStatus);
+			goto ends;
+		}
+		if (rxStatus == 0xff)
+		{
+			priv->last_command_was_rx = 0;
+			WRITESHMB(arlan->rxStatus, 0x00);
+			arlan_command(dev, ARLAN_COMMAND_RX);
+			if (registrationBad(dev))
+				dev->start = 0;
+			if (!registrationBad(dev))
+			{
+				priv->registrationLastSeen = jiffies;
+				if (!dev->tbusy && !priv->under_reset && !priv->under_config)
+				{
+					mark_bh(NET_BH);
+					dev->start = 1;
+				}
+			}
+			goto ends;
+		}
+ends:
+
+		arlan_command_process(dev);
+
+		rxStatus = READSHMB(arlan->rxStatus);
+		txStatus = READSHMB(arlan->txStatus);
+		rxOffset = READSHMS(arlan->rxOffset);
+		pkt_len = READSHMS(arlan->rxLength);
+
+
+		priv->irq_test_done = 1;
+
+		interrupt_count++;
+	}
+	priv->interrupt_processing_active = 0;
+
+end_int_process:
+	arlan_command_process(dev);
+
+	ARLAN_DEBUG_EXIT("arlan_process_interrupt");
+	return;
+}
+
+static void arlan_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = dev_id;
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	volatile struct arlan_shmem *arlan = priv->card;
+	u_char rxStatus = READSHMB(arlan->rxStatus);
+	u_char txStatus = READSHMB(arlan->txStatus);
+
+	ARLAN_DEBUG_ENTRY("arlan_interrupt");
+
+
+	if (!rxStatus && !txStatus)
+		priv->interrupt_ack_requested++;
+	dev->interrupt++;
+
+	arlan_process_interrupt(dev);
+	
+	priv->irq_test_done = 1;
+	dev->interrupt--;
+
+	ARLAN_DEBUG_EXIT("arlan_interrupt");
+	return;
+
+}
+
+
+static int arlan_close(struct device *dev)
+{
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+
+	if (!dev)
+	{
+		printk(KERN_CRIT "arlan: No Device\n");
+		return 0;
+	}
+	priv = (struct arlan_private *) dev->priv;
+	if (!priv)
+	{
+		printk(KERN_CRIT "arlan: No Device priv \n");
+		return 0;
+	}
+	ARLAN_DEBUG_ENTRY("arlan_close");
+
+	IFDEBUG(ARLAN_DEBUG_STARTUP)
+		printk(KERN_NOTICE "%s: Closing device\n", dev->name);
+
+	priv->open_time = 0;
+	dev->tbusy = 1;
+	dev->start = 0;
+	del_timer(&priv->timer);
+	free_irq(dev->irq, dev);
+
+	MOD_DEC_USE_COUNT;
+
+	ARLAN_DEBUG_EXIT("arlan_close");
+	return 0;
+}
+
+
+static long alignLong(volatile u_char * ptr)
+{
+	long ret;
+	memcpy_fromio(&ret, (void *) ptr, 4);
+	return ret;
+}
+
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+
+static struct enet_statistics *arlan_statistics(struct device *dev)
+{
+	struct arlan_private *priv = (struct arlan_private *) dev->priv;
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+
+
+	ARLAN_DEBUG_ENTRY("arlan_statistics");
+
+	/* Update the statistics from the device registers. */
+
+	READSHM(priv->stats.collisions, arlan->numReTransmissions, u_int);
+	READSHM(priv->stats.rx_crc_errors, arlan->numCRCErrors, u_int);
+	READSHM(priv->stats.rx_dropped, arlan->numFramesDiscarded, u_int);
+	READSHM(priv->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int);
+	READSHM(priv->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int);
+	READSHM(priv->stats.rx_over_errors, arlan->numRXOverruns, u_int);
+	READSHM(priv->stats.rx_packets, arlan->numDatagramsReceived, u_int);
+	READSHM(priv->stats.tx_aborted_errors, arlan->numAbortErrors, u_int);
+	READSHM(priv->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int);
+	READSHM(priv->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int);
+	READSHM(priv->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int);
+	READSHM(priv->stats.tx_packets, arlan->numDatagramsTransmitted, u_int);
+	READSHM(priv->stats.tx_window_errors, arlan->numHoldOffs, u_int);
+
+	ARLAN_DEBUG_EXIT("arlan_statistics");
+
+	return &priv->stats;
+}
+
+
+static void arlan_set_multicast(struct device *dev)
+{
+	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
+	struct arlan_conf_stru *conf = ((struct arlan_private *) dev->priv)->Conf;
+	int board_conf_needed = 0;
+
+
+	ARLAN_DEBUG_ENTRY("arlan_set_multicast");
+
+	if (dev->flags & IFF_PROMISC)
+	{
+		unsigned char recMode;
+		READSHM(recMode, arlan->receiveMode, u_char);
+		conf->receiveMode = (ARLAN_RCV_PROMISC | ARLAN_RCV_CONTROL);
+		if (conf->receiveMode != recMode)
+			board_conf_needed = 1;
+	}
+	else
+	{
+		/* turn off promiscuous mode  */
+		unsigned char recMode;
+		READSHM(recMode, arlan->receiveMode, u_char);
+		conf->receiveMode = ARLAN_RCV_CLEAN | ARLAN_RCV_CONTROL;
+		if (conf->receiveMode != recMode)
+			board_conf_needed = 1;
+	}
+	if (board_conf_needed)
+		arlan_command(dev, ARLAN_COMMAND_CONF);
+
+	ARLAN_DEBUG_EXIT("arlan_set_multicast");
+}
+
+
+__initfunctio(int arlan_probe(struct device *dev))
+{
+	printk("Arlan driver %s\n", arlan_version);
+
+	if (arlan_probe_everywhere(dev))
+		return ENODEV;
+
+	arlans_found++;
+
+	if (arlans_found == 1)
+		siteName = kmalloc(100, GFP_KERNEL);
+	return 0;
+}
+
+#ifdef  MODULE
+
+int init_module(void)
+{
+	int i = 0;
+
+	ARLAN_DEBUG_ENTRY("init_module");
+
+	if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN)
+	{
+		printk(KERN_WARNING "arlan: wrong module params for multiple devices\n ");
+		return -1;
+	}
+	numDevices = arlan_find_devices();
+	if (numDevices == 0)
+	{
+		printk(KERN_ERR "arlan: no devices found \n");
+		return -1;
+	}
+
+	siteName = kmalloc(100, GFP_KERNEL);
+	if(siteName==NULL)
+	{
+		printk(KERN_ERR "arlan: No memory for site name.\n");
+		return -1;
+	}
+	for (i = 0; i < numDevices && i < MAX_ARLANS; i++)
+	{
+		if (!arlan_allocate_device(i, NULL))
+			return -1;
+		if (arlan_device[i] == NULL)
+		{
+			printk(KERN_CRIT "arlan: Not Enough memory \n");
+			return -1;
+		}
+		if (probe)
+			arlan_probe_everywhere(arlan_device[i]);
+	}
+	printk(KERN_INFO "Arlan driver %s\n", arlan_version);
+	ARLAN_DEBUG_EXIT("init_module");
+	return 0;
+}
+
+
+void cleanup_module(void)
+{
+	int i = 0;
+
+	ARLAN_DEBUG_ENTRY("cleanup_module");
+
+	IFDEBUG(ARLAN_DEBUG_SHUTDOWN)
+		printk(KERN_INFO "arlan: unloading module\n");
+	for (i = 0; i < MAX_ARLANS; i++)
+	{
+		if (arlan_device[i])
+		{
+			unregister_netdev(arlan_device[i]);
+			if (arlan_device[i]->priv)
+			{
+				if (((struct arlan_private *) arlan_device[i]->priv)->conf)
+					kfree(((struct arlan_private *) arlan_device[i]->priv)->conf);
+				kfree(arlan_device[i]);
+			}
+			arlan_device[i] = NULL;
+		}
+	}
+	ARLAN_DEBUG_EXIT("cleanup_module");
+}
+
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/arlan.h linux.pre11.3/drivers/net/arlan.h
--- linux.vanilla/drivers/net/arlan.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/arlan.h	Tue Jul 20 02:02:45 1999
@@ -0,0 +1,574 @@
+/*
+ *  Copyright (C) 1997 Cullen Jennings
+ *  Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500	
+ *  Gnu Public License applies
+ */
+#include <linux/version.h>
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/if_ether.h>	/* For the statistics structure. */
+#include <linux/if_arp.h>	/* For ARPHRD_ETHER */
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+
+#include <linux/init.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+
+#define DEBUG 1
+
+#define ARLAN_PROC_INTERFACE
+#define MAX_ARLANS 4 /* not more than 4 ! */
+#define ARLAN_PROC_SHM_DUMP /* shows all card registers, makes driver way larger */
+
+#define ARLAN_MAX_MULTICAST_ADDRS 16
+#define ARLAN_RCV_CLEAN 	0
+#define ARLAN_RCV_PROMISC 1
+#define ARLAN_RCV_CONTROL 2
+
+
+#ifdef CONFIG_PROC_FS
+extern int 	init_arlan_proc(void);
+#endif
+
+extern struct device *arlan_device[MAX_ARLANS];
+static int	arlan_debug;
+static char *	siteName;
+static int	arlan_entry_debug;
+static int	arlan_exit_debug;
+static int	arlan_entry_and_exit_debug;
+static int	testMemory;
+static const char* arlan_version;
+ 
+#define SIDUNKNOWN -1
+#define radioNodeIdUNKNOWN -1
+#define encryptionKeyUNKNOWN '\0';
+#define irqUNKNOWN 0
+#define memUNKNOWN 0
+#define debugUNKNOWN 0
+#define probeUNKNOWN 1
+#define numDevicesUNKNOWN 1
+#define testMemoryUNKNOWN 1
+#define spreadingCodeUNKNOWN 0
+#define channelNumberUNKNOWN 0
+#define channelSetUNKNOWN 0
+#define systemIdUNKNOWN -1
+#define registrationModeUNKNOWN -1
+#define siteNameUNKNOWN "LinuxSite"
+
+
+
+#define IFDEBUG( L ) if ( (L) & arlan_debug ) 
+#define ARLAN_FAKE_HDR_LEN 12 
+
+#ifdef DEBUG
+	#define ARLAN_ENTRY_EXIT_DEBUGING 1
+	#define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
+#else
+	#define ARLAN_DEBUG(a,b) 
+#endif
+
+struct arlan_shmem
+{
+      /* Header Signature */ 
+      volatile	char textRegion[48];
+      volatile	u_char resetFlag;
+      volatile	u_char  diagnosticInfo;
+      volatile	u_short diagnosticOffset;
+      volatile	u_char _1[12];
+      volatile	u_char lanCardNodeId[6];
+      volatile	u_char broadcastAddress[6];
+      volatile	u_char hardwareType;
+      volatile	u_char majorHardwareVersion;
+      volatile	u_char minorHardwareVersion;
+      volatile	u_char radioModule;// shows EEPROM, can be overridden at 0x111
+      volatile	u_char defaultChannelSet; // shows EEProm, can be overriiden at 0x10A
+      volatile	u_char _2[47];
+      
+      /* Control/Status Block - 0x0080 */
+      volatile	u_char interruptInProgress; /* not used by lancpu */
+      volatile	u_char cntrlRegImage; /* not used by lancpu */
+      volatile	u_char _3[13];
+      volatile	u_char dumpByte;
+      volatile	u_char commandByte; /* non-zero = active */
+      volatile	u_char commandParameter[15];
+
+      /* Receive Status - 0x00a0 */
+      volatile	u_char rxStatus; /* 1- data, 2-control, 0xff - registr change */
+      volatile	u_char rxFrmType;
+      volatile	u_short rxOffset;
+      volatile	u_short rxLength;
+      volatile	u_char rxSrc[6];
+      volatile	u_char rxBroadcastFlag;
+      volatile	u_char rxQuality;
+      volatile	u_char scrambled;
+      volatile	u_char _4[1];
+      
+      /* Transmit Status - 0x00b0 */
+      volatile	u_char txStatus;
+      volatile	u_char txAckQuality;
+      volatile	u_char numRetries;
+      volatile	u_char _5[14];
+      volatile	u_char registeredRouter[6];
+      volatile	u_char backboneRouter[6];
+      volatile	u_char registrationStatus;
+      volatile	u_char configuredStatusFlag;
+      volatile	u_char _6[1];
+      volatile	u_char ultimateDestAddress[6];
+      volatile	u_char immedDestAddress[6];
+      volatile	u_char immedSrcAddress[6];
+      volatile	u_short rxSequenceNumber;
+      volatile	u_char assignedLocaltalkAddress;
+      volatile	u_char _7[27];
+
+      /* System Parameter Block */
+
+      /* - Driver Parameters (Novell Specific) */
+
+      volatile	u_short txTimeout;
+      volatile	u_short transportTime;
+      volatile	u_char _8[4];
+
+      /* - Configuration Parameters */
+      volatile	u_char irqLevel;
+      volatile	u_char spreadingCode;
+      volatile	u_char channelSet;
+      volatile	u_char channelNumber;
+      volatile	u_short radioNodeId;
+      volatile	u_char _9[2];
+      volatile	u_char scramblingDisable;
+      volatile	u_char radioType;
+      volatile	u_short routerId;
+      volatile	u_char _10[9];
+      volatile	u_char txAttenuation;
+      volatile	u_char systemId[4]; 
+      volatile	u_short globalChecksum;
+      volatile	u_char _11[4];
+      volatile	u_short maxDatagramSize;
+      volatile	u_short maxFrameSize;
+      volatile	u_char maxRetries;
+      volatile	u_char receiveMode;
+      volatile	u_char priority;
+      volatile	u_char rootOrRepeater;
+      volatile	u_char specifiedRouter[6];
+      volatile	u_short fastPollPeriod;
+      volatile	u_char pollDecay;
+      volatile	u_char fastPollDelay[2];
+      volatile	u_char arlThreshold;
+      volatile	u_char arlDecay;
+      volatile	u_char _12[1];
+      volatile	u_short specRouterTimeout;
+      volatile	u_char _13[5];
+
+      /* Scrambled Area */
+      volatile	u_char SID[4];
+      volatile	u_char encryptionKey[12];
+      volatile	u_char _14[2];
+      volatile	u_char waitTime[2];
+      volatile	u_char lParameter[2];
+      volatile	u_char _15[3];
+      volatile	u_short headerSize;
+      volatile	u_short sectionChecksum;
+
+      volatile	u_char registrationMode;
+      volatile	u_char registrationFill;
+      volatile	u_short pollPeriod;
+      volatile	u_short refreshPeriod;
+      volatile	u_char name[16];
+      volatile	u_char NID[6];
+      volatile	u_char localTalkAddress;
+      volatile	u_char codeFormat;
+      volatile	u_char numChannels;
+      volatile	u_char channel1;
+      volatile	u_char channel2;
+      volatile	u_char channel3;
+      volatile	u_char channel4;
+      volatile	u_char SSCode[59];
+
+      volatile	u_char _16[0xC0];
+      volatile	u_short auxCmd;
+      volatile	u_char  dumpPtr[4];
+      volatile	u_char dumpVal;
+      volatile	u_char _17[0x6A];
+      volatile	u_char wireTest;
+      volatile	u_char _18[14];
+
+      /* Statistics Block - 0x0300 */
+      volatile	u_char hostcpuLock;
+      volatile	u_char lancpuLock;
+      volatile	u_char resetTime[18];
+      
+      volatile	u_char numDatagramsTransmitted[4];
+      volatile	u_char numReTransmissions[4];
+      volatile	u_char numFramesDiscarded[4];
+      volatile	u_char numDatagramsReceived[4];
+      volatile	u_char numDuplicateReceivedFrames[4];
+      volatile	u_char numDatagramsDiscarded[4];
+      
+      volatile	u_short maxNumReTransmitDatagram;
+      volatile	u_short maxNumReTransmitFrames;
+      volatile	u_short maxNumConsecutiveDuplicateFrames;
+      /* misaligned here so we have to go to characters */
+     
+      volatile	u_char numBytesTransmitted[4];
+      volatile	u_char numBytesReceived[4];
+      volatile	u_char numCRCErrors[4];
+      volatile	u_char numLengthErrors[4];
+      volatile	u_char numAbortErrors[4];
+      volatile	u_char numTXUnderruns[4];
+      volatile	u_char numRXOverruns[4];
+      volatile	u_char numHoldOffs[4];
+      volatile	u_char numFramesTransmitted[4];
+      volatile	u_char numFramesReceived[4];
+      volatile	u_char numReceiveFramesLost[4];
+      volatile	u_char numRXBufferOverflows[4];
+      volatile	u_char numFramesDiscardedAddrMismatch[4];
+      volatile	u_char numFramesDiscardedSIDMismatch[4];
+      volatile	u_char numPollsTransmistted[4];
+      volatile	u_char numPollAcknowledges[4];
+      volatile	u_char numStatusTimeouts[4];
+      volatile	u_char numNACKReceived[4];
+
+      volatile	u_char _19[0x86];
+
+      volatile	u_char txBuffer[0x800];
+      volatile	u_char rxBuffer[0x800];
+
+      volatile	u_char _20[0x800];
+      volatile	u_char _21[0x3fb];
+      volatile	u_char configStatus;
+      volatile	u_char _22;
+      volatile	u_char progIOCtrl;
+      volatile	u_char shareMBase;
+      volatile	u_char controlRegister;
+};
+
+struct arlan_conf_stru {
+      int spreadingCode;
+      int channelSet;
+      int channelNumber;
+      int scramblingDisable;
+      int txAttenuation;
+      int systemId; 
+      int maxDatagramSize;
+      int maxFrameSize;
+      int maxRetries;
+      int receiveMode;
+      int priority;
+      int rootOrRepeater;
+      int SID;
+      int radioNodeId;
+      int registrationMode;
+      int registrationFill;
+      int localTalkAddress;
+      int codeFormat;
+      int numChannels;
+      int channel1;
+      int channel2;
+      int channel3;
+      int channel4;
+      int txClear;
+      int txRetries;
+      int txRouting;
+      int txScrambled;
+      int rxParameter;
+      int txTimeoutMs;
+      int txAckTimeoutMs;
+      int waitCardTimeout;
+      int	waitTime;
+      int	lParameter;
+      int	_15;
+      int	headerSize;
+      int async;
+      int retries;
+      int tx_delay_ms;
+      int waitReTransmitPacketMaxSize;
+      int ReTransmitPacketMaxSize;
+      int fastReTransCount;
+      int driverRetransmissions;
+      int registrationInterrupts;
+      int hardwareType;
+      int radioType;
+      int writeRadioType;
+      int writeEEPROM;
+      char siteName[17];
+      int measure_rate;
+      int in_speed;
+      int out_speed;
+      int in_speed10;
+      int out_speed10;
+      int in_speed_max;
+      int out_speed_max;
+      int pre_Command_Wait;
+      int rx_tweak1;
+      int rx_tweak2;
+      int tx_queue_len;
+};
+
+struct arlan_conf_stru arlan_conf[MAX_ARLANS];
+
+struct TxParam
+{
+      volatile	short 		offset;
+      volatile 	short 		length;
+      volatile	u_char 		dest[6];
+      volatile	unsigned	char clear;
+      volatile	unsigned	char retries;
+      volatile	unsigned	char routing;
+      volatile	unsigned	char scrambled;
+};
+
+struct TxRingPoint  {
+	struct TxParam txParam;
+	
+	
+};
+
+#define TX_RING_SIZE 2
+/* Information that need to be kept for each board. */
+struct arlan_private {
+      struct enet_statistics stats;
+      long open_time;			/* Useless example local info. */
+      struct arlan_shmem * card;
+      struct arlan_shmem * conf;
+      struct TxParam txParam;      
+      int multicastLength;
+      char  multicastList[ARLAN_MAX_MULTICAST_ADDRS][6];
+      int promiscModeEnabled;
+      struct arlan_conf_stru * Conf;	     
+      int	bad;
+      int 	reset;
+      long long lastReset;
+      struct timer_list timer;
+      struct timer_list tx_delay_timer;
+      struct timer_list tx_retry_timer;
+      struct timer_list rx_check_timer;
+      struct semaphore card_lock;
+      atomic_t 	card_users;
+      atomic_t	delay_on;
+      atomic_t  retr_on;
+      int registrationLostCount;
+      int reRegisterExp;
+      int nof_tx;
+      int nof_tx_ack;
+      int last_nof_tx;
+      int last_nof_tx_ack;
+      int irq_test_done;
+      int last_command_was_rx;
+      struct TxParam txRing[TX_RING_SIZE];
+      char reTransmitBuff[0x800];
+      volatile int txLast;
+      volatile int txNew;
+      volatile int txOffset;
+      volatile char ReTransmitRequested;
+      volatile long long tx_done_delayed;
+      volatile long long registrationLastSeen;
+      volatile char under_command;
+      volatile char under_toggle;
+      volatile long long tx_last_sent;
+      volatile long long tx_last_cleared;
+      volatile u_char under_tx;
+      volatile int 	retransmissions;
+      volatile int	tx_chain_active;
+      volatile int 	timer_chain_active;
+      volatile int 	interrupt_ack_requested;
+      volatile int	command_lock;
+      volatile int	rx_command_needed;
+      volatile int	tx_command_needed;
+      volatile int 	waiting_command_mask;
+      volatile int 	card_polling_interval;
+      volatile int 	last_command_buff_free_time;
+      volatile int	numResets;
+      volatile int 	under_reset;
+      volatile int 	under_config;
+      volatile int 	rx_command_given;
+      volatile int 	tx_command_given;
+      volatile int	interrupt_processing_active;
+      volatile long long 	last_tx_time;
+      volatile long long	last_rx_time;
+      volatile long long	last_rx_int_ack_time;
+      int	in_bytes;
+      int	out_bytes;
+      int	in_time;
+      int	out_time;
+      int	in_time10;
+      int	out_time10;
+      int	in_bytes10;
+      int	out_bytes10;
+};
+
+
+
+#define ARLAN_CLEAR		0x00
+#define ARLAN_RESET 		0x01
+#define ARLAN_CHANNEL_ATTENTION 0x02
+#define ARLAN_INTERRUPT_ENABLE 	0x04
+#define ARLAN_CLEAR_INTERRUPT 	0x08
+#define ARLAN_POWER 		0x40
+#define ARLAN_ACCESS		0x80
+
+#define ARLAN_COM_CONF                0x01
+#define ARLAN_COM_RX_ENABLE           0x03
+#define ARLAN_COM_RX_ABORT            0x04
+#define ARLAN_COM_TX_ENABLE           0x05
+#define ARLAN_COM_TX_ABORT            0x06
+#define ARLAN_COM_NOP		      0x07
+#define ARLAN_COM_STANDBY             0x08
+#define ARLAN_COM_ACTIVATE            0x09
+#define ARLAN_COM_GOTO_SLOW_POLL      0x0a
+#define ARLAN_COM_INT                 0x80
+
+
+#define TXLAST(dev) (((struct arlan_private *)dev->priv)->txRing[((struct arlan_private *)dev->priv)->txLast])
+#define TXHEAD(dev) (((struct arlan_private *)dev->priv)->txRing[0])
+#define TXTAIL(dev) (((struct arlan_private *)dev->priv)->txRing[1])
+
+#define TXBuffStart(dev) \
+ ((int)(((struct arlan_private *)dev->priv)->card)->txBuffer) - ((int)(((struct arlan_private *)dev->priv)->card) )
+#define TXBuffEnd(dev) \
+ ((int)(((struct arlan_private *)dev->priv)->card)->rxBuffer) - ((int)(((struct arlan_private *)dev->priv)->card)
+ 
+#define READSHM(to,from,atype) {\
+	atype tmp;\
+	memcpy_fromio(&(tmp),&(from),sizeof(atype));\
+	to = tmp;\
+	}
+
+#define READSHMEM(from,atype)\
+	atype from; \
+	READSHM(from, arlan->from, atype);
+
+#define WRITESHM(to,from,atype) \
+	{ atype tmpSHM = from;\
+	memcpy_toio(&(to),&tmpSHM,sizeof(atype));\
+	}
+
+#define DEBUGSHM(levelSHM,stringSHM,stuff,atype) \
+	{	atype tmpSHM; \
+		memcpy_fromio(&tmpSHM,&(stuff),sizeof(atype));\
+		IFDEBUG(levelSHM) printk(stringSHM,tmpSHM);\
+	}
+
+#define WRITESHMB(to, val) \
+	writeb(val,&(to))
+#define READSHMB(to) \
+	readb(&(to))
+#define WRITESHMS(to, val) \
+	writew(val,&(to))
+#define READSHMS(to) \
+	readw(&(to))
+#define WRITESHMI(to, val) \
+	writel(val,&(to))
+#define READSHMI(to) \
+	readl(&(to))
+
+
+
+
+
+#define registrationBad(dev)\
+   ( (   READSHMB(((struct arlan_private *)dev->priv)->card->registrationMode)    > 0) && \
+     (   READSHMB(((struct arlan_private *)dev->priv)->card->registrationStatus) == 0)    )
+
+
+#define readControlRegister(dev)\
+ 	READSHMB(((struct arlan_private *)dev->priv)->card->cntrlRegImage)
+
+#define writeControlRegister(dev, v){\
+   WRITESHMB(((struct arlan_private *)dev->priv)->card->cntrlRegImage	,((v) &0xF) );\
+   WRITESHMB(((struct arlan_private *)dev->priv)->card->controlRegister	,(v) 	);}
+
+
+#define arlan_interrupt_lancpu(dev) {\
+   int cr;   \
+   \
+   priv->under_toggle++;   \
+   cr = readControlRegister(dev);\
+   if (cr & ARLAN_CHANNEL_ATTENTION){ \
+      writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\
+   }else  \
+      writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\
+   priv->under_toggle=0;     \
+}
+
+#define clearChannelAttention(dev){ \
+   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION);}
+#define setHardwareReset(dev) {\
+   writeControlRegister(dev,readControlRegister(dev) | ARLAN_RESET);}
+#define clearHardwareReset(dev) {\
+   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_RESET);}
+#define setInterruptEnable(dev){\
+   writeControlRegister(dev,readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE)  ;}
+#define clearInterruptEnable(dev){\
+   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE)  ;}
+#define setClearInterrupt(dev){\
+   writeControlRegister(dev,readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT)   ;}
+#define clearClearInterrupt(dev){\
+   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT);}
+#define setPowerOff(dev){\
+   writeControlRegister(dev,readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
+   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
+#define setPowerOn(dev){\
+   writeControlRegister(dev,readControlRegister(dev) & ~(ARLAN_POWER));   }
+#define arlan_lock_card_access(dev){\
+   writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
+#define arlan_unlock_card_access(dev){\
+   writeControlRegister(dev,readControlRegister(dev) | ARLAN_ACCESS ); }  
+
+
+
+
+#define ARLAN_COMMAND_RX		0x00001
+#define ARLAN_COMMAND_NOOP		0x00002
+#define ARLAN_COMMAND_NOOPINT		0x00004
+#define ARLAN_COMMAND_TX		0x00008
+#define ARLAN_COMMAND_CONF		0x00010
+#define ARLAN_COMMAND_RESET		0x00020
+#define ARLAN_COMMAND_TX_ABORT		0x00040
+#define ARLAN_COMMAND_RX_ABORT		0x00080
+#define ARLAN_COMMAND_POWERDOWN		0x00100
+#define ARLAN_COMMAND_POWERUP		0x00200
+#define ARLAN_COMMAND_SLOW_POLL 	0x00400
+#define ARLAN_COMMAND_ACTIVATE 		0x00800
+#define ARLAN_COMMAND_INT_ACK		0x01000
+#define ARLAN_COMMAND_INT_ENABLE	0x02000
+#define ARLAN_COMMAND_WAIT_NOW		0x04000
+#define ARLAN_COMMAND_LONG_WAIT_NOW	0x08000
+#define ARLAN_COMMAND_STANDBY		0x10000
+#define ARLAN_COMMAND_INT_RACK		0x20000
+#define ARLAN_COMMAND_INT_RENABLE	0x40000
+#define ARLAN_COMMAND_CONF_WAIT		0x80000
+#define ARLAN_COMMAND_CLEAN_AND_CONF	(ARLAN_COMMAND_TX_ABORT\
+					| ARLAN_COMMAND_RX_ABORT\
+					| ARLAN_COMMAND_CONF)
+#define ARLAN_COMMAND_CLEAN_AND_RESET   (ARLAN_COMMAND_TX_ABORT\
+					| ARLAN_COMMAND_RX_ABORT\
+					| ARLAN_COMMAND_RESET)
+
+
+ 
+#define ARLAN_DEBUG_CHAIN_LOCKS		0x00001
+#define ARLAN_DEBUG_RESET		0x00002
+#define ARLAN_DEBUG_TIMING		0x00004
+#define ARLAN_DEBUG_CARD_STATE		0x00008
+#define ARLAN_DEBUG_TX_CHAIN		0x00010
+#define ARLAN_DEBUG_MULTICAST		0x00020
+#define ARLAN_DEBUG_HEADER_DUMP		0x00040
+#define ARLAN_DEBUG_INTERRUPT		0x00080
+#define ARLAN_DEBUG_STARTUP		0x00100
+#define ARLAN_DEBUG_SHUTDOWN		0x00200
+ 
\ No newline at end of file
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/bagetlance.c linux.pre11.3/drivers/net/bagetlance.c
--- linux.vanilla/drivers/net/bagetlance.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/bagetlance.c	Mon Jul 19 23:27:35 1999
@@ -0,0 +1,1363 @@
+/* $Id$
+ * vmelance.c: Ethernet driver for VME Lance cards on Baget/MIPS
+ *      This code stolen and adopted from linux/drivers/net/atarilance.c
+ *      See that for author info
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+
+/* 
+ * Driver code for Baget/Lance taken from atarilance.c, which also
+ * works well in case of Besta. Most significant changes made here
+ * related with 16BIT-only access to A24 space.
+ */
+
+static char *version = "bagetlance.c: v1.1 11/10/98\n";
+
+#include <linux/module.h>
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/baget/baget.h>
+
+#define BAGET_LANCE_IRQ  BAGET_IRQ_MASK(0xdf)
+
+/*
+ *  Define following if you don't need 16BIT-only access to Lance memory
+ *  (Normally BAGET needs it)
+ */
+#undef NORMAL_MEM_ACCESS 
+
+/* Debug level:
+ *  0 = silent, print only serious errors
+ *  1 = normal, print error messages
+ *  2 = debug, print debug infos
+ *  3 = debug, print even more debug infos (packet data)
+ */
+
+#define	LANCE_DEBUG	1  
+
+#ifdef LANCE_DEBUG
+static int lance_debug = LANCE_DEBUG;
+#else
+static int lance_debug = 1;
+#endif
+MODULE_PARM(lance_debug, "i");
+
+/* Print debug messages on probing? */
+#undef LANCE_DEBUG_PROBE
+
+#define	DPRINTK(n,a)							\
+	do {										\
+		if (lance_debug >= n)					\
+			printk a;							\
+	} while( 0 )
+
+#ifdef LANCE_DEBUG_PROBE
+# define PROBE_PRINT(a)	printk a
+#else
+# define PROBE_PRINT(a)
+#endif
+
+/* These define the number of Rx and Tx buffers as log2. (Only powers
+ * of two are valid)
+ * Much more rx buffers (32) are reserved than tx buffers (8), since receiving
+ * is more time critical then sending and packets may have to remain in the
+ * board's memory when main memory is low.
+ */
+
+/* Baget Lance has 64K on-board memory, so it looks we can't increase
+   buffer quantity (40*1.5K is about 64K) */
+
+#define TX_LOG_RING_SIZE			3
+#define RX_LOG_RING_SIZE			5
+
+/* These are the derived values */
+
+#define TX_RING_SIZE			(1 << TX_LOG_RING_SIZE)
+#define TX_RING_LEN_BITS		(TX_LOG_RING_SIZE << 5)
+#define	TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+
+#define RX_RING_SIZE			(1 << RX_LOG_RING_SIZE)
+#define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
+#define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+
+/* The LANCE Rx and Tx ring descriptors. */
+struct lance_rx_head {
+	volatile unsigned short	base;		/* Low word of base addr */
+#ifdef NORMAL_MEM_ACCESS
+       /* Following two fields are joined into one short to guarantee
+		  16BIT access to Baget lance registers */
+	volatile unsigned char	flag;
+	unsigned char			base_hi;	/* High word of base addr (unused) */
+#else
+/* Following macros are used as replecements to 8BIT fields */
+#define GET_FLAG(h)    (((h)->flag_base_hi >> 8) & 0xff)
+#define SET_FLAG(h,f)  (h)->flag_base_hi = ((h)->flag_base_hi & 0xff) | \
+		                                                (((unsigned)(f)) << 8)
+	volatile unsigned short flag_base_hi; 
+#endif
+	volatile short			buf_length;	/* This length is 2s complement! */
+	volatile short			msg_length;	/* This length is "normal". */
+};
+
+
+struct lance_tx_head {
+	volatile unsigned short	base;		/* Low word of base addr */
+#ifdef NORMAL_MEM_ACCESS 
+/* See comments above about 8BIT-access Baget A24-space problems */
+	volatile unsigned char	flag;
+	unsigned char			base_hi;	/* High word of base addr (unused) */
+#else
+	volatile unsigned short  flag_base_hi;
+#endif
+	volatile short			length;		/* Length is 2s complement! */
+	volatile short			misc;
+};
+
+struct ringdesc {
+	volatile unsigned short	adr_lo;		/* Low 16 bits of address */
+#ifdef NORMAL_MEM_ACCESS 
+/* See comments above about 8BIT-access Bage A24-space problems */
+	unsigned char	len;		/* Length bits */
+	unsigned char	adr_hi;		/* High 8 bits of address (unused) */
+#else
+	volatile unsigned short  len_adr_hi;
+#endif
+};
+
+/* The LANCE initialization block, described in databook. */
+struct lance_init_block {
+	unsigned short	mode;		/* Pre-set mode */
+	unsigned char	hwaddr[6];	/* Physical ethernet address */
+	unsigned		filter[2];	/* Multicast filter (unused). */
+	/* Receive and transmit ring base, along with length bits. */
+	struct ringdesc	rx_ring;
+	struct ringdesc	tx_ring;
+};
+
+/* The whole layout of the Lance shared memory */
+struct lance_memory {
+	struct lance_init_block	init;
+	struct lance_tx_head	tx_head[TX_RING_SIZE];
+	struct lance_rx_head	rx_head[RX_RING_SIZE];
+	char					packet_area[0];	/* packet data follow after the
+											 * init block and the ring
+											 * descriptors and are located
+											 * at runtime */
+};
+
+/* RieblCard specifics:
+ * The original TOS driver for these cards reserves the area from offset
+ * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the
+ * Ethernet address there, and the magic for verifying the data's validity.
+ * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe
+ * is reserved for the interrupt vector number.
+ */
+#define	RIEBL_RSVD_START	0xee70
+#define	RIEBL_RSVD_END		0xeec0
+#define RIEBL_MAGIC			0x09051990
+#define RIEBL_MAGIC_ADDR	((unsigned long *)(((char *)MEM) + 0xee8a))
+#define RIEBL_HWADDR_ADDR	((unsigned char *)(((char *)MEM) + 0xee8e))
+#define RIEBL_IVEC_ADDR		((unsigned short *)(((char *)MEM) + 0xfffe))
+
+/* This is a default address for the old RieblCards without a battery
+ * that have no ethernet address at boot time. 00:00:36:04 is the
+ * prefix for Riebl cards, the 00:00 at the end is arbitrary.
+ */
+
+static unsigned char OldRieblDefHwaddr[6] = {
+	0x00, 0x00, 0x36, 0x04, 0x00, 0x00
+};
+
+/* I/O registers of the Lance chip */
+
+struct lance_ioreg {
+/* base+0x0 */	volatile unsigned short	data;
+/* base+0x2 */	volatile unsigned short	addr;
+				unsigned char			_dummy1[3];
+/* base+0x7 */	volatile unsigned char	ivec;
+				unsigned char			_dummy2[5];
+/* base+0xd */	volatile unsigned char	eeprom;
+				unsigned char			_dummy3;
+/* base+0xf */	volatile unsigned char	mem;
+};
+
+/* Types of boards this driver supports */
+
+enum lance_type {
+	OLD_RIEBL,		/* old Riebl card without battery */
+	NEW_RIEBL,		/* new Riebl card with battery */
+	PAM_CARD		/* PAM card with EEPROM */
+};
+
+static char *lance_names[] = {
+	"Riebl-Card (without battery)",
+	"Riebl-Card (with battery)",
+	"PAM intern card"
+};
+
+/* The driver's private device structure */
+
+struct lance_private {
+	enum lance_type		cardtype;
+	struct lance_ioreg	*iobase;
+	struct lance_memory	*mem;
+	int					cur_rx, cur_tx;	/* The next free ring entry */
+	int					dirty_tx;		/* Ring entries to be freed. */
+						/* copy function */
+	void				*(*memcpy_f)( void *, const void *, size_t );
+	struct net_device_stats stats;
+/* These two must be ints for set_bit() */
+	int					tx_full;
+	int					lock;
+};
+
+/* I/O register access macros */
+
+#define	MEM		lp->mem
+#define	DREG	IO->data
+#define	AREG	IO->addr
+#define	REGA(a)	( AREG = (a), DREG )
+
+/* Definitions for packet buffer access: */
+#define PKT_BUF_SZ		1544
+/* Get the address of a packet buffer corresponding to a given buffer head */
+#define	PKTBUF_ADDR(head)	(((unsigned char *)(MEM)) + (head)->base)
+
+/* Possible memory/IO addresses for probing */
+
+struct lance_addr {
+	unsigned long	memaddr;
+	unsigned long	ioaddr;
+	int				slow_flag;
+} lance_addr_list[] = {
+	{ BAGET_LANCE_MEM_BASE, BAGET_LANCE_IO_BASE, 1 }	/* Baget Lance */
+};
+
+#define	N_LANCE_ADDR	(sizeof(lance_addr_list)/sizeof(*lance_addr_list))
+
+
+#define LANCE_HI_BASE (0xff & (BAGET_LANCE_MEM_BASE >> 16))
+
+/* Definitions for the Lance */
+
+/* tx_head flags */
+#define TMD1_ENP		0x01	/* end of packet */
+#define TMD1_STP		0x02	/* start of packet */
+#define TMD1_DEF		0x04	/* deferred */
+#define TMD1_ONE		0x08	/* one retry needed */
+#define TMD1_MORE		0x10	/* more than one retry needed */
+#define TMD1_ERR		0x40	/* error summary */
+#define TMD1_OWN 		0x80	/* ownership (set: chip owns) */
+
+#define TMD1_OWN_CHIP	TMD1_OWN
+#define TMD1_OWN_HOST	0
+
+/* tx_head misc field */
+#define TMD3_TDR		0x03FF	/* Time Domain Reflectometry counter */
+#define TMD3_RTRY		0x0400	/* failed after 16 retries */
+#define TMD3_LCAR		0x0800	/* carrier lost */
+#define TMD3_LCOL		0x1000	/* late collision */
+#define TMD3_UFLO		0x4000	/* underflow (late memory) */
+#define TMD3_BUFF		0x8000	/* buffering error (no ENP) */
+
+/* rx_head flags */
+#define RMD1_ENP		0x01	/* end of packet */
+#define RMD1_STP		0x02	/* start of packet */
+#define RMD1_BUFF		0x04	/* buffer error */
+#define RMD1_CRC		0x08	/* CRC error */
+#define RMD1_OFLO		0x10	/* overflow */
+#define RMD1_FRAM		0x20	/* framing error */
+#define RMD1_ERR		0x40	/* error summary */
+#define RMD1_OWN 		0x80	/* ownership (set: ship owns) */
+
+#define RMD1_OWN_CHIP	RMD1_OWN
+#define RMD1_OWN_HOST	0
+
+/* register names */
+#define CSR0	0		/* mode/status */
+#define CSR1	1		/* init block addr (low) */
+#define CSR2	2		/* init block addr (high) */
+#define CSR3	3		/* misc */
+#define CSR8	8	  	/* address filter */
+#define CSR15	15		/* promiscuous mode */
+
+/* CSR0 */
+/* (R=readable, W=writeable, S=set on write, C=clear on write) */
+#define CSR0_INIT	0x0001		/* initialize (RS) */
+#define CSR0_STRT	0x0002		/* start (RS) */
+#define CSR0_STOP	0x0004		/* stop (RS) */
+#define CSR0_TDMD	0x0008		/* transmit demand (RS) */
+#define CSR0_TXON	0x0010		/* transmitter on (R) */
+#define CSR0_RXON	0x0020		/* receiver on (R) */
+#define CSR0_INEA	0x0040		/* interrupt enable (RW) */
+#define CSR0_INTR	0x0080		/* interrupt active (R) */
+#define CSR0_IDON	0x0100		/* initialization done (RC) */
+#define CSR0_TINT	0x0200		/* transmitter interrupt (RC) */
+#define CSR0_RINT	0x0400		/* receiver interrupt (RC) */
+#define CSR0_MERR	0x0800		/* memory error (RC) */
+#define CSR0_MISS	0x1000		/* missed frame (RC) */
+#define CSR0_CERR	0x2000		/* carrier error (no heartbeat :-) (RC) */
+#define CSR0_BABL	0x4000		/* babble: tx-ed too many bits (RC) */
+#define CSR0_ERR	0x8000		/* error (RC) */
+
+/* CSR3 */
+#define CSR3_BCON	0x0001		/* byte control */
+#define CSR3_ACON	0 // fixme: 0x0002		/* ALE control */
+#define CSR3_BSWP	0x0004		/* byte swap (1=big endian) */
+
+
+
+/***************************** Prototypes *****************************/
+
+static int addr_accessible( volatile void *regp, int wordflag, int
+                            writeflag );
+static unsigned long lance_probe1( struct device *dev, struct lance_addr
+                                   *init_rec );
+static int lance_open( struct device *dev );
+static void lance_init_ring( struct device *dev );
+static int lance_start_xmit( struct sk_buff *skb, struct device *dev );
+static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
+static int lance_rx( struct device *dev );
+static int lance_close( struct device *dev );
+static struct net_device_stats *lance_get_stats( struct device *dev );
+static void set_multicast_list( struct device *dev );
+static int lance_set_mac_address( struct device *dev, void *addr );
+
+/************************* End of Prototypes **************************/
+
+/* Network traffic statistic (bytes) */
+
+int lance_stat = 0;
+
+static void update_lance_stat (int len) {
+		lance_stat += len;
+}
+
+/* 
+   This function is used to access Baget/Lance memory to avoid 
+   8/32BIT access to VAC A24 space 
+   ALL memcpy calls was chenged to this function to avoid dbe problems
+   Don't confuse with function name -- it stays from original code
+*/
+
+void *slow_memcpy( void *dst, const void *src, size_t len )
+
+{	
+	unsigned long to     = (unsigned long)dst;
+	unsigned long from   = (unsigned long)src;
+	unsigned long to_end = to +len;
+	
+	/* Unaligned flags */
+
+	int odd_from   = from   & 1;
+	int odd_to     = to     & 1;
+	int odd_to_end = to_end & 1;
+
+	/* Align for 16BIT-access first */
+
+	register unsigned short *from_a   = (unsigned short*) (from   & ~1);
+	register unsigned short *to_a     = (unsigned short*) (to     & ~1); 
+	register unsigned short *to_end_a = (unsigned short*) (to_end & ~1);
+
+	/* Caching values -- not in loop invariant */
+
+	register unsigned short from_v; 
+	register unsigned short to_v;
+
+	/* Invariant is: from_a and to_a are pointers before or exactly to
+	   currently copying byte */
+
+	if (odd_to) { 
+			/* First byte unaligned case */
+			from_v = *from_a;
+			to_v   = *to_a;
+
+			to_v &= ~0xff;
+			to_v |=  0xff & (from_v >> (odd_from ? 0 : 8));
+			*to_a++ = to_v;
+
+			if (odd_from) from_a++;
+	}
+    if (odd_from == odd_to) {
+			/* Same parity */
+			while (to_a + 7 < to_end_a) {
+					unsigned long dummy1, dummy2;
+					unsigned long reg1, reg2, reg3, reg4;
+
+					__asm__ __volatile__(
+					".set\tnoreorder\n\t"
+					".set\tnoat\n\t"
+					"lh\t%2,0(%1)\n\t"
+					"nop\n\t"
+					 "lh\t%3,2(%1)\n\t"
+					"sh\t%2,0(%0)\n\t"
+					   "lh\t%4,4(%1)\n\t"
+					 "sh\t%3,2(%0)\n\t"
+					    "lh\t%5,6(%1)\n\t"
+					   "sh\t%4,4(%0)\n\t"
+					"lh\t%2,8(%1)\n\t"
+					    "sh\t%5,6(%0)\n\t"
+					 "lh\t%3,10(%1)\n\t"
+					"sh\t%2,8(%0)\n\t"
+					  "lh\t%4,12(%1)\n\t"
+					 "sh\t%3,10(%0)\n\t"
+					    "lh\t%5,14(%1)\n\t"
+					  "sh\t%4,12(%0)\n\t"
+					 "nop\n\t"
+					    "sh\t%5,14(%0)\n\t"
+					".set\tat\n\t"
+					".set\treorder"
+					:"=r" (dummy1), "=r" (dummy2),
+					"=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+					:"0" (to_a), "1" (from_a)
+					:"memory");
+
+					to_a   += 8;
+					from_a += 8;
+
+			}
+			while (to_a < to_end_a) {
+					*to_a++ = *from_a++;
+			}
+	} else {
+			/* Different parity */
+			from_v = *from_a;
+			while (to_a < to_end_a) {
+					unsigned short from_v_next;
+					from_v_next = *++from_a;
+					*to_a++ = ((from_v & 0xff)<<8) | ((from_v_next>>8) & 0xff);
+					from_v = from_v_next; 
+			}
+
+	}
+	if (odd_to_end) {
+			/* Last byte unaligned case */
+			to_v = *to_a;
+			from_v = *from_a;
+
+			to_v &= ~0xff00;
+			if (odd_from == odd_to) {
+					to_v |= from_v & 0xff00;
+			} else {
+					to_v |= (from_v<<8) & 0xff00;
+			}
+
+			*to_a = to_v;
+	}
+
+	update_lance_stat( len );
+
+	return( dst );
+}
+
+
+__initfunc(int bagetlance_probe( struct device *dev ))
+
+{	int i;
+	static int found = 0;
+
+	if (found)
+		/* Assume there's only one board possible... That seems true, since
+		 * the Riebl/PAM board's address cannot be changed. */
+		return( ENODEV );
+
+	for( i = 0; i < N_LANCE_ADDR; ++i ) {
+		if (lance_probe1( dev, &lance_addr_list[i] )) {
+			found = 1;
+			return( 0 );
+		}
+	}
+
+	return( ENODEV );
+}
+
+
+
+/* Derived from hwreg_present() in vme/config.c: */
+
+__initfunc(static int addr_accessible( volatile void *regp, 
+									   int wordflag, 
+									   int writeflag ))
+{	
+		/* We have a fine function to do it */
+		extern int try_read(unsigned long, int);
+		return try_read((unsigned long)regp, sizeof(short)) != -1;   
+}
+
+
+
+/* Original atari driver uses it */
+#define IRQ_TYPE_PRIO SA_INTERRUPT
+#define IRQ_SOURCE_TO_VECTOR(x) (x)
+
+__initfunc(static unsigned long lance_probe1( struct device *dev,
+								   struct lance_addr *init_rec ))
+
+{	volatile unsigned short *memaddr =
+		(volatile unsigned short *)init_rec->memaddr;
+	volatile unsigned short *ioaddr =
+		(volatile unsigned short *)init_rec->ioaddr;
+	struct lance_private	*lp;
+	struct lance_ioreg		*IO;
+	int 					i;
+	static int 				did_version = 0;
+	unsigned short			save1, save2;
+
+	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
+				  (long)memaddr, (long)ioaddr ));
+
+	/* Test whether memory readable and writable */
+	PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));
+	if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;
+
+	if ((unsigned long)memaddr >= KSEG2) {
+			extern int kseg2_alloc_io (unsigned long addr, unsigned long size);
+			if (kseg2_alloc_io((unsigned long)memaddr, BAGET_LANCE_MEM_SIZE)) {
+					printk("bagetlance: unable map lance memory\n");
+					goto probe_fail;
+			}
+	}
+
+	/* Written values should come back... */
+	PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));
+	save1 = *memaddr;
+	*memaddr = 0x0001;
+	if (*memaddr != 0x0001) goto probe_fail;
+	PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));
+	*memaddr = 0x0000;
+	if (*memaddr != 0x0000) goto probe_fail;
+	*memaddr = save1;
+
+	/* First port should be readable and writable */
+	PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));
+	if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;
+
+	/* and written values should be readable */
+	PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));
+	save2 = ioaddr[1];
+	ioaddr[1] = 0x0001;
+	if (ioaddr[1] != 0x0001) goto probe_fail;
+
+	/* The CSR0_INIT bit should not be readable */
+	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));
+	save1 = ioaddr[0];
+	ioaddr[1] = CSR0;
+	ioaddr[0] = CSR0_INIT | CSR0_STOP;
+	if (ioaddr[0] != CSR0_STOP) {
+		ioaddr[0] = save1;
+		ioaddr[1] = save2;
+		goto probe_fail;
+	}
+	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));
+	ioaddr[0] = CSR0_STOP;
+	if (ioaddr[0] != CSR0_STOP) {
+		ioaddr[0] = save1;
+		ioaddr[1] = save2;
+		goto probe_fail;
+	}
+
+	/* Now ok... */
+	PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));
+	goto probe_ok;
+
+  probe_fail:
+	return( 0 );
+
+  probe_ok:
+	init_etherdev( dev, sizeof(struct lance_private) );
+	if (!dev->priv)
+		dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL );
+	lp = (struct lance_private *)dev->priv;
+	MEM = (struct lance_memory *)memaddr;
+	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
+	dev->base_addr = (unsigned long)ioaddr; /* informational only */
+	lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;
+
+	REGA( CSR0 ) = CSR0_STOP;
+
+	/* Now test for type: If the eeprom I/O port is readable, it is a
+	 * PAM card */
+	if (addr_accessible( &(IO->eeprom), 0, 0 )) {
+		/* Switch back to Ram */
+		i = IO->mem;
+		lp->cardtype = PAM_CARD;
+	}
+#ifdef NORMAL_MEM_ACCESS
+	else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
+#else
+	else if (({
+			unsigned short *a = (unsigned short*)RIEBL_MAGIC_ADDR;
+		    (((int)a[0]) << 16) + ((int)a[1]) == RIEBL_MAGIC;
+	})) {
+#endif
+		lp->cardtype = NEW_RIEBL;
+	}
+	else
+		lp->cardtype = OLD_RIEBL;
+
+	if (lp->cardtype == PAM_CARD ||
+		memaddr == (unsigned short *)0xffe00000) {
+		/* PAMs card and Riebl on ST use level 5 autovector */
+		request_irq(BAGET_LANCE_IRQ, lance_interrupt, IRQ_TYPE_PRIO,
+		            "PAM/Riebl-ST Ethernet", dev);
+		dev->irq = (unsigned short)BAGET_LANCE_IRQ;
+	}
+	else {
+		/* For VME-RieblCards, request a free VME int;
+		 * (This must be unsigned long, since dev->irq is short and the
+		 * IRQ_MACHSPEC bit would be cut off...)
+		 */
+		unsigned long irq = BAGET_LANCE_IRQ; 
+		if (!irq) {
+			printk( "Lance: request for VME interrupt failed\n" );
+			return( 0 );
+		}
+		request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
+		            "Riebl-VME Ethernet", dev);
+		dev->irq = irq;
+	}
+
+	printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",
+		   dev->name, lance_names[lp->cardtype],
+		   (unsigned long)ioaddr,
+		   (unsigned long)memaddr,
+		   dev->irq,
+		   init_rec->slow_flag ? " (slow memcpy)" : "" );
+
+	/* Get the ethernet address */
+	switch( lp->cardtype ) {
+	  case OLD_RIEBL:
+		/* No ethernet address! (Set some default address) */
+		slow_memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 );
+		break;
+	  case NEW_RIEBL:
+		lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 );
+		break;
+	  case PAM_CARD:
+		i = IO->eeprom;
+		for( i = 0; i < 6; ++i )
+			dev->dev_addr[i] =
+				((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
+				((((unsigned short *)MEM)[i*2+1] & 0x0f));
+		i = IO->mem;
+		break;
+	}
+	for( i = 0; i < 6; ++i )
+		printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" );
+	if (lp->cardtype == OLD_RIEBL) {
+		printk( "%s: Warning: This is a default ethernet address!\n",
+				dev->name );
+		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
+	}
+
+	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
+
+	{
+			unsigned char hwaddr[6];
+			for( i = 0; i < 6; i++ ) 
+					hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
+			slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr));
+	}
+
+	MEM->init.filter[0] = 0x00000000;
+	MEM->init.filter[1] = 0x00000000;
+	MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
+
+#ifdef NORMAL_MEM_ACCESS
+	MEM->init.rx_ring.adr_hi = LANCE_HI_BASE; 
+	MEM->init.rx_ring.len    = RX_RING_LEN_BITS;
+#else
+	MEM->init.rx_ring.len_adr_hi = 
+			((unsigned)RX_RING_LEN_BITS << 8) | LANCE_HI_BASE;
+#endif
+
+
+	MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
+
+#ifdef NORMAL_MEM_ACCESS
+	MEM->init.tx_ring.adr_hi = LANCE_HI_BASE; 
+	MEM->init.tx_ring.len    = TX_RING_LEN_BITS;
+#else
+	MEM->init.tx_ring.len_adr_hi = 
+			((unsigned)TX_RING_LEN_BITS<<8) | LANCE_HI_BASE;
+#endif
+
+	if (lp->cardtype == PAM_CARD)
+		IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);
+	else
+		*RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);
+
+	if (did_version++ == 0)
+		DPRINTK( 1, ( version ));
+
+	/* The LANCE-specific entries in the device structure. */
+	dev->open = &lance_open;
+	dev->hard_start_xmit = &lance_start_xmit;
+	dev->stop = &lance_close;
+	dev->get_stats = &lance_get_stats;
+	dev->set_multicast_list = &set_multicast_list;
+	dev->set_mac_address = &lance_set_mac_address;
+	dev->start = 0;
+
+	memset( &lp->stats, 0, sizeof(lp->stats) );
+
+	return( 1 );
+}
+
+
+static int lance_open( struct device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	struct lance_ioreg	 *IO = lp->iobase;
+	int i;
+
+	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
+
+	lance_init_ring(dev);
+	/* Re-initialize the LANCE, and start it when done. */
+
+	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+	REGA( CSR2 ) = 0;
+	REGA( CSR1 ) = 0;
+	REGA( CSR0 ) = CSR0_INIT;
+	/* From now on, AREG is kept to point to CSR0 */
+
+	i = 1000000;
+	while (--i > 0)
+		if (DREG & CSR0_IDON)
+			break;
+	if (i < 0 || (DREG & CSR0_ERR)) {
+		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
+					  dev->name, i, DREG ));
+		DREG = CSR0_STOP;
+		return( -EIO );
+	}
+	DREG = CSR0_IDON;
+	DREG = CSR0_STRT;
+	DREG = CSR0_INEA;
+
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
+	MOD_INC_USE_COUNT;
+
+	return( 0 );
+}
+
+
+/* Initialize the LANCE Rx and Tx rings. */
+
+static void lance_init_ring( struct device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	int i;
+	unsigned offset;
+
+	lp->lock = 0;
+	lp->tx_full = 0;
+	lp->cur_rx = lp->cur_tx = 0;
+	lp->dirty_tx = 0;
+
+	offset = offsetof( struct lance_memory, packet_area );
+
+/* If the packet buffer at offset 'o' would conflict with the reserved area
+ * of RieblCards, advance it */
+#define	CHECK_OFFSET(o)														 \
+	do {																	 \
+		if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) {		 \
+			if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \
+										 : (o) < RIEBL_RSVD_END)			 \
+				(o) = RIEBL_RSVD_END;										 \
+		}																	 \
+	} while(0)
+
+	for( i = 0; i < TX_RING_SIZE; i++ ) {
+		CHECK_OFFSET(offset);
+		MEM->tx_head[i].base = offset;
+#ifdef NORMAL_MEM_ACCESS
+		MEM->tx_head[i].flag = TMD1_OWN_HOST;
+ 		MEM->tx_head[i].base_hi = LANCE_HI_BASE;
+#else
+		MEM->tx_head[i].flag_base_hi = 
+				(TMD1_OWN_HOST<<8) | LANCE_HI_BASE;
+#endif
+		MEM->tx_head[i].length = 0;
+		MEM->tx_head[i].misc = 0;
+		offset += PKT_BUF_SZ;
+	}
+
+	for( i = 0; i < RX_RING_SIZE; i++ ) {
+		CHECK_OFFSET(offset);
+		MEM->rx_head[i].base = offset;
+#ifdef NORMAL_MEM_ACCESS
+		MEM->rx_head[i].flag = TMD1_OWN_CHIP;
+		MEM->rx_head[i].base_hi = LANCE_HI_BASE; 
+#else
+		MEM->rx_head[i].flag_base_hi = 
+				(TMD1_OWN_CHIP<<8) | LANCE_HI_BASE;
+#endif
+		MEM->rx_head[i].buf_length = -PKT_BUF_SZ;
+		MEM->rx_head[i].msg_length = 0;
+		offset += PKT_BUF_SZ;
+	}
+}
+
+
+static int lance_start_xmit( struct sk_buff *skb, struct device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	struct lance_ioreg	 *IO = lp->iobase;
+	int entry, len;
+	struct lance_tx_head *head;
+	unsigned long flags;
+
+	/* Transmitter timeout, serious problems. */
+	if (dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 20)
+			return( 1 );
+		AREG = CSR0;
+		DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
+					  dev->name, DREG ));
+		DREG = CSR0_STOP;
+		/*
+		 * Always set BSWP after a STOP as STOP puts it back into
+		 * little endian mode.
+		 */
+		REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+		lp->stats.tx_errors++;
+#ifndef final_version
+		{	int i;
+			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
+						  lp->dirty_tx, lp->cur_tx,
+						  lp->tx_full ? " (full)" : "",
+						  lp->cur_rx ));
+			for( i = 0 ; i < RX_RING_SIZE; i++ )
+				DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
+							  i, MEM->rx_head[i].base,
+							  -MEM->rx_head[i].buf_length,
+							  MEM->rx_head[i].msg_length ));
+			for( i = 0 ; i < TX_RING_SIZE; i++ )
+				DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",
+							  i, MEM->tx_head[i].base,
+							  -MEM->tx_head[i].length,
+							  MEM->tx_head[i].misc ));
+		}
+#endif
+		lance_init_ring(dev);
+		REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
+
+		dev->tbusy = 0;
+		dev->trans_start = jiffies;
+
+		return( 0 );
+	}
+
+	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
+				  dev->name, DREG ));
+
+	/* 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) {
+		DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name ));
+		return 1;
+	}
+
+	if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
+		DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name ));
+		/* don't clear dev->tbusy flag. */
+		return 1;
+	}
+
+	/* Fill in a Tx ring entry */
+	if (lance_debug >= 3) {
+		u_char *p;
+		int i;
+		printk( "%s: TX pkt type 0x%04x from ", dev->name,
+				((u_short *)skb->data)[6]);
+		for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ )
+			printk("%02x%s", *p++, i != 5 ? ":" : "" );
+		printk(" to ");
+		for( p = (u_char *)skb->data, i = 0; i < 6; i++ )
+			printk("%02x%s", *p++, i != 5 ? ":" : "" );
+		printk(" data at 0x%08x len %d\n", (int)skb->data,
+			   (int)skb->len );
+	}
+
+	/* We're not prepared for the int until the last flags are set/reset. And
+	 * the int may happen already after setting the OWN_CHIP... */
+	save_flags(flags);
+	cli();
+
+	/* Mask to ring buffer boundary. */
+	entry = lp->cur_tx & TX_RING_MOD_MASK;
+	head  = &(MEM->tx_head[entry]);
+
+	/* Caution: the write order is important here, set the "ownership" bits
+	 * last.
+	 */
+
+	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
+	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
+	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
+	if (lp->cardtype == PAM_CARD && (len & 1))
+		++len;
+
+	head->length = -len;
+	head->misc = 0;
+	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
+#ifdef NORMAL_MEM_ACCESS
+	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
+#else
+    SET_FLAG(head,(TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP));
+#endif
+	dev_kfree_skb( skb );
+	lp->cur_tx++;
+	lp->stats.tx_bytes += skb->len;
+	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
+		lp->cur_tx -= TX_RING_SIZE;
+		lp->dirty_tx -= TX_RING_SIZE;
+	}
+
+	/* Trigger an immediate send poll. */
+	DREG = CSR0_INEA | CSR0_TDMD;
+	dev->trans_start = jiffies;
+
+	lp->lock = 0;
+#ifdef NORMAL_MEM_ACCESS
+	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
+#else
+	if ((GET_FLAG(&MEM->tx_head[(entry+1) & TX_RING_MOD_MASK]) & TMD1_OWN) ==
+#endif
+		TMD1_OWN_HOST)
+		dev->tbusy = 0;
+	else
+		lp->tx_full = 1;
+	restore_flags(flags);
+
+	return 0;
+}
+
+/* The LANCE interrupt handler. */
+
+static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
+{
+	struct device *dev = dev_id;
+	struct lance_private *lp;
+	struct lance_ioreg	 *IO;
+	int csr0, boguscnt = 10;
+
+	if (dev == NULL) {
+		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
+		return;
+	}
+
+	lp = (struct lance_private *)dev->priv;
+	IO = lp->iobase;
+	AREG = CSR0;
+
+	if (dev->interrupt) {
+			DPRINTK( 1, ( "Re-entering CAUSE=%08x STATUS=%08x\n",  
+						  read_32bit_cp0_register(CP0_CAUSE),  
+						  read_32bit_cp0_register(CP0_STATUS) ));
+			panic("lance: interrupt handler reentered !");
+	}
+
+	dev->interrupt = 1;
+
+	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
+		   --boguscnt >= 0) {
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
+									CSR0_TDMD | CSR0_INEA);
+
+		DPRINTK( 2, ( "%s: interrupt  csr0=%04x new csr=%04x.\n",
+					  dev->name, csr0, DREG ));
+
+		if (csr0 & CSR0_RINT)			/* Rx interrupt */
+			lance_rx( dev );
+
+		if (csr0 & CSR0_TINT) {			/* Tx-done interrupt */
+			int dirty_tx = lp->dirty_tx;
+
+			while( dirty_tx < lp->cur_tx) {
+				int entry = dirty_tx & TX_RING_MOD_MASK;
+#ifdef NORMAL_MEM_ACCESS
+				int status = MEM->tx_head[entry].flag;
+#else
+				int status = GET_FLAG(&MEM->tx_head[entry]);
+#endif
+				if (status & TMD1_OWN_CHIP)
+					break;			/* It still hasn't been Txed */
+
+#ifdef NORMAL_MEM_ACCESS
+				MEM->tx_head[entry].flag = 0;
+#else
+				SET_FLAG(&MEM->tx_head[entry],0);
+#endif
+
+				if (status & TMD1_ERR) {
+					/* There was an major error, log it. */
+					int err_status = MEM->tx_head[entry].misc;
+					lp->stats.tx_errors++;
+					if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++;
+					if (err_status & TMD3_LCAR) lp->stats.tx_carrier_errors++;
+					if (err_status & TMD3_LCOL) lp->stats.tx_window_errors++;
+					if (err_status & TMD3_UFLO) {
+						/* Ackk!  On FIFO errors the Tx unit is turned off! */
+						lp->stats.tx_fifo_errors++;
+						/* Remove this verbosity later! */
+						DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n",
+									  dev->name, csr0 ));
+						/* Restart the chip. */
+						DREG = CSR0_STRT;
+					}
+				} else {
+					if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF))
+						lp->stats.collisions++;
+					lp->stats.tx_packets++;
+				}
+				dirty_tx++;
+			}
+
+#ifndef final_version
+			if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
+				DPRINTK( 0, ( "out-of-sync dirty pointer,"
+							  " %d vs. %d, full=%d.\n",
+							  dirty_tx, lp->cur_tx, lp->tx_full ));
+				dirty_tx += TX_RING_SIZE;
+			}
+#endif
+
+			if (lp->tx_full && dev->tbusy
+				&& dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+				/* The ring is no longer full, clear tbusy. */
+				lp->tx_full = 0;
+				dev->tbusy = 0;
+				mark_bh( NET_BH );
+			}
+
+			lp->dirty_tx = dirty_tx;
+		}
+
+		/* Log misc errors. */
+		if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */
+		if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */
+		if (csr0 & CSR0_MERR) {
+			DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
+						  "status %04x.\n", dev->name, csr0 ));
+			/* Restart the chip. */
+			DREG = CSR0_STRT;
+		}
+	}
+
+    /* Clear any other interrupt, and set interrupt enable. */
+	DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
+		   CSR0_IDON | CSR0_INEA;
+
+	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
+				  dev->name, DREG ));
+	dev->interrupt = 0;
+	return;
+}
+
+
+static int lance_rx( struct device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	int entry = lp->cur_rx & RX_RING_MOD_MASK;
+	int i;
+
+#ifdef NORMAL_MEM_ACCESS
+	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
+				  MEM->rx_head[entry].flag ));
+#else
+	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
+				  GET_FLAG(&MEM->rx_head[entry]) ));
+#endif
+
+	/* If we own the next entry, it's a new packet. Send it up. */
+#ifdef NORMAL_MEM_ACCESS
+	while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
+#else
+	while( (GET_FLAG(&MEM->rx_head[entry]) & RMD1_OWN) == RMD1_OWN_HOST ) {
+#endif
+		struct lance_rx_head *head = &(MEM->rx_head[entry]);
+#ifdef NORMAL_MEM_ACCESS
+		int status = head->flag;
+#else
+		int status = GET_FLAG(head);
+#endif
+
+		if (status != (RMD1_ENP|RMD1_STP)) {		/* There was an error. */
+			/* There is a tricky error noted by John Murphy,
+			   <murf@perftech.com> to Russ Nelson: Even with full-sized
+			   buffers it's possible for a jabber packet to use two
+			   buffers, with only the last correctly noting the error. */
+			if (status & RMD1_ENP)	/* Only count a general error at the */
+				lp->stats.rx_errors++; /* end of a packet.*/
+			if (status & RMD1_FRAM) lp->stats.rx_frame_errors++;
+			if (status & RMD1_OFLO) lp->stats.rx_over_errors++;
+			if (status & RMD1_CRC) lp->stats.rx_crc_errors++;
+			if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++;
+#ifdef NORMAL_MEM_ACCESS
+			head->flag &= (RMD1_ENP|RMD1_STP);
+#else
+			SET_FLAG(head,GET_FLAG(head) & (RMD1_ENP|RMD1_STP));
+#endif
+		} else {
+			/* Malloc up new buffer, compatible with net-3. */
+			short pkt_len = head->msg_length & 0xfff;
+			struct sk_buff *skb;
+
+			if (pkt_len < 60) {
+				printk( "%s: Runt packet!\n", dev->name );
+				lp->stats.rx_errors++;
+			}
+			else {
+				skb = dev_alloc_skb( pkt_len+2 );
+				if (skb == NULL) {
+					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
+								  dev->name ));
+                          for( i = 0; i < RX_RING_SIZE; i++ )
+#ifdef NORMAL_MEM_ACCESS
+                        if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
+#else
+						if (GET_FLAG(&MEM->rx_head[(entry+i) & \
+												  RX_RING_MOD_MASK]) &
+#endif
+							RMD1_OWN_CHIP)
+							break;
+
+					if (i > RX_RING_SIZE - 2) {
+						lp->stats.rx_dropped++;
+#ifdef NORMAL_MEM_ACCESS
+                        head->flag |= RMD1_OWN_CHIP;
+#else
+                        SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP);
+#endif
+						lp->cur_rx++;
+					}
+					break;
+				}
+
+				if (lance_debug >= 3) {
+					u_char *data = PKTBUF_ADDR(head), *p;
+					printk( "%s: RX pkt type 0x%04x from ", dev->name,
+							((u_short *)data)[6]);
+					for( p = &data[6], i = 0; i < 6; i++ )
+						printk("%02x%s", *p++, i != 5 ? ":" : "" );
+					printk(" to ");
+					for( p = data, i = 0; i < 6; i++ )
+						printk("%02x%s", *p++, i != 5 ? ":" : "" );
+					printk(" data %02x %02x %02x %02x %02x %02x %02x %02x "
+						   "len %d\n",
+						   data[15], data[16], data[17], data[18],
+						   data[19], data[20], data[21], data[22],
+						   pkt_len );
+				}
+
+				skb->dev = dev;
+				skb_reserve( skb, 2 );	/* 16 byte align */
+				skb_put( skb, pkt_len );	/* Make room */
+				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
+				skb->protocol = eth_type_trans( skb, dev );
+				netif_rx( skb );
+				lp->stats.rx_packets++;
+				lp->stats.rx_bytes += skb->len;
+			}
+		}
+
+#ifdef NORMAL_MEM_ACCESS
+		head->flag |= RMD1_OWN_CHIP;
+#else
+		SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP);
+#endif
+		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
+	}
+	lp->cur_rx &= RX_RING_MOD_MASK;
+
+	/* From lance.c (Donald Becker): */
+	/* We should check that at least two ring entries are free.	 If not,
+	   we should free one and mark stats->rx_dropped++. */
+
+	return 0;
+}
+
+
+static int lance_close( struct device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	struct lance_ioreg	 *IO = lp->iobase;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	AREG = CSR0;
+
+	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
+				  dev->name, DREG ));
+
+	/* We stop the LANCE here -- it occasionally polls
+	   memory if we don't. */
+	DREG = CSR0_STOP;
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+
+static struct net_device_stats *lance_get_stats( struct device *dev )
+
+{	
+	struct lance_private *lp = (struct lance_private *)dev->priv;
+	return &lp->stats;
+}
+
+
+/* Set or clear the multicast filter for this adaptor.
+   num_addrs == -1		Promiscuous mode, receive all packets
+   num_addrs == 0		Normal mode, clear multicast list
+   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
+						best-effort filtering.
+ */
+
+static void set_multicast_list( struct device *dev )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	struct lance_ioreg	 *IO = lp->iobase;
+
+	if (!dev->start)
+		/* Only possible if board is already started */
+		return;
+
+	/* We take the simple way out and always enable promiscuous mode. */
+	DREG = CSR0_STOP; /* Temporarily stop the lance. */
+
+	if (dev->flags & IFF_PROMISC) {
+		/* Log any net taps. */
+		DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name ));
+		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
+	} else {
+		short multicast_table[4];
+		int num_addrs = dev->mc_count;
+		int i;
+		/* We don't use the multicast table, but rely on upper-layer
+		 * filtering. */
+		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
+				sizeof(multicast_table) );
+		for( i = 0; i < 4; i++ )
+			REGA( CSR8+i ) = multicast_table[i];
+		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
+	}
+
+	/*
+	 * Always set BSWP after a STOP as STOP puts it back into
+	 * little endian mode.
+	 */
+	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
+
+	/* Resume normal operation and reset AREG to CSR0 */
+	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
+}
+
+
+/* This is needed for old RieblCards and possible for new RieblCards */
+
+static int lance_set_mac_address( struct device *dev, void *addr )
+
+{	struct lance_private *lp = (struct lance_private *)dev->priv;
+	struct sockaddr *saddr = addr;
+	int i;
+
+	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
+		return( -EOPNOTSUPP );
+
+	if (dev->start) {
+		/* Only possible while card isn't started */
+		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
+					  dev->name ));
+		return( -EIO );
+	}
+
+	slow_memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
+
+	{
+			unsigned char hwaddr[6];
+			for( i = 0; i < 6; i++ ) 
+					hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
+			slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr));
+	}
+
+	lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
+	/* set also the magic for future sessions */
+#ifdef NORMAL_MEM_ACCESS
+	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
+#else
+	{
+			unsigned long magic = RIEBL_MAGIC;
+			slow_memcpy(RIEBL_MAGIC_ADDR, &magic, sizeof(*RIEBL_MAGIC_ADDR));
+	}
+#endif
+	return( 0 );
+}
+
+
+#ifdef MODULE
+static char devicename[9] = { 0, };
+
+static struct device bagetlance_dev =
+{
+	devicename,	/* filled in by register_netdev() */
+	0, 0, 0, 0,	/* memory */
+	0, 0,		/* base, irq */
+	0, 0, 0, NULL, bagetlance_probe,
+};
+
+int init_module(void)
+
+{	int err;
+
+	if ((err = register_netdev( &bagetlance_dev ))) {
+		if (err == -EIO)  {
+			printk( "No Vme Lance board found. Module not loaded.\n");
+		}
+		return( err );
+	}
+	return( 0 );
+}
+
+void cleanup_module(void)
+
+{
+	unregister_netdev( &bagetlance_dev );
+}
+
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  tab-width: 4
+ * End:
+ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/com90xx.c linux.pre11.3/drivers/net/com90xx.c
--- linux.vanilla/drivers/net/com90xx.c	Sun Nov  8 15:07:30 1998
+++ linux.pre11.3/drivers/net/com90xx.c	Mon Jul 19 23:27:30 1999
@@ -399,7 +399,7 @@
 			 */
 			airqmask = probe_irq_on();
 			AINTMASK(NORXflag);
-			udelay(1);
+			mdelay(1);
 			AINTMASK(0);
 			airq = probe_irq_off(airqmask);
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/de4x5.c linux.pre11.3/drivers/net/de4x5.c
--- linux.vanilla/drivers/net/de4x5.c	Thu May 27 22:11:54 1999
+++ linux.pre11.3/drivers/net/de4x5.c	Mon Jul 19 23:59:55 1999
@@ -5559,17 +5559,15 @@
     switch(ioc->cmd) {
     case DE4X5_GET_HWADDR:           /* Get the hardware address */
 	ioc->len = ETH_ALEN;
-	if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
 	for (i=0; i<ETH_ALEN; i++) {
 	    tmp.addr[i] = dev->dev_addr[i];
 	}
-	copy_to_user(ioc->data, tmp.addr, ioc->len);
+	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
 	break;
 
     case DE4X5_SET_HWADDR:           /* Set the hardware address */
 	if (!capable(CAP_NET_ADMIN)) return -EPERM;
-	if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN)) return -EFAULT;
-	copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
+	if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) return -EFAULT;
 	for (i=0; i<ETH_ALEN; i++) {
 	    dev->dev_addr[i] = tmp.addr[i];
 	}
@@ -5612,9 +5610,8 @@
 
     case DE4X5_GET_STATS:            /* Get the driver statistics */
 	ioc->len = sizeof(lp->pktStats);
-	if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
 	spin_lock_irqsave(&lp->lock, flags);
-	copy_to_user(ioc->data, &lp->pktStats, ioc->len); 
+	if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT; 
 	spin_unlock_irqrestore(&lp->lock, flags);
 	break;
 
@@ -5627,14 +5624,12 @@
 
     case DE4X5_GET_OMR:              /* Get the OMR Register contents */
 	tmp.addr[0] = inl(DE4X5_OMR);
-	if (verify_area(VERIFY_WRITE, ioc->data, 1)) return -EFAULT;
-	copy_to_user(ioc->data, tmp.addr, 1);
+	if (copy_to_user(ioc->data, tmp.addr, 1)) return -EFAULT;
 	break;
 
     case DE4X5_SET_OMR:              /* Set the OMR Register contents */
 	if (!capable(CAP_NET_ADMIN)) return -EPERM;
-	if (verify_area(VERIFY_READ, ioc->data, 1)) return -EFAULT;
-	copy_from_user(tmp.addr, ioc->data, 1);
+	if (copy_from_user(tmp.addr, ioc->data, 1)) return -EFAULT;
 	outl(tmp.addr[0], DE4X5_OMR);
 	break;
 
@@ -5649,8 +5644,7 @@
 	tmp.lval[6] = inl(DE4X5_STRR); j+=4;
 	tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
 	ioc->len = j;
-	if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
-	copy_to_user(ioc->data, tmp.addr, ioc->len);
+	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
 	break;
 	
 #define DE4X5_DUMP              0x0f /* Dump the DE4X5 Status */
@@ -5739,8 +5733,7 @@
 	tmp.addr[j++] = dev->tbusy;
 	
 	ioc->len = j;
-	if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
-	copy_to_user(ioc->data, tmp.addr, ioc->len);
+	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
 	break;
 
 */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/declance.c linux.pre11.3/drivers/net/declance.c
--- linux.vanilla/drivers/net/declance.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/declance.c	Mon Jul 19 23:27:35 1999
@@ -0,0 +1,1259 @@
+/*     
+ *    Lance ethernet driver for the MIPS processor based
+ *      DECstation family
+ *
+ *
+ *      adopted from sunlance.c by Richard van den Berg
+ *
+ *      additional sources:
+ *      - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
+ *        Revision 1.2
+ *
+ *      History:
+ *
+ *      v0.001: The kernel accepts the code and it shows the hardware address.
+ *
+ *      v0.002: Removed most sparc stuff, left only some module and dma stuff.
+ *
+ *      v0.003: Enhanced base address calculation from proposals by
+ *      Harald Koerfgen and Thomas Riemer.
+ *
+ *      v0.004: lance-regs is pointing at the right addresses, added prom
+ *      check. First start of address mapping and DMA.
+ *
+ *      v0.005: started to play around with LANCE-DMA. This driver will not work
+ *      for non IOASIC lances. HK
+ *
+ *      v0.006: added pointer arrays to lance_private and setup routine for them
+ *      in dec_lance_init. HK
+ *
+ *      v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access
+ *      the init block. This looks like one (short) word at a time, but the smallest
+ *      amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here.
+ *      Changed lance_init_block accordingly. The 16-16 padding for the buffers
+ *      seems to be correct. HK
+ *
+ *     v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer
+ */
+
+#undef DEBUG_DRIVER
+
+static char *version =
+"declance.c: v0.008 by Linux Mips DECstation task force\n";
+
+static char *lancestr = "LANCE";
+
+/*
+ * card types
+ */
+#define ASIC_LANCE 1
+#define PMAD_LANCE 2
+#define PMAX_LANCE 3
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic_ints.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/tc.h>
+#include <asm/dec/kn01.h>
+#include <asm/addrspace.h>
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/hdreg.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/utsname.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <linux/etherdevice.h>
+
+#ifndef CONFIG_TC
+unsigned long system_base = 0;
+unsigned long dmaptr;
+#endif
+static int type;
+
+#define CRC_POLYNOMIAL_BE 0x04c11db7UL	/* Ethernet CRC, big endian */
+#define CRC_POLYNOMIAL_LE 0xedb88320UL	/* Ethernet CRC, little endian */
+
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+
+#define LE_MO_PROM      0x8000	/* Enable promiscuous mode */
+
+#define	LE_C0_ERR	0x8000	/* Error: set if BAB, SQE, MISS or ME is set */
+#define	LE_C0_BABL	0x4000	/* BAB:  Babble: tx timeout. */
+#define	LE_C0_CERR	0x2000	/* SQE:  Signal quality error */
+#define	LE_C0_MISS	0x1000	/* MISS: Missed a packet */
+#define	LE_C0_MERR	0x0800	/* ME:   Memory error */
+#define	LE_C0_RINT	0x0400	/* Received interrupt */
+#define	LE_C0_TINT	0x0200	/* Transmitter Interrupt */
+#define	LE_C0_IDON	0x0100	/* IFIN: Init finished. */
+#define	LE_C0_INTR	0x0080	/* Interrupt or error */
+#define	LE_C0_INEA	0x0040	/* Interrupt enable */
+#define	LE_C0_RXON	0x0020	/* Receiver on */
+#define	LE_C0_TXON	0x0010	/* Transmitter on */
+#define	LE_C0_TDMD	0x0008	/* Transmitter demand */
+#define	LE_C0_STOP	0x0004	/* Stop the card */
+#define	LE_C0_STRT	0x0002	/* Start the card */
+#define	LE_C0_INIT	0x0001	/* Init the card */
+
+#define	LE_C3_BSWP	0x4	/* SWAP */
+#define	LE_C3_ACON	0x2	/* ALE Control */
+#define	LE_C3_BCON	0x1	/* Byte control */
+
+/* Receive message descriptor 1 */
+#define LE_R1_OWN       0x80	/* Who owns the entry */
+#define LE_R1_ERR       0x40	/* Error: if FRA, OFL, CRC or BUF is set */
+#define LE_R1_FRA       0x20	/* FRA: Frame error */
+#define LE_R1_OFL       0x10	/* OFL: Frame overflow */
+#define LE_R1_CRC       0x08	/* CRC error */
+#define LE_R1_BUF       0x04	/* BUF: Buffer error */
+#define LE_R1_SOP       0x02	/* Start of packet */
+#define LE_R1_EOP       0x01	/* End of packet */
+#define LE_R1_POK       0x03	/* Packet is complete: SOP + EOP */
+
+#define LE_T1_OWN       0x80	/* Lance owns the packet */
+#define LE_T1_ERR       0x40	/* Error summary */
+#define LE_T1_EMORE     0x10	/* Error: more than one retry needed */
+#define LE_T1_EONE      0x08	/* Error: one retry needed */
+#define LE_T1_EDEF      0x04	/* Error: deferred */
+#define LE_T1_SOP       0x02	/* Start of packet */
+#define LE_T1_EOP       0x01	/* End of packet */
+#define LE_T1_POK	0x03	/* Packet is complete: SOP + EOP */
+
+#define LE_T3_BUF       0x8000	/* Buffer error */
+#define LE_T3_UFL       0x4000	/* Error underflow */
+#define LE_T3_LCOL      0x1000	/* Error late collision */
+#define LE_T3_CLOS      0x0800	/* Error carrier loss */
+#define LE_T3_RTY       0x0400	/* Error retry */
+#define LE_T3_TDR       0x03ff	/* Time Domain Reflectometry counter */
+
+/* Define: 2^4 Tx buffers and 2^4 Rx buffers */
+
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 4
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+
+#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+
+#define PKT_BUF_SZ		1536
+#define RX_BUFF_SIZE            PKT_BUF_SZ
+#define TX_BUFF_SIZE            PKT_BUF_SZ
+
+#undef TEST_HITS
+#define DEBUG_DRIVER 1
+
+#define ZERO 0
+
+/* The DS2000/3000 have a linear 64 KB buffer.
+
+ * The PMAD-AA has 128 kb buffer on-board. 
+ *
+ * The IOASIC LANCE devices use a shared memory region. This region as seen 
+ * from the CPU is (max) 128 KB long and has to be on an 128 KB boundary.
+ * The LANCE sees this as a 64 KB long continuous memory region.
+ *
+ * The LANCE's DMA address is used as an index in this buffer and DMA takes
+ * place in bursts of eight 16-Bit words which are packed into four 32-Bit words
+ * by the IOASIC. This leads to a strange padding: 16 bytes of valid data followed
+ * by a 16 byte gap :-(.
+ */
+
+struct lance_rx_desc {
+	unsigned short rmd0;	/* low address of packet */
+	short gap0;
+	unsigned char rmd1_hadr;	/* high address of packet */
+	unsigned char rmd1_bits;	/* descriptor bits */
+	short gap1;
+	short length;		/* This length is 2s complement (negative)!
+				   * Buffer length
+				 */
+	short gap2;
+	unsigned short mblength;	/* This is the actual number of bytes received */
+	short gap3;
+};
+
+struct lance_tx_desc {
+	unsigned short tmd0;	/* low address of packet */
+	short gap0;
+	unsigned char tmd1_hadr;	/* high address of packet */
+	unsigned char tmd1_bits;	/* descriptor bits */
+	short gap1;
+	short length;		/* Length is 2s complement (negative)! */
+	short gap2;
+	unsigned short misc;
+	short gap3;
+};
+
+
+/* First part of the LANCE initialization block, described in databook. */
+struct lance_init_block {
+	unsigned short mode;	/* Pre-set mode (reg. 15) */
+	short gap0;
+
+	unsigned char phys_addr[12];	/* Physical ethernet address
+					   * only 0, 1, 4, 5, 8, 9 are valid
+					   * 2, 3, 6, 7, 10, 11 are gaps
+					 */
+	unsigned short filter[8];	/* Multicast filter.
+					   * only 0, 2, 4, 6 are valid
+					   * 1, 3, 5, 7 are gaps
+					 */
+
+	/* Receive and transmit ring base, along with extra bits. */
+	unsigned short rx_ptr;	/* receive descriptor addr */
+	short gap1;
+	unsigned short rx_len;	/* receive len and high addr */
+	short gap2;
+	unsigned short tx_ptr;	/* transmit descriptor addr */
+	short gap3;
+	unsigned short tx_len;	/* transmit len and high addr */
+	short gap4;
+	char gap5[16];
+
+	/* The buffer descriptors */
+	struct lance_rx_desc brx_ring[RX_RING_SIZE];
+	struct lance_tx_desc btx_ring[TX_RING_SIZE];
+};
+
+#define BUF_OFFSET_CPU sizeof(struct lance_init_block)
+#define BUF_OFFSET_LNC (sizeof(struct lance_init_block)>>1)
+
+#define libdesc_offset(rt, elem) \
+((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem])))))
+
+/*
+ * This works *only* for the ring descriptors
+ */
+#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
+
+struct lance_private {
+	char *name;
+	volatile struct lance_regs *ll;
+	volatile struct lance_init_block *init_block;
+	volatile unsigned long *dma_ptr_reg;
+
+	int rx_new, tx_new;
+	int rx_old, tx_old;
+
+	struct net_device_stats stats;
+
+	unsigned short busmaster_regval;
+
+	struct device *dev;	/* Backpointer        */
+	struct lance_private *next_module;
+
+	/* Pointers to the ring buffers as seen from the CPU */
+	char *rx_buf_ptr_cpu[RX_RING_SIZE];
+	char *tx_buf_ptr_cpu[TX_RING_SIZE];
+
+	/* Pointers to the ring buffers as seen from the LANCE */
+	char *rx_buf_ptr_lnc[RX_RING_SIZE];
+	char *tx_buf_ptr_lnc[TX_RING_SIZE];
+};
+
+#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
+			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
+			lp->tx_old - lp->tx_new-1)
+
+/* The lance control ports are at an absolute address, machine and tc-slot
+ * dependant.
+ * DECstations do only 32-bit access and the LANCE uses 16 bit addresses,
+ * so we have to give the structure an extra member making rap pointing
+ * at the right address
+ */
+struct lance_regs {
+	volatile unsigned short rdp;	/* register data port */
+	unsigned short pad;
+	volatile unsigned short rap;	/* register address port */
+};
+
+int dec_lance_debug = 2;
+
+/*
+   #ifdef MODULE
+   static struct lance_private *root_lance_dev = NULL;
+   #endif
+ */
+
+static inline void writereg(volatile unsigned short *regptr, short value)
+{
+	*regptr = value;
+}
+
+/* Load the CSR registers */
+static void load_csrs(struct lance_private *lp)
+{
+	volatile struct lance_regs *ll = lp->ll;
+	int leptr;
+
+	/* The address space as seen from the LANCE
+	 * begins at address 0. HK
+	 */
+	leptr = 0;
+
+	writereg(&ll->rap, LE_CSR1);
+	writereg(&ll->rdp, (leptr & 0xFFFF));
+	writereg(&ll->rap, LE_CSR2);
+	writereg(&ll->rdp, leptr >> 16);
+	writereg(&ll->rap, LE_CSR3);
+	writereg(&ll->rdp, lp->busmaster_regval);
+
+	/* Point back to csr0 */
+	writereg(&ll->rap, LE_CSR0);
+}
+
+/*
+ * Our specialized copy routines
+ *
+ */
+void cp_to_buf(void *to, const void *from, __kernel_size_t len)
+{
+	unsigned short *tp, *fp, clen;
+	unsigned char *rtp, *rfp;
+
+	if (type == PMAX_LANCE) {
+		clen = len >> 1;
+		tp = (unsigned short *) to;
+		fp = (unsigned short *) from;
+
+		while (clen--) {
+			*tp++ = *fp++;
+			tp++;
+		}
+
+		clen = len & 1;
+		rtp = (unsigned char *) tp;
+		rfp = (unsigned char *) fp;
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+	} else {
+		/*
+		 * copy 16 Byte chunks
+		 */
+		clen = len >> 4;
+		tp = (unsigned short *) to;
+		fp = (unsigned short *) from;
+		while (clen--) {
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			tp += 8;
+		}
+
+		/*
+		 * do the rest, if any.
+		 */
+		clen = len & 15;
+		rtp = (unsigned char *) tp;
+		rfp = (unsigned char *) fp;
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+	}
+
+}
+
+void cp_from_buf(void *to, unsigned char *from, int len)
+{
+	unsigned short *tp, *fp, clen;
+	unsigned char *rtp, *rfp;
+
+	if (type == PMAX_LANCE) {
+		clen = len >> 1;
+		tp = (unsigned short *) to;
+		fp = (unsigned short *) from;
+		while (clen--) {
+			*tp++ = *fp++;
+			fp++;
+		}
+
+		clen = len & 1;
+
+		rtp = (unsigned char *) tp;
+		rfp = (unsigned char *) fp;
+
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+	} else {
+
+		/*
+		 * copy 16 Byte chunks
+		 */
+		clen = len >> 4;
+		tp = (unsigned short *) to;
+		fp = (unsigned short *) from;
+		while (clen--) {
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			*tp++ = *fp++;
+			fp += 8;
+		}
+
+		/*
+		 * do the rest, if any.
+		 */
+		clen = len & 15;
+		rtp = (unsigned char *) tp;
+		rfp = (unsigned char *) fp;
+		while (clen--) {
+			*rtp++ = *rfp++;
+		}
+
+
+	}
+
+}
+
+/* Setup the Lance Rx and Tx rings */
+/* Sets dev->tbusy */
+static void lance_init_ring(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib;
+	int leptr;
+	int i;
+
+	ib = (struct lance_init_block *) (dev->mem_start);
+
+	/* Lock out other processes while setting up hardware */
+	dev->tbusy = 1;
+	lp->rx_new = lp->tx_new = 0;
+	lp->rx_old = lp->tx_old = 0;
+
+	ib->mode = 0;
+
+	/* Copy the ethernet address to the lance init block.
+	 * XXX bit 0 of the physical address registers has to be zero
+	 */
+	ib->phys_addr[0] = dev->dev_addr[0];
+	ib->phys_addr[1] = dev->dev_addr[1];
+	ib->phys_addr[4] = dev->dev_addr[2];
+	ib->phys_addr[5] = dev->dev_addr[3];
+	ib->phys_addr[8] = dev->dev_addr[4];
+	ib->phys_addr[9] = dev->dev_addr[5];
+	/* Setup the initialization block */
+
+	/* Setup rx descriptor pointer */
+	leptr = LANCE_ADDR(libdesc_offset(brx_ring, 0));
+	ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
+	ib->rx_ptr = leptr;
+	if (ZERO)
+		printk("RX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(brx_ring, 0));
+
+	/* Setup tx descriptor pointer */
+	leptr = LANCE_ADDR(libdesc_offset(btx_ring, 0));
+	ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
+	ib->tx_ptr = leptr;
+	if (ZERO)
+		printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0));
+
+	/* Clear the multicast filter */
+	ib->filter[0] = 0;
+	ib->filter[2] = 0;
+	ib->filter[4] = 0;
+	ib->filter[6] = 0;
+	if (ZERO)
+		printk("TX rings:\n");
+
+	/* Setup the Tx ring entries */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		leptr = (int) lp->tx_buf_ptr_lnc[i];
+		ib->btx_ring[i].tmd0 = leptr;
+		ib->btx_ring[i].tmd1_hadr = leptr >> 16;
+		ib->btx_ring[i].tmd1_bits = 0;
+		ib->btx_ring[i].length = 0xf000;	/* The ones required by tmd2 */
+		ib->btx_ring[i].misc = 0;
+		if (i < 3 && ZERO)
+			printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->tx_buf_ptr_cpu[i]);
+	}
+
+	/* Setup the Rx ring entries */
+	if (ZERO)
+		printk("RX rings:\n");
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		leptr = (int) lp->rx_buf_ptr_lnc[i];
+		ib->brx_ring[i].rmd0 = leptr;
+		ib->brx_ring[i].rmd1_hadr = leptr >> 16;
+		ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
+		ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000;
+		ib->brx_ring[i].mblength = 0;
+		if (i < 3 && ZERO)
+			printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
+	}
+}
+
+static int init_restart_lance(struct lance_private *lp)
+{
+	volatile struct lance_regs *ll = lp->ll;
+	int i;
+
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_INIT);
+
+	/* Wait for the lance to complete initialization */
+	for (i = 0; (i < 100) && !(ll->rdp & LE_C0_IDON); i++) {
+		udelay(10);
+	}
+	if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
+		printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+		return -1;
+	}
+	if ((ll->rdp & LE_C0_ERR)) {
+		printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+		return -1;
+	}
+	writereg(&ll->rdp, LE_C0_IDON);
+	writereg(&ll->rdp, LE_C0_STRT);
+	writereg(&ll->rdp, LE_C0_INEA);
+
+	return 0;
+}
+
+static int lance_rx(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib;
+	volatile struct lance_rx_desc *rd = 0;
+	unsigned char bits;
+	int len = 0;
+	struct sk_buff *skb = 0;
+	ib = (struct lance_init_block *) (dev->mem_start);
+
+#ifdef TEST_HITS
+	int i;
+
+	printk("[");
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		if (i == lp->rx_new)
+			printk("%s",
+			       ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+		else
+			printk("%s",
+			       ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1");
+	}
+	printk("]");
+#endif
+
+	for (rd = &ib->brx_ring[lp->rx_new];
+	     !((bits = rd->rmd1_bits) & LE_R1_OWN);
+	     rd = &ib->brx_ring[lp->rx_new]) {
+
+		/* We got an incomplete frame? */
+		if ((bits & LE_R1_POK) != LE_R1_POK) {
+			lp->stats.rx_over_errors++;
+			lp->stats.rx_errors++;
+		} else if (bits & LE_R1_ERR) {
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
+			if (bits & LE_R1_BUF)
+				lp->stats.rx_fifo_errors++;
+			if (bits & LE_R1_CRC)
+				lp->stats.rx_crc_errors++;
+			if (bits & LE_R1_OFL)
+				lp->stats.rx_over_errors++;
+			if (bits & LE_R1_FRA)
+				lp->stats.rx_frame_errors++;
+			if (bits & LE_R1_EOP)
+				lp->stats.rx_errors++;
+		} else {
+			len = (rd->mblength & 0xfff) - 4;
+			skb = dev_alloc_skb(len + 2);
+
+			if (skb == 0) {
+				printk("%s: Memory squeeze, deferring packet.\n",
+				       dev->name);
+				lp->stats.rx_dropped++;
+				rd->mblength = 0;
+				rd->rmd1_bits = LE_R1_OWN;
+				lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+				return 0;
+			}
+			lp->stats.rx_bytes += len;
+
+			skb->dev = dev;
+			skb_reserve(skb, 2);	/* 16 byte align */
+			skb_put(skb, len);	/* make room */
+			cp_from_buf(skb->data,
+				 (char *) lp->rx_buf_ptr_cpu[lp->rx_new],
+				    len);
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			lp->stats.rx_packets++;
+		}
+
+		/* Return the packet to the pool */
+		rd->mblength = 0;
+		rd->length = -RX_BUFF_SIZE | 0xf000;
+		rd->rmd1_bits = LE_R1_OWN;
+		lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+	}
+	return 0;
+}
+
+static int lance_tx(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib;
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_tx_desc *td;
+	int i, j;
+	int status;
+	ib = (struct lance_init_block *) (dev->mem_start);
+	j = lp->tx_old;
+
+	for (i = j; i != lp->tx_new; i = j) {
+		td = &ib->btx_ring[i];
+		/* If we hit a packet not owned by us, stop */
+		if (td->tmd1_bits & LE_T1_OWN)
+			break;
+
+		if (td->tmd1_bits & LE_T1_ERR) {
+			status = td->misc;
+
+			lp->stats.tx_errors++;
+			if (status & LE_T3_RTY)
+				lp->stats.tx_aborted_errors++;
+			if (status & LE_T3_LCOL)
+				lp->stats.tx_window_errors++;
+
+			if (status & LE_T3_CLOS) {
+				lp->stats.tx_carrier_errors++;
+				printk("%s: Carrier Lost", dev->name);
+				/* Stop the lance */
+				writereg(&ll->rap, LE_CSR0);
+				writereg(&ll->rdp, LE_C0_STOP);
+				lance_init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				return 0;
+			}
+			/* Buffer errors and underflows turn off the
+			 * transmitter, restart the adapter.
+			 */
+			if (status & (LE_T3_BUF | LE_T3_UFL)) {
+				lp->stats.tx_fifo_errors++;
+
+				printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
+				       dev->name);
+				/* Stop the lance */
+				writereg(&ll->rap, LE_CSR0);
+				writereg(&ll->rdp, LE_C0_STOP);
+				lance_init_ring(dev);
+				load_csrs(lp);
+				init_restart_lance(lp);
+				return 0;
+			}
+		} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
+			/*
+			 * So we don't count the packet more than once.
+			 */
+			td->tmd1_bits &= ~(LE_T1_POK);
+
+			/* One collision before packet was sent. */
+			if (td->tmd1_bits & LE_T1_EONE)
+				lp->stats.collisions++;
+
+			/* More than one collision, be optimistic. */
+			if (td->tmd1_bits & LE_T1_EMORE)
+				lp->stats.collisions += 2;
+
+			lp->stats.tx_packets++;
+		}
+		j = (j + 1) & TX_RING_MOD_MASK;
+	}
+	lp->tx_old = j;
+	return 0;
+}
+
+static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev = (struct device *) dev_id;
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_regs *ll = lp->ll;
+	int csr0;
+
+	if (dev->interrupt)
+		printk("%s: again\n", dev->name);
+
+	dev->interrupt = 1;
+
+	writereg(&ll->rap, LE_CSR0);
+	csr0 = ll->rdp;
+
+	/* Acknowledge all the interrupt sources ASAP */
+	writereg(&ll->rdp, csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT));
+
+	if ((csr0 & LE_C0_ERR)) {
+		/* Clear the error condition */
+		writereg(&ll->rdp, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
+			 LE_C0_CERR | LE_C0_MERR);
+	}
+	if (csr0 & LE_C0_RINT)
+		lance_rx(dev);
+
+	if (csr0 & LE_C0_TINT)
+		lance_tx(dev);
+
+	if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
+	}
+	if (csr0 & LE_C0_BABL)
+		lp->stats.tx_errors++;
+
+	if (csr0 & LE_C0_MISS)
+		lp->stats.rx_errors++;
+
+	if (csr0 & LE_C0_MERR) {
+		volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR);
+
+		printk("%s: Memory error, status %04x", dev->name, csr0);
+
+		if (int_stat & LANCE_DMA_MEMRDERR) {
+			printk("%s: DMA error\n", dev->name);
+			int_stat |= LANCE_DMA_MEMRDERR;
+			/*
+			 * re-enable LANCE DMA
+			 */
+			*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
+		}
+		writereg(&ll->rdp, LE_C0_STOP);
+
+		lance_init_ring(dev);
+		load_csrs(lp);
+		init_restart_lance(lp);
+		dev->tbusy = 0;
+	}
+	writereg(&ll->rdp, LE_C0_INEA);
+	writereg(&ll->rdp, LE_C0_INEA);
+	dev->interrupt = 0;
+}
+
+struct device *last_dev = 0;
+
+static int lance_open(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_regs *ll = lp->ll;
+	int status = 0;
+
+	last_dev = dev;
+
+	/* Associate IRQ with lance_interrupt */
+	if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) {
+		printk("Lance: Can't get irq %d\n", dev->irq);
+		return -EAGAIN;
+	}
+	/* Stop the Lance */
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	lance_init_ring(dev);
+	load_csrs(lp);
+
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	status = init_restart_lance(lp);
+
+	/*
+	 * if (!status)
+	 *      MOD_INC_USE_COUNT;
+	 */
+
+	return status;
+}
+
+static int lance_close(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_regs *ll = lp->ll;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	/* Stop the card */
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	free_irq(dev->irq, (void *) dev);
+	/*
+	   MOD_DEC_USE_COUNT;
+	 */
+	return 0;
+}
+
+static inline int lance_reset(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_regs *ll = lp->ll;
+	int status;
+
+	/* Stop the lance */
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	lance_init_ring(dev);
+	load_csrs(lp);
+	dev->trans_start = jiffies;
+	dev->interrupt = 0;
+	dev->start = 1;
+	dev->tbusy = 0;
+	status = init_restart_lance(lp);
+#ifdef DEBUG_DRIVER
+	printk("Lance restart=%d\n", status);
+#endif
+	return status;
+}
+
+static int lance_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_init_block *ib;
+	unsigned long flags;
+	int entry, skblen, len;
+	int status = 0;
+	static int outs;
+	ib = (struct lance_init_block *) (dev->mem_start);
+
+	/* Transmitter timeout, serious problems */
+	if (dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+
+		if (tickssofar < 100) {
+			status = -1;
+		} else {
+			printk("%s: transmit timed out, status %04x, reset\n",
+			       dev->name, ll->rdp);
+			lance_reset(dev);
+		}
+		return status;
+	}
+	/* Block a timer-based transmit from overlapping. */
+	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
+		printk("Transmitter access conflict.\n");
+		return -1;
+	}
+	skblen = skb->len;
+	save_and_cli(flags);
+	if (!TX_BUFFS_AVAIL) {
+		restore_flags(flags);
+		return -1;
+	}
+	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+
+	lp->stats.tx_bytes += len;
+
+	entry = lp->tx_new & TX_RING_MOD_MASK;
+	ib->btx_ring[entry].length = (-len);
+	ib->btx_ring[entry].misc = 0;
+
+	cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen);
+
+	/* Clear the slack of the packet, do I need this? */
+	/* For a firewall its a good idea - AC */
+/*
+   if (len != skblen)
+   memset ((char *) &ib->tx_buf [entry][skblen], 0, (len - skblen) << 1);
+ */
+
+	/* Now, give the packet to the lance */
+	ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
+	lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK;
+
+	outs++;
+	/* Kick the lance: transmit now */
+	writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
+	dev->trans_start = jiffies;
+	dev_kfree_skb(skb);
+
+	if (TX_BUFFS_AVAIL)
+		dev->tbusy = 0;
+
+	restore_flags(flags);
+	return status;
+}
+
+static struct net_device_stats *lance_get_stats(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+
+	return &lp->stats;
+}
+
+static void lance_load_multicast(struct device *dev)
+{
+	volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
+	volatile u16 *mcast_table = (u16 *) & ib->filter;
+	struct dev_mc_list *dmi = dev->mc_list;
+	char *addrs;
+	int i, j, bit, byte;
+	u32 crc, poly = CRC_POLYNOMIAL_BE;
+
+	/* set all multicast bits */
+	if (dev->flags & IFF_ALLMULTI) {
+		ib->filter[0] = 0xffff;
+		ib->filter[2] = 0xffff;
+		ib->filter[4] = 0xffff;
+		ib->filter[6] = 0xffff;
+		return;
+	}
+	/* clear the multicast filter */
+	ib->filter[0] = 0;
+	ib->filter[2] = 0;
+	ib->filter[4] = 0;
+	ib->filter[6] = 0;
+
+	/* Add addresses */
+	for (i = 0; i < dev->mc_count; i++) {
+		addrs = dmi->dmi_addr;
+		dmi = dmi->next;
+
+		/* multicast address? */
+		if (!(*addrs & 1))
+			continue;
+
+		crc = 0xffffffff;
+		for (byte = 0; byte < 6; byte++)
+			for (bit = *addrs++, j = 0; j < 8; j++, bit >>= 1) {
+				int test;
+
+				test = ((bit ^ crc) & 0x01);
+				crc >>= 1;
+
+				if (test) {
+					crc = crc ^ poly;
+				}
+			}
+
+		crc = crc >> 26;
+		mcast_table[crc >> 3] |= 1 << (crc & 0xf);
+	}
+	return;
+}
+
+static void lance_set_multicast(struct device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_init_block *ib;
+	volatile struct lance_regs *ll = lp->ll;
+
+	ib = (struct lance_init_block *) (dev->mem_start);
+
+	while (dev->tbusy)
+		schedule();
+	set_bit(0, (void *) &dev->tbusy);
+	while (lp->tx_old != lp->tx_new)
+		schedule();
+
+	writereg(&ll->rap, LE_CSR0);
+	writereg(&ll->rdp, LE_C0_STOP);
+
+	lance_init_ring(dev);
+
+	if (dev->flags & IFF_PROMISC) {
+		ib->mode |= LE_MO_PROM;
+	} else {
+		ib->mode &= ~LE_MO_PROM;
+		lance_load_multicast(dev);
+	}
+	load_csrs(lp);
+	init_restart_lance(lp);
+	dev->tbusy = 0;
+}
+
+__initfunc(static int dec_lance_init(struct device *dev, const int type))
+{
+	static unsigned version_printed = 0;
+	struct lance_private *lp;
+	volatile struct lance_regs *ll;
+	int i;
+	unsigned long esar_base;
+	unsigned char *esar;
+
+#ifndef CONFIG_TC
+	system_base = KN01_LANCE_BASE;
+#else
+	int slot;
+#endif
+
+	if (dec_lance_debug && version_printed++ == 0)
+		printk(version);
+
+	if (dev == NULL) {
+		dev = init_etherdev(0, sizeof(struct lance_private) + 8);
+	} else {
+		dev->priv = kmalloc(sizeof(struct lance_private) + 8,
+				    GFP_KERNEL);
+		if (dev->priv == NULL)
+			return -ENOMEM;
+		memset(dev->priv, 0, sizeof(struct lance_private) + 8);
+
+	}
+
+	/* Make certain the data structures used by the LANCE are aligned. */
+	dev->priv = (void *) (((unsigned long) dev->priv + 7) & ~7);
+	lp = (struct lance_private *) dev->priv;
+
+	switch (type) {
+#ifdef CONFIG_TC
+	case ASIC_LANCE:
+		dev->base_addr = system_base + LANCE;
+
+		/* buffer space for the on-board LANCE shared memory */
+		/*
+		 * FIXME: ugly hack!
+		 */
+		dev->mem_start = KSEG1ADDR(0x0020000);
+		dev->mem_end = dev->mem_start + 0x00020000;
+		dev->irq = ETHER;
+		esar_base = system_base + ESAR;
+
+		/*
+		 * setup the pointer arrays, this sucks [tm] :-(
+		 */
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU
+						 + 2 * i * RX_BUFF_SIZE);
+			lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
+						     + i * RX_BUFF_SIZE);
+		}
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU
+					+ 2 * RX_RING_SIZE * RX_BUFF_SIZE
+						 + 2 * i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
+					    + RX_RING_SIZE * RX_BUFF_SIZE
+						     + i * TX_BUFF_SIZE);
+		}
+
+		/*
+		 * setup and enable IOASIC LANCE DMA
+		 */
+		lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P);
+		*(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3;
+		*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
+
+		break;
+	case PMAD_LANCE:
+		slot = search_tc_card("PMAD-AA");
+		claim_tc_card(slot);
+
+		dev->mem_start = get_tc_base_addr(slot);
+		dev->base_addr = dev->mem_start + 0x100000;
+		dev->irq = get_tc_irq_nr(slot);
+		esar_base = dev->mem_start + 0x1c0002;
+		break;
+#endif
+	case PMAX_LANCE:
+		dev->irq = ETHER;
+		dev->base_addr = KN01_LANCE_BASE;
+		dev->mem_start = KN01_LANCE_BASE + 0x01000000;
+		esar_base = KN01_RTC_BASE + 1;
+		/*
+		 * setup the pointer arrays, this sucks [tm] :-(
+		 */
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			lp->rx_buf_ptr_cpu[i] =
+			    (char *) (dev->mem_start + BUF_OFFSET_CPU
+				      + 2 * i * RX_BUFF_SIZE);
+
+			lp->rx_buf_ptr_lnc[i] =
+			    (char *) (BUF_OFFSET_LNC
+				      + i * RX_BUFF_SIZE);
+
+		}
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			lp->tx_buf_ptr_cpu[i] =
+			    (char *) (dev->mem_start + BUF_OFFSET_CPU
+				      + 2 * RX_RING_SIZE * RX_BUFF_SIZE
+				      + 2 * i * TX_BUFF_SIZE);
+			lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
+					    + RX_RING_SIZE * RX_BUFF_SIZE
+						     + i * TX_BUFF_SIZE);
+
+		}
+		break;
+	default:
+		printk("declance_init called with unknown type\n");
+		return -ENODEV;
+		break;
+	}
+
+	ll = (struct lance_regs *) dev->base_addr;
+	esar = (unsigned char *) esar_base;
+
+	/* prom checks */
+	/* First, check for test pattern */
+	if (esar[0x60] != 0xff && esar[0x64] != 0x00 &&
+	    esar[0x68] != 0x55 && esar[0x6c] != 0xaa) {
+		printk("Ethernet station address prom not found!\n");
+		return -ENODEV;
+	}
+	/* Check the prom contents */
+	for (i = 0; i < 8; i++) {
+		if (esar[i * 4] != esar[0x3c - i * 4] &&
+		    esar[i * 4] != esar[0x40 + i * 4] &&
+		    esar[0x3c - i * 4] != esar[0x40 + i * 4]) {
+			printk("Something is wrong with the ethernet "
+			       "station address prom!\n");
+			return -ENODEV;
+		}
+	}
+
+	/* Copy the ethernet address to the device structure, later to the
+	 * lance initialization block so the lance gets it every time it's
+	 * (re)initialized.
+	 */
+	switch (type) {
+	case ASIC_LANCE:
+		printk("%s: IOASIC onboard LANCE, addr = ", dev->name);
+		break;
+	case PMAD_LANCE:
+		printk("%s: PMAD-AA, addr = ", dev->name);
+		break;
+	case PMAX_LANCE:
+		printk("%s: PMAX onboard LANCE, addr = ", dev->name);
+		break;
+	}
+	for (i = 0; i < 6; i++) {
+		dev->dev_addr[i] = esar[i * 4];
+		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ',' : ':');
+	}
+
+	printk(" irq = %d\n", dev->irq);
+
+	/* Fill the dev fields */
+
+	dev->open = lance_open;
+	dev->stop = lance_close;
+	dev->hard_start_xmit = lance_start_xmit;
+	dev->get_stats = lance_get_stats;
+	dev->set_multicast_list = lance_set_multicast;
+	dev->dma = 0;
+
+	/* lp->ll is the location of the registers for lance card */
+	lp->ll = ll;
+
+	lp->name = lancestr;
+
+	/* busmaster_regval (CSR3) should be zero according to the PMAD-AA
+	 * specification.
+	 */
+	lp->busmaster_regval = 0;
+	lp->dev = dev;
+
+	ether_setup(dev);
+/*
+   #ifdef MODULE
+   dev->ifindex = dev_new_index();
+   lp->next_module = root_lance_dev;
+   root_lance_dev = lp;
+   #endif
+ */
+	return 0;
+}
+
+
+/* Find all the lance cards on the system and initialize them */
+__initfunc(int dec_lance_probe(struct device *dev))
+{
+	static int called = 0;
+
+#ifdef CONFIG_TC
+	int slot = -1;
+
+	if (TURBOCHANNEL) {
+		if (IOASIC && !called) {
+			called = 1;
+			type = ASIC_LANCE;
+		} else {
+			if ((slot = search_tc_card("PMAD-AA")) >= 0) {
+				type = PMAD_LANCE;
+			} else {
+				return -ENODEV;
+			}
+		}
+	} else {
+		if (!called) {
+			called = 1;
+			type = PMAX_LANCE;
+		} else {
+			return -ENODEV;
+		}
+	}
+#else
+	if (!called && !TURBOCHANNEL) {
+		called = 1;
+		type = PMAX_LANCE;
+	} else {
+		return -ENODEV;
+	}
+#endif
+
+	return dec_lance_init(dev, type);
+}
+
+/*
+   #ifdef MODULE
+
+   int
+   init_module(void)
+   {
+   root_lance_dev = NULL;
+   return dec_lance_probe(NULL);
+   }
+
+   void
+   cleanup_module(void)
+   {
+   struct lance_private *lp;
+
+   while (root_lance_dev) {
+   lp = root_lance_dev->next_module;
+
+   unregister_netdev(root_lance_dev->dev);
+   kfree(root_lance_dev->dev);
+   root_lance_dev = lp;
+   }
+   }
+
+   #endif -* MODULE */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/depca.c linux.pre11.3/drivers/net/depca.c
--- linux.vanilla/drivers/net/depca.c	Thu Dec  3 13:48:35 1998
+++ linux.pre11.3/drivers/net/depca.c	Mon Jul 19 23:59:56 1999
@@ -221,11 +221,13 @@
                            by <tymm@computer.org> 
       0.451    5-Nov-98   Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
       0.5     14-Nov-98   Re-spin for 2.1.x kernels.
+      0.51    27-Jun-99   Correct received packet length for CRC from
+                           report by <worm@dkik.dk>
 
     =========================================================================
 */
 
-static const char *version = "depca.c:v0.5 1998/11/14 davies@maniac.ultranet.com\n";
+static const char *version = "depca.c:v0.51 1999/6/27 davies@maniac.ultranet.com\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -947,7 +949,7 @@
 	if (status & R_CRC)  lp->stats.rx_crc_errors++;
 	if (status & R_BUFF) lp->stats.rx_fifo_errors++;
       } else {	
-	short len, pkt_len = readw(&lp->rx_ring[entry].msg_length);
+	short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
 	struct sk_buff *skb;
 
 	skb = dev_alloc_skb(pkt_len+2);
@@ -1898,14 +1900,12 @@
       tmp.addr[i] = dev->dev_addr[i];
     }
     ioc->len = ETH_ALEN;
-    if (verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len)) return -EFAULT;
-    copy_to_user(ioc->data, tmp.addr, ioc->len);
+    if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
     break;
 
   case DEPCA_SET_HWADDR:             /* Set the hardware address */
     if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    if (verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN)) return -EFAULT;
-    copy_from_user(tmp.addr,ioc->data,ETH_ALEN);
+    if (copy_from_user(tmp.addr,ioc->data,ETH_ALEN)) return -EFAULT;
     for (i=0; i<ETH_ALEN; i++) {
       dev->dev_addr[i] = tmp.addr[i];
     }
@@ -1956,14 +1956,12 @@
 
   case DEPCA_GET_MCA:                /* Get the multicast address table */
     ioc->len = (HASH_TABLE_LEN >> 3);
-    if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
-    copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len); 
+    if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) return -EFAULT; 
     break;
 
   case DEPCA_SET_MCA:                /* Set a multicast address */
     if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    if (verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len)) return -EFAULT;
-    copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
+    if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) return -EFAULT;
     set_multicast_list(dev);
     break;
 
@@ -1980,11 +1978,8 @@
   case DEPCA_GET_STATS:              /* Get the driver statistics */
     cli();
     ioc->len = sizeof(lp->pktStats);
-    if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) {
-	status = -EFAULT;
-    } else {
-	copy_to_user(ioc->data, &lp->pktStats, ioc->len); 
-    }
+	if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) 
+		status = -EFAULT;
     sti();
     break;
 
@@ -2002,8 +1997,7 @@
     tmp.sval[i++] = inw(DEPCA_DATA);
     memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));
     ioc->len = i+sizeof(struct depca_init);
-    if (verify_area(VERIFY_WRITE, ioc->data, ioc->len)) return -EFAULT;
-    copy_to_user(ioc->data, tmp.addr, ioc->len);
+    if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
     break;
 
   default:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/eepro100.c linux.pre11.3/drivers/net/eepro100.c
--- linux.vanilla/drivers/net/eepro100.c	Tue Feb 23 14:21:33 1999
+++ linux.pre11.3/drivers/net/eepro100.c	Mon Jul 19 23:27:30 1999
@@ -343,7 +343,8 @@
 	const char *product_name;
 	struct device *next_module;
 	spinlock_t lock;
-	struct TxFD	tx_ring[TX_RING_SIZE];	/* Commands (usually CmdTxPacket). */
+	struct TxFD	tx_ring[TX_RING_SIZE] 	/* Commands (usually CmdTxPacket). */
+				__attribute__ ((aligned (L1_CACHE_BYTES)));;
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	struct descriptor  *last_cmd;	/* Last command sent. */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/eql.c linux.pre11.3/drivers/net/eql.c
--- linux.vanilla/drivers/net/eql.c	Thu May 27 22:11:54 1999
+++ linux.pre11.3/drivers/net/eql.c	Mon Jul 19 23:59:56 1999
@@ -411,16 +411,15 @@
 	slaving_request_t srq;
 	int err;
 
-	err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
+	err = copy_from_user(&srq, srqp, sizeof (slaving_request_t));
 	if (err)  
 	  {
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
-		printk ("EQL enslave: error detected by verify_area\n");
+		printk ("EQL enslave: error detected by copy_from_user\n");
 #endif  
 		return err;
 	  }
-	copy_from_user (&srq, srqp, sizeof (slaving_request_t));
 
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
@@ -473,11 +472,10 @@
 	slaving_request_t srq;
 	int err;
 
-	err = verify_area(VERIFY_READ, (void *)srqp, sizeof (slaving_request_t));
+	err = copy_from_user(&srq, srqp, sizeof (slaving_request_t));
 	if (err) 
 		return err;
 
-	copy_from_user (&srq, srqp, sizeof (slaving_request_t));
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
 		printk ("%s: emancipate `%s`\n", dev->name, srq.slave_name);
@@ -504,11 +502,10 @@
 	slave_config_t sc;
 	int err;
 
-	err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
+	err = copy_from_user (&sc, scp, sizeof (slave_config_t));
 	if (err) 
 		return err;
 
-	copy_from_user (&sc, scp, sizeof (slave_config_t));
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
 		printk ("%s: get config for slave `%s'\n", dev->name, sc.slave_name);
@@ -541,7 +538,7 @@
 	slave_config_t sc;
 	int err;
 
-	err = verify_area(VERIFY_READ, (void *)scp, sizeof (slave_config_t));
+	err = copy_from_user (&sc, scp, sizeof (slave_config_t));
 	if (err) 
 		return err;
 
@@ -550,7 +547,6 @@
 		printk ("%s: set config for slave `%s'\n", dev->name, sc.slave_name);
 #endif
   
-	copy_from_user (&sc, scp, sizeof (slave_config_t));
 
 	eql = (equalizer_t *) dev->priv;
 	slave_dev = dev_get (sc.slave_name);
@@ -583,13 +579,12 @@
 	if ( eql_is_master (dev) )
 	{
 		int err;
-		err = verify_area(VERIFY_WRITE, (void *)mcp, sizeof (master_config_t));
-		if (err) 
-			return err;
 		eql = (equalizer_t *) dev->priv;
 		mc.max_slaves = eql->max_slaves;
 		mc.min_slaves = eql->min_slaves;
-		copy_to_user (mcp, &mc, sizeof (master_config_t));
+		err = copy_to_user (mcp, &mc, sizeof (master_config_t));
+		if (err) 
+			return err;
 		return 0;
 	}
 	return -EINVAL;
@@ -602,14 +597,13 @@
 	master_config_t mc;
 	int err;
 
-	err = verify_area(VERIFY_READ, (void *)mcp, sizeof (master_config_t));
+	err = copy_from_user (&mc, mcp, sizeof (master_config_t));
 	if (err)
 		return err;
 #if EQL_DEBUG
 	if (eql_debug >= 20)
 		printk ("%s: set master config\n", dev->name);
 #endif
-	copy_from_user (&mc, mcp, sizeof (master_config_t));
 	if ( eql_is_master (dev) )
 	{
 		eql = (equalizer_t *) dev->priv;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ewrk3.c linux.pre11.3/drivers/net/ewrk3.c
--- linux.vanilla/drivers/net/ewrk3.c	Sun Nov  8 15:07:23 1998
+++ linux.pre11.3/drivers/net/ewrk3.c	Mon Jul 19 23:59:56 1999
@@ -1679,18 +1679,20 @@
 			tmp.addr[i] = dev->dev_addr[i];
 		}
 		ioc->len = ETH_ALEN;
-		if (!(status = verify_area(VERIFY_WRITE, (void *) ioc->data, ioc->len))) {
-			copy_to_user(ioc->data, tmp.addr, ioc->len);
+		if (copy_to_user(ioc->data, tmp.addr, ioc->len)) {
+			status = -EFAULT;
+			break;
 		}
-		break;
 	case EWRK3_SET_HWADDR:	/* Set the hardware address */
 		if (capable(CAP_NET_ADMIN)) {
-			if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {
 				csr = inb(EWRK3_CSR);
 				csr |= (CSR_TXD | CSR_RXD);
 				outb(csr, EWRK3_CSR);	/* Disable the TX and RX */
 
-				copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
+				if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) {
+					status = -EFAULT;
+					break;
+				}
 				for (i = 0; i < ETH_ALEN; i++) {
 					dev->dev_addr[i] = tmp.addr[i];
 					outb(tmp.addr[i], EWRK3_PAR0 + i);
@@ -1698,7 +1700,6 @@
 
 				csr &= ~(CSR_TXD | CSR_RXD);	/* Enable the TX and RX */
 				outb(csr, EWRK3_CSR);
-			}
 		} else {
 			status = -EPERM;
 		}
@@ -1730,7 +1731,6 @@
 
 		break;
 	case EWRK3_GET_MCA:	/* Get the multicast address table */
-		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
 			while (test_and_set_bit(0, (void *) &lp->lock) != 0);	/* Wait for lock to free */
 			if (lp->shmem_length == IO_ONLY) {
 				outb(0, EWRK3_IOPR);
@@ -1743,17 +1743,21 @@
 				memcpy_fromio(tmp.addr, (char *) (lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));
 			}
 			ioc->len = (HASH_TABLE_LEN >> 3);
-			copy_to_user(ioc->data, tmp.addr, ioc->len);
-		}
+			if (copy_to_user(ioc->data, tmp.addr, ioc->len)) {
+				status = -EFAULT;
+				break;
+			}
+
 		lp->lock = 0;	/* Unlock the page register */
 
 		break;
 	case EWRK3_SET_MCA:	/* Set a multicast address */
 		if (capable(CAP_NET_ADMIN)) {
-			if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {
-				copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
-				set_multicast_list(dev);
+			if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) {
+				status = -EFAULT;
+				break;
 			}
+			set_multicast_list(dev);
 		} else {
 			status = -EPERM;
 		}
@@ -1781,9 +1785,8 @@
 	case EWRK3_GET_STATS:	/* Get the driver statistics */
 		cli();
 		ioc->len = sizeof(lp->pktStats);
-		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-			copy_to_user(ioc->data, &lp->pktStats, ioc->len);
-		}
+		if (copy_to_user(ioc->data, &lp->pktStats, ioc->len))
+			status = -EFAULT;
 		sti();
 
 		break;
@@ -1800,16 +1803,16 @@
 	case EWRK3_GET_CSR:	/* Get the CSR Register contents */
 		tmp.addr[0] = inb(EWRK3_CSR);
 		ioc->len = 1;
-		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-			copy_to_user(ioc->data, tmp.addr, ioc->len);
-		}
+		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+			status = -EFAULT;
 		break;
 	case EWRK3_SET_CSR:	/* Set the CSR Register contents */
 		if (capable(CAP_NET_ADMIN)) {
-			if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) {
-				copy_from_user(tmp.addr, ioc->data, 1);
-				outb(tmp.addr[0], EWRK3_CSR);
+			if (copy_from_user(tmp.addr, ioc->data, 1)) {
+				status = -EFAULT;
+				break;
 			}
+			outb(tmp.addr[0], EWRK3_CSR);
 		} else {
 			status = -EPERM;
 		}
@@ -1826,9 +1829,8 @@
 				tmp.addr[i++] = inb(EWRK3_PAR0 + j);
 			}
 			ioc->len = EEPROM_MAX + 1 + ETH_ALEN;
-			if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-				copy_to_user(ioc->data, tmp.addr, ioc->len);
-			}
+			if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+				status = -EFAULT;
 		} else {
 			status = -EPERM;
 		}
@@ -1836,11 +1838,12 @@
 		break;
 	case EWRK3_SET_EEPROM:	/* Set the EEPROM contents */
 		if (capable(CAP_NET_ADMIN)) {
-			if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {
-				copy_from_user(tmp.addr, ioc->data, EEPROM_MAX);
-				for (i = 0; i < (EEPROM_MAX >> 1); i++) {
-					Write_EEPROM(tmp.val[i], iobase, i);
-				}
+			if (copy_from_user(tmp.addr, ioc->data, EEPROM_MAX)) {
+				status = -EFAULT;
+				break;
+			}
+			for (i = 0; i < (EEPROM_MAX >> 1); i++) {
+				Write_EEPROM(tmp.val[i], iobase, i);
 			}
 		} else {
 			status = -EPERM;
@@ -1850,9 +1853,8 @@
 	case EWRK3_GET_CMR:	/* Get the CMR Register contents */
 		tmp.addr[0] = inb(EWRK3_CMR);
 		ioc->len = 1;
-		if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-			copy_to_user(ioc->data, tmp.addr, ioc->len);
-		}
+		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+			status = -EFAULT;
 		break;
 	case EWRK3_SET_TX_CUT_THRU:	/* Set TX cut through mode */
 		if (suser()) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/Config.in linux.pre11.3/drivers/net/hamradio/Config.in
--- linux.vanilla/drivers/net/hamradio/Config.in	Thu Dec 31 18:10:42 1998
+++ linux.pre11.3/drivers/net/hamradio/Config.in	Tue Jul 20 00:29:25 1999
@@ -28,3 +28,5 @@
   bool '   soundmodem support for 4800 baud PSK modulation' CONFIG_SOUNDMODEM_PSK4800
   bool '   soundmodem support for 9600 baud FSK G3RUH modulation' CONFIG_SOUNDMODEM_FSK9600
 fi
+
+tristate 'YAM driver for AX.25' CONFIG_YAM
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/Makefile linux.pre11.3/drivers/net/hamradio/Makefile
--- linux.vanilla/drivers/net/hamradio/Makefile	Sun Nov  8 15:07:26 1998
+++ linux.pre11.3/drivers/net/hamradio/Makefile	Tue Jul 20 00:29:25 1999
@@ -53,6 +53,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_YAM),y)
+L_OBJS += yam.o
+else
+  ifeq ($(CONFIG_YAM),m)
+  M_OBJS += yam.o
+  endif
+endif
+
 ifeq ($(CONFIG_PI),y)
 L_OBJS += pi2.o
 else
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/hdlcdrv.c linux.pre11.3/drivers/net/hamradio/hdlcdrv.c
--- linux.vanilla/drivers/net/hamradio/hdlcdrv.c	Thu Dec 31 18:10:42 1998
+++ linux.pre11.3/drivers/net/hamradio/hdlcdrv.c	Tue Jul 20 00:29:25 1999
@@ -43,7 +43,6 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/types.h>
 #include <linux/net.h>
 #include <linux/in.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/soundmodem/sm.h linux.pre11.3/drivers/net/hamradio/soundmodem/sm.h
--- linux.vanilla/drivers/net/hamradio/soundmodem/sm.h	Sun Nov  8 15:07:27 1998
+++ linux.pre11.3/drivers/net/hamradio/soundmodem/sm.h	Tue Jul 20 00:29:25 1999
@@ -296,8 +296,6 @@
 
 #ifdef __i386__
 
-#include <asm/processor.h>
-
 #define HAS_RDTSC (current_cpu_data.x86_capability & X86_FEATURE_TSC)
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/yam.c linux.pre11.3/drivers/net/hamradio/yam.c
--- linux.vanilla/drivers/net/hamradio/yam.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/hamradio/yam.c	Tue Jul 20 00:29:25 1999
@@ -0,0 +1,1297 @@
+/*****************************************************************************/
+
+/*
+ *    yam.c  -- YAM radio modem driver.
+ *
+ *      Copyright (C) 1998 Frederic Rible F1OAT (frible@teaser.fr)
+ *      Adapted from baycom.c driver written by Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Please note that the GPL allows you to use the driver, NOT the radio.
+ *  In order to use the radio, you need a license from the communications
+ *  authority of your country.
+ *
+ *
+ *  History:
+ *   0.0 F1OAT 06.06.98  Begin of work with baycom.c source code V 0.3
+ *   0.1 F1OAT 07.06.98  Add timer polling routine for channel arbitration
+ *   0.2 F6FBB 08.06.98  Added delay after FPGA programming
+ *   0.3 F6FBB 29.07.98  Delayed PTT implementation for dupmode=2
+ *   0.4 F6FBB 30.07.98  Added TxTail, Slottime and Persistance
+ *   0.5 F6FBB 01.08.98  Shared IRQs, /proc/net and network statistics
+ *   0.6 F6FBB 25.08.98  Added 1200Bds format
+ *   0.7 F6FBB 12.09.98  Added to the kernel configuration
+ *   0.8 F6FBB 14.10.98  Fixed slottime/persistance timing bug
+ */
+
+/*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/net.h>
+#include <linux/in.h>
+#include <linux/if.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+/* prototypes for ax25_encapsulate and ax25_rebuild_header */
+#include <net/ax25.h>
+#endif							/* CONFIG_AX25 || CONFIG_AX25_MODULE */
+
+/* make genksyms happy */
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/tcp.h>
+
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+
+#include <linux/yam.h>
+#include "yam9600.h"
+#include "yam1200.h"
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * currently this module is supposed to support both module styles, i.e.
+ * the old one present up to about 2.1.9, and the new one functioning
+ * starting with 2.1.21. The reason is I have a kit allowing to compile
+ * this module also under 2.0.x which was requested by several people.
+ * This will go in 2.2
+ */
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE >= 0x20100
+#include <asm/uaccess.h>
+#else
+#include <asm/segment.h>
+#include <linux/mm.h>
+
+#undef put_user
+#undef get_user
+
+#define put_user(x,ptr) ({ __put_user((unsigned long)(x),(ptr),sizeof(*(ptr))); 0; })
+#define get_user(x,ptr) ({ x = ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr)))); 0; })
+
+extern inline int copy_from_user(void *to, const void *from, unsigned long n)
+{
+	int i = verify_area(VERIFY_READ, from, n);
+	if (i)
+		return i;
+	memcpy_fromfs(to, from, n);
+	return 0;
+}
+
+extern inline int copy_to_user(void *to, const void *from, unsigned long n)
+{
+	int i = verify_area(VERIFY_WRITE, to, n);
+	if (i)
+		return i;
+	memcpy_tofs(to, from, n);
+	return 0;
+}
+#endif
+
+#if LINUX_VERSION_CODE < 0x20115
+extern __inline__ void dev_init_buffers(struct device *dev)
+{
+	int i;
+	for (i = 0; i < DEV_NUMBUFFS; i++) {
+		skb_queue_head_init(&dev->buffs[i]);
+	}
+}
+#endif
+
+#if LINUX_VERSION_CODE >= 0x20123
+#include <linux/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(x) x
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static const char yam_drvname[] = "yam";
+static const char yam_drvinfo[] = KERN_INFO "YAM driver version 0.8 by F1OAT/F6FBB\n";
+
+/* --------------------------------------------------------------------- */
+
+#define YAM_9600	1
+#define YAM_1200	2
+
+#define NR_PORTS 	4
+#define YAM_MAGIC	0xF10A7654
+
+/* Transmitter states */
+
+#define TX_OFF  	0
+#define TX_HEAD		1
+#define TX_DATA  	2
+#define TX_CRC1  	3
+#define TX_CRC2  	4
+#define TX_TAIL  	5
+
+#define YAM_MAX_FRAME	1024
+
+#define DEFAULT_BITRATE	9600	/* bps */
+#define DEFAULT_HOLDD   10		/* sec */
+#define DEFAULT_TXD	    300		/* ms */
+#define DEFAULT_TXTAIL  10		/* ms */
+#define DEFAULT_SLOT    100		/* ms */
+#define DEFAULT_PERS    64		/* 0->255 */
+
+struct yam_port {
+	int magic;
+	int bitrate;
+	int baudrate;
+	int iobase;
+	int irq;
+	int dupmode;
+	char name[16];
+
+	struct device dev;
+
+	/* Stats section */
+
+#if LINUX_VERSION_CODE < 0x20119
+	struct enet_statistics stats;
+#else
+	struct net_device_stats stats;
+#endif
+	int nb_rxint;
+	int nb_mdint;
+
+	/* Parameters section */
+
+	int txd;					/* tx delay */
+	int holdd;					/* duplex ptt delay */
+	int txtail;					/* txtail delay */
+	int slot;					/* slottime */
+	int pers;					/* persistence */
+
+	/* Tx section */
+
+	int tx_state;
+	int tx_count;
+	int slotcnt;
+	unsigned char tx_buf[YAM_MAX_FRAME];
+	int tx_len;
+	int tx_crcl, tx_crch;
+	struct sk_buff_head send_queue;		/* Packets awaiting transmission */
+
+	/* Rx section */
+
+	int dcd;
+	unsigned char rx_buf[YAM_MAX_FRAME];
+	int rx_len;
+	int rx_crcl, rx_crch;
+};
+
+struct yam_mcs {
+	unsigned char bits[YAM_FPGA_SIZE];
+	int bitrate;
+	struct yam_mcs *next;
+};
+
+static struct yam_port yam_ports[NR_PORTS];
+
+static struct yam_mcs *yam_data = NULL;
+
+static unsigned irqs[16];
+
+static char ax25_bcast[7] =
+{'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1, '0' << 1};
+static char ax25_test[7] =
+{'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1, '1' << 1};
+
+static struct timer_list yam_timer;
+
+/* --------------------------------------------------------------------- */
+
+#define RBR(iobase) (iobase+0)
+#define THR(iobase) (iobase+0)
+#define IER(iobase) (iobase+1)
+#define IIR(iobase) (iobase+2)
+#define FCR(iobase) (iobase+2)
+#define LCR(iobase) (iobase+3)
+#define MCR(iobase) (iobase+4)
+#define LSR(iobase) (iobase+5)
+#define MSR(iobase) (iobase+6)
+#define SCR(iobase) (iobase+7)
+#define DLL(iobase) (iobase+0)
+#define DLM(iobase) (iobase+1)
+
+#define YAM_EXTENT 8
+
+/* Interrupt Identification Register Bit Masks */
+#define IIR_NOPEND 	1
+#define IIR_MSR  	0
+#define IIR_TX     	2
+#define IIR_RX     	4
+#define IIR_LSR   	6
+#define IIR_TIMEOUT	12			/* Fifo mode only */
+
+#define IIR_MASK	0x0F
+
+/* Interrupt Enable Register Bit Masks */
+#define IER_RX  1				/* enable rx interrupt */
+#define IER_TX  2				/* enable tx interrupt */
+#define IER_LSR 4				/* enable line status interrupts */
+#define IER_MSR 8				/* enable modem status interrupts */
+
+/* Modem Control Register Bit Masks */
+#define MCR_DTR  0x01			/* DTR output */
+#define MCR_RTS  0x02			/* RTS output */
+#define MCR_OUT1 0x04			/* OUT1 output (not accessible in RS232) */
+#define MCR_OUT2 0x08			/* Master Interrupt enable (must be set on PCs) */
+#define MCR_LOOP 0x10			/* Loopback enable */
+
+/* Modem Status Register Bit Masks */
+#define MSR_DCTS 0x01			/* Delta CTS input */
+#define MSR_DDSR 0x02			/* Delta DSR */
+#define MSR_DRIN 0x04			/* Delta RI */
+#define MSR_DDCD 0x08			/* Delta DCD */
+#define MSR_CTS  0x10			/* CTS input */
+#define MSR_DSR  0x20			/* DSR input */
+#define MSR_RING 0x40			/* RI  input */
+#define MSR_DCD  0x80			/* DCD input */
+
+/* line status register bit mask */
+#define LSR_RXC	   0x01
+#define LSR_OE	   0x02
+#define LSR_PE	   0x04
+#define LSR_FE	   0x08
+#define LSR_BREAK  0x10
+#define LSR_THRE   0x20
+#define LSR_TSRE   0x40
+
+/* Line Control Register Bit Masks */
+#define LCR_DLAB    0x80
+#define LCR_BREAK   0x40
+#define LCR_PZERO   0x28
+#define LCR_PEVEN   0x18
+#define LCR_PODD    0x08
+#define LCR_STOP1   0x00
+#define LCR_STOP2   0x04
+#define LCR_BIT5    0x00
+#define LCR_BIT6    0x02
+#define LCR_BIT7    0x01
+#define LCR_BIT8    0x03
+
+/* YAM Modem <-> UART Port mapping */
+
+#define TX_RDY 	  MSR_DCTS		/* transmitter ready to send */
+#define RX_DCD    MSR_DCD		/* carrier detect */
+#define RX_FLAG   MSR_RING		/* hdlc flag received */
+#define FPGA_DONE MSR_DSR		/* FPGA is configured */
+#define PTT_ON    (MCR_RTS|MCR_OUT2)	/* activate PTT */
+#define PTT_OFF   (MCR_DTR|MCR_OUT2)	/* release PTT */
+
+#define ENABLE_RXINT   IER_RX	/* enable uart rx interrupt during rx */
+#define ENABLE_TXINT   IER_MSR	/* enable uart ms interrupt during tx */
+#define ENABLE_RTXINT  (IER_RX|IER_MSR)		/* full duplex operations */
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+/*************************************************************************
+* CRC Tables
+************************************************************************/
+
+static const unsigned char chktabl[256] =
+{0x00, 0x89, 0x12, 0x9b, 0x24, 0xad, 0x36, 0xbf, 0x48, 0xc1, 0x5a, 0xd3, 0x6c, 0xe5, 0x7e,
+ 0xf7, 0x81, 0x08, 0x93, 0x1a, 0xa5, 0x2c, 0xb7, 0x3e, 0xc9, 0x40, 0xdb, 0x52, 0xed, 0x64,
+ 0xff, 0x76, 0x02, 0x8b, 0x10, 0x99, 0x26, 0xaf, 0x34, 0xbd, 0x4a, 0xc3, 0x58, 0xd1, 0x6e,
+ 0xe7, 0x7c, 0xf5, 0x83, 0x0a, 0x91, 0x18, 0xa7, 0x2e, 0xb5, 0x3c, 0xcb, 0x42, 0xd9, 0x50,
+ 0xef, 0x66, 0xfd, 0x74, 0x04, 0x8d, 0x16, 0x9f, 0x20, 0xa9, 0x32, 0xbb, 0x4c, 0xc5, 0x5e,
+ 0xd7, 0x68, 0xe1, 0x7a, 0xf3, 0x85, 0x0c, 0x97, 0x1e, 0xa1, 0x28, 0xb3, 0x3a, 0xcd, 0x44,
+ 0xdf, 0x56, 0xe9, 0x60, 0xfb, 0x72, 0x06, 0x8f, 0x14, 0x9d, 0x22, 0xab, 0x30, 0xb9, 0x4e,
+ 0xc7, 0x5c, 0xd5, 0x6a, 0xe3, 0x78, 0xf1, 0x87, 0x0e, 0x95, 0x1c, 0xa3, 0x2a, 0xb1, 0x38,
+ 0xcf, 0x46, 0xdd, 0x54, 0xeb, 0x62, 0xf9, 0x70, 0x08, 0x81, 0x1a, 0x93, 0x2c, 0xa5, 0x3e,
+ 0xb7, 0x40, 0xc9, 0x52, 0xdb, 0x64, 0xed, 0x76, 0xff, 0x89, 0x00, 0x9b, 0x12, 0xad, 0x24,
+ 0xbf, 0x36, 0xc1, 0x48, 0xd3, 0x5a, 0xe5, 0x6c, 0xf7, 0x7e, 0x0a, 0x83, 0x18, 0x91, 0x2e,
+ 0xa7, 0x3c, 0xb5, 0x42, 0xcb, 0x50, 0xd9, 0x66, 0xef, 0x74, 0xfd, 0x8b, 0x02, 0x99, 0x10,
+ 0xaf, 0x26, 0xbd, 0x34, 0xc3, 0x4a, 0xd1, 0x58, 0xe7, 0x6e, 0xf5, 0x7c, 0x0c, 0x85, 0x1e,
+ 0x97, 0x28, 0xa1, 0x3a, 0xb3, 0x44, 0xcd, 0x56, 0xdf, 0x60, 0xe9, 0x72, 0xfb, 0x8d, 0x04,
+ 0x9f, 0x16, 0xa9, 0x20, 0xbb, 0x32, 0xc5, 0x4c, 0xd7, 0x5e, 0xe1, 0x68, 0xf3, 0x7a, 0x0e,
+ 0x87, 0x1c, 0x95, 0x2a, 0xa3, 0x38, 0xb1, 0x46, 0xcf, 0x54, 0xdd, 0x62, 0xeb, 0x70, 0xf9,
+ 0x8f, 0x06, 0x9d, 0x14, 0xab, 0x22, 0xb9, 0x30, 0xc7, 0x4e, 0xd5, 0x5c, 0xe3, 0x6a, 0xf1,
+ 0x78};
+static const unsigned char chktabh[256] =
+{0x00, 0x11, 0x23, 0x32, 0x46, 0x57, 0x65, 0x74, 0x8c, 0x9d, 0xaf, 0xbe, 0xca, 0xdb, 0xe9,
+ 0xf8, 0x10, 0x01, 0x33, 0x22, 0x56, 0x47, 0x75, 0x64, 0x9c, 0x8d, 0xbf, 0xae, 0xda, 0xcb,
+ 0xf9, 0xe8, 0x21, 0x30, 0x02, 0x13, 0x67, 0x76, 0x44, 0x55, 0xad, 0xbc, 0x8e, 0x9f, 0xeb,
+ 0xfa, 0xc8, 0xd9, 0x31, 0x20, 0x12, 0x03, 0x77, 0x66, 0x54, 0x45, 0xbd, 0xac, 0x9e, 0x8f,
+ 0xfb, 0xea, 0xd8, 0xc9, 0x42, 0x53, 0x61, 0x70, 0x04, 0x15, 0x27, 0x36, 0xce, 0xdf, 0xed,
+ 0xfc, 0x88, 0x99, 0xab, 0xba, 0x52, 0x43, 0x71, 0x60, 0x14, 0x05, 0x37, 0x26, 0xde, 0xcf,
+ 0xfd, 0xec, 0x98, 0x89, 0xbb, 0xaa, 0x63, 0x72, 0x40, 0x51, 0x25, 0x34, 0x06, 0x17, 0xef,
+ 0xfe, 0xcc, 0xdd, 0xa9, 0xb8, 0x8a, 0x9b, 0x73, 0x62, 0x50, 0x41, 0x35, 0x24, 0x16, 0x07,
+ 0xff, 0xee, 0xdc, 0xcd, 0xb9, 0xa8, 0x9a, 0x8b, 0x84, 0x95, 0xa7, 0xb6, 0xc2, 0xd3, 0xe1,
+ 0xf0, 0x08, 0x19, 0x2b, 0x3a, 0x4e, 0x5f, 0x6d, 0x7c, 0x94, 0x85, 0xb7, 0xa6, 0xd2, 0xc3,
+ 0xf1, 0xe0, 0x18, 0x09, 0x3b, 0x2a, 0x5e, 0x4f, 0x7d, 0x6c, 0xa5, 0xb4, 0x86, 0x97, 0xe3,
+ 0xf2, 0xc0, 0xd1, 0x29, 0x38, 0x0a, 0x1b, 0x6f, 0x7e, 0x4c, 0x5d, 0xb5, 0xa4, 0x96, 0x87,
+ 0xf3, 0xe2, 0xd0, 0xc1, 0x39, 0x28, 0x1a, 0x0b, 0x7f, 0x6e, 0x5c, 0x4d, 0xc6, 0xd7, 0xe5,
+ 0xf4, 0x80, 0x91, 0xa3, 0xb2, 0x4a, 0x5b, 0x69, 0x78, 0x0c, 0x1d, 0x2f, 0x3e, 0xd6, 0xc7,
+ 0xf5, 0xe4, 0x90, 0x81, 0xb3, 0xa2, 0x5a, 0x4b, 0x79, 0x68, 0x1c, 0x0d, 0x3f, 0x2e, 0xe7,
+ 0xf6, 0xc4, 0xd5, 0xa1, 0xb0, 0x82, 0x93, 0x6b, 0x7a, 0x48, 0x59, 0x2d, 0x3c, 0x0e, 0x1f,
+ 0xf7, 0xe6, 0xd4, 0xc5, 0xb1, 0xa0, 0x92, 0x83, 0x7b, 0x6a, 0x58, 0x49, 0x3d, 0x2c, 0x1e,
+ 0x0f};
+
+/*************************************************************************
+* FPGA functions
+************************************************************************/
+
+static void delay(int ms)
+{
+	unsigned long timeout = jiffies + ((ms * HZ) / 1000);
+	while (jiffies < timeout);
+}
+
+/*
+ * reset FPGA
+ */
+
+static void fpga_reset(int iobase)
+{
+	outb(0, IER(iobase));
+	outb(LCR_DLAB | LCR_BIT5, LCR(iobase));
+	outb(1, DLL(iobase));
+	outb(0, DLM(iobase));
+
+	outb(LCR_BIT5, LCR(iobase));
+	inb(LSR(iobase));
+	inb(MSR(iobase));
+	/* turn off FPGA supply voltage */
+	outb(MCR_OUT1 | MCR_OUT2, MCR(iobase));
+	delay(100);
+	/* turn on FPGA supply voltage again */
+	outb(MCR_DTR | MCR_RTS | MCR_OUT1 | MCR_OUT2, MCR(iobase));
+	delay(100);
+}
+
+/*
+ * send one byte to FPGA
+ */
+
+static int fpga_write(int iobase, unsigned char wrd)
+{
+	unsigned char bit;
+	int k;
+	unsigned long timeout = jiffies + HZ / 10;
+
+	for (k = 0; k < 8; k++) {
+		bit = (wrd & 0x80) ? (MCR_RTS | MCR_DTR) : MCR_DTR;
+		outb(bit | MCR_OUT1 | MCR_OUT2, MCR(iobase));
+		wrd <<= 1;
+		outb(0xfc, THR(iobase));
+		while ((inb(LSR(iobase)) & LSR_TSRE) == 0)
+			if (jiffies > timeout)
+				return -1;
+	}
+
+	return 0;
+}
+
+#ifdef MODULE
+static void free_mcs(void)
+{
+	struct yam_mcs *p;
+
+	while (yam_data) {
+		p = yam_data;
+		yam_data = yam_data->next;
+		kfree(p);
+	}
+}
+#endif
+
+static unsigned char *
+ add_mcs(unsigned char *bits, int bitrate)
+{
+	struct yam_mcs *p;
+
+	/* If it already exists, replace the bit data */
+	p = yam_data;
+	while (p) {
+		if (p->bitrate == bitrate) {
+			memcpy(p->bits, bits, YAM_FPGA_SIZE);
+			return p->bits;
+		}
+		p = p->next;
+	}
+
+	/* Allocate a new mcs */
+	p = kmalloc(sizeof(struct yam_mcs), GFP_ATOMIC);
+	if (p == NULL) {
+		printk(KERN_WARNING "YAM: no memory to allocate mcs\n");
+		return NULL;
+	}
+	memcpy(p->bits, bits, YAM_FPGA_SIZE);
+	p->bitrate = bitrate;
+	p->next = yam_data;
+	yam_data = p;
+
+	return p->bits;
+}
+
+static unsigned char *get_mcs(int bitrate)
+{
+	struct yam_mcs *p;
+
+	p = yam_data;
+	while (p) {
+		if (p->bitrate == bitrate)
+			return p->bits;
+		p = p->next;
+	}
+
+	/* Load predefined mcs data */
+	switch (bitrate) {
+	case 1200:
+		return add_mcs(bits_1200, bitrate);
+	default:
+		return add_mcs(bits_9600, bitrate);
+	}
+}
+
+/*
+ * download bitstream to FPGA
+ * data is contained in bits[] array in fpgaconf.h
+ */
+
+static int fpga_download(int iobase, int bitrate)
+{
+	int i, rc;
+	unsigned char *pbits;
+
+	pbits = get_mcs(bitrate);
+	if (pbits == NULL)
+		return -1;
+
+	fpga_reset(iobase);
+	for (i = 0; i < YAM_FPGA_SIZE; i++) {
+		if (fpga_write(iobase, pbits[i])) {
+			printk("yam: error in write cycle\n");
+			return -1;			/* write... */
+		}
+	}
+
+	fpga_write(iobase, 0xFF);
+	rc = inb(MSR(iobase));		/* check DONE signal */
+
+	/* Needed for some hardwares */
+	delay(50);
+
+	return (rc & MSR_DSR) ? 0 : -1;
+}
+
+
+/************************************************************************
+* Serial port init 
+************************************************************************/
+
+static void yam_set_uart(struct device *dev)
+{
+	struct yam_port *yp = (struct yam_port *) dev->priv;
+	int divisor = 115200 / yp->baudrate;
+
+	outb(0, IER(dev->base_addr));
+	outb(LCR_DLAB | LCR_BIT8, LCR(dev->base_addr));
+	outb(divisor, DLL(dev->base_addr));
+	outb(0, DLM(dev->base_addr));
+	outb(LCR_BIT8, LCR(dev->base_addr));
+	outb(PTT_OFF, MCR(dev->base_addr));
+	outb(0x00, FCR(dev->base_addr));
+
+	/* Flush pending irq */
+
+	inb(RBR(dev->base_addr));
+	inb(MSR(dev->base_addr));
+
+	/* Enable rx irq */
+
+	outb(ENABLE_RTXINT, IER(dev->base_addr));
+}
+
+
+/* --------------------------------------------------------------------- */
+
+enum uart {
+	c_uart_unknown, c_uart_8250,
+	c_uart_16450, c_uart_16550, c_uart_16550A
+};
+
+static const char *uart_str[] =
+{"unknown", "8250", "16450", "16550", "16550A"};
+
+static enum uart yam_check_uart(unsigned int iobase)
+{
+	unsigned char b1, b2, b3;
+	enum uart u;
+	enum uart uart_tab[] =
+	{c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A};
+
+	b1 = inb(MCR(iobase));
+	outb(b1 | 0x10, MCR(iobase));	/* loopback mode */
+	b2 = inb(MSR(iobase));
+	outb(0x1a, MCR(iobase));
+	b3 = inb(MSR(iobase)) & 0xf0;
+	outb(b1, MCR(iobase));		/* restore old values */
+	outb(b2, MSR(iobase));
+	if (b3 != 0x90)
+		return c_uart_unknown;
+	inb(RBR(iobase));
+	inb(RBR(iobase));
+	outb(0x01, FCR(iobase));	/* enable FIFOs */
+	u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
+	if (u == c_uart_16450) {
+		outb(0x5a, SCR(iobase));
+		b1 = inb(SCR(iobase));
+		outb(0xa5, SCR(iobase));
+		b2 = inb(SCR(iobase));
+		if ((b1 != 0x5a) || (b2 != 0xa5))
+			u = c_uart_8250;
+	}
+	return u;
+}
+
+/******************************************************************************
+* Rx Section
+******************************************************************************/
+static void inline
+ yam_rx_flag(struct device *dev, struct yam_port *yp)
+{
+	if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) {
+		int pkt_len = yp->rx_len - 2 + 1;	/* -CRC + kiss */
+		struct sk_buff *skb;
+
+		if ((yp->rx_crch & yp->rx_crcl) != 0xFF) {
+			/* Bad crc */
+		} else {
+			if (!(skb = dev_alloc_skb(pkt_len))) {
+				printk("%s: memory squeeze, dropping packet\n", dev->name);
+				++yp->stats.rx_dropped;
+			} else {
+				unsigned char *cp;
+				skb->dev = dev;
+				cp = skb_put(skb, pkt_len);
+				*cp++ = 0;		/* KISS kludge */
+				memcpy(cp, yp->rx_buf, pkt_len - 1);
+				skb->protocol = htons(ETH_P_AX25);
+				skb->mac.raw = skb->data;
+				netif_rx(skb);
+				++yp->stats.rx_packets;
+			}
+		}
+	}
+	yp->rx_len = 0;
+	yp->rx_crcl = 0x21;
+	yp->rx_crch = 0xf3;
+}
+
+static void inline
+ yam_rx_byte(struct device *dev, struct yam_port *yp, unsigned char rxb)
+{
+	if (yp->rx_len < YAM_MAX_FRAME) {
+		unsigned char c = yp->rx_crcl;
+		yp->rx_crcl = (chktabl[c] ^ yp->rx_crch);
+		yp->rx_crch = (chktabh[c] ^ rxb);
+		yp->rx_buf[yp->rx_len++] = rxb;
+	}
+}
+
+/********************************************************************************
+* TX Section
+********************************************************************************/
+
+static void ptt_on(struct device *dev)
+{
+	outb(PTT_ON, MCR(dev->base_addr));
+}
+
+static void ptt_off(struct device *dev)
+{
+	outb(PTT_OFF, MCR(dev->base_addr));
+}
+
+static int yam_send_packet(struct sk_buff *skb, struct device *dev)
+{
+	struct yam_port *yp = dev->priv;
+
+	if (skb == NULL) {
+		return 0;
+	}
+	skb_queue_tail(&yp->send_queue, skb);
+	dev->trans_start = jiffies;
+	return 0;
+}
+
+static void yam_start_tx(struct device *dev, struct yam_port *yp)
+{
+	if ((yp->tx_state == TX_TAIL) || (yp->txd == 0))
+		yp->tx_count = 1;
+	else
+		yp->tx_count = (yp->bitrate * yp->txd) / 8000;
+	yp->tx_state = TX_HEAD;
+	ptt_on(dev);
+}
+
+static unsigned short random_seed;
+
+static inline unsigned short random_num(void)
+{
+	random_seed = 28629 * random_seed + 157;
+	return random_seed;
+}
+
+static void yam_arbitrate(struct device *dev)
+{
+	struct yam_port *yp = dev->priv;
+
+	if (!yp || yp->magic != YAM_MAGIC
+		|| yp->tx_state != TX_OFF || skb_queue_empty(&yp->send_queue)) {
+		return;
+	}
+	/* tx_state is TX_OFF and there is data to send */
+
+	if (yp->dupmode) {
+		/* Full duplex mode, don't wait */
+		yam_start_tx(dev, yp);
+		return;
+	}
+	if (yp->dcd) {
+		/* DCD on, wait slotime ... */
+		yp->slotcnt = yp->slot / 10;
+		return;
+	}
+	/* Is slottime passed ? */
+	if ((--yp->slotcnt) > 0)
+		return;
+
+	yp->slotcnt = yp->slot / 10;
+
+	/* is random > persist ? */
+	if ((random_num() % 256) > yp->pers)
+		return;
+
+	yam_start_tx(dev, yp);
+}
+
+static void yam_dotimer(unsigned long dummy)
+{
+	int i;
+
+	for (i = 0; i < NR_PORTS; i++) {
+		struct device *dev = &yam_ports[i].dev;
+		if (dev->start)
+			yam_arbitrate(dev);
+	}
+	yam_timer.expires = jiffies + HZ / 100;
+	add_timer(&yam_timer);
+}
+
+static void yam_tx_byte(struct device *dev, struct yam_port *yp)
+{
+	struct sk_buff *skb;
+	unsigned char b, temp;
+
+	switch (yp->tx_state) {
+	case TX_OFF:
+		break;
+	case TX_HEAD:
+		if (--yp->tx_count <= 0) {
+			if (!(skb = skb_dequeue(&yp->send_queue))) {
+				ptt_off(dev);
+				yp->tx_state = TX_OFF;
+				break;
+			}
+			yp->tx_state = TX_DATA;
+			if (skb->data[0] != 0) {
+/*                              do_kiss_params(s, skb->data, skb->len); */
+				dev_kfree_skb(skb);
+				break;
+			}
+			yp->tx_len = skb->len - 1;	/* strip KISS byte */
+			if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) {
+				dev_kfree_skb(skb);
+				break;
+			}
+			memcpy(yp->tx_buf, skb->data + 1, yp->tx_len);
+			dev_kfree_skb(skb);
+			yp->tx_count = 0;
+			yp->tx_crcl = 0x21;
+			yp->tx_crch = 0xf3;
+			yp->tx_state = TX_DATA;
+		}
+		break;
+	case TX_DATA:
+		b = yp->tx_buf[yp->tx_count++];
+		outb(b, THR(dev->base_addr));
+		temp = yp->tx_crcl;
+		yp->tx_crcl = chktabl[temp] ^ yp->tx_crch;
+		yp->tx_crch = chktabh[temp] ^ b;
+		if (yp->tx_count >= yp->tx_len) {
+			yp->tx_state = TX_CRC1;
+		}
+		break;
+	case TX_CRC1:
+		yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch;
+		yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff;
+		outb(yp->tx_crcl, THR(dev->base_addr));
+		yp->tx_state = TX_CRC2;
+		break;
+	case TX_CRC2:
+		outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr));
+		if (skb_queue_empty(&yp->send_queue)) {
+			yp->tx_count = (yp->bitrate * yp->txtail) / 8000;
+			if (yp->dupmode == 2)
+				yp->tx_count += (yp->bitrate * yp->holdd) / 8;
+			if (yp->tx_count == 0)
+				yp->tx_count = 1;
+			yp->tx_state = TX_TAIL;
+		} else {
+			yp->tx_count = 1;
+			yp->tx_state = TX_HEAD;
+		}
+		++yp->stats.tx_packets;
+		break;
+	case TX_TAIL:
+		if (--yp->tx_count <= 0) {
+			yp->tx_state = TX_OFF;
+			ptt_off(dev);
+		}
+		break;
+	}
+}
+
+/***********************************************************************************
+* ISR routine
+************************************************************************************/
+
+static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct device *dev;
+	struct yam_port *yp;
+	unsigned char iir;
+	int counter = 100;
+	int i;
+
+	sti();
+
+	for (i = 0; i < NR_PORTS; i++) {
+		yp = &yam_ports[i];
+		dev = &yp->dev;
+
+		if (!dev->start)
+			continue;
+
+		while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) {
+			unsigned char msr = inb(MSR(dev->base_addr));
+			unsigned char lsr = inb(LSR(dev->base_addr));
+			unsigned char rxb;
+
+			if (lsr & LSR_OE)
+				++yp->stats.rx_fifo_errors;
+
+			yp->dcd = (msr & RX_DCD) ? 1 : 0;
+
+			if (--counter <= 0) {
+				printk("%s: too many irq iir=%d\n", dev->name, iir);
+				return;
+			}
+			if (msr & TX_RDY) {
+				++yp->nb_mdint;
+				yam_tx_byte(dev, yp);
+			}
+			if (lsr & LSR_RXC) {
+				++yp->nb_rxint;
+				rxb = inb(RBR(dev->base_addr));
+				if (msr & RX_FLAG)
+					yam_rx_flag(dev, yp);
+				else
+					yam_rx_byte(dev, yp, rxb);
+			}
+		}
+	}
+}
+
+static int yam_net_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+	int len = 0;
+	int i;
+	off_t pos = 0;
+	off_t begin = 0;
+
+	cli();
+
+	for (i = 0; i < NR_PORTS; i++) {
+		if (yam_ports[i].iobase == 0 || yam_ports[i].irq == 0)
+			continue;
+		len += sprintf(buffer + len, "Device %s\n", yam_ports[i].name);
+		len += sprintf(buffer + len, "  Up       %d\n", yam_ports[i].dev.start);
+		len += sprintf(buffer + len, "  Speed    %u\n", yam_ports[i].bitrate);
+		len += sprintf(buffer + len, "  IoBase   0x%x\n", yam_ports[i].iobase);
+		len += sprintf(buffer + len, "  BaudRate %u\n", yam_ports[i].baudrate);
+		len += sprintf(buffer + len, "  IRQ      %u\n", yam_ports[i].irq);
+		len += sprintf(buffer + len, "  TxState  %u\n", yam_ports[i].tx_state);
+		len += sprintf(buffer + len, "  Duplex   %u\n", yam_ports[i].dupmode);
+		len += sprintf(buffer + len, "  HoldDly  %u\n", yam_ports[i].holdd);
+		len += sprintf(buffer + len, "  TxDelay  %u\n", yam_ports[i].txd);
+		len += sprintf(buffer + len, "  TxTail   %u\n", yam_ports[i].txtail);
+		len += sprintf(buffer + len, "  SlotTime %u\n", yam_ports[i].slot);
+		len += sprintf(buffer + len, "  Persist  %u\n", yam_ports[i].pers);
+		len += sprintf(buffer + len, "  TxFrames %lu\n", yam_ports[i].stats.tx_packets);
+		len += sprintf(buffer + len, "  RxFrames %lu\n", yam_ports[i].stats.rx_packets);
+		len += sprintf(buffer + len, "  TxInt    %u\n", yam_ports[i].nb_mdint);
+		len += sprintf(buffer + len, "  RxInt    %u\n", yam_ports[i].nb_rxint);
+		len += sprintf(buffer + len, "  RxOver   %lu\n", yam_ports[i].stats.rx_fifo_errors);
+		len += sprintf(buffer + len, "\n");
+
+		pos = begin + len;
+
+		if (pos < offset) {
+			len = 0;
+			begin = pos;
+		}
+		if (pos > offset + length)
+			break;
+	}
+
+	sti();
+
+	*start = buffer + (offset - begin);
+	len -= (offset - begin);
+
+	if (len > length)
+		len = length;
+
+	return len;
+}
+
+#ifdef CONFIG_INET
+#ifndef PROC_NET_YAM
+#define PROC_NET_YAM (PROC_NET_LAST+10)		/* Sorry again... */
+#endif
+
+struct proc_dir_entry yam_proc_dir_entry =
+{
+	PROC_NET_YAM, 3, "yam", S_IFREG | S_IRUGO, 1, 0, 0, 0,
+	&proc_net_inode_operations, yam_net_get_info
+};
+
+#define yam_net_procfs_init()   proc_net_register(&yam_proc_dir_entry);
+#define yam_net_procfs_remove() proc_net_unregister(PROC_NET_YAM);
+#else
+#define yam_net_procfs_init()
+#define yam_net_procfs_remove()
+#endif
+
+/* --------------------------------------------------------------------- */
+
+#if LINUX_VERSION_CODE >= 0x20119
+static struct net_device_stats *
+ yam_get_stats(struct device *dev)
+#else
+static struct enet_statistics *
+ yam_get_stats(struct device *dev)
+#endif
+{
+	struct yam_port *yp;
+
+	if (!dev || !dev->priv)
+		return NULL;
+
+	yp = (struct yam_port *) dev->priv;
+	if (yp->magic != YAM_MAGIC)
+		return NULL;
+
+	/* 
+	 * Get the current statistics.  This may be called with the
+	 * card open or closed. 
+	 */
+	return &yp->stats;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int yam_open(struct device *dev)
+{
+	struct yam_port *yp = (struct yam_port *) dev->priv;
+	enum uart u;
+	int i;
+
+	printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq);
+
+	if (!dev || !yp || !yp->bitrate)
+		return -ENXIO;
+	if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT ||
+		dev->irq < 2 || dev->irq > 15) {
+		return -ENXIO;
+	}
+	if (check_region(dev->base_addr, YAM_EXTENT)) {
+		printk("%s: cannot 0x%lx busy\n", dev->name, dev->base_addr);
+		return -EACCES;
+	}
+	if ((u = yam_check_uart(dev->base_addr)) == c_uart_unknown) {
+		printk("%s: cannot find uart type\n", dev->name);
+		return -EIO;
+	}
+	if (fpga_download(dev->base_addr, yp->bitrate)) {
+		printk("%s: cannot init FPGA\n", dev->name);
+		return -EIO;
+	}
+	outb(0, IER(dev->base_addr));
+	if (request_irq(dev->irq, yam_interrupt, SA_INTERRUPT | SA_SHIRQ, dev->name, NULL)) {
+		printk("%s: irq %d busy\n", dev->name, dev->irq);
+		return -EBUSY;
+	}
+	request_region(dev->base_addr, YAM_EXTENT, dev->name);
+
+	yam_set_uart(dev);
+	dev->start = 1;
+	yp->slotcnt = yp->slot / 10;
+
+	/* Reset overruns for all ports - FPGA programming makes overruns */
+	for (i = 0; i < NR_PORTS; i++) {
+		inb(LSR(yam_ports[i].dev.base_addr));
+		yam_ports[i].stats.rx_fifo_errors = 0;
+	}
+
+	printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq,
+		   uart_str[u]);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int yam_close(struct device *dev)
+{
+	struct sk_buff *skb;
+	struct yam_port *yp = (struct yam_port *) dev->priv;
+
+	if (!dev || !yp)
+		return -EINVAL;
+	/*
+	 * disable interrupts
+	 */
+	outb(0, IER(dev->base_addr));
+	outb(1, MCR(dev->base_addr));
+	/* Remove IRQ handler if last */
+	free_irq(dev->irq, NULL);
+	release_region(dev->base_addr, YAM_EXTENT);
+	dev->start = 0;
+	dev->tbusy = 1;
+	while ((skb = skb_dequeue(&yp->send_queue)))
+		dev_kfree_skb(skb);
+
+	printk(KERN_INFO "%s: close yam at iobase 0x%lx irq %u\n",
+		   yam_drvname, dev->base_addr, dev->irq);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int yam_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+	struct yam_port *yp = (struct yam_port *) dev->priv;
+	struct yamdrv_ioctl_cfg yi;
+	struct yamdrv_ioctl_mcs *ym;
+	int ioctl_cmd;
+
+	if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(int)))
+		 return -EFAULT;
+
+	if (yp == NULL || yp->magic != YAM_MAGIC)
+		return -EINVAL;
+
+	if (!suser())
+		return -EPERM;
+
+	if (cmd != SIOCDEVPRIVATE)
+		return -EINVAL;
+
+	switch (ioctl_cmd) {
+
+	case SIOCYAMRESERVED:
+		return -EINVAL;			/* unused */
+
+	case SIOCYAMSMCS:
+		if (dev->start)
+			return -EINVAL;		/* Cannot change this parameter when up */
+		ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_ATOMIC);
+		ym->bitrate = 9600;
+		if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs)))
+			 return -EFAULT;
+		if (ym->bitrate > YAM_MAXBITRATE)
+			return -EINVAL;
+		add_mcs(ym->bits, ym->bitrate);
+		kfree(ym);
+		break;
+
+	case SIOCYAMSCFG:
+		if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg)))
+			 return -EFAULT;
+
+		if ((yi.cfg.mask & YAM_IOBASE) && dev->start)
+			return -EINVAL;		/* Cannot change this parameter when up */
+		if ((yi.cfg.mask & YAM_IRQ) && dev->start)
+			return -EINVAL;		/* Cannot change this parameter when up */
+		if ((yi.cfg.mask & YAM_BITRATE) && dev->start)
+			return -EINVAL;		/* Cannot change this parameter when up */
+		if ((yi.cfg.mask & YAM_BAUDRATE) && dev->start)
+			return -EINVAL;		/* Cannot change this parameter when up */
+
+		if (yi.cfg.mask & YAM_IOBASE) {
+			yp->iobase = yi.cfg.iobase;
+			dev->base_addr = yi.cfg.iobase;
+		}
+		if (yi.cfg.mask & YAM_IRQ) {
+			if (yi.cfg.irq > 15)
+				return -EINVAL;
+			yp->irq = yi.cfg.irq;
+			dev->irq = yi.cfg.irq;
+		}
+		if (yi.cfg.mask & YAM_BITRATE) {
+			if (yi.cfg.bitrate > YAM_MAXBITRATE)
+				return -EINVAL;
+			yp->bitrate = yi.cfg.bitrate;
+		}
+		if (yi.cfg.mask & YAM_BAUDRATE) {
+			if (yi.cfg.baudrate > YAM_MAXBAUDRATE)
+				return -EINVAL;
+			yp->baudrate = yi.cfg.baudrate;
+		}
+		if (yi.cfg.mask & YAM_MODE) {
+			if (yi.cfg.mode > YAM_MAXMODE)
+				return -EINVAL;
+			yp->dupmode = yi.cfg.mode;
+		}
+		if (yi.cfg.mask & YAM_HOLDDLY) {
+			if (yi.cfg.holddly > YAM_MAXHOLDDLY)
+				return -EINVAL;
+			yp->holdd = yi.cfg.holddly;
+		}
+		if (yi.cfg.mask & YAM_TXDELAY) {
+			if (yi.cfg.txdelay > YAM_MAXTXDELAY)
+				return -EINVAL;
+			yp->txd = yi.cfg.txdelay;
+		}
+		if (yi.cfg.mask & YAM_TXTAIL) {
+			if (yi.cfg.txtail > YAM_MAXTXTAIL)
+				return -EINVAL;
+			yp->txtail = yi.cfg.txtail;
+		}
+		if (yi.cfg.mask & YAM_PERSIST) {
+			if (yi.cfg.persist > YAM_MAXPERSIST)
+				return -EINVAL;
+			yp->pers = yi.cfg.persist;
+		}
+		if (yi.cfg.mask & YAM_SLOTTIME) {
+			if (yi.cfg.slottime > YAM_MAXSLOTTIME)
+				return -EINVAL;
+			yp->slot = yi.cfg.slottime;
+			yp->slotcnt = yp->slot / 10;
+		}
+		break;
+
+	case SIOCYAMGCFG:
+		yi.cfg.mask = 0xffffffff;
+		yi.cfg.iobase = yp->iobase;
+		yi.cfg.irq = yp->irq;
+		yi.cfg.bitrate = yp->bitrate;
+		yi.cfg.baudrate = yp->baudrate;
+		yi.cfg.mode = yp->dupmode;
+		yi.cfg.txdelay = yp->txd;
+		yi.cfg.holddly = yp->holdd;
+		yi.cfg.txtail = yp->txtail;
+		yi.cfg.persist = yp->pers;
+		yi.cfg.slottime = yp->slot;
+		if (copy_to_user(ifr->ifr_data, &yi, sizeof(struct yamdrv_ioctl_cfg)))
+			 return -EFAULT;
+		break;
+
+	default:
+		return -EINVAL;
+
+	}
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int yam_set_mac_address(struct device *dev, void *addr)
+{
+	struct sockaddr *sa = (struct sockaddr *) addr;
+
+	/* addr is an AX.25 shifted ASCII mac address */
+	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int yam_probe(struct device *dev)
+{
+	struct yam_port *yp;
+
+	if (!dev)
+		return -ENXIO;
+
+	yp = (struct yam_port *) dev->priv;
+
+	dev->open = yam_open;
+	dev->stop = yam_close;
+	dev->do_ioctl = yam_ioctl;
+	dev->hard_start_xmit = yam_send_packet;
+	dev->get_stats = yam_get_stats;
+
+	dev_init_buffers(dev);
+	skb_queue_head_init(&yp->send_queue);
+
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+	dev->hard_header = ax25_encapsulate;
+	dev->rebuild_header = ax25_rebuild_header;
+#else							/* CONFIG_AX25 || CONFIG_AX25_MODULE */
+	dev->hard_header = NULL;
+	dev->rebuild_header = NULL;
+#endif							/* CONFIG_AX25 || CONFIG_AX25_MODULE */
+
+	dev->set_mac_address = yam_set_mac_address;
+
+	dev->type = ARPHRD_AX25;	/* AF_AX25 device */
+	dev->hard_header_len = 73;	/* We do digipeaters now */
+	dev->mtu = 256;				/* AX25 is the default */
+	dev->addr_len = 7;			/* sizeof an ax.25 address */
+	memcpy(dev->broadcast, ax25_bcast, 7);
+	memcpy(dev->dev_addr, ax25_test, 7);
+
+	/* New style flags */
+	dev->flags = 0;
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+__initfunc(int yam_init(struct device *dev))
+{
+	int i;
+
+	printk(yam_drvinfo);
+
+	/* Clears the IRQ table */
+	memset(irqs, 0, sizeof(irqs));
+	memset(yam_ports, 0, sizeof(yam_ports));
+
+	for (i = 0; i < NR_PORTS; i++) {
+		sprintf(yam_ports[i].name, "yam%d", i);
+		yam_ports[i].magic = YAM_MAGIC;
+		yam_ports[i].bitrate = DEFAULT_BITRATE;
+		yam_ports[i].baudrate = DEFAULT_BITRATE * 2;
+		yam_ports[i].iobase = 0;
+		yam_ports[i].irq = 0;
+		yam_ports[i].dupmode = 0;
+		yam_ports[i].holdd = DEFAULT_HOLDD;
+		yam_ports[i].txd = DEFAULT_TXD;
+		yam_ports[i].txtail = DEFAULT_TXTAIL;
+		yam_ports[i].slot = DEFAULT_SLOT;
+		yam_ports[i].pers = DEFAULT_PERS;
+
+		dev = &yam_ports[i].dev;
+
+		dev->priv = &yam_ports[i];
+		dev->name = yam_ports[i].name;
+		dev->base_addr = yam_ports[i].iobase;
+		dev->irq = yam_ports[i].irq;
+		dev->init = yam_probe;
+		dev->if_port = 0;
+		dev->start = 0;
+		dev->tbusy = 1;
+
+		if (register_netdev(dev)) {
+			printk(KERN_WARNING "yam: cannot register net  device %s\n", dev->name);
+			return -ENXIO;
+		}
+	}
+
+	yam_timer.function = yam_dotimer;
+	yam_timer.expires = jiffies + HZ / 100;
+	add_timer(&yam_timer);
+
+	yam_net_procfs_init();
+
+	/* do not keep this device */
+	return 1;
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+
+/*
+ * command line settable parameters
+ */
+
+#if LINUX_VERSION_CODE >= 0x20115
+
+MODULE_AUTHOR("Frederic Rible F1OAT frible@teaser.fr");
+MODULE_DESCRIPTION("Yam amateur radio modem driver");
+
+#endif
+
+__initfunc(int init_module(void))
+{
+	int ret = yam_init(NULL);
+
+	return (ret == 1) ? 0 : ret;
+}
+
+/* --------------------------------------------------------------------- */
+
+void cleanup_module(void)
+{
+	int i;
+
+	del_timer(&yam_timer);
+	for (i = 0; i < NR_PORTS; i++) {
+		struct device *dev = &yam_ports[i].dev;
+		if (!dev->priv)
+			continue;
+		if (dev->start)
+			yam_close(dev);
+		unregister_netdev(dev);
+	}
+	free_mcs();
+	yam_net_procfs_remove();
+}
+
+#endif							/* MODULE */
+/* --------------------------------------------------------------------- */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/yam1200.h linux.pre11.3/drivers/net/hamradio/yam1200.h
--- linux.vanilla/drivers/net/hamradio/yam1200.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/hamradio/yam1200.h	Tue Jul 20 00:29:25 1999
@@ -0,0 +1,343 @@
+/*
+ *
+ * File yam1k2b5.mcs converted to h format by mcs2h
+ *
+ * (C) F6FBB 1998
+ *
+ * Tue Aug 25 20:24:08 1998
+ *
+ */
+
+static unsigned char bits_1200[]= {
+0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xf3,0xcb,0xff,0xdb,0xfc,0xf2,
+0xff,0xf6,0xff,0x3c,0xbf,0xfd,0xbf,0xdf,0x6e,0x3f,0x6f,0xf1,0x7d,0xb4,0xfd,0xbf,
+0xdf,0x6f,0x3f,0x6f,0xf7,0x0b,0xff,0xdb,0xfd,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff,
+0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xef,0xff,0xff,0xff,
+0xfd,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xbf,
+0xff,0xff,0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfc,0xff,0xfe,0xff,0xff,0xff,0xf0,
+0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xf1,0xff,0xff,0xfe,0x7f,0xbf,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xff,0xff,0xf0,0x9f,
+0xff,0xff,0xff,0xfe,0xff,0xfd,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xff,
+0xff,0xff,0xfb,0xff,0xfb,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xf7,0xff,0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xf0,0x5f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xbf,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xfb,0xfe,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,
+0xff,0xff,0xff,0xfd,0xff,0xbf,0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xfb,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff,
+0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xf7,0xff,0xff,0xf1,0xff,0xff,0xf7,0xbf,0xe7,0xff,0xff,0xff,0xff,0xfb,
+0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdb,
+0xff,0xff,0xf5,0xa5,0xfd,0x4b,0x6e,0xef,0x33,0x32,0xdd,0xd3,0x4a,0xd6,0x92,0xfe,
+0xb3,0x3f,0xbd,0xf1,0xfa,0xdb,0xfe,0xf7,0xf6,0x96,0xbd,0xbd,0xff,0xbd,0xff,0xed,
+0x7f,0x6b,0x7f,0xfb,0xdf,0xfe,0xfb,0xfe,0x90,0xcf,0xff,0xff,0xff,0xfe,0xbe,0xef,
+0xff,0xff,0xdb,0x5f,0xf6,0xff,0xf6,0x8f,0xfd,0xa5,0xdd,0xff,0xff,0xff,0xff,0x6f,
+0x7f,0xdb,0xf1,0xfc,0xbf,0xff,0x6f,0xff,0xef,0xfc,0x5b,0x5d,0xda,0xdf,0xf4,0xff,
+0xf2,0xff,0xfd,0xbf,0xff,0xff,0xff,0xd0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
+0xff,0xfb,0xef,0xb7,0xfc,0x33,0xff,0xfb,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0,
+0x0f,0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x72,0x0f,0xf1,0x6f,0xff,0xfe,0x94,0x3f,
+0xff,0xff,0xff,0x7b,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf0,
+0xf7,0xef,0xb7,0xfc,0x33,0xff,0xff,0xff,0x04,0x6a,0xf3,0x3c,0x36,0xff,0xf0,0x0f,
+0xf1,0x0f,0xff,0xff,0xff,0xf3,0x15,0x73,0x8f,0xf2,0x6f,0xff,0xfe,0x94,0x3f,0xff,
+0xff,0xff,0x7d,0x9f,0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x9e,
+0xff,0xfc,0xef,0xd3,0xfb,0xff,0x7f,0xf5,0x5f,0xfe,0x59,0xff,0xff,0xff,0xfc,0xf1,
+0xfe,0x7f,0xff,0xff,0xfa,0x17,0xff,0xe7,0xef,0xef,0xff,0xff,0x3f,0xf1,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xfc,0xea,
+0xff,0xf0,0xff,0xff,0xbf,0xf9,0x3f,0xb1,0xef,0xff,0xd7,0xff,0xfb,0xff,0xf0,0xff,
+0xff,0xf3,0xff,0xdf,0xff,0x7b,0xff,0xfd,0xff,0xf6,0xff,0xbf,0xff,0xff,0xbf,0xff,
+0xff,0xff,0xda,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x01,0x00,0x00,0x02,0x02,
+0x02,0x02,0x00,0x40,0x40,0x40,0x10,0x00,0x00,0x00,0x20,0x00,0x00,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x19,0x00,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
+0x00,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfb,0xff,0xfd,0xff,
+0xff,0x7f,0xff,0xff,0xbf,0xff,0xef,0xff,0xff,0xfd,0xff,0xff,0xf1,0xff,0xdf,0xff,
+0xff,0xff,0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xdf,
+0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xdf,0xff,0x7f,0xff,0xff,0xff,0xff,
+0xdf,0xdf,0xff,0xef,0xff,0x9e,0xef,0xff,0xff,0x7f,0xff,0xf1,0xef,0xff,0xff,0xff,
+0xf7,0xfa,0xbf,0xff,0xff,0xfe,0x47,0xef,0xff,0xbd,0xf6,0xff,0xff,0xdf,0xf5,0xf0,
+0xf0,0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x01,0x02,0x08,
+0x16,0x00,0x00,0x00,0x80,0x00,0x01,0x02,0x00,0x80,0x01,0x0c,0x02,0x00,0x00,0x01,
+0x00,0x00,0x20,0x00,0x00,0x06,0x00,0x20,0x00,0x10,0x00,0x14,0x00,0x04,0xc1,0xf0,
+0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f,
+0xec,0xff,0xff,0xfa,0xff,0xbf,0xff,0x6f,0xff,0xe1,0xff,0xff,0xff,0xff,0xbd,0xfe,
+0x46,0xff,0xef,0x7f,0xcd,0xdf,0xff,0xff,0xfd,0xff,0xbd,0xff,0x7f,0x7f,0xf0,0x4f,
+0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa4,0xbc,0xcd,0x6d,0x6b,0x6f,0x5b,0xdc,0x33,
+0x5a,0xf6,0xf7,0xf6,0xb3,0x3f,0xbd,0xc1,0xfa,0x5a,0xf6,0xf6,0xb6,0xf7,0xff,0xbd,
+0xbb,0x3c,0xce,0xcf,0x34,0xef,0x33,0xbb,0xcc,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,
+0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xd6,0xff,0xfd,0xfd,0xbf,0xff,0xad,
+0xbf,0xf9,0x7f,0x6f,0xfc,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0xff,0xda,0xdb,0xfc,
+0xdb,0xff,0x76,0x8f,0xf6,0xff,0xcd,0xab,0xfe,0xfb,0xff,0xd0,0xff,0xff,0xff,0xff,
+0xfe,0xff,0x9f,0xff,0xf4,0x20,0xaf,0x6d,0x0b,0xc1,0x7b,0xff,0xff,0xff,0xcb,0xff,
+0x3f,0xf0,0xef,0x7f,0x0f,0xf1,0xc3,0x3c,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x0b,
+0x1d,0x6a,0x64,0x05,0x6b,0x99,0x01,0xff,0xfd,0xef,0xf0,0x2f,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xf4,0x00,0x2f,0xcc,0x0b,0xc3,0x7f,0xff,0xff,0xff,0x0a,0xdf,0xbf,
+0xfd,0x7f,0xff,0xff,0xf1,0xc3,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x4a,0x0e,
+0x96,0x64,0x02,0x97,0x99,0x10,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xfe,0x84,0xf9,0xd5,0x27,0xf1,0x7f,0xff,0xf8,0xeb,0xdf,0xf3,0xcf,0x3f,
+0x1f,0xff,0xf7,0x11,0xff,0xcf,0xff,0xfe,0x67,0xff,0xff,0xff,0xff,0xc4,0xff,0xff,
+0xb3,0xa1,0xff,0xf9,0xe0,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff,
+0xff,0xfb,0x7f,0xe0,0xff,0xc7,0xfe,0x7f,0x3f,0xff,0xfd,0x77,0x8d,0x7f,0x0f,0xff,
+0xc3,0xff,0xf1,0xbf,0x8f,0xcf,0xff,0xff,0xdd,0x7b,0xff,0xf6,0xfa,0xf7,0xff,0x40,
+0x9f,0xf9,0x7f,0xd8,0xff,0xff,0xfa,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,
+0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x10,0x00,0x00,0x10,
+0x00,0x01,0x00,0x10,0x20,0x20,0x00,0x00,0x10,0x00,0x04,0x01,0x05,0x00,0x00,0x00,
+0x00,0x40,0x40,0x00,0x00,0x3c,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,
+0xff,0xff,0xfe,0x7f,0x7f,0xff,0xef,0xff,0xff,0xdf,0xff,0xff,0xdf,0xff,0xef,0xf7,
+0xf1,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xfc,0xfd,0xff,0x7f,
+0x7e,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0xff,0xff,
+0xff,0xff,0xfe,0xeb,0xfd,0x6f,0xff,0xf7,0xfe,0xf5,0x7f,0xff,0xff,0x7f,0xbf,0xb1,
+0xff,0xff,0x9f,0xbf,0xfb,0xff,0xfe,0xff,0xfe,0xff,0xf7,0xeb,0xdf,0xbf,0x5f,0xdd,
+0xff,0xdb,0xfd,0xd0,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x00,0x42,0x00,
+0x00,0x00,0x30,0x18,0x04,0x08,0x09,0x21,0x82,0x80,0x02,0x00,0x08,0x00,0x01,0x00,
+0x00,0x00,0x0c,0x20,0x10,0x00,0x11,0x00,0x44,0x84,0x00,0x20,0x20,0x84,0x80,0x00,
+0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xf7,0xff,0xfb,0xdd,0xf9,0xff,
+0xda,0xff,0xdc,0xdd,0xfc,0xfb,0xff,0xbf,0xfb,0x3e,0xd7,0x96,0xfe,0x61,0xf7,0xff,
+0x7f,0xff,0x3f,0xfd,0xff,0xdf,0xcf,0xf7,0xdf,0xf7,0xbf,0xfd,0xff,0xfe,0xef,0xef,
+0xfe,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf3,0xbd,0xfd,0x4b,0x74,0xcf,
+0x73,0x5b,0xcb,0x3b,0xdf,0xfe,0xf7,0xfe,0xd3,0x75,0xac,0xa1,0xfb,0xdf,0xfe,0xf7,
+0x76,0x96,0xb5,0x24,0xbd,0xa5,0xad,0x49,0x2f,0x69,0x2b,0x52,0x5b,0xbd,0xff,0xff,
+0xf0,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0xff,0xcc,
+0xa7,0xfb,0xad,0xff,0x7f,0x6f,0xff,0x6d,0x7f,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,
+0x6f,0xff,0xdb,0xff,0xdb,0xff,0xf6,0x97,0xf6,0xff,0xb5,0xb5,0xff,0xff,0xff,0xd0,
+0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xa5,0xbc,0x43,0xfc,0x7c,0x03,0xe7,
+0xff,0xff,0x20,0xff,0xff,0xff,0xcc,0xfd,0x7d,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59,
+0xba,0x56,0x66,0x6a,0xad,0x9a,0xa9,0x9a,0x97,0xa5,0xaa,0xbb,0xff,0xff,0xf0,0x0f,
+0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xfd,0xf7,0xfd,0x43,0xff,0xfd,0x6b,0xe7,0xff,
+0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0x3f,0xf1,0xff,0xff,0xff,0xff,0xd5,0x59,0xb5,
+0xa6,0x66,0x6a,0xad,0x9a,0xa9,0x99,0x6b,0x5a,0xaa,0xff,0xff,0xb7,0xf0,0x3f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x9c,0xf7,0xfd,0xd2,0x41,0xff,0xff,0xf2,0x7f,
+0x8f,0xff,0xff,0x3d,0xf3,0xff,0x17,0xf1,0xff,0xff,0xff,0xff,0xff,0x7f,0xdf,0xfc,
+0x8f,0x38,0xff,0xef,0x23,0xff,0xfb,0xf7,0xc8,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,
+0xff,0xfe,0xf5,0x7f,0xff,0xfd,0xff,0xe4,0xff,0xeb,0xff,0xcf,0xbf,0xfa,0xff,0xab,
+0xef,0xff,0xfb,0xff,0xf3,0xfd,0x61,0xff,0xff,0xff,0xff,0xfa,0xff,0xfb,0xfd,0x0d,
+0xff,0xfe,0xff,0x43,0x7f,0xfe,0xbf,0xd0,0xfd,0xff,0xfa,0xf0,0x3f,0xff,0xff,0xff,
+0xfe,0xf3,0xc0,0x00,0x00,0x00,0x02,0x00,0x02,0x01,0x00,0x60,0xc0,0x40,0x00,0x00,
+0x00,0x00,0x34,0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x88,0x00,
+0x00,0x03,0x00,0x00,0x40,0x00,0x40,0x00,0x00,0x3c,0xf0,0x3f,0xff,0xff,0xff,0xfe,
+0xfd,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfd,0xff,
+0xff,0xff,0xff,0xfe,0xfe,0x5f,0xff,0xff,0xcb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0,
+0xff,0xff,0xfd,0xff,0xef,0xe3,0xde,0xee,0xd9,0xc5,0x93,0xff,0xff,0xfe,0xfe,0xff,
+0xfb,0xee,0xfe,0xf1,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xbf,0xf7,0xff,0xff,0x7f,
+0xaf,0xbd,0xdf,0xdf,0xfb,0xf3,0xf3,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x34,
+0x00,0x06,0x61,0x00,0x18,0x01,0xa0,0x05,0x17,0x00,0x20,0x05,0x28,0x20,0x00,0x00,
+0x05,0x00,0x41,0x00,0x00,0x40,0x00,0x09,0x00,0x01,0x20,0x86,0x82,0x08,0x40,0x03,
+0x80,0x30,0x70,0x08,0x14,0x02,0xc1,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
+0xff,0xff,0xbd,0xef,0xfb,0xff,0xff,0xfb,0x9c,0x7f,0xef,0xdf,0xff,0xbf,0xeb,0xde,
+0xff,0xc1,0x7f,0xff,0xfb,0x7f,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xdf,0xbf,0xef,
+0x3f,0xf7,0x8f,0xef,0x7f,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbd,
+0xdf,0xef,0x7d,0x6d,0x2b,0x5a,0x5d,0xd2,0xdf,0xf6,0x92,0xb6,0xb2,0xb3,0xac,0xa1,
+0xfb,0xdf,0xfe,0xf1,0xee,0xf5,0xf6,0xbc,0x6b,0xbd,0x7d,0xaf,0x1a,0xef,0x5f,0x6b,
+0xc6,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,
+0xf6,0xff,0xf6,0xb7,0xfd,0xad,0xfd,0xbf,0xf3,0x6f,0xff,0x6f,0xff,0xdb,0xd1,0xfd,
+0xbf,0xff,0x6f,0xf5,0x6b,0xbc,0x5b,0x3c,0xda,0xef,0x16,0xaf,0x16,0xff,0xcd,0xab,
+0xff,0x6f,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfc,0xbf,0xff,0xff,
+0xff,0x6c,0x03,0x10,0xc1,0xf3,0xff,0xf3,0x3a,0xf3,0xca,0xff,0xaf,0xf1,0xff,0xff,
+0xff,0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff,
+0xff,0x5f,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,
+0xea,0x0f,0x50,0xc3,0xf3,0x7f,0xff,0xf3,0xf3,0xc3,0xff,0xaf,0xf1,0xff,0xff,0xff,
+0xff,0xd9,0x96,0xa6,0x65,0xa6,0x66,0x6a,0x95,0x69,0x69,0x6a,0x5a,0x5a,0xff,0xff,
+0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xd7,0xff,0xff,0x5f,0xc1,
+0x3f,0xf7,0x5e,0xf5,0xce,0x9e,0x5f,0x3f,0x17,0xff,0xf3,0xe1,0xff,0xff,0xff,0xff,
+0xd8,0xff,0xfa,0xfe,0x67,0xff,0xfe,0xbf,0x5a,0xff,0xff,0xaf,0xf5,0xff,0xff,0xff,
+0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfd,0xff,0xf7,0xff,0xfd,0x4e,0x3d,
+0x3f,0xe7,0x0b,0xbf,0x8f,0xf9,0xff,0xeb,0xe3,0xff,0xe1,0xff,0xff,0xfc,0xff,0xc7,
+0x9f,0xff,0x3e,0x39,0xe5,0xff,0xcf,0x9b,0xf9,0xff,0xff,0xc5,0xff,0xff,0xfa,0xf0,
+0x5f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,
+0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x20,0x00,0x20,
+0x00,0x01,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0xf0,0x4f,
+0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xbf,
+0x3f,0xff,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf1,0xff,0xff,0xff,0xff,0xf7,0xff,0xf7,
+0xff,0xed,0xff,0xfb,0xfe,0xff,0x7f,0xff,0x7f,0xdf,0xff,0xff,0xdd,0xf0,0x3f,0xff,
+0xff,0xff,0xfe,0xf0,0xff,0xff,0xf3,0xff,0xf7,0xff,0xfe,0x5f,0xff,0xf7,0xff,0xff,
+0xdf,0xff,0xff,0xff,0xf7,0xfe,0x7b,0xf1,0xff,0xfd,0xfd,0xff,0xdf,0xdf,0xff,0x7d,
+0x73,0xf9,0xff,0xc3,0x7e,0xfe,0xff,0xef,0xd7,0xff,0xcf,0xd0,0xf0,0x6f,0xff,0xff,
+0xff,0xfe,0xf8,0x30,0x00,0x00,0x40,0x04,0x00,0x01,0x41,0x20,0x00,0x04,0x00,0x02,
+0xd5,0x09,0x00,0x02,0x80,0x02,0x01,0x00,0x00,0x00,0x0a,0x04,0x00,0x07,0x00,0x01,
+0x50,0x01,0x80,0x02,0x61,0x40,0x41,0x0c,0x14,0x08,0xc1,0xf0,0x9f,0xff,0xff,0xff,
+0xfe,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0xdf,0xcb,0x5f,0xfe,0xef,0xff,0xfe,
+0xff,0x3f,0xff,0x7f,0xfd,0xc1,0xff,0xff,0x7f,0xff,0xdf,0xfd,0xfc,0xfd,0xf7,0xee,
+0xff,0xff,0x4e,0xff,0xdf,0xcf,0xdb,0xeb,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0x7f,
+0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,
+0xf7,0xfb,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0x7f,0xff,0xff,0xff,0x7f,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xdd,0xff,
+0xff,0xff,0xa5,0xff,0x6f,0x6b,0xe9,0x6f,0xda,0xca,0xfb,0xdd,0xee,0xf7,0xf6,0xb2,
+0xb3,0xa4,0xa1,0x5b,0x5b,0xf6,0xd7,0xf4,0xf7,0x7b,0xbd,0xbd,0xad,0xcf,0xef,0x7f,
+0x6b,0x7f,0x3b,0xdf,0xdb,0xff,0xff,0x30,0xcf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,
+0xff,0xff,0xff,0xf6,0xfe,0x96,0xff,0xfd,0xb5,0xfd,0xbf,0xad,0x7f,0xff,0x6f,0xff,
+0xde,0xd1,0xad,0xad,0xe9,0xff,0xf1,0xec,0xef,0xde,0x3f,0xcb,0xff,0xf6,0xff,0x32,
+0xff,0xc5,0xbd,0xff,0xff,0xff,0xd0,0xbf,0xff,0xff,0xff,0xfe,0xfe,0xfb,0xff,0xf4,
+0x28,0xbf,0xff,0xfd,0xfb,0xd3,0xff,0xff,0x42,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3,
+0xc1,0xff,0x33,0xff,0xc0,0x15,0x6b,0x70,0xff,0xf0,0xf2,0x4f,0xff,0xfc,0x3e,0x97,
+0x3c,0xff,0xff,0xfd,0xef,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfe,0x78,
+0xbf,0xff,0xfd,0xf3,0xef,0x55,0xff,0x7e,0xff,0xff,0xff,0xea,0xb3,0xfc,0xc3,0xc1,
+0xff,0x33,0xff,0xc0,0x15,0x6f,0xff,0x0f,0xf0,0xf0,0x0f,0xff,0xfc,0x3d,0x6b,0xc3,
+0xff,0xff,0xfe,0xf7,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,
+0xff,0x23,0xf8,0x7f,0xff,0x4e,0xff,0xff,0xff,0xfb,0xf9,0x17,0xff,0xf6,0xf1,0xff,
+0xcf,0xef,0xff,0xff,0x13,0xdf,0xe6,0x2f,0xc7,0xff,0xff,0xe7,0xc1,0xfd,0xff,0xfe,
+0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xfe,0xae,0xff,
+0xff,0x7f,0x3b,0x3f,0xfc,0x7f,0xfc,0xef,0xff,0xfc,0xe2,0x7b,0xff,0xf1,0xfd,0xed,
+0xef,0xff,0xff,0x35,0x73,0xff,0xff,0xfe,0xfa,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,
+0xff,0xfa,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x00,0x0c,0x04,0x01,0x40,0x40,0x00,
+0x00,0x30,0x28,0x04,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,
+0x38,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xfb,0xff,0x7f,
+0xff,0xff,0x9f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xdf,0xdf,0xff,
+0xff,0xff,0xff,0xed,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xbf,0xbf,0xff,0xff,0xc3,
+0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xbf,0xfd,0xff,0xbf,0xff,0xff,0xfd,0xff,0xff,
+0xff,0xff,0xff,0xfd,0x7b,0xff,0x7f,0xff,0xbd,0xff,0xf1,0xef,0xff,0xff,0xfd,0xdf,
+0xfd,0xfb,0xff,0xff,0xbf,0xbe,0xff,0xcd,0x7f,0xfc,0xf7,0xf7,0x6f,0xbf,0xd8,0xf0,
+0xef,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,0x00,0x00,0x04,0x00,0x00,0xa0,0x00,0x00,
+0xc0,0x00,0x00,0x20,0x34,0x00,0x00,0x00,0x0c,0x81,0x00,0x20,0xa4,0x20,0x00,0x10,
+0x08,0x04,0x48,0x08,0x00,0x40,0x93,0x00,0x10,0x00,0x38,0x18,0x20,0xc1,0xf0,0x3f,
+0xff,0xff,0xff,0xfe,0xff,0xfb,0xff,0xff,0xb9,0xdf,0xfe,0xb3,0xff,0xff,0xe7,0xfd,
+0xff,0xff,0x3b,0xff,0x7f,0xff,0xbf,0xff,0xc1,0xff,0xfc,0xff,0xff,0x3f,0x77,0xfe,
+0xfe,0xcf,0xff,0xbf,0xfd,0xbf,0xff,0xfe,0xed,0xf2,0xfd,0xf7,0xff,0xf0,0x2f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xf3,0xad,0xcf,0xef,0x70,0xc9,0x73,0x3b,0xdf,0x5b,0x4a,
+0xf6,0xb7,0xfe,0xd7,0xf5,0xbc,0xc1,0x33,0xca,0xd6,0xb7,0x6e,0xf7,0xfb,0xbd,0xc5,
+0x24,0xcf,0x6f,0x2f,0x4d,0x2b,0xba,0x5a,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,
+0xfe,0xbf,0xff,0xff,0xff,0xff,0xf6,0xf6,0xd7,0xff,0xff,0xad,0xbd,0xff,0xff,0xff,
+0xef,0xf7,0x7f,0xfc,0x5b,0xb1,0xfd,0xbd,0x75,0x6f,0xef,0x6a,0xfd,0x5b,0xfb,0xdb,
+0x3a,0xbf,0x8e,0x9f,0xff,0xbf,0xfd,0xff,0x6f,0xff,0xd0,0x6f,0xff,0xff,0xff,0xfe,
+0xff,0xbb,0xff,0xf0,0x3f,0xff,0xff,0xfd,0xfb,0x7f,0xde,0xff,0xff,0x5a,0xd6,0xbf,
+0xd8,0x2a,0xbf,0xbf,0xf1,0xe5,0xff,0xcc,0xc0,0xa9,0x70,0xff,0xf3,0x3c,0x3c,0xfd,
+0x57,0xfd,0x98,0x03,0x00,0xc3,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xff,0x3d,0xbf,0xff,0xfd,0xfb,0xff,0xdb,0xff,0xff,0x0f,0xfc,0x3f,0xd8,
+0x2a,0xbf,0xbf,0xf1,0xef,0xff,0xcc,0xc0,0x96,0xbe,0xff,0xf3,0x3f,0xff,0xfd,0x57,
+0xfd,0x99,0x0f,0xff,0xc3,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xff,0xff,
+0xff,0xf1,0xe7,0xff,0xff,0xf3,0x8e,0x7b,0xff,0xa8,0xff,0xdf,0x7f,0x8e,0x78,0x73,
+0xff,0xf1,0x51,0x62,0xff,0xfc,0x4b,0xff,0xf3,0xff,0x7e,0xcf,0xf9,0xff,0xfd,0xff,
+0xff,0x7f,0xff,0xe0,0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,
+0xfb,0xfd,0xae,0xff,0xfc,0xfe,0x6f,0x3f,0xf8,0xfd,0x77,0xaf,0xfe,0x37,0xfe,0x7b,
+0xff,0xb1,0x8c,0xff,0xef,0xfd,0xf8,0xe7,0xbf,0xff,0xf1,0xfe,0x3e,0xf7,0xfe,0x95,
+0x3e,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,0x00,
+0x01,0x04,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x08,
+0x41,0x80,0x10,0x00,0x00,0x08,0x10,0x84,0x00,0x0c,0x04,0x02,0x61,0x00,0x00,0x81,
+0x00,0x00,0x00,0x00,0x3d,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,
+0xff,0xff,0x7f,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
+0x7f,0xbf,0xf7,0x7f,0xef,0xff,0xef,0xff,0xf7,0xfd,0xff,0xff,0xfd,0x7f,0xff,0xbe,
+0xdf,0xff,0xff,0xd9,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xff,0x7f,0xfb,0xff,
+0xfb,0xff,0xbf,0xff,0xf3,0x7f,0xfb,0xfd,0xeb,0x7f,0xdf,0xfa,0xff,0xde,0xf0,0xed,
+0xff,0xb1,0xf7,0xf9,0x1f,0xb5,0x5b,0xfe,0x7e,0xf7,0xbe,0xfd,0x7f,0x5f,0xb5,0xf7,
+0xff,0xff,0xd0,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x01,0x00,0x07,0x42,0x01,
+0x00,0x6a,0x18,0x50,0x80,0x00,0x00,0x02,0x40,0x01,0x01,0x20,0x01,0x01,0x24,0x14,
+0x21,0x10,0x02,0x08,0x07,0x08,0x00,0x40,0x10,0x80,0x58,0x00,0x84,0x80,0x18,0x10,
+0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xff,0xdb,0xb7,0xf3,
+0xdf,0x7c,0xf8,0x74,0xff,0xff,0x6f,0x7d,0x3f,0x7e,0xec,0x7f,0xc1,0xf5,0xff,0xcf,
+0x6f,0x9f,0xf9,0xdf,0xbe,0xe5,0xe7,0xff,0xd7,0xf3,0xdd,0xfb,0xff,0xfc,0xff,0xbf,
+0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xf0,0x2f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xff,0xb4,0xcf,0xef,0x77,0x6f,0x73,
+0x3a,0x4a,0x3a,0xcb,0xd4,0xf7,0x2e,0xd6,0xbd,0xbd,0xa1,0x3b,0xdf,0xd6,0xf7,0xee,
+0xd3,0x35,0xbd,0xfb,0xbd,0xce,0xeb,0x2b,0x4d,0x2f,0xbb,0xda,0xff,0xff,0xfe,0xb0,
+0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdf,0x5f,0x36,0xaf,0x3f,0xed,0xb7,
+0xf5,0xfd,0xf3,0x2b,0xef,0x77,0xff,0xfb,0xda,0xb1,0xbd,0xa3,0x77,0x69,0x7f,0x4f,
+0xff,0xdb,0xfa,0x5b,0xff,0xf2,0xfe,0xff,0x96,0xff,0xff,0xfe,0xdf,0xff,0xd0,0xaf,
+0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x8f,0xfd,0x40,0x6f,0x9e,0x83,0x5a,0x0f,
+0xfa,0xc3,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xd0,0x00,0xfe,0xbf,0xcd,0x3f,0xf0,
+0xef,0xfc,0xc5,0x0c,0x3f,0xfd,0x68,0x0b,0xff,0xff,0xff,0xfe,0xdf,0xf0,0xff,0xff,
+0xff,0xff,0xfe,0xff,0xbb,0xff,0xfd,0x85,0xff,0xd4,0x6f,0x9f,0xc3,0x5a,0x0f,0xff,
+0xff,0xff,0xff,0xfc,0xe9,0x7f,0xf3,0x01,0xf0,0xfb,0xc2,0xbf,0xfc,0x00,0x37,0xef,
+0xfc,0xcd,0xbc,0x3f,0xff,0x0c,0xbf,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xff,0xd9,0xf7,0xd1,0xb7,0x7e,0x7f,0xf1,0xe4,0xfd,0xff,
+0xfb,0xfb,0xff,0x5f,0xff,0x7f,0xb1,0xbc,0x0f,0x67,0xeb,0xb8,0x3f,0xff,0xe2,0xff,
+0xe9,0xff,0xfd,0xe3,0xff,0x3f,0x9f,0xc2,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,
+0xfe,0xf5,0x7f,0xff,0xf0,0x3f,0xbc,0xff,0xd5,0xf5,0xce,0x3f,0xfe,0xff,0xfe,0x6d,
+0xff,0xf1,0xbf,0x7b,0xff,0xf1,0xfd,0xff,0x4f,0xff,0x87,0xff,0xae,0xff,0xb1,0xf8,
+0xfe,0xff,0xff,0x78,0x01,0xb9,0xff,0xff,0xff,0xfa,0xf0,0x2f,0xff,0xff,0xff,0xfe,
+0xf3,0xc0,0x00,0x00,0x00,0x04,0x02,0x13,0x02,0x00,0x80,0x40,0x00,0x90,0x10,0x00,
+0x10,0x00,0x02,0x00,0x01,0x20,0x80,0x12,0x10,0x00,0x40,0x08,0x00,0x04,0x00,0x00,
+0x02,0x00,0x01,0x40,0x00,0x80,0x00,0x00,0x3c,0xf0,0xef,0xff,0xff,0xff,0xfe,0xfd,
+0x1f,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xf7,0xdf,0xf7,0xff,
+0xf7,0xfb,0xeb,0xd1,0xff,0xff,0xff,0xff,0xef,0xf7,0xff,0xff,0xfb,0xff,0xfe,0xff,
+0xff,0x7e,0xff,0xfb,0xff,0xff,0xff,0xdb,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf0,0xff,
+0xff,0xb7,0xeb,0xf7,0xdf,0xff,0xfe,0xf5,0x6b,0xe7,0xed,0xf7,0x3e,0xec,0xff,0x54,
+0xef,0x6f,0xf1,0xf5,0xaf,0x6f,0xf6,0xfd,0xff,0xdd,0x7b,0xff,0xef,0xbf,0x7f,0xff,
+0xff,0xf7,0xff,0xf3,0x5f,0xf7,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x00,
+0x80,0x40,0x04,0x00,0x81,0x2c,0x04,0x24,0x00,0x02,0x01,0xc8,0x02,0x00,0x02,0x24,
+0x00,0x01,0xb4,0x42,0xdc,0x44,0x02,0x15,0x90,0x02,0x03,0x48,0x39,0x10,0x02,0x24,
+0xa0,0xba,0x00,0x00,0x40,0xc1,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
+0xfe,0xfc,0xf7,0xf0,0xee,0xb6,0x5d,0xfd,0xf5,0xff,0xdb,0xf7,0x7f,0x7f,0xbe,0xff,
+0xc1,0xfe,0xbf,0xfa,0xfa,0x5f,0xff,0xad,0xff,0xef,0xff,0x7f,0xdf,0x7f,0xfe,0xbf,
+0xb7,0x94,0xbf,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xd7,0xff,0xff,0xfb,0xb5,0xff,
+0xef,0x7c,0xeb,0x2b,0x52,0x5b,0x3b,0xda,0xd4,0xf3,0x36,0x96,0xb5,0xbd,0xf1,0xfb,
+0xda,0xee,0xf6,0xfe,0xd3,0x35,0xbd,0xdf,0xad,0xcf,0xef,0x7e,0xcd,0x6b,0xbb,0xdf,
+0xff,0xff,0xfd,0xb0,0xef,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xd3,0x5f,0xf6,
+0xff,0xf6,0xff,0xfd,0xad,0xfd,0xff,0x7f,0xef,0xff,0x6f,0x7f,0xdb,0xf1,0xa5,0xa3,
+0x7f,0x6f,0x6b,0x4f,0xff,0xdb,0xfb,0xcb,0xff,0xf6,0xff,0xf4,0xd7,0xfd,0xbf,0xfe,
+0xdf,0xff,0xd0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdf,0xff,0xff,0xff,
+0x3f,0x7f,0xfc,0xe5,0xff,0x20,0xfe,0xff,0xff,0xdf,0x7f,0xff,0xf1,0x7f,0xff,0xfe,
+0xff,0xf0,0x7c,0x3d,0x4f,0xf3,0xc3,0x3f,0xff,0xff,0x6f,0xc3,0xff,0x0f,0xff,0xff,
+0xaf,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0xb7,0xe0,0x0f,0xff,0xff,0x2b,
+0xff,0x7d,0xbf,0xff,0xdf,0xff,0xff,0xf8,0x9f,0x7f,0xff,0xf1,0x55,0xff,0xff,0xff,
+0xfd,0x7c,0x3c,0xff,0xf3,0xc3,0x3f,0xff,0xff,0xef,0xc3,0xff,0xdf,0xff,0xff,0xff,
+0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xef,0xff,0xff,0x9f,0xbf,0x7f,
+0xf9,0x19,0x47,0x8e,0xe7,0x9f,0x3f,0x17,0xff,0xfc,0x81,0xc1,0x7e,0xf3,0xd9,0xf9,
+0x73,0xdf,0xf4,0x7f,0xfa,0xff,0xff,0xff,0xfb,0x7f,0x77,0xc7,0xff,0xff,0xff,0xf0,
+0x2f,0xff,0xff,0xff,0xfe,0xf5,0xf7,0xff,0xfb,0xff,0xf7,0x3f,0xfc,0xbf,0x3e,0x3f,
+0xec,0xff,0x81,0xaf,0xfe,0x4f,0xf3,0xbb,0xff,0xf0,0x7e,0xff,0x6f,0xff,0x87,0xff,
+0xbb,0xff,0xd5,0xfc,0xff,0x7f,0xfc,0x6f,0xff,0xef,0xe7,0xff,0xff,0xfa,0xf0,0x3f,
+0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+0x00,0x30,0x10,0x60,0x20,0x00,0x08,0x00,0x01,0x20,0x80,0x00,0x10,0x00,0x04,0x00,
+0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x40,0x00,0x08,0x20,0x3c,0xf0,0x6f,0xff,
+0xff,0xff,0xfe,0xf5,0xbf,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x3f,0xff,
+0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xf1,0xdf,0xdf,0xff,0xff,0xff,0x7f,0xdf,0xff,
+0xfd,0xbd,0xff,0xff,0xff,0xfb,0xdf,0xff,0xff,0xff,0xff,0x5b,0xf0,0xff,0xff,0xff,
+0xff,0xfe,0xf0,0xbf,0xbf,0xbf,0xff,0xf7,0xfb,0xff,0xfe,0xee,0xfa,0xff,0xff,0xff,
+0x3d,0x3b,0xff,0xff,0xfe,0xfb,0xf1,0xff,0xbf,0x7b,0xff,0xff,0xef,0xff,0xbf,0xff,
+0xff,0xff,0xff,0xff,0xfe,0xff,0xf7,0xef,0xff,0xfb,0xd0,0xf0,0xdf,0xff,0xff,0xff,
+0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x00,0x0b,0x10,0x05,0x01,0x00,0x08,0x00,0x02,
+0x01,0x01,0x00,0x00,0x10,0x01,0xc8,0x08,0x00,0x00,0x00,0x00,0x42,0x02,0x00,0x00,
+0x00,0x80,0x02,0x00,0x00,0x40,0x24,0x80,0x00,0xc1,0xf0,0x3f,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xf7,0xfd,0xf7,0xfa,0xef,0xee,0xf9,0xfd,0xff,0xf7,0xfe,0xbf,
+0x1f,0xfd,0x9e,0xfd,0xd1,0xef,0xff,0xf7,0x7f,0x9f,0xff,0xef,0xff,0xf6,0xff,0xfe,
+0xfe,0x7b,0xff,0xbd,0xff,0x7e,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xff,0xff,
+0xff,0xf7,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xdf,0xfd,0xff,0xff,0xdf,0xff,
+0xff,0x5f,0xf1,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xef,0xff,
+0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xfb,0xff,0xff,0xef,0xfb,0xfd,
+0xff,0xf1,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xf7,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xe7,0xff,
+0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xcf,0xff,0xfb,0xff,0xfb,0xf1,
+0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7b,0xff,0xff,0xff,0x7f,0xff,0xf1,0xff,
+0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xef,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0x57,0xff,0xfe,0xbf,0xfb,0xf1,0xff,0xff,
+0xfd,0xf7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xd7,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd,
+0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xef,0x2f,0xf1,0x3c,0xbf,0xbc,
+0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff,
+0x01,0xe2,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff };
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hamradio/yam9600.h linux.pre11.3/drivers/net/hamradio/yam9600.h
--- linux.vanilla/drivers/net/hamradio/yam9600.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/hamradio/yam9600.h	Tue Jul 20 00:29:25 1999
@@ -0,0 +1,343 @@
+/*
+ *
+ * File yam111.mcs converted to h format by mcs2h
+ *
+ * (C) F6FBB 1998
+ *
+ * Tue Aug 25 20:23:03 1998
+ *
+ */
+
+static unsigned char bits_9600[]= {
+0xff,0xf2,0x00,0xa5,0xad,0xff,0xfe,0x9f,0xff,0xef,0xfb,0xcb,0xff,0xdb,0xfe,0xf2,
+0xff,0xf6,0xff,0x9c,0xbf,0xfd,0xbf,0xef,0x2e,0x3f,0x6f,0xf1,0xfd,0xb4,0xfd,0xbf,
+0xff,0x6f,0xff,0x6f,0xff,0x0b,0xff,0xdb,0xff,0xf2,0xff,0xf6,0xff,0xff,0xff,0xff,
+0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xfd,0xdf,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,
+0xfb,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0x7f,0xf1,0xff,0xfe,0xff,0xbf,0xbf,
+0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xfe,0xff,0xfe,0xff,0xff,0xff,0xf0,
+0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xf7,
+0xff,0xff,0xf7,0xef,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0x7e,0xff,0xff,
+0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0xdf,
+0xff,0xff,0xff,0xfe,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xef,0xff,0xf3,0xfb,0xfe,0xff,0xf1,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xdf,0xff,0xf0,0x7f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xdf,0xff,0xff,0xff,0xf7,0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,
+0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xef,0xff,0x7f,0xff,0xef,
+0xff,0xef,0xff,0x7f,0xef,0xf1,0xff,0xef,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xff,0xbd,0xff,0xef,0x7f,0xef,0x7f,0xfb,0xdf,0xd3,0x5a,0xfe,0xd7,0xd6,
+0xf7,0x7f,0xbd,0xf1,0xbb,0x5d,0xd6,0xf7,0xfe,0x96,0xff,0xbd,0xaf,0xad,0xbf,0xef,
+0x7f,0x6b,0x7f,0xfb,0xd6,0xfe,0xf7,0xff,0x10,0xef,0xff,0xff,0xff,0xfe,0xbe,0xef,
+0xff,0xff,0xdb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xbf,0xff,0x7f,0xff,0x7f,
+0xdf,0xdb,0xf1,0xfd,0x35,0xff,0x6f,0xff,0x6f,0xff,0xdb,0xff,0xcb,0xff,0xf6,0xff,
+0xf2,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff,
+0xff,0xf1,0x24,0xf0,0xff,0xff,0xcf,0xef,0x3f,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f,
+0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x55,0xff,0xcc,0xc0,0x3f,0xff,0xff,
+0xf1,0x00,0xf0,0xff,0xff,0xcf,0xdf,0xff,0xff,0xf0,0xff,0xff,0xff,0xfc,0x3f,0xff,
+0xff,0xff,0x7d,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0x7f,0xdf,0xff,0xff,0xff,0xf1,
+0xff,0xcf,0xff,0xf3,0xff,0x97,0xff,0xff,0x8f,0xe7,0xff,0xff,0xfc,0x71,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xf5,0xff,0xbf,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xf7,0xef,0xff,0xff,0xfc,0x7b,0xff,0xf1,0x3f,
+0xff,0xef,0xff,0xcf,0xe3,0xe3,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xbf,0xff,
+0xbf,0xff,0xda,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf2,0xc0,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0x9f,0xff,
+0xff,0xff,0xf7,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xdb,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf0,0xbb,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xdf,0xbf,0xf1,0xfe,0xfd,0xf7,0xff,
+0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x77,0xfd,0xf2,
+0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
+0x00,0x00,0x00,0x02,0x00,0x90,0x00,0x00,0x00,0x0c,0x01,0x00,0x00,0x04,0x24,0x00,
+0x40,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0xc0,0xf0,
+0x4f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xbf,0xff,0xff,0x6f,0xff,0xdf,0xff,0xd1,0xff,0xfe,0xff,0xff,0xff,0xff,
+0xff,0xff,0xdf,0xff,0xfb,0xff,0xfb,0xef,0xff,0xff,0xee,0xff,0xff,0x7f,0xf0,0xdf,
+0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xad,0xff,0x69,0x2a,0xed,0x6b,0xfb,0xdf,0x3a,
+0xdc,0xf4,0x96,0xee,0xb3,0x3d,0x35,0xc1,0xbb,0xdd,0xfe,0xf6,0xfe,0xd6,0xb5,0xad,
+0xbf,0xa5,0xad,0x49,0x2f,0x4f,0x2b,0xda,0x5f,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,
+0xff,0xfe,0xbf,0xff,0xff,0xfb,0x5b,0xf7,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xa5,
+0xf3,0x6f,0xf3,0x6e,0xfa,0x7b,0xd1,0xfd,0xb5,0x77,0x6f,0xe9,0x6f,0xff,0xdb,0xfb,
+0xdb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0x3f,0xfe,0xf7,0xff,0xd0,0x4f,0xff,0xff,0xff,
+0xfe,0xff,0x9f,0xff,0xff,0x0f,0xff,0xc0,0x3f,0x9c,0x03,0xff,0xff,0x8b,0xa5,0xfe,
+0x80,0x3e,0xc2,0xbf,0xac,0xb1,0x24,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xa3,
+0xff,0xfd,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0xaf,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0x0f,0xff,0xc0,0x3f,0xd4,0x6b,0xff,0xff,0xdb,0xff,0xfe,0x86,
+0xbf,0xc2,0xbf,0x30,0xa1,0x24,0xff,0xff,0xff,0xff,0xcc,0xff,0x0f,0xff,0xa3,0xff,
+0x05,0x6b,0xff,0xff,0xf0,0xa5,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xfb,0xc7,0xff,0xc4,0xff,0xff,0x7f,0xff,0xec,0xfe,0x7f,0xdf,0xd8,0xb9,
+0x47,0xfc,0x36,0xc1,0xdf,0xff,0xff,0xf9,0xff,0xf3,0xff,0xf7,0xff,0xfc,0xff,0xfd,
+0x3f,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff,
+0xff,0xff,0xff,0xfe,0xff,0xff,0x7e,0xbd,0x3f,0xff,0x2b,0xfe,0x2f,0xf5,0xa3,0xfc,
+0x5b,0xfe,0x61,0x9f,0x7f,0xef,0xff,0xff,0xa7,0xfb,0xff,0xff,0xfa,0xfe,0xff,0x33,
+0xf1,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xf1,0xc0,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x24,0x04,
+0x00,0x01,0x00,0x80,0x40,0x00,0x08,0x00,0x00,0x00,0x02,0x01,0x01,0x00,0x02,0x00,
+0x00,0x00,0x00,0x00,0x01,0x3d,0xf0,0x2f,0xff,0xff,0xff,0xfe,0xfd,0xbd,0xff,0xfd,
+0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0x7f,0xf6,0xef,0xbf,0xf7,0xff,0x73,0xeb,
+0xf1,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xf9,0xff,0xfd,0xfe,0xff,0xff,
+0xff,0xff,0xff,0xff,0xd9,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf0,0xbf,0x7f,0xff,0xff,
+0xff,0x7f,0xff,0xff,0xde,0xff,0xff,0xef,0xdd,0xde,0x77,0xf2,0xfb,0xed,0xe7,0xf1,
+0x73,0xfd,0xfd,0xdf,0xff,0x7d,0xbe,0xdf,0xff,0xfb,0xff,0xef,0xff,0xef,0xff,0xff,
+0xff,0xff,0xff,0xd0,0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x20,0x02,0x00,0x22,
+0x40,0xc0,0x00,0x00,0x00,0x08,0x00,0x02,0x41,0x02,0x12,0x00,0x21,0x87,0x81,0x00,
+0x00,0x80,0x04,0x0b,0x28,0x01,0xb0,0x00,0x82,0x00,0x40,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0xc1,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,
+0xf7,0xff,0xfe,0x7f,0xed,0x79,0xff,0xde,0xeb,0x7f,0x74,0xf7,0xf7,0xe1,0xf9,0xff,
+0xf6,0x5f,0x7f,0xff,0xff,0xff,0xd7,0xdb,0xef,0xff,0xbb,0xff,0xff,0xff,0xcc,0xff,
+0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xf0,0x0f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x3d,0xcd,0x49,0x7f,0x6f,
+0x2b,0xba,0x5c,0xd2,0xda,0xf6,0xf3,0x3e,0xf7,0xff,0xbd,0xf1,0xfa,0xdf,0xfe,0xf7,
+0xcc,0xf6,0xbb,0xa5,0xb3,0xad,0xbf,0x6f,0x7d,0x6f,0x6b,0xdb,0xdf,0xbd,0xff,0xfe,
+0xb0,0x5f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xfb,0xdb,0x57,0xf6,0xfe,0x9f,0xd5,
+0xb7,0xff,0xaf,0xe5,0x3f,0xff,0xff,0x6f,0xff,0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0x69,
+0x6c,0xdf,0xda,0xdf,0xcb,0xff,0xf6,0xff,0x76,0xfd,0xfd,0xbf,0xff,0xff,0xff,0xd0,
+0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfd,0xbd,0x08,0x03,0x89,0x4f,0x5a,
+0x0f,0xf0,0xff,0xf8,0xbf,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xf3,
+0xfa,0xa0,0xf0,0xf2,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,
+0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xfd,0x00,0x6b,0xff,0xff,0x5a,0x0f,
+0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,0xff,0xb3,0xf5,
+0x50,0xf0,0xf0,0xff,0xff,0xff,0xd7,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0xbc,0xff,0xe4,0xe7,0x71,0xff,0xf9,0xc4,0xf4,
+0x7f,0x7f,0xcf,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xfb,0xf7,0x73,0xbf,0x14,
+0xff,0xe6,0xff,0xff,0xe1,0x7d,0xff,0xff,0xe7,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,
+0xff,0xfe,0xf5,0xff,0xff,0xfe,0xd2,0xfa,0xff,0xc4,0xf4,0x5c,0xbf,0xfa,0xff,0xff,
+0xec,0x7e,0xbf,0xff,0xff,0xff,0xf1,0xff,0xff,0xef,0xff,0xff,0x6b,0xdb,0xff,0xdf,
+0xf9,0xfb,0xbf,0xff,0xf1,0xff,0xbf,0xff,0xff,0xff,0xfb,0xf0,0xbf,0xff,0xff,0xff,
+0xfe,0xf3,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x00,0x80,0x00,
+0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x20,0x00,0x00,0x00,0x00,
+0x01,0x00,0x01,0x00,0x00,0x80,0x02,0x00,0x01,0x3c,0xf0,0x5f,0xff,0xff,0xff,0xfe,
+0xfd,0xbf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0x7f,0xff,0xdf,0xff,0xef,0xff,
+0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xfb,0xff,0xfd,0xff,
+0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xc3,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf0,
+0xff,0xdf,0xff,0xff,0xf7,0x23,0xff,0xff,0xfd,0xff,0xef,0xff,0xfe,0x7f,0x7d,0xf7,
+0xfe,0xff,0x7f,0x71,0xff,0xfb,0x7f,0xff,0xff,0xff,0x6e,0xfd,0xf7,0xfd,0xff,0xbf,
+0xff,0xbf,0xf9,0xfd,0xff,0xdf,0xef,0xf0,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xf8,0x30,
+0x40,0x01,0x00,0x83,0x00,0x00,0x00,0x0c,0x06,0x08,0x04,0x26,0x26,0x00,0x00,0x06,
+0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x70,0x08,0x80,0x00,0x20,0x01,0x20,
+0x00,0x02,0x00,0x30,0x00,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
+0xff,0xff,0x7b,0x3f,0xf7,0xff,0xd7,0xfe,0xfe,0xfb,0xfe,0x3b,0xfe,0xbd,0xff,0x2f,
+0xff,0x71,0xff,0xfb,0x7f,0xe7,0xff,0xf9,0xef,0xff,0xd7,0xfa,0xff,0xb7,0xbb,0xfe,
+0xff,0xff,0x74,0xff,0xf7,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xb5,
+0xbd,0x6f,0x7c,0xeb,0x7f,0xfb,0xdb,0xd3,0x4b,0xee,0xd6,0xf6,0xb7,0xfd,0xac,0xa1,
+0xfb,0xdf,0xfe,0xf7,0xf4,0x96,0xbd,0xb4,0xc5,0xa5,0xaf,0x6f,0x69,0x4f,0x7f,0xba,
+0xdb,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,
+0xf6,0xff,0xf6,0xff,0xbd,0xbf,0xa5,0xbf,0xff,0x7d,0x7f,0xef,0xff,0xfb,0xf1,0xfd,
+0xbf,0xff,0x6f,0xff,0x6b,0x7a,0xdb,0xff,0xdb,0xdf,0xf6,0xfe,0xb6,0xfd,0xfd,0xbf,
+0xfe,0xf7,0xff,0xd0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xf4,0x2f,0xff,
+0xfc,0x43,0x6b,0xff,0xff,0xff,0x0d,0xff,0xfc,0x33,0x3f,0xf0,0x5f,0xf1,0xff,0xff,
+0xff,0xff,0xf9,0xde,0xf0,0x4c,0xfe,0x77,0xaf,0xff,0xff,0xef,0xff,0xf0,0xff,0xdb,
+0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xfe,0xf7,0xff,0xf0,0x2f,0xff,0xfd,
+0x43,0x7f,0xff,0xff,0xf1,0x0f,0xff,0xfc,0x33,0x3f,0xff,0xaf,0xf1,0xff,0xff,0xff,
+0xff,0xf6,0xd7,0xff,0xbc,0xfd,0xbd,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,
+0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0xfb,0xf1,
+0xbf,0xff,0xf9,0xfd,0xcf,0xf2,0x70,0xff,0x1f,0x9f,0xf3,0xf1,0xff,0xff,0xff,0xff,
+0xfc,0xf7,0xff,0x13,0x9f,0xfc,0xff,0xff,0x84,0xf7,0xff,0xff,0x47,0xff,0xff,0xff,
+0xf0,0xbf,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xf1,0xfc,0xff,0xfe,0xfe,0x79,
+0x3f,0xff,0x1d,0x46,0xcf,0xff,0xcf,0xfc,0x7b,0xff,0xf1,0xff,0xff,0xff,0xff,0xed,
+0xf3,0xab,0xff,0xcb,0xff,0xf8,0xff,0xfc,0xf5,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,
+0x8f,0xff,0xff,0xff,0xfe,0xf3,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
+0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x04,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x20,
+0x0c,0x00,0x00,0x04,0x01,0x00,0x01,0x00,0x00,0x80,0x00,0x00,0x01,0x3c,0xf0,0x7f,
+0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xfd,0xfe,0xff,0xff,0xff,0xff,0xfe,0xff,
+0xdf,0xff,0xff,0xf7,0xff,0xff,0xff,0xef,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xeb,
+0xff,0xdf,0xff,0xff,0xfb,0xf7,0x7f,0xff,0xfe,0xff,0xff,0xbf,0xdb,0xf0,0xff,0xff,
+0xff,0xff,0xfe,0xf0,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0x7f,0xf7,0xff,
+0xbf,0xbf,0xcf,0xff,0xff,0xff,0x3e,0xf1,0x7f,0xff,0xff,0xef,0xff,0xff,0xff,0xfe,
+0xff,0xfd,0xff,0xbf,0xbd,0xfe,0xff,0xfb,0xf7,0xdf,0xfb,0xd0,0xf0,0x9f,0xff,0xff,
+0xff,0xfe,0xf8,0x30,0x20,0x00,0x40,0x01,0x80,0xc0,0x30,0x00,0x00,0x20,0x00,0x10,
+0x50,0x88,0x20,0x00,0x00,0x13,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,
+0x00,0x00,0x01,0x80,0x08,0x00,0x00,0xa0,0x00,0x10,0xc1,0xf0,0xef,0xff,0xff,0xff,
+0xfe,0xfd,0xef,0x7f,0xff,0xff,0xbf,0xff,0xf7,0xff,0xef,0xfb,0xfd,0x77,0xef,0xbf,
+0xf7,0x7f,0xff,0xff,0xbf,0xd1,0x7f,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xaf,0xff,
+0xdf,0xf7,0xfb,0xff,0xfd,0xff,0xfc,0xff,0xfd,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,
+0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x3f,0xff,0xff,0xff,0xfe,0xdd,0xff,
+0xff,0xff,0xa5,0xfd,0x6f,0x7d,0x6d,0x7f,0x52,0xdf,0x5a,0x4b,0xee,0xb6,0xee,0xf2,
+0xbb,0xac,0xa1,0x5b,0x4d,0xd6,0xf7,0xfe,0xb2,0xbd,0x35,0xb5,0xb5,0xdd,0x6f,0x7f,
+0xe9,0x5f,0x52,0xdf,0xbd,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,
+0xff,0xdb,0xfe,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfd,0xb5,0xbf,0xf9,0x7f,0x6f,0xff,
+0xdb,0xf1,0xfd,0xbf,0xff,0x6f,0xff,0x69,0x7f,0xdb,0xff,0xd3,0xff,0xf6,0xfe,0xf2,
+0xff,0xad,0xbf,0xff,0xff,0xff,0xd0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,
+0x30,0x0f,0xff,0xff,0xfd,0x6b,0xca,0xff,0xf0,0x0f,0xd6,0xbf,0xcf,0x3f,0xff,0xff,
+0xf1,0xff,0xff,0xff,0xca,0xfe,0xbf,0xff,0xf0,0x05,0xaf,0x0f,0xff,0xfc,0xf0,0xcf,
+0xf0,0xff,0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0x30,
+0x0f,0xff,0xff,0xfc,0x3f,0xca,0xff,0x0f,0x0f,0xd6,0xbf,0xff,0xff,0xf5,0x5f,0xf1,
+0xff,0x8b,0xff,0xc3,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xfc,0xf0,0xcf,0xf0,
+0xff,0xff,0xff,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xcf,0xff,
+0xff,0xbf,0x9f,0x3f,0xfe,0xfc,0xff,0x4f,0xff,0xff,0xff,0xff,0xff,0xf7,0xf1,0xff,
+0xdf,0xfe,0x7e,0x3f,0x9f,0xf4,0xfc,0x7f,0xfc,0xff,0xff,0x3f,0xff,0x3f,0xfe,0x3f,
+0xff,0xff,0xff,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xfb,0xff,0xfe,0xff,
+0xff,0xff,0xff,0xbf,0xfb,0xff,0xf8,0xed,0xff,0x8f,0xff,0xbb,0xff,0xb1,0xf3,0xef,
+0x8f,0xf7,0xff,0xff,0xdb,0xff,0xff,0xff,0xef,0xbf,0xfd,0x79,0xbf,0xbf,0xff,0xff,
+0xff,0xfb,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x00,0x04,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x04,0x08,0x08,0x01,0x01,0x00,0x90,
+0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0x00,0x01,
+0x3c,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0x9f,0xff,0xaf,0xdf,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,
+0xbf,0xef,0xff,0xff,0xff,0xed,0xff,0xff,0xff,0xef,0xff,0xbf,0xff,0xff,0xff,0xc3,
+0xf0,0x3f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xfd,0xff,0xff,0xff,0xfb,0xff,0xbb,0xff,
+0xff,0xff,0x7f,0xf6,0xff,0x7f,0xfb,0xfd,0xed,0xff,0xf1,0xff,0xfe,0x7f,0xff,0xff,
+0xff,0x5f,0xff,0xf7,0xff,0x7e,0xff,0xfd,0xff,0xef,0xff,0xff,0xff,0xef,0xf0,0xf0,
+0x8f,0xff,0xff,0xff,0xfe,0xf8,0x30,0x80,0x00,0x04,0x00,0x00,0x40,0x02,0x00,0x03,
+0x00,0x05,0x04,0x20,0x00,0x00,0x01,0xd0,0x00,0x81,0x00,0x20,0x04,0x04,0x00,0x00,
+0x81,0x04,0x08,0x80,0x10,0x00,0xc0,0x00,0x00,0x00,0x20,0x00,0x08,0xc1,0xf0,0x6f,
+0xff,0xff,0xff,0xfe,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xf3,0xfd,0xff,0xed,0xfc,
+0xff,0xff,0x9f,0xfb,0xfd,0xff,0xff,0xff,0xf1,0xff,0xff,0x7f,0xfb,0x3e,0xff,0x9f,
+0xff,0xff,0xff,0xff,0xfd,0xf9,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xf0,0x6f,0xff,
+0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xfd,0xbd,0xff,0xef,0x7c,0xeb,0x7f,0xfb,0xdb,0xfa,0xdc,
+0xee,0xf7,0xf6,0xd7,0xf5,0x2d,0xa1,0xbb,0xdd,0xee,0xf7,0x54,0xf7,0xfb,0x2c,0xb5,
+0xb4,0xbd,0x6b,0x6f,0xef,0x6f,0xbb,0xdf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,
+0xfe,0xbf,0xff,0xff,0xff,0xfb,0xff,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xff,0xbf,0xef,
+0x6f,0xff,0x6f,0xfa,0xdb,0xf1,0xc5,0xbd,0xf5,0x6f,0xff,0x6f,0xca,0xdb,0xff,0xdb,
+0xfb,0xf6,0x97,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x9f,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0x7f,0xff,0xff,0xe7,0x63,0xff,0xff,
+0xff,0xfc,0x77,0xdf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff,
+0xc3,0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0x5f,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xfc,0xff,0xcf,0xf1,0xdb,0xff,0xd6,0xa8,0x3f,0xff,0xff,0x08,0x2f,0xf0,0xff,0xc3,
+0xff,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xbf,0xff,0xca,0xff,0x9f,0xff,0xfa,0xb9,0xe7,
+0x9f,0xf3,0x81,0xff,0xff,0xfc,0x73,0xd7,0xff,0xff,0x77,0xff,0xfd,0xff,0xfc,0xff,
+0xff,0xff,0xff,0xcf,0xff,0xff,0xff,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,
+0xff,0xf7,0xde,0xff,0xfe,0x7e,0xff,0xbf,0xff,0xbf,0xf1,0xb3,0xff,0xff,0xe3,0xfb,
+0xff,0xe1,0x1f,0x7f,0xff,0xf8,0x78,0xff,0xfb,0x1e,0xff,0xf7,0xfe,0xe7,0xff,0xff,
+0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x04,0x00,
+0x01,0x80,0x40,0x40,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
+0x80,0x00,0x00,0x01,0x3c,0xf0,0xaf,0xff,0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xff,
+0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xf7,0xf1,
+0xfd,0xff,0xff,0xff,0xdf,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+0xff,0xff,0xff,0xdb,0xf0,0x8f,0xff,0xff,0xff,0xfe,0xf0,0xff,0xdf,0xff,0xff,0x7f,
+0xff,0xff,0xff,0xbe,0xd7,0xff,0xed,0xbd,0x7e,0xbf,0xfe,0xf6,0x7f,0xbf,0x71,0xff,
+0xff,0xda,0xff,0xf9,0xff,0xbf,0x7f,0xfe,0xff,0x6f,0x7f,0xff,0xff,0xff,0xff,0xff,
+0x7f,0xff,0xd0,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xf8,0x30,0x42,0x00,0x00,0x00,0x00,
+0x80,0xc1,0x00,0x00,0x90,0x00,0xc4,0x00,0x00,0x12,0x20,0x43,0x22,0x81,0x84,0x00,
+0x00,0x14,0x00,0x01,0x00,0x08,0x80,0x00,0x02,0x00,0x02,0x00,0x04,0x02,0x00,0x00,
+0x10,0xc1,0xf0,0x1f,0xff,0xff,0xff,0xfe,0xff,0xff,0xfd,0xff,0xff,0xdd,0xfe,0xff,
+0xb6,0x76,0xe5,0xbc,0xf9,0xf7,0xaf,0x5f,0xbf,0xfc,0xdf,0xcf,0xf1,0xff,0xef,0x79,
+0xff,0xbd,0xff,0xef,0xff,0xff,0xf7,0x6f,0x5f,0xff,0xff,0xfd,0xef,0xef,0xbf,0xff,
+0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xf0,0xff,0xff,0xff,0xff,0xfe,0xdb,0xff,0xff,0xfd,0x2d,0xff,0x69,0x2a,0xef,0x77,
+0xbb,0xdd,0x5a,0xdf,0xf6,0xf6,0xd6,0xf7,0x7d,0xbd,0xd1,0xb2,0x4a,0xd6,0xb2,0xbe,
+0x97,0xf5,0xbd,0xb3,0xad,0xff,0xef,0x7f,0x69,0x6b,0xfb,0xdf,0xff,0xff,0xff,0xf0,
+0x2f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,0xfe,0x9f,0xd4,0xbf,
+0xed,0xaf,0xff,0x6b,0x6f,0xf7,0xff,0xdd,0xdb,0x31,0xfd,0xbf,0xff,0x6f,0x7f,0xff,
+0xff,0xdb,0xff,0xcb,0xdf,0xf6,0xff,0xf6,0xff,0xfd,0xbf,0xfe,0xf7,0xff,0xd0,0x8f,
+0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff,
+0xa5,0xff,0xff,0xff,0xdf,0xb7,0xff,0xff,0xf1,0xff,0xff,0xff,0xf7,0xe9,0x6a,0xbf,
+0xff,0xff,0xfd,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xaf,0xf0,0x4f,0xff,
+0xff,0xff,0xfe,0xfe,0xdf,0xff,0xfd,0x1f,0xff,0x46,0x2f,0x9f,0xff,0xff,0xff,0xa5,
+0xff,0xff,0xff,0xc0,0x37,0xff,0xff,0xf1,0x99,0x8e,0xdc,0x7f,0xe9,0x6a,0xbf,0xff,
+0xf0,0x0f,0xff,0xff,0xfd,0x55,0x57,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xff,0x07,0xff,0xc0,0xbe,0xff,0xff,0xcf,0xef,0x9f,0xff,
+0xff,0xfb,0xff,0xe7,0xff,0xff,0xa1,0xe3,0xce,0x3c,0x58,0x3f,0xf3,0xff,0xfd,0xef,
+0xf9,0xff,0xff,0xf7,0xf1,0x7f,0xff,0xcb,0xff,0xff,0xff,0xf0,0x2f,0xff,0xff,0xff,
+0xfe,0xf5,0x7f,0xff,0xf0,0xff,0xfe,0xff,0xc4,0x75,0xe7,0xb9,0xff,0xff,0xff,0xef,
+0xff,0xc7,0x37,0x3b,0xff,0xf0,0x13,0x9e,0x0f,0xf4,0xff,0xfe,0xfb,0xff,0xff,0xf9,
+0xfc,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xfa,0xf0,0xef,0xff,0xff,0xff,0xfe,
+0xf3,0xc0,0x01,0x00,0x00,0x02,0x00,0x02,0x22,0x00,0x00,0xc0,0x40,0x00,0x40,0x00,
+0x04,0x08,0x04,0x0a,0x01,0x01,0x10,0x20,0x20,0x00,0x00,0x04,0x08,0x08,0x04,0x00,
+0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x3c,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xfd,
+0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,0x7f,0xff,0x7f,0xff,0xcf,0x9d,0xff,
+0xff,0xf7,0xfd,0xf1,0xff,0xff,0xff,0xee,0xbf,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xf0,0xff,
+0xff,0xff,0xf7,0xf7,0xff,0xff,0xfe,0xbf,0xf7,0xff,0xff,0x5b,0xff,0xbf,0xf7,0xff,
+0xfd,0x7f,0x71,0xfd,0xff,0xed,0xf7,0xfe,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,
+0xff,0xff,0xef,0xff,0x7f,0xff,0xd0,0xf0,0xff,0xff,0xff,0xff,0xfe,0xf8,0x30,0x11,
+0x00,0x48,0x60,0x40,0x82,0x60,0x24,0x60,0x00,0xcc,0x00,0x80,0x04,0x01,0x00,0x00,
+0x14,0x01,0x0c,0x04,0x00,0x30,0x00,0x00,0x00,0x08,0x08,0x00,0x01,0x00,0xc2,0x00,
+0x00,0x02,0x00,0x80,0x00,0xc1,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,
+0xf7,0x7b,0xff,0xf3,0xeb,0xbf,0xff,0xf7,0xff,0xff,0xff,0xe7,0x5d,0x3f,0xff,0xf6,
+0xd1,0xfd,0xff,0xeb,0xf7,0x3d,0xff,0xff,0xff,0x5f,0xff,0x7f,0x7f,0xf3,0xff,0xff,
+0xef,0xfd,0xbf,0xff,0xff,0xf0,0x5f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf0,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xb5,0xdf,
+0x6f,0x7d,0x69,0x7f,0xfb,0xdf,0x52,0x5f,0xf6,0xf7,0xfe,0xf6,0xf3,0xbd,0xb1,0xda,
+0xcd,0xfe,0xf6,0xee,0xd2,0xbd,0xa5,0xaf,0xbd,0xff,0x6f,0x7c,0xeb,0x2b,0xfa,0xda,
+0xff,0xfe,0xdf,0xf0,0x4f,0xff,0xff,0xff,0xfe,0xbf,0xff,0xff,0xff,0xdb,0xff,0xf6,
+0xff,0xf6,0xff,0xbd,0xbf,0xcd,0xbf,0xeb,0x6f,0xf7,0x6f,0xdf,0xdb,0x51,0xfd,0xbd,
+0xff,0x6f,0xff,0x6f,0xfb,0x5b,0xff,0xdb,0xff,0xf6,0xfe,0xf6,0xfd,0xfd,0xbf,0xfe,
+0xf7,0xff,0xd0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xfa,0x50,0xff,0xff,0xff,
+0xf0,0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0xfc,0xff,0xff,
+0xf7,0xdb,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff,
+0xaf,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf5,0xa0,0xff,0xff,0xff,0xf0,
+0x6f,0xff,0xff,0xf0,0x96,0xff,0xff,0xc6,0x2b,0xff,0xff,0xf1,0x5a,0xff,0xff,0xff,
+0xf3,0xc3,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xc1,0x4f,0xc3,0xff,0xff,0xff,0xff,
+0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfc,0xff,0xff,0x9f,0xf0,0x7f,
+0xff,0xf9,0xfc,0x4f,0xf3,0xff,0x27,0xeb,0xff,0xfc,0x81,0xfc,0x7f,0xfe,0x7b,0xff,
+0xf7,0xff,0x12,0x7f,0xff,0xff,0xff,0xff,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,
+0x7f,0xff,0xff,0xff,0xfe,0xf5,0xff,0xff,0xff,0xdf,0xfe,0xff,0xfc,0x7e,0x7f,0xbf,
+0xff,0xff,0xaf,0xef,0xff,0xdf,0xdf,0xfb,0xff,0xf1,0xc3,0xfe,0x6f,0xf1,0xcf,0x3f,
+0xfb,0xff,0xff,0xcf,0xfe,0xff,0xff,0xfe,0x7f,0xbf,0xff,0xff,0xbf,0xfa,0xf0,0xdf,
+0xff,0xff,0xff,0xfe,0xf3,0xc0,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
+0x20,0x00,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x02,0x00,0x00,0x80,0x00,0x02,0x80,0x00,0x02,0x3c,0xf0,0x2f,0xff,
+0xff,0xff,0xfe,0xfd,0xbf,0xff,0xfb,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xf1,0xff,0x7f,0xff,0xff,0xff,0xff,0xef,0xff,
+0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xf0,0x2f,0xff,0xff,
+0xff,0xfe,0xf0,0xff,0xff,0xff,0xfb,0xff,0xbf,0xff,0xff,0xff,0xff,0xf7,0xbf,0xfb,
+0xff,0xff,0xff,0xdf,0xf7,0xff,0xf1,0xf7,0xbf,0xfb,0xff,0xff,0xff,0x7f,0xde,0xff,
+0xff,0xff,0xff,0xff,0xff,0xed,0xf7,0xff,0xff,0x7f,0xd0,0xf0,0x3f,0xff,0xff,0xff,
+0xfe,0xf8,0x30,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x80,
+0x20,0x01,0x01,0x92,0x00,0x01,0x01,0x00,0xe0,0x1c,0x60,0x20,0x30,0x08,0x08,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0xc1,0xf0,0x6f,0xff,0xff,0xff,0xfe,
+0xff,0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0xff,0xdf,0xff,0xfc,0x7f,0xfb,0xbf,0xff,
+0xff,0xff,0xff,0xff,0xf1,0xf6,0xff,0xf7,0x7e,0x3f,0xff,0x7f,0xff,0xff,0xff,0xf7,
+0xff,0xff,0xff,0xed,0xff,0xdf,0xff,0xb7,0xff,0xf0,0x3f,0xff,0xff,0xff,0xfe,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,
+0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xbf,0xff,0xdf,
+0x57,0xef,0xf1,0xfd,0xfe,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfb,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x7f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,
+0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xdf,0xff,
+0xff,0xf1,0xfd,0xff,0x7f,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xfe,0xff,0xff,0xff,0xff,0xf0,0x9f,0xff,0xff,0xff,0xfe,0xf7,0xfd,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,
+0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xf0,0x6f,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,
+0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xfb,0x6f,0xff,0xfe,0xbf,0xff,0xf1,0xff,
+0xf7,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,
+0xff,0xff,0xff,0xf0,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xfb,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0x57,0xff,0xfd,0xbf,0xff,0xf1,0xff,0xef,
+0xfe,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,
+0xde,0xff,0xf0,0xcf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xf7,0xdb,0xff,0xdb,0xfd,
+0xf6,0xff,0xf6,0xff,0x3c,0xbc,0xbc,0xbf,0xdf,0x6f,0xe7,0x2f,0xf1,0x3c,0xbf,0xfd,
+0xbf,0xdf,0x6f,0xff,0x6f,0xf7,0xdb,0xff,0xdb,0xfd,0xf6,0xff,0xf6,0xff,0xff,0xff,
+0x02,0x01,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff };
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/hostess_sv11.c linux.pre11.3/drivers/net/hostess_sv11.c
--- linux.vanilla/drivers/net/hostess_sv11.c	Tue Feb 23 14:21:33 1999
+++ linux.pre11.3/drivers/net/hostess_sv11.c	Mon Jul 19 23:27:33 1999
@@ -389,7 +389,8 @@
 	free_irq(dev->sync.irq, dev);
 	if(dma)
 	{
-		free_dma(dev->sync.chanA.rxdma);
+		if(dma==1)
+			free_dma(dev->sync.chanA.rxdma);
 		free_dma(dev->sync.chanA.txdma);
 	}
 	release_region(dev->sync.chanA.ctrlio-1, 8);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/irda/toshoboe.c linux.pre11.3/drivers/net/irda/toshoboe.c
--- linux.vanilla/drivers/net/irda/toshoboe.c	Tue Jun 15 16:49:49 1999
+++ linux.pre11.3/drivers/net/irda/toshoboe.c	Mon Jul 19 23:27:34 1999
@@ -568,11 +568,11 @@
   self->rxs = inb_p (OBOE_RCVT);
   self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET;
 
-#ifdef 0
+#if 0
   self->rxs = 0;
   self->txs = 0;
 #endif
-#ifdef 0
+#if 0
   self->rxs = RX_SLOTS - 1;
   self->txs = 0;
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/jazzsonic.c linux.pre11.3/drivers/net/jazzsonic.c
--- linux.vanilla/drivers/net/jazzsonic.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/jazzsonic.c	Mon Jul 19 23:27:35 1999
@@ -0,0 +1,266 @@
+/*
+ * sonic.c
+ *
+ * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * 
+ * This driver is based on work from Andreas Busse, but most of
+ * the code is rewritten.
+ * 
+ * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
+ *
+ * A driver for the onboard Sonic ethernet controller on Mips Jazz
+ * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
+ * perhaps others, too)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <asm/bootinfo.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <linux/errno.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#define SREGS_PAD(n)    u16 n;
+
+#include "sonic.h"
+
+/*
+ * Macros to access SONIC registers
+ */
+#define SONIC_READ(reg) \
+	*((volatile unsigned int *)base_addr+reg)
+
+#define SONIC_WRITE(reg,val) \
+	*((volatile unsigned int *)base_addr+reg) = val
+
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifdef SONIC_DEBUG
+static unsigned int sonic_debug = SONIC_DEBUG;
+#else 
+static unsigned int sonic_debug = 1;
+#endif
+
+/*
+ * Base address and interupt of the SONIC controller on JAZZ boards
+ */
+static struct {
+    unsigned int port;
+    unsigned int irq;
+} sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}};
+
+/*
+ * We cannot use station (ethernet) address prefixes to detect the
+ * sonic controller since these are board manufacturer depended.
+ * So we check for known Silicon Revision IDs instead. 
+ */
+static unsigned short known_revisions[] =
+{
+  0x04,				/* Mips Magnum 4000 */
+  0xffff			/* end of list */
+};
+
+/* Index to functions, as function prototypes. */
+
+extern int sonic_probe(struct device *dev);
+static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq);
+
+
+/*
+ * Probe for a SONIC ethernet controller on a Mips Jazz board.
+ * Actually probing is superfluous but we're paranoid.
+ */
+__initfunc(int sonic_probe(struct device *dev))
+{
+    unsigned int base_addr = dev ? dev->base_addr : 0;
+    int i;
+
+    /*
+     * Don't probe if we're not running on a Jazz board.
+     */
+    if (mips_machgroup != MACH_GROUP_JAZZ)
+	return -ENODEV;
+    if (base_addr >= KSEG0)	/* Check a single specified location. */
+	return sonic_probe1(dev, base_addr, dev->irq);
+    else if (base_addr != 0)	/* Don't probe at all. */
+	return -ENXIO;
+    
+    for (i = 0; sonic_portlist[i].port; i++) {
+	int base_addr = sonic_portlist[i].port;
+	if (check_region(base_addr, 0x100))
+	    continue;
+	if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0)
+	    return 0;
+    }
+    return -ENODEV;
+}
+
+__initfunc(static int sonic_probe1(struct device *dev,
+                                   unsigned int base_addr, unsigned int irq))
+{
+    static unsigned version_printed = 0;
+    unsigned int silicon_revision;
+    unsigned int val;
+    struct sonic_local *lp;
+    int i;
+    
+    /*
+     * get the Silicon Revision ID. If this is one of the known
+     * one assume that we found a SONIC ethernet controller at
+     * the expected location.
+     */
+    silicon_revision = SONIC_READ(SONIC_SR);
+    if (sonic_debug > 1)
+      printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
+
+    i = 0;
+    while ((known_revisions[i] != 0xffff) &&
+	   (known_revisions[i] != silicon_revision))
+      i++;
+	
+    if (known_revisions[i] == 0xffff) {
+	printk("SONIC ethernet controller not found (0x%4x)\n",
+	       silicon_revision);
+	return -ENODEV;
+    }
+    
+    request_region(base_addr, 0x100, "SONIC");
+    
+    /* Allocate a new 'dev' if needed. */
+    if (dev == NULL)
+      dev = init_etherdev(0, sizeof(struct sonic_local));
+
+    if (sonic_debug  &&  version_printed++ == 0)
+      printk(version);
+
+    printk("%s: %s found at 0x%08x, ",
+	   dev->name, "SONIC ethernet", base_addr);
+
+    /* Fill in the 'dev' fields. */
+    dev->base_addr = base_addr;
+    dev->irq = irq;
+
+    /*
+     * Put the sonic into software reset, then
+     * retrieve and print the ethernet address.
+     */
+    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+    SONIC_WRITE(SONIC_CEP,0);
+    for (i=0; i<3; i++) {
+	val = SONIC_READ(SONIC_CAP0-i);
+	dev->dev_addr[i*2] = val;
+	dev->dev_addr[i*2+1] = val >> 8;
+    }
+
+    printk("HW Address ");
+    for (i = 0; i < 6; i++) {
+	printk("%2.2x", dev->dev_addr[i]);
+	if (i<5)
+	  printk(":");
+    }
+    
+    printk(" IRQ %d\n", irq);
+    
+    /* Initialize the device structure. */
+    if (dev->priv == NULL) {
+	/*
+	 * the memory be located in the same 64kb segment
+	 */
+	lp = NULL;
+	i = 0;
+	do {
+	    lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
+	    if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
+		/* FIXME, free the memory later */
+		kfree (lp);
+		lp = NULL;
+	    }
+	} while (lp == NULL && i++ < 20);
+	
+	if (lp == NULL) {
+	    printk ("%s: couldn't allocate memory for descriptors\n",
+	            dev->name);
+	    return -ENOMEM;
+	}
+	
+	memset(lp, 0, sizeof(struct sonic_local));
+	
+	/* get the virtual dma address */
+	lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
+	if (lp->cda_laddr == ~0UL) {
+	    printk ("%s: couldn't get DMA page entry for descriptors\n",
+	            dev->name);
+	    return -ENOMEM;
+	}
+
+	lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
+	lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
+	lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
+	
+	/* allocate receive buffer area */
+	/* FIXME, maybe we should use skbs */
+	if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) {
+	    printk ("%s: couldn't allocate receive buffers\n",dev->name);
+	    return -ENOMEM;
+	}
+	
+	/* get virtual dma address */
+	if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) {
+	    printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name);
+	    return -ENOMEM;
+	}
+	
+	/* now convert pointer to KSEG1 pointer */
+	lp->rba = (char *)KSEG1ADDR(lp->rba);
+	flush_cache_all();
+	dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
+    }
+
+    lp = (struct sonic_local *)dev->priv;
+    dev->open = sonic_open;
+    dev->stop = sonic_close;
+    dev->hard_start_xmit = sonic_send_packet;
+    dev->get_stats	= sonic_get_stats;
+    dev->set_multicast_list = &sonic_multicast_list;
+
+    /*
+     * clear tally counter
+     */
+    SONIC_WRITE(SONIC_CRCT,0xffff);
+    SONIC_WRITE(SONIC_FAET,0xffff);
+    SONIC_WRITE(SONIC_MPT,0xffff);
+
+    /* Fill in the fields of the device structure with ethernet values. */
+    ether_setup(dev);
+    return 0;
+}
+
+/*
+ *      SONIC uses a normal IRQ
+ */
+#define sonic_request_irq       request_irq
+#define sonic_free_irq          free_irq
+
+#define sonic_chiptomem(x)      KSEG1ADDR(vdma_log2phys(x))
+
+#include "sonic.c"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/lance.c linux.pre11.3/drivers/net/lance.c
--- linux.vanilla/drivers/net/lance.c	Mon Dec 28 23:09:43 1998
+++ linux.pre11.3/drivers/net/lance.c	Tue Jul 20 00:00:12 1999
@@ -499,6 +499,8 @@
 		
 	lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7,
 										   GFP_DMA | GFP_KERNEL)+7) & ~7);
+	if(lp==NULL)
+		return -ENODEV;
 	if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
 	memset(lp, 0, sizeof(*lp));
 	dev->priv = lp;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/ne2k-pci.c linux.pre11.3/drivers/net/ne2k-pci.c
--- linux.vanilla/drivers/net/ne2k-pci.c	Tue Jan 26 09:44:21 1999
+++ linux.pre11.3/drivers/net/ne2k-pci.c	Mon Jul 19 23:27:32 1999
@@ -24,11 +24,8 @@
 
 /* Our copyright info must remain in the binary. */
 static const char *version =
-"ne2k-pci.c:v0.99L 2/7/98 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
+"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n";
 
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -44,6 +41,13 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
+#if defined(__powerpc__)
+#define inl_le(addr)  le32_to_cpu(inl(addr))
+#define inw_le(addr)  le16_to_cpu(inw(addr))
+#define insl insl_ns
+#define outsl outsl_ns
+#endif
+
 /* Set statically or when loading the driver module. */
 static int debug = 1;
 
@@ -58,19 +62,34 @@
 /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
 /* #define PACKETBUF_MEMSIZE	0x40 */
 
+#define ne2k_flags reg0			/* Rename an existing field to store flags! */
+
+/* Only the low 8 bits are usable for non-init-time flags! */
+enum {
+	HOLTEK_FDX=1, 		/* Full duplex -> set 0x80 at offset 0x20. */
+	ONLY_16BIT_IO=2, ONLY_32BIT_IO=4,	/* Chip can do only 16/32-bit xfers. */
+	STOP_PG_0x60=0x100,
+};
+
+/* This will eventually be converted to the standard PCI probe table. */
+
 static struct {
 	unsigned short vendor, dev_id;
 	char *name;
+	int flags;
 }
 pci_clone_list[] __initdata = {
-	{0x10ec, 0x8029, "RealTek RTL-8029"},
-	{0x1050, 0x0940, "Winbond 89C940"},
-	{0x11f6, 0x1401, "Compex RL2000"},
-	{0x8e2e, 0x3000, "KTI ET32P2"},
-	{0x4a14, 0x5000, "NetVin NV5000SC"},
-	{0x1106, 0x0926, "Via 82C926"},
-	{0x10bd, 0x0e34, "SureCom NE34"},
-	{0x1050, 0x5a5a, "Winbond"},
+	{0x10ec, 0x8029, "RealTek RTL-8029", 0},
+	{0x1050, 0x0940, "Winbond 89C940", 0},
+	{0x11f6, 0x1401, "Compex RL2000", 0},
+	{0x8e2e, 0x3000, "KTI ET32P2", 0},
+	{0x4a14, 0x5000, "NetVin NV5000SC", 0},
+	{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO},
+	{0x10bd, 0x0e34, "SureCom NE34", 0},
+	{0x1050, 0x5a5a, "Winbond", 0},
+	{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
+	{0x12c3, 0x5598, "Holtek HT80229",
+	 ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
 	{0,}
 };
 
@@ -86,7 +105,8 @@
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
 int ne2k_pci_probe(struct device *dev);
-static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq);
+static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq,
+									  int chip_idx);
 
 static int ne2k_pci_open(struct device *dev);
 static int ne2k_pci_close(struct device *dev);
@@ -115,17 +135,13 @@
 int
 init_module(void)
 {
-	int retval;
-
 	/* We must emit version information. */
 	if (debug)
 		printk(KERN_INFO "%s", version);
 
-	retval = ne2k_pci_probe(0);
-
-	if (retval) {
-		printk(KERN_NOTICE "ne2k-pci.c: no (useable) cards found, driver NOT installed.\n");
-		return retval;
+	if (ne2k_pci_probe(0)) {
+		printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n");
+		return -ENODEV;
 	}
 	lock_8390_module();
 	return 0;
@@ -225,7 +241,7 @@
 
 		printk("ne2k-pci.c: PCI NE2000 clone '%s' at I/O %#x, IRQ %d.\n",
 			   pci_clone_list[i].name, pci_ioaddr, pci_irq_line);
-		dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line);
+		dev = ne2k_pci_probe1(dev, pci_ioaddr, pci_irq_line, i);
 		if (dev == 0) {
 			/* Should not happen. */
 			printk(KERN_ERR "ne2k-pci: Probe of PCI card at %#x failed.\n",
@@ -247,11 +263,11 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq))
+__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, int ioaddr, int irq,
+									  int chip_idx))
 {
 	int i;
 	unsigned char SA_prom[32];
-	const char *name = NULL;
 	int start_page, stop_page;
 	int reg0 = inb(ioaddr);
 
@@ -273,6 +289,8 @@
 		}
 	}
 
+	dev = init_etherdev(dev, 0);
+
 	/* Reset card. Who knows what dain-bramaged state it was left in. */
 	{
 		unsigned long reset_start_time = jiffies;
@@ -321,59 +339,47 @@
 
 	}
 
-#ifdef notdef
-	/* Some broken PCI cards don't respect the byte-wide
-	   request in program_seq above, and hence don't have doubled up values.
-	*/
-	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])
-			sa_prom_doubled = 0;
-	}
-
-	if (sa_prom_doubled)
-		for (i = 0; i < 16; i++)
-			SA_prom[i] = SA_prom[i+i];
-#else
-	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
-		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+	/* Note: all PCI cards have at least 16 bit access, so we don't have
+	   to check for 8 bit cards.  Most cards permit 32 bit access. */
 
-#endif
+	if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) {
+		for (i = 0; i < 4 ; i++)
+			((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
+	} else
+		for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
+			SA_prom[i] = inb(ioaddr + NE_DATAPORT);
 
 	/* We always set the 8390 registers for word mode. */
 	outb(0x49, ioaddr + EN0_DCFG);
 	start_page = NESM_START_PG;
-	stop_page = NESM_STOP_PG;
 
-	/* Set up the rest of the parameters. */
-	name = "PCI NE2000";
-
-	dev = init_etherdev(dev, 0);
+	stop_page =
+		pci_clone_list[chip_idx].flags&STOP_PG_0x60 ? 0x60 : NESM_STOP_PG;
 
+	/* Set up the rest of the parameters. */
 	dev->irq = irq;
 	dev->base_addr = ioaddr;
 
 	/* Allocate dev->priv and fill in 8390 specific dev fields. */
 	if (ethdev_init(dev)) {
 		printk ("%s: unable to get memory for dev->priv.\n", dev->name);
-		kfree(dev);
 		return 0;
 	}
 
 	request_region(ioaddr, NE_IO_EXTENT, dev->name);
 
 	printk("%s: %s found at %#x, IRQ %d, ",
-		   dev->name, name, ioaddr, dev->irq);
+		   dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq);
 	for(i = 0; i < 6; i++) {
 		printk("%2.2X%s", SA_prom[i], i == 5 ? ".\n": ":");
 		dev->dev_addr[i] = SA_prom[i];
 	}
 
-	ei_status.name = name;
+	ei_status.name = pci_clone_list[chip_idx].name;
 	ei_status.tx_start_page = start_page;
 	ei_status.stop_page = stop_page;
 	ei_status.word16 = 1;
+	ei_status.ne2k_flags = pci_clone_list[chip_idx].flags;
 
 	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
@@ -447,9 +453,9 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
-			   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   dev->interrupt);
+			   (int)dev->interrupt);
 		return;
 	}
 
@@ -461,11 +467,12 @@
 	outb(ring_page, nic_base + EN0_RSARHI);
 	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-#if defined(USE_LONGIO)
-	*(u32*)hdr = inl(NE_BASE + NE_DATAPORT);
-#else
-	insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-#endif
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	} else {
+		*(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
+		le16_to_cpus(&hdr->count);
+	}
 
 	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
 	ei_status.dmaing &= ~0x01;
@@ -485,12 +492,14 @@
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 	if (ei_status.dmaing) {
 		printk("%s: DMAing conflict in ne2k_pci_block_input "
-			   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   dev->interrupt);
+			   (int)dev->interrupt);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
+	if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+		count = (count + 3) & 0xFFFC;
 	outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
 	outb(count & 0xff, nic_base + EN0_RCNTLO);
 	outb(count >> 8, nic_base + EN0_RCNTHI);
@@ -498,21 +507,21 @@
 	outb(ring_offset >> 8, nic_base + EN0_RSARHI);
 	outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-#if defined(USE_LONGIO)
-	insl(NE_BASE + NE_DATAPORT, buf, count>>2);
-	if (count & 3) {
-		buf += count & ~3;
-		if (count & 2)
-			*((u16*)buf)++ = inw(NE_BASE + NE_DATAPORT);
-		if (count & 1)
-			*buf = inb(NE_BASE + NE_DATAPORT);
-	}
-#else
-	insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-	if (count & 0x01) {
-		buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01) {
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+		}
+	} else {
+		insl(NE_BASE + NE_DATAPORT, buf, count>>2);
+		if (count & 3) {
+			buf += count & ~3;
+			if (count & 2)
+				*((u16*)buf)++ = le16_to_cpu(inw(NE_BASE + NE_DATAPORT));
+			if (count & 1)
+				*buf = inb(NE_BASE + NE_DATAPORT);
+		}
 	}
-#endif
 
 	outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
 	ei_status.dmaing &= ~0x01;
@@ -527,15 +536,18 @@
 
 	/* On little-endian it's always safe to round the count up for
 	   word writes. */
-	if (count & 0x01)
-		count++;
+	if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+		count = (count + 3) & 0xFFFC;
+	else
+		if (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 ne2k_pci_block_output."
-			   "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
+			   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
 			   dev->name, ei_status.dmaing, ei_status.irqlock,
-			   dev->interrupt);
+			   (int)dev->interrupt);
 		return;
 	}
 	ei_status.dmaing |= 0x01;
@@ -561,16 +573,16 @@
 	outb(0x00, nic_base + EN0_RSARLO);
 	outb(start_page, nic_base + EN0_RSARHI);
 	outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-#if defined(USE_LONGIO)
-	outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
-	if (count & 3) {
-		buf += count & ~3;
-		if (count & 2)
-			outw(*((u16*)buf)++, NE_BASE + NE_DATAPORT);
+	if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
+		if (count & 3) {
+			buf += count & ~3;
+			if (count & 2)
+				outw(cpu_to_le16(*((u16*)buf)++), NE_BASE + NE_DATAPORT);
+		}
 	}
-#else
-	outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-#endif
 
 	dma_start = jiffies;
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/net_init.c linux.pre11.3/drivers/net/net_init.c
--- linux.vanilla/drivers/net/net_init.c	Wed Apr 28 19:14:27 1999
+++ linux.pre11.3/drivers/net/net_init.c	Tue Jul 20 00:00:21 1999
@@ -107,6 +107,8 @@
 		alloc_size &= ~3;		/* Round to dword boundary. */
 
 		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		if(dev==NULL)
+			return NULL;
 		memset(dev, 0, alloc_size);
 		if (sizeof_priv)
 			dev->priv = (void *) (dev + 1);
@@ -225,6 +227,8 @@
 		alloc_size &= ~3;		/* Round to dword boundary. */
 
 		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		if(dev==NULL)
+			return NULL;
 		memset(dev, 0, alloc_size);
 		if (sizeof_priv)
 			dev->priv = (void *) (dev + 1);
@@ -551,6 +555,8 @@
 
 		alloc_size &= ~3;		/* Round to dword boundary. */
 		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		if(dev==NULL)
+			return NULL;
 		memset(dev, 0, alloc_size);
 		if (sizeof_priv)
 			dev->priv = (void *) (dev + 1);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/olympic.c linux.pre11.3/drivers/net/olympic.c
--- linux.vanilla/drivers/net/olympic.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/olympic.c	Tue Jul 20 00:00:32 1999
@@ -0,0 +1,1661 @@
+/*
+ *   olympic.c (c) 1999 Peter De Schrijver All Rights Reserved
+ *		   1999 Mike Phillips (phillim@amtrak.com)
+ *
+ *  Linux driver for IBM PCI tokenring cards based on the Pit/Pit-Phy/Olympic
+ *  chipset. 
+ *
+ *  Base Driver Skeleton:
+ *      Written 1993-94 by Donald Becker.
+ *
+ *      Copyright 1993 United States Government as represented by the
+ *      Director, National Security Agency.
+ *
+ *  Thanks to Erik De Cock, Adrian Bridgett and Frank Fiene for their 
+ *  assistance and perserverance with the testing of this driver.
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ * 
+ *  4/27/99 - Alpha Release 0.1.0
+ *            First release to the public
+ *
+ *  6/8/99  - Official Release 0.2.0   
+ *            Merged into the kernel code 
+ *  
+ *  To Do:
+ *
+ *  Sanitize for smp
+ *
+ *  If Problems do Occur
+ *  Most problems can be rectified by either closing and opening the interface
+ *  (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
+ *  if compiled into the kernel).
+ */
+
+/* Change OLYMPIC_DEBUG to 1 to get verbose, and I mean really verbose, messages */
+
+#define OLYMPIC_DEBUG 0
+
+/* Change OLYMPIC_NETWORK_MONITOR to receive mac frames through the arb channel.
+ * Will also create a /proc/net/olympic_tr entry if proc_fs is compiled into the
+ * kernel.
+ * Intended to be used to create a ring-error reporting network module 
+ * i.e. it will give you the source address of beaconers on the ring 
+ */
+
+#define OLYMPIC_NETWORK_MONITOR 0
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <net/checksum.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+#include "olympic.h"
+
+/* I've got to put some intelligence into the version number so that Peter and I know
+ * which version of the code somebody has got. 
+ * Version Number = a.b.c.d  where a.b.c is the level of code and d is the latest author.
+ * So 0.0.1.pds = Peter, 0.0.1.mlp = Mike
+ * 
+ * Official releases will only have an a.b.c version number format.
+ */
+
+static char *version = 
+"Olympic.c v0.2.0 6/8/99 - Peter De Schrijver & Mike Phillips" ; 
+
+static char *open_maj_error[]  = {"No error", "Lobe Media Test", "Physical Insertion",
+				   "Address Verification", "Neighbor Notification (Ring Poll)",
+				   "Request Parameters","FDX Registration Request",
+				   "FDX Duplicate Address Check", "Station registration Query Wait",
+				   "Unknown stage"};
+
+static char *open_min_error[] = {"No error", "Function Failure", "Signal Lost", "Wire Fault",
+				   "Ring Speed Mismatch", "Timeout","Ring Failure","Ring Beaconing",
+				   "Duplicate Node Address","Request Parameters","Remove Received",
+				   "Reserved", "Reserved", "No Monitor Detected for RPL", 
+				   "Monitor Contention failer for RPL", "FDX Protocol Error"};
+
+/* Module paramters */
+
+/* Ring Speed 0,4,16,100 
+ * 0 = Autosense         
+ * 4,16 = Selected speed only, no autosense
+ * This allows the card to be the first on the ring
+ * and become the active monitor.
+ * 100 = Nothing at present, 100mbps is autodetected
+ * if FDX is turned on. May be implemented in the future to 
+ * fail if 100mpbs is not detected.
+ *
+ * WARNING: Some hubs will allow you to insert
+ * at the wrong speed
+ */
+
+static int ringspeed[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+
+MODULE_PARM(ringspeed, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i");
+
+/* Packet buffer size */
+
+static int pkt_buf_sz[OLYMPIC_MAX_ADAPTERS] = {0,} ;
+ 
+MODULE_PARM(pkt_buf_sz, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ; 
+
+/* Message Level */
+
+static int message_level[OLYMPIC_MAX_ADAPTERS] = {0,} ; 
+
+MODULE_PARM(message_level, "1-" __MODULE_STRING(OLYMPIC_MAX_ADAPTERS) "i") ; 
+
+static int olympic_scan(struct device *dev);
+static int olympic_init(struct device *dev);
+static int olympic_open(struct device *dev);
+static int olympic_xmit(struct sk_buff *skb, struct device *dev);
+static int olympic_close(struct device *dev);
+static void olympic_set_rx_mode(struct device *dev);
+static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct net_device_stats * olympic_get_stats(struct device *dev);
+static int olympic_set_mac_address(struct device *dev, void *addr) ; 
+static void olympic_arb_cmd(struct device *dev);
+static int olympic_change_mtu(struct device *dev, int mtu);
+static void olympic_srb_bh(struct device *dev) ; 
+static void olympic_asb_bh(struct device *dev) ; 
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+static int sprintf_info(char *buffer, struct device *dev) ; 
+#endif
+#endif
+
+__initfunc(int olympic_probe(struct device *dev)) 
+{
+	int cards_found;
+
+	cards_found=olympic_scan(dev);
+	return cards_found ? 0 : -ENODEV;
+}
+
+__initfunc(static int olympic_scan(struct device *dev)) 
+{
+	struct pci_dev *pci_device = NULL ;
+	struct olympic_private *olympic_priv;
+	int card_no = 0 ;
+	if (pci_present()) {
+
+		while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) {
+
+			pci_set_master(pci_device);
+
+			/* Check to see if io has been allocated, if so, we've already done this card,
+			   so continue on the card discovery loop  */
+
+			if (check_region(pci_device->base_address[0] & (~3), OLYMPIC_IO_SPACE)) {
+				card_no++ ; 
+				continue ; 
+			}
+
+			olympic_priv=kmalloc(sizeof (struct olympic_private), GFP_KERNEL);
+			memset(olympic_priv, 0, sizeof(struct olympic_private));
+#ifndef MODULE
+			dev=init_trdev(dev, 0);
+#endif
+			dev->priv=(void *)olympic_priv;
+#if OLYMPIC_DEBUG  
+			printk("pci_device: %p, dev:%p, dev->priv: %p\n", pci_device, dev, dev->priv);
+#endif 
+			dev->irq=pci_device->irq;
+			dev->base_addr=pci_device->base_address[0] & (~3);
+			dev->init=&olympic_init;
+			olympic_priv->olympic_mmio=ioremap(pci_device->base_address[1],256);
+			olympic_priv->olympic_lap=ioremap(pci_device->base_address[2],2048);
+			
+			if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) )
+				olympic_priv->pkt_buf_sz = PKT_BUF_SZ ; 
+			else
+				olympic_priv->pkt_buf_sz = pkt_buf_sz[card_no] ; 
+
+			olympic_priv->olympic_ring_speed = ringspeed[card_no] ; 
+			olympic_priv->olympic_message_level = message_level[card_no] ; 
+			olympic_priv->olympic_multicast_set  = 0 ; 
+	
+			if(olympic_init(dev)==-1) {
+				unregister_netdevice(dev);
+				kfree(dev->priv);
+				return 0;
+			}				
+
+			dev->open=&olympic_open;
+			dev->hard_start_xmit=&olympic_xmit;
+			dev->change_mtu=&olympic_change_mtu;
+
+			dev->stop=&olympic_close;
+			dev->do_ioctl=NULL;
+			dev->set_multicast_list=&olympic_set_rx_mode;
+			dev->get_stats=&olympic_get_stats ;
+			dev->set_mac_address=&olympic_set_mac_address ;  
+			return 1; 
+		}
+	}
+	return  0 ;
+}
+
+
+__initfunc(static int olympic_init(struct device *dev)) 
+{
+    	struct olympic_private *olympic_priv;
+	__u8 *olympic_mmio, *init_srb,*adapter_addr;
+	unsigned long t; 
+	unsigned int uaa_addr;
+
+    	olympic_priv=(struct olympic_private *)dev->priv;
+	olympic_mmio=olympic_priv->olympic_mmio;
+
+	printk("%s \n", version);
+	printk("%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, LAP at %p, using irq %d\n",dev->name, (unsigned int) dev->base_addr,olympic_priv->olympic_mmio, olympic_priv->olympic_lap, dev->irq);
+
+	request_region(dev->base_addr, OLYMPIC_IO_SPACE, "olympic");
+	writel(readl(olympic_mmio+BCTL) | BCTL_SOFTRESET,olympic_mmio+BCTL);
+	t=jiffies;
+	while((readl(olympic_priv->olympic_mmio+BCTL)) & BCTL_SOFTRESET) {
+		schedule();		
+		if(jiffies-t > 40*HZ) {
+			printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
+			release_region(dev->base_addr, OLYMPIC_IO_SPACE) ; 
+			return -1;
+		}
+	}
+
+#if OLYMPIC_DEBUG
+	printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
+	printk("GPR: %x\n",readw(olympic_mmio+GPR));
+	printk("SISRMASK: %x\n",readl(olympic_mmio+SISR_MASK));
+#endif
+	/* Aaaahhh, You have got to be real careful setting GPR, the card
+	   holds the previous values from flash memory, including autosense 
+           and ring speed */
+
+	writel(readl(olympic_mmio+BCTL)|BCTL_MIMREB,olympic_mmio+BCTL);
+	
+	if (olympic_priv->olympic_ring_speed  == 0) { /* Autosense */
+		writel(readl(olympic_mmio+GPR)|GPR_AUTOSENSE,olympic_mmio+GPR);
+		if (olympic_priv->olympic_message_level) 
+			printk(KERN_INFO "%s: Ringspeed autosense mode on\n",dev->name);
+	} else if (olympic_priv->olympic_ring_speed == 16) {
+		if (olympic_priv->olympic_message_level) 
+			printk(KERN_INFO "%s: Trying to open at 16 Mbps as requested\n", dev->name);
+		writel(GPR_16MBPS, olympic_mmio+GPR);
+	} else if (olympic_priv->olympic_ring_speed == 4) {
+		if (olympic_priv->olympic_message_level) 
+			printk(KERN_INFO "%s: Trying to open at 4 Mbps as requested\n", dev->name) ; 
+		writel(0, olympic_mmio+GPR);
+	} 
+	
+	writel(readl(olympic_mmio+GPR)|GPR_NEPTUNE_BF,olympic_mmio+GPR);
+
+#if OLYMPIC_DEBUG
+	printk("GPR = %x\n",readw(olympic_mmio + GPR) ) ; 
+#endif
+	/* start solo init */
+	writel((1<<15),olympic_mmio+SISR_MASK_SUM);
+
+	t=jiffies;
+	while(!((readl(olympic_mmio+SISR_RR)) & SISR_SRB_REPLY)) {
+		schedule();		
+		if(jiffies-t > 40*HZ) {
+			printk(KERN_ERR "IBM PCI tokenring card not responding.\n");
+			release_region(dev->base_addr, OLYMPIC_IO_SPACE); 
+			return -1;
+		}
+	}
+	
+	writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+
+#if OLYMPIC_DEBUG
+	printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));
+#endif
+
+	init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800));
+
+#if OLYMPIC_DEBUG		
+{
+	int i;
+	printk("init_srb(%p): ",init_srb);
+	for(i=0;i<20;i++)
+		printk("%x ",readb(init_srb+i));
+	printk("\n");
+}
+#endif	
+	if(readw(init_srb+6)) {
+		printk(KERN_INFO "tokenring card intialization failed. errorcode : %x\n",readw(init_srb+6));
+		release_region(dev->base_addr, OLYMPIC_IO_SPACE);
+		return -1;
+	}
+
+	uaa_addr=ntohs(readw(init_srb+8));
+
+#if OLYMPIC_DEBUG
+	printk("UAA resides at %x\n",uaa_addr);
+#endif
+
+	writel(uaa_addr,olympic_mmio+LAPA);
+	adapter_addr=olympic_priv->olympic_lap + (uaa_addr & (~0xf800));
+
+#if OLYMPIC_DEBUG
+	printk("adapter address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+			readb(adapter_addr), readb(adapter_addr+1),readb(adapter_addr+2),
+			readb(adapter_addr+3),readb(adapter_addr+4),readb(adapter_addr+5));
+#endif
+
+	memcpy_fromio(&dev->dev_addr[0], adapter_addr,6);
+
+	olympic_priv->olympic_addr_table_addr = ntohs(readw(init_srb + 12)) ; 
+	olympic_priv->olympic_parms_addr      = ntohs(readw(init_srb + 14)) ; 
+
+	return 0;
+
+}
+
+static int olympic_open(struct device *dev) 
+{
+	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+	__u8 *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
+	unsigned long flags;
+	char open_error[255] ; 
+	int i, open_finished = 1 ;
+
+#if OLYMPIC_NETWORK_MONITOR
+	__u8 *oat ; 
+	__u8 *opt ; 
+#endif
+
+	if(request_irq(dev->irq, &olympic_interrupt, SA_SHIRQ , "olympic", dev)) {
+		return -EAGAIN;
+	}
+
+#if OLYMPIC_DEBUG
+	printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));
+	printk("pending ints: %x\n",readl(olympic_mmio+SISR_RR));
+#endif
+
+	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
+	writel(SISR_MI | SISR_SRB_REPLY, olympic_mmio+SISR_MASK); /* more ints later, doesn't stop arb cmd interrupt */
+
+	writel(LISR_LIE,olympic_mmio+LISR); /* more ints later */
+
+	/* adapter is closed, so SRB is pointed to by LAPWWO */
+
+	writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+	init_srb=olympic_priv->olympic_lap + ((readl(olympic_mmio+LAPWWO)) & (~0xf800));
+	
+#if OLYMPIC_DEBUG
+	printk("LAPWWO: %x, LAPA: %x\n",readl(olympic_mmio+LAPWWO), readl(olympic_mmio+LAPA));
+	printk("SISR Mask = %04x\n", readl(olympic_mmio+SISR_MASK));
+	printk("Before the open command \n");
+#endif	
+	do {
+		int i;
+
+		save_flags(flags);
+		cli();
+		for(i=0;i<SRB_COMMAND_SIZE;i+=4)
+			writel(0,init_srb+i);
+		if(SRB_COMMAND_SIZE & 2)
+			writew(0,init_srb+(SRB_COMMAND_SIZE & ~3));
+		if(SRB_COMMAND_SIZE & 1)
+			writeb(0,init_srb+(SRB_COMMAND_SIZE & ~1));
+
+		writeb(SRB_OPEN_ADAPTER,init_srb) ; 	/* open */
+		writeb(OLYMPIC_CLEAR_RET_CODE,init_srb+2);
+
+		/* If Network Monitor, instruct card to copy MAC frames through the ARB */
+
+#if OLYMPIC_NETWORK_MONITOR
+		writew(ntohs(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON),init_srb+8);
+#else
+		writew(OPEN_ADAPTER_ENABLE_FDX,init_srb+8);
+#endif		
+
+		if (olympic_priv->olympic_laa[0]) {
+			writeb(olympic_priv->olympic_laa[0],init_srb+12);
+			writeb(olympic_priv->olympic_laa[1],init_srb+13);
+			writeb(olympic_priv->olympic_laa[2],init_srb+14);
+			writeb(olympic_priv->olympic_laa[3],init_srb+15);
+			writeb(olympic_priv->olympic_laa[4],init_srb+16);
+			writeb(olympic_priv->olympic_laa[5],init_srb+17);
+			memcpy(dev->dev_addr,olympic_priv->olympic_laa,dev->addr_len) ;  
+		} 	
+		writeb(1,init_srb+30);
+	
+		olympic_priv->srb_queued=1;
+
+		writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+ 		while(olympic_priv->srb_queued) {        
+        		interruptible_sleep_on_timeout(&olympic_priv->srb_wait, 60*HZ);
+        		if(signal_pending(current))	{            
+				printk(KERN_WARNING "%s: SRB timed out.\n",
+                			dev->name);
+            			printk(KERN_WARNING "SISR=%x MISR=%x\n",
+                			readl(olympic_mmio+SISR),
+                			readl(olympic_mmio+LISR));
+            			olympic_priv->srb_queued=0;
+            			break;
+        		}
+    		}
+		restore_flags(flags);
+#if OLYMPIC_DEBUG
+		printk("init_srb(%p): ",init_srb);
+		for(i=0;i<20;i++)
+			printk("%x ",readb(init_srb+i));
+		printk("\n");
+#endif
+		
+		/* If we get the same return response as we set, the interrupt wasn't raised and the open
+                 * timed out.
+		 */
+
+		if(readb(init_srb+2)== OLYMPIC_CLEAR_RET_CODE) {
+			printk(KERN_WARNING "%s: Adapter Open time out or error.\n", dev->name) ; 
+			return -EIO ; 
+		}	
+
+		if(readb(init_srb+2)!=0) {
+			if (readb(init_srb+2) == 0x07) {  
+				if (!olympic_priv->olympic_ring_speed && open_finished) { /* Autosense , first time around */
+					printk(KERN_WARNING "%s: Retrying at different ring speed \n", dev->name); 
+					open_finished = 0 ;  
+				} else {
+
+					strcpy(open_error, open_maj_error[(readb(init_srb+7) & 0xf0) >> 4]) ; 
+					strcat(open_error," - ") ; 
+					strcat(open_error, open_min_error[(readb(init_srb+7) & 0x0f)]) ;
+
+					if (!olympic_priv->olympic_ring_speed && ((readb(init_srb+7) & 0x0f) == 0x0d)) { 
+						printk(KERN_WARNING "%s: Tried to autosense ring speed with no monitors present\n",dev->name);
+						printk(KERN_WARNING "%s: Please try again with a specified ring speed \n",dev->name);
+						free_irq(dev->irq, dev);
+						return -EIO ;
+					}
+
+					printk(KERN_WARNING "%s: %s\n",dev->name,open_error);
+					free_irq(dev->irq,dev) ; 
+					return -EIO ; 
+ 
+				}	/* if autosense && open_finished */
+			} else {  
+				printk(KERN_WARNING "%s: Bad OPEN response: %x\n", dev->name,init_srb[2]);
+				free_irq(dev->irq, dev);
+				return -EIO;
+			} 
+		} else 
+			open_finished = 1 ; 
+	} while (!(open_finished)) ; /* Will only loop if ring speed mismatch re-open attempted && autosense is on */	
+
+	if (readb(init_srb+18) & (1<<3)) 
+		if (olympic_priv->olympic_message_level) 
+			printk(KERN_INFO "%s: Opened in FDX Mode\n",dev->name);
+
+	if (readb(init_srb+18) & (1<<1))
+		olympic_priv->olympic_ring_speed = 100 ; 
+	else if (readb(init_srb+18) & 1)
+		olympic_priv->olympic_ring_speed = 16 ; 
+	else
+		olympic_priv->olympic_ring_speed = 4 ; 
+
+	if (olympic_priv->olympic_message_level) 
+		printk(KERN_INFO "%s: Opened in %d Mbps mode\n",dev->name, olympic_priv->olympic_ring_speed);
+
+	olympic_priv->asb=ntohs(readw(init_srb+8));
+	olympic_priv->srb=ntohs(readw(init_srb+10));
+	olympic_priv->arb=ntohs(readw(init_srb+12));
+	olympic_priv->trb=ntohs(readw(init_srb+16));
+
+	olympic_priv->olympic_receive_options = 0x01 ; 
+	olympic_priv->olympic_copy_all_options = 0 ; 
+	
+	/* setup rx ring */
+	
+	writel((3<<16),olympic_mmio+BMCTL_RWM); /* Ensure end of frame generated interrupts */ 
+
+	writel(BMCTL_RX_DIS|3,olympic_mmio+BMCTL_RWM); /* Yes, this the enables RX channel */
+
+	for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+
+		struct sk_buff *skb;
+		
+		skb=dev_alloc_skb(olympic_priv->pkt_buf_sz);
+		if(skb == NULL)
+			break;
+
+		skb->dev = dev;
+
+		olympic_priv->olympic_rx_ring[i].buffer=virt_to_bus(skb->data);
+		olympic_priv->olympic_rx_ring[i].res_length = olympic_priv->pkt_buf_sz ; 
+		olympic_priv->rx_ring_skb[i]=skb;
+	}
+
+	if (i==0) {
+		printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled\n",dev->name);
+		free_irq(dev->irq, dev);
+		return -EIO;
+	}
+
+	writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXDESCQ);
+	writel(virt_to_bus(&olympic_priv->olympic_rx_ring[0]),olympic_mmio+RXCDA);
+	writew(i,olympic_mmio+RXDESCQCNT);
+		
+	writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXSTATQ);
+	writel(virt_to_bus(&olympic_priv->olympic_rx_status_ring[0]),olympic_mmio+RXCSA);
+	
+ 	olympic_priv->rx_ring_last_received=OLYMPIC_RX_RING_SIZE-1;	/* last processed rx status */
+	olympic_priv->rx_status_last_received = OLYMPIC_RX_RING_SIZE-1;  
+
+	writew(i,olympic_mmio+RXSTATQCNT);
+
+#if OLYMPIC_DEBUG 
+	printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));
+	printk("RXCSA: %x, rx_status_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]);
+	printk(" stat_ring[1]: %p, stat_ring[2]: %p, stat_ring[3]: %p\n", &(olympic_priv->olympic_rx_status_ring[1]), &(olympic_priv->olympic_rx_status_ring[2]), &(olympic_priv->olympic_rx_status_ring[3]) );
+	printk(" stat_ring[4]: %p, stat_ring[5]: %p, stat_ring[6]: %p\n", &(olympic_priv->olympic_rx_status_ring[4]), &(olympic_priv->olympic_rx_status_ring[5]), &(olympic_priv->olympic_rx_status_ring[6]) );
+	printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7])  );
+
+	printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]);
+#endif
+
+	writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);
+
+#if OLYMPIC_DEBUG 
+	printk("# of rx buffers: %d, RXENQ: %x\n",i, readw(olympic_mmio+RXENQ));
+	printk("RXCSA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCSA)),&olympic_priv->olympic_rx_status_ring[0]);
+	printk("RXCDA: %x, rx_ring[0]: %p\n",bus_to_virt(readl(olympic_mmio+RXCDA)),&olympic_priv->olympic_rx_ring[0]);
+#endif 
+
+	writel(SISR_RX_STATUS | SISR_RX_NOBUF,olympic_mmio+SISR_MASK_SUM);
+
+	/* setup tx ring */
+
+	writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */
+	for(i=0;i<OLYMPIC_TX_RING_SIZE;i++) 
+		olympic_priv->olympic_tx_ring[i].buffer=0xdeadbeef;
+
+	olympic_priv->free_tx_ring_entries=OLYMPIC_TX_RING_SIZE;
+	writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXDESCQ_1);
+	writel(virt_to_bus(&olympic_priv->olympic_tx_ring[0]),olympic_mmio+TXCDA_1);
+	writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXDESCQCNT_1);
+	
+	writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXSTATQ_1);
+	writel(virt_to_bus(&olympic_priv->olympic_tx_status_ring[0]),olympic_mmio+TXCSA_1);
+	writew(OLYMPIC_TX_RING_SIZE,olympic_mmio+TXSTATQCNT_1);
+		
+	olympic_priv->tx_ring_free=0; /* next entry in tx ring to use */
+	olympic_priv->tx_ring_last_status=OLYMPIC_TX_RING_SIZE-1; /* last processed tx status */
+
+	writel(SISR_TX1_EOF | SISR_ADAPTER_CHECK | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_ASB_FREE,olympic_mmio+SISR_MASK_SUM);
+
+#if OLYMPIC_DEBUG 
+	printk("BMCTL: %x\n",readl(olympic_mmio+BMCTL_SUM));
+	printk("SISR MASK: %x\n",readl(olympic_mmio+SISR_MASK));
+#endif
+
+#if OLYMPIC_NETWORK_MONITOR
+	oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
+	opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
+
+	printk("%s: Node Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, 
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), 
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5));
+	printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name, 
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), 
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
+		    readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));
+
+	printk("%s: NAUN Address: %02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, 
+			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),
+			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),
+			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),
+			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),
+			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),
+			readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5));
+
+
+#endif 	
+	
+	dev->start = 1;
+	dev->interrupt=0;
+	dev->tbusy=0;
+
+	MOD_INC_USE_COUNT ;
+	return 0;
+	
+}	
+
+/*
+ *	When we enter the rx routine we do not know how many frames have been 
+ *	queued on the rx channel.  Therefore we start at the next rx status
+ *	position and travel around the receive ring until we have completed
+ *	all the frames.
+ *
+ *	This means that we may process the frame before we receive the end
+ *	of frame interrupt. This is why we always test the status instead
+ *	of blindly processing the next frame.
+ *	
+ */
+static void olympic_rx(struct device *dev)
+{
+	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	struct olympic_rx_status *rx_status;
+	struct olympic_rx_desc *rx_desc ; 
+	int rx_ring_last_received,length, buffer_cnt, cpy_length, frag_len;
+	struct sk_buff *skb, *skb2;
+	int i;
+
+	rx_status=&(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received + 1) & (OLYMPIC_RX_RING_SIZE - 1)]) ; 
+ 
+	while (rx_status->status_buffercnt) { 
+
+		olympic_priv->rx_status_last_received++ ;
+		olympic_priv->rx_status_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+#if OLYMPIC_DEBUG
+		printk(" stat_ring addr: %x \n", &(olympic_priv->olympic_rx_status_ring[olympic_priv->rx_status_last_received]) ); 
+		printk("rx status: %x rx len: %x \n",rx_status->status_buffercnt,rx_status->fragmentcnt_framelen);	
+#endif
+		length=rx_status->fragmentcnt_framelen & 0xffff;
+		buffer_cnt = rx_status->status_buffercnt & 0xffff ; 
+		i = buffer_cnt ; /* Need buffer_cnt later for rxenq update */ 
+		frag_len = rx_status->fragmentcnt_framelen >> 16 ; 
+
+#if OLYMPIC_DEBUG 
+		printk("length: %x, frag_len: %x, buffer_cnt: %x\n",length,frag_len,buffer_cnt);
+#endif
+
+		if(rx_status->status_buffercnt & 0xC0000000) {
+			if (rx_status->status_buffercnt & 0x3B000000) {
+				if (olympic_priv->olympic_message_level) {
+					if (rx_status->status_buffercnt & (1<<29))  /* Rx Frame Truncated */
+						printk(KERN_WARNING "%s: Rx Frame Truncated \n",dev->name);
+					if (rx_status->status_buffercnt & (1<<28)) /*Rx receive overrun */
+						printk(KERN_WARNING "%s: Rx Frame Receive overrun \n",dev->name);
+					if (rx_status->status_buffercnt & (1<<27)) /* No receive buffers */
+						printk(KERN_WARNING "%s: No receive buffers \n",dev->name);
+					if (rx_status->status_buffercnt & (1<<25)) /* Receive frame error detect */
+						printk(KERN_WARNING "%s: Receive frame error detect \n",dev->name);
+					if (rx_status->status_buffercnt & (1<<24)) /* Received Error Detect */
+						printk(KERN_WARNING "%s: Received Error Detect \n",dev->name);
+				} 
+				olympic_priv->rx_ring_last_received += i ; 
+				olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ; 
+				olympic_priv->olympic_stats.rx_errors++;	 
+			} else {	
+			
+				if (buffer_cnt == 1) {
+					skb = dev_alloc_skb(olympic_priv->pkt_buf_sz) ; 
+				} else {
+					skb = dev_alloc_skb(length) ; 
+				}
+
+				if (skb == NULL) {
+					printk(KERN_WARNING "%s: Not enough memory to copy packet to upper layers. \n",dev->name) ;
+					olympic_priv->olympic_stats.rx_dropped++ ; 
+					/* Update counters even though we don't transfer the frame */
+					olympic_priv->rx_ring_last_received += i ; 
+					olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1) ;  
+				} else  {
+					skb->dev = dev ; 
+
+					/* Optimise based upon number of buffers used. 
+			   	   	   If only one buffer is used we can simply swap the buffers around.
+			   	   	   If more than one then we must use the new buffer and copy the information
+			   	   	   first. Ideally all frames would be in a single buffer, this can be tuned by
+                               	   	   altering the buffer size. */
+				
+ 					if (buffer_cnt==1) {
+						olympic_priv->rx_ring_last_received++ ; 
+						olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+						rx_ring_last_received = olympic_priv->rx_ring_last_received ;
+						skb2=olympic_priv->rx_ring_skb[rx_ring_last_received] ; 
+						skb_put(skb2,length);
+						skb2->protocol = tr_type_trans(skb2,dev);
+						olympic_priv->olympic_rx_ring[rx_ring_last_received].buffer=virt_to_bus(skb->data);
+						olympic_priv->olympic_rx_ring[rx_ring_last_received].res_length = olympic_priv->pkt_buf_sz ; 
+						olympic_priv->rx_ring_skb[rx_ring_last_received] = skb ; 
+						netif_rx(skb2) ; 
+					} else {
+						do { /* Walk the buffers */ 
+							olympic_priv->rx_ring_last_received++ ; 
+							olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE -1);
+							rx_ring_last_received = olympic_priv->rx_ring_last_received ; 
+							rx_desc = &(olympic_priv->olympic_rx_ring[rx_ring_last_received]);
+							cpy_length = (i == 1 ? frag_len : rx_desc->res_length); 
+							memcpy(skb_put(skb, cpy_length), bus_to_virt(rx_desc->buffer), cpy_length) ; 
+						} while (--i) ; 
+		
+						skb->protocol = tr_type_trans(skb,dev);
+						netif_rx(skb) ; 
+					} 
+					olympic_priv->olympic_stats.rx_packets++ ; 
+					olympic_priv->olympic_stats.rx_bytes += length ; 
+				} /* if skb == null */
+			} /* If status & 0x3b */
+
+		} else { /*if buffercnt & 0xC */
+			olympic_priv->rx_ring_last_received += i ; 
+			olympic_priv->rx_ring_last_received &= (OLYMPIC_RX_RING_SIZE - 1) ; 
+		} 
+
+		rx_status->fragmentcnt_framelen = 0 ; 
+		rx_status->status_buffercnt = 0 ; 
+		rx_status = &(olympic_priv->olympic_rx_status_ring[(olympic_priv->rx_status_last_received+1) & (OLYMPIC_RX_RING_SIZE -1) ]);
+
+		writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) |  buffer_cnt , olympic_mmio+RXENQ); 
+	} /* while */
+
+}
+
+static void olympic_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+{
+	struct device *dev= (struct device *)dev_id;
+	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	__u32 sisr;
+	__u8 *adapter_check_area ; 
+	
+	sisr=readl(olympic_mmio+SISR_RR) ; /* Reset sisr */ 
+	
+	if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 
+		return ;
+
+	if (dev->interrupt) 
+		printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; 
+
+	dev->interrupt = 1 ; 
+
+	if (sisr & (SISR_SRB_REPLY | SISR_TX1_EOF | SISR_RX_STATUS | SISR_ADAPTER_CHECK |  
+			SISR_ASB_FREE | SISR_ARB_CMD | SISR_TRB_REPLY | SISR_RX_NOBUF)) {  
+	
+		if(sisr & SISR_SRB_REPLY) {
+			if(olympic_priv->srb_queued==1) {
+				wake_up_interruptible(&olympic_priv->srb_wait);
+			} else if (olympic_priv->srb_queued==2) { 
+				olympic_srb_bh(dev) ; 
+			}
+			olympic_priv->srb_queued=0;
+		} /* SISR_SRB_REPLY */
+
+		if (sisr & SISR_TX1_EOF) {
+			olympic_priv->tx_ring_last_status++;
+			olympic_priv->tx_ring_last_status &= (OLYMPIC_TX_RING_SIZE-1);
+			olympic_priv->free_tx_ring_entries++;
+			olympic_priv->olympic_stats.tx_bytes += olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]->len;
+			olympic_priv->olympic_stats.tx_packets++ ; 
+			dev_kfree_skb(olympic_priv->tx_ring_skb[olympic_priv->tx_ring_last_status]);
+			olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_last_status].buffer=0xdeadbeef;
+			olympic_priv->olympic_tx_status_ring[olympic_priv->tx_ring_last_status].status=0;
+
+			if(dev->tbusy) {
+				dev->tbusy=0;
+				mark_bh(NET_BH);
+			}
+		} /* SISR_TX1_EOF */
+	
+		if (sisr & SISR_RX_STATUS) {
+			olympic_rx(dev);
+		} /* SISR_RX_STATUS */
+	
+		if (sisr & SISR_ADAPTER_CHECK) {
+			printk(KERN_WARNING "%s: Adapter Check Interrupt Raised, 8 bytes of information follow:\n", dev->name);
+			writel(readl(olympic_mmio+LAPWWO),olympic_mmio+LAPA);
+			adapter_check_area = (__u8 *)(olympic_mmio+LAPWWO) ; 
+			printk(KERN_WARNING "%s: Bytes %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",dev->name, readb(adapter_check_area+0), readb(adapter_check_area+1), readb(adapter_check_area+2), readb(adapter_check_area+3), readb(adapter_check_area+4), readb(adapter_check_area+5), readb(adapter_check_area+6), readb(adapter_check_area+7)) ; 
+			dev->interrupt = 0  ; 	
+			free_irq(dev->irq, dev) ; 
+	
+		} /* SISR_ADAPTER_CHECK */
+	
+		if (sisr & SISR_ASB_FREE) {
+			/* Wake up anything that is waiting for the asb response */  
+			if (olympic_priv->asb_queued) {
+				olympic_asb_bh(dev) ; 
+			}
+		} /* SISR_ASB_FREE */
+	
+		if (sisr & SISR_ARB_CMD) {
+			olympic_arb_cmd(dev) ; 
+		} /* SISR_ARB_CMD */
+	
+		if (sisr & SISR_TRB_REPLY) {
+			/* Wake up anything that is waiting for the trb response */
+			if (olympic_priv->trb_queued) {
+				wake_up_interruptible(&olympic_priv->trb_wait);
+			}
+			olympic_priv->trb_queued = 0 ; 
+		} /* SISR_TRB_REPLY */	
+	
+		if (sisr & SISR_RX_NOBUF) {
+			/* According to the documentation, we don't have to do anything, but trapping it keeps it out of
+                  	   	   /var/log/messages.  */
+		} /* SISR_RX_NOBUF */
+	} else { 
+		printk(KERN_WARNING "%s: Unexpected interrupt: %x\n",dev->name, sisr);
+		printk(KERN_WARNING "%s: SISR_MASK: %x\n",dev->name, readl(olympic_mmio+SISR_MASK)) ;
+	} /* One if the interrupts we want */
+
+	dev->interrupt = 0 ;  
+
+	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
+}	
+
+static int olympic_xmit(struct sk_buff *skb, struct device *dev) 
+{
+	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+    __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		return 1;
+	}
+
+	if(olympic_priv->free_tx_ring_entries) {
+		olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data);
+		olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000);
+		olympic_priv->tx_ring_skb[olympic_priv->tx_ring_free]=skb;
+		olympic_priv->free_tx_ring_entries--;
+
+        	olympic_priv->tx_ring_free++;
+        	olympic_priv->tx_ring_free &= (OLYMPIC_TX_RING_SIZE-1);
+
+
+		writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
+
+		dev->tbusy=0;		
+
+		return 0;
+	} else 
+		return 1;
+
+}
+	
+
+static int olympic_close(struct device *dev) 
+{
+	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+    	__u8 *olympic_mmio=olympic_priv->olympic_mmio,*srb;
+	unsigned long flags;
+	int i;
+
+	writel(olympic_priv->srb,olympic_mmio+LAPA);
+	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+	
+    	writeb(SRB_CLOSE_ADAPTER,srb+0);
+	writeb(0,srb+1);
+	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+
+	save_flags(flags);
+	cli();	
+
+	olympic_priv->srb_queued=1;
+
+	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+	while(olympic_priv->srb_queued) {
+	        interruptible_sleep_on_timeout(&olympic_priv->srb_wait, jiffies+60*HZ);
+        	if(signal_pending(current))	{            
+			printk(KERN_WARNING "%s: SRB timed out.\n",
+                		dev->name);
+            		printk(KERN_WARNING "SISR=%x MISR=%x\n",
+                	readl(olympic_mmio+SISR),
+                	readl(olympic_mmio+LISR));
+            		olympic_priv->srb_queued=0;
+            		break;
+        	}
+    	}
+
+	restore_flags(flags) ; 
+	olympic_priv->rx_status_last_received++;
+	olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+	
+	for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+		dev_kfree_skb(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+		olympic_priv->rx_status_last_received++;
+		olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+	}
+
+	/* reset tx/rx fifo's and busmaster logic */
+
+	writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
+	udelay(1);
+	writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
+
+#if OLYMPIC_DEBUG
+	printk("srb(%p): ",srb);
+	for(i=0;i<4;i++)
+		printk("%x ",readb(srb+i));
+	printk("\n");
+#endif
+    	dev->start = 0;
+	free_irq(dev->irq,dev);
+
+	MOD_DEC_USE_COUNT ; 
+	return 0;
+	
+}
+
+static void olympic_set_rx_mode(struct device *dev) 
+{
+	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
+   	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
+	__u8 options = 0, set_mc_list = 0 ; 
+	__u8 *srb, *ata ;
+	struct dev_mc_list *dmi ; 
+
+	writel(olympic_priv->srb,olympic_mmio+LAPA);
+	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+	options = olympic_priv->olympic_copy_all_options; 
+
+	if (dev->flags&IFF_PROMISC)  
+		options |= (3<<5) ; /* All LLC and MAC frames, all through the main rx channel */  
+	else
+		options &= ~(3<<5) ; 
+
+	if (dev->mc_count) {  
+		set_mc_list = 1 ; 
+	}
+
+	/* Only issue the srb if there is a change in options */
+
+	if ((options ^ olympic_priv->olympic_copy_all_options)) { 
+	
+		/* Now to issue the srb command to alter the copy.all.options */
+	
+		writeb(SRB_MODIFY_RECEIVE_OPTIONS,srb);
+		writeb(0,srb+1);
+		writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+		writeb(0,srb+3);
+		writeb(olympic_priv->olympic_receive_options,srb+4);
+		writeb(options,srb+5);
+
+		olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+		writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+		olympic_priv->olympic_copy_all_options = options ;
+		
+		return ;  
+	} 
+
+	if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */ 
+
+		dmi = dev->mc_list ; 
+
+		if (set_mc_list) { /* Turn multicast on */
+
+			/* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00
+                         * We do this with a set functional address mask.
+			 */
+						
+			ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
+			if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */ 
+				writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+				writeb(0,srb+1);
+				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+				writeb(0,srb+3);
+				writeb(0,srb+4);
+				writeb(0,srb+5);
+				writeb(readb(ata+10),srb+6);
+				writeb(readb(ata+11)|4,srb+7);
+				writeb(readb(ata+12),srb+8);
+				writeb(readb(ata+13),srb+9);
+			
+				olympic_priv->srb_queued = 2 ; 
+				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+				olympic_priv->olympic_multicast_set = 1 ;  
+			}    
+
+
+		} else { /* Turn multicast off */
+	
+			ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
+			if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */ 
+				writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+				writeb(0,srb+1);
+				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+				writeb(0,srb+3);
+				writeb(0,srb+4);
+				writeb(0,srb+5);
+				writeb(readb(ata+10),srb+6);
+				writeb(readb(ata+11) & ~4,srb+7);
+				writeb(readb(ata+12),srb+8);
+				writeb(readb(ata+13),srb+9);
+			
+				olympic_priv->srb_queued = 2 ; 
+				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);	
+
+				olympic_priv->olympic_multicast_set = 0 ; 
+			}
+		} 		
+
+	}
+
+
+}
+
+static void olympic_srb_bh(struct device *dev) 
+{ 
+	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
+   	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
+	__u8 *srb;
+
+	writel(olympic_priv->srb,olympic_mmio+LAPA);
+	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
+
+	switch (readb(srb)) { 
+
+		/* SRB_MODIFY_RECEIVE_OPTIONS i.e. set_multicast_list options (promiscuous) 
+                 * At some point we should do something if we get an error, such as
+                 * resetting the IFF_PROMISC flag in dev
+		 */
+
+		case SRB_MODIFY_RECEIVE_OPTIONS:
+			switch (readb(srb+2)) { 
+				case 0x01:
+					printk(KERN_WARNING "%s: Unrecognized srb command\n",dev->name) ; 
+					break ; 
+				case 0x04:
+					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name);
+					break ; 
+				default:
+					if (olympic_priv->olympic_message_level) 
+						printk(KERN_WARNING "%s: Receive Options Modified to %x,%x\n",dev->name,olympic_priv->olympic_copy_all_options, olympic_priv->olympic_receive_options) ; 
+					break ; 	
+			} /* switch srb[2] */ 
+			break ;
+		
+		/* SRB_SET_GROUP_ADDRESS - Multicast group setting 
+                 */
+
+		case SRB_SET_GROUP_ADDRESS:
+			switch (readb(srb+2)) { 
+				case 0x00:
+					olympic_priv->olympic_multicast_set = 1 ; 
+					break ; 
+				case 0x01:
+					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
+					break ;
+				case 0x04:
+					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name); 
+					break ;
+				case 0x3c:
+					printk(KERN_WARNING "%s: Group/Functional address indicator bits not set correctly\n",dev->name) ; 
+					break ;
+				case 0x3e: /* If we ever implement individual multicast addresses, will need to deal with this */
+					printk(KERN_WARNING "%s: Group address registers full\n",dev->name) ; 
+					break ;  
+				case 0x55:
+					printk(KERN_INFO "%s: Group Address already set.\n",dev->name) ; 
+					break ;
+				default:
+					break ; 
+			} /* switch srb[2] */ 
+			break ; 
+
+		/* SRB_RESET_GROUP_ADDRESS - Remove a multicast address from group list
+ 		 */
+
+		case SRB_RESET_GROUP_ADDRESS:
+			switch (readb(srb+2)) { 
+				case 0x00:
+					olympic_priv->olympic_multicast_set = 0 ; 
+					break ; 
+				case 0x01:
+					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
+					break ; 
+				case 0x04:
+					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 
+					break ; 
+				case 0x39: /* Must deal with this if individual multicast addresses used */
+					printk(KERN_INFO "%s: Group address not found \n",dev->name); 
+					break ;
+				default:
+					break ; 
+			} /* switch srb[2] */
+			break ; 
+
+		
+		/* SRB_SET_FUNC_ADDRESS - Called by the set_rx_mode 
+		 */
+
+		case SRB_SET_FUNC_ADDRESS:
+			switch (readb(srb+2)) { 
+				case 0x00:
+					if (olympic_priv->olympic_message_level)
+						printk(KERN_INFO "%s: Functional Address Mask Set \n",dev->name) ; 
+					break ;
+				case 0x01:
+					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
+					break ; 
+				case 0x04:
+					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 
+					break ; 
+				default:
+					break ; 
+			} /* switch srb[2] */
+			break ; 
+	
+		/* SRB_READ_LOG - Read and reset the adapter error counters
+ 		 */
+
+		case SRB_READ_LOG:
+			switch (readb(srb+2)) { 
+				case 0x00: 
+					if (olympic_priv->olympic_message_level) 
+						printk(KERN_INFO "%s: Read Log issued\n",dev->name) ; 
+					break ; 
+				case 0x01:
+					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
+					break ; 
+				case 0x04:
+					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 
+					break ; 
+			
+			} /* switch srb[2] */
+			break ; 
+		
+		/* SRB_READ_SR_COUNTERS - Read and reset the source routing bridge related counters */
+
+		case SRB_READ_SR_COUNTERS:
+			switch (readb(srb+2)) { 
+				case 0x00: 
+					if (olympic_priv->olympic_message_level) 
+						printk(KERN_INFO "%s: Read Source Routing Counters issued\n",dev->name) ; 
+					break ; 
+				case 0x01:
+					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
+					break ; 
+				case 0x04:
+					printk(KERN_WARNING "%s: Adapter must be open for this operation, doh!!\n",dev->name) ; 
+					break ; 
+				default:
+					break ; 
+			} /* switch srb[2] */
+			break ;
+ 
+		default:
+			printk(KERN_WARNING "%s: Unrecognized srb bh return value.\n",dev->name);
+			break ; 
+	} /* switch srb[0] */
+
+} 
+
+static struct net_device_stats * olympic_get_stats(struct device *dev)
+{
+	struct olympic_private *olympic_priv ;
+	olympic_priv=(struct olympic_private *) dev->priv;
+	return (struct net_device_stats *) &olympic_priv->olympic_stats; 
+}
+
+static int olympic_set_mac_address (struct device *dev, void *addr) 
+{
+	struct sockaddr *saddr = addr ; 
+	struct olympic_private *olympic_priv = (struct olympic_private *)dev->priv ; 
+
+	if (dev->start) { 
+		printk(KERN_WARNING "%s: Cannot set mac/laa address while card is open\n", dev->name) ; 
+		return -EIO ; 
+	}
+
+	memcpy(olympic_priv->olympic_laa, saddr->sa_data,dev->addr_len) ; 
+	
+	if (olympic_priv->olympic_message_level) { 
+ 		printk(KERN_INFO "%s: MAC/LAA Set to  = %x.%x.%x.%x.%x.%x\n",dev->name, olympic_priv->olympic_laa[0],
+		olympic_priv->olympic_laa[1], olympic_priv->olympic_laa[2],
+		olympic_priv->olympic_laa[3], olympic_priv->olympic_laa[4],
+		olympic_priv->olympic_laa[5]);
+	} 
+
+	return 0 ; 
+}
+
+static void olympic_arb_cmd(struct device *dev)
+{
+	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
+    	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	__u8 *arb_block, *asb_block, *srb  ; 
+	__u8 header_len ; 
+	__u16 frame_len, buffer_len ;
+	struct sk_buff *mac_frame ;  
+	__u8 *buf_ptr ;
+	__u8 *frame_data ;  
+	__u16 buff_off ; 
+	__u16 lan_status = 0, lan_status_diff  ; /* Initialize to stop compiler warning */
+	__u8 fdx_prot_error ; 
+	__u16 next_ptr;
+
+#if OLYMPIC_NETWORK_MONITOR
+	struct trh_hdr *mac_hdr ; 
+#endif
+
+	arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 
+	asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 
+	srb = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->srb) ; 
+	writel(readl(olympic_mmio+LAPA),olympic_mmio+LAPWWO);
+
+	if (readb(arb_block+0) == ARB_RECEIVE_DATA) { /* Receive.data, MAC frames */
+
+		header_len = readb(arb_block+8) ; /* 802.5 Token-Ring Header Length */	
+		frame_len = ntohs(readw(arb_block + 10)) ; 
+
+		buff_off = ntohs(readw(arb_block + 6)) ;
+		
+		buf_ptr = olympic_priv->olympic_lap + buff_off ; 
+
+#if OLYMPIC_DEBUG
+{
+		int i;
+		frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; 
+
+		for (i=0 ;  i < 14 ; i++) { 
+			printk("Loc %d = %02x\n",i,readb(frame_data + i)); 
+		}
+
+		printk("next %04x, fs %02x, len %04x \n",readw(buf_ptr+offsetof(struct mac_receive_buffer,next)), readb(buf_ptr+offsetof(struct mac_receive_buffer,frame_status)), readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); 
+}
+#endif 
+		mac_frame = dev_alloc_skb(frame_len) ; 
+
+		/* Walk the buffer chain, creating the frame */
+
+		do {
+			frame_data = buf_ptr+offsetof(struct mac_receive_buffer,frame_data) ; 
+			buffer_len = ntohs(readw(buf_ptr+offsetof(struct mac_receive_buffer,buffer_length))); 
+			memcpy_fromio(skb_put(mac_frame, buffer_len), frame_data , buffer_len ) ;
+			next_ptr=readw(buf_ptr+offsetof(struct mac_receive_buffer,next)); 
+
+		} while (next_ptr && (buf_ptr=olympic_priv->olympic_lap + ntohs(next_ptr)));
+
+#if OLYMPIC_NETWORK_MONITOR
+		printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name) ;
+		mac_hdr = (struct trh_hdr *)mac_frame->data ; 
+		printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->daddr[0], mac_hdr->daddr[1], mac_hdr->daddr[2], mac_hdr->daddr[3], mac_hdr->daddr[4], mac_hdr->daddr[5]) ; 
+		printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %02x:%02x:%02x:%02x:%02x:%02x \n", dev->name , mac_hdr->saddr[0], mac_hdr->saddr[1], mac_hdr->saddr[2], mac_hdr->saddr[3], mac_hdr->saddr[4], mac_hdr->saddr[5]) ; 
+#endif
+		mac_frame->dev = dev ; 
+		mac_frame->protocol = tr_type_trans(mac_frame,dev);
+		netif_rx(mac_frame) ; 	
+
+		/* Now tell the card we have dealt with the received frame */
+
+		/* Set LISR Bit 1 */
+		writel(LISR_ARB_FREE,olympic_priv->olympic_lap + LISR_SUM);
+
+		/* Is the ASB free ? */ 	
+		
+		if (!(readl(olympic_priv->olympic_mmio + SISR) & SISR_ASB_FREE)) {
+			olympic_priv->asb_queued = 1 ; 
+			writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); 
+			return ; 	
+			/* Drop out and wait for the bottom half to be run */
+		}
+		
+		writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */
+		writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */
+		writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */
+		writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */		
+
+		writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+		
+		olympic_priv->asb_queued = 2 ; 
+	
+		return ; 	
+		
+	} else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */
+		lan_status = readw(arb_block+6);
+		fdx_prot_error = readb(arb_block+8) ; 
+		
+		/* Issue ARB Free */
+		writel(LISR_ARB_FREE,olympic_priv->olympic_mmio+LISR_SUM);
+
+		lan_status_diff = olympic_priv->olympic_lan_status ^ lan_status ; 
+
+		if (lan_status_diff & (LSC_LWF | LSC_ARW | LSC_FPE | LSC_RR) ) { 
+			if (lan_status_diff & LSC_LWF) 
+					printk(KERN_WARNING "%s: Short circuit detected on the lobe\n",dev->name);
+			if (lan_status_diff & LSC_ARW) 
+					printk(KERN_WARNING "%s: Auto removal error\n",dev->name);
+			if (lan_status_diff & LSC_FPE)
+					printk(KERN_WARNING "%s: FDX Protocol Error\n",dev->name);
+			if (lan_status_diff & LSC_RR) 
+					printk(KERN_WARNING "%s: Force remove MAC frame received\n",dev->name);
+		
+			/* Adapter has been closed by the hardware */
+		
+			/* reset tx/rx fifo's and busmaster logic */
+
+			writel(readl(olympic_mmio+BCTL)|(3<<13),olympic_mmio+BCTL);
+			udelay(1);
+			writel(readl(olympic_mmio+BCTL)&~(3<<13),olympic_mmio+BCTL);
+			dev->tbusy = 1 ;
+			dev->interrupt = 1 ; 
+			dev->start = 0 ; 
+			olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; 
+			free_irq(dev->irq,dev);
+			
+			printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; 
+	
+		} /* If serious error */
+		
+		if (olympic_priv->olympic_message_level) { 
+			if (lan_status_diff & LSC_SIG_LOSS) 
+					printk(KERN_WARNING "%s: No receive signal detected \n", dev->name) ; 
+			if (lan_status_diff & LSC_HARD_ERR)
+					printk(KERN_INFO "%s: Beaconing \n",dev->name);
+			if (lan_status_diff & LSC_SOFT_ERR)
+					printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame \n",dev->name);
+			if (lan_status_diff & LSC_TRAN_BCN) 
+					printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+			if (lan_status_diff & LSC_SS) 
+					printk(KERN_INFO "%s: Single Station on the ring \n", dev->name);
+			if (lan_status_diff & LSC_RING_REC)
+					printk(KERN_INFO "%s: Ring recovery ongoing\n",dev->name);
+			if (lan_status_diff & LSC_FDX_MODE)
+					printk(KERN_INFO "%s: Operating in FDX mode\n",dev->name);
+		} 	
+		
+		if (lan_status_diff & LSC_CO) { 
+					
+				if (olympic_priv->olympic_message_level) 
+					printk(KERN_INFO "%s: Counter Overflow \n", dev->name);
+					
+				/* Issue READ.LOG command */
+
+				writeb(SRB_READ_LOG, srb);
+				writeb(0,srb+1);
+				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+				writeb(0,srb+3);
+				writeb(0,srb+4);
+				writeb(0,srb+5);
+					
+				olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+					
+		}
+
+		if (lan_status_diff & LSC_SR_CO) { 
+
+				if (olympic_priv->olympic_message_level)
+					printk(KERN_INFO "%s: Source routing counters overflow\n", dev->name);
+
+				/* Issue a READ.SR.COUNTERS */
+				
+				writeb(SRB_READ_SR_COUNTERS,srb);
+				writeb(0,srb+1);
+				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+				writeb(0,srb+3);
+				
+				olympic_priv->srb_queued=2; /* Can't sleep, use srb_bh */
+
+				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
+
+		}
+
+		olympic_priv->olympic_lan_status = lan_status ; 
+	
+	}  /* Lan.change.status */
+	else
+		printk(KERN_WARNING "%s: Unknown arb command \n", dev->name);
+}
+
+static void olympic_asb_bh(struct device *dev) 
+{
+	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
+	__u8 *arb_block, *asb_block ; 
+
+	arb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->arb) ; 
+	asb_block = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->asb) ; 
+
+	if (olympic_priv->asb_queued == 1) {   /* Dropped through the first time */
+
+		writeb(ASB_RECEIVE_DATA,asb_block); /* Receive data */
+		writeb(OLYMPIC_CLEAR_RET_CODE,asb_block+2); /* Necessary ?? */
+		writeb(readb(arb_block+6),asb_block+6); /* Must send the address back to the adapter */
+		writeb(readb(arb_block+7),asb_block+7); /* To let it know we have dealt with the data */		
+
+		writel(LISR_ASB_REPLY | LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM);
+		olympic_priv->asb_queued = 2 ; 
+
+		return ; 
+	}
+
+	if (olympic_priv->asb_queued == 2) { 
+		switch (readb(asb_block+2)) {
+			case 0x01:
+				printk(KERN_WARNING "%s: Unrecognized command code \n", dev->name);
+				break ;
+			case 0x26:
+				printk(KERN_WARNING "%s: Unrecognized buffer address \n", dev->name);
+				break ;
+			case 0xFF:
+				/* Valid response, everything should be ok again */
+				break ;
+			default:
+				printk(KERN_WARNING "%s: Invalid return code in asb\n",dev->name);
+				break ;
+		}
+	}
+	olympic_priv->asb_queued = 0 ; 
+}
+ 
+static int olympic_change_mtu(struct device *dev, int mtu) 
+{
+	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv;
+	__u16 max_mtu ; 
+
+	if (olympic_priv->olympic_ring_speed == 4)
+		max_mtu = 4500 ; 
+	else
+		max_mtu = 18000 ; 
+	
+	if (mtu > max_mtu)
+		return -EINVAL ; 
+	if (mtu < 100) 
+		return -EINVAL ; 
+
+	dev->mtu = mtu ; 
+	olympic_priv->pkt_buf_sz = mtu + TR_HLEN ; 
+
+	return 0 ; 
+}
+
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+static int olympic_proc_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
+{
+	struct pci_dev *pci_device = NULL ;
+	int len=0;
+	off_t begin=0;
+	off_t pos=0;
+	int size;
+	
+	struct device *dev;
+
+
+	size = sprintf(buffer, 
+		"IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapters\n");
+	
+	pos+=size;
+	len+=size;
+	
+
+	while((pci_device=pci_find_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, pci_device))) {
+	
+		for (dev = dev_base; dev != NULL; dev = dev->next) 
+		{
+			if (dev->base_addr == (pci_device->base_address[0] & (~3)) ) { /* Yep, an Olympic device */	
+				size = sprintf_info(buffer+len, dev);
+				len+=size;
+				pos=begin+len;
+				
+				if(pos<offset)
+				{
+					len=0;
+					begin=pos;
+				}
+				if(pos>offset+length)
+					break;
+			} /* if */
+		} /* for */
+	} /* While */
+
+	*start=buffer+(offset-begin);	/* Start of wanted data */
+	len-=(offset-begin);		/* Start slop */
+	if(len>length)
+		len=length;		/* Ending slop */
+	return len;
+}
+
+static int sprintf_info(char *buffer, struct device *dev)
+{
+	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
+	__u8 *oat = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr) ; 
+	__u8 *opt = (__u8 *)(olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr) ; 
+	int size = 0 ; 
+		
+	size = sprintf(buffer, "\n%6s: Adapter Address   : Node Address      : Functional Addr\n",
+ 	   dev->name); 
+
+	size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x\n",
+	   dev->name,
+           dev->dev_addr[0],
+	   dev->dev_addr[1],
+	   dev->dev_addr[2],
+ 	   dev->dev_addr[3],
+	   dev->dev_addr[4],
+	   dev->dev_addr[5],
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)), 
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+1),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+2),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+3),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+4),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+5),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)), 
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
+	   readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+3));
+	 
+	size += sprintf(buffer+size, "\n%6s: Token Ring Parameters Table:\n", dev->name);
+
+	size += sprintf(buffer+size, "%6s: Physical Addr : Up Node Address   : Poll Address      : AccPri : Auth Src : Att Code :\n",
+	  dev->name) ; 
+	   
+	size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x   : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x:%02x:%02x : %04x   : %04x     :  %04x    :\n",
+	  dev->name,
+	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)),
+	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1),
+	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2),
+	  readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3),
+	  readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)),
+	  readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+1),
+	  readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+2),
+	  readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+3),
+	  readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+4),
+	  readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+5),
+	  readb(opt+offsetof(struct olympic_parameters_table, poll_addr)),
+	  readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+1),
+	  readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+2),
+	  readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+3),
+	  readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+4),
+	  readb(opt+offsetof(struct olympic_parameters_table, poll_addr)+5),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, att_code))));
+
+	size += sprintf(buffer+size, "%6s: Source Address    : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n",
+	  dev->name) ; 
+	
+	size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x:%02x:%02x : %04x  : %04x   : %04x   : %04x   : %04x    :     %04x     : \n",
+	  dev->name,
+	  readb(opt+offsetof(struct olympic_parameters_table, source_addr)),
+	  readb(opt+offsetof(struct olympic_parameters_table, source_addr)+1),
+	  readb(opt+offsetof(struct olympic_parameters_table, source_addr)+2),
+	  readb(opt+offsetof(struct olympic_parameters_table, source_addr)+3),
+	  readb(opt+offsetof(struct olympic_parameters_table, source_addr)+4),
+	  readb(opt+offsetof(struct olympic_parameters_table, source_addr)+5),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, major_vector))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, lan_status))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, local_ring))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, mon_error))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, frame_correl))));
+
+	size += sprintf(buffer+size, "%6s: Beacon Details :  Tx  :  Rx  : NAUN Node Address : NAUN Node Phys : \n",
+	  dev->name) ; 
+
+	size += sprintf(buffer+size, "%6s:                :  %02x  :  %02x  : %02x:%02x:%02x:%02x:%02x:%02x : %02x:%02x:%02x:%02x    : \n",
+	  dev->name,
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))),
+	  ntohs(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+1),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+2),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+3),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+4),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_naun)+5),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2),
+	  readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+3));
+
+ 
+	return size;
+}
+#endif
+#endif 
+
+#ifdef MODULE
+
+static struct device* dev_olympic[OLYMPIC_MAX_ADAPTERS];
+
+int init_module(void)
+{
+        int i;
+
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry *ent ; 
+
+	ent = create_proc_entry("net/olympic_tr",0,0); 
+	ent->read_proc = &olympic_proc_info ; 
+#endif
+#endif
+        for (i = 0; (i<OLYMPIC_MAX_ADAPTERS); i++) {
+		dev_olympic[i] = NULL;
+                dev_olympic[i] = init_trdev(dev_olympic[i], 0);
+                if (dev_olympic[i] == NULL)
+                        return -ENOMEM;
+
+		dev_olympic[i]->init      = &olympic_probe;
+
+	        if (register_trdev(dev_olympic[i]) != 0) {
+			kfree_s(dev_olympic[i], sizeof(struct device));
+			dev_olympic[i] = NULL;
+		        if (i == 0) {
+			        printk("Olympic: No IBM PCI Token Ring cards found in system.\n");
+		                return -EIO;
+			} else {
+			       	printk("Olympic: %d IBM PCI Token Ring card(s) found in system.\n",i) ; 
+				return 0;
+			}
+	        }
+	}
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+        int i;
+
+        for (i = 0; i < OLYMPIC_MAX_ADAPTERS; i++)
+	        if (dev_olympic[i]) {
+			 unregister_trdev(dev_olympic[i]);
+			 release_region(dev_olympic[i]->base_addr, OLYMPIC_IO_SPACE);
+			 kfree_s(dev_olympic[i]->priv, sizeof(struct olympic_private));
+			 kfree_s(dev_olympic[i], sizeof(struct device));
+			 dev_olympic[i] = NULL;
+                }
+
+#if OLYMPIC_NETWORK_MONITOR
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("net/olympic_tr", NULL) ; 
+#endif 
+#endif
+}
+#endif /* MODULE */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/olympic.h linux.pre11.3/drivers/net/olympic.h
--- linux.vanilla/drivers/net/olympic.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/olympic.h	Mon Jul 19 23:27:35 1999
@@ -0,0 +1,303 @@
+/*
+ *  olympic.h (c) 1999 Peter De Schrijver All Rights Reserved
+ *                1999 Mike Phillips (phillim@amtrak.com)
+ *
+ *  Linux driver for IBM PCI tokenring cards based on the olympic and the PIT/PHY chipset.
+ *
+ *  Base Driver Skeleton:
+ *      Written 1993-94 by Donald Becker.
+ *
+ *      Copyright 1993 United States Government as represented by the
+ *      Director, National Security Agency.
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ */
+
+#define CID 0x4e
+
+#define BCTL 0x70
+#define BCTL_SOFTRESET (1<<15)
+#define BCTL_MIMREB (1<<6)
+
+#define GPR 0x4a
+#define GPR_OPTI_BF (1<<6)
+#define GPR_NEPTUNE_BF (1<<4) 
+#define GPR_AUTOSENSE (1<<2)
+#define GPR_16MBPS (1<<3) 
+
+#define PAG 0x85
+#define LBC 0x8e
+
+#define LISR 0x10
+#define LISR_SUM 0x14
+#define LISR_RWM 0x18
+
+#define LISR_LIE (1<<15)
+#define LISR_SLIM (1<<13)
+#define LISR_SLI (1<<12)
+#define LISR_PCMSRMASK (1<<11)
+#define LISR_PCMSRINT (1<<10)
+#define LISR_WOLMASK (1<<9)
+#define LISR_WOL (1<<8)
+#define LISR_SRB_CMD (1<<5)
+#define LISR_ASB_REPLY (1<<4)
+#define LISR_ASB_FREE_REQ (1<<2)
+#define LISR_ARB_FREE (1<<1)
+#define LISR_TRB_FRAME (1<<0)
+
+#define SISR 0x20
+#define SISR_SUM 0x24
+#define SISR_RWM 0x28
+#define SISR_RR 0x2C
+#define SISR_RESMASK 0x30
+#define SISR_MASK 0x54
+#define SISR_MASK_SUM 0x58
+#define SISR_MASK_RWM 0x5C
+
+#define SISR_TX2_IDLE (1<<31)
+#define SISR_TX2_HALT (1<<29)
+#define SISR_TX2_EOF (1<<28)
+#define SISR_TX1_IDLE (1<<27)
+#define SISR_TX1_HALT (1<<25)
+#define SISR_TX1_EOF (1<<24)
+#define SISR_TIMEOUT (1<<23)
+#define SISR_RX_NOBUF (1<<22)
+#define SISR_RX_STATUS (1<<21)
+#define SISR_RX_HALT (1<<18)
+#define SISR_RX_EOF_EARLY (1<<16)
+#define SISR_MI (1<<15)
+#define SISR_PI (1<<13)
+#define SISR_ERR (1<<9)
+#define SISR_ADAPTER_CHECK (1<<6)
+#define SISR_SRB_REPLY (1<<5)
+#define SISR_ASB_FREE (1<<4)
+#define SISR_ARB_CMD (1<<3)
+#define SISR_TRB_REPLY (1<<2)
+
+#define EISR 0x34
+#define EISR_RWM 0x38
+#define EISR_MASK 0x3c
+
+#define LAPA 0x60
+#define LAPWWO 0x64
+#define LAPWWC 0x68
+#define LAPCTL 0x6C
+#define LAIPD 0x78
+#define LAIPDDINC 0x7C
+
+#define TIMER 0x50
+
+#define CLKCTL 0x74
+
+#define PM_CON 0x4
+
+#define BMCTL_SUM 0x40
+#define BMCTL_RWM 0x44
+#define BMCTL_TX2_DIS (1<<30) 
+#define BMCTL_TX1_DIS (1<<26) 
+#define BMCTL_RX_DIS (1<<22) 
+
+#define BMASR 0xcc
+
+#define RXDESCQ 0x90
+#define RXDESCQCNT 0x94
+#define RXCDA 0x98
+#define RXENQ 0x9C
+#define RXSTATQ 0xA0
+#define RXSTATQCNT 0xA4
+#define RXCSA 0xA8
+#define RXCLEN 0xAC
+#define RXHLEN 0xAE
+
+#define TXDESCQ_1 0xb0
+#define TXDESCQ_2 0xd0
+#define TXDESCQCNT_1 0xb4
+#define TXDESCQCNT_2 0xd4
+#define TXCDA_1 0xb8
+#define TXCDA_2 0xd8
+#define TXENQ_1 0xbc
+#define TXENQ_2 0xdc
+#define TXSTATQ_1 0xc0
+#define TXSTATQ_2 0xe0
+#define TXSTATQCNT_1 0xc4
+#define TXSTATQCNT_2 0xe4
+#define TXCSA_1 0xc8
+#define TXCSA_2 0xe8
+
+#define OLYMPIC_IO_SPACE 256
+
+#define SRB_COMMAND_SIZE 50
+
+#define OLYMPIC_MAX_ADAPTERS 8 /* 0x08 __MODULE_STRING can't hand 0xnn */
+
+/* Defines for LAN STATUS CHANGE reports */
+#define LSC_SIG_LOSS 0x8000
+#define LSC_HARD_ERR 0x4000
+#define LSC_SOFT_ERR 0x2000
+#define LSC_TRAN_BCN 0x1000
+#define LSC_LWF      0x0800
+#define LSC_ARW      0x0400
+#define LSC_FPE      0x0200
+#define LSC_RR       0x0100
+#define LSC_CO       0x0080
+#define LSC_SS       0x0040
+#define LSC_RING_REC 0x0020
+#define LSC_SR_CO    0x0010
+#define LSC_FDX_MODE 0x0004
+
+/* Defines for OPEN ADAPTER command */
+
+#define OPEN_ADAPTER_EXT_WRAP (1<<15)
+#define OPEN_ADAPTER_DIS_HARDEE (1<<14)
+#define OPEN_ADAPTER_DIS_SOFTERR (1<<13)
+#define OPEN_ADAPTER_PASS_ADC_MAC (1<<12)
+#define OPEN_ADAPTER_PASS_ATT_MAC (1<<11)
+#define OPEN_ADAPTER_ENABLE_EC (1<<10)
+#define OPEN_ADAPTER_CONTENDER (1<<8)
+#define OPEN_ADAPTER_PASS_BEACON (1<<7)
+#define OPEN_ADAPTER_ENABLE_FDX (1<<6)
+#define OPEN_ADAPTER_ENABLE_RPL (1<<5)
+#define OPEN_ADAPTER_INHIBIT_ETR (1<<4)
+#define OPEN_ADAPTER_INTERNAL_WRAP (1<<3)
+#define OPEN_ADAPTER_USE_OPTS2 (1<<0)
+
+#define OPEN_ADAPTER_2_ENABLE_ONNOW (1<<15)
+
+/* Defines for SRB Commands */
+
+#define SRB_ACCESS_REGISTER 0x1f
+#define SRB_CLOSE_ADAPTER 0x04
+#define SRB_CONFIGURE_BRIDGE 0x0c
+#define SRB_CONFIGURE_WAKEUP_EVENT 0x1a
+#define SRB_MODIFY_BRIDGE_PARMS 0x15
+#define SRB_MODIFY_OPEN_OPTIONS 0x01
+#define SRB_MODIFY_RECEIVE_OPTIONS 0x17
+#define SRB_NO_OPERATION 0x00
+#define SRB_OPEN_ADAPTER 0x03
+#define SRB_READ_LOG 0x08
+#define SRB_READ_SR_COUNTERS 0x16
+#define SRB_RESET_GROUP_ADDRESS 0x02
+#define SRB_SAVE_CONFIGURATION 0x1b
+#define SRB_SET_BRIDGE_PARMS 0x09
+#define SRB_SET_BRIDGE_TARGETS 0x10
+#define SRB_SET_FUNC_ADDRESS 0x07
+#define SRB_SET_GROUP_ADDRESS 0x06
+#define SRB_SET_GROUP_ADDR_OPTIONS 0x11
+#define SRB_UPDATE_WAKEUP_PATTERN 0x19
+
+/* Clear return code */
+
+#define OLYMPIC_CLEAR_RET_CODE 0xfe 
+
+/* ARB Commands */
+#define ARB_RECEIVE_DATA 0x81
+#define ARB_LAN_CHANGE_STATUS 0x84
+/* ASB Response commands */
+
+#define ASB_RECEIVE_DATA 0x81
+
+
+/* Olympic defaults for buffers */
+ 
+#define OLYMPIC_RX_RING_SIZE 16 /* should be a power of 2 */
+#define OLYMPIC_TX_RING_SIZE 8 /* should be a power of 2 */
+
+#define PKT_BUF_SZ 4096 /* Default packet size */
+
+/* Olympic data structures */
+
+struct olympic_tx_desc {
+	__u32 buffer;
+	__u32 status_length;
+};
+
+struct olympic_tx_status {
+	__u32 status;
+};
+
+struct olympic_rx_desc {
+	__u32 buffer;
+	__u32 res_length ; 
+};
+
+struct olympic_rx_status {
+	__u32 fragmentcnt_framelen;
+	__u32 status_buffercnt;
+};
+
+struct mac_receive_buffer {
+	__u16 next ; 
+	__u8 padding ; 
+	__u8 frame_status ;
+	__u16 buffer_length ; 
+	__u8 frame_data ; 
+};
+
+struct olympic_private {
+	
+	__u16 srb;
+	__u16 trb;
+	__u16 arb;
+	__u16 asb;
+
+	__u8 *olympic_mmio;
+	__u8 *olympic_lap;
+
+	volatile int srb_queued;    /* True if an SRB is still posted */	
+	struct wait_queue *srb_wait;
+
+	volatile int asb_queued;    /* True if an ASB is posted */
+
+	volatile int trb_queued;   /* True if a TRB is posted */
+	struct wait_queue *trb_wait ; 
+
+	struct olympic_rx_desc olympic_rx_ring[OLYMPIC_RX_RING_SIZE];
+	struct olympic_tx_desc olympic_tx_ring[OLYMPIC_TX_RING_SIZE];
+	struct olympic_rx_status olympic_rx_status_ring[OLYMPIC_RX_RING_SIZE];	
+	struct olympic_tx_status olympic_tx_status_ring[OLYMPIC_TX_RING_SIZE];	
+	struct sk_buff *tx_ring_skb[OLYMPIC_TX_RING_SIZE], *rx_ring_skb[OLYMPIC_RX_RING_SIZE];	
+	int tx_ring_free, tx_ring_last_status, rx_ring_last_received,rx_status_last_received, free_tx_ring_entries;
+
+	struct net_device_stats olympic_stats ;
+	__u16 olympic_lan_status ;
+	__u8 olympic_ring_speed ;
+	__u16 pkt_buf_sz ; 
+	__u8 olympic_receive_options, olympic_copy_all_options, olympic_message_level;  
+	__u8 olympic_multicast_set ; 
+	__u16 olympic_addr_table_addr, olympic_parms_addr ; 
+	__u8 olympic_laa[6] ; 
+};
+
+struct olympic_adapter_addr_table {
+
+	__u8 node_addr[6] ; 
+	__u8 reserved[4] ; 
+	__u8 func_addr[4] ; 
+} ; 
+
+struct olympic_parameters_table { 
+	
+	__u8  phys_addr[4] ; 
+	__u8  up_node_addr[6] ; 
+	__u8  up_phys_addr[6] ; 
+	__u8  poll_addr[6] ; 
+	__u16 reserved ; 
+	__u16 acc_priority ; 
+	__u16 auth_source_class ; 
+	__u16 att_code ; 
+	__u8  source_addr[6] ; 
+	__u16 beacon_type ; 
+	__u16 major_vector ; 
+	__u16 lan_status ; 
+	__u16 soft_error_time ; 
+ 	__u16 reserved1 ; 
+	__u16 local_ring ; 
+	__u16 mon_error ; 
+	__u16 beacon_transmit ; 
+	__u16 beacon_receive ; 
+	__u16 frame_correl ; 
+	__u8  beacon_naun[6] ; 
+	__u32 reserved2 ; 
+	__u8  beacon_phys[4] ; 	
+}; 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/rtl8139.c linux.pre11.3/drivers/net/rtl8139.c
--- linux.vanilla/drivers/net/rtl8139.c	Thu Dec  3 13:48:36 1998
+++ linux.pre11.3/drivers/net/rtl8139.c	Tue Jul 20 00:00:38 1999
@@ -1,6 +1,6 @@
 /* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
 /*
-	Written 1997-1998 by Donald Becker.
+	Written 1997-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
@@ -16,11 +16,11 @@
 	Support and updates available at
 	http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html
 
-	Twister-tuning code contributed by Kinston <shangh@realtek.com.tw>.
+	Twister-tuning table provided by Kinston <shangh@realtek.com.tw>.
 */
 
 static const char *version =
-"rtl8139.c:v1.04 9/22/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
+"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
 
 /* A few user-configurable values. */
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
@@ -178,7 +178,9 @@
    0x10ec, 0x8129, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
  { "RealTek RTL8139 Fast Ethernet",
    0x10ec, 0x8139, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
- { "RealTek RTL8139 Fast Ethernet (mislabeled)",
+ { "SMC1211TX EZCard 10/100 (RealTek RTL8139)",
+   0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
+ { "Accton MPX5030 (RealTek RTL8139)",
    0x1113, 0x1211, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 0x80, rtl8129_probe1},
  {0,},						/* 0 terminated list. */
 };
@@ -235,13 +237,13 @@
 	RxBadAlign=0x0002, RxStatusOK=0x0001,
 };
 
+/* Twister tuning parameters from RealTek.
+   Completely undocumented, but required to tune bad links. */
 enum CSCRBits {
 	CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
 	CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
 	CSCR_LinkDownCmd=0x0f3c0,
-};	
-
-/* Twister tuning parameters from RealTek.  Completely undocumented. */
+};
 unsigned long param[4][4]={
 	{0x0cb39de43,0x0cb39ce43,0x0fb38de03,0x0cb38de43},
 	{0x0cb39de43,0x0cb39ce43,0x0cb39ce83,0x0cb39ce83},
@@ -270,9 +272,10 @@
 	unsigned char *rx_ring;
 	unsigned char *tx_bufs;				/* Tx bounce buffer region. */
 	char phys[4];						/* MII device addresses. */
+	char twistie, twist_cnt;			/* Twister tune state. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;			/* Full-duplex operation requested. */
+	unsigned int duplex_lock:1;
 	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. */
@@ -325,7 +328,7 @@
 	if ( ! pcibios_present())
 		return -ENODEV;
 
-	for (;pci_index < 0xff; pci_index++) {
+	for (; pci_index < 0xff; pci_index++) {
 		u16 vendor, device, pci_command, new_command;
 		int chip_idx, irq;
 		long ioaddr;
@@ -402,9 +405,9 @@
 	return cards_found ? 0 : -ENODEV;
 }
 
-static struct device * rtl8129_probe1(int pci_bus, int pci_devfn,
-									  struct device *dev, long ioaddr,
-									  int irq, int chip_idx, int found_cnt)
+static struct device *rtl8129_probe1(int pci_bus, int pci_devfn,
+									 struct device *dev, long ioaddr,
+									 int irq, int chip_idx, int found_cnt)
 {
 	static int did_version = 0;			/* Already printed version info. */
 	struct rtl8129_private *tp;
@@ -470,9 +473,8 @@
 				   dev->name);
 			tp->phys[0] = -1;
 		}
-	} else {
-			tp->phys[0] = 32;
-	}
+	} else
+		tp->phys[0] = 32;
 
 	/* Put the chip into low-power mode. */
 	outb(0xC0, ioaddr + Cfg9346);
@@ -601,7 +603,7 @@
 	int retval = 0;
 	int i;
 
-	if ((phy_id & 0x1f) == 0) {	/* Really a 8139.  Use internal registers. */
+	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
 		return location < 8 && mii_2_8139_map[location] ?
 			inw(dev->base_addr + mii_2_8139_map[location]) : 0;
 	}
@@ -633,7 +635,7 @@
 	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
 	int i;
 
-	if (phy_id == 32) {			/* Really a 8139.  Use internal registers. */
+	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
 		if (location < 8  &&  mii_2_8139_map[location])
 			outw(value, dev->base_addr + mii_2_8139_map[location]);
 		return;
@@ -678,6 +680,7 @@
 	tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL);
 	tp->rx_ring = kmalloc(RX_BUF_LEN + 16, GFP_KERNEL);
 	if (tp->tx_bufs == NULL ||  tp->rx_ring == NULL) {
+		free_irq(dev->irq, dev);
 		if (tp->tx_bufs)
 			kfree(tp->tx_bufs);
 		if (rtl8129_debug > 0)
@@ -736,7 +739,7 @@
 
 	/* Enable all known interrupts by setting the interrupt mask. */
 	outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
-		| TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
+		 | TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
 
 	if (rtl8129_debug > 1)
 		printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %#lx IRQ %d"
@@ -749,7 +752,7 @@
 	init_timer(&tp->timer);
 	tp->timer.expires = RUN_AT((24*HZ)/10);			/* 2.4 sec. */
 	tp->timer.data = (unsigned long)dev;
-	tp->timer.function = &rtl8129_timer;				/* timer handler */
+	tp->timer.function = &rtl8129_timer;
 	add_timer(&tp->timer);
 
 	return 0;
@@ -760,7 +763,7 @@
 	struct device *dev = (struct device *)data;
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	int next_tick = 0;
+	int next_tick = 60*HZ;
 	int mii_reg5 = mdio_read(dev, tp->phys[0], 5);
 
 	if (! tp->duplex_lock  &&  mii_reg5 != 0xffff) {
@@ -774,8 +777,65 @@
 			outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
 			outb(0x00, ioaddr + Cfg9346);
 		}
-		next_tick = 60*HZ;
 	}
+	/* Check for bogusness. */
+	if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) {
+		int status = inw(ioaddr + IntrStatus);
+		if (status & (TxOK | RxOK)) {	/* Double check */
+			printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n",
+				   dev->name, status);
+			rtl8129_interrupt(dev->irq, dev, 0);
+		}
+	}
+	if (dev->tbusy  &&  jiffies - dev->trans_start >= 2*TX_TIMEOUT)
+		rtl8129_tx_timeout(dev);
+
+#if 0
+	if (tp->twistie) {
+		unsigned int CSCRval = inw(ioaddr + CSCR);		/* Read link status. */
+		if (tp->twistie == 1) {
+			if (CSCRval & CSCR_LinkOKBit) {
+				outw(CSCR_LinkDownOffCmd, ioaddr + CSCR);
+				tp->twistie = 2;
+				next_tick = HZ/10;
+			} else {
+				outw(CSCR_LinkDownCmd, ioaddr + CSCR);
+				outl(FIFOTMS_default,ioaddr + FIFOTMS);
+				outl(PARA78_default ,ioaddr + PARA78);
+				outl(PARA7c_default ,ioaddr + PARA7c);
+				tp->twistie = 0;
+			}
+		} else if (tp->twistie == 2) {
+			int linkcase = (CSCRval & CSCR_LinkStatusBits) >> 12;
+			int row;
+			if (linkcase >= 0x7000) row = 3;
+			else if (linkcase >= 0x3000) row = 2;
+			else if (linkcase >= 0x1000) row = 1;
+			else row = 0;
+			tp->twistie == row + 3;
+			outw(0,ioaddr+FIFOTMS);
+			outl(param[row][0], ioaddr+PARA7c);
+			tp->twist_cnt = 1;
+		} else {
+			outl(param[tp->twistie-3][tp->twist_cnt], ioaddr+PARA7c);
+			if (++tp->twist_cnt < 4) {
+				next_tick = HZ/10;
+			} else if (tp->twistie-3 == 3) {
+				if ((CSCRval & CSCR_LinkStatusBits) != 0x7000) {
+					outl(PARA7c_xxx, ioaddr+PARA7c);
+					next_tick = HZ/10; 		/* 100ms. */
+					outl(FIFOTMS_default, ioaddr+FIFOTMS);
+					outl(PARA78_default,  ioaddr+PARA78);
+					outl(PARA7c_default,  ioaddr+PARA7c);
+					tp->twistie == 3 + 3;
+					outw(0,ioaddr+FIFOTMS);
+					outl(param[3][0], ioaddr+PARA7c);
+					tp->twist_cnt = 1;
+				}
+			}
+		}
+	}
+#endif
 
 	if (rtl8129_debug > 2) {
 		if (rtl_cap_tbl[tp->chip_id] & HAS_MII_XCVR)
@@ -792,10 +852,8 @@
 			   dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1));
 	}
 
-	if (next_tick) {
-		tp->timer.expires = RUN_AT(next_tick);
-		add_timer(&tp->timer);
-	}
+	tp->timer.expires = RUN_AT(next_tick);
+	add_timer(&tp->timer);
 }
 
 static void rtl8129_tx_timeout(struct device *dev)
@@ -861,7 +919,7 @@
 		}
 		tp->cur_tx = i;
 		while (i < NUM_TX_DESC)
-			tp->tx_skbuff[i] = 0;
+			tp->tx_skbuff[i++] = 0;
 		if (tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
 			dev->tbusy = 0;
 			tp->tx_full = 0;
@@ -906,9 +964,8 @@
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		if (jiffies - dev->trans_start < TX_TIMEOUT)
-			return 1;
-		rtl8129_tx_timeout(dev);
+		if (jiffies - dev->trans_start >= TX_TIMEOUT)
+			rtl8129_tx_timeout(dev);
 		return 1;
 	}
 
@@ -925,7 +982,7 @@
 	outl(tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
 		 ioaddr + TxStatus0 + entry*4);
 
-	if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
+	if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {	/* Typical path */
 		clear_bit(0, (void*)&dev->tbusy);
 	} else {
 		tp->tx_full = 1;
@@ -946,7 +1003,7 @@
 	struct device *dev = (struct device *)dev_instance;
 	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
 	int boguscnt = max_interrupt_work;
-	int status;
+	int status, link_changed = 0;
 	long ioaddr = dev->base_addr;
 
 #if defined(__i386__)
@@ -967,7 +1024,10 @@
 
 	do {
 		status = inw(ioaddr + IntrStatus);
-		/* Acknowledge all of the current interrupt sources ASAP. */
+		/* Acknowledge all of the current interrupt sources ASAP, but
+		   an first get an additional status bit from CSCR. */
+		if ((status & RxUnderrun)  &&  inw(ioaddr+CSCR) & CSCR_LinkChangeBit)
+			link_changed = 1;
 		outw(status, ioaddr + IntrStatus);
 
 		if (rtl8129_debug > 4)
@@ -982,9 +1042,9 @@
 			rtl8129_rx(dev);
 
 		if (status & (TxOK | TxErr)) {
-			unsigned int dirty_tx;
+			unsigned int dirty_tx = tp->dirty_tx;
 
-			for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) {
+			while (tp->cur_tx - dirty_tx > 0) {
 				int entry = dirty_tx % NUM_TX_DESC;
 				int txstatus = inl(ioaddr + TxStatus0 + entry*4);
 
@@ -994,11 +1054,9 @@
 				/* Note: TxCarrierLost is always asserted at 100mbps. */
 				if (txstatus & (TxOutOfWindow | TxAborted)) {
 					/* There was an major error, log it. */
-#ifndef final_version
 					if (rtl8129_debug > 1)
 						printk(KERN_NOTICE"%s: Transmit error, Tx status %8.8x.\n",
 							   dev->name, txstatus);
-#endif
 					tp->stats.tx_errors++;
 					if (txstatus&TxAborted) {
 						tp->stats.tx_aborted_errors++;
@@ -1011,9 +1069,6 @@
 						tp->stats.collisions16++;
 #endif
 				} else {
-#ifdef ETHER_STATS
-					/* No count for tp->stats.tx_deferred */
-#endif
 					if (txstatus & TxUnderrun) {
 						/* Add 64 to the Tx FIFO threshold. */
 						if (tp->tx_flag <  0x00300000)
@@ -1030,6 +1085,13 @@
 				/* Free the original skb. */
 				dev_free_skb(tp->tx_skbuff[entry]);
 				tp->tx_skbuff[entry] = 0;
+				if (tp->tx_full) {
+					/* The ring is no longer full, clear tbusy. */
+					tp->tx_full = 0;
+					clear_bit(0, (void*)&dev->tbusy);
+					mark_bh(NET_BH);
+				}
+				dirty_tx++;
 			}
 
 #ifndef final_version
@@ -1039,14 +1101,6 @@
 				dirty_tx += NUM_TX_DESC;
 			}
 #endif
-
-			if (tp->tx_full  &&  dirty_tx > tp->cur_tx - NUM_TX_DESC) {
-				/* The ring is no longer full, clear tbusy. */
-				tp->tx_full = 0;
-				dev->tbusy = 0;
-				mark_bh(NET_BH);
-			}
-
 			tp->dirty_tx = dirty_tx;
 		}
 
@@ -1063,7 +1117,7 @@
 			tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
 			outl(0, ioaddr + RxMissed);
 
-			if ((status & RxUnderrun)  &&
+			if ((status & RxUnderrun)  &&  link_changed  &&
 				(rtl_cap_tbl[tp->chip_id] & HAS_LNK_CHNG)) {
 				/* Really link-change on new chips. */
 				int lpar = inw(ioaddr + NWayLPAR);
@@ -1284,12 +1338,12 @@
 		data[0] = tp->phys[0] & 0x3f;
 		/* Fall Through */
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+		data[3] = mdio_read(dev, data[0], data[1] & 0x1f);
 		return 0;
 	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
-		if (!suser())
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		mdio_write(dev, data[0], data[1] & 0x1f, data[2]);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
@@ -1318,7 +1372,7 @@
 {
     int crc = -1;
 
-    while(--length >= 0) {
+    while (--length >= 0) {
 		unsigned char current_octet = *data++;
 		int bit;
 		for (bit = 0; bit < 8; bit++, current_octet >>= 1)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sealevel.c linux.pre11.3/drivers/net/sealevel.c
--- linux.vanilla/drivers/net/sealevel.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/net/sealevel.c	Mon Jul 19 23:27:35 1999
@@ -0,0 +1,471 @@
+#define LINUX_21
+
+/*
+ *	Sealevel Systems 4021 driver.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	(c) Copyright 1999 Building Number Three Ltd
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <net/arp.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+#include "syncppp.h"
+#include "z85230.h"
+
+
+struct slvl_device
+{
+	struct z8530_channel *chan;
+	struct ppp_device netdev;
+	char name[16];
+	int channel;
+};
+
+
+struct slvl_board
+{
+	struct slvl_device dev[2];
+	struct z8530_dev board;
+	int iobase;
+};
+
+/*
+ *	Network driver support routines
+ */
+
+/*
+ *	Frame receive. Simple for our card as we do sync ppp and there
+ *	is no funny garbage involved
+ */
+ 
+static void sealevel_input(struct z8530_channel *c, struct sk_buff *skb)
+{
+	/* Drop the CRC - its not a good idea to try and negotiate it ;) */
+	skb_trim(skb, skb->len-2);
+	skb->protocol=htons(ETH_P_WAN_PPP);
+	skb->mac.raw=skb->data;
+	skb->dev=c->netdevice;
+	/*
+	 *	Send it to the PPP layer. We dont have time to process
+	 *	it right now.
+	 */
+	netif_rx(skb);
+}
+ 
+/*
+ *	We've been placed in the UP state
+ */ 
+ 
+static int sealevel_open(struct device *d)
+{
+	struct slvl_device *slvl=d->priv;
+	int err = -1;
+	int unit = slvl->channel;
+	
+	/*
+	 *	Link layer up. 
+	 */
+
+	switch(unit)
+	{
+		case 0:
+			err=z8530_sync_dma_open(d, slvl->chan);
+			break;
+		case 1:
+			err=z8530_sync_open(d, slvl->chan);
+			break;
+	}
+	
+	if(err)
+		return err;
+	/*
+	 *	Begin PPP
+	 */
+	err=sppp_open(d);
+	if(err)
+	{
+		switch(unit)
+		{
+			case 0:
+				z8530_sync_dma_close(d, slvl->chan);
+				break;
+			case 1:
+				z8530_sync_close(d, slvl->chan);
+				break;
+		}				
+		return err;
+	}
+	
+	slvl->chan->rx_function=sealevel_input;
+	
+	/*
+	 *	Go go go
+	 */
+	d->tbusy=0;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int sealevel_close(struct device *d)
+{
+	struct slvl_device *slvl=d->priv;
+	int unit = slvl->channel;
+	
+	/*
+	 *	Discard new frames
+	 */
+	
+	slvl->chan->rx_function=z8530_null_rx;
+		
+	/*
+	 *	PPP off
+	 */
+	sppp_close(d);
+	/*
+	 *	Link layer down
+	 */
+	d->tbusy=1;
+	
+	switch(unit)
+	{
+		case 0:
+			z8530_sync_dma_close(d, slvl->chan);
+			break;
+		case 1:
+			z8530_sync_close(d, slvl->chan);
+			break;
+	}
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int sealevel_ioctl(struct device *d, struct ifreq *ifr, int cmd)
+{
+	/* struct slvl_device *slvl=d->priv;
+	   z8530_ioctl(d,&slvl->sync.chanA,ifr,cmd) */
+	return sppp_do_ioctl(d, ifr,cmd);
+}
+
+static struct enet_statistics *sealevel_get_stats(struct device *d)
+{
+	struct slvl_device *slvl=d->priv;
+	if(slvl)
+		return z8530_get_stats(slvl->chan);
+	else
+		return NULL;
+}
+
+/*
+ *	Passed PPP frames, fire them downwind.
+ */
+ 
+static int sealevel_queue_xmit(struct sk_buff *skb, struct device *d)
+{
+	struct slvl_device *slvl=d->priv;
+	return z8530_queue_xmit(slvl->chan, skb);
+}
+
+#ifdef LINUX_21
+static int sealevel_neigh_setup(struct neighbour *n)
+{
+	if (n->nud_state == NUD_NONE) {
+		n->ops = &arp_broken_ops;
+		n->output = n->ops->output;
+	}
+	return 0;
+}
+
+static int sealevel_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
+{
+	if (p->tbl->family == AF_INET) {
+		p->neigh_setup = sealevel_neigh_setup;
+		p->ucast_probes = 0;
+		p->mcast_probes = 0;
+	}
+	return 0;
+}
+
+#else
+
+static int return_0(struct device *d)
+{
+	return 0;
+}
+
+#endif
+
+/*
+ *	Description block for a Comtrol Hostess SV11 card
+ */
+ 
+static struct slvl_board *slvl_init(int iobase, int irq, int txdma, int rxdma, int slow)
+{
+	struct z8530_dev *dev;
+	struct slvl_device *sv;
+	struct slvl_board *b;
+	
+	int i;
+	unsigned long flags;
+	int u;
+	
+	/*
+	 *	Get the needed I/O space
+	 */
+	 
+	if(check_region(iobase, 8))
+	{	
+		printk(KERN_WARNING "sealevel: I/O 0x%X already in use.\n", iobase);
+		return NULL;
+	}
+	request_region(iobase, 8, "Sealevel 4021");
+	
+	b=(struct slvl_board *)kmalloc(sizeof(struct slvl_board), GFP_KERNEL);
+	if(!b)
+		goto fail3;
+			
+	memset(b, 0, sizeof(*sv));
+
+	b->dev[0].chan = &b->board.chanA;	
+	b->dev[1].chan = &b->board.chanB;
+	
+	dev=&b->board;
+	
+	/*
+	 *	Stuff in the I/O addressing
+	 */
+	 
+	dev->active = 0;
+
+	b->iobase = iobase;
+	
+	/*
+	 *	Select 8530 delays for the old board
+	 */
+	 
+	if(slow)
+		iobase |= Z8530_PORT_SLEEP;
+		
+	dev->chanA.ctrlio=iobase+1;
+	dev->chanA.dataio=iobase;
+	dev->chanB.ctrlio=iobase+3;
+	dev->chanB.dataio=iobase+2;
+	
+	dev->chanA.irqs=&z8530_nop;
+	dev->chanB.irqs=&z8530_nop;
+	
+	/*
+	 *	Assert DTR enable DMA
+	 */
+	 
+	outb(3|(1<<7), b->iobase+4);	
+	
+
+	/* We want a fast IRQ for this device. Actually we'd like an even faster
+	   IRQ ;) - This is one driver RtLinux is made for */
+   
+	if(request_irq(irq, &z8530_interrupt, SA_INTERRUPT, "SeaLevel", dev)<0)
+	{
+		printk(KERN_WARNING "sealevel: IRQ %d already in use.\n", irq);
+		goto fail2;
+	}
+	
+	dev->irq=irq;
+	dev->chanA.private=&b->dev[0];
+	dev->chanB.private=&b->dev[1];
+	dev->chanA.netdevice=&b->dev[0].netdev.dev;
+	dev->chanB.netdevice=&b->dev[1].netdev.dev;
+	dev->chanA.dev=dev;
+	dev->chanB.dev=dev;
+	dev->name=b->dev[0].name;
+
+	dev->chanA.txdma=3;
+	dev->chanA.rxdma=1;
+	if(request_dma(dev->chanA.txdma, "SeaLevel (TX)")!=0)
+		goto fail;
+		
+	if(request_dma(dev->chanA.rxdma, "SeaLevel (RX)")!=0)
+		goto dmafail;
+	
+	save_flags(flags);
+	cli();
+	
+	/*
+	 *	Begin normal initialise
+	 */
+	 
+	if(z8530_init(dev)!=0)
+	{
+		printk(KERN_ERR "Z8530 series device not found.\n");
+		goto dmafail2;
+	}
+	if(dev->type==Z85C30)
+	{
+		z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream);
+		z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream);
+	}
+	else
+	{
+		z8530_channel_load(&dev->chanA, z8530_hdlc_kilostream_85230);
+		z8530_channel_load(&dev->chanB, z8530_hdlc_kilostream_85230);
+	}
+
+	/*
+	 *	Now we can take the IRQ
+	 */
+	
+	restore_flags(flags);
+
+	for(u=0; u<2; u++)
+	{
+		sv=&b->dev[u];
+		sv->channel = u;
+	
+		for(i=0;i<999;i++)
+		{
+			sprintf(sv->name,"hdlc%d", i);
+			if(dev_get(sv->name)==NULL)
+			{
+				struct device *d=sv->chan->netdevice;
+	
+				/* 
+				 *	Initialise the PPP components
+				 */
+				sppp_attach(&sv->netdev);
+			
+				/*
+				 *	Local fields
+				 */	
+				sprintf(sv->name,"hdlc%d", i);
+				
+				d->name = sv->name;
+				d->base_addr = iobase;
+				d->irq = irq;
+				d->priv = sv;
+				d->init = NULL;
+			
+				d->open = sealevel_open;
+				d->stop = sealevel_close;
+				d->hard_start_xmit = sealevel_queue_xmit;
+				d->get_stats = sealevel_get_stats;
+				d->set_multicast_list = NULL;
+				d->do_ioctl = sealevel_ioctl;
+#ifdef LINUX_21			
+				d->neigh_setup = sealevel_neigh_setup_dev;
+				dev_init_buffers(d);
+#else
+				d->init = return_0;
+#endif
+				d->set_mac_address = NULL;
+			
+				if(register_netdev(d)==-1)
+				{
+					printk(KERN_ERR "%s: unable to register device.\n",
+						sv->name);
+					goto fail_unit;
+				}				
+
+				break;
+			}
+		}
+	}
+	z8530_describe(dev, "I/O", iobase);
+	dev->active=1;
+	return b;
+
+fail_unit:
+	if(u==1)
+		unregister_netdev(b->dev[0].chan->netdevice);
+	
+dmafail2:
+	free_dma(dev->chanA.rxdma);
+dmafail:
+	free_dma(dev->chanA.txdma);
+fail:
+	free_irq(irq, dev);
+fail2:
+	kfree(b);
+fail3:
+	release_region(iobase,8);
+	return NULL;
+}
+
+static void slvl_shutdown(struct slvl_board *b)
+{
+	int u;
+
+	z8530_shutdown(&b->board);
+	
+	for(u=0; u<2; u++)
+	{
+		sppp_detach(&b->dev[u].netdev.dev);
+		unregister_netdev(&b->dev[u].netdev.dev);
+	}
+	
+	free_irq(b->board.irq, &b->board);
+	free_dma(b->board.chanA.rxdma);
+	free_dma(b->board.chanA.txdma);
+	/* DMA off on the card, drop DTR */
+	outb(0, b->iobase);
+	release_region(b->iobase, 8);
+}
+
+#ifdef MODULE
+
+static int io=0x238;
+static int txdma=1;
+static int rxdma=3;
+static int irq=5;
+static int slow=0;
+
+#ifdef LINUX_21
+MODULE_PARM(io,"i");
+MODULE_PARM_DESC(io, "The I/O base of the Sealevel card");
+MODULE_PARM(txdma,"i");
+MODULE_PARM_DESC(txdma, "Transmit DMA channel");
+MODULE_PARM(rxdma,"i");
+MODULE_PARM_DESC(rxdma, "Receive DMA channel");
+MODULE_PARM(irq,"i");
+MODULE_PARM_DESC(irq, "The interrupt line setting for the SeaLevel card");
+MODULE_PARM(slow,"i");
+MODULE_PARM_DESC(slow, "Set this for an older Sealevel card such as the 4012");
+
+MODULE_AUTHOR("Bulding Number Three Ltd");
+MODULE_DESCRIPTION("Modular driver for the SeaLevel 4021");
+#endif
+
+static struct slvl_board *slvl_unit;
+
+int init_module(void)
+{
+	printk(KERN_INFO "SeaLevel Z85230 Synchronous Driver v 0.01.\n");
+	printk(KERN_INFO "(c) Copyright 1998, Building Number Three Ltd.\n");	
+	if((slvl_unit=slvl_init(io,irq, txdma, rxdma, slow))==NULL)
+		return -ENODEV;
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	if(slvl_unit)
+		slvl_shutdown(slvl_unit);
+}
+
+#endif
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/seeq8005.c linux.pre11.3/drivers/net/seeq8005.c
--- linux.vanilla/drivers/net/seeq8005.c	Thu Dec 31 18:10:43 1998
+++ linux.pre11.3/drivers/net/seeq8005.c	Mon Jul 19 23:27:26 1999
@@ -736,6 +736,54 @@
 		outw( SEEQCMD_WINDOW_INT_ACK | (status & SEEQCMD_INT_MASK), SEEQ_CMD);
 }
 	
+#ifdef MODULE
+
+static char devicename[9] = { 0, };
+
+static struct device dev_seeq =
+{
+	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
+	0, 0, 0, 0,
+	0x300, 5,
+	0, 0, 0, NULL, seeq8005_probe
+};
+
+static int io=0x320;
+static int irq=10;
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+
+int init_module(void)
+{
+	dev_seeq.irq=irq;
+	dev_seeq.base_addr=io;
+	if (register_netdev(&dev_seeq) != 0)
+		return -EIO;
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	/*
+	 *	No need to check MOD_IN_USE, as sys_delete_module() checks.
+	 */
+
+	unregister_netdev(&dev_seeq);
+
+	/*
+	 *	Free up the private structure, or leak memory :-)
+	 */
+
+	kfree(dev_seeq.priv);
+	dev_seeq.priv = NULL;	/* gets re-allocated by el1_probe1 */
+
+	/*
+	 *	If we don't do this, we can't re-insmod it later.
+	 */
+	release_region(dev_seeq.base_addr, EL1_IO_EXTENT);
+}
+
+#endif /* MODULE */
 
 /*
  * Local variables:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sgiseeq.c linux.pre11.3/drivers/net/sgiseeq.c
--- linux.vanilla/drivers/net/sgiseeq.c	Thu Nov 19 18:38:38 1998
+++ linux.pre11.3/drivers/net/sgiseeq.c	Mon Jul 19 23:27:30 1999
@@ -1,11 +1,9 @@
-/*
+/* $Id: sgiseeq.c,v 1.9 1998/10/14 23:40:46 ralf Exp $
+ *
  * sgiseeq.c: Seeq8003 ethernet driver for SGI machines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: sgiseeq.c,v 1.6 1998/10/14 17:29:44 ralf Exp $
  */
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -695,6 +693,7 @@
 	dev->irq                  = irq;
 	dev->dma                  = 0;
 	ether_setup(dev);
+
 	return 0;
 }
 
@@ -724,15 +723,20 @@
 
 int sgiseeq_probe(struct device *dev)
 {
+	static int initialized;
 	char *ep;
 
+	if (initialized)	/* Already initialized? */
+		return 0;
+	initialized++;
+
 	/* First get the ethernet address of the onboard
 	 * interface from ARCS.
+	 * (This is fragile; PROM doesn't like running from cache.)
 	 */
 	ep = romvec->get_evar("eaddr");
 	str2eaddr(onboard_eth_addr, ep);
 	return sgiseeq_init(dev,
 			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
 			    &hpc3c0->ethregs, 3);
-
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sgiseeq.h linux.pre11.3/drivers/net/sgiseeq.h
--- linux.vanilla/drivers/net/sgiseeq.h	Sun Nov  8 15:07:30 1998
+++ linux.pre11.3/drivers/net/sgiseeq.h	Mon Jul 19 23:27:30 1999
@@ -1,4 +1,4 @@
-/* $Id: sgiseeq.h,v 1.1 1997/06/09 08:34:32 ralf Exp $
+/* $Id: sgiseeq.h,v 1.3 1998/08/25 09:17:45 ralf Exp $
  * sgiseeq.h: Defines for the Seeq8003 ethernet controller.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/shaper.c linux.pre11.3/drivers/net/shaper.c
--- linux.vanilla/drivers/net/shaper.c	Tue Jun 15 16:49:50 1999
+++ linux.pre11.3/drivers/net/shaper.c	Mon Jul 19 23:27:29 1999
@@ -51,14 +51,19 @@
  *		will render your machine defunct. Don't for now shape over
  *		PPP or SLIP therefore!
  *		This will be fixed in BETA4
- */
- 
-/*
- * bh_atomic() SMP races fixes and rewritten the locking code to be SMP safe
- * and irq-mask friendly. NOTE: we can't use start_bh_atomic() in kick_shaper()
- * because it's going to be recalled from an irq handler, and synchronize_bh()
- * is a nono if called from irq context.
+ *
+ * Update History :
+ *
+ *              bh_atomic() SMP races fixes and rewritten the locking code to
+ *              be SMP safe and irq-mask friendly.
+ *              NOTE: we can't use start_bh_atomic() in kick_shaper()
+ *              because it's going to be recalled from an irq handler,
+ *              and synchronize_bh() is a nono if called from irq context.
  *						1999  Andrea Arcangeli
+ *
+ *              Device statistics (tx_pakets, tx_bytes,
+ *              tx_drops: queue_over_time and collisions: max_queue_exceded)
+ *                               1999/06/18 Jordi Murgo <savage@apostols.org>
  */
  
 #include <linux/module.h>
@@ -228,18 +233,20 @@
 		/*
 		 *	Queue over time. Spill packet.
 		 */
-		if(skb->shapeclock-jiffies > SHAPER_LATENCY)
+		if(skb->shapeclock-jiffies > SHAPER_LATENCY) {
 			dev_kfree_skb(skb);
-		else
+			shaper->stats.tx_dropped++;
+		} else
 			skb_queue_tail(&shaper->sendq, skb);
 	}
 #endif 	
- 	if(sh_debug)
+	if(sh_debug)
  		printk("Frame queued.\n");
  	if(skb_queue_len(&shaper->sendq)>SHAPER_QLEN)
  	{
  		ptr=skb_dequeue(&shaper->sendq);
- 		dev_kfree_skb(ptr);
+                dev_kfree_skb(ptr);
+                shaper->stats.collisions++;
  	}
  	shaper_unlock(shaper);
  	return 0;
@@ -262,7 +269,11 @@
 			printk("Kick new frame to %s, %d\n",
 				shaper->dev->name,newskb->priority);
 		dev_queue_xmit(newskb);
-		if(sh_debug)
+
+                shaper->stats.tx_bytes+=newskb->len;
+		shaper->stats.tx_packets++;
+
+                if(sh_debug)
 			printk("Kicked new frame out.\n");
 		dev_kfree_skb(skb);
 	}
@@ -415,7 +426,8 @@
 
 static struct net_device_stats *shaper_get_stats(struct device *dev)
 {
-	return NULL;
+     	struct shaper *sh=dev->priv;
+	return &sh->stats;
 }
 
 static int shaper_header(struct sk_buff *skb, struct device *dev, 
@@ -581,7 +593,7 @@
 	skb_queue_head_init(&sh->sendq);
 	init_timer(&sh->timer);
 	sh->timer.function=shaper_timer;
-	sh->timer.data=(unsigned long)sh;
+        sh->timer.data=(unsigned long)sh;
 	return sh;
 }
 
@@ -664,7 +676,9 @@
 
 void cleanup_module(void)
 {
-	/*
+        struct shaper *sh=dev_shape.priv;
+
+        /*
 	 *	No need to check MOD_IN_USE, as sys_delete_module() checks.
 	 *	To be unloadable we must be closed and detached so we don't
 	 *	need to flush things.
@@ -673,10 +687,9 @@
 	unregister_netdev(&dev_shape);
 
 	/*
-	 *	Free up the private structure, or leak memory :-) 
+	 *	Free up the private structure, or leak memory :-)
 	 */
-	 
-	kfree(dev_shape.priv);
+	kfree(sh);
 	dev_shape.priv = NULL;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sonic.c linux.pre11.3/drivers/net/sonic.c
--- linux.vanilla/drivers/net/sonic.c	Sat Jan  9 21:50:42 1999
+++ linux.pre11.3/drivers/net/sonic.c	Mon Jul 19 23:27:30 1999
@@ -1,290 +1,23 @@
 /*
  * sonic.c
  *
- * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
+ * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  * 
  * This driver is based on work from Andreas Busse, but most of
  * the code is rewritten.
  * 
  * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
  *
- * A driver for the onboard Sonic ethernet controller on Mips Jazz
- * systems (Acer Pica-61, Mips Magnum 4000, Olivetti M700 and
- * perhaps others, too)
+ *    Core code included by system sonic drivers
  */
 
-static const char *version =
-	"sonic.c:v0.10 6.7.96 tsbogend@bigbug.franken.de\n";
-
 /*
  * Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
  * National Semiconductors data sheet for the DP83932B Sonic Ethernet
  * controller, and the files "8390.c" and "skeleton.c" in this directory.
  */
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <asm/bootinfo.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/pgtable.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
-#include <linux/errno.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-
-#include "sonic.h"
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifdef SONIC_DEBUG
-static unsigned int sonic_debug = SONIC_DEBUG;
-#else 
-static unsigned int sonic_debug = 2;
-#endif
-
-/*
- * Some tunables for the buffer areas. Power of 2 is required
- * the current driver uses one receive buffer for each descriptor.
- */
-#define SONIC_NUM_RRS    16             /* number of receive resources */
-#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
-#define SONIC_NUM_TDS    16      /* number of transmit descriptors */
-#define SONIC_RBSIZE   1520      /* size of one resource buffer */
-
-#define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK   (SONIC_NUM_TDS-1)
 
-/*
- * Base address and interupt of the SONIC controller on JAZZ boards
- */
-static struct {
-    unsigned int port;
-    unsigned int irq;
-    } sonic_portlist[] = { {JAZZ_ETHERNET_BASE, JAZZ_ETHERNET_IRQ}, {0, 0}};
-
-
-/* Information that need to be kept for each board. */
-struct sonic_local {
-    sonic_cda_t   cda;                     /* virtual CPU address of CDA */
-    sonic_td_t    tda[SONIC_NUM_TDS];      /* transmit descriptor area */
-    sonic_rr_t    rra[SONIC_NUM_RRS];      /* receive resource arrea */
-    sonic_rd_t    rda[SONIC_NUM_RDS];      /* receive descriptor area */
-    struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
-    unsigned int  tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
-    unsigned char *rba;                    /* start of receive buffer areas */    
-    unsigned int  cda_laddr;               /* logical DMA address of CDA */    
-    unsigned int  tda_laddr;               /* logical DMA address of TDA */
-    unsigned int  rra_laddr;               /* logical DMA address of RRA */    
-    unsigned int  rda_laddr;               /* logical DMA address of RDA */
-    unsigned int  rba_laddr;               /* logical DMA address of RBA */
-    unsigned int  cur_tx, cur_rx;          /* current indexes to resource areas */
-    unsigned int  dirty_tx,cur_rra;        /* last unacked transmit packet */
-    char tx_full;
-    struct enet_statistics stats;
-};
-
-/*
- * We cannot use station (ethernet) address prefixes to detect the
- * sonic controller since these are board manufacturer depended.
- * So we check for known Silicon Revision IDs instead. 
- */
-static unsigned short known_revisions[] =
-{
-  0x04,				/* Mips Magnum 4000 */
-  0xffff			/* end of list */
-};
-
-/* Index to functions, as function prototypes. */
-
-extern int sonic_probe(struct device *dev);
-static int sonic_probe1(struct device *dev, unsigned int base_addr, unsigned int irq);
-static int sonic_open(struct device *dev);
-static int sonic_send_packet(struct sk_buff *skb, struct device *dev);
-static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void sonic_rx(struct device *dev);
-static int sonic_close(struct device *dev);
-static struct enet_statistics *sonic_get_stats(struct device *dev);
-static void sonic_multicast_list(struct device *dev);
-static int sonic_init(struct device *dev);
-
-
-/*
- * Probe for a SONIC ethernet controller on a Mips Jazz board.
- * Actually probing is superfluous but we're paranoid.
- */
-__initfunc(int sonic_probe(struct device *dev))
-{
-    unsigned int base_addr = dev ? dev->base_addr : 0;
-    int i;
-
-    /*
-     * Don't probe if we're not running on a Jazz board.
-     */
-    if (mips_machgroup != MACH_GROUP_JAZZ)
-	return -ENODEV;
-    if (base_addr > 0x1ff)	/* Check a single specified location. */
-	return sonic_probe1(dev, base_addr, dev->irq);
-    else if (base_addr != 0)	/* Don't probe at all. */
-	return -ENXIO;
-    
-    for (i = 0; sonic_portlist[i].port; i++) {
-	int base_addr = sonic_portlist[i].port;
-	if (check_region(base_addr, 0x100))
-	    continue;
-	if (sonic_probe1(dev, base_addr, sonic_portlist[i].irq) == 0)
-	    return 0;
-    }
-    return -ENODEV;
-}
-
-__initfunc(static int sonic_probe1(struct device *dev,
-                                   unsigned int base_addr, unsigned int irq))
-{
-    static unsigned version_printed = 0;
-    unsigned int silicon_revision;
-    unsigned int val;
-    struct sonic_local *lp;
-    int i;
-    
-    /*
-     * get the Silicon Revision ID. If this is one of the known
-     * one assume that we found a SONIC ethernet controller at
-     * the expected location.
-     */
-    silicon_revision = SONIC_READ(SONIC_SR);
-    if (sonic_debug > 1)
-      printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
-
-    i = 0;
-    while ((known_revisions[i] != 0xffff) &&
-	   (known_revisions[i] != silicon_revision))
-      i++;
-	
-    if (known_revisions[i] == 0xffff) {
-	printk("SONIC ethernet controller not found (0x%4x)\n",
-	       silicon_revision);
-	return -ENODEV;
-    }
-    
-    request_region(base_addr, 0x100, "SONIC");
-    
-    /* Allocate a new 'dev' if needed. */
-    if (dev == NULL)
-      dev = init_etherdev(0, sizeof(struct sonic_local));
-
-    if (sonic_debug  &&  version_printed++ == 0)
-      printk(version);
-
-    printk("%s: %s found at 0x%08x, ",
-	   dev->name, "SONIC ethernet", base_addr);
-
-    /* Fill in the 'dev' fields. */
-    dev->base_addr = base_addr;
-    dev->irq = irq;
-
-    /*
-     * Put the sonic into software reset, then
-     * retrieve and print the ethernet address.
-     */
-    SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
-    SONIC_WRITE(SONIC_CEP,0);
-    for (i=0; i<3; i++) {
-	val = SONIC_READ(SONIC_CAP0-i);
-	dev->dev_addr[i*2] = val;
-	dev->dev_addr[i*2+1] = val >> 8;
-    }
-
-    printk("HW Address ");
-    for (i = 0; i < 6; i++) {
-	printk("%2.2x", dev->dev_addr[i]);
-	if (i<5)
-	  printk(":");
-    }
-    
-    printk(" IRQ %d\n", irq);
-    
-    /* Initialize the device structure. */
-    if (dev->priv == NULL) {
-	/*
-	 * the memory be located in the same 64kb segment
-	 */
-	lp = NULL;
-	i = 0;
-	do {
-	    lp = (struct sonic_local *)kmalloc(sizeof(*lp), GFP_KERNEL);
-	    if ((unsigned long)lp >> 16 != ((unsigned long)lp + sizeof(*lp) ) >> 16) {
-		/* FIXME, free the memory later */
-		kfree (lp);
-		lp = NULL;
-	    }
-	} while (lp == NULL && i++ < 20);
-	
-	if (lp == NULL) {
-	    printk ("%s: couldn't allocate memory for descriptors\n",
-	            dev->name);
-	    return -ENOMEM;
-	}
-	
-	memset(lp, 0, sizeof(struct sonic_local));
-	
-	/* get the virtual dma address */
-	lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
-	if (lp->cda_laddr == ~0UL) {
-	    printk ("%s: couldn't get DMA page entry for descriptors\n",
-	            dev->name);
-	    return -ENOMEM;
-	}
-
-	lp->tda_laddr = lp->cda_laddr + sizeof (lp->cda);
-	lp->rra_laddr = lp->tda_laddr + sizeof (lp->tda);
-	lp->rda_laddr = lp->rra_laddr + sizeof (lp->rra);
-	
-	/* allocate receive buffer area */
-	/* FIXME, maybe we should use skbs */
-	if ((lp->rba = (char *)kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL) {
-	    printk ("%s: couldn't allocate receive buffers\n",dev->name);
-	    return -ENOMEM;
-	}
-	
-	/* get virtual dma address */
-	if ((lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),SONIC_NUM_RRS * SONIC_RBSIZE)) == ~0UL) {
-	    printk ("%s: couldn't get DMA page entry for receive buffers\n",dev->name);
-	    return -ENOMEM;
-	}
-	
-	/* now convert pointer to KSEG1 pointer */
-	lp->rba = (char *)KSEG1ADDR(lp->rba);
-	flush_cache_all();
-	dev->priv = (struct sonic_local *)KSEG1ADDR(lp);
-    }
-
-    lp = (struct sonic_local *)dev->priv;
-    dev->open = sonic_open;
-    dev->stop = sonic_close;
-    dev->hard_start_xmit = sonic_send_packet;
-    dev->get_stats	= sonic_get_stats;
-    dev->set_multicast_list = &sonic_multicast_list;
-
-    /* Fill in the fields of the device structure with ethernet values. */
-    ether_setup(dev);
-    return 0;
-}
 
 /*
  * Open/initialize the SONIC controller.
@@ -308,8 +41,8 @@
  * covering another bug otherwise corrupting data.  This doesn't mean
  * this glue works ok under all situations.
  */
-//    if (request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
-    if (request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) {
+//    if (sonic_request_irq(dev->irq, &sonic_interrupt, 0, "sonic", dev)) {
+    if (sonic_request_irq(dev->irq, &sonic_interrupt, SA_INTERRUPT, "sonic", dev)) {
 	printk ("\n%s: unable to get IRQ %d .\n", dev->name, dev->irq);
 	return EAGAIN;
     }
@@ -351,7 +84,7 @@
     SONIC_WRITE(SONIC_IMR,0);
     SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
 
-    free_irq(dev->irq, dev);			/* release the IRQ */
+    sonic_free_irq(dev->irq, dev);		/* release the IRQ */
 
     return 0;
 }
@@ -424,11 +157,6 @@
     lp->tda[entry].tx_frag_ptr_l = laddr & 0xffff;
     lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
     lp->tda[entry].tx_frag_size  = length;
-    
-    /* if there are already packets queued, allow sending several packets at once */
-    if (lp->dirty_tx != lp->cur_tx)
-	lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
-    
     lp->cur_tx++;
     lp->stats.tx_bytes += length;
     
@@ -479,20 +207,23 @@
     
     if (status & SONIC_INT_TXDN) {
 	int dirty_tx = lp->dirty_tx;
-	
+
 	while (dirty_tx < lp->cur_tx) {
 	    int entry = dirty_tx & SONIC_TDS_MASK;
 	    int status = lp->tda[entry].tx_status;
-	    
+
 	    if (sonic_debug > 3)
 	      printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
 		      status,lp->cur_tx,lp->dirty_tx);
-	    
-	    if (status == 0)
-	      break;			/* It still hasn't been Txed */
+
+	    if (status == 0) {
+		/* It still hasn't been Txed, kick the sonic again */
+		SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);		
+		break;
+	    }
 
 	    /* put back EOL and free descriptor */
-	    lp->tda[entry].link |= SONIC_END_OF_LINKS;
+	    lp->tda[entry].tx_frag_count = 0;
 	    lp->tda[entry].tx_status = 0;
 
 	    if (status & 0x0001)
@@ -574,27 +305,25 @@
 {
     unsigned int base_addr = dev->base_addr;
     struct sonic_local *lp = (struct sonic_local *)dev->priv;
-    int entry = lp->cur_rx & SONIC_RDS_MASK;
+    sonic_rd_t *rd = &lp->rda[lp->cur_rx & SONIC_RDS_MASK];
     int status;
 
-    while(lp->rda[entry].in_use == 0)
-    {
+    while (rd->in_use == 0) {
 	struct sk_buff *skb;
 	int pkt_len;
 	unsigned char *pkt_ptr;
 	
-	status = lp->rda[entry].rx_status;
+	status = rd->rx_status;
 	if (sonic_debug > 3)
-	  printk ("status %x, cur_rx %d, cur_rra %d\n",status,lp->cur_rx,lp->cur_rra);
+	  printk ("status %x, cur_rx %d, cur_rra %x\n",status,lp->cur_rx,lp->cur_rra);
 	if (status & SONIC_RCR_PRX) {	    
-	    pkt_len = lp->rda[entry].rx_pktlen;
-	    pkt_ptr = (char *)KSEG1ADDR(vdma_log2phys((lp->rda[entry].rx_pktptr_h << 16) +
-						      lp->rda[entry].rx_pktptr_l));
+	    pkt_len = rd->rx_pktlen;
+	    pkt_ptr = (char *)sonic_chiptomem((rd->rx_pktptr_h << 16) +
+						      rd->rx_pktptr_l);
 	    
 	    if (sonic_debug > 3)
-	      printk ("pktptr %p (rba %p) h:%x l:%x, rra h:%x l:%x bsize h:%x l:%x\n", pkt_ptr,lp->rba,
-		      lp->rda[entry].rx_pktptr_h,lp->rda[entry].rx_pktptr_l,
-		      lp->rra[lp->cur_rra & 15].rx_bufadr_h,lp->rra[lp->cur_rra & 15].rx_bufadr_l,
+	      printk ("pktptr %p (rba %p) h:%x l:%x, bsize h:%x l:%x\n", pkt_ptr,lp->rba,
+		      rd->rx_pktptr_h,rd->rx_pktptr_l,
 		      SONIC_READ(SONIC_RBWC1),SONIC_READ(SONIC_RBWC0));
 	
 	    /* Malloc up new buffer. */
@@ -620,21 +349,26 @@
 	    if (status & SONIC_RCR_CRCR) lp->stats.rx_crc_errors++;
 	}
 	
-	lp->rda[entry].in_use = 1;
-	entry = (++lp->cur_rx) & SONIC_RDS_MASK;
+	rd->in_use = 1;
+	rd = &lp->rda[(++lp->cur_rx) & SONIC_RDS_MASK];
 	/* now give back the buffer to the receive buffer area */
 	if (status & SONIC_RCR_LPKT) {
 	    /*
 	     * this was the last packet out of the current receice buffer
 	     * give the buffer back to the SONIC
 	     */
-	    SONIC_WRITE(SONIC_RWP,(lp->rra_laddr + (++lp->cur_rra & 15) * sizeof(sonic_rr_t)) & 0xffff);
-	}
+	    lp->cur_rra += sizeof(sonic_rr_t);
+	    if (lp->cur_rra > (lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t)))
+		lp->cur_rra = lp->rra_laddr;
+	    SONIC_WRITE(SONIC_RWP, lp->cur_rra & 0xffff);
+	} else
+	    printk ("%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",dev->name);
     }
-  
-    /* If any worth-while packets have been received, dev_rint()
-     has done a mark_bh(NET_BH) for us and will work on them
-     when we get to the bottom-half routine. */
+    /*
+     * If any worth-while packets have been received, dev_rint()
+     * has done a mark_bh(NET_BH) for us and will work on them
+     * when we get to the bottom-half routine.
+     */
     return;
 }
 
@@ -689,16 +423,15 @@
 	    for (i = 1; i <= dev->mc_count; i++) {
 		addr = dmi->dmi_addr;
 		dmi = dmi->next;
-		lp->cda.cam_desc[i].cam_frag2 = addr[1] << 8 | addr[0];
-		lp->cda.cam_desc[i].cam_frag1 = addr[3] << 8 | addr[2];
-		lp->cda.cam_desc[i].cam_frag0 = addr[5] << 8 | addr[4];
+		lp->cda.cam_desc[i].cam_cap0 = addr[1] << 8 | addr[0];
+		lp->cda.cam_desc[i].cam_cap1 = addr[3] << 8 | addr[2];
+		lp->cda.cam_desc[i].cam_cap2 = addr[5] << 8 | addr[4];
 		lp->cda.cam_enable |= (1 << i);
 	    }
-	    /* number of CAM entries to load */
-	    SONIC_WRITE(SONIC_CDC,dev->mc_count+1);
+	    SONIC_WRITE(SONIC_CDC,16);
 	    /* issue Load CAM command */
 	    SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);	    
-	    SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM);	    
+	    SONIC_WRITE(SONIC_CMD,SONIC_CR_LCAM);
 	}
     }
     
@@ -736,7 +469,6 @@
     SONIC_WRITE(SONIC_CMD,0);
     SONIC_WRITE(SONIC_CMD,SONIC_CR_RXDIS);
 
-
     /*
      * initialize the receive resource area
      */
@@ -761,7 +493,7 @@
     SONIC_WRITE(SONIC_URRA,lp->rra_laddr >> 16);
     SONIC_WRITE(SONIC_EOBC,(SONIC_RBSIZE-2) >> 1);
     
-    lp->cur_rra = SONIC_NUM_RRS - 2;
+    lp->cur_rra = lp->rra_laddr + (SONIC_NUM_RRS-1) * sizeof(sonic_rr_t);
 
     /* load the resource pointers */
     if (sonic_debug > 3)
@@ -796,7 +528,6 @@
     /* fix last descriptor */
     lp->rda[SONIC_NUM_RDS-1].link = lp->rda_laddr;
     lp->cur_rx = 0;
-    
     SONIC_WRITE(SONIC_URDA,lp->rda_laddr >> 16);
     SONIC_WRITE(SONIC_CRDA,lp->rda_laddr & 0xffff);
     
@@ -816,13 +547,14 @@
 
     SONIC_WRITE(SONIC_UTDA,lp->tda_laddr >> 16);
     SONIC_WRITE(SONIC_CTDA,lp->tda_laddr & 0xffff);
+    lp->cur_tx = lp->dirty_tx = 0;
     
     /*
      * put our own address to CAM desc[0]
      */
-    lp->cda.cam_desc[0].cam_frag2 = dev->dev_addr[1] << 8 | dev->dev_addr[0];
-    lp->cda.cam_desc[0].cam_frag1 = dev->dev_addr[3] << 8 | dev->dev_addr[2];
-    lp->cda.cam_desc[0].cam_frag0 = dev->dev_addr[5] << 8 | dev->dev_addr[4];
+    lp->cda.cam_desc[0].cam_cap0 = dev->dev_addr[1] << 8 | dev->dev_addr[0];
+    lp->cda.cam_desc[0].cam_cap1 = dev->dev_addr[3] << 8 | dev->dev_addr[2];
+    lp->cda.cam_desc[0].cam_cap2 = dev->dev_addr[5] << 8 | dev->dev_addr[4];
     lp->cda.cam_enable = 1;
     
     for (i=0; i < 16; i++)
@@ -832,7 +564,7 @@
      * initialize CAM registers
      */
     SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);
-    SONIC_WRITE(SONIC_CDC,1);
+    SONIC_WRITE(SONIC_CDC,16);
     
     /*
      * load the CAM
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sonic.h linux.pre11.3/drivers/net/sonic.h
--- linux.vanilla/drivers/net/sonic.h	Sun Nov  8 15:07:30 1998
+++ linux.pre11.3/drivers/net/sonic.h	Mon Jul 19 23:27:30 1999
@@ -15,16 +15,6 @@
 #define SONIC_H
 
 /*
- * Macros to access SONIC registers
- */
-#define SONIC_READ(reg) \
-	*((volatile unsigned int *)base_addr+reg)
-
-#define SONIC_WRITE(reg,val) \
-	*((volatile unsigned int *)base_addr+reg) = val
-
-
-/*
  * SONIC register offsets
  */
  
@@ -242,9 +232,9 @@
 
 typedef struct {
   u16 rx_status;	/* status after reception of a packet */
-  u16 pad0;
+  SREGS_PAD(pad0);
   u16 rx_pktlen;	/* length of the packet incl. CRC */
-  u16 pad1;
+  SREGS_PAD(pad1);
   
   /*
    * Pointers to the location in the receive buffer area (RBA)
@@ -252,22 +242,22 @@
    * a contiguous piece of memory.
    */
   u16 rx_pktptr_l;
-  u16 pad2;
+  SREGS_PAD(pad2);
   u16 rx_pktptr_h;
-  u16 pad3;
+  SREGS_PAD(pad3);
 
   u16 rx_seqno;	/* sequence no. */
-  u16 pad4;
+  SREGS_PAD(pad4);
 
   u16 link;		/* link to next RDD (end if EOL bit set) */
-  u16 pad5;
+  SREGS_PAD(pad5);
 
   /*
    * Owner of this descriptor, 0= driver, 1=sonic
    */
   
   u16 in_use;	
-  u16 pad6;
+  SREGS_PAD(pad6);
 
   caddr_t rda_next;		/* pointer to next RD */
 } sonic_rd_t;
@@ -278,23 +268,23 @@
  */
 typedef struct {
   u16 tx_status;	/* status after transmission of a packet */
-  u16 pad0;		
+  SREGS_PAD(pad0);
   u16 tx_config;	/* transmit configuration for this packet */
-  u16 pad1;		
+  SREGS_PAD(pad1);
   u16 tx_pktsize;	/* size of the packet to be transmitted */
-  u16 pad2;		
+  SREGS_PAD(pad2);
   u16 tx_frag_count;	/* no. of fragments */
-  u16 pad3;		
+  SREGS_PAD(pad3);
 
   u16 tx_frag_ptr_l;
-  u16 pad4;		
+  SREGS_PAD(pad4);
   u16 tx_frag_ptr_h;
-  u16 pad5;		
+  SREGS_PAD(pad5);
   u16 tx_frag_size;
-  u16 pad6;		
+  SREGS_PAD(pad6);
   
   u16 link;		/* ptr to next descriptor */
-  u16 pad7;		
+  SREGS_PAD(pad7);
 } sonic_td_t;
 
 
@@ -304,13 +294,13 @@
 
 typedef struct {
   u16 cam_entry_pointer;
-  u16 pad;
-  u16 cam_frag2;
-  u16 pad2;
-  u16 cam_frag1;
-  u16 pad1;
-  u16 cam_frag0;
-  u16 pad0;
+  SREGS_PAD(pad0);
+  u16 cam_cap0;
+  SREGS_PAD(pad1);
+  u16 cam_cap1;
+  SREGS_PAD(pad2);
+  u16 cam_cap2;
+  SREGS_PAD(pad3);
 } sonic_cd_t;
 
 #define CAM_DESCRIPTORS 16
@@ -319,8 +309,56 @@
 typedef struct {
   sonic_cd_t cam_desc[CAM_DESCRIPTORS];
   u16 cam_enable;
-  u16 pad;
+  SREGS_PAD(pad);
 } sonic_cda_t;
 
+/*
+ * Some tunables for the buffer areas. Power of 2 is required
+ * the current driver uses one receive buffer for each descriptor.
+ */
+#define SONIC_NUM_RRS    16             /* number of receive resources */
+#define SONIC_NUM_RDS    SONIC_NUM_RRS  /* number of receive descriptors */
+#define SONIC_NUM_TDS    16      /* number of transmit descriptors */
+#define SONIC_RBSIZE   1520      /* size of one resource buffer */
+
+#define SONIC_RDS_MASK   (SONIC_NUM_RDS-1)
+#define SONIC_TDS_MASK   (SONIC_NUM_TDS-1)
+
+
+/* Information that need to be kept for each board. */
+struct sonic_local {
+    sonic_cda_t   cda;                     /* virtual CPU address of CDA */
+    sonic_td_t    tda[SONIC_NUM_TDS];      /* transmit descriptor area */
+    sonic_rr_t    rra[SONIC_NUM_RRS];      /* receive resource arrea */
+    sonic_rd_t    rda[SONIC_NUM_RDS];      /* receive descriptor area */
+    struct sk_buff* tx_skb[SONIC_NUM_TDS]; /* skbuffs for packets to transmit */
+    unsigned int  tx_laddr[SONIC_NUM_TDS]; /* logical DMA address fro skbuffs */
+    unsigned char *rba;                    /* start of receive buffer areas */    
+    unsigned int  cda_laddr;               /* logical DMA address of CDA */    
+    unsigned int  tda_laddr;               /* logical DMA address of TDA */
+    unsigned int  rra_laddr;               /* logical DMA address of RRA */    
+    unsigned int  rda_laddr;               /* logical DMA address of RDA */
+    unsigned int  rba_laddr;               /* logical DMA address of RBA */
+    unsigned int  cur_rra;                 /* current indexes to resource areas */
+    unsigned int  cur_rx;
+    unsigned int  cur_tx;
+    unsigned int  dirty_tx;                /* last unacked transmit packet */
+    char tx_full;
+    struct enet_statistics stats;
+};
+
+/* Index to functions, as function prototypes. */
+
+static int sonic_open(struct device *dev);
+static int sonic_send_packet(struct sk_buff *skb, struct device *dev);
+static void sonic_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void sonic_rx(struct device *dev);
+static int sonic_close(struct device *dev);
+static struct enet_statistics *sonic_get_stats(struct device *dev);
+static void sonic_multicast_list(struct device *dev);
+static int sonic_init(struct device *dev);
+
+static const char *version =
+	"sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
 
 #endif /* SONIC_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/sunhme.c linux.pre11.3/drivers/net/sunhme.c
--- linux.vanilla/drivers/net/sunhme.c	Tue Jun 15 16:49:50 1999
+++ linux.pre11.3/drivers/net/sunhme.c	Mon Jul 19 23:27:26 1999
@@ -3406,7 +3406,7 @@
 	/* Set the latency timer and cache line size as well,
 	 * PROM leaves it at zero.
 	 */
-	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 128);
+	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
 #ifdef __sparc_v9__
 	/* NOTE: Cache line size is in 32-bit word units. */
 	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x10);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/syncppp.c linux.pre11.3/drivers/net/syncppp.c
--- linux.vanilla/drivers/net/syncppp.c	Fri Apr 16 22:10:53 1999
+++ linux.pre11.3/drivers/net/syncppp.c	Tue Jul 20 00:00:50 1999
@@ -48,6 +48,7 @@
 #include <linux/netdevice.h>
 #include <linux/inetdevice.h>
 #include <linux/random.h>
+#include <linux/pkt_sched.h>
 #include <asm/byteorder.h>
 #include "syncppp.h"
 
@@ -771,7 +772,7 @@
 	}
 	sp->obytes += skb->len;
 	/* Control is high priority so it doesnt get queued behind data */
-	skb->priority=1;
+	skb->priority=TC_PRIO_CONTROL;
 	skb->dev = dev;
 	dev_queue_xmit(skb);
 }
@@ -813,7 +814,7 @@
 			dev->name,  ntohl (ch->type), ch->par1,
 			ch->par2, ch->rel, ch->time0, ch->time1);
 	sp->obytes += skb->len;
-	skb->priority=1;
+	skb->priority=TC_PRIO_CONTROL;
 	skb->dev = dev;
 	dev_queue_xmit(skb);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/tulip.c linux.pre11.3/drivers/net/tulip.c
--- linux.vanilla/drivers/net/tulip.c	Sun Jan 24 19:55:35 1999
+++ linux.pre11.3/drivers/net/tulip.c	Tue Jul 20 00:00:55 1999
@@ -327,6 +327,10 @@
 	TxFIFOUnderflow=0x20, TxJabber=0x08, TxNoBuf=0x04, TxDied=0x02, TxIntr=0x01,
 };
 
+enum desc_status_bits {
+	DescOwned=0x80000000, RxDescFatalErr=0x8000, RxWholePkt=0x0300,
+};
+        
 /* The Tulip Rx and Tx buffer descriptors. */
 struct tulip_rx_desc {
 	s32 status;
@@ -2698,8 +2702,8 @@
 			/* Same setup recently queued, we need not add it. */
 		} else {
 			unsigned long flags;
-			unsigned int entry;
-			
+			unsigned int entry, dummy = 0;
+
 			save_flags(flags); cli();
 			entry = tp->cur_tx++ % TX_RING_SIZE;
 
@@ -2709,7 +2713,8 @@
 				tp->tx_ring[entry].length =
 					(entry == TX_RING_SIZE-1) ? 0x02000000 : 0;
 				tp->tx_ring[entry].buffer1 = 0;
-				tp->tx_ring[entry].status = 0x80000000;
+				/* race with chip, set DescOwned later */
+				dummy = entry;
 				entry = tp->cur_tx++ % TX_RING_SIZE;
 			}
 
@@ -2724,6 +2729,8 @@
 				dev->tbusy = 1;
 				tp->tx_full = 1;
 			}
+			if (dummy >= 0)
+				tp->tx_ring[dummy].status = DescOwned;
 			restore_flags(flags);
 			/* Trigger an immediate transmit demand. */
 			outl(0, ioaddr + CSR1);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/via-rhine.c linux.pre11.3/drivers/net/via-rhine.c
--- linux.vanilla/drivers/net/via-rhine.c	Thu May 27 22:11:54 1999
+++ linux.pre11.3/drivers/net/via-rhine.c	Mon Jul 19 23:27:33 1999
@@ -1,6 +1,6 @@
 /* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */
 /*
-	Written 1998 by Donald Becker.
+	Written 1998-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License (GPL), incorporated herein by reference.
@@ -20,7 +20,7 @@
 */
 
 static const char *versionA =
-"via-rhine.c:v1.00 9/5/98  Written by Donald Becker\n";
+"via-rhine.c:v1.01 2/27/99  Written by Donald Becker\n";
 static const char *versionB =
 "  http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n";
 
@@ -81,9 +81,11 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 
-/* This driver was written to use PCI memory space, however some boards
-   only work with I/O space accesses. */
+/* This driver was written to use PCI memory space, however some x86
+   motherboards only configure I/O space accesses correctly. */
+#if defined(__i386__)  &&  !defined(VIA_USE_MEMORY)
 #define VIA_USE_IO
+#endif
 #ifdef VIA_USE_IO
 #undef readb
 #undef readw
@@ -105,6 +107,7 @@
 #define RUN_AT(x) (jiffies + (x))
 
 #if (LINUX_VERSION_CODE >= 0x20100)
+char kernel_version[] = UTS_RELEASE;
 #else
 #ifndef __alpha__
 #define ioremap vremap
@@ -502,6 +505,7 @@
 #ifndef MODULE
 int via_rhine_probe(struct device *dev)
 {
+	printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
 	return pci_etherdev_probe(dev, pci_tbl);
 }
 #endif
@@ -510,13 +514,9 @@
 								 struct device *dev, long ioaddr, int irq,
 								 int chip_id, int card_idx)
 {
-	static int did_version = 0;		/* Already printed version info */
 	struct netdev_private *np;
 	int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 
-	if (debug > 0 && did_version++ == 0)
-		printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
-
 	dev = init_etherdev(dev, 0);
 
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
@@ -685,6 +685,8 @@
 		   ioaddr + IntrEnable);
 
 	np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
+	if (np->duplex_lock)
+		np->chip_cmd |= CmdFDuplex;
 	writew(np->chip_cmd, ioaddr + ChipCmd);
 
 	check_duplex(dev);
@@ -1053,7 +1055,6 @@
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
 			dev->last_rx = jiffies;
-			np->stats.rx_bytes += pkt_len;
 			np->stats.rx_packets++;
 		}
 		entry = (++np->cur_rx) % RX_RING_SIZE;
@@ -1182,7 +1183,7 @@
 		}
 		writel(mc_filter[0], ioaddr + MulticastFilter0);
 		writel(mc_filter[1], ioaddr + MulticastFilter1);
-		rx_mode = 0x0C;
+		rx_mode = 0x08;
 	}
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/wavelan.c linux.pre11.3/drivers/net/wavelan.c
--- linux.vanilla/drivers/net/wavelan.c	Thu May 27 22:11:55 1999
+++ linux.pre11.3/drivers/net/wavelan.c	Tue Jul 20 00:01:04 1999
@@ -2087,12 +2087,6 @@
 	{
 	  struct iw_range	range;
 
-	  /* Verify the user buffer. */
-	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-			    sizeof(struct iw_range));
-	  if(ret)
-	    break;
-
 	  /* Set the length (useless:  it's constant). */
 	  wrq->u.data.length = sizeof(struct iw_range);
 
@@ -2118,8 +2112,8 @@
 	  range.max_qual.noise = MMR_SILENCE_LVL;
 
 	  /* Copy structure to the user buffer. */
-	  copy_to_user(wrq->u.data.pointer, &range,
-		       sizeof(struct iw_range));
+	  if (copy_to_user(wrq->u.data.pointer, &range, sizeof(struct iw_range)))
+	  	ret = -EFAULT;
 	}
       break;
 
@@ -2136,18 +2130,12 @@
 	    { SIOCGIPHISTO, 0,	    IW_PRIV_TYPE_INT | 16, "gethisto" },
 	  };
 
-	  /* Verify the user buffer. */
-	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-			    sizeof(priv));
-	  if(ret)
-	    break;
-
 	  /* Set the number of available ioctls. */
 	  wrq->u.data.length = 4;
 
 	  /* Copy structure to the user buffer. */
-	  copy_to_user(wrq->u.data.pointer, (u_char *) priv,
-		       sizeof(priv));
+	  if (copy_to_user(wrq->u.data.pointer, (u_char *) priv, sizeof(priv)))
+	  	ret = -EFAULT;
 	}
       break;
 
@@ -2169,14 +2157,11 @@
 	  struct sockaddr	address[IW_MAX_SPY];
 	  int			i;
 
-	  /* Verify where the user has set his addresses. */
-	  ret = verify_area(VERIFY_READ, wrq->u.data.pointer,
-			    sizeof(struct sockaddr) * lp->spy_number);
-	  if(ret)
-	    break;
 	  /* Copy addresses to the driver. */
-	  copy_from_user(address, wrq->u.data.pointer,
-			 sizeof(struct sockaddr) * lp->spy_number);
+	  if (copy_from_user(address, wrq->u.data.pointer, sizeof(struct sockaddr) * lp->spy_number)) {
+	  	ret = -EFAULT;
+	  	break;
+	  }
 
 	  /* Copy addresses to the lp structure. */
 	  for(i = 0; i < lp->spy_number; i++)
@@ -2215,13 +2200,6 @@
 	  struct sockaddr	address[IW_MAX_SPY];
 	  int			i;
 
-	  /* Verify the user buffer. */
-	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-			    (sizeof(iw_qual) + sizeof(struct sockaddr))
-			    * IW_MAX_SPY);
-	  if(ret)
-	    break;
-
 	  /* Copy addresses from the lp structure. */
 	  for(i = 0; i < lp->spy_number; i++)
 	    {
@@ -2231,13 +2209,18 @@
 	    }
 
 	  /* Copy addresses to the user buffer. */
-	  copy_to_user(wrq->u.data.pointer, address,
-		       sizeof(struct sockaddr) * lp->spy_number);
-
+	  if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * lp->spy_number)) {
+	  	ret = -EFAULT;
+	  	break;
+	  }
+	  	
 	  /* Copy stats to the user buffer (just after). */
-	  copy_to_user(wrq->u.data.pointer +
+	  if (copy_to_user(wrq->u.data.pointer +
 		       (sizeof(struct sockaddr) * lp->spy_number),
-		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
+		       lp->spy_stat, sizeof(iw_qual) * lp->spy_number)) {
+		       		ret = -EFAULT;
+		       		break;
+	  }
 
 	  /* Reset updated flags. */
 	  for(i = 0; i < lp->spy_number; i++)
@@ -2283,14 +2266,11 @@
       /* Are there addresses to copy? */
       if(lp->his_number > 0)
 	{
-	  /* Verify where the user has set his addresses. */
-	  ret = verify_area(VERIFY_READ, wrq->u.data.pointer,
-			    sizeof(char) * lp->his_number);
-	  if(ret)
-	    break;
 	  /* Copy interval ranges to the driver */
-	  copy_from_user(lp->his_range, wrq->u.data.pointer,
-			 sizeof(char) * lp->his_number);
+	  if (copy_from_user(lp->his_range, wrq->u.data.pointer, sizeof(char) * lp->his_number)) {
+	  	ret = -EFAULT;
+	  	break;
+	  }
 
 	  /* Reset structure. */
 	  memset(lp->his_sum, 0x00, sizeof(long) * 16);
@@ -2304,15 +2284,10 @@
       /* Give back the distribution statistics */
       if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
 	{
-	  /* Verify the user buffer. */
-	  ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer,
-			    sizeof(long) * 16);
-	  if(ret)
-	    break;
-
 	  /* Copy data to the user buffer. */
-	  copy_to_user(wrq->u.data.pointer, lp->his_sum,
-		       sizeof(long) * lp->his_number);
+	  if (copy_to_user(wrq->u.data.pointer, lp->his_sum, sizeof(long) * lp->his_number)) 
+			ret = -EFAULT;
+			
 	}	/* if(pointer != NULL) */
       break;
 #endif	/* HISTOGRAM */
@@ -4265,6 +4240,11 @@
 
 	  /* Create device and set basic arguments. */
 	  dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+	  if(dev==NULL)
+	  {
+	  	ret = -ENOMEM;
+	  	break;
+	  }
 	  memset(dev, 0x00, sizeof(struct device));
 	  dev->name = name[i];
 	  dev->base_addr = io[i];
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/yellowfin.c linux.pre11.3/drivers/net/yellowfin.c
--- linux.vanilla/drivers/net/yellowfin.c	Tue Dec 22 23:19:47 1998
+++ linux.pre11.3/drivers/net/yellowfin.c	Mon Jul 19 23:27:31 1999
@@ -76,6 +76,7 @@
 #include <linux/pci.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
+#include <asm/unaligned.h>
 #include <asm/io.h>
 
 #include <linux/netdevice.h>
@@ -1054,7 +1055,7 @@
 		u16 desc_status = desc->status;
 		int data_size = desc->request_cnt - desc->result_cnt;
 		u8 *buf_addr = bus_to_virt(desc->addr);
-		s16 frame_status = *(s16*)&(buf_addr[data_size - 2]); /* ?Alpha safe on 885? */
+		s16 frame_status = get_unaligned((s16*)(buf_addr+data_size-2));
 
 		if (yellowfin_debug > 4)
 			printk(KERN_DEBUG "  yellowfin_rx() status was %4.4x.\n",
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/net/z85230.c linux.pre11.3/drivers/net/z85230.c
--- linux.vanilla/drivers/net/z85230.c	Wed Apr 28 19:14:27 1999
+++ linux.pre11.3/drivers/net/z85230.c	Tue Jul 20 00:01:09 1999
@@ -187,7 +187,6 @@
 	1,	EXT_INT_ENAB|TxINT_ENAB|INT_ALL_Rx,
 	9,	NV|MIE|NORESET,
 	23,	3,		/* Extended mode AUTO TX and EOM*/
-	31,	3,		/* Extended mode AUTO TX and EOM*/
 	
 	255
 };
@@ -673,6 +672,7 @@
 	{
 		kfree(c->rx_buf[0]);
 		c->rx_buf[0]=NULL;
+		c->rx_buf[1]=NULL;
 		return -ENOBUFS;
 	}
 	
@@ -834,6 +834,8 @@
 
 int z8530_sync_txdma_open(struct device *dev, struct z8530_channel *c)
 {
+	unsigned long flags;
+
 	printk("Opening sync interface for TX-DMA\n");
 	c->sync = 1;
 	c->mtu = dev->mtu+64;
@@ -889,14 +891,21 @@
 	c->regs[R14]|= DTRREQ;
 	write_zsreg(c, R14, c->regs[R14]);     
 	
+	c->regs[R1]&= ~TxINT_ENAB;
+	write_zsreg(c, R1, c->regs[R1]);
+	
 	/*
 	 *	Set up the DMA configuration
 	 */	
 	 
+	flags = claim_dma_lock();
+
 	disable_dma(c->txdma);
 	clear_dma_ff(c->txdma);
 	set_dma_mode(c->txdma, DMA_MODE_WRITE);
 	disable_dma(c->txdma);
+
+	release_dma_lock(flags);
 	
 	/*
 	 *	Select the DMA interrupt handlers
@@ -918,6 +927,7 @@
 	
 int z8530_sync_txdma_close(struct device *dev, struct z8530_channel *c)
 {
+	unsigned long flags;
 	u8 chk;
 	c->irqs = &z8530_nop;
 	c->max = 0;
@@ -927,10 +937,14 @@
 	 *	Disable the PC DMA channels
 	 */
 	 
+	flags = claim_dma_lock();
+
 	disable_dma(c->txdma);
 	clear_dma_ff(c->txdma);
 	c->txdma_on = 0;
 	c->tx_dma_used = 0;
+
+	release_dma_lock(flags);
 
 	/*
 	 *	Disable DMA control mode
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/pci/oldproc.c linux.pre11.3/drivers/pci/oldproc.c
--- linux.vanilla/drivers/pci/oldproc.c	Tue Jun 15 16:49:50 1999
+++ linux.pre11.3/drivers/pci/oldproc.c	Tue Jul 20 00:01:27 1999
@@ -103,6 +103,7 @@
 	DEVICE( DEC,		DEC_21152,	"DC21152"),
 	DEVICE( DEC,		DEC_21153,	"DC21153"),
 	DEVICE( DEC,		DEC_21154,	"DC21154"),
+	DEVICE( DEC,		DEC_21285,	"DC21285 Footbridge"),
 	DEVICE( CIRRUS,		CIRRUS_7548,	"GD 7548"),
 	DEVICE( CIRRUS,		CIRRUS_5430,	"GD 5430"),
 	DEVICE( CIRRUS,		CIRRUS_5434_4,	"GD 5434"),
@@ -222,6 +223,9 @@
 	DEVICE( X,		X_AGX016,	"ITT AGX016"),
 	DEVICE( PICOP,		PICOP_PT86C52X,	"PT86C52x Vesuvius"),
 	DEVICE( PICOP,		PICOP_PT80C524,	"PT80C524 Nile"),
+	DEVICE( MYLEX,		MYLEX_DAC960P_V2,"DAC960P V2"),
+	DEVICE( MYLEX,		MYLEX_DAC960P_V3,"DAC960P V3"),
+	DEVICE( MYLEX,		MYLEX_DAC960P_V4,"DAC960P V4"),
 	DEVICE( APPLE,		APPLE_BANDIT,	"Bandit"),
 	DEVICE( APPLE,		APPLE_GC,	"Grand Central"),
 	DEVICE( APPLE,		APPLE_HYDRA,	"Hydra"),
@@ -303,6 +307,7 @@
 	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
 	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128ZV, "MagicGraph 128ZV"),
 	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_NM2160, "MagicGraph NM2160"),
+	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128ZVPLUS, "MagicGraph 128ZV+"),
 	DEVICE( ASP,		ASP_ABP940,	"ABP940"),
 	DEVICE( ASP,		ASP_ABP940U,	"ABP940U"),
 	DEVICE( ASP,		ASP_ABP940UW,	"ABP940UW"),
@@ -460,6 +465,7 @@
 	DEVICE( SATSAGEM,	SATSAGEM_PCR2101,"PCR2101 DVB receiver"),
 	DEVICE( SATSAGEM,	SATSAGEM_TELSATTURBO,"Telsat Turbo DVB"),
 	DEVICE( HUGHES,		HUGHES_DIRECPC,	"DirecPC"),
+	DEVICE( ENSONIQ,	ENSONIQ_ES1371,	"ES1371"),
 	DEVICE( ENSONIQ,	ENSONIQ_AUDIOPCI,"AudioPCI"),
 	DEVICE( ALTEON,		ALTEON_ACENIC,  "AceNIC"),
 	DEVICE( PICTUREL,	PICTUREL_PCIVST,"PCIVST"),
@@ -498,11 +504,13 @@
 	DEVICE( S3,		S3_ViRGE_MXPMV,	"ViRGE/MX+MV"),
 	DEVICE( S3,		S3_SONICVIBES,	"SonicVibes"),
 	DEVICE( DCI,		DCI_PCCOM4,	"PC COM PCI Bus 4 port serial Adapter"),
+	DEVICE( GENROCO,	GENROCO_HFP832,	"TURBOstor HFP832"),
 	DEVICE( INTEL,		INTEL_82375,	"82375EB"),
 	DEVICE( INTEL,		INTEL_82424,	"82424ZX Saturn"),
 	DEVICE( INTEL,		INTEL_82378,	"82378IB"),
 	DEVICE( INTEL,		INTEL_82430,	"82430ZX Aries"),
 	DEVICE( INTEL,		INTEL_82434,	"82434LX Mercury/Neptune"),
+	DEVICE( INTEL,		INTEL_I960,	"i960"),
 	DEVICE( INTEL,		INTEL_82092AA_0,"82092AA PCMCIA bridge"),
 	DEVICE( INTEL,		INTEL_82092AA_1,"82092AA EIDE"),
 	DEVICE( INTEL,		INTEL_7116,	"SAA7116"),
@@ -536,6 +544,7 @@
 	DEVICE(	KTI,		KTI_ET32P2,	"ET32P2"),
 	DEVICE( ADAPTEC,	ADAPTEC_7810,	"AIC-7810 RAID"),
 	DEVICE( ADAPTEC,	ADAPTEC_7821,	"AIC-7860"),
+	DEVICE( ADAPTEC,	ADAPTEC_38602,	"AIC-7860"),
 	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850"),
 	DEVICE( ADAPTEC,	ADAPTEC_7855,	"AIC-7855"),
 	DEVICE( ADAPTEC,	ADAPTEC_5800,	"AIC-5800"),
@@ -627,8 +636,8 @@
 	      case PCI_CLASS_STORAGE_SCSI:		return "SCSI storage controller";
 	      case PCI_CLASS_STORAGE_IDE:		return "IDE interface";
 	      case PCI_CLASS_STORAGE_FLOPPY:		return "Floppy disk controller";
-	      case PCI_CLASS_STORAGE_IPI:		return "IPI bus controller";
-	      case PCI_CLASS_STORAGE_RAID:		return "RAID bus controller";
+	      case PCI_CLASS_STORAGE_IPI:		return "IPI storage controller";
+	      case PCI_CLASS_STORAGE_RAID:		return "RAID storage controller";
 	      case PCI_CLASS_STORAGE_OTHER:		return "Unknown mass storage controller";
 
 	      case PCI_CLASS_NETWORK_ETHERNET:		return "Ethernet controller";
@@ -736,6 +745,7 @@
 	      case PCI_VENDOR_ID_N9:		return "Number Nine";
 	      case PCI_VENDOR_ID_UMC:		return "UMC";
 	      case PCI_VENDOR_ID_X:		return "X TECHNOLOGY";
+	      case PCI_VENDOR_ID_MYLEX:		return "Mylex";
 	      case PCI_VENDOR_ID_PICOP:		return "PicoPower";
 	      case PCI_VENDOR_ID_APPLE:		return "Apple";
 	      case PCI_VENDOR_ID_NEXGEN:	return "Nexgen";
@@ -826,6 +836,7 @@
 	      case PCI_VENDOR_ID_NETVIN:	return "NetVin";
 	      case PCI_VENDOR_ID_S3:		return "S3 Inc.";
 	      case PCI_VENDOR_ID_DCI:		return "Decision Computer Int.";
+	      case PCI_VENDOR_ID_GENROCO:	return "Genroco";
 	      case PCI_VENDOR_ID_INTEL:		return "Intel";
 	      case PCI_VENDOR_ID_KTI:		return "KTI";
 	      case PCI_VENDOR_ID_ADAPTEC:	return "Adaptec";
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/pci/pci.c linux.pre11.3/drivers/pci/pci.c
--- linux.vanilla/drivers/pci/pci.c	Wed Mar 10 21:13:04 1999
+++ linux.pre11.3/drivers/pci/pci.c	Tue Jul 20 00:01:32 1999
@@ -184,6 +184,11 @@
 		}
 
 		dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
+		if(dev==NULL)
+		{
+			printk(KERN_ERR "pci: out of memory.\n");
+			continue;
+		}
 		memset(dev, 0, sizeof(*dev));
 		dev->bus = bus;
 		dev->devfn  = devfn;
@@ -292,6 +297,11 @@
 			 * Insert it into the tree of buses.
 			 */
 			child = kmalloc(sizeof(*child), GFP_ATOMIC);
+			if(child==NULL)
+			{
+				printk(KERN_ERR "pci: out of memory for bridge.\n");
+				continue;
+			}
 			memset(child, 0, sizeof(*child));
 			child->next = bus->children;
 			bus->children = child;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/NCR53C9x.c linux.pre11.3/drivers/scsi/NCR53C9x.c
--- linux.vanilla/drivers/scsi/NCR53C9x.c	Tue Dec 22 23:19:48 1998
+++ linux.pre11.3/drivers/scsi/NCR53C9x.c	Mon Jul 19 23:28:02 1999
@@ -3390,6 +3390,7 @@
 	struct ESP_regs *eregs;
 	Scsi_Cmnd *SCptr;
 	int what_next = do_intr_end;
+	unsigned long flags;
 #ifdef CONFIG_SCSI_SUNESP
 	struct sparc_dma_registers *dregs = 
 	  (struct sparc_dma_registers*) esp->dregs;
@@ -3610,7 +3611,9 @@
 			}
 			SCptr->result = (DID_RESET << 16);
 
+			spin_lock_irqsave(&io_request_lock,flags);
 			SCptr->scsi_done(SCptr);
+			spin_unlock_irqrestore(&io_request_lock, flags);
 		}
 		esp->current_SC = NULL;
 		if(esp->disconnected_SC) {
@@ -3625,7 +3628,9 @@
 				}
 				SCptr->result = (DID_RESET << 16);
 
+				spin_lock_irqsave(&io_request_lock,flags);
 				SCptr->scsi_done(SCptr);
+				spin_unlock_irqrestore(&io_request_lock, flags);
 			}
 		}
 		esp->resetting_bus = 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aha152x.c linux.pre11.3/drivers/scsi/aha152x.c
--- linux.vanilla/drivers/scsi/aha152x.c	Fri May 28 00:32:59 1999
+++ linux.pre11.3/drivers/scsi/aha152x.c	Mon Jul 19 23:27:57 1999
@@ -183,7 +183,7 @@
  **************************************************************************
 
 
- 
+
  DESCRIPTION:
 
  This is the Linux low-level SCSI driver for Adaptec AHA-1520/1522 SCSI
@@ -192,30 +192,30 @@
 
  CONFIGURATION ARGUMENTS:
 
-  IOPORT        base io address                           (0x340/0x140)
-  IRQ           interrupt level                           (9-12; default 11)
-  SCSI_ID       scsi id of controller                     (0-7; default 7)
-  RECONNECT     allow targets to disconnect from the bus  (0/1; default 1 [on])
-  PARITY        enable parity checking                    (0/1; default 1 [on])
-  SYNCHRONOUS   enable synchronous transfers              (0/1; default 0 [off])
-                (NOT WORKING YET)
-  DELAY:        bus reset delay                           (default 100)
-  EXT_TRANS:    enable extended translation               (0/1: default 0 [off])
-                (see NOTES below)
+ IOPORT        base io address                           (0x340/0x140)
+ IRQ           interrupt level                           (9-12; default 11)
+ SCSI_ID       scsi id of controller                     (0-7; default 7)
+ RECONNECT     allow targets to disconnect from the bus  (0/1; default 1 [on])
+ PARITY        enable parity checking                    (0/1; default 1 [on])
+ SYNCHRONOUS   enable synchronous transfers              (0/1; default 0 [off])
+ (NOT WORKING YET)
+ DELAY:        bus reset delay                           (default 100)
+ EXT_TRANS:    enable extended translation               (0/1: default 0 [off])
+ (see NOTES below)
 
  COMPILE TIME CONFIGURATION (put into AHA152X in drivers/scsi/Makefile):
 
  -DAUTOCONF
-   use configuration the controller reports (AHA-152x only)
+ use configuration the controller reports (AHA-152x only)
 
  -DSKIP_BIOSTEST
-   Don't test for BIOS signature (AHA-1510 or disabled BIOS)
+ Don't test for BIOS signature (AHA-1510 or disabled BIOS)
 
  -DSETUP0="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }"
-   override for the first controller 
-   
+ override for the first controller 
+
  -DSETUP1="{ IOPORT, IRQ, SCSI_ID, RECONNECT, PARITY, SYNCHRONOUS, DELAY, EXT_TRANS }"
-   override for the second controller
+ override for the second controller
 
 
  LILO COMMAND LINE OPTIONS:
@@ -230,13 +230,13 @@
 
 
  SYMBOLS FOR MODULE CONFIGURATION:
- 
-  aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
-    configuration override of first controller
-
- 
-  aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
-    configuration override of second controller
+
+ aha152x=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
+ configuration override of first controller
+
+
+ aha152x1=IOPORT,IRQ,SCSI_ID,RECONNECT,PARITY,SYNCHRONOUS,DELAY,EXT_TRANS
+ configuration override of second controller
 
 
  NOTES ON EXT_TRANS: 
@@ -287,14 +287,14 @@
 
  - for disks<1GB: use default translation (C/32/64)
  - for disks>1GB:
-   - take current geometry from the partition table
-     (using scsicam_bios_param and accept only `valid' geometries,
-      ie. either (C/32/64) or (C/63/255)).  This can be extended
-      translation even if it's not enabled in the driver.
-   - if that fails, take extended translation if enabled by override,
-     kernel or module parameter, otherwise take default translation and
-     ask the user for verification.  This might on not yet partitioned
-     disks or
+ - take current geometry from the partition table
+ (using scsicam_bios_param and accept only `valid' geometries,
+ ie. either (C/32/64) or (C/63/255)).  This can be extended
+ translation even if it's not enabled in the driver.
+ - if that fails, take extended translation if enabled by override,
+ kernel or module parameter, otherwise take default translation and
+ ask the user for verification.  This might on not yet partitioned
+ disks or
 
 
  REFERENCES USED:
@@ -308,7 +308,7 @@
  "Kernel Hacker's Guide", Michael K. Johnson (johnsonm@sunsite.unc.edu)
 
  "Adaptec 1520/1522 User's Guide", Adaptec Corporation.
- 
+
  Michael K. Johnson (johnsonm@sunsite.unc.edu)
 
  Drew Eckhardt (drew@cs.colorado.edu)
@@ -350,9 +350,10 @@
 
 #include <scsi/scsicam.h>
 
-struct proc_dir_entry proc_scsi_aha152x = {
-    PROC_SCSI_AHA152X, 7, "aha152x",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
+struct proc_dir_entry proc_scsi_aha152x =
+{
+	PROC_SCSI_AHA152X, 7, "aha152x",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
 /* DEFINES */
@@ -370,25 +371,25 @@
 
 #if defined(DEBUG_AHA152X)
 
-#undef  SKIP_PORTS              /* don't display ports */
+#undef  SKIP_PORTS		/* don't display ports */
 
-#undef  DEBUG_QUEUE             /* debug queue() */
-#undef  DEBUG_RESET             /* debug reset() */
-#undef  DEBUG_INTR              /* debug intr() */
-#undef  DEBUG_SELECTION         /* debug selection part in intr() */
-#undef  DEBUG_MSGO              /* debug message out phase in intr() */
-#undef  DEBUG_MSGI              /* debug message in phase in intr() */
-#undef  DEBUG_STATUS            /* debug status phase in intr() */
-#undef  DEBUG_CMD               /* debug command phase in intr() */
-#undef  DEBUG_DATAI             /* debug data in phase in intr() */
-#undef  DEBUG_DATAO             /* debug data out phase in intr() */
-#undef  DEBUG_ABORT             /* debug abort() */
-#undef  DEBUG_DONE              /* debug done() */
-#undef  DEBUG_BIOSPARAM         /* debug biosparam() */
-
-#undef  DEBUG_RACE              /* debug race conditions */
-#undef  DEBUG_PHASES            /* debug phases (useful to trace) */
-#undef  DEBUG_QUEUES            /* debug reselection */
+#undef  DEBUG_QUEUE		/* debug queue() */
+#undef  DEBUG_RESET		/* debug reset() */
+#undef  DEBUG_INTR		/* debug intr() */
+#undef  DEBUG_SELECTION		/* debug selection part in intr() */
+#undef  DEBUG_MSGO		/* debug message out phase in intr() */
+#undef  DEBUG_MSGI		/* debug message in phase in intr() */
+#undef  DEBUG_STATUS		/* debug status phase in intr() */
+#undef  DEBUG_CMD		/* debug command phase in intr() */
+#undef  DEBUG_DATAI		/* debug data in phase in intr() */
+#undef  DEBUG_DATAO		/* debug data out phase in intr() */
+#undef  DEBUG_ABORT		/* debug abort() */
+#undef  DEBUG_DONE		/* debug done() */
+#undef  DEBUG_BIOSPARAM		/* debug biosparam() */
+
+#undef  DEBUG_RACE		/* debug race conditions */
+#undef  DEBUG_PHASES		/* debug phases (useful to trace) */
+#undef  DEBUG_QUEUES		/* debug reselection */
 
 /* recently used for debugging */
 #if 0
@@ -424,46 +425,50 @@
 #define IRQS    IRQ_MAX-IRQ_MIN+1
 
 enum {
-  not_issued   = 0x0001,
-  in_selection = 0x0002,
-  disconnected = 0x0004,
-  aborted      = 0x0008,
-  sent_ident   = 0x0010,
-  in_other     = 0x0020,
-  in_sync      = 0x0040,
-  sync_ok      = 0x0080,
+	not_issued = 0x0001,
+	in_selection = 0x0002,
+	disconnected = 0x0004,
+	aborted = 0x0008,
+	sent_ident = 0x0010,
+	in_other = 0x0020,
+	in_sync = 0x0040,
+	sync_ok = 0x0080,
 };
 
 #if defined(MODULE)
 #if defined(DEBUG_AHA152X)
-int aha152x[]  = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT };
-int aha152x1[] = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT };
+int aha152x[] =
+{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
+int aha152x1[] =
+{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
 MODULE_PARM(aha152x, "1-9i");
 MODULE_PARM(aha152x1, "1-9i");
 #else
-int aha152x[]  = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0 };
-int aha152x1[] = { 0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0 };
+int aha152x[] =
+{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
+int aha152x1[] =
+{0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0};
 MODULE_PARM(aha152x, "1-8i");
 MODULE_PARM(aha152x1, "1-8i");
 #endif
 #endif
 
 /* set by aha152x_setup according to the command line */
-static int  setup_count=0;
-static int  registered_count=0;
+static int setup_count = 0;
+static int registered_count = 0;
 static struct aha152x_setup {
-  int io_port;
-  int irq;
-  int scsiid;
-  int reconnect;
-  int parity;
-  int synchronous;
-  int delay;
-  int ext_trans;
+	int io_port;
+	int irq;
+	int scsiid;
+	int reconnect;
+	int parity;
+	int synchronous;
+	int delay;
+	int ext_trans;
 #ifdef DEBUG_AHA152X
-  int debug;
+	int debug;
 #endif
-  char *conf;
+	char *conf;
 } setup[2];
 
 static struct Scsi_Host *aha152x_host[IRQS];
@@ -480,30 +485,30 @@
 #define ADDMSG(x)         (MSG(MSGLEN++)=x)
 
 struct aha152x_hostdata {
-  Scsi_Cmnd     *issue_SC;
-  Scsi_Cmnd     *current_SC;
-  Scsi_Cmnd     *disconnected_SC;
-  int           aborting;
-  int           abortion_complete;
-  int           abort_result;
-  int           commands;
-  
-  int           reconnect;
-  int           parity;
-  int           synchronous;
-  int           delay;
-  int           ext_trans;
-
-  int           swint;
-  int		service;
- 
-  unsigned char syncrate[8];
-  
-  unsigned char message[256];
-  int           message_len;
+	Scsi_Cmnd *issue_SC;
+	Scsi_Cmnd *current_SC;
+	Scsi_Cmnd *disconnected_SC;
+	int aborting;
+	int abortion_complete;
+	int abort_result;
+	int commands;
+
+	int reconnect;
+	int parity;
+	int synchronous;
+	int delay;
+	int ext_trans;
+
+	int swint;
+	int service;
+
+	unsigned char syncrate[8];
+
+	unsigned char message[256];
+	int message_len;
 
 #ifdef DEBUG_AHA152X
-  int           debug;
+	int debug;
 #endif
 };
 
@@ -516,7 +521,7 @@
 static void aha152x_panic(struct Scsi_Host *shpnt, char *msg);
 
 static void disp_ports(struct Scsi_Host *shpnt);
-static void show_command(Scsi_Cmnd *ptr);
+static void show_command(Scsi_Cmnd * ptr);
 static void show_queues(struct Scsi_Host *shpnt);
 static void disp_enintr(struct Scsi_Host *shpnt);
 
@@ -528,8 +533,8 @@
 /* possible i/o addresses for the AIC-6260 */
 static unsigned short ports[] =
 {
-  0x340,      /* default first */
-  0x140
+	0x340,			/* default first */
+	0x140
 };
 #define PORT_COUNT (sizeof(ports) / sizeof(unsigned short))
 
@@ -537,15 +542,15 @@
 /* possible locations for the Adaptec BIOS */
 static unsigned int addresses[] =
 {
-  0xdc000,   /* default first */
-  0xc8000,
-  0xcc000,
-  0xd0000,
-  0xd4000,
-  0xd8000,
-  0xe0000,
-  0xeb800,   /* VTech Platinum SMP */
-  0xf0000,
+	0xdc000,		/* default first */
+	0xc8000,
+	0xcc000,
+	0xd0000,
+	0xd4000,
+	0xd8000,
+	0xe0000,
+	0xeb800,		/* VTech Platinum SMP */
+	0xf0000,
 };
 #define ADDRESS_COUNT (sizeof(addresses) / sizeof(unsigned int))
 
@@ -557,80 +562,103 @@
    needed anyway.  May be an information whether or not the BIOS supports
    extended translation could be also useful here. */
 static struct signature {
-  unsigned char *signature;
-  int  sig_offset;
-  int  sig_length;
+	unsigned char *signature;
+	int sig_offset;
+	int sig_length;
 } signatures[] =
+
 {
-  { "Adaptec AHA-1520 BIOS",      0x102e, 21 },  /* Adaptec 152x */
-  { "Adaptec AHA-1520B",            0x0b, 19 },  /* Adaptec 152x rev B */
-  { "Adaptec ASW-B626 BIOS",      0x1029, 21 },  /* on-board controller */
-  { "Adaptec BIOS: ASW-B626",       0x0f, 22 },  /* on-board controller */
-  { "Adaptec ASW-B626 S2",        0x2e6c, 19 },  /* on-board controller */
-  { "Adaptec BIOS:AIC-6360",         0xc, 21 },  /* on-board controller */
-  { "ScsiPro SP-360 BIOS",        0x2873, 19 },  /* ScsiPro-Controller  */
-  { "GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26 },  /* Gigabyte Local-Bus-SCSI */
-  { "Adaptec BIOS:AVA-282X",         0xc, 21 },  /* Adaptec 282x */
-  { "Adaptec IBM Dock II SCSI",   0x2edd, 24 },  /* IBM Thinkpad Dock II */
-  { "Adaptec BIOS:AHA-1532P",       0x1c, 22 },  /* IBM Thinkpad Dock II SCSI */
-  { "DTC3520A Host Adapter BIOS", 0x318a, 26 },  /* DTC 3520A ISA SCSI */
+	{
+		"Adaptec AHA-1520 BIOS", 0x102e, 21
+	},			/* Adaptec 152x */
+	{
+		"Adaptec AHA-1520B", 0x0b, 19
+	},			/* Adaptec 152x rev B */
+	{
+		"Adaptec ASW-B626 BIOS", 0x1029, 21
+	},			/* on-board controller */
+	{
+		"Adaptec BIOS: ASW-B626", 0x0f, 22
+	},			/* on-board controller */
+	{
+		"Adaptec ASW-B626 S2", 0x2e6c, 19
+	},			/* on-board controller */
+	{
+		"Adaptec BIOS:AIC-6360", 0xc, 21
+	},			/* on-board controller */
+	{
+		"ScsiPro SP-360 BIOS", 0x2873, 19
+	},			/* ScsiPro-Controller  */
+	{
+		"GA-400 LOCAL BUS SCSI BIOS", 0x102e, 26
+	},			/* Gigabyte Local-Bus-SCSI */
+	{
+		"Adaptec BIOS:AVA-282X", 0xc, 21
+	},			/* Adaptec 282x */
+	{
+		"Adaptec IBM Dock II SCSI", 0x2edd, 24
+	},			/* IBM Thinkpad Dock II */
+	{
+		"Adaptec BIOS:AHA-1532P", 0x1c, 22
+	},			/* IBM Thinkpad Dock II SCSI */
+	{
+		"DTC3520A Host Adapter BIOS", 0x318a, 26
+	},			/* DTC 3520A ISA SCSI */
 };
+
 #define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
 #endif
 
 
-static void do_pause(unsigned amount) /* Pause for amount*10 milliseconds */
-{
-   unsigned long the_time = jiffies + amount; /* 0.01 seconds per jiffy */
+static void do_pause(unsigned amount)
+{				/* Pause for amount*10 milliseconds */
+	unsigned long the_time = jiffies + amount;	/* 0.01 seconds per jiffy */
 
-   while (time_before(jiffies, the_time))
-     barrier();
+	while (time_before(jiffies, the_time))
+		barrier();
 }
 
 /*
  *  queue services:
  */
-static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void append_SC(Scsi_Cmnd ** SC, Scsi_Cmnd * new_SC)
 {
-  Scsi_Cmnd *end;
+	Scsi_Cmnd *end;
 
-  new_SC->host_scribble = (unsigned char *) NULL;
-  if(!*SC)
-    *SC=new_SC;
-  else {
-    for(end=*SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble)
-      ;
-    end->host_scribble = (unsigned char *) new_SC;
-  }
+	new_SC->host_scribble = (unsigned char *) NULL;
+	if (!*SC)
+		*SC = new_SC;
+	else {
+		for (end = *SC; end->host_scribble; end = (Scsi_Cmnd *) end->host_scribble);
+		end->host_scribble = (unsigned char *) new_SC;
+	}
 }
 
-static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
+static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd ** SC)
 {
-  Scsi_Cmnd *ptr;
+	Scsi_Cmnd *ptr;
 
-  ptr=*SC;
-  if(ptr)
-    *SC= (Scsi_Cmnd *) (*SC)->host_scribble;
-  return ptr;
+	ptr = *SC;
+	if (ptr)
+		*SC = (Scsi_Cmnd *) (*SC)->host_scribble;
+	return ptr;
 }
 
-static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
+static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd ** SC, int target, int lun)
 {
-  Scsi_Cmnd *ptr, *prev;
-
-  for(ptr=*SC, prev=NULL;
-       ptr && ((ptr->target!=target) || (ptr->lun!=lun));
-      prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
-    ;
+	Scsi_Cmnd *ptr, *prev;
 
-  if(ptr){
-    if(prev)
-      prev->host_scribble = ptr->host_scribble;
-    else
-      *SC= (Scsi_Cmnd *) ptr->host_scribble;
-  }
+	for (ptr = *SC, prev = NULL;
+	     ptr && ((ptr->target != target) || (ptr->lun != lun));
+	     prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble);
 
-  return ptr;
+	if (ptr) {
+		if (prev)
+			prev->host_scribble = ptr->host_scribble;
+		else
+			*SC = (Scsi_Cmnd *) ptr->host_scribble;
+	}
+	return ptr;
 }
 
 /*
@@ -638,12 +666,12 @@
  */
 static void make_acklow(struct Scsi_Host *shpnt)
 {
-  SETPORT(SXFRCTL0, CH1|SPIOEN);
-  GETPORT(SCSIDAT);
-  SETPORT(SXFRCTL0, CH1);
+	SETPORT(SXFRCTL0, CH1 | SPIOEN);
+	GETPORT(SCSIDAT);
+	SETPORT(SXFRCTL0, CH1);
 
-  while(TESTHI(SCSISIG, ACKI))
-    barrier();
+	while (TESTHI(SCSISIG, ACKI))
+		barrier();
 }
 
 /*
@@ -658,61 +686,61 @@
  */
 static int getphase(struct Scsi_Host *shpnt)
 {
-  int phase, sstat1;
-  
-  while(1) {
-    do {
-      while(!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE|SCSIRSTI|REQINIT)))
-        barrier();
-      if(sstat1 & BUSFREE)
-        return P_BUSFREE;
-      if(sstat1 & SCSIRSTI) {
-        printk("aha152x: RESET IN\n");
-        SETPORT(SSTAT1, SCSIRSTI);
-      }
-    } while(TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT));
-
-    SETPORT(SSTAT1, CLRSCSIPERR);
-  
-    phase = GETPORT(SCSISIG) & P_MASK ;
-
-    if(TESTHI(SSTAT1, SCSIPERR)) {
-      if((phase & (CDO|MSGO))==0)                        /* DATA phase */
-        return P_PARITY;
-
-      make_acklow(shpnt);
-    } else
-      return phase;
-  }
+	int phase, sstat1;
+
+	while (1) {
+		do {
+			while (!((sstat1 = GETPORT(SSTAT1)) & (BUSFREE | SCSIRSTI | REQINIT)))
+				barrier();
+			if (sstat1 & BUSFREE)
+				return P_BUSFREE;
+			if (sstat1 & SCSIRSTI) {
+				printk("aha152x: RESET IN\n");
+				SETPORT(SSTAT1, SCSIRSTI);
+			}
+		} while (TESTHI(SCSISIG, ACKI) || TESTLO(SSTAT1, REQINIT));
+
+		SETPORT(SSTAT1, CLRSCSIPERR);
+
+		phase = GETPORT(SCSISIG) & P_MASK;
+
+		if (TESTHI(SSTAT1, SCSIPERR)) {
+			if ((phase & (CDO | MSGO)) == 0)	/* DATA phase */
+				return P_PARITY;
+
+			make_acklow(shpnt);
+		} else
+			return phase;
+	}
 }
 
 /* called from init/main.c */
 void aha152x_setup(char *str, int *ints)
 {
-  if(setup_count>2)
-    panic("aha152x: you can only configure up to two controllers\n");
+	if (setup_count > 2)
+		panic("aha152x: you can only configure up to two controllers\n");
 
-  setup[setup_count].conf        = str;
-  setup[setup_count].io_port     = ints[0] >= 1 ? ints[1] : 0x340;
-  setup[setup_count].irq         = ints[0] >= 2 ? ints[2] : 11;
-  setup[setup_count].scsiid      = ints[0] >= 3 ? ints[3] : 7;
-  setup[setup_count].reconnect   = ints[0] >= 4 ? ints[4] : 1;
-  setup[setup_count].parity      = ints[0] >= 5 ? ints[5] : 1;
-  setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */;
-  setup[setup_count].delay       = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
-  setup[setup_count].ext_trans   = ints[0] >= 8 ? ints[8] : 0;
+	setup[setup_count].conf = str;
+	setup[setup_count].io_port = ints[0] >= 1 ? ints[1] : 0x340;
+	setup[setup_count].irq = ints[0] >= 2 ? ints[2] : 11;
+	setup[setup_count].scsiid = ints[0] >= 3 ? ints[3] : 7;
+	setup[setup_count].reconnect = ints[0] >= 4 ? ints[4] : 1;
+	setup[setup_count].parity = ints[0] >= 5 ? ints[5] : 1;
+	setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 0 /* FIXME: 1 */ ;
+	setup[setup_count].delay = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
+	setup[setup_count].ext_trans = ints[0] >= 8 ? ints[8] : 0;
 #ifdef DEBUG_AHA152X
-  setup[setup_count].debug       = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT;
-  if(ints[0]>9) { 
-    printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
-           "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");
+	setup[setup_count].debug = ints[0] >= 9 ? ints[9] : DEBUG_DEFAULT;
+	if (ints[0] > 9) {
+		printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
+		       "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>[,<DEBUG>]]]]]]]]\n");
 #else
-  if(ints[0]>8) {
-    printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
-           "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
+	if (ints[0] > 8) {
+		printk("aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
+		       "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
 #endif
-  } else 
-    setup_count++;
+	} else
+		setup_count++;
 }
 
 /*
@@ -720,598 +748,589 @@
  */
 static int aha152x_porttest(int io_port)
 {
-  int i;
+	int i;
 
-  if(check_region(io_port, IO_RANGE))
-    return 0;
+	if (check_region(io_port, IO_RANGE))
+		return 0;
 
-  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
-  for(i=0; i<16; i++)
-    SETPORT(io_port+O_STACK, i);
+	SETPORT(io_port + O_DMACNTRL1, 0);	/* reset stack pointer */
+	for (i = 0; i < 16; i++)
+		SETPORT(io_port + O_STACK, i);
 
-  SETPORT(io_port+O_DMACNTRL1, 0);          /* reset stack pointer */
-  for(i=0; i<16 && GETPORT(io_port+O_STACK)==i; i++)
-    ;
+	SETPORT(io_port + O_DMACNTRL1, 0);	/* reset stack pointer */
+	for (i = 0; i < 16 && GETPORT(io_port + O_STACK) == i; i++);
 
-  return(i==16);
+	return (i == 16);
 }
 
 int aha152x_checksetup(struct aha152x_setup *setup)
 {
-  int i;
-  
+	int i;
+
 #ifndef PCMCIA
-  for(i=0; i<PORT_COUNT && (setup->io_port != ports[i]); i++)
-    ;
-  
-  if(i==PORT_COUNT)
-    return 0;
-#endif
-  
-  if(!aha152x_porttest(setup->io_port))
-    return 0;
-  
-  if((setup->irq<IRQ_MIN) || (setup->irq>IRQ_MAX))
-    return 0;
-  
-  if((setup->scsiid < 0) || (setup->scsiid > 7))
-    return 0;
-  
-  if((setup->reconnect < 0) || (setup->reconnect > 1))
-    return 0;
-  
-  if((setup->parity < 0) || (setup->parity > 1))
-    return 0;
-  
-  if((setup->synchronous < 0) || (setup->synchronous > 1))
-    return 0;
-
-  if((setup->ext_trans < 0) || (setup->ext_trans > 1))
-    return 0;
-  
-  
-  return 1;
+	for (i = 0; i < PORT_COUNT && (setup->io_port != ports[i]); i++);
+
+	if (i == PORT_COUNT)
+		return 0;
+#endif
+
+	if (!aha152x_porttest(setup->io_port))
+		return 0;
+
+	if ((setup->irq < IRQ_MIN) || (setup->irq > IRQ_MAX))
+		return 0;
+
+	if ((setup->scsiid < 0) || (setup->scsiid > 7))
+		return 0;
+
+	if ((setup->reconnect < 0) || (setup->reconnect > 1))
+		return 0;
+
+	if ((setup->parity < 0) || (setup->parity > 1))
+		return 0;
+
+	if ((setup->synchronous < 0) || (setup->synchronous > 1))
+		return 0;
+
+	if ((setup->ext_trans < 0) || (setup->ext_trans > 1))
+		return 0;
+
+
+	return 1;
 }
 
-void aha152x_swintr(int irqno, void *dev_id, struct pt_regs * regs)
+void aha152x_swintr(int irqno, void *dev_id, struct pt_regs *regs)
 {
-  struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
+	struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN];
 
-  if(!shpnt)
-    panic("aha152x: catched software interrupt for unknown controller.\n");
+	if (!shpnt)
+		panic("aha152x: catched software interrupt for unknown controller.\n");
 
-  HOSTDATA(shpnt)->swint++;
+	HOSTDATA(shpnt)->swint++;
 }
 
 
 int aha152x_detect(Scsi_Host_Template * tpnt)
 {
-  int                 i, j, ok;
+	int i, j, ok;
 #if defined(AUTOCONF)
-  aha152x_config      conf;
+	aha152x_config conf;
 #endif
-  
-  tpnt->proc_dir = &proc_scsi_aha152x;
 
-  for(i=0; i<IRQS; i++)
-    aha152x_host[i] = (struct Scsi_Host *) NULL;
-  
-  if(setup_count) {
-    printk("aha152x: processing commandline: ");
-   
-    for(i=0; i<setup_count; i++)
-      if(!aha152x_checksetup(&setup[i])) {
-        printk("\naha152x: %s\n", setup[i].conf);
-        printk("aha152x: invalid line (controller=%d)\n", i+1);
-      }
-
-      printk("ok\n");
-  }
- 
+	tpnt->proc_dir = &proc_scsi_aha152x;
+
+	for (i = 0; i < IRQS; i++)
+		aha152x_host[i] = (struct Scsi_Host *) NULL;
+
+	if (setup_count) {
+		printk("aha152x: processing commandline: ");
+
+		for (i = 0; i < setup_count; i++)
+			if (!aha152x_checksetup(&setup[i])) {
+				printk("\naha152x: %s\n", setup[i].conf);
+				printk("aha152x: invalid line (controller=%d)\n", i + 1);
+			}
+		printk("ok\n");
+	}
 #ifdef SETUP0
-  if(setup_count<2) {
-    struct aha152x_setup override = SETUP0;
+	if (setup_count < 2) {
+		struct aha152x_setup override = SETUP0;
 
-    if(setup_count==0 || (override.io_port != setup[0].io_port))
-      if(!aha152x_checksetup(&override)) {
-        printk("\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
-               override.io_port,
-               override.irq,
-               override.scsiid,
-               override.reconnect,
-               override.parity,
-               override.synchronous,
-               override.delay,
-               override.ext_trans);
-      } else
-        setup[setup_count++] = override;
-  }
+		if (setup_count == 0 || (override.io_port != setup[0].io_port))
+			if (!aha152x_checksetup(&override)) {
+				printk("\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
+				       override.io_port,
+				       override.irq,
+				       override.scsiid,
+				       override.reconnect,
+				       override.parity,
+				       override.synchronous,
+				       override.delay,
+				       override.ext_trans);
+			} else
+				setup[setup_count++] = override;
+	}
 #endif
 
 #ifdef SETUP1
-  if(setup_count<2) {
-    struct aha152x_setup override = SETUP1;
+	if (setup_count < 2) {
+		struct aha152x_setup override = SETUP1;
 
-    if(setup_count==0 || (override.io_port != setup[0].io_port))
-      if(!aha152x_checksetup(&override)) {
-        printk("\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
-               override.io_port,
-               override.irq,
-               override.scsiid,
-               override.reconnect,
-               override.parity,
-               override.synchronous,
-               override.delay,
-               override.ext_trans);
-      } else
-        setup[setup_count++] = override;
-  }
+		if (setup_count == 0 || (override.io_port != setup[0].io_port))
+			if (!aha152x_checksetup(&override)) {
+				printk("\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n",
+				       override.io_port,
+				       override.irq,
+				       override.scsiid,
+				       override.reconnect,
+				       override.parity,
+				       override.synchronous,
+				       override.delay,
+				       override.ext_trans);
+			} else
+				setup[setup_count++] = override;
+	}
 #endif
 
 #if defined(MODULE)
-  if(setup_count<2 && aha152x[0]!=0) {
-    setup[setup_count].conf        = "";
-    setup[setup_count].io_port     = aha152x[0];
-    setup[setup_count].irq         = aha152x[1];
-    setup[setup_count].scsiid      = aha152x[2];
-    setup[setup_count].reconnect   = aha152x[3];
-    setup[setup_count].parity      = aha152x[4];
-    setup[setup_count].synchronous = aha152x[5];
-    setup[setup_count].delay       = aha152x[6];
-    setup[setup_count].ext_trans   = aha152x[7];
+	if (setup_count < 2 && aha152x[0] != 0) {
+		setup[setup_count].conf = "";
+		setup[setup_count].io_port = aha152x[0];
+		setup[setup_count].irq = aha152x[1];
+		setup[setup_count].scsiid = aha152x[2];
+		setup[setup_count].reconnect = aha152x[3];
+		setup[setup_count].parity = aha152x[4];
+		setup[setup_count].synchronous = aha152x[5];
+		setup[setup_count].delay = aha152x[6];
+		setup[setup_count].ext_trans = aha152x[7];
 #ifdef DEBUG_AHA152X
-    setup[setup_count].debug       = aha152x[8];
+		setup[setup_count].debug = aha152x[8];
 #endif
-    if(aha152x_checksetup(&setup[setup_count]))
-      setup_count++;
-    else
-      printk("\naha152x: invalid module argument aha152x=0x%x,%d,%d,%d,%d,%d,%d,%d\n",
-             setup[setup_count].io_port,
-             setup[setup_count].irq,
-             setup[setup_count].scsiid,
-             setup[setup_count].reconnect,
-             setup[setup_count].parity,
-             setup[setup_count].synchronous,
-             setup[setup_count].delay,
-             setup[setup_count].ext_trans);
-  }
-
-  if(setup_count<2 && aha152x1[0]!=0) {
-    setup[setup_count].conf        = "";
-    setup[setup_count].io_port     = aha152x1[0];
-    setup[setup_count].irq         = aha152x1[1];
-    setup[setup_count].scsiid      = aha152x1[2];
-    setup[setup_count].reconnect   = aha152x1[3];
-    setup[setup_count].parity      = aha152x1[4];
-    setup[setup_count].synchronous = aha152x1[5];
-    setup[setup_count].delay       = aha152x1[6];
-    setup[setup_count].ext_trans   = aha152x1[7];
+		if (aha152x_checksetup(&setup[setup_count]))
+			setup_count++;
+		else
+			printk("\naha152x: invalid module argument aha152x=0x%x,%d,%d,%d,%d,%d,%d,%d\n",
+			       setup[setup_count].io_port,
+			       setup[setup_count].irq,
+			       setup[setup_count].scsiid,
+			       setup[setup_count].reconnect,
+			       setup[setup_count].parity,
+			       setup[setup_count].synchronous,
+			       setup[setup_count].delay,
+			       setup[setup_count].ext_trans);
+	}
+	if (setup_count < 2 && aha152x1[0] != 0) {
+		setup[setup_count].conf = "";
+		setup[setup_count].io_port = aha152x1[0];
+		setup[setup_count].irq = aha152x1[1];
+		setup[setup_count].scsiid = aha152x1[2];
+		setup[setup_count].reconnect = aha152x1[3];
+		setup[setup_count].parity = aha152x1[4];
+		setup[setup_count].synchronous = aha152x1[5];
+		setup[setup_count].delay = aha152x1[6];
+		setup[setup_count].ext_trans = aha152x1[7];
 #ifdef DEBUG_AHA152X
-    setup[setup_count].debug       = aha152x1[8];
+		setup[setup_count].debug = aha152x1[8];
 #endif
-    if(aha152x_checksetup(&setup[setup_count]))
-      setup_count++;
-    else
-      printk("\naha152x: invalid module argument aha152x1=0x%x,%d,%d,%d,%d,%d,%d,%d\n",
-             setup[setup_count].io_port,
-             setup[setup_count].irq,
-             setup[setup_count].scsiid,
-             setup[setup_count].reconnect,
-             setup[setup_count].parity,
-             setup[setup_count].synchronous,
-             setup[setup_count].delay,
-             setup[setup_count].ext_trans);
-  }
+		if (aha152x_checksetup(&setup[setup_count]))
+			setup_count++;
+		else
+			printk("\naha152x: invalid module argument aha152x1=0x%x,%d,%d,%d,%d,%d,%d,%d\n",
+			       setup[setup_count].io_port,
+			       setup[setup_count].irq,
+			       setup[setup_count].scsiid,
+			       setup[setup_count].reconnect,
+			       setup[setup_count].parity,
+			       setup[setup_count].synchronous,
+			       setup[setup_count].delay,
+			       setup[setup_count].ext_trans);
+	}
 #endif
-  
+
 #if defined(AUTOCONF)
-  if(setup_count<2) {
+	if (setup_count < 2) {
 #if !defined(SKIP_BIOSTEST)
-    ok=0;
-    for(i=0; i < ADDRESS_COUNT && !ok; i++)
-      for(j=0; (j < SIGNATURE_COUNT) && !ok; j++)
-      	ok = check_signature(addresses[i]+signatures[j].sig_offset,
-      		signatures[j].signature, signatures[j].sig_length);
+		ok = 0;
+		for (i = 0; i < ADDRESS_COUNT && !ok; i++)
+			for (j = 0; (j < SIGNATURE_COUNT) && !ok; j++)
+				ok = check_signature(addresses[i] + signatures[j].sig_offset,
+						     signatures[j].signature, signatures[j].sig_length);
 
-    if(!ok && setup_count==0)
-      return 0;
+		if (!ok && setup_count == 0)
+			return 0;
 
-    printk("aha152x: BIOS test: passed, ");
+		printk("aha152x: BIOS test: passed, ");
 #else
-    printk("aha152x: ");
-#endif /* !SKIP_BIOSTEST */
- 
-    ok=0;
-    for(i=0; i<PORT_COUNT && setup_count<2; i++) {
-      if((setup_count==1) && (setup[0].io_port == ports[i]))
-        continue;
-
-      if(aha152x_porttest(ports[i])) {
-        ok++;
-        setup[setup_count].io_port = ports[i];
-              
-        conf.cf_port =
-          (GETPORT(ports[i]+O_PORTA)<<8) + GETPORT(ports[i]+O_PORTB);
-              
-        setup[setup_count].irq         = IRQ_MIN + conf.cf_irq;
-        setup[setup_count].scsiid      = conf.cf_id;
-        setup[setup_count].reconnect   = conf.cf_tardisc;
-        setup[setup_count].parity      = !conf.cf_parity;
-        setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */;
-        setup[setup_count].delay       = DELAY_DEFAULT;
-        setup[setup_count].ext_trans   = 0;
+		printk("aha152x: ");
+#endif				/* !SKIP_BIOSTEST */
+
+		ok = 0;
+		for (i = 0; i < PORT_COUNT && setup_count < 2; i++) {
+			if ((setup_count == 1) && (setup[0].io_port == ports[i]))
+				continue;
+
+			if (aha152x_porttest(ports[i])) {
+				ok++;
+				setup[setup_count].io_port = ports[i];
+
+				conf.cf_port =
+				    (GETPORT(ports[i] + O_PORTA) << 8) + GETPORT(ports[i] + O_PORTB);
+
+				setup[setup_count].irq = IRQ_MIN + conf.cf_irq;
+				setup[setup_count].scsiid = conf.cf_id;
+				setup[setup_count].reconnect = conf.cf_tardisc;
+				setup[setup_count].parity = !conf.cf_parity;
+				setup[setup_count].synchronous = 0 /* FIXME: conf.cf_syncneg */ ;
+				setup[setup_count].delay = DELAY_DEFAULT;
+				setup[setup_count].ext_trans = 0;
 #ifdef DEBUG_AHA152X
-        setup[setup_count].debug       = DEBUG_DEFAULT;
+				setup[setup_count].debug = DEBUG_DEFAULT;
 #endif
-        setup_count++;
-      }
-    }
+				setup_count++;
+			}
+		}
 
-    if(ok)
-      printk("auto configuration: ok, ");
-  }
+		if (ok)
+			printk("auto configuration: ok, ");
+	}
 #endif
 
-  printk("detected %d controller(s)\n", setup_count);
+	printk("detected %d controller(s)\n", setup_count);
 
-  for(i=0; i<setup_count; i++) {
-    struct Scsi_Host        *shpnt;
-    unsigned long int       the_time;
+	for (i = 0; i < setup_count; i++) {
+		struct Scsi_Host *shpnt;
+		unsigned long int the_time;
+
+		shpnt = aha152x_host[setup[i].irq - IRQ_MIN] =
+		    scsi_register(tpnt, sizeof(struct aha152x_hostdata));
+		registered_count++;
+
+		shpnt->io_port = setup[i].io_port;
+		shpnt->n_io_port = IO_RANGE;
+		shpnt->irq = setup[i].irq;
+
+		ISSUE_SC = (Scsi_Cmnd *) NULL;
+		CURRENT_SC = (Scsi_Cmnd *) NULL;
+		DISCONNECTED_SC = (Scsi_Cmnd *) NULL;
+
+		HOSTDATA(shpnt)->reconnect = setup[i].reconnect;
+		HOSTDATA(shpnt)->parity = setup[i].parity;
+		HOSTDATA(shpnt)->synchronous = setup[i].synchronous;
+		HOSTDATA(shpnt)->delay = setup[i].delay;
+		HOSTDATA(shpnt)->ext_trans = setup[i].ext_trans;
+#ifdef DEBUG_AHA152X
+		HOSTDATA(shpnt)->debug = setup[i].debug;
+#endif
 
-    shpnt = aha152x_host[setup[i].irq-IRQ_MIN] =
-      scsi_register(tpnt, sizeof(struct aha152x_hostdata));
-    registered_count++;
+		HOSTDATA(shpnt)->aborting = 0;
+		HOSTDATA(shpnt)->abortion_complete = 0;
+		HOSTDATA(shpnt)->abort_result = 0;
+		HOSTDATA(shpnt)->commands = 0;
+
+		HOSTDATA(shpnt)->message_len = 0;
+
+		for (j = 0; j < 8; j++)
+			HOSTDATA(shpnt)->syncrate[j] = 0;
+
+		SETPORT(SCSIID, setup[i].scsiid << 4);
+		shpnt->this_id = setup[i].scsiid;
+
+		if (setup[i].reconnect)
+			shpnt->can_queue = AHA152X_MAXQUEUE;
+
+		/* RESET OUT */
+		SETBITS(SCSISEQ, SCSIRSTO);
+		do_pause(30);
+		CLRBITS(SCSISEQ, SCSIRSTO);
+		do_pause(setup[i].delay);
+
+		aha152x_reset_ports(shpnt);
+
+		printk("aha152x%d: vital data: PORTBASE=0x%03lx, IRQ=%d, SCSI ID=%d,"
+		       " reconnect=%s, parity=%s, synchronous=%s, delay=%d, extended translation=%s\n",
+		       i,
+		       shpnt->io_port,
+		       shpnt->irq,
+		       shpnt->this_id,
+		     HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled",
+		       HOSTDATA(shpnt)->parity ? "enabled" : "disabled",
+		   HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled",
+		       HOSTDATA(shpnt)->delay,
+		    HOSTDATA(shpnt)->ext_trans ? "enabled" : "disabled");
+
+		request_region(shpnt->io_port, IO_RANGE, "aha152x");	/* Register */
+
+		/* not expecting any interrupts */
+		SETPORT(SIMODE0, 0);
+		SETPORT(SIMODE1, 0);
+
+		SETBITS(DMACNTRL0, INTEN);
+
+		ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", shpnt);
+		if (ok < 0) {
+			if (ok == -EINVAL)
+				printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq);
+			else if (ok == -EBUSY)
+				printk("aha152x%d: IRQ %d already in use.\n", i, shpnt->irq);
+			else
+				printk("\naha152x%d: Unexpected error code %d on requesting IRQ %d.\n", i, ok, shpnt->irq);
+			printk("aha152x: driver needs an IRQ.\n");
+
+			scsi_unregister(shpnt);
+			registered_count--;
+			release_region(shpnt->io_port, IO_RANGE);
+			shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0;
+			continue;
+		}
+		HOSTDATA(shpnt)->swint = 0;
 
-    shpnt->io_port                     = setup[i].io_port;
-    shpnt->n_io_port                   = IO_RANGE;
-    shpnt->irq                         = setup[i].irq;
+		printk("aha152x: trying software interrupt, ");
+		SETBITS(DMACNTRL0, SWINT);
 
-    ISSUE_SC                           = (Scsi_Cmnd *) NULL;
-    CURRENT_SC                         = (Scsi_Cmnd *) NULL;
-    DISCONNECTED_SC                    = (Scsi_Cmnd *) NULL;
+		the_time = jiffies + 100;
+		while (!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time))
+			barrier();
+
+		free_irq(shpnt->irq, shpnt);
+
+		if (!HOSTDATA(shpnt)->swint) {
+			if (TESTHI(DMASTAT, INTSTAT)) {
+				printk("lost.\n");
+			} else {
+				printk("failed.\n");
+			}
+
+			printk("aha152x: IRQ %d possibly wrong.  Please verify.\n", shpnt->irq);
+
+			scsi_unregister(shpnt);
+			registered_count--;
+			release_region(shpnt->io_port, IO_RANGE);
+			shpnt = aha152x_host[shpnt->irq - IRQ_MIN] = 0;
+			continue;
+		}
+		printk("ok.\n");
 
-    HOSTDATA(shpnt)->reconnect         = setup[i].reconnect;
-    HOSTDATA(shpnt)->parity            = setup[i].parity;
-    HOSTDATA(shpnt)->synchronous       = setup[i].synchronous;
-    HOSTDATA(shpnt)->delay             = setup[i].delay;
-    HOSTDATA(shpnt)->ext_trans         = setup[i].ext_trans;
-#ifdef DEBUG_AHA152X
-    HOSTDATA(shpnt)->debug             = setup[i].debug;
-#endif
+		CLRBITS(DMACNTRL0, SWINT);
 
-    HOSTDATA(shpnt)->aborting          = 0;
-    HOSTDATA(shpnt)->abortion_complete = 0;
-    HOSTDATA(shpnt)->abort_result      = 0;
-    HOSTDATA(shpnt)->commands          = 0;
-
-    HOSTDATA(shpnt)->message_len       = 0;
-
-    for(j=0; j<8; j++)
-      HOSTDATA(shpnt)->syncrate[j] = 0;
- 
-    SETPORT(SCSIID, setup[i].scsiid << 4);
-    shpnt->this_id=setup[i].scsiid;
-  
-    if(setup[i].reconnect)
-      shpnt->can_queue=AHA152X_MAXQUEUE;
-
-    /* RESET OUT */
-    SETBITS(SCSISEQ, SCSIRSTO);
-    do_pause(30);
-    CLRBITS(SCSISEQ, SCSIRSTO);
-    do_pause(setup[i].delay);
-
-    aha152x_reset_ports(shpnt);
-      
-    printk("aha152x%d: vital data: PORTBASE=0x%03lx, IRQ=%d, SCSI ID=%d,"
-           " reconnect=%s, parity=%s, synchronous=%s, delay=%d, extended translation=%s\n",
-           i,
-           shpnt->io_port,
-           shpnt->irq,
-           shpnt->this_id,
-           HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled",
-           HOSTDATA(shpnt)->parity ? "enabled" : "disabled",
-           HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled",
-           HOSTDATA(shpnt)->delay,
-           HOSTDATA(shpnt)->ext_trans ? "enabled" : "disabled");
-
-    request_region(shpnt->io_port, IO_RANGE, "aha152x");  /* Register */
-  
-    /* not expecting any interrupts */
-    SETPORT(SIMODE0, 0);
-    SETPORT(SIMODE1, 0);
-
-    SETBITS(DMACNTRL0, INTEN);
-
-    ok = request_irq(shpnt->irq, aha152x_swintr, SA_INTERRUPT, "aha152x", shpnt);
-    if(ok<0) {
-      if(ok == -EINVAL)
-        printk("aha152x%d: bad IRQ %d.\n", i, shpnt->irq);
-      else if(ok == -EBUSY)
-        printk("aha152x%d: IRQ %d already in use.\n", i, shpnt->irq);
-      else
-        printk("\naha152x%d: Unexpected error code %d on requesting IRQ %d.\n",                 i, ok, shpnt->irq);
-      printk("aha152x: driver needs an IRQ.\n");
-
-      scsi_unregister(shpnt);
-      registered_count--;
-      release_region(shpnt->io_port, IO_RANGE);
-      shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0;
-      continue;
-    }
-
-    HOSTDATA(shpnt)->swint=0;
-
-    printk("aha152x: trying software interrupt, ");
-    SETBITS(DMACNTRL0, SWINT);
-
-    the_time=jiffies+100;
-    while(!HOSTDATA(shpnt)->swint && time_before(jiffies, the_time))
-      barrier();
-
-    free_irq(shpnt->irq,shpnt);
-
-    if(!HOSTDATA(shpnt)->swint) {
-      if(TESTHI(DMASTAT, INTSTAT)) {
-        printk("lost.\n");
-      } else {
-        printk("failed.\n");
-      }
-
-      printk("aha152x: IRQ %d possibly wrong.  Please verify.\n", shpnt->irq);
-
-      scsi_unregister(shpnt);
-      registered_count--;
-      release_region(shpnt->io_port, IO_RANGE);
-      shpnt=aha152x_host[shpnt->irq-IRQ_MIN]=0;
-      continue;
-    }
-
-    printk("ok.\n");
-
-    CLRBITS(DMACNTRL0, SWINT);
-
-    /* clear interrupts */
-    SETPORT(SSTAT0, 0x7f);
-    SETPORT(SSTAT1, 0xef);
-
-    if(request_irq(shpnt->irq,aha152x_intr,SA_INTERRUPT,"aha152x",shpnt)<0) {
-      printk("aha152x: failed to reassign interrupt.\n");
-    }
-  }
-  
-  return (registered_count>0);
+		/* clear interrupts */
+		SETPORT(SSTAT0, 0x7f);
+		SETPORT(SSTAT1, 0xef);
+
+		if (request_irq(shpnt->irq, aha152x_intr, SA_INTERRUPT, "aha152x", shpnt) < 0) {
+			printk("aha152x: failed to reassign interrupt.\n");
+		}
+	}
+
+	return (registered_count > 0);
 }
 
 
 int aha152x_release(struct Scsi_Host *shpnt)
 {
-  if (shpnt->irq)
-    free_irq(shpnt->irq, shpnt);
-  if (shpnt->io_port)
-    release_region(shpnt->io_port, IO_RANGE);
+	if (shpnt->irq)
+		free_irq(shpnt->irq, shpnt);
+	if (shpnt->io_port)
+		release_region(shpnt->io_port, IO_RANGE);
 
-  return 0;
+	return 0;
 }
 
 /* 
  *  Queue a command and setup interrupts for a free bus.
  */
-int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *))
+int aha152x_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
 {
-  struct Scsi_Host *shpnt = SCpnt->host;
-  unsigned long flags;
+	struct Scsi_Host *shpnt = SCpnt->host;
+	unsigned long flags;
 
 #if defined(DEBUG_RACE)
-  enter_driver("queue");
+	enter_driver("queue");
 #else
 #if defined(DEBUG_QUEUE)
-  if(HOSTDATA(shpnt)->debug & debug_queue)
-    printk("aha152x: queue(), ");
+	if (HOSTDATA(shpnt)->debug & debug_queue)
+		printk("aha152x: queue(), ");
 #endif
 #endif
 
 #if defined(DEBUG_QUEUE)
-  if(HOSTDATA(shpnt)->debug & debug_queue) {
-    printk("SCpnt (target = %d lun = %d cmnd = ",
-           SCpnt->target, SCpnt->lun);
-    print_command(SCpnt->cmnd);
-    printk(", cmd_len=%d, pieces = %d size = %u), ",
-           SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
-    disp_ports(shpnt);
-  }
-#endif
-
-  SCpnt->scsi_done =       done;
-
-  /* setup scratch area
-     SCp.ptr              : buffer pointer
-     SCp.this_residual    : buffer length
-     SCp.buffer           : next buffer
-     SCp.buffers_residual : left buffers in list
-     SCp.phase            : current state of the command */
-  SCpnt->SCp.phase = not_issued;
-  if (SCpnt->use_sg) {
-    SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
-    SCpnt->SCp.ptr              = SCpnt->SCp.buffer->address;
-    SCpnt->SCp.this_residual    = SCpnt->SCp.buffer->length;
-    SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
-  } else {
-    SCpnt->SCp.ptr              = (char *)SCpnt->request_buffer;
-    SCpnt->SCp.this_residual    = SCpnt->request_bufflen;
-    SCpnt->SCp.buffer           = NULL;
-    SCpnt->SCp.buffers_residual = 0;
-  }
-          
-  SCpnt->SCp.Status              = CHECK_CONDITION;
-  SCpnt->SCp.Message             = 0;
-  SCpnt->SCp.have_data_in        = 0;
-  SCpnt->SCp.sent_command        = 0;
-
-  /* Turn led on, when this is the first command. */
-  save_flags(flags);
-  cli();
-  HOSTDATA(shpnt)->commands++;
-  if(HOSTDATA(shpnt)->commands==1)
-    SETPORT(PORTA, 1);
+	if (HOSTDATA(shpnt)->debug & debug_queue) {
+		printk("SCpnt (target = %d lun = %d cmnd = ",
+		       SCpnt->target, SCpnt->lun);
+		print_command(SCpnt->cmnd);
+		printk(", cmd_len=%d, pieces = %d size = %u), ",
+		  SCpnt->cmd_len, SCpnt->use_sg, SCpnt->request_bufflen);
+		disp_ports(shpnt);
+	}
+#endif
+
+	SCpnt->scsi_done = done;
+
+	/* setup scratch area
+	   SCp.ptr              : buffer pointer
+	   SCp.this_residual    : buffer length
+	   SCp.buffer           : next buffer
+	   SCp.buffers_residual : left buffers in list
+	   SCp.phase            : current state of the command */
+	SCpnt->SCp.phase = not_issued;
+	if (SCpnt->use_sg) {
+		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
+		SCpnt->SCp.ptr = SCpnt->SCp.buffer->address;
+		SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
+		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
+	} else {
+		SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
+		SCpnt->SCp.this_residual = SCpnt->request_bufflen;
+		SCpnt->SCp.buffer = NULL;
+		SCpnt->SCp.buffers_residual = 0;
+	}
+
+	SCpnt->SCp.Status = CHECK_CONDITION;
+	SCpnt->SCp.Message = 0;
+	SCpnt->SCp.have_data_in = 0;
+	SCpnt->SCp.sent_command = 0;
+
+	/* Turn led on, when this is the first command. */
+	save_flags(flags);
+	cli();
+	HOSTDATA(shpnt)->commands++;
+	if (HOSTDATA(shpnt)->commands == 1)
+		SETPORT(PORTA, 1);
 
 #if defined(DEBUG_QUEUES)
-  if(HOSTDATA(shpnt)->debug & debug_queues)
-    printk("i+ (%d), ", HOSTDATA(shpnt)->commands);
+	if (HOSTDATA(shpnt)->debug & debug_queues)
+		printk("i+ (%d), ", HOSTDATA(shpnt)->commands);
 #endif
-  append_SC(&ISSUE_SC, SCpnt);
-  
-  /* Enable bus free interrupt, when we aren't currently on the bus */
-  if(!CURRENT_SC) {
-    SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-    SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
-  }
-  restore_flags(flags);
+	append_SC(&ISSUE_SC, SCpnt);
+
+	/* Enable bus free interrupt, when we aren't currently on the bus */
+	if (!CURRENT_SC) {
+		SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+		SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+	}
+	restore_flags(flags);
 
 #if defined(DEBUG_RACE)
-  leave_driver("queue");
+	leave_driver("queue");
 #endif
 
-  return 0;
+	return 0;
 }
 
 /*
  *  We only support commands in interrupt-driven fashion
  */
-int aha152x_command(Scsi_Cmnd *SCpnt)
+int aha152x_command(Scsi_Cmnd * SCpnt)
 {
-  printk("aha152x: interrupt driven driver; use aha152x_queue()\n");
-  return -1;
+	printk("aha152x: interrupt driven driver; use aha152x_queue()\n");
+	return -1;
 }
 
 /*
  *  Abort a queued command
  *  (commands that are on the bus can't be aborted easily)
  */
-int aha152x_abort(Scsi_Cmnd *SCpnt)
+int aha152x_abort(Scsi_Cmnd * SCpnt)
 {
-  struct Scsi_Host *shpnt = SCpnt->host;
-  unsigned long flags;
-  Scsi_Cmnd *ptr, *prev;
+	struct Scsi_Host *shpnt = SCpnt->host;
+	unsigned long flags;
+	Scsi_Cmnd *ptr, *prev;
 
-  save_flags(flags);
-  cli();
+	save_flags(flags);
+	cli();
 
 #if defined(DEBUG_ABORT)
-  if(HOSTDATA(shpnt)->debug & debug_abort) { 
-    printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt);
-    show_queues(shpnt);
-  }
-#endif
-
-  /* look for command in issue queue */
-  for(ptr=ISSUE_SC, prev=NULL;
-       ptr && ptr!=SCpnt;
-       prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
-    ;
-
-  if(ptr) {
-    /* dequeue */
-    if(prev)
-      prev->host_scribble = ptr->host_scribble;
-    else
-      ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble;
-
-    HOSTDATA(shpnt)->commands--; 
-
-    restore_flags(flags);
-
-    ptr->host_scribble = NULL;
-    ptr->result = DID_ABORT << 16;
-    ptr->scsi_done(ptr);
-
-    return SCSI_ABORT_SUCCESS;
-  }
-
-  /* if the bus is busy or a command is currently processed,
-     we can't do anything more */
-  if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC!=SCpnt)) {
-    /* fail abortion, if bus is busy */
-
-    if(!CURRENT_SC)
-      printk("bus busy w/o current command, ");
- 
-    restore_flags(flags);
-
-    return SCSI_ABORT_BUSY;
-  }
-
-  /* bus is free */
-
-  if(CURRENT_SC) { 
-    HOSTDATA(shpnt)->commands--; 
-
-    /* target entered bus free before COMMAND COMPLETE, nothing to abort */
-    restore_flags(flags);
-    CURRENT_SC->result = DID_ERROR << 16;
-    CURRENT_SC->scsi_done(CURRENT_SC);
-    CURRENT_SC = (Scsi_Cmnd *) NULL;
-
-    return SCSI_ABORT_SUCCESS;
-  }
-
-  /* look for command in disconnected queue */
-  for(ptr=DISCONNECTED_SC, prev=NULL;
-       ptr && ptr!=SCpnt;
-       prev=ptr, ptr=(Scsi_Cmnd *) ptr->host_scribble)
-    ;
-
-  if(!ptr) {
-    /* command wasn't found */
-    printk("command not found\n");
-    restore_flags(flags);
-
-    return SCSI_ABORT_NOT_RUNNING;
-  }
-
-  if(!HOSTDATA(shpnt)->aborting) {
-    /* dequeue */
-    if(prev)
-      prev->host_scribble = ptr->host_scribble;
-    else
-      DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
-
-    HOSTDATA(shpnt)->commands--; 
-
-    /* set command current and initiate selection,
-       let the interrupt routine take care of the abortion */
-    CURRENT_SC     = ptr;
-    ptr->SCp.phase = in_selection|aborted;
-    SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
-      
-    ADDMSG(ABORT);
-
-    /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-    SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
-    SETPORT(SIMODE1, ENSELTIMO);
-
-    /* Enable SELECTION OUT sequence */
-    SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
-
-    SETBITS(DMACNTRL0, INTEN);
-    HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
-    HOSTDATA(shpnt)->aborting++;
-    HOSTDATA(shpnt)->abortion_complete=0;
-
-    restore_flags(flags);
-
-    /* sleep until the abortion is complete */
-    while(!HOSTDATA(shpnt)->abortion_complete)
-      barrier();
-    HOSTDATA(shpnt)->aborting=0;
-
-    return HOSTDATA(shpnt)->abort_result;
-  } else {
-    /* we're already aborting a command */
-    restore_flags(flags);
+	if (HOSTDATA(shpnt)->debug & debug_abort) {
+		printk("aha152x: abort(), SCpnt=0x%08x, ", (unsigned int) SCpnt);
+		show_queues(shpnt);
+	}
+#endif
+
+	/* look for command in issue queue */
+	for (ptr = ISSUE_SC, prev = NULL;
+	     ptr && ptr != SCpnt;
+	     prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble);
+
+	if (ptr) {
+		/* dequeue */
+		if (prev)
+			prev->host_scribble = ptr->host_scribble;
+		else
+			ISSUE_SC = (Scsi_Cmnd *) ptr->host_scribble;
+
+		HOSTDATA(shpnt)->commands--;
+
+		restore_flags(flags);
+
+		ptr->host_scribble = NULL;
+		ptr->result = DID_ABORT << 16;
+		spin_lock_irqsave(&io_request_lock, flags);
+		ptr->scsi_done(ptr);
+		spin_unlock_irqrestore(&io_request_lock, flags);
+
+		return SCSI_ABORT_SUCCESS;
+	}
+	/* if the bus is busy or a command is currently processed,
+	   we can't do anything more */
+	if (TESTLO(SSTAT1, BUSFREE) || (CURRENT_SC && CURRENT_SC != SCpnt)) {
+		/* fail abortion, if bus is busy */
+
+		if (!CURRENT_SC)
+			printk("bus busy w/o current command, ");
+
+		restore_flags(flags);
+
+		return SCSI_ABORT_BUSY;
+	}
+	/* bus is free */
+
+	if (CURRENT_SC) {
+		HOSTDATA(shpnt)->commands--;
+
+		/* target entered bus free before COMMAND COMPLETE, nothing to abort */
+		restore_flags(flags);
+		spin_lock_irqsave(&io_request_lock, flags);
+		CURRENT_SC->result = DID_ERROR << 16;
+		CURRENT_SC->scsi_done(CURRENT_SC);
+		CURRENT_SC = (Scsi_Cmnd *) NULL;
+		spin_unlock_irqrestore(&io_request_lock, flags);
+
+		return SCSI_ABORT_SUCCESS;
+	}
+	/* look for command in disconnected queue */
+	for (ptr = DISCONNECTED_SC, prev = NULL;
+	     ptr && ptr != SCpnt;
+	     prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble);
+
+	if (!ptr) {
+		/* command wasn't found */
+		printk("command not found\n");
+		restore_flags(flags);
+
+		return SCSI_ABORT_NOT_RUNNING;
+	}
+	if (!HOSTDATA(shpnt)->aborting) {
+		/* dequeue */
+		if (prev)
+			prev->host_scribble = ptr->host_scribble;
+		else
+			DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
+
+		HOSTDATA(shpnt)->commands--;
+
+		/* set command current and initiate selection,
+		   let the interrupt routine take care of the abortion */
+		CURRENT_SC = ptr;
+		ptr->SCp.phase = in_selection | aborted;
+		SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
+
+		ADDMSG(ABORT);
+
+		/* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
+		SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+		SETPORT(SIMODE1, ENSELTIMO);
+
+		/* Enable SELECTION OUT sequence */
+		SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
+
+		SETBITS(DMACNTRL0, INTEN);
+		HOSTDATA(shpnt)->abort_result = SCSI_ABORT_SUCCESS;
+		HOSTDATA(shpnt)->aborting++;
+		HOSTDATA(shpnt)->abortion_complete = 0;
+
+		restore_flags(flags);
+
+		/* sleep until the abortion is complete */
+		while (!HOSTDATA(shpnt)->abortion_complete)
+			barrier();
+		HOSTDATA(shpnt)->aborting = 0;
+
+		return HOSTDATA(shpnt)->abort_result;
+	} else {
+		/* we're already aborting a command */
+		restore_flags(flags);
 
-    return SCSI_ABORT_BUSY;
-  }
+		return SCSI_ABORT_BUSY;
+	}
 }
 
 /*
@@ -1319,110 +1338,113 @@
  */
 static void aha152x_reset_ports(struct Scsi_Host *shpnt)
 {
-  /* disable interrupts */
-  SETPORT(DMACNTRL0, RSTFIFO);
+	/* disable interrupts */
+	SETPORT(DMACNTRL0, RSTFIFO);
 
-  SETPORT(SCSISEQ, 0);
+	SETPORT(SCSISEQ, 0);
 
-  SETPORT(SXFRCTL1, 0);
-  SETPORT(SCSISIG, 0);
-  SETPORT(SCSIRATE, 0);
+	SETPORT(SXFRCTL1, 0);
+	SETPORT(SCSISIG, 0);
+	SETPORT(SCSIRATE, 0);
 
-  /* clear all interrupt conditions */
-  SETPORT(SSTAT0, 0x7f);
-  SETPORT(SSTAT1, 0xef);
+	/* clear all interrupt conditions */
+	SETPORT(SSTAT0, 0x7f);
+	SETPORT(SSTAT1, 0xef);
 
-  SETPORT(SSTAT4, SYNCERR|FWERR|FRERR);
+	SETPORT(SSTAT4, SYNCERR | FWERR | FRERR);
 
-  SETPORT(DMACNTRL0, 0);
-  SETPORT(DMACNTRL1, 0);
+	SETPORT(DMACNTRL0, 0);
+	SETPORT(DMACNTRL1, 0);
 
-  SETPORT(BRSTCNTRL, 0xf1);
+	SETPORT(BRSTCNTRL, 0xf1);
 
-  /* clear SCSI fifo and transfer count */
-  SETPORT(SXFRCTL0, CH1|CLRCH1|CLRSTCNT);
-  SETPORT(SXFRCTL0, CH1);
+	/* clear SCSI fifo and transfer count */
+	SETPORT(SXFRCTL0, CH1 | CLRCH1 | CLRSTCNT);
+	SETPORT(SXFRCTL0, CH1);
 
-  /* enable interrupts */
-  SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-  SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+	/* enable interrupts */
+	SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+	SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 }
 
 /*
  *  Reset registers, reset a hanging bus and
  *  kill active and disconnected commands for target w/o soft reset
  */
-int aha152x_reset(Scsi_Cmnd *SCpnt, unsigned int unused)
+int aha152x_reset(Scsi_Cmnd * SCpnt, unsigned int unused)
 {
-  struct Scsi_Host *shpnt = SCpnt->host;
-  unsigned long flags;
-  Scsi_Cmnd *ptr, *prev, *next;
+	struct Scsi_Host *shpnt = SCpnt->host;
+	unsigned long flags;
+	Scsi_Cmnd *ptr, *prev, *next;
 
-  aha152x_reset_ports(shpnt);
+	aha152x_reset_ports(shpnt);
 
-  /* Reset, if bus hangs */
-  if(TESTLO(SSTAT1, BUSFREE)) {
-    CLRBITS(DMACNTRL0, INTEN);
+	/* Reset, if bus hangs */
+	if (TESTLO(SSTAT1, BUSFREE)) {
+		CLRBITS(DMACNTRL0, INTEN);
 
 #if defined(DEBUG_RESET)
-    if(HOSTDATA(shpnt)->debug & debug_reset) {
-      printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");
-      show_queues(shpnt);
-    }
-#endif
-
-    ptr=CURRENT_SC;
-    if(ptr && !ptr->device->soft_reset) {
-      ptr->host_scribble = NULL;
-      ptr->result = DID_RESET << 16;
-      ptr->scsi_done(CURRENT_SC);
-      CURRENT_SC=NULL;
-    }
-
-    save_flags(flags);
-    cli();
-    prev=NULL; ptr=DISCONNECTED_SC;
-    while(ptr) {
-      if(!ptr->device->soft_reset) {
-        if(prev)
-          prev->host_scribble = ptr->host_scribble;
-        else
-          DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
-
-        next = (Scsi_Cmnd *) ptr->host_scribble;
-
-        ptr->host_scribble = NULL;
-        ptr->result        = DID_RESET << 16;
-        ptr->scsi_done(ptr);
-  
-        ptr = next; 
-      } else {
-        prev=ptr;
-        ptr = (Scsi_Cmnd *) ptr->host_scribble;
-      }
-    }
-    restore_flags(flags);
+		if (HOSTDATA(shpnt)->debug & debug_reset) {
+			printk("aha152x: reset(), bus not free: SCSI RESET OUT\n");
+			show_queues(shpnt);
+		}
+#endif
+
+		ptr = CURRENT_SC;
+		if (ptr && !ptr->device->soft_reset) {
+			ptr->host_scribble = NULL;
+			ptr->result = DID_RESET << 16;
+			spin_lock_irqsave(&io_request_lock, flags);
+			ptr->scsi_done(CURRENT_SC);
+			spin_unlock_irqrestore(&io_request_lock, flags);
+			CURRENT_SC = NULL;
+		}
+		save_flags(flags);
+		cli();
+		prev = NULL;
+		ptr = DISCONNECTED_SC;
+		while (ptr) {
+			if (!ptr->device->soft_reset) {
+				if (prev)
+					prev->host_scribble = ptr->host_scribble;
+				else
+					DISCONNECTED_SC = (Scsi_Cmnd *) ptr->host_scribble;
+
+				next = (Scsi_Cmnd *) ptr->host_scribble;
+
+				ptr->host_scribble = NULL;
+				ptr->result = DID_RESET << 16;
+				spin_lock_irqsave(&io_request_lock, flags);
+				ptr->scsi_done(ptr);
+				spin_unlock_irqrestore(&io_request_lock, flags);
+
+				ptr = next;
+			} else {
+				prev = ptr;
+				ptr = (Scsi_Cmnd *) ptr->host_scribble;
+			}
+		}
+		restore_flags(flags);
 
 #if defined(DEBUG_RESET)
-    if(HOSTDATA(shpnt)->debug & debug_reset) {
-      printk("commands on targets w/ soft-resets:\n");
-      show_queues(shpnt);
-    }
+		if (HOSTDATA(shpnt)->debug & debug_reset) {
+			printk("commands on targets w/ soft-resets:\n");
+			show_queues(shpnt);
+		}
 #endif
 
-    /* RESET OUT */
-    SETPORT(SCSISEQ, SCSIRSTO);
-    do_pause(30);
-    SETPORT(SCSISEQ, 0);
-    do_pause(DELAY);
-
-    SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-    SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+		/* RESET OUT */
+		SETPORT(SCSISEQ, SCSIRSTO);
+		do_pause(30);
+		SETPORT(SCSISEQ, 0);
+		do_pause(DELAY);
 
-    SETPORT(DMACNTRL0, INTEN);
-  }
+		SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+		SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-  return SCSI_RESET_SUCCESS;
+		SETPORT(DMACNTRL0, INTEN);
+	}
+	return SCSI_RESET_SUCCESS;
 }
 
 /*
@@ -1430,59 +1452,58 @@
  */
 int aha152x_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
 {
-  struct Scsi_Host *shpnt=disk->device->host;
+	struct Scsi_Host *shpnt = disk->device->host;
 
 #if defined(DEBUG_BIOSPARAM)
-  if(HOSTDATA(shpnt)->debug & debug_biosparam)
-    printk("aha152x_biosparam: dev=%s, size=%d, ",
-           kdevname(dev), disk->capacity);
-#endif
- 
-  /* try default translation */
-  info_array[0]=64;
-  info_array[1]=32;
-  info_array[2]=disk->capacity / (64 * 32);
-
-  /* for disks >1GB do some guessing */
-  if(info_array[2]>=1024) {
-    int info[3];
-
-    /* try to figure out the geometry from the partition table */
-    if(scsicam_bios_param(disk, dev, info)<0 ||
-       !((info[0]==64 && info[1]==32) || (info[0]==255 && info[1]==63))) {
-      if(EXT_TRANS) {
-        printk("aha152x: unable to verify geometry for disk with >1GB.\n"
-               "         using extended translation.\n");
-        info_array[0] = 255;
-        info_array[1] = 63;
-        info_array[2] = disk->capacity / (255 * 63);
-      } else {
-        printk("aha152x: unable to verify geometry for disk with >1GB.\n"
-               "         Using default translation. Please verify yourself.\n"
-               "         Perhaps you need to enable extended translation in the driver.\n"
-               "         See /usr/src/linux/drivers/scsi/aha152x.c for details.\n");
-      }
-    } else {
-      info_array[0]=info[0];
-      info_array[1]=info[1];
-      info_array[2]=info[2];
-      
-      if(info[0]==255 && !EXT_TRANS) {
-        printk("aha152x: current partition table is using extended translation.\n"
-               "         using it also, although it's not explicty enabled.\n");
-      }
-    }
-  }
-
+	if (HOSTDATA(shpnt)->debug & debug_biosparam)
+		printk("aha152x_biosparam: dev=%s, size=%d, ",
+		       kdevname(dev), disk->capacity);
+#endif
+
+	/* try default translation */
+	info_array[0] = 64;
+	info_array[1] = 32;
+	info_array[2] = disk->capacity / (64 * 32);
+
+	/* for disks >1GB do some guessing */
+	if (info_array[2] >= 1024) {
+		int info[3];
+
+		/* try to figure out the geometry from the partition table */
+		if (scsicam_bios_param(disk, dev, info) < 0 ||
+		    !((info[0] == 64 && info[1] == 32) || (info[0] == 255 && info[1] == 63))) {
+			if (EXT_TRANS) {
+				printk("aha152x: unable to verify geometry for disk with >1GB.\n"
+				"         using extended translation.\n");
+				info_array[0] = 255;
+				info_array[1] = 63;
+				info_array[2] = disk->capacity / (255 * 63);
+			} else {
+				printk("aha152x: unable to verify geometry for disk with >1GB.\n"
+				       "         Using default translation. Please verify yourself.\n"
+				       "         Perhaps you need to enable extended translation in the driver.\n"
+				       "         See /usr/src/linux/drivers/scsi/aha152x.c for details.\n");
+			}
+		} else {
+			info_array[0] = info[0];
+			info_array[1] = info[1];
+			info_array[2] = info[2];
+
+			if (info[0] == 255 && !EXT_TRANS) {
+				printk("aha152x: current partition table is using extended translation.\n"
+				       "         using it also, although it's not explicty enabled.\n");
+			}
+		}
+	}
 #if defined(DEBUG_BIOSPARAM)
-  if(HOSTDATA(shpnt)->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");
-  }
+	if (HOSTDATA(shpnt)->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;
+	return 0;
 }
 
 /*
@@ -1490,71 +1511,73 @@
  */
 void aha152x_done(struct Scsi_Host *shpnt, int error)
 {
-  unsigned long flags;
-  Scsi_Cmnd *done_SC;
+	unsigned long flags;
+	Scsi_Cmnd *done_SC;
 
 #if defined(DEBUG_DONE)
-  if(HOSTDATA(shpnt)->debug & debug_done) {
-    printk("\naha152x: done(), ");
-    disp_ports(shpnt);
-  }
+	if (HOSTDATA(shpnt)->debug & debug_done) {
+		printk("\naha152x: done(), ");
+		disp_ports(shpnt);
+	}
 #endif
 
-  if(CURRENT_SC) {
+	if (CURRENT_SC) {
 #if defined(DEBUG_DONE)
-    if(HOSTDATA(shpnt)->debug & debug_done)
-      printk("done(%x), ", error);
+		if (HOSTDATA(shpnt)->debug & debug_done)
+			printk("done(%x), ", error);
 #endif
 
-    save_flags(flags);
-    cli();
+		save_flags(flags);
+		cli();
 
-    done_SC = CURRENT_SC;
-    CURRENT_SC = NULL;
+		done_SC = CURRENT_SC;
+		CURRENT_SC = NULL;
 
-    /* turn led off, when no commands are in the driver */
-    HOSTDATA(shpnt)->commands--;
-    if(!HOSTDATA(shpnt)->commands)
-      SETPORT(PORTA, 0);                                  /* turn led off */
+		/* turn led off, when no commands are in the driver */
+		HOSTDATA(shpnt)->commands--;
+		if (!HOSTDATA(shpnt)->commands)
+			SETPORT(PORTA, 0);	/* turn led off */
 
 #if defined(DEBUG_QUEUES)
-    if(HOSTDATA(shpnt)->debug & debug_queues) 
-      printk("ok (%d), ", HOSTDATA(shpnt)->commands);
+		if (HOSTDATA(shpnt)->debug & debug_queues)
+			printk("ok (%d), ", HOSTDATA(shpnt)->commands);
 #endif
-    restore_flags(flags);
+		restore_flags(flags);
 
-    SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-    SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+		SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+		SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
 #if 0
 /* Why poll for the BUS FREE phase, when we have setup the interrupt!? */
 #if defined(DEBUG_PHASES)
-    if(HOSTDATA(shpnt)->debug & debug_phases)
-      printk("BUS FREE loop, ");
+		if (HOSTDATA(shpnt)->debug & debug_phases)
+			printk("BUS FREE loop, ");
 #endif
-    while(TESTLO(SSTAT1, BUSFREE))
-      barrier();
+		while (TESTLO(SSTAT1, BUSFREE))
+			barrier();
 #if defined(DEBUG_PHASES)
-    if(HOSTDATA(shpnt)->debug & debug_phases)
-      printk("BUS FREE\n");
+		if (HOSTDATA(shpnt)->debug & debug_phases)
+			printk("BUS FREE\n");
 #endif
 #endif
 
-    done_SC->result = error;
-    if(done_SC->scsi_done) {
+		done_SC->result = error;
+		if (done_SC->scsi_done) {
 #if defined(DEBUG_DONE)
-      if(HOSTDATA(shpnt)->debug & debug_done)
-        printk("calling scsi_done, ");
+			if (HOSTDATA(shpnt)->debug & debug_done)
+				printk("calling scsi_done, ");
 #endif
-      done_SC->scsi_done(done_SC);
+			spin_lock_irqsave(&io_request_lock, flags);
+			done_SC->scsi_done(done_SC);
+			spin_unlock_irqrestore(&io_request_lock, flags);
 #if defined(DEBUG_DONE)
-      if(HOSTDATA(shpnt)->debug & debug_done)
-        printk("done returned, ");
+			if (HOSTDATA(shpnt)->debug & debug_done)
+				printk("done returned, ");
 #endif
-    } else
-       panic("aha152x: current_SC->scsi_done() == NULL");
-  } else
-    aha152x_panic(shpnt, "done() called outside of command");
+		} else
+			panic("aha152x: current_SC->scsi_done() == NULL");
+	} else
+		aha152x_panic(shpnt, "done() called outside of command");
 }
 
 
@@ -1563,41 +1586,39 @@
 static struct tq_struct aha152x_tq;
 
 /*
- *	Run service completions on the card with interrupts enabled.
+ *    Run service completions on the card with interrupts enabled.
  */
- 
+
 static void aha152x_run(void)
 {
 	int i;
-	for(i=0;i<IRQS;i++)
-	{
-		struct Scsi_Host *shpnt=aha152x_host[i];
-		if(shpnt && HOSTDATA(shpnt)->service)
-		{
-			HOSTDATA(shpnt)->service=0;
+	for (i = 0; i < IRQS; i++) {
+		struct Scsi_Host *shpnt = aha152x_host[i];
+		if (shpnt && HOSTDATA(shpnt)->service) {
+			HOSTDATA(shpnt)->service = 0;
 			aha152x_complete(shpnt);
 		}
 	}
 }
 
 /*
- *	Interrupts handler (main routine of the driver)
+ *    Interrupts handler (main routine of the driver)
  */
 
-static void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs)
+static void aha152x_intr(int irqno, void *dev_id, struct pt_regs *regs)
 {
-	struct Scsi_Host *shpnt = aha152x_host[irqno-IRQ_MIN];
+	struct Scsi_Host *shpnt = aha152x_host[irqno - IRQ_MIN];
 
 #if defined(DEBUG_RACE)
 	enter_driver("intr");
 #else
 #if defined(DEBUG_INTR)
-	if(HOSTDATA(shpnt)->debug & debug_intr)
+	if (HOSTDATA(shpnt)->debug & debug_intr)
 		printk("\naha152x: intr(), ");
 #endif
 #endif
 
-	if(!shpnt)
+	if (!shpnt)
 		panic("aha152x: catched interrupt for unknown controller.\n");
 
 	/* no more interrupts from the controller, while we're busy.
@@ -1606,9 +1627,9 @@
 	CLRBITS(DMACNTRL0, INTEN);
 
 	/* Poke the BH handler */
-	
-	HOSTDATA(shpnt)->service=1;
-	aha152x_tq.routine = (void *)aha152x_run;
+
+	HOSTDATA(shpnt)->service = 1;
+	aha152x_tq.routine = (void *) aha152x_run;
 	queue_task(&aha152x_tq, &tq_immediate);
 	mark_bh(IMMEDIATE_BH);
 }
@@ -1616,1020 +1637,1001 @@
 static void aha152x_complete(struct Scsi_Host *shpnt)
 {
 	unsigned int flags;
-	int done=0, phase;
+	int done = 0, phase;
 
 	/* disconnected target is trying to reconnect.
 	   Only possible, if we have disconnected nexuses and
 	   nothing is occupying the bus.
 	 */
-	 
-  if(TESTHI(SSTAT0, SELDI) &&
-      DISCONNECTED_SC &&
-      (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection)) ) {
-    int identify_msg, target, i;
-
-    /* Avoid conflicts when a target reconnects
-       while we are trying to connect to another. */
-    if(CURRENT_SC) {
+
+	if (TESTHI(SSTAT0, SELDI) &&
+	    DISCONNECTED_SC &&
+	    (!CURRENT_SC || (CURRENT_SC->SCp.phase & in_selection))) {
+		int identify_msg, target, i;
+
+		/* Avoid conflicts when a target reconnects
+		   while we are trying to connect to another. */
+		if (CURRENT_SC) {
 #if defined(DEBUG_QUEUES)
-      if(HOSTDATA(shpnt)->debug & debug_queues)
-        printk("i+, ");
+			if (HOSTDATA(shpnt)->debug & debug_queues)
+				printk("i+, ");
 #endif
-      save_flags(flags);
-      cli();
-      append_SC(&ISSUE_SC, CURRENT_SC);
-      CURRENT_SC=NULL;
-      restore_flags(flags);
-    }
-
-    /* disable sequences */
-    SETPORT(SCSISEQ, 0);
-    SETPORT(SSTAT0, CLRSELDI);
-    SETPORT(SSTAT1, CLRBUSFREE);
+			save_flags(flags);
+			cli();
+			append_SC(&ISSUE_SC, CURRENT_SC);
+			CURRENT_SC = NULL;
+			restore_flags(flags);
+		}
+		/* disable sequences */
+		SETPORT(SCSISEQ, 0);
+		SETPORT(SSTAT0, CLRSELDI);
+		SETPORT(SSTAT1, CLRBUSFREE);
 
 #if defined(DEBUG_QUEUES) || defined(DEBUG_PHASES)
-    if(HOSTDATA(shpnt)->debug & (debug_queues|debug_phases))
-      printk("reselected, ");
+		if (HOSTDATA(shpnt)->debug & (debug_queues | debug_phases))
+			printk("reselected, ");
 #endif
 
-    i = GETPORT(SELID) & ~(1 << shpnt->this_id);
-    target=0;
+		i = GETPORT(SELID) & ~(1 << shpnt->this_id);
+		target = 0;
 
-    if(i==0)
-      aha152x_panic(shpnt, "reconnecting target unknown");
+		if (i == 0)
+			aha152x_panic(shpnt, "reconnecting target unknown");
 
-    for(; (i & 1)==0; target++, i>>=1)
-      ;
+		for (; (i & 1) == 0; target++, i >>= 1);
 
 #if defined(DEBUG_QUEUES)
-    if(HOSTDATA(shpnt)->debug & debug_queues)
-      printk("SELID=%02x, target=%d, ", GETPORT(SELID), target);
+		if (HOSTDATA(shpnt)->debug & debug_queues)
+			printk("SELID=%02x, target=%d, ", GETPORT(SELID), target);
 #endif
-    SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
-    SETPORT(SCSISEQ, ENRESELI);
-
-    if(TESTLO(SSTAT0, SELDI))
-      aha152x_panic(shpnt, "RESELI failed");
-
-    SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target]&0x7f);
+		SETPORT(SCSIID, (shpnt->this_id << OID_) | target);
+		SETPORT(SCSISEQ, ENRESELI);
 
-    SETPORT(SCSISIG, P_MSGI);
+		if (TESTLO(SSTAT0, SELDI))
+			aha152x_panic(shpnt, "RESELI failed");
 
-    /* Get identify message */
-    if((i=getphase(shpnt))!=P_MSGI) {
-      printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
-      aha152x_panic(shpnt, "unknown lun");
-    }
-    SETPORT(SCSISEQ, 0);
+		SETPORT(SCSIRATE, HOSTDATA(shpnt)->syncrate[target] & 0x7f);
 
-    SETPORT(SXFRCTL0, CH1);
+		SETPORT(SCSISIG, P_MSGI);
 
-    identify_msg = GETPORT(SCSIBUS);
+		/* Get identify message */
+		if ((i = getphase(shpnt)) != P_MSGI) {
+			printk("target doesn't enter MSGI to identify (phase=%02x)\n", i);
+			aha152x_panic(shpnt, "unknown lun");
+		}
+		SETPORT(SCSISEQ, 0);
 
-    if(!(identify_msg & IDENTIFY_BASE)) {
-      printk("target=%d, inbound message (%02x) != IDENTIFY\n",
-             target, identify_msg);
-      aha152x_panic(shpnt, "unknown lun");
-    }
+		SETPORT(SXFRCTL0, CH1);
 
+		identify_msg = GETPORT(SCSIBUS);
 
+		if (!(identify_msg & IDENTIFY_BASE)) {
+			printk("target=%d, inbound message (%02x) != IDENTIFY\n",
+			       target, identify_msg);
+			aha152x_panic(shpnt, "unknown lun");
+		}
 #if defined(DEBUG_QUEUES)
-    if(HOSTDATA(shpnt)->debug & debug_queues)
-      printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f);
+		if (HOSTDATA(shpnt)->debug & debug_queues)
+			printk("identify=%02x, lun=%d, ", identify_msg, identify_msg & 0x3f);
 #endif
 
-    save_flags(flags);
-    cli();
+		save_flags(flags);
+		cli();
 
 #if defined(DEBUG_QUEUES)
-    if(HOSTDATA(shpnt)->debug & debug_queues)
-      printk("d-, ");
+		if (HOSTDATA(shpnt)->debug & debug_queues)
+			printk("d-, ");
 #endif
-    CURRENT_SC = remove_SC(&DISCONNECTED_SC, target, identify_msg & 0x3f);
+		CURRENT_SC = remove_SC(&DISCONNECTED_SC, target, identify_msg & 0x3f);
+
+		if (!CURRENT_SC) {
+			printk("lun=%d, ", identify_msg & 0x3f);
+			aha152x_panic(shpnt, "no disconnected command for that lun");
+		}
+		CURRENT_SC->SCp.phase &= ~disconnected;
+		restore_flags(flags);
 
-    if(!CURRENT_SC) {
-      printk("lun=%d, ", identify_msg & 0x3f);
-      aha152x_panic(shpnt, "no disconnected command for that lun");
-    }
-
-    CURRENT_SC->SCp.phase &= ~disconnected;
-    restore_flags(flags);
-
-    make_acklow(shpnt);
-    if(getphase(shpnt)!=P_MSGI) {
-      SETPORT(SIMODE0, 0);
-      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
+		make_acklow(shpnt);
+		if (getphase(shpnt) != P_MSGI) {
+			SETPORT(SIMODE0, 0);
+			SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE);
 #if defined(DEBUG_RACE)
-      leave_driver("(reselected) intr");
+			leave_driver("(reselected) intr");
 #endif
-      SETBITS(DMACNTRL0, INTEN);
-      return;
-    }
-  }
-  
-  /* Check, if we aren't busy with a command */
-  if(!CURRENT_SC) {
-    /* bus is free to issue a queued command */
-    if(TESTHI(SSTAT1, BUSFREE) && ISSUE_SC) {
-      save_flags(flags);
-      cli();
+			SETBITS(DMACNTRL0, INTEN);
+			return;
+		}
+	}
+	/* Check, if we aren't busy with a command */
+	if (!CURRENT_SC) {
+		/* bus is free to issue a queued command */
+		if (TESTHI(SSTAT1, BUSFREE) && ISSUE_SC) {
+			save_flags(flags);
+			cli();
 #if defined(DEBUG_QUEUES)
-      if(HOSTDATA(shpnt)->debug & debug_queues)
-        printk("i-, ");
+			if (HOSTDATA(shpnt)->debug & debug_queues)
+				printk("i-, ");
 #endif
-      CURRENT_SC = remove_first_SC(&ISSUE_SC);
-      restore_flags(flags);
+			CURRENT_SC = remove_first_SC(&ISSUE_SC);
+			restore_flags(flags);
 
 #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
-        printk("issuing command, ");
+			if (HOSTDATA(shpnt)->debug & (debug_intr | debug_selection | debug_phases))
+				printk("issuing command, ");
 #endif
-      CURRENT_SC->SCp.phase = in_selection;
+			CURRENT_SC->SCp.phase = in_selection;
 
 #if defined(DEBUG_INTR) || defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_selection|debug_phases))
-        printk("selecting %d, ", CURRENT_SC->target); 
+			if (HOSTDATA(shpnt)->debug & (debug_intr | debug_selection | debug_phases))
+				printk("selecting %d, ", CURRENT_SC->target);
 #endif
-      SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
+			SETPORT(SCSIID, (shpnt->this_id << OID_) | CURRENT_SC->target);
 
-      /* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
-      SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK|ENSTIMER) : ENSTIMER);
+			/* Enable interrupts for SELECTION OUT DONE and SELECTION OUT INITIATED */
+			SETPORT(SXFRCTL1, HOSTDATA(shpnt)->parity ? (ENSPCHK | ENSTIMER) : ENSTIMER);
 
-      /* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
-      SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
-      SETPORT(SIMODE1, ENSELTIMO);
-
-      /* Enable SELECTION OUT sequence */
-      SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
-        
-    } else {
-      /* No command we are busy with and no new to issue */
-      printk("aha152x: ignoring spurious interrupt, nothing to do\n");
-      if(TESTHI(DMACNTRL0, SWINT)) {
-        printk("aha152x: SWINT is set!  Why?\n");
-        CLRBITS(DMACNTRL0, SWINT);
-      }
-      show_queues(shpnt);
-    }
+			/* enable interrupts for SELECTION OUT DONE and SELECTION TIME OUT */
+			SETPORT(SIMODE0, ENSELDO | (DISCONNECTED_SC ? ENSELDI : 0));
+			SETPORT(SIMODE1, ENSELTIMO);
+
+			/* Enable SELECTION OUT sequence */
+			SETBITS(SCSISEQ, ENSELO | ENAUTOATNO);
+
+		} else {
+			/* No command we are busy with and no new to issue */
+			printk("aha152x: ignoring spurious interrupt, nothing to do\n");
+			if (TESTHI(DMACNTRL0, SWINT)) {
+				printk("aha152x: SWINT is set!  Why?\n");
+				CLRBITS(DMACNTRL0, SWINT);
+			}
+			show_queues(shpnt);
+		}
 
 #if defined(DEBUG_RACE)
-    leave_driver("(selecting) intr");
+		leave_driver("(selecting) intr");
 #endif
-    SETBITS(DMACNTRL0, INTEN);
-          return;
-  }
-
-  /* the bus is busy with something */
+		SETBITS(DMACNTRL0, INTEN);
+		return;
+	}
+	/* the bus is busy with something */
 
 #if defined(DEBUG_INTR)
-  if(HOSTDATA(shpnt)->debug & debug_intr)
-    disp_ports(shpnt);
+	if (HOSTDATA(shpnt)->debug & debug_intr)
+		disp_ports(shpnt);
 #endif
 
-  /* we are waiting for the result of a selection attempt */
-  if(CURRENT_SC->SCp.phase & in_selection) {
-    if(TESTLO(SSTAT1, SELTO)) {
-      /* no timeout */
-      if(TESTHI(SSTAT0, SELDO)) {
-        /* clear BUS FREE interrupt */
-        SETPORT(SSTAT1, CLRBUSFREE);
-
-        /* Disable SELECTION OUT sequence */
-        CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
-
-        /* Disable SELECTION OUT DONE interrupt */
-        CLRBITS(SIMODE0, ENSELDO);
-        CLRBITS(SIMODE1, ENSELTIMO);
+	/* we are waiting for the result of a selection attempt */
+	if (CURRENT_SC->SCp.phase & in_selection) {
+		if (TESTLO(SSTAT1, SELTO)) {
+			/* no timeout */
+			if (TESTHI(SSTAT0, SELDO)) {
+				/* clear BUS FREE interrupt */
+				SETPORT(SSTAT1, CLRBUSFREE);
+
+				/* Disable SELECTION OUT sequence */
+				CLRBITS(SCSISEQ, ENSELO | ENAUTOATNO);
+
+				/* Disable SELECTION OUT DONE interrupt */
+				CLRBITS(SIMODE0, ENSELDO);
+				CLRBITS(SIMODE1, ENSELTIMO);
 
-        if(TESTLO(SSTAT0, SELDO)) {
-          printk("aha152x: passing bus free condition\n");
+				if (TESTLO(SSTAT0, SELDO)) {
+					printk("aha152x: passing bus free condition\n");
 
 #if defined(DEBUG_RACE)
-          leave_driver("(passing bus free) intr");
+					leave_driver("(passing bus free) intr");
 #endif
-          SETBITS(DMACNTRL0, INTEN);
+					SETBITS(DMACNTRL0, INTEN);
 
-          if(CURRENT_SC->SCp.phase & aborted) {
-            HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
-            HOSTDATA(shpnt)->abortion_complete++;
-          }
+					if (CURRENT_SC->SCp.phase & aborted) {
+						HOSTDATA(shpnt)->abort_result = SCSI_ABORT_ERROR;
+						HOSTDATA(shpnt)->abortion_complete++;
+					}
+					aha152x_done(shpnt, DID_NO_CONNECT << 16);
 
-          aha152x_done(shpnt, DID_NO_CONNECT << 16);
-
-          return;
-        }
+					return;
+				}
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-        if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
-          printk("SELDO (SELID=%x), ", GETPORT(SELID));
+				if (HOSTDATA(shpnt)->debug & (debug_selection | debug_phases))
+					printk("SELDO (SELID=%x), ", GETPORT(SELID));
 #endif
 
-        /* selection was done */
-        SETPORT(SSTAT0, CLRSELDO);
+				/* selection was done */
+				SETPORT(SSTAT0, CLRSELDO);
 
 #if defined(DEBUG_ABORT)
-        if((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted))
-          printk("(ABORT) target selected, ");
+				if ((HOSTDATA(shpnt)->debug & debug_abort) && (CURRENT_SC->SCp.phase & aborted))
+					printk("(ABORT) target selected, ");
 #endif
 
-        CURRENT_SC->SCp.phase &= ~in_selection;
-        CURRENT_SC->SCp.phase |= in_other;
-
-        ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun));
+				CURRENT_SC->SCp.phase &= ~in_selection;
+				CURRENT_SC->SCp.phase |= in_other;
 
-        if(!(SYNCRATE&0x80) && HOSTDATA(shpnt)->synchronous) {
-          ADDMSG(EXTENDED_MESSAGE);
-          ADDMSG(3);
-          ADDMSG(EXTENDED_SDTR);
-          ADDMSG(50);
-          ADDMSG(8);
+				ADDMSG(IDENTIFY(HOSTDATA(shpnt)->reconnect, CURRENT_SC->lun));
 
-          printk("outbound SDTR: ");
-          print_msg(&MSG(MSGLEN-5));
+				if (!(SYNCRATE & 0x80) && HOSTDATA(shpnt)->synchronous) {
+					ADDMSG(EXTENDED_MESSAGE);
+					ADDMSG(3);
+					ADDMSG(EXTENDED_SDTR);
+					ADDMSG(50);
+					ADDMSG(8);
 
-          SYNCRATE=0x80;
-          CURRENT_SC->SCp.phase |= in_sync;
-        }
+					printk("outbound SDTR: ");
+					print_msg(&MSG(MSGLEN - 5));
 
+					SYNCRATE = 0x80;
+					CURRENT_SC->SCp.phase |= in_sync;
+				}
 #if defined(DEBUG_RACE)
-        leave_driver("(SELDO) intr");
+				leave_driver("(SELDO) intr");
 #endif
-        SETPORT(SCSIRATE, SYNCRATE&0x7f);
+				SETPORT(SCSIRATE, SYNCRATE & 0x7f);
 
-        SETPORT(SCSISIG, P_MSGO);
+				SETPORT(SCSISIG, P_MSGO);
 
-        SETPORT(SIMODE0, 0);
-        SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
-        SETBITS(DMACNTRL0, INTEN);
+				SETPORT(SIMODE0, 0);
+				SETPORT(SIMODE1, ENREQINIT | ENBUSFREE);
+				SETBITS(DMACNTRL0, INTEN);
 
-        return;
-      } else
-        aha152x_panic(shpnt, "neither timeout nor selection\007");
-    } else {
+				return;
+			} else
+				aha152x_panic(shpnt, "neither timeout nor selection\007");
+		} else {
 #if defined(DEBUG_SELECTION) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_selection|debug_phases))
-        printk("SELTO, ");
+			if (HOSTDATA(shpnt)->debug & (debug_selection | debug_phases))
+				printk("SELTO, ");
 #endif
-      /* end selection attempt */
-      CLRBITS(SCSISEQ, ENSELO|ENAUTOATNO);
+			/* end selection attempt */
+			CLRBITS(SCSISEQ, ENSELO | ENAUTOATNO);
 
-      /* timeout */
-      SETPORT(SSTAT1, CLRSELTIMO);
+			/* timeout */
+			SETPORT(SSTAT1, CLRSELTIMO);
 
-      SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-      SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
-      SETBITS(DMACNTRL0, INTEN);
+			SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+			SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+			SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
-      leave_driver("(SELTO) intr");
+			leave_driver("(SELTO) intr");
 #endif
 
-      if(CURRENT_SC->SCp.phase & aborted) {
+			if (CURRENT_SC->SCp.phase & aborted) {
 #if defined(DEBUG_ABORT)
-        if(HOSTDATA(shpnt)->debug & debug_abort)
-          printk("(ABORT) selection timeout, ");
+				if (HOSTDATA(shpnt)->debug & debug_abort)
+					printk("(ABORT) selection timeout, ");
 #endif
-        HOSTDATA(shpnt)->abort_result=SCSI_ABORT_ERROR;
-        HOSTDATA(shpnt)->abortion_complete++;
-      }
-
-      if(TESTLO(SSTAT0, SELINGO))
-        /* ARBITRATION not won */
-        aha152x_done(shpnt, DID_BUS_BUSY << 16);
-      else
-        /* ARBITRATION won, but SELECTION failed */
-        aha152x_done(shpnt, DID_NO_CONNECT << 16);
-
-      return;
-    }
-  }
-
-  /* enable interrupt, when target leaves current phase */
-  phase = getphase(shpnt);
-  if(!(phase & ~P_MASK))                                      /* "real" phase */
-    SETPORT(SCSISIG, phase);
-  SETPORT(SSTAT1, CLRPHASECHG);
-  CURRENT_SC->SCp.phase =
-    (CURRENT_SC->SCp.phase & ~((P_MASK|1)<<16)) | (phase << 16);
-
-  /* information transfer phase */
-  switch(phase) {
-  case P_MSGO:                                               /* MESSAGE OUT */
-    {
-      int i, identify=0, abort=0;
+				HOSTDATA(shpnt)->abort_result = SCSI_ABORT_ERROR;
+				HOSTDATA(shpnt)->abortion_complete++;
+			}
+			if (TESTLO(SSTAT0, SELINGO))
+				/* ARBITRATION not won */
+				aha152x_done(shpnt, DID_BUS_BUSY << 16);
+			else
+				/* ARBITRATION won, but SELECTION failed */
+				aha152x_done(shpnt, DID_NO_CONNECT << 16);
+
+			return;
+		}
+	}
+	/* enable interrupt, when target leaves current phase */
+	phase = getphase(shpnt);
+	if (!(phase & ~P_MASK))	/* "real" phase */
+		SETPORT(SCSISIG, phase);
+	SETPORT(SSTAT1, CLRPHASECHG);
+	CURRENT_SC->SCp.phase =
+	    (CURRENT_SC->SCp.phase & ~((P_MASK | 1) << 16)) | (phase << 16);
+
+	/* information transfer phase */
+	switch (phase) {
+	case P_MSGO:		/* MESSAGE OUT */
+		{
+			int i, identify = 0, abort = 0;
 
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGO) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgo|debug_phases))
-        printk("MESSAGE OUT, ");
+			if (HOSTDATA(shpnt)->debug & (debug_intr | debug_msgo | debug_phases))
+				printk("MESSAGE OUT, ");
 #endif
-      if(MSGLEN==0) {
-        ADDMSG(MESSAGE_REJECT);
+			if (MSGLEN == 0) {
+				ADDMSG(MESSAGE_REJECT);
 #if defined(DEBUG_MSGO)
-        if(HOSTDATA(shpnt)->debug & debug_msgo)
-          printk("unexpected MESSAGE OUT phase; rejecting, ");
+				if (HOSTDATA(shpnt)->debug & debug_msgo)
+					printk("unexpected MESSAGE OUT phase; rejecting, ");
 #endif
-      }
-        
-      CLRBITS(SXFRCTL0, ENDMA);
-        
-      SETPORT(SIMODE0, 0);
-      SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE);
-        
-      /* wait for data latch to become ready or a phase change */
-      while(TESTLO(DMASTAT, INTSTAT))
-        barrier();
-        
+			}
+			CLRBITS(SXFRCTL0, ENDMA);
+
+			SETPORT(SIMODE0, 0);
+			SETPORT(SIMODE1, ENPHASEMIS | ENREQINIT | ENBUSFREE);
+
+			/* wait for data latch to become ready or a phase change */
+			while (TESTLO(DMASTAT, INTSTAT))
+				barrier();
+
 #if defined(DEBUG_MSGO)
-      if(HOSTDATA(shpnt)->debug & debug_msgo) {
-        int i;
-            
-        printk("messages (");
-        for(i=0; i<MSGLEN; i+=print_msg(&MSG(i)), printk(" "))
-          ;
-        printk("), ");
-      }
+			if (HOSTDATA(shpnt)->debug & debug_msgo) {
+				int i;
+
+				printk("messages (");
+				for (i = 0; i < MSGLEN; i += print_msg(&MSG(i)), printk(" "));
+				printk("), ");
+			}
 #endif
-        
-      for(i=0; i<MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++) {
+
+			for (i = 0; i < MSGLEN && TESTLO(SSTAT1, PHASEMIS); i++) {
 #if defined(DEBUG_MSGO)
-        if(HOSTDATA(shpnt)->debug & debug_msgo)
-          printk("%x ", MSG(i));
+				if (HOSTDATA(shpnt)->debug & debug_msgo)
+					printk("%x ", MSG(i));
 #endif
-        if(i==MSGLEN-1) {
-          /* Leave MESSAGE OUT after transfer */
-          SETPORT(SSTAT1, CLRATNO);
-        }
-          
-        SETPORT(SCSIDAT, MSG(i));
+				if (i == MSGLEN - 1) {
+					/* Leave MESSAGE OUT after transfer */
+					SETPORT(SSTAT1, CLRATNO);
+				}
+				SETPORT(SCSIDAT, MSG(i));
 
-        make_acklow(shpnt);
-        getphase(shpnt);
+				make_acklow(shpnt);
+				getphase(shpnt);
 
-        if(MSG(i)==IDENTIFY(HOSTDATA(shpnt)->reconnect,CURRENT_SC->lun))
-          identify++;
+				if (MSG(i) == IDENTIFY(HOSTDATA(shpnt)->reconnect, CURRENT_SC->lun))
+					identify++;
 
-        if(MSG(i)==ABORT)
-          abort++;
+				if (MSG(i) == ABORT)
+					abort++;
 
-      }
+			}
 
-      MSGLEN=0;
+			MSGLEN = 0;
 
-      if(identify)
-        CURRENT_SC->SCp.phase |= sent_ident;
+			if (identify)
+				CURRENT_SC->SCp.phase |= sent_ident;
 
-      if(abort) {
-        /* revive abort(); abort() enables interrupts */
-        HOSTDATA(shpnt)->abort_result=SCSI_ABORT_SUCCESS;
-        HOSTDATA(shpnt)->abortion_complete++;
+			if (abort) {
+				/* revive abort(); abort() enables interrupts */
+				HOSTDATA(shpnt)->abort_result = SCSI_ABORT_SUCCESS;
+				HOSTDATA(shpnt)->abortion_complete++;
 
-        CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
+				CURRENT_SC->SCp.phase &= ~(P_MASK << 16);
 
-        /* exit */
-        SETBITS(DMACNTRL0, INTEN);
+				/* exit */
+				SETBITS(DMACNTRL0, INTEN);
 #if defined(DEBUG_RACE)
-        leave_driver("(ABORT) intr");
+				leave_driver("(ABORT) intr");
 #endif
-        aha152x_done(shpnt, DID_ABORT<<16);
+				aha152x_done(shpnt, DID_ABORT << 16);
 
-        return;
-      }
-    }
-    break;
+				return;
+			}
+		}
+		break;
 
-  case P_CMD:                                          /* COMMAND phase */
+	case P_CMD:		/* COMMAND phase */
 #if defined(DEBUG_INTR) || defined(DEBUG_CMD) || defined(DEBUG_PHASES)
-    if(HOSTDATA(shpnt)->debug & (debug_intr|debug_cmd|debug_phases))
-      printk("COMMAND, ");
+		if (HOSTDATA(shpnt)->debug & (debug_intr | debug_cmd | debug_phases))
+			printk("COMMAND, ");
 #endif
-    if(!(CURRENT_SC->SCp.sent_command)) {
-      int i;
+		if (!(CURRENT_SC->SCp.sent_command)) {
+			int i;
+
+			CLRBITS(SXFRCTL0, ENDMA);
+
+			SETPORT(SIMODE0, 0);
+			SETPORT(SIMODE1, ENPHASEMIS | ENREQINIT | ENBUSFREE);
+
+			/* wait for data latch to become ready or a phase change */
+			while (TESTLO(DMASTAT, INTSTAT))
+				barrier();
 
-      CLRBITS(SXFRCTL0, ENDMA);
+			for (i = 0; i < CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++) {
+				SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]);
+
+				make_acklow(shpnt);
+				getphase(shpnt);
+			}
+
+			if (i < CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS))
+				aha152x_panic(shpnt, "target left COMMAND");
+
+			CURRENT_SC->SCp.sent_command++;
+		} else
+			aha152x_panic(shpnt, "Nothing to send while in COMMAND");
+		break;
+
+	case P_MSGI:		/* MESSAGE IN phase */
+		{
+			int start_sync = 0;
 
-      SETPORT(SIMODE0, 0);
-      SETPORT(SIMODE1, ENPHASEMIS|ENREQINIT|ENBUSFREE);
-  
-      /* wait for data latch to become ready or a phase change */
-      while(TESTLO(DMASTAT, INTSTAT))
-        barrier();
-  
-      for(i=0; i<CURRENT_SC->cmd_len && TESTLO(SSTAT1, PHASEMIS); i++) {
-        SETPORT(SCSIDAT, CURRENT_SC->cmnd[i]);
-
-        make_acklow(shpnt);
-        getphase(shpnt);
-      }
-
-      if(i<CURRENT_SC->cmd_len && TESTHI(SSTAT1, PHASEMIS))
-        aha152x_panic(shpnt, "target left COMMAND");
-
-      CURRENT_SC->SCp.sent_command++;
-    } else
-      aha152x_panic(shpnt, "Nothing to send while in COMMAND");
-      break;
-
-  case P_MSGI:                                          /* MESSAGE IN phase */
-    {
-      int start_sync=0;
-        
 #if defined(DEBUG_INTR) || defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_intr|debug_msgi|debug_phases))
-        printk("MESSAGE IN, ");
+			if (HOSTDATA(shpnt)->debug & (debug_intr | debug_msgi | debug_phases))
+				printk("MESSAGE IN, ");
 #endif
-      SETPORT(SXFRCTL0, CH1);
+			SETPORT(SXFRCTL0, CH1);
+
+			SETPORT(SIMODE0, 0);
+			SETPORT(SIMODE1, ENBUSFREE);
 
-      SETPORT(SIMODE0, 0);
-      SETPORT(SIMODE1, ENBUSFREE);
-  
-      while(phase == P_MSGI) {
-        CURRENT_SC->SCp.Message = GETPORT(SCSIDAT);
-        switch(CURRENT_SC->SCp.Message) {
-        case DISCONNECT:
+			while (phase == P_MSGI) {
+				CURRENT_SC->SCp.Message = GETPORT(SCSIDAT);
+				switch (CURRENT_SC->SCp.Message) {
+				case DISCONNECT:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-          if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
-            printk("target disconnected, ");
+					if (HOSTDATA(shpnt)->debug & (debug_msgi | debug_phases))
+						printk("target disconnected, ");
 #endif
-          CURRENT_SC->SCp.Message = 0;
-          CURRENT_SC->SCp.phase   |= disconnected;
-          if(!HOSTDATA(shpnt)->reconnect)
-            aha152x_panic(shpnt, "target was not allowed to disconnect");
-
-          break;
-        
-        case COMMAND_COMPLETE:
+					CURRENT_SC->SCp.Message = 0;
+					CURRENT_SC->SCp.phase |= disconnected;
+					if (!HOSTDATA(shpnt)->reconnect)
+						aha152x_panic(shpnt, "target was not allowed to disconnect");
+
+					break;
+
+				case COMMAND_COMPLETE:
 #if defined(DEBUG_MSGI) || defined(DEBUG_PHASES)
-          if(HOSTDATA(shpnt)->debug & (debug_msgi|debug_phases))
-            printk("inbound message (COMMAND COMPLETE), ");
+					if (HOSTDATA(shpnt)->debug & (debug_msgi | debug_phases))
+						printk("inbound message (COMMAND COMPLETE), ");
 #endif
-          done++;
-          break;
+					done++;
+					break;
 
-        case MESSAGE_REJECT:
-          if(CURRENT_SC->SCp.phase & in_sync) { 
-            CURRENT_SC->SCp.phase &= ~in_sync;
-            SYNCRATE=0x80;
-            printk("synchronous rejected, ");
-          } else
-            printk("inbound message (MESSAGE REJECT), ");
+				case MESSAGE_REJECT:
+					if (CURRENT_SC->SCp.phase & in_sync) {
+						CURRENT_SC->SCp.phase &= ~in_sync;
+						SYNCRATE = 0x80;
+						printk("synchronous rejected, ");
+					} else
+						printk("inbound message (MESSAGE REJECT), ");
 #if defined(DEBUG_MSGI)
-          if(HOSTDATA(shpnt)->debug & debug_msgi)
-            printk("inbound message (MESSAGE REJECT), ");
+					if (HOSTDATA(shpnt)->debug & debug_msgi)
+						printk("inbound message (MESSAGE REJECT), ");
 #endif
-          break;
+					break;
 
-        case SAVE_POINTERS:
+				case SAVE_POINTERS:
 #if defined(DEBUG_MSGI)
-          if(HOSTDATA(shpnt)->debug & debug_msgi)
-            printk("inbound message (SAVE DATA POINTERS), ");
+					if (HOSTDATA(shpnt)->debug & debug_msgi)
+						printk("inbound message (SAVE DATA POINTERS), ");
 #endif
-          break;
+					break;
 
-        case RESTORE_POINTERS:
+				case RESTORE_POINTERS:
 #if defined(DEBUG_MSGI)
-          if(HOSTDATA(shpnt)->debug & debug_msgi)
-            printk("inbound message (RESTORE DATA POINTERS), ");
+					if (HOSTDATA(shpnt)->debug & debug_msgi)
+						printk("inbound message (RESTORE DATA POINTERS), ");
 #endif
-          break;
+					break;
 
-        case EXTENDED_MESSAGE:
-          { 
-            char buffer[16];
-            int  i;
+				case EXTENDED_MESSAGE:
+					{
+						char buffer[16];
+						int i;
 
 #if defined(DEBUG_MSGI)
-            if(HOSTDATA(shpnt)->debug & debug_msgi)
-              printk("inbound message (EXTENDED MESSAGE), ");
+						if (HOSTDATA(shpnt)->debug & debug_msgi)
+							printk("inbound message (EXTENDED MESSAGE), ");
 #endif
-            make_acklow(shpnt);
-            if(getphase(shpnt)!=P_MSGI)
-              break;
-  
-            buffer[0]=EXTENDED_MESSAGE;
-            buffer[1]=GETPORT(SCSIDAT);
-
-            for(i=0; i<buffer[1] &&
-                     (make_acklow(shpnt), getphase(shpnt)==P_MSGI); i++)
-              buffer[2+i]=GETPORT(SCSIDAT);
+						make_acklow(shpnt);
+						if (getphase(shpnt) != P_MSGI)
+							break;
+
+						buffer[0] = EXTENDED_MESSAGE;
+						buffer[1] = GETPORT(SCSIDAT);
+
+						for (i = 0; i < buffer[1] &&
+						     (make_acklow(shpnt), getphase(shpnt) == P_MSGI); i++)
+							buffer[2 + i] = GETPORT(SCSIDAT);
 
 #if defined(DEBUG_MSGI)
-            if(HOSTDATA(shpnt)->debug & debug_msgi)
-              print_msg(buffer);
+						if (HOSTDATA(shpnt)->debug & debug_msgi)
+							print_msg(buffer);
 #endif
 
-            switch(buffer [2]) {
-            case EXTENDED_SDTR:
-              {
-                long ticks;
-
-                if(buffer[1]!=3)
-                  aha152x_panic(shpnt, "SDTR message length != 3");
-
-                if(!HOSTDATA(shpnt)->synchronous)
-                  break;
-
-                printk("inbound SDTR: "); print_msg(buffer);
-
-                ticks=(buffer[3]*4+49)/50;
-
-                if(CURRENT_SC->SCp.phase & in_sync) {
-                  /* we initiated SDTR */
-                  if(ticks>9 || buffer[4]<1 || buffer[4]>8)
-                    aha152x_panic(shpnt, "received SDTR invalid");
-
-                  SYNCRATE |= ((ticks-2)<<4) + buffer[4];
-                } else if(ticks<=9 && buffer[4]>=1) {
-                  if(buffer[4]>8)
-                    buffer[4]=8;
-        
-                  ADDMSG(EXTENDED_MESSAGE);
-                  ADDMSG(3);
-                  ADDMSG(EXTENDED_SDTR);
-                  if(ticks<4) {
-                    ticks=4;
-                    ADDMSG(50);
-                  } else
-                    ADDMSG(buffer[3]);
-
-                  ADDMSG(buffer[4]);
-
-                  printk("outbound SDTR: ");
-                  print_msg(&MSG(MSGLEN-5));
-
-                  CURRENT_SC->SCp.phase |= in_sync;
-                   
-                  SYNCRATE |= ((ticks-2)<<4) + buffer[4];
-
-                  start_sync++;
-                } else {
-                  /* requested SDTR is too slow, do it asynchronously */
-                  ADDMSG(MESSAGE_REJECT);
-                  SYNCRATE = 0;
-                } 
-
-                SETPORT(SCSIRATE, SYNCRATE&0x7f);
-              }
-              break;
-                      
-            case EXTENDED_MODIFY_DATA_POINTER:
-            case EXTENDED_EXTENDED_IDENTIFY:
-            case EXTENDED_WDTR:
-            default:
-              ADDMSG(MESSAGE_REJECT);
-              break;
-            }
-          }
-          break;
-       
-        default:
-          printk("unsupported inbound message %x, ", CURRENT_SC->SCp.Message);
-          break;
-
-        }
-
-        make_acklow(shpnt);
-        phase=getphase(shpnt);
-      } 
-
-      if(start_sync)
-        CURRENT_SC->SCp.phase |= in_sync;
-      else
-        CURRENT_SC->SCp.phase &= ~in_sync;
-        
-      if(MSGLEN>0)
-        SETPORT(SCSISIG, P_MSGI|ATNO);
-        
-      /* clear SCSI fifo on BUSFREE */
-      if(phase==P_BUSFREE)
-        SETPORT(SXFRCTL0, CH1|CLRCH1);
-
-      if(CURRENT_SC->SCp.phase & disconnected) {
-        save_flags(flags);
-        cli();
+						switch (buffer[2]) {
+						case EXTENDED_SDTR:
+							{
+								long ticks;
+
+								if (buffer[1] != 3)
+									aha152x_panic(shpnt, "SDTR message length != 3");
+
+								if (!HOSTDATA(shpnt)->synchronous)
+									break;
+
+								printk("inbound SDTR: ");
+								print_msg(buffer);
+
+								ticks = (buffer[3] * 4 + 49) / 50;
+
+								if (CURRENT_SC->SCp.phase & in_sync) {
+									/* we initiated SDTR */
+									if (ticks > 9 || buffer[4] < 1 || buffer[4] > 8)
+										aha152x_panic(shpnt, "received SDTR invalid");
+
+									SYNCRATE |= ((ticks - 2) << 4) + buffer[4];
+								} else if (ticks <= 9 && buffer[4] >= 1) {
+									if (buffer[4] > 8)
+										buffer[4] = 8;
+
+									ADDMSG(EXTENDED_MESSAGE);
+									ADDMSG(3);
+									ADDMSG(EXTENDED_SDTR);
+									if (ticks < 4) {
+										ticks = 4;
+										ADDMSG(50);
+									} else
+										ADDMSG(buffer[3]);
+
+									ADDMSG(buffer[4]);
+
+									printk("outbound SDTR: ");
+									print_msg(&MSG(MSGLEN - 5));
+
+									CURRENT_SC->SCp.phase |= in_sync;
+
+									SYNCRATE |= ((ticks - 2) << 4) + buffer[4];
+
+									start_sync++;
+								} else {
+									/* requested SDTR is too slow, do it asynchronously */
+									ADDMSG(MESSAGE_REJECT);
+									SYNCRATE = 0;
+								}
+
+								SETPORT(SCSIRATE, SYNCRATE & 0x7f);
+							}
+							break;
+
+						case EXTENDED_MODIFY_DATA_POINTER:
+						case EXTENDED_EXTENDED_IDENTIFY:
+						case EXTENDED_WDTR:
+						default:
+							ADDMSG(MESSAGE_REJECT);
+							break;
+						}
+					}
+					break;
+
+				default:
+					printk("unsupported inbound message %x, ", CURRENT_SC->SCp.Message);
+					break;
+
+				}
+
+				make_acklow(shpnt);
+				phase = getphase(shpnt);
+			}
+
+			if (start_sync)
+				CURRENT_SC->SCp.phase |= in_sync;
+			else
+				CURRENT_SC->SCp.phase &= ~in_sync;
+
+			if (MSGLEN > 0)
+				SETPORT(SCSISIG, P_MSGI | ATNO);
+
+			/* clear SCSI fifo on BUSFREE */
+			if (phase == P_BUSFREE)
+				SETPORT(SXFRCTL0, CH1 | CLRCH1);
+
+			if (CURRENT_SC->SCp.phase & disconnected) {
+				save_flags(flags);
+				cli();
 #if defined(DEBUG_QUEUES)
-        if(HOSTDATA(shpnt)->debug & debug_queues)
-          printk("d+, ");
+				if (HOSTDATA(shpnt)->debug & debug_queues)
+					printk("d+, ");
 #endif
-        append_SC(&DISCONNECTED_SC, CURRENT_SC);
-        CURRENT_SC->SCp.phase |= 1<<16;
-        CURRENT_SC = NULL;
-        restore_flags(flags);
+				append_SC(&DISCONNECTED_SC, CURRENT_SC);
+				CURRENT_SC->SCp.phase |= 1 << 16;
+				CURRENT_SC = NULL;
+				restore_flags(flags);
 
-        SETBITS(SCSISEQ, ENRESELI);
+				SETBITS(SCSISEQ, ENRESELI);
 
-        SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-        SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+				SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+				SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
 
-        SETBITS(DMACNTRL0, INTEN);
+				SETBITS(DMACNTRL0, INTEN);
 
-        return;
-      }
-    }
-    break;
+				return;
+			}
+		}
+		break;
 
-  case P_STATUS:                                         /* STATUS IN phase */
+	case P_STATUS:		/* STATUS IN phase */
 #if defined(DEBUG_STATUS) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-    if(HOSTDATA(shpnt)->debug & (debug_status|debug_intr|debug_phases))
-      printk("STATUS, ");
+		if (HOSTDATA(shpnt)->debug & (debug_status | debug_intr | debug_phases))
+			printk("STATUS, ");
 #endif
-    SETPORT(SXFRCTL0, CH1);
+		SETPORT(SXFRCTL0, CH1);
 
-    SETPORT(SIMODE0, 0);
-    SETPORT(SIMODE1, ENREQINIT|ENBUSFREE);
+		SETPORT(SIMODE0, 0);
+		SETPORT(SIMODE1, ENREQINIT | ENBUSFREE);
 
-    if(TESTHI(SSTAT1, PHASEMIS))
-      printk("aha152x: passing STATUS phase");
-      
-    CURRENT_SC->SCp.Status = GETPORT(SCSIBUS);
-    make_acklow(shpnt);
-    getphase(shpnt);
+		if (TESTHI(SSTAT1, PHASEMIS))
+			printk("aha152x: passing STATUS phase");
+
+		CURRENT_SC->SCp.Status = GETPORT(SCSIBUS);
+		make_acklow(shpnt);
+		getphase(shpnt);
 
 #if defined(DEBUG_STATUS)
-    if(HOSTDATA(shpnt)->debug & debug_status) {
-      printk("inbound status ");
-      print_status(CURRENT_SC->SCp.Status);
-      printk(", ");
-    }
-#endif
-    break;
-
-  case P_DATAI:                                            /* DATA IN phase */
-    {
-      int fifodata, data_count, done;
+		if (HOSTDATA(shpnt)->debug & debug_status) {
+			printk("inbound status ");
+			print_status(CURRENT_SC->SCp.Status);
+			printk(", ");
+		}
+#endif
+		break;
+
+	case P_DATAI:		/* DATA IN phase */
+		{
+			int fifodata, data_count, done;
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr|debug_phases))
-        printk("DATA IN, ");
+			if (HOSTDATA(shpnt)->debug & (debug_datai | debug_intr | debug_phases))
+				printk("DATA IN, ");
 #endif
 
 #if 0
-      if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT))
-        printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n",
-               GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
+			if (GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL | SFCNT))
+				printk("aha152x: P_DATAI: %d(%d) bytes left in FIFO, resetting\n",
+				       GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL | SFCNT));
 #endif
 
-      /* reset host fifo */
-      SETPORT(DMACNTRL0, RSTFIFO);
-      SETPORT(DMACNTRL0, RSTFIFO|ENDMA);
+			/* reset host fifo */
+			SETPORT(DMACNTRL0, RSTFIFO);
+			SETPORT(DMACNTRL0, RSTFIFO | ENDMA);
 
-      SETPORT(SXFRCTL0, CH1|SCSIEN|DMAEN);
+			SETPORT(SXFRCTL0, CH1 | SCSIEN | DMAEN);
 
-      SETPORT(SIMODE0, 0);
-      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
+			SETPORT(SIMODE0, 0);
+			SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE);
 
-      /* done is set when the FIFO is empty after the target left DATA IN */
-      done=0;
-      
-      /* while the target stays in DATA to transfer data */
-      while (!done) {
+			/* done is set when the FIFO is empty after the target left DATA IN */
+			done = 0;
+
+			/* while the target stays in DATA to transfer data */
+			while (!done) {
 #if defined(DEBUG_DATAI)
-        if(HOSTDATA(shpnt)->debug & debug_datai)
-          printk("expecting data, ");
+				if (HOSTDATA(shpnt)->debug & debug_datai)
+					printk("expecting data, ");
 #endif
-        /* wait for PHASEMIS or full FIFO */
-        while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT))
-          barrier();
+				/* wait for PHASEMIS or full FIFO */
+				while (TESTLO(DMASTAT, DFIFOFULL | INTSTAT))
+					barrier();
 
 #if defined(DEBUG_DATAI)
-        if(HOSTDATA(shpnt)->debug & debug_datai)
-          printk("ok, ");
+				if (HOSTDATA(shpnt)->debug & debug_datai)
+					printk("ok, ");
 #endif
-           
-        if(TESTHI(DMASTAT, DFIFOFULL))
-          fifodata=GETPORT(FIFOSTAT);
-        else {
-          /* wait for SCSI fifo to get empty */
-          while(TESTLO(SSTAT2, SEMPTY))
-            barrier();
 
-          /* rest of data in FIFO */
-          fifodata=GETPORT(FIFOSTAT);
+				if (TESTHI(DMASTAT, DFIFOFULL))
+					fifodata = GETPORT(FIFOSTAT);
+				else {
+					/* wait for SCSI fifo to get empty */
+					while (TESTLO(SSTAT2, SEMPTY))
+						barrier();
+
+					/* rest of data in FIFO */
+					fifodata = GETPORT(FIFOSTAT);
 #if defined(DEBUG_DATAI)
-          if(HOSTDATA(shpnt)->debug & debug_datai)
-            printk("last transfer, ");
+					if (HOSTDATA(shpnt)->debug & debug_datai)
+						printk("last transfer, ");
 #endif
-          done=1;
-        }
-  
+					done = 1;
+				}
+
 #if defined(DEBUG_DATAI)
-        if(HOSTDATA(shpnt)->debug & debug_datai)
-          printk("fifodata=%d, ", fifodata);
+				if (HOSTDATA(shpnt)->debug & debug_datai)
+					printk("fifodata=%d, ", fifodata);
 #endif
 
-        while(fifodata && CURRENT_SC->SCp.this_residual) {
-          data_count=fifodata;
-  
-          /* limit data transfer to size of first sg buffer */
-          if(data_count > CURRENT_SC->SCp.this_residual)
-            data_count = CURRENT_SC->SCp.this_residual;
-  
-          fifodata -= data_count;
+				while (fifodata && CURRENT_SC->SCp.this_residual) {
+					data_count = fifodata;
+
+					/* limit data transfer to size of first sg buffer */
+					if (data_count > CURRENT_SC->SCp.this_residual)
+						data_count = CURRENT_SC->SCp.this_residual;
+
+					fifodata -= data_count;
 
 #if defined(DEBUG_DATAI)
-          if(HOSTDATA(shpnt)->debug & debug_datai)
-            printk("data_count=%d, ", data_count);
+					if (HOSTDATA(shpnt)->debug & debug_datai)
+						printk("data_count=%d, ", data_count);
 #endif
-  
-          if(data_count&1) {
-            /* get a single byte in byte mode */
-            SETBITS(DMACNTRL0, _8BIT);
-            *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
-            CURRENT_SC->SCp.this_residual--;
-          }
- 
-          if(data_count>1) {
-            CLRBITS(DMACNTRL0, _8BIT);
-            data_count >>= 1; /* Number of words */
-            insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
+
+					if (data_count & 1) {
+						/* get a single byte in byte mode */
+						SETBITS(DMACNTRL0, _8BIT);
+						*CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT);
+						CURRENT_SC->SCp.this_residual--;
+					}
+					if (data_count > 1) {
+						CLRBITS(DMACNTRL0, _8BIT);
+						data_count >>= 1;	/* Number of words */
+						insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
 #if defined(DEBUG_DATAI)
-            if(HOSTDATA(shpnt)->debug & debug_datai)
-              /* show what comes with the last transfer */
-              if(done) {
+						if (HOSTDATA(shpnt)->debug & debug_datai)
+							/* show what comes with the last transfer */
+							if (done) {
 #if 0
-                int           i;
-                unsigned char *data;
+								int i;
+								unsigned char *data;
 #endif
-  
-                printk("data on last transfer (%d bytes) ",
-                       2*data_count);
-#if 0
-                printk("data on last transfer (%d bytes: ",
-                       2*data_count);
-                data = (unsigned char *) CURRENT_SC->SCp.ptr;
-                for(i=0; i<2*data_count; i++)
-                  printk("%2x ", *data++);
-                printk("), ");
-#endif
-              }
-#endif
-            CURRENT_SC->SCp.ptr           += 2 * data_count;
-            CURRENT_SC->SCp.this_residual -= 2 * data_count;
-          }
-             
-          /* if this buffer is full and there are more buffers left */
-          if(!CURRENT_SC->SCp.this_residual &&
-             CURRENT_SC->SCp.buffers_residual) {
-            /* advance to next buffer */
-            CURRENT_SC->SCp.buffers_residual--;
-            CURRENT_SC->SCp.buffer++;
-            CURRENT_SC->SCp.ptr           = CURRENT_SC->SCp.buffer->address;
-            CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
-          } 
-        }
- 
-        /*
-         * FIFO should be empty
-         */
-        if(fifodata>0) {
-          printk("aha152x: more data than expected (%d bytes)\n",
-                 GETPORT(FIFOSTAT));
-          SETBITS(DMACNTRL0, _8BIT);
-          printk("aha152x: data (");
-          while(fifodata--)
-            printk("%2x ", GETPORT(DATAPORT));
-            printk(")\n");
-        }
 
+								printk("data on last transfer (%d bytes) ",
+								       2 * data_count);
+#if 0
+								printk("data on last transfer (%d bytes: ",
+								       2 * data_count);
+								data = (unsigned char *) CURRENT_SC->SCp.ptr;
+								for (i = 0; i < 2 * data_count; i++)
+									printk("%2x ", *data++);
+								printk("), ");
+#endif
+							}
+#endif
+						CURRENT_SC->SCp.ptr += 2 * data_count;
+						CURRENT_SC->SCp.this_residual -= 2 * data_count;
+					}
+					/* if this buffer is full and there are more buffers left */
+					if (!CURRENT_SC->SCp.this_residual &&
+					    CURRENT_SC->SCp.buffers_residual) {
+						/* advance to next buffer */
+						CURRENT_SC->SCp.buffers_residual--;
+						CURRENT_SC->SCp.buffer++;
+						CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address;
+						CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
+					}
+				}
+
+				/*
+				 * FIFO should be empty
+				 */
+				if (fifodata > 0) {
+					printk("aha152x: more data than expected (%d bytes)\n",
+					       GETPORT(FIFOSTAT));
+					SETBITS(DMACNTRL0, _8BIT);
+					printk("aha152x: data (");
+					while (fifodata--)
+						printk("%2x ", GETPORT(DATAPORT));
+					printk(")\n");
+				}
 #if defined(DEBUG_DATAI)
-        if(HOSTDATA(shpnt)->debug & debug_datai)
-          if(!fifodata)
-            printk("fifo empty, ");
-          else
-           printk("something left in fifo, ");
+				if (HOSTDATA(shpnt)->debug & debug_datai)
+					if (!fifodata)
+						printk("fifo empty, ");
+					else
+						printk("something left in fifo, ");
 #endif
-      }
+			}
 
 #if defined(DEBUG_DATAI)
-      if((HOSTDATA(shpnt)->debug & debug_datai) &&
-         (CURRENT_SC->SCp.buffers_residual ||
-          CURRENT_SC->SCp.this_residual))
-        printk("left buffers (buffers=%d, bytes=%d), ",
-               CURRENT_SC->SCp.buffers_residual, CURRENT_SC->SCp.this_residual);
-#endif
-      /* transfer can be considered ended, when SCSIEN reads back zero */
-      CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-      while(TESTHI(SXFRCTL0, SCSIEN))
-        barrier();
-      CLRBITS(DMACNTRL0, ENDMA);
+			if ((HOSTDATA(shpnt)->debug & debug_datai) &&
+			    (CURRENT_SC->SCp.buffers_residual ||
+			     CURRENT_SC->SCp.this_residual))
+				printk("left buffers (buffers=%d, bytes=%d), ",
+				       CURRENT_SC->SCp.buffers_residual, CURRENT_SC->SCp.this_residual);
+#endif
+			/* transfer can be considered ended, when SCSIEN reads back zero */
+			CLRBITS(SXFRCTL0, SCSIEN | DMAEN);
+			while (TESTHI(SXFRCTL0, SCSIEN))
+				barrier();
+			CLRBITS(DMACNTRL0, ENDMA);
 
 #if defined(DEBUG_DATAI) || defined(DEBUG_INTR)
-      if(HOSTDATA(shpnt)->debug & (debug_datai|debug_intr))
-        printk("got %d bytes, ", GETSTCNT());
+			if (HOSTDATA(shpnt)->debug & (debug_datai | debug_intr))
+				printk("got %d bytes, ", GETSTCNT());
 #endif
 
-      CURRENT_SC->SCp.have_data_in++;
-    }
-    break;
+			CURRENT_SC->SCp.have_data_in++;
+		}
+		break;
 
-  case P_DATAO:                                           /* DATA OUT phase */
-    {
-      int data_count;
+	case P_DATAO:		/* DATA OUT phase */
+		{
+			int data_count;
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR) || defined(DEBUG_PHASES)
-      if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr|debug_phases))
-        printk("DATA OUT, ");
+			if (HOSTDATA(shpnt)->debug & (debug_datao | debug_intr | debug_phases))
+				printk("DATA OUT, ");
 #endif
 #if defined(DEBUG_DATAO)
-      if(HOSTDATA(shpnt)->debug & debug_datao)
-        printk("got data to send (bytes=%d, buffers=%d), ",
-               CURRENT_SC->SCp.this_residual,
-               CURRENT_SC->SCp.buffers_residual);
-#endif
-
-      if(GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL|SFCNT)) {
-        printk("%d(%d) left in FIFO, ",
-               GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL|SFCNT));
-        aha152x_panic(shpnt, "FIFO should be empty");
-      }
-
-      SETPORT(SXFRCTL0, CH1|CLRSTCNT|CLRCH1);
-      SETPORT(SXFRCTL0, SCSIEN|DMAEN|CH1);
-        
-      SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
-      SETPORT(DMACNTRL0, ENDMA|WRITE_READ);
-
-      SETPORT(SIMODE0, 0);
-      SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
-
-      /* while current buffer is not empty or
-         there are more buffers to transfer */
-      while(TESTLO(SSTAT1, PHASEMIS) &&
-            (CURRENT_SC->SCp.this_residual ||
-            CURRENT_SC->SCp.buffers_residual)) {
+			if (HOSTDATA(shpnt)->debug & debug_datao)
+				printk("got data to send (bytes=%d, buffers=%d), ",
+				       CURRENT_SC->SCp.this_residual,
+				       CURRENT_SC->SCp.buffers_residual);
+#endif
+
+			if (GETPORT(FIFOSTAT) || GETPORT(SSTAT2) & (SFULL | SFCNT)) {
+				printk("%d(%d) left in FIFO, ",
+				       GETPORT(FIFOSTAT), GETPORT(SSTAT2) & (SFULL | SFCNT));
+				aha152x_panic(shpnt, "FIFO should be empty");
+			}
+			SETPORT(SXFRCTL0, CH1 | CLRSTCNT | CLRCH1);
+			SETPORT(SXFRCTL0, SCSIEN | DMAEN | CH1);
+
+			SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO);
+			SETPORT(DMACNTRL0, ENDMA | WRITE_READ);
+
+			SETPORT(SIMODE0, 0);
+			SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE);
+
+			/* while current buffer is not empty or
+			   there are more buffers to transfer */
+			while (TESTLO(SSTAT1, PHASEMIS) &&
+			       (CURRENT_SC->SCp.this_residual ||
+				CURRENT_SC->SCp.buffers_residual)) {
 #if defined(DEBUG_DATAO)
-        if(HOSTDATA(shpnt)->debug & debug_datao)
-          printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
-                 CURRENT_SC->SCp.this_residual,
-                 CURRENT_SC->SCp.buffers_residual);
-#endif
-        /* transfer rest of buffer, but max. 128 byte */
-        data_count =
-          CURRENT_SC->SCp.this_residual > 128 ?
-          128 : CURRENT_SC->SCp.this_residual ;
+				if (HOSTDATA(shpnt)->debug & debug_datao)
+					printk("sending data (left: bytes=%d, buffers=%d), waiting, ",
+					   CURRENT_SC->SCp.this_residual,
+					CURRENT_SC->SCp.buffers_residual);
+#endif
+				/* transfer rest of buffer, but max. 128 byte */
+				data_count =
+				    CURRENT_SC->SCp.this_residual > 128 ?
+				    128 : CURRENT_SC->SCp.this_residual;
 
 #if defined(DEBUG_DATAO)
-        if(HOSTDATA(shpnt)->debug & debug_datao)
-          printk("data_count=%d, ", data_count);
+				if (HOSTDATA(shpnt)->debug & debug_datao)
+					printk("data_count=%d, ", data_count);
 #endif
-  
-        if(data_count&1) {
-          /* put a single byte in byte mode */
-          SETBITS(DMACNTRL0, _8BIT);
-          SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
-          CURRENT_SC->SCp.this_residual--;
-        }
-        if(data_count>1) {
-          CLRBITS(DMACNTRL0, _8BIT);
-          data_count >>= 1; /* number of words */
-          outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
-          CURRENT_SC->SCp.ptr           += 2 * data_count;
-          CURRENT_SC->SCp.this_residual -= 2 * data_count;
-        }
-
-        /* wait for FIFO to get empty */
-        while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT))
-          barrier();
+
+				if (data_count & 1) {
+					/* put a single byte in byte mode */
+					SETBITS(DMACNTRL0, _8BIT);
+					SETPORT(DATAPORT, *CURRENT_SC->SCp.ptr++);
+					CURRENT_SC->SCp.this_residual--;
+				}
+				if (data_count > 1) {
+					CLRBITS(DMACNTRL0, _8BIT);
+					data_count >>= 1;	/* number of words */
+					outsw(DATAPORT, CURRENT_SC->SCp.ptr, data_count);
+					CURRENT_SC->SCp.ptr += 2 * data_count;
+					CURRENT_SC->SCp.this_residual -= 2 * data_count;
+				}
+				/* wait for FIFO to get empty */
+				while (TESTLO(DMASTAT, DFIFOEMP | INTSTAT))
+					barrier();
 
 #if defined(DEBUG_DATAO)
-        if(HOSTDATA(shpnt)->debug & debug_datao)
-          printk("fifo (%d bytes), transfered (%d bytes), ",
-                 GETPORT(FIFOSTAT), GETSTCNT());
-#endif
-
-        /* if this buffer is empty and there are more buffers left */
-        if(TESTLO(SSTAT1, PHASEMIS) &&
-           !CURRENT_SC->SCp.this_residual &&
-           CURRENT_SC->SCp.buffers_residual) {
-          /* advance to next buffer */
-          CURRENT_SC->SCp.buffers_residual--;
-          CURRENT_SC->SCp.buffer++;
-          CURRENT_SC->SCp.ptr           = CURRENT_SC->SCp.buffer->address;
-          CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
-        }
-      }
-
-      if(CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual) {
-        /* target leaves DATA OUT for an other phase (perhaps disconnect) */
-
-        /* data in fifos has to be resend */
-        data_count = GETPORT(SSTAT2) & (SFULL|SFCNT);
-
-        data_count += GETPORT(FIFOSTAT) ;
-        CURRENT_SC->SCp.ptr           -= data_count;
-        CURRENT_SC->SCp.this_residual += data_count;
+				if (HOSTDATA(shpnt)->debug & debug_datao)
+					printk("fifo (%d bytes), transfered (%d bytes), ",
+					  GETPORT(FIFOSTAT), GETSTCNT());
+#endif
+
+				/* if this buffer is empty and there are more buffers left */
+				if (TESTLO(SSTAT1, PHASEMIS) &&
+				    !CURRENT_SC->SCp.this_residual &&
+				    CURRENT_SC->SCp.buffers_residual) {
+					/* advance to next buffer */
+					CURRENT_SC->SCp.buffers_residual--;
+					CURRENT_SC->SCp.buffer++;
+					CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address;
+					CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
+				}
+			}
+
+			if (CURRENT_SC->SCp.this_residual || CURRENT_SC->SCp.buffers_residual) {
+				/* target leaves DATA OUT for an other phase (perhaps disconnect) */
+
+				/* data in fifos has to be resend */
+				data_count = GETPORT(SSTAT2) & (SFULL | SFCNT);
+
+				data_count += GETPORT(FIFOSTAT);
+				CURRENT_SC->SCp.ptr -= data_count;
+				CURRENT_SC->SCp.this_residual += data_count;
 #if defined(DEBUG_DATAO)
-        if(HOSTDATA(shpnt)->debug & debug_datao)
-          printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), "
-                 "transfer incomplete, resetting fifo, ",
-                 CURRENT_SC->SCp.this_residual,
-                 CURRENT_SC->SCp.buffers_residual,
-                 data_count);
-#endif
-        SETPORT(DMACNTRL0, WRITE_READ|RSTFIFO);
-        CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-        CLRBITS(DMACNTRL0, ENDMA);
-      } else {
+				if (HOSTDATA(shpnt)->debug & debug_datao)
+					printk("left data (bytes=%d, buffers=%d), fifos (bytes=%d), "
+					       "transfer incomplete, resetting fifo, ",
+					   CURRENT_SC->SCp.this_residual,
+					CURRENT_SC->SCp.buffers_residual,
+					       data_count);
+#endif
+				SETPORT(DMACNTRL0, WRITE_READ | RSTFIFO);
+				CLRBITS(SXFRCTL0, SCSIEN | DMAEN);
+				CLRBITS(DMACNTRL0, ENDMA);
+			} else {
 #if defined(DEBUG_DATAO)
-        if(HOSTDATA(shpnt)->debug & debug_datao)
-          printk("waiting for SCSI fifo to get empty, ");
+				if (HOSTDATA(shpnt)->debug & debug_datao)
+					printk("waiting for SCSI fifo to get empty, ");
 #endif
-        /* wait for SCSI fifo to get empty */
-        while(TESTLO(SSTAT2, SEMPTY))
-          barrier();
+				/* wait for SCSI fifo to get empty */
+				while (TESTLO(SSTAT2, SEMPTY))
+					barrier();
 #if defined(DEBUG_DATAO)
-        if(HOSTDATA(shpnt)->debug & debug_datao)
-          printk("ok, left data (bytes=%d, buffers=%d) ",
-                 CURRENT_SC->SCp.this_residual,
-                 CURRENT_SC->SCp.buffers_residual);
-#endif
-        CLRBITS(SXFRCTL0, SCSIEN|DMAEN);
-
-        /* transfer can be considered ended, when SCSIEN reads back zero */
-        while(TESTHI(SXFRCTL0, SCSIEN))
-          barrier();
+				if (HOSTDATA(shpnt)->debug & debug_datao)
+					printk("ok, left data (bytes=%d, buffers=%d) ",
+					   CURRENT_SC->SCp.this_residual,
+					CURRENT_SC->SCp.buffers_residual);
+#endif
+				CLRBITS(SXFRCTL0, SCSIEN | DMAEN);
+
+				/* transfer can be considered ended, when SCSIEN reads back zero */
+				while (TESTHI(SXFRCTL0, SCSIEN))
+					barrier();
 
-        CLRBITS(DMACNTRL0, ENDMA);
-      }
+				CLRBITS(DMACNTRL0, ENDMA);
+			}
 
 #if defined(DEBUG_DATAO) || defined(DEBUG_INTR)
-      if(HOSTDATA(shpnt)->debug & (debug_datao|debug_intr))
-        printk("sent %d data bytes, ", GETSTCNT());
+			if (HOSTDATA(shpnt)->debug & (debug_datao | debug_intr))
+				printk("sent %d data bytes, ", GETSTCNT());
 #endif
-    }
-    break;
+		}
+		break;
 
-  case P_BUSFREE:                                                /* BUSFREE */
+	case P_BUSFREE:	/* BUSFREE */
 #if defined(DEBUG_RACE)
-    leave_driver("(BUSFREE) intr");
+		leave_driver("(BUSFREE) intr");
 #endif
 #if defined(DEBUG_PHASES)
-    if(HOSTDATA(shpnt)->debug & debug_phases)
-      printk("unexpected BUS FREE, ");
+		if (HOSTDATA(shpnt)->debug & debug_phases)
+			printk("unexpected BUS FREE, ");
 #endif
-    CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
+		CURRENT_SC->SCp.phase &= ~(P_MASK << 16);
 
-    aha152x_done(shpnt, DID_ERROR << 16);         /* Don't know any better */
-    return;
-    break;
+		aha152x_done(shpnt, DID_ERROR << 16);	/* Don't know any better */
+		return;
+		break;
 
-  case P_PARITY:                              /* parity error in DATA phase */
+	case P_PARITY:		/* parity error in DATA phase */
 #if defined(DEBUG_RACE)
-    leave_driver("(DID_PARITY) intr");
+		leave_driver("(DID_PARITY) intr");
 #endif
-    printk("PARITY error in DATA phase, ");
+		printk("PARITY error in DATA phase, ");
 
-    CURRENT_SC->SCp.phase &= ~(P_MASK<<16);
+		CURRENT_SC->SCp.phase &= ~(P_MASK << 16);
 
-    SETBITS(DMACNTRL0, INTEN);
-    aha152x_done(shpnt, DID_PARITY << 16);
-    return;
-    break;
+		SETBITS(DMACNTRL0, INTEN);
+		aha152x_done(shpnt, DID_PARITY << 16);
+		return;
+		break;
 
-  default:
-    printk("aha152x: unexpected phase\n");
-    break;
-  }
+	default:
+		printk("aha152x: unexpected phase\n");
+		break;
+	}
 
-  if(done) {
+	if (done) {
 #if defined(DEBUG_INTR)
-    if(HOSTDATA(shpnt)->debug & debug_intr)
-      printk("command done.\n");
+		if (HOSTDATA(shpnt)->debug & debug_intr)
+			printk("command done.\n");
 #endif
 #if defined(DEBUG_RACE)
-    leave_driver("(done) intr");
+		leave_driver("(done) intr");
 #endif
 
-    SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
-    SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
-    SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
-    
-    SETBITS(DMACNTRL0, INTEN);
-      
-    aha152x_done(shpnt,
-                 (CURRENT_SC->SCp.Status  & 0xff)
-                 | ((CURRENT_SC->SCp.Message & 0xff) << 8)
-                 | (DID_OK << 16));
+		SETPORT(SIMODE0, DISCONNECTED_SC ? ENSELDI : 0);
+		SETPORT(SIMODE1, ISSUE_SC ? ENBUSFREE : 0);
+		SETPORT(SCSISEQ, DISCONNECTED_SC ? ENRESELI : 0);
+
+		SETBITS(DMACNTRL0, INTEN);
+
+		aha152x_done(shpnt,
+			     (CURRENT_SC->SCp.Status & 0xff)
+			     | ((CURRENT_SC->SCp.Message & 0xff) << 8)
+			     | (DID_OK << 16));
 
 #if defined(DEBUG_RACE)
-    printk("done returned (DID_OK: Status=%x; Message=%x).\n",
-           CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message);
+		printk("done returned (DID_OK: Status=%x; Message=%x).\n",
+		       CURRENT_SC->SCp.Status, CURRENT_SC->SCp.Message);
 #endif
-    return;
-  }
-
-  if(CURRENT_SC)
-    CURRENT_SC->SCp.phase |= 1<<16;
+		return;
+	}
+	if (CURRENT_SC)
+		CURRENT_SC->SCp.phase |= 1 << 16;
 
-  SETPORT(SIMODE0, 0);
-  SETPORT(SIMODE1, ENPHASEMIS|ENBUSFREE);
+	SETPORT(SIMODE0, 0);
+	SETPORT(SIMODE1, ENPHASEMIS | ENBUSFREE);
 #if defined(DEBUG_INTR)
-  if(HOSTDATA(shpnt)->debug & debug_intr)
-    disp_enintr(shpnt);
+	if (HOSTDATA(shpnt)->debug & debug_intr)
+		disp_enintr(shpnt);
 #endif
 #if defined(DEBUG_RACE)
-  leave_driver("(PHASEEND) intr");
+	leave_driver("(PHASEEND) intr");
 #endif
 
-  SETBITS(DMACNTRL0, INTEN);
-  return;
+	SETBITS(DMACNTRL0, INTEN);
+	return;
 }
 
 /* 
@@ -2637,9 +2639,9 @@
  */
 static void aha152x_panic(struct Scsi_Host *shpnt, char *msg)
 {
-  printk("\naha152x: %s\n", msg);
-  show_queues(shpnt);
-  panic("aha152x panic");
+	printk("\naha152x: %s\n", msg);
+	show_queues(shpnt);
+	panic("aha152x panic");
 }
 
 /*
@@ -2648,166 +2650,231 @@
 static void disp_ports(struct Scsi_Host *shpnt)
 {
 #ifdef DEBUG_AHA152X
-  int s;
+	int s;
 
 #ifdef SKIP_PORTS
-  if(HOSTDATA(shpnt)->debug & debug_skipports)
-        return;
+	if (HOSTDATA(shpnt)->debug & debug_skipports)
+		return;
 #endif
 
-  printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting");
+	printk("\n%s: ", CURRENT_SC ? "on bus" : "waiting");
 
-  s=GETPORT(SCSISEQ);
-  printk("SCSISEQ (");
-  if(s & TEMODEO)     printk("TARGET MODE ");
-  if(s & ENSELO)      printk("SELO ");
-  if(s & ENSELI)      printk("SELI ");
-  if(s & ENRESELI)    printk("RESELI ");
-  if(s & ENAUTOATNO)  printk("AUTOATNO ");
-  if(s & ENAUTOATNI)  printk("AUTOATNI ");
-  if(s & ENAUTOATNP)  printk("AUTOATNP ");
-  if(s & SCSIRSTO)    printk("SCSIRSTO ");
-  printk(");");
-
-  printk(" SCSISIG (");
-  s=GETPORT(SCSISIG);
-  switch(s & P_MASK) {
-  case P_DATAO:
-    printk("DATA OUT");
-    break;
-  case P_DATAI:
-    printk("DATA IN");
-    break;
-  case P_CMD:
-    printk("COMMAND"); 
-    break;
-  case P_STATUS:
-    printk("STATUS"); 
-    break;
-  case P_MSGO:
-    printk("MESSAGE OUT");
-    break;
-  case P_MSGI:
-    printk("MESSAGE IN");
-    break;
-  default:
-    printk("*illegal*");
-    break;
-  }
-  
-  printk("); ");
-
-  printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
-
-  printk("SSTAT (");
-  s=GETPORT(SSTAT0);
-  if(s & TARGET)   printk("TARGET ");
-  if(s & SELDO)    printk("SELDO ");
-  if(s & SELDI)    printk("SELDI ");
-  if(s & SELINGO)  printk("SELINGO ");
-  if(s & SWRAP)    printk("SWRAP ");
-  if(s & SDONE)    printk("SDONE ");
-  if(s & SPIORDY)  printk("SPIORDY ");
-  if(s & DMADONE)  printk("DMADONE ");
-
-  s=GETPORT(SSTAT1);
-  if(s & SELTO)     printk("SELTO ");
-  if(s & ATNTARG)   printk("ATNTARG ");
-  if(s & SCSIRSTI)  printk("SCSIRSTI ");
-  if(s & PHASEMIS)  printk("PHASEMIS ");
-  if(s & BUSFREE)   printk("BUSFREE ");
-  if(s & SCSIPERR)  printk("SCSIPERR ");
-  if(s & PHASECHG)  printk("PHASECHG ");
-  if(s & REQINIT)   printk("REQINIT ");
-  printk("); ");
-
-
-  printk("SSTAT (");
-
-  s=GETPORT(SSTAT0) & GETPORT(SIMODE0);
-
-  if(s & TARGET)    printk("TARGET ");
-  if(s & SELDO)     printk("SELDO ");
-  if(s & SELDI)     printk("SELDI ");
-  if(s & SELINGO)   printk("SELINGO ");
-  if(s & SWRAP)     printk("SWRAP ");
-  if(s & SDONE)     printk("SDONE ");
-  if(s & SPIORDY)   printk("SPIORDY ");
-  if(s & DMADONE)   printk("DMADONE ");
-
-  s=GETPORT(SSTAT1) & GETPORT(SIMODE1);
-
-  if(s & SELTO)     printk("SELTO ");
-  if(s & ATNTARG)   printk("ATNTARG ");
-  if(s & SCSIRSTI)  printk("SCSIRSTI ");
-  if(s & PHASEMIS)  printk("PHASEMIS ");
-  if(s & BUSFREE)   printk("BUSFREE ");
-  if(s & SCSIPERR)  printk("SCSIPERR ");
-  if(s & PHASECHG)  printk("PHASECHG ");
-  if(s & REQINIT)   printk("REQINIT ");
-  printk("); ");
-
-  printk("SXFRCTL0 (");
-
-  s=GETPORT(SXFRCTL0);
-  if(s & SCSIEN)    printk("SCSIEN ");
-  if(s & DMAEN)     printk("DMAEN ");
-  if(s & CH1)       printk("CH1 ");
-  if(s & CLRSTCNT)  printk("CLRSTCNT ");
-  if(s & SPIOEN)    printk("SPIOEN ");
-  if(s & CLRCH1)    printk("CLRCH1 ");
-  printk("); ");
-
-  printk("SIGNAL (");
-
-  s=GETPORT(SCSISIG);
-  if(s & ATNI)  printk("ATNI ");
-  if(s & SELI)  printk("SELI ");
-  if(s & BSYI)  printk("BSYI ");
-  if(s & REQI)  printk("REQI ");
-  if(s & ACKI)  printk("ACKI ");
-  printk("); ");
-
-  printk("SELID (%02x), ", GETPORT(SELID));
-
-  printk("SSTAT2 (");
-
-  s=GETPORT(SSTAT2);
-  if(s & SOFFSET)  printk("SOFFSET ");
-  if(s & SEMPTY)   printk("SEMPTY ");
-  if(s & SFULL)    printk("SFULL ");
-  printk("); SFCNT (%d); ", s & (SFULL|SFCNT));
-
-  s=GETPORT(SSTAT3);
-  printk("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f);
-  
-  printk("SSTAT4 (");
-  s=GETPORT(SSTAT4);
-  if(s & SYNCERR)   printk("SYNCERR ");
-  if(s & FWERR)     printk("FWERR ");
-  if(s & FRERR)     printk("FRERR ");
-  printk("); ");
-
-  printk("DMACNTRL0 (");
-  s=GETPORT(DMACNTRL0);
-  printk("%s ", s & _8BIT      ? "8BIT"  : "16BIT");
-  printk("%s ", s & DMA        ? "DMA"   : "PIO"  );
-  printk("%s ", s & WRITE_READ ? "WRITE" : "READ" );
-  if(s & ENDMA)    printk("ENDMA ");
-  if(s & INTEN)    printk("INTEN ");
-  if(s & RSTFIFO)  printk("RSTFIFO ");
-  if(s & SWINT)    printk("SWINT ");
-  printk("); ");
-
-  printk("DMASTAT (");
-  s=GETPORT(DMASTAT);
-  if(s & ATDONE)     printk("ATDONE ");
-  if(s & WORDRDY)    printk("WORDRDY ");
-  if(s & DFIFOFULL)  printk("DFIFOFULL ");
-  if(s & DFIFOEMP)   printk("DFIFOEMP ");
-  printk(")");
+	s = GETPORT(SCSISEQ);
+	printk("SCSISEQ (");
+	if (s & TEMODEO)
+		printk("TARGET MODE ");
+	if (s & ENSELO)
+		printk("SELO ");
+	if (s & ENSELI)
+		printk("SELI ");
+	if (s & ENRESELI)
+		printk("RESELI ");
+	if (s & ENAUTOATNO)
+		printk("AUTOATNO ");
+	if (s & ENAUTOATNI)
+		printk("AUTOATNI ");
+	if (s & ENAUTOATNP)
+		printk("AUTOATNP ");
+	if (s & SCSIRSTO)
+		printk("SCSIRSTO ");
+	printk(");");
+
+	printk(" SCSISIG (");
+	s = GETPORT(SCSISIG);
+	switch (s & P_MASK) {
+	case P_DATAO:
+		printk("DATA OUT");
+		break;
+	case P_DATAI:
+		printk("DATA IN");
+		break;
+	case P_CMD:
+		printk("COMMAND");
+		break;
+	case P_STATUS:
+		printk("STATUS");
+		break;
+	case P_MSGO:
+		printk("MESSAGE OUT");
+		break;
+	case P_MSGI:
+		printk("MESSAGE IN");
+		break;
+	default:
+		printk("*illegal*");
+		break;
+	}
+
+	printk("); ");
+
+	printk("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
 
-  printk("\n");
+	printk("SSTAT (");
+	s = GETPORT(SSTAT0);
+	if (s & TARGET)
+		printk("TARGET ");
+	if (s & SELDO)
+		printk("SELDO ");
+	if (s & SELDI)
+		printk("SELDI ");
+	if (s & SELINGO)
+		printk("SELINGO ");
+	if (s & SWRAP)
+		printk("SWRAP ");
+	if (s & SDONE)
+		printk("SDONE ");
+	if (s & SPIORDY)
+		printk("SPIORDY ");
+	if (s & DMADONE)
+		printk("DMADONE ");
+
+	s = GETPORT(SSTAT1);
+	if (s & SELTO)
+		printk("SELTO ");
+	if (s & ATNTARG)
+		printk("ATNTARG ");
+	if (s & SCSIRSTI)
+		printk("SCSIRSTI ");
+	if (s & PHASEMIS)
+		printk("PHASEMIS ");
+	if (s & BUSFREE)
+		printk("BUSFREE ");
+	if (s & SCSIPERR)
+		printk("SCSIPERR ");
+	if (s & PHASECHG)
+		printk("PHASECHG ");
+	if (s & REQINIT)
+		printk("REQINIT ");
+	printk("); ");
+
+
+	printk("SSTAT (");
+
+	s = GETPORT(SSTAT0) & GETPORT(SIMODE0);
+
+	if (s & TARGET)
+		printk("TARGET ");
+	if (s & SELDO)
+		printk("SELDO ");
+	if (s & SELDI)
+		printk("SELDI ");
+	if (s & SELINGO)
+		printk("SELINGO ");
+	if (s & SWRAP)
+		printk("SWRAP ");
+	if (s & SDONE)
+		printk("SDONE ");
+	if (s & SPIORDY)
+		printk("SPIORDY ");
+	if (s & DMADONE)
+		printk("DMADONE ");
+
+	s = GETPORT(SSTAT1) & GETPORT(SIMODE1);
+
+	if (s & SELTO)
+		printk("SELTO ");
+	if (s & ATNTARG)
+		printk("ATNTARG ");
+	if (s & SCSIRSTI)
+		printk("SCSIRSTI ");
+	if (s & PHASEMIS)
+		printk("PHASEMIS ");
+	if (s & BUSFREE)
+		printk("BUSFREE ");
+	if (s & SCSIPERR)
+		printk("SCSIPERR ");
+	if (s & PHASECHG)
+		printk("PHASECHG ");
+	if (s & REQINIT)
+		printk("REQINIT ");
+	printk("); ");
+
+	printk("SXFRCTL0 (");
+
+	s = GETPORT(SXFRCTL0);
+	if (s & SCSIEN)
+		printk("SCSIEN ");
+	if (s & DMAEN)
+		printk("DMAEN ");
+	if (s & CH1)
+		printk("CH1 ");
+	if (s & CLRSTCNT)
+		printk("CLRSTCNT ");
+	if (s & SPIOEN)
+		printk("SPIOEN ");
+	if (s & CLRCH1)
+		printk("CLRCH1 ");
+	printk("); ");
+
+	printk("SIGNAL (");
+
+	s = GETPORT(SCSISIG);
+	if (s & ATNI)
+		printk("ATNI ");
+	if (s & SELI)
+		printk("SELI ");
+	if (s & BSYI)
+		printk("BSYI ");
+	if (s & REQI)
+		printk("REQI ");
+	if (s & ACKI)
+		printk("ACKI ");
+	printk("); ");
+
+	printk("SELID (%02x), ", GETPORT(SELID));
+
+	printk("SSTAT2 (");
+
+	s = GETPORT(SSTAT2);
+	if (s & SOFFSET)
+		printk("SOFFSET ");
+	if (s & SEMPTY)
+		printk("SEMPTY ");
+	if (s & SFULL)
+		printk("SFULL ");
+	printk("); SFCNT (%d); ", s & (SFULL | SFCNT));
+
+	s = GETPORT(SSTAT3);
+	printk("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f);
+
+	printk("SSTAT4 (");
+	s = GETPORT(SSTAT4);
+	if (s & SYNCERR)
+		printk("SYNCERR ");
+	if (s & FWERR)
+		printk("FWERR ");
+	if (s & FRERR)
+		printk("FRERR ");
+	printk("); ");
+
+	printk("DMACNTRL0 (");
+	s = GETPORT(DMACNTRL0);
+	printk("%s ", s & _8BIT ? "8BIT" : "16BIT");
+	printk("%s ", s & DMA ? "DMA" : "PIO");
+	printk("%s ", s & WRITE_READ ? "WRITE" : "READ");
+	if (s & ENDMA)
+		printk("ENDMA ");
+	if (s & INTEN)
+		printk("INTEN ");
+	if (s & RSTFIFO)
+		printk("RSTFIFO ");
+	if (s & SWINT)
+		printk("SWINT ");
+	printk("); ");
+
+	printk("DMASTAT (");
+	s = GETPORT(DMASTAT);
+	if (s & ATDONE)
+		printk("ATDONE ");
+	if (s & WORDRDY)
+		printk("WORDRDY ");
+	if (s & DFIFOFULL)
+		printk("DFIFOFULL ");
+	if (s & DFIFOEMP)
+		printk("DFIFOEMP ");
+	printk(")");
+
+	printk("\n");
 #endif
 }
 
@@ -2816,518 +2883,618 @@
  */
 static void disp_enintr(struct Scsi_Host *shpnt)
 {
-  int s;
+	int s;
+
+	printk("enabled interrupts (");
 
-  printk("enabled interrupts (");
-  
-  s=GETPORT(SIMODE0);
-  if(s & ENSELDO)    printk("ENSELDO ");
-  if(s & ENSELDI)    printk("ENSELDI ");
-  if(s & ENSELINGO)  printk("ENSELINGO ");
-  if(s & ENSWRAP)    printk("ENSWRAP ");
-  if(s & ENSDONE)    printk("ENSDONE ");
-  if(s & ENSPIORDY)  printk("ENSPIORDY ");
-  if(s & ENDMADONE)  printk("ENDMADONE ");
-
-  s=GETPORT(SIMODE1);
-  if(s & ENSELTIMO)    printk("ENSELTIMO ");
-  if(s & ENATNTARG)    printk("ENATNTARG ");
-  if(s & ENPHASEMIS)   printk("ENPHASEMIS ");
-  if(s & ENBUSFREE)    printk("ENBUSFREE ");
-  if(s & ENSCSIPERR)   printk("ENSCSIPERR ");
-  if(s & ENPHASECHG)   printk("ENPHASECHG ");
-  if(s & ENREQINIT)    printk("ENREQINIT ");
-  printk(")\n");
+	s = GETPORT(SIMODE0);
+	if (s & ENSELDO)
+		printk("ENSELDO ");
+	if (s & ENSELDI)
+		printk("ENSELDI ");
+	if (s & ENSELINGO)
+		printk("ENSELINGO ");
+	if (s & ENSWRAP)
+		printk("ENSWRAP ");
+	if (s & ENSDONE)
+		printk("ENSDONE ");
+	if (s & ENSPIORDY)
+		printk("ENSPIORDY ");
+	if (s & ENDMADONE)
+		printk("ENDMADONE ");
+
+	s = GETPORT(SIMODE1);
+	if (s & ENSELTIMO)
+		printk("ENSELTIMO ");
+	if (s & ENATNTARG)
+		printk("ENATNTARG ");
+	if (s & ENPHASEMIS)
+		printk("ENPHASEMIS ");
+	if (s & ENBUSFREE)
+		printk("ENBUSFREE ");
+	if (s & ENSCSIPERR)
+		printk("ENSCSIPERR ");
+	if (s & ENPHASECHG)
+		printk("ENPHASECHG ");
+	if (s & ENREQINIT)
+		printk("ENREQINIT ");
+	printk(")\n");
 }
 
 #if defined(DEBUG_RACE)
 
 static const char *should_leave;
-static int in_driver=0;
+static int in_driver = 0;
 
 /*
  * Only one routine can be in the driver at once.
  */
 static void enter_driver(const char *func)
 {
-  unsigned long flags;
+	unsigned long flags;
 
-  save_flags(flags);
-  cli();
-  printk("aha152x: entering %s() (%x)\n", func, jiffies);
-  if(in_driver) {
-    printk("%s should leave first.\n", should_leave);
-    panic("aha152x: already in driver\n");
-  }
-
-  in_driver++;
-  should_leave=func;
-  restore_flags(flags);
+	save_flags(flags);
+	cli();
+	printk("aha152x: entering %s() (%x)\n", func, jiffies);
+	if (in_driver) {
+		printk("%s should leave first.\n", should_leave);
+		panic("aha152x: already in driver\n");
+	}
+	in_driver++;
+	should_leave = func;
+	restore_flags(flags);
 }
 
 static void leave_driver(const char *func)
 {
-  unsigned long flags;
+	unsigned long flags;
 
-  save_flags(flags);
-  cli();
-  printk("\naha152x: leaving %s() (%x)\n", func, jiffies);
-  if(!in_driver) {
-    printk("aha152x: %s already left.\n", should_leave);
-    panic("aha152x: %s already left driver.\n");
-  }
-
-  in_driver--;
-  should_leave=func;
-  restore_flags(flags);
+	save_flags(flags);
+	cli();
+	printk("\naha152x: leaving %s() (%x)\n", func, jiffies);
+	if (!in_driver) {
+		printk("aha152x: %s already left.\n", should_leave);
+		panic("aha152x: %s already left driver.\n");
+	}
+	in_driver--;
+	should_leave = func;
+	restore_flags(flags);
 }
 #endif
 
 /*
  * Show the command data of a command
  */
-static void show_command(Scsi_Cmnd *ptr)
+static void show_command(Scsi_Cmnd * ptr)
 {
-  printk("0x%08x: target=%d; lun=%d; cmnd=(",
-         (unsigned int) ptr, ptr->target, ptr->lun);
-  
-  print_command(ptr->cmnd);
-
-  printk("); residual=%d; buffers=%d; phase |",
-         ptr->SCp.this_residual, ptr->SCp.buffers_residual);
-
-  if(ptr->SCp.phase & not_issued  )  printk("not issued|");
-  if(ptr->SCp.phase & in_selection)  printk("in selection|");
-  if(ptr->SCp.phase & disconnected)  printk("disconnected|");
-  if(ptr->SCp.phase & aborted     )  printk("aborted|");
-  if(ptr->SCp.phase & sent_ident  )  printk("send_ident|");
-  if(ptr->SCp.phase & in_other) { 
-    printk("; in other(");
-    switch((ptr->SCp.phase >> 16) & P_MASK) {
-    case P_DATAO:
-      printk("DATA OUT");
-      break;
-    case P_DATAI:
-      printk("DATA IN");
-      break;
-    case P_CMD:
-      printk("COMMAND");
-      break;
-    case P_STATUS:
-      printk("STATUS");
-      break;
-    case P_MSGO:
-      printk("MESSAGE OUT");
-      break;
-    case P_MSGI:
-      printk("MESSAGE IN");
-      break;
-    default: 
-      printk("*illegal*");
-      break;
-    }
-    printk(")");
-    if(ptr->SCp.phase & (1<<16))
-      printk("; phaseend");
-  }
-  printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
+	printk("0x%08x: target=%d; lun=%d; cmnd=(",
+	       (unsigned int) ptr, ptr->target, ptr->lun);
+
+	print_command(ptr->cmnd);
+
+	printk("); residual=%d; buffers=%d; phase |",
+	       ptr->SCp.this_residual, ptr->SCp.buffers_residual);
+
+	if (ptr->SCp.phase & not_issued)
+		printk("not issued|");
+	if (ptr->SCp.phase & in_selection)
+		printk("in selection|");
+	if (ptr->SCp.phase & disconnected)
+		printk("disconnected|");
+	if (ptr->SCp.phase & aborted)
+		printk("aborted|");
+	if (ptr->SCp.phase & sent_ident)
+		printk("send_ident|");
+	if (ptr->SCp.phase & in_other) {
+		printk("; in other(");
+		switch ((ptr->SCp.phase >> 16) & P_MASK) {
+		case P_DATAO:
+			printk("DATA OUT");
+			break;
+		case P_DATAI:
+			printk("DATA IN");
+			break;
+		case P_CMD:
+			printk("COMMAND");
+			break;
+		case P_STATUS:
+			printk("STATUS");
+			break;
+		case P_MSGO:
+			printk("MESSAGE OUT");
+			break;
+		case P_MSGI:
+			printk("MESSAGE IN");
+			break;
+		default:
+			printk("*illegal*");
+			break;
+		}
+		printk(")");
+		if (ptr->SCp.phase & (1 << 16))
+			printk("; phaseend");
+	}
+	printk("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
 }
- 
+
 /*
  * Dump the queued data
  */
 static void show_queues(struct Scsi_Host *shpnt)
 {
-  unsigned long flags;
-  Scsi_Cmnd *ptr;
+	unsigned long flags;
+	Scsi_Cmnd *ptr;
 
-  save_flags(flags);
-  cli();
-  printk("QUEUE STATUS:\nissue_SC:\n");
-  for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-    show_command(ptr);
-
-  printk("current_SC:\n");
-  if(CURRENT_SC)
-    show_command(CURRENT_SC);
-  else
-    printk("none\n");
-
-  printk("disconnected_SC:\n");
-  for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-    show_command(ptr);
-
-  disp_ports(shpnt);
-  disp_enintr(shpnt);
-  restore_flags(flags);
+	save_flags(flags);
+	cli();
+	printk("QUEUE STATUS:\nissue_SC:\n");
+	for (ptr = ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+		show_command(ptr);
+
+	printk("current_SC:\n");
+	if (CURRENT_SC)
+		show_command(CURRENT_SC);
+	else
+		printk("none\n");
+
+	printk("disconnected_SC:\n");
+	for (ptr = DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+		show_command(ptr);
+
+	disp_ports(shpnt);
+	disp_enintr(shpnt);
+	restore_flags(flags);
 }
 
 int aha152x_set_info(char *buffer, int length, struct Scsi_Host *shpnt)
 {
-  return(-ENOSYS);  /* Currently this is a no-op */
+	return (-ENOSYS);	/* Currently this is a no-op */
 }
 
 #undef SPRINTF
 #define SPRINTF(args...) pos += sprintf(pos, ## args)
 
-static int get_command(char *pos, Scsi_Cmnd *ptr)
+static int get_command(char *pos, Scsi_Cmnd * ptr)
 {
-  char *start = pos;
-  int i;
-  
-  SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ",
-          (unsigned int) ptr, ptr->target, ptr->lun);
-  
-  for(i=0; i<COMMAND_SIZE(ptr->cmnd[0]); i++)
-    SPRINTF("0x%02x ", ptr->cmnd[i]);
-  
-  SPRINTF("); residual=%d; buffers=%d; phase |",
-          ptr->SCp.this_residual, ptr->SCp.buffers_residual);
-  
-  if(ptr->SCp.phase & not_issued  )  SPRINTF("not issued|");
-  if(ptr->SCp.phase & in_selection)  SPRINTF("in selection|");
-  if(ptr->SCp.phase & disconnected)  SPRINTF("disconnected|");
-  if(ptr->SCp.phase & aborted     )  SPRINTF("aborted|");
-  if(ptr->SCp.phase & sent_ident  )  SPRINTF("send_ident|");
-  if(ptr->SCp.phase & in_other) { 
-    SPRINTF("; in other(");
-    switch((ptr->SCp.phase >> 16) & P_MASK) {
-    case P_DATAO:
-      SPRINTF("DATA OUT");
-      break;
-    case P_DATAI:
-      SPRINTF("DATA IN");
-      break;
-    case P_CMD:
-      SPRINTF("COMMAND");
-      break;
-    case P_STATUS:
-      SPRINTF("STATUS");
-      break;
-    case P_MSGO:
-      SPRINTF("MESSAGE OUT");
-      break;
-    case P_MSGI:
-      SPRINTF("MESSAGE IN");
-      break;
-    default: 
-      SPRINTF("*illegal*");
-      break;
-    }
-    SPRINTF(")");
-    if(ptr->SCp.phase & (1<<16))
-      SPRINTF("; phaseend");
-  }
-  SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
-  
-  return(pos-start);
+	char *start = pos;
+	int i;
+
+	SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ",
+		(unsigned int) ptr, ptr->target, ptr->lun);
+
+	for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++)
+		SPRINTF("0x%02x ", ptr->cmnd[i]);
+
+	SPRINTF("); residual=%d; buffers=%d; phase |",
+		ptr->SCp.this_residual, ptr->SCp.buffers_residual);
+
+	if (ptr->SCp.phase & not_issued)
+		SPRINTF("not issued|");
+	if (ptr->SCp.phase & in_selection)
+		SPRINTF("in selection|");
+	if (ptr->SCp.phase & disconnected)
+		SPRINTF("disconnected|");
+	if (ptr->SCp.phase & aborted)
+		SPRINTF("aborted|");
+	if (ptr->SCp.phase & sent_ident)
+		SPRINTF("send_ident|");
+	if (ptr->SCp.phase & in_other) {
+		SPRINTF("; in other(");
+		switch ((ptr->SCp.phase >> 16) & P_MASK) {
+		case P_DATAO:
+			SPRINTF("DATA OUT");
+			break;
+		case P_DATAI:
+			SPRINTF("DATA IN");
+			break;
+		case P_CMD:
+			SPRINTF("COMMAND");
+			break;
+		case P_STATUS:
+			SPRINTF("STATUS");
+			break;
+		case P_MSGO:
+			SPRINTF("MESSAGE OUT");
+			break;
+		case P_MSGI:
+			SPRINTF("MESSAGE IN");
+			break;
+		default:
+			SPRINTF("*illegal*");
+			break;
+		}
+		SPRINTF(")");
+		if (ptr->SCp.phase & (1 << 16))
+			SPRINTF("; phaseend");
+	}
+	SPRINTF("; next=0x%08x\n", (unsigned int) ptr->host_scribble);
+
+	return (pos - start);
 }
 
 static int get_ports(struct Scsi_Host *shpnt, char *pos)
 {
-  char *start = pos;
-  int s;
+	char *start = pos;
+	int s;
 
 #ifdef SKIP_PORTS
-  if(HOSTDATA(shpnt)->debug & debug_skipports)
-        return;
+	if (HOSTDATA(shpnt)->debug & debug_skipports)
+		return;
 #endif
 
-  SPRINTF("\n%s: ", CURRENT_SC ? "on bus" : "waiting");
+	SPRINTF("\n%s: ", CURRENT_SC ? "on bus" : "waiting");
+
+	s = GETPORT(SCSISEQ);
+	SPRINTF("SCSISEQ (");
+	if (s & TEMODEO)
+		SPRINTF("TARGET MODE ");
+	if (s & ENSELO)
+		SPRINTF("SELO ");
+	if (s & ENSELI)
+		SPRINTF("SELI ");
+	if (s & ENRESELI)
+		SPRINTF("RESELI ");
+	if (s & ENAUTOATNO)
+		SPRINTF("AUTOATNO ");
+	if (s & ENAUTOATNI)
+		SPRINTF("AUTOATNI ");
+	if (s & ENAUTOATNP)
+		SPRINTF("AUTOATNP ");
+	if (s & SCSIRSTO)
+		SPRINTF("SCSIRSTO ");
+	SPRINTF(");");
+
+	SPRINTF(" SCSISIG (");
+	s = GETPORT(SCSISIG);
+	switch (s & P_MASK) {
+	case P_DATAO:
+		SPRINTF("DATA OUT");
+		break;
+	case P_DATAI:
+		SPRINTF("DATA IN");
+		break;
+	case P_CMD:
+		SPRINTF("COMMAND");
+		break;
+	case P_STATUS:
+		SPRINTF("STATUS");
+		break;
+	case P_MSGO:
+		SPRINTF("MESSAGE OUT");
+		break;
+	case P_MSGI:
+		SPRINTF("MESSAGE IN");
+		break;
+	default:
+		SPRINTF("*illegal*");
+		break;
+	}
+
+	SPRINTF("); ");
+
+	SPRINTF("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
 
-  s=GETPORT(SCSISEQ);
-  SPRINTF("SCSISEQ (");
-  if(s & TEMODEO)     SPRINTF("TARGET MODE ");
-  if(s & ENSELO)      SPRINTF("SELO ");
-  if(s & ENSELI)      SPRINTF("SELI ");
-  if(s & ENRESELI)    SPRINTF("RESELI ");
-  if(s & ENAUTOATNO)  SPRINTF("AUTOATNO ");
-  if(s & ENAUTOATNI)  SPRINTF("AUTOATNI ");
-  if(s & ENAUTOATNP)  SPRINTF("AUTOATNP ");
-  if(s & SCSIRSTO)    SPRINTF("SCSIRSTO ");
-  SPRINTF(");");
-
-  SPRINTF(" SCSISIG (");
-  s=GETPORT(SCSISIG);
-  switch(s & P_MASK) {
-  case P_DATAO:
-    SPRINTF("DATA OUT");
-    break;
-  case P_DATAI:
-    SPRINTF("DATA IN");
-    break;
-  case P_CMD:
-    SPRINTF("COMMAND"); 
-    break;
-  case P_STATUS:
-    SPRINTF("STATUS"); 
-    break;
-  case P_MSGO:
-    SPRINTF("MESSAGE OUT");
-    break;
-  case P_MSGI:
-    SPRINTF("MESSAGE IN");
-    break;
-  default:
-    SPRINTF("*illegal*");
-    break;
-  }
-  
-  SPRINTF("); ");
-
-  SPRINTF("INTSTAT (%s); ", TESTHI(DMASTAT, INTSTAT) ? "hi" : "lo");
-
-  SPRINTF("SSTAT (");
-  s=GETPORT(SSTAT0);
-  if(s & TARGET)   SPRINTF("TARGET ");
-  if(s & SELDO)    SPRINTF("SELDO ");
-  if(s & SELDI)    SPRINTF("SELDI ");
-  if(s & SELINGO)  SPRINTF("SELINGO ");
-  if(s & SWRAP)    SPRINTF("SWRAP ");
-  if(s & SDONE)    SPRINTF("SDONE ");
-  if(s & SPIORDY)  SPRINTF("SPIORDY ");
-  if(s & DMADONE)  SPRINTF("DMADONE ");
-
-  s=GETPORT(SSTAT1);
-  if(s & SELTO)     SPRINTF("SELTO ");
-  if(s & ATNTARG)   SPRINTF("ATNTARG ");
-  if(s & SCSIRSTI)  SPRINTF("SCSIRSTI ");
-  if(s & PHASEMIS)  SPRINTF("PHASEMIS ");
-  if(s & BUSFREE)   SPRINTF("BUSFREE ");
-  if(s & SCSIPERR)  SPRINTF("SCSIPERR ");
-  if(s & PHASECHG)  SPRINTF("PHASECHG ");
-  if(s & REQINIT)   SPRINTF("REQINIT ");
-  SPRINTF("); ");
-
-
-  SPRINTF("SSTAT (");
-
-  s=GETPORT(SSTAT0) & GETPORT(SIMODE0);
-
-  if(s & TARGET)    SPRINTF("TARGET ");
-  if(s & SELDO)     SPRINTF("SELDO ");
-  if(s & SELDI)     SPRINTF("SELDI ");
-  if(s & SELINGO)   SPRINTF("SELINGO ");
-  if(s & SWRAP)     SPRINTF("SWRAP ");
-  if(s & SDONE)     SPRINTF("SDONE ");
-  if(s & SPIORDY)   SPRINTF("SPIORDY ");
-  if(s & DMADONE)   SPRINTF("DMADONE ");
-
-  s=GETPORT(SSTAT1) & GETPORT(SIMODE1);
-
-  if(s & SELTO)     SPRINTF("SELTO ");
-  if(s & ATNTARG)   SPRINTF("ATNTARG ");
-  if(s & SCSIRSTI)  SPRINTF("SCSIRSTI ");
-  if(s & PHASEMIS)  SPRINTF("PHASEMIS ");
-  if(s & BUSFREE)   SPRINTF("BUSFREE ");
-  if(s & SCSIPERR)  SPRINTF("SCSIPERR ");
-  if(s & PHASECHG)  SPRINTF("PHASECHG ");
-  if(s & REQINIT)   SPRINTF("REQINIT ");
-  SPRINTF("); ");
-
-  SPRINTF("SXFRCTL0 (");
-
-  s=GETPORT(SXFRCTL0);
-  if(s & SCSIEN)    SPRINTF("SCSIEN ");
-  if(s & DMAEN)     SPRINTF("DMAEN ");
-  if(s & CH1)       SPRINTF("CH1 ");
-  if(s & CLRSTCNT)  SPRINTF("CLRSTCNT ");
-  if(s & SPIOEN)    SPRINTF("SPIOEN ");
-  if(s & CLRCH1)    SPRINTF("CLRCH1 ");
-  SPRINTF("); ");
-
-  SPRINTF("SIGNAL (");
-
-  s=GETPORT(SCSISIG);
-  if(s & ATNI)  SPRINTF("ATNI ");
-  if(s & SELI)  SPRINTF("SELI ");
-  if(s & BSYI)  SPRINTF("BSYI ");
-  if(s & REQI)  SPRINTF("REQI ");
-  if(s & ACKI)  SPRINTF("ACKI ");
-  SPRINTF("); ");
-
-  SPRINTF("SELID (%02x), ", GETPORT(SELID));
-
-  SPRINTF("SSTAT2 (");
-
-  s=GETPORT(SSTAT2);
-  if(s & SOFFSET)  SPRINTF("SOFFSET ");
-  if(s & SEMPTY)   SPRINTF("SEMPTY ");
-  if(s & SFULL)    SPRINTF("SFULL ");
-  SPRINTF("); SFCNT (%d); ", s & (SFULL|SFCNT));
-
-  s=GETPORT(SSTAT3);
-  SPRINTF("SCSICNT (%d), OFFCNT(%d), ", (s&0xf0)>>4, s&0x0f);
-  
-  SPRINTF("SSTAT4 (");
-  s=GETPORT(SSTAT4);
-  if(s & SYNCERR)   SPRINTF("SYNCERR ");
-  if(s & FWERR)     SPRINTF("FWERR ");
-  if(s & FRERR)     SPRINTF("FRERR ");
-  SPRINTF("); ");
-
-  SPRINTF("DMACNTRL0 (");
-  s=GETPORT(DMACNTRL0);
-  SPRINTF("%s ", s & _8BIT      ? "8BIT"  : "16BIT");
-  SPRINTF("%s ", s & DMA        ? "DMA"   : "PIO"  );
-  SPRINTF("%s ", s & WRITE_READ ? "WRITE" : "READ" );
-  if(s & ENDMA)    SPRINTF("ENDMA ");
-  if(s & INTEN)    SPRINTF("INTEN ");
-  if(s & RSTFIFO)  SPRINTF("RSTFIFO ");
-  if(s & SWINT)    SPRINTF("SWINT ");
-  SPRINTF("); ");
-
-  SPRINTF("DMASTAT (");
-  s=GETPORT(DMASTAT);
-  if(s & ATDONE)     SPRINTF("ATDONE ");
-  if(s & WORDRDY)    SPRINTF("WORDRDY ");
-  if(s & DFIFOFULL)  SPRINTF("DFIFOFULL ");
-  if(s & DFIFOEMP)   SPRINTF("DFIFOEMP ");
-  SPRINTF(")\n\n");
-
-  SPRINTF("enabled interrupts (");
-  
-  s=GETPORT(SIMODE0);
-  if(s & ENSELDO)    SPRINTF("ENSELDO ");
-  if(s & ENSELDI)    SPRINTF("ENSELDI ");
-  if(s & ENSELINGO)  SPRINTF("ENSELINGO ");
-  if(s & ENSWRAP)    SPRINTF("ENSWRAP ");
-  if(s & ENSDONE)    SPRINTF("ENSDONE ");
-  if(s & ENSPIORDY)  SPRINTF("ENSPIORDY ");
-  if(s & ENDMADONE)  SPRINTF("ENDMADONE ");
-
-  s=GETPORT(SIMODE1);
-  if(s & ENSELTIMO)    SPRINTF("ENSELTIMO ");
-  if(s & ENATNTARG)    SPRINTF("ENATNTARG ");
-  if(s & ENPHASEMIS)   SPRINTF("ENPHASEMIS ");
-  if(s & ENBUSFREE)    SPRINTF("ENBUSFREE ");
-  if(s & ENSCSIPERR)   SPRINTF("ENSCSIPERR ");
-  if(s & ENPHASECHG)   SPRINTF("ENPHASECHG ");
-  if(s & ENREQINIT)    SPRINTF("ENREQINIT ");
-  SPRINTF(")\n");
-  
-  return (pos-start);
+	SPRINTF("SSTAT (");
+	s = GETPORT(SSTAT0);
+	if (s & TARGET)
+		SPRINTF("TARGET ");
+	if (s & SELDO)
+		SPRINTF("SELDO ");
+	if (s & SELDI)
+		SPRINTF("SELDI ");
+	if (s & SELINGO)
+		SPRINTF("SELINGO ");
+	if (s & SWRAP)
+		SPRINTF("SWRAP ");
+	if (s & SDONE)
+		SPRINTF("SDONE ");
+	if (s & SPIORDY)
+		SPRINTF("SPIORDY ");
+	if (s & DMADONE)
+		SPRINTF("DMADONE ");
+
+	s = GETPORT(SSTAT1);
+	if (s & SELTO)
+		SPRINTF("SELTO ");
+	if (s & ATNTARG)
+		SPRINTF("ATNTARG ");
+	if (s & SCSIRSTI)
+		SPRINTF("SCSIRSTI ");
+	if (s & PHASEMIS)
+		SPRINTF("PHASEMIS ");
+	if (s & BUSFREE)
+		SPRINTF("BUSFREE ");
+	if (s & SCSIPERR)
+		SPRINTF("SCSIPERR ");
+	if (s & PHASECHG)
+		SPRINTF("PHASECHG ");
+	if (s & REQINIT)
+		SPRINTF("REQINIT ");
+	SPRINTF("); ");
+
+
+	SPRINTF("SSTAT (");
+
+	s = GETPORT(SSTAT0) & GETPORT(SIMODE0);
+
+	if (s & TARGET)
+		SPRINTF("TARGET ");
+	if (s & SELDO)
+		SPRINTF("SELDO ");
+	if (s & SELDI)
+		SPRINTF("SELDI ");
+	if (s & SELINGO)
+		SPRINTF("SELINGO ");
+	if (s & SWRAP)
+		SPRINTF("SWRAP ");
+	if (s & SDONE)
+		SPRINTF("SDONE ");
+	if (s & SPIORDY)
+		SPRINTF("SPIORDY ");
+	if (s & DMADONE)
+		SPRINTF("DMADONE ");
+
+	s = GETPORT(SSTAT1) & GETPORT(SIMODE1);
+
+	if (s & SELTO)
+		SPRINTF("SELTO ");
+	if (s & ATNTARG)
+		SPRINTF("ATNTARG ");
+	if (s & SCSIRSTI)
+		SPRINTF("SCSIRSTI ");
+	if (s & PHASEMIS)
+		SPRINTF("PHASEMIS ");
+	if (s & BUSFREE)
+		SPRINTF("BUSFREE ");
+	if (s & SCSIPERR)
+		SPRINTF("SCSIPERR ");
+	if (s & PHASECHG)
+		SPRINTF("PHASECHG ");
+	if (s & REQINIT)
+		SPRINTF("REQINIT ");
+	SPRINTF("); ");
+
+	SPRINTF("SXFRCTL0 (");
+
+	s = GETPORT(SXFRCTL0);
+	if (s & SCSIEN)
+		SPRINTF("SCSIEN ");
+	if (s & DMAEN)
+		SPRINTF("DMAEN ");
+	if (s & CH1)
+		SPRINTF("CH1 ");
+	if (s & CLRSTCNT)
+		SPRINTF("CLRSTCNT ");
+	if (s & SPIOEN)
+		SPRINTF("SPIOEN ");
+	if (s & CLRCH1)
+		SPRINTF("CLRCH1 ");
+	SPRINTF("); ");
+
+	SPRINTF("SIGNAL (");
+
+	s = GETPORT(SCSISIG);
+	if (s & ATNI)
+		SPRINTF("ATNI ");
+	if (s & SELI)
+		SPRINTF("SELI ");
+	if (s & BSYI)
+		SPRINTF("BSYI ");
+	if (s & REQI)
+		SPRINTF("REQI ");
+	if (s & ACKI)
+		SPRINTF("ACKI ");
+	SPRINTF("); ");
+
+	SPRINTF("SELID (%02x), ", GETPORT(SELID));
+
+	SPRINTF("SSTAT2 (");
+
+	s = GETPORT(SSTAT2);
+	if (s & SOFFSET)
+		SPRINTF("SOFFSET ");
+	if (s & SEMPTY)
+		SPRINTF("SEMPTY ");
+	if (s & SFULL)
+		SPRINTF("SFULL ");
+	SPRINTF("); SFCNT (%d); ", s & (SFULL | SFCNT));
+
+	s = GETPORT(SSTAT3);
+	SPRINTF("SCSICNT (%d), OFFCNT(%d), ", (s & 0xf0) >> 4, s & 0x0f);
+
+	SPRINTF("SSTAT4 (");
+	s = GETPORT(SSTAT4);
+	if (s & SYNCERR)
+		SPRINTF("SYNCERR ");
+	if (s & FWERR)
+		SPRINTF("FWERR ");
+	if (s & FRERR)
+		SPRINTF("FRERR ");
+	SPRINTF("); ");
+
+	SPRINTF("DMACNTRL0 (");
+	s = GETPORT(DMACNTRL0);
+	SPRINTF("%s ", s & _8BIT ? "8BIT" : "16BIT");
+	SPRINTF("%s ", s & DMA ? "DMA" : "PIO");
+	SPRINTF("%s ", s & WRITE_READ ? "WRITE" : "READ");
+	if (s & ENDMA)
+		SPRINTF("ENDMA ");
+	if (s & INTEN)
+		SPRINTF("INTEN ");
+	if (s & RSTFIFO)
+		SPRINTF("RSTFIFO ");
+	if (s & SWINT)
+		SPRINTF("SWINT ");
+	SPRINTF("); ");
+
+	SPRINTF("DMASTAT (");
+	s = GETPORT(DMASTAT);
+	if (s & ATDONE)
+		SPRINTF("ATDONE ");
+	if (s & WORDRDY)
+		SPRINTF("WORDRDY ");
+	if (s & DFIFOFULL)
+		SPRINTF("DFIFOFULL ");
+	if (s & DFIFOEMP)
+		SPRINTF("DFIFOEMP ");
+	SPRINTF(")\n\n");
+
+	SPRINTF("enabled interrupts (");
+
+	s = GETPORT(SIMODE0);
+	if (s & ENSELDO)
+		SPRINTF("ENSELDO ");
+	if (s & ENSELDI)
+		SPRINTF("ENSELDI ");
+	if (s & ENSELINGO)
+		SPRINTF("ENSELINGO ");
+	if (s & ENSWRAP)
+		SPRINTF("ENSWRAP ");
+	if (s & ENSDONE)
+		SPRINTF("ENSDONE ");
+	if (s & ENSPIORDY)
+		SPRINTF("ENSPIORDY ");
+	if (s & ENDMADONE)
+		SPRINTF("ENDMADONE ");
+
+	s = GETPORT(SIMODE1);
+	if (s & ENSELTIMO)
+		SPRINTF("ENSELTIMO ");
+	if (s & ENATNTARG)
+		SPRINTF("ENATNTARG ");
+	if (s & ENPHASEMIS)
+		SPRINTF("ENPHASEMIS ");
+	if (s & ENBUSFREE)
+		SPRINTF("ENBUSFREE ");
+	if (s & ENSCSIPERR)
+		SPRINTF("ENSCSIPERR ");
+	if (s & ENPHASECHG)
+		SPRINTF("ENPHASECHG ");
+	if (s & ENREQINIT)
+		SPRINTF("ENREQINIT ");
+	SPRINTF(")\n");
+
+	return (pos - start);
 }
 
 #undef SPRINTF
 #define SPRINTF(args...) do { if(pos < buffer + length) pos += sprintf(pos, ## args); } while(0)
 
 int aha152x_proc_info(char *buffer, char **start,
-                      off_t offset, int length, int hostno, int inout)
+		      off_t offset, int length, int hostno, int inout)
 {
-  int i;
-  char *pos = buffer;
-  struct Scsi_Host *shpnt;
-  unsigned long flags;
-  Scsi_Cmnd *ptr;
-  
-  for(i=0, shpnt= (struct Scsi_Host *) NULL; i<IRQS; i++)
-    if(aha152x_host[i] && aha152x_host[i]->host_no == hostno)
-      shpnt=aha152x_host[i];
-  
-  if(!shpnt)
-    return(-ESRCH);
-  
-  if(inout) /* Has data been written to the file ? */ 
-    return(aha152x_set_info(buffer, length, shpnt));
-  
-  SPRINTF(AHA152X_REVID "\n");
-  
-  save_flags(flags);
-  cli();
-  
-  SPRINTF("ioports 0x%04lx to 0x%04lx\n",
-          shpnt->io_port, shpnt->io_port+shpnt->n_io_port-1);
-  SPRINTF("interrupt 0x%02x\n", shpnt->irq);
-  SPRINTF("disconnection/reconnection %s\n", 
-          HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled");
-  SPRINTF("parity checking %s\n", 
-          HOSTDATA(shpnt)->parity ? "enabled" : "disabled");
-  SPRINTF("synchronous transfers %s\n", 
-          HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
-  SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands);
-  
-  if(HOSTDATA(shpnt)->synchronous) {
+	int i;
+	char *pos = buffer;
+	struct Scsi_Host *shpnt;
+	unsigned long flags;
+	Scsi_Cmnd *ptr;
+
+	for (i = 0, shpnt = (struct Scsi_Host *) NULL; i < IRQS; i++)
+		if (aha152x_host[i] && aha152x_host[i]->host_no == hostno)
+			shpnt = aha152x_host[i];
+
+	if (!shpnt)
+		return (-ESRCH);
+
+	if (inout)		/* Has data been written to the file ? */
+		return (aha152x_set_info(buffer, length, shpnt));
+
+	SPRINTF(AHA152X_REVID "\n");
+
+	save_flags(flags);
+	cli();
+
+	SPRINTF("ioports 0x%04lx to 0x%04lx\n",
+		shpnt->io_port, shpnt->io_port + shpnt->n_io_port - 1);
+	SPRINTF("interrupt 0x%02x\n", shpnt->irq);
+	SPRINTF("disconnection/reconnection %s\n",
+		HOSTDATA(shpnt)->reconnect ? "enabled" : "disabled");
+	SPRINTF("parity checking %s\n",
+		HOSTDATA(shpnt)->parity ? "enabled" : "disabled");
+	SPRINTF("synchronous transfers %s\n",
+		HOSTDATA(shpnt)->synchronous ? "enabled" : "disabled");
+	SPRINTF("%d commands currently queued\n", HOSTDATA(shpnt)->commands);
+
+	if (HOSTDATA(shpnt)->synchronous) {
 #if 0
-    SPRINTF("synchronously operating targets (tick=%ld ns):\n",
-            250000000/loops_per_sec);
-    for(i=0; i<8; i++)
-      if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
-        SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n",
-                i,
-                (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
-                         (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*
-                         250000000/loops_per_sec,
-                           HOSTDATA(shpnt)->syncrate[i]&0x0f);
+		SPRINTF("synchronously operating targets (tick=%ld ns):\n",
+			250000000 / loops_per_sec);
+		for (i = 0; i < 8; i++)
+			if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
+				SPRINTF("target %d: period %dT/%ldns; req/ack offset %d\n",
+					i,
+					(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
+					(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) *
+					250000000 / loops_per_sec,
+				    HOSTDATA(shpnt)->syncrate[i] & 0x0f);
 #else
-    SPRINTF("synchronously operating targets (tick=50 ns):\n");
-    for(i=0; i<8; i++)
-      if(HOSTDATA(shpnt)->syncrate[i]&0x7f)
-        SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
-                i,
-                (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2),
-                (((HOSTDATA(shpnt)->syncrate[i]&0x70)>>4)+2)*50,
-                HOSTDATA(shpnt)->syncrate[i]&0x0f);
+		SPRINTF("synchronously operating targets (tick=50 ns):\n");
+		for (i = 0; i < 8; i++)
+			if (HOSTDATA(shpnt)->syncrate[i] & 0x7f)
+				SPRINTF("target %d: period %dT/%dns; req/ack offset %d\n",
+					i,
+					(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2),
+					(((HOSTDATA(shpnt)->syncrate[i] & 0x70) >> 4) + 2) * 50,
+				    HOSTDATA(shpnt)->syncrate[i] & 0x0f);
 #endif
-  }
-  
+	}
 #ifdef DEBUG_AHA152X
 #define PDEBUG(flags,txt) if(HOSTDATA(shpnt)->debug & flags) SPRINTF("(%s) ", txt);
-  
-  SPRINTF("enabled debugging options: ");
-  
-  PDEBUG(debug_skipports, "skip ports");
-  PDEBUG(debug_queue, "queue");
-  PDEBUG(debug_intr, "interrupt");
-  PDEBUG(debug_selection, "selection");
-  PDEBUG(debug_msgo, "message out");
-  PDEBUG(debug_msgi, "message in");
-  PDEBUG(debug_status, "status");
-  PDEBUG(debug_cmd, "command");
-  PDEBUG(debug_datai, "data in");
-  PDEBUG(debug_datao, "data out");
-  PDEBUG(debug_abort, "abort");
-  PDEBUG(debug_done, "done");
-  PDEBUG(debug_biosparam, "bios parameters");
-  PDEBUG(debug_phases, "phases");
-  PDEBUG(debug_queues, "queues");
-  PDEBUG(debug_reset, "reset");
-  
-  SPRINTF("\n");
-#endif
-  
-  SPRINTF("\nqueue status:\n");
-  if(ISSUE_SC) {
-    SPRINTF("not yet issued commands:\n");
-    for(ptr=ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-      pos += get_command(pos, ptr);
-  } else 
-    SPRINTF("no not yet issued commands\n");
-  
-  if(CURRENT_SC) {
-    SPRINTF("current command:\n");
-    pos += get_command(pos, CURRENT_SC);
-  } else
-    SPRINTF("no current command\n");
-  
-  if(DISCONNECTED_SC) {
-    SPRINTF("disconnected commands:\n");
-    for(ptr=DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
-      pos += get_command(pos, ptr);
-  } else
-    SPRINTF("no disconnected commands\n");
-  
-  restore_flags(flags);
-
-  pos += get_ports(shpnt, pos);
-  
-  *start=buffer+offset;
-  if (pos - buffer < offset)
-    return 0;
-  else if (pos - buffer - offset < length)
-    return pos - buffer - offset;
-  else
-    return length;
+
+	SPRINTF("enabled debugging options: ");
+
+	PDEBUG(debug_skipports, "skip ports");
+	PDEBUG(debug_queue, "queue");
+	PDEBUG(debug_intr, "interrupt");
+	PDEBUG(debug_selection, "selection");
+	PDEBUG(debug_msgo, "message out");
+	PDEBUG(debug_msgi, "message in");
+	PDEBUG(debug_status, "status");
+	PDEBUG(debug_cmd, "command");
+	PDEBUG(debug_datai, "data in");
+	PDEBUG(debug_datao, "data out");
+	PDEBUG(debug_abort, "abort");
+	PDEBUG(debug_done, "done");
+	PDEBUG(debug_biosparam, "bios parameters");
+	PDEBUG(debug_phases, "phases");
+	PDEBUG(debug_queues, "queues");
+	PDEBUG(debug_reset, "reset");
+
+	SPRINTF("\n");
+#endif
+
+	SPRINTF("\nqueue status:\n");
+	if (ISSUE_SC) {
+		SPRINTF("not yet issued commands:\n");
+		for (ptr = ISSUE_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+			pos += get_command(pos, ptr);
+	} else
+		SPRINTF("no not yet issued commands\n");
+
+	if (CURRENT_SC) {
+		SPRINTF("current command:\n");
+		pos += get_command(pos, CURRENT_SC);
+	} else
+		SPRINTF("no current command\n");
+
+	if (DISCONNECTED_SC) {
+		SPRINTF("disconnected commands:\n");
+		for (ptr = DISCONNECTED_SC; ptr; ptr = (Scsi_Cmnd *) ptr->host_scribble)
+			pos += get_command(pos, ptr);
+	} else
+		SPRINTF("no disconnected commands\n");
+
+	restore_flags(flags);
+
+	pos += get_ports(shpnt, pos);
+
+	*start = buffer + offset;
+	if (pos - buffer < offset)
+		return 0;
+	else if (pos - buffer - offset < length)
+		return pos - buffer - offset;
+	else
+		return length;
 }
 
 #ifdef MODULE
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aha1542.c linux.pre11.3/drivers/scsi/aha1542.c
--- linux.vanilla/drivers/scsi/aha1542.c	Sun Nov  8 15:07:48 1998
+++ linux.pre11.3/drivers/scsi/aha1542.c	Tue Jul 20 00:01:44 1999
@@ -18,6 +18,9 @@
  *        1-Jan-97
  *  Modified by Bjorn L. Thordarson and Einar Thor Einarsson
  *        Recognize that DMA0 is valid DMA channel -- 13-Jul-98
+ *  Modified by Chris Faulhaber	<jedgar@fxp.org>
+ *        Added module command-line options
+ *        18-Jul-99
  */
 
 #include <linux/module.h>
@@ -84,7 +87,7 @@
 static char *setup_str[MAXBOARDS] = {(char *)NULL,(char *)NULL};
 
 /*
- * LILO params:  aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]
+ * LILO/Module params:  aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]
  *
  * Where:  <PORTBASE> is any of the valid AHA addresses:
  *			0x130, 0x134, 0x230, 0x234, 0x330, 0x334
@@ -100,6 +103,11 @@
  *		    Factory default is 5 MB/s.
  */
 
+#if defined(MODULE)
+int aha1542[] = { 0x330, 11, 4, -1 };
+MODULE_PARM(aha1542, "1-4i");
+#endif
+
 #define BIOS_TRANSLATION_1632 0  /* Used by some old 1542A boards */
 #define BIOS_TRANSLATION_6432 1 /* Default case these days */
 #define BIOS_TRANSLATION_25563 2 /* Big disk case */
@@ -823,7 +831,8 @@
      mbenable_cmd[1]=0;
      mbenable_cmd[2]=mbenable_result[1];
 
-     if(mbenable_result[1] & 0x03) retval = BIOS_TRANSLATION_25563;
+     if((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03))
+       retval = BIOS_TRANSLATION_25563;
 
      aha1542_out(base,mbenable_cmd,3);
      WAIT(INTRFLAGS(base),INTRMASK,HACC,0);
@@ -953,6 +962,14 @@
     DEB(printk("aha1542_detect: \n"));
 
     tpnt->proc_dir = &proc_scsi_aha1542;
+
+#ifdef MODULE
+    bases[0] = 4;
+    bases[1] = aha1542[0];
+    bases[2] = aha1542[1];
+    bases[3] = aha1542[2];
+    bases[4] = aha1542[3];
+#endif
 
     for(indx = 0; indx < sizeof(bases)/sizeof(bases[0]); indx++)
 	    if(bases[indx] != 0 && !check_region(bases[indx], 4)) { 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx/aic7xxx.reg linux.pre11.3/drivers/scsi/aic7xxx/aic7xxx.reg
--- linux.vanilla/drivers/scsi/aic7xxx/aic7xxx.reg	Tue Jun 15 16:49:50 1999
+++ linux.pre11.3/drivers/scsi/aic7xxx/aic7xxx.reg	Mon Jul 19 23:28:02 1999
@@ -845,7 +845,7 @@
 	bit	CRCENDCHKEN	0x20 /* CRC End Check Enable */
 	bit	CRCREQCHKEN	0x10
 	bit	TARGCRCENDEN	0x08 /* Enable End CRC transfer when target */
-	bit	TARGCRCCNTEN	0x40 /* Enable CRC transfer when target */
+	bit	TARGCRCCNTEN	0x04 /* Enable CRC transfer when target */
 }
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx.c linux.pre11.3/drivers/scsi/aic7xxx.c
--- linux.vanilla/drivers/scsi/aic7xxx.c	Tue Jun 15 16:49:51 1999
+++ linux.pre11.3/drivers/scsi/aic7xxx.c	Tue Jul 20 00:02:00 1999
@@ -270,7 +270,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.17"
+#define AIC7XXX_C_VERSION  "5.1.19"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -7412,73 +7412,83 @@
 
 /*+F*************************************************************************
  * Function:
- *   write_brdctl
+ *   read_brdctl
  *
  * Description:
- *   Writes a value to the BRDCTL register.
+ *   Reads the BRDCTL register.
  *-F*************************************************************************/
-static void
-write_brdctl(struct aic7xxx_host *p, unsigned char value)
+static unsigned char
+read_brdctl(struct aic7xxx_host *p)
 {
-  unsigned char brdctl;
+  unsigned char brdctl, value;
 
-  if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895)
+  if (p->features & AHC_ULTRA2)
   {
-    brdctl = BRDSTB;
-    if (p->flags & AHC_CHNLB)
-      brdctl |= BRDCS;
+    brdctl = BRDRW_ULTRA2;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(4);
+    return(aic_inb(p, BRDCTL));
+  }
+  brdctl = BRDRW;
+  if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) ||
+        (p->flags & AHC_CHNLB) )
+  {
+    brdctl |= BRDCS;
   }
-  else if (p->features & AHC_ULTRA2)
-    brdctl = 0;
-  else
-    brdctl = BRDSTB | BRDCS;
-  aic_outb(p, brdctl, BRDCTL);
-  udelay(1);
-  brdctl |= value;
   aic_outb(p, brdctl, BRDCTL);
   udelay(1);
-  if (p->features & AHC_ULTRA2)
-    brdctl |= BRDSTB_ULTRA2;
-  else
-    brdctl &= ~BRDSTB;
-  aic_outb(p, brdctl, BRDCTL);
-  udelay(1);
-  if (p->features & AHC_ULTRA2)
-    brdctl = 0;
-  else
-    brdctl &= ~BRDCS;
-  aic_outb(p, brdctl, BRDCTL);
+  value = aic_inb(p, BRDCTL);
+  aic_outb(p, 0, BRDCTL);
   udelay(1);
+  return (value);
 }
 
 /*+F*************************************************************************
  * Function:
- *   read_brdctl
+ *   write_brdctl
  *
  * Description:
- *   Reads the BRDCTL register.
+ *   Writes a value to the BRDCTL register.
  *-F*************************************************************************/
-static unsigned char
-read_brdctl(struct aic7xxx_host *p)
+static void
+write_brdctl(struct aic7xxx_host *p, unsigned char value)
 {
-  unsigned char brdctl, value;
+  unsigned char brdctl;
 
-  if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895)
+  if (p->features & AHC_ULTRA2)
   {
-    brdctl = BRDRW;
-    if (p->flags & AHC_CHNLB)
-      brdctl |= BRDCS;
+    brdctl = value;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(4);
+    brdctl |= BRDSTB_ULTRA2;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(4);
+    brdctl &= ~BRDSTB_ULTRA2;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(4);
+    read_brdctl(p);
   }
-  else if (p->features & AHC_ULTRA2)
-    brdctl = BRDRW_ULTRA2;
   else
-    brdctl = BRDRW | BRDCS;
-  aic_outb(p, brdctl, BRDCTL);
-  udelay(1);
-  value = aic_inb(p, BRDCTL);
-  aic_outb(p, 0, BRDCTL);
-  udelay(1);
-  return (value);
+  {
+    brdctl = BRDSTB;
+    if ( !((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) ||
+          (p->flags & AHC_CHNLB) )
+    {
+      brdctl |= BRDCS;
+    }
+    brdctl = BRDSTB | BRDCS;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(1);
+    brdctl |= value;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(1);
+    brdctl &= ~BRDSTB;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(1);
+    brdctl &= ~BRDCS;
+    aic_outb(p, brdctl, BRDCTL);
+    udelay(1);
+  }
 }
 
 /*+F*************************************************************************
@@ -7770,9 +7780,9 @@
                  p->host_no);
       }
     }
+    aic_outb(p, sxfrctl1, SXFRCTL1);
     write_brdctl(p, brddat);
     release_seeprom(p);
-    aic_outb(p, sxfrctl1, SXFRCTL1);
   }
 }
 
@@ -8086,7 +8096,11 @@
     /* Select channel B */
     aic_outb(p, aic_inb(p, SBLKCTL) | SELBUSB, SBLKCTL);
 
-    term = ((p->flags & AHC_TERM_ENB_B) != 0) ? STPWEN : 0;
+    if ((p->flags & AHC_SEEPROM_FOUND) || (aic7xxx_override_term != -1))
+      term = (aic_inb(p, SXFRCTL1) & STPWEN);
+    else
+      term = ((p->flags & AHC_TERM_ENB_B) ? STPWEN : 0);
+
     aic_outb(p, p->scsi_id_b, SCSIID);
     scsi_conf = aic_inb(p, SCSICONF + 1);
     aic_outb(p, DFON | SPIOEN, SXFRCTL0);
@@ -8100,11 +8114,18 @@
     aic_outb(p, aic_inb(p, SBLKCTL) & ~SELBUSB, SBLKCTL);
   }
 
-  term = ((p->flags & AHC_TERM_ENB_SE_LOW) != 0) ? STPWEN : 0;
   if (p->features & AHC_ULTRA2)
+  {
     aic_outb(p, p->scsi_id, SCSIID_ULTRA2);
+  }
   else
+  {
     aic_outb(p, p->scsi_id, SCSIID);
+  }
+  if ((p->flags & AHC_SEEPROM_FOUND) || (aic7xxx_override_term != -1))
+    term = (aic_inb(p, SXFRCTL1) & STPWEN);
+  else
+    term = ((p->flags & (AHC_TERM_ENB_A|AHC_TERM_ENB_LVD)) ? STPWEN : 0);
   scsi_conf = aic_inb(p, SCSICONF);
   aic_outb(p, DFON | SPIOEN, SXFRCTL0);
   aic_outb(p, (scsi_conf & ENSPCHK) | STIMESEL | term | 
@@ -8794,27 +8815,33 @@
     }
     if (p->flags & AHC_NEWEEPROM_FMT)
     {
-      if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) &&
-          !(p->features & AHC_ULTRA2) )
+      if ( !(p->features & AHC_ULTRA2) )
       {
         /*
          * I know of two different Ultra BIOSes that do this differently.
          * One on the Gigabyte 6BXU mb that wants flags[i] & CFXFER to
-         * be == to 0x03 and SYNCISULTRA to be true to mean 40MByte/s
+         * be == to 0x03 and SYNCHISULTRA to be true to mean 40MByte/s
          * while on the IBM Netfinity 5000 they want the same thing
          * to be something else, while flags[i] & CFXFER == 0x03 and
-         * SYNCISULTRA false should be 40MByte/s.  So, we set both to
+         * SYNCHISULTRA false should be 40MByte/s.  So, we set both to
          * 40MByte/s and the lower speeds be damned.  People will have
          * to select around the conversely mapped lower speeds in order
          * to select lower speeds on these boards.
          */
-        if ((sc->device_flags[i] & (CFXFER)) == 0x03)
+        if ( (sc->device_flags[i] & CFNEWULTRAFORMAT) &&
+            ((sc->device_flags[i] & CFXFER) == 0x03) )
         {
           sc->device_flags[i] &= ~CFXFER;
           sc->device_flags[i] |= CFSYNCHISULTRA;
         }
+        if (sc->device_flags[i] & CFSYNCHISULTRA)
+        {
+          p->ultraenb |= mask;
+        }
       }
-      if (sc->device_flags[i] & CFSYNCHISULTRA)
+      else if ( !(sc->device_flags[i] & CFNEWULTRAFORMAT) &&
+                 (p->features & AHC_ULTRA2) &&
+                 (sc->device_flags[i] & CFSYNCHISULTRA) )
       {
         p->ultraenb |= mask;
       }
@@ -9035,11 +9062,44 @@
 
 
 #if defined(__i386__) || defined(__alpha__)
+#ifdef CONFIG_PCI
+  /*
+   * PCI-bus chipset probe.
+   */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
+  if (pci_present())
+  {
+    if (pci_find_device(PCI_VENDOR_ID_INTEL,
+                        PCI_DEVICE_ID_INTEL_82450GX,
+                        NULL))
+      aic7xxx_no_probe = 1;
+    if (pci_find_device(PCI_VENDOR_ID_INTEL,
+                        PCI_DEVICE_ID_INTEL_82451NX,
+                        NULL))
+      aic7xxx_no_probe = 1;
+  }
+#else
+#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
+  if (pcibios_present())
+  {
+    unsigned char pci_bus, pci_devfn;
+    if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
+                              PCI_DEVICE_ID_INTEL_82450GX,
+                              0, &pci_bus, &pci_devfn)) )
+      aic7xxx_no_probe = 1;
+    if (!(pcibios_find_device(PCI_VENDOR_ID_INTEL,
+                              PCI_DEVICE_ID_INTEL_82451NX,
+                              0, &pci_bus, &pci_devfn)) )
+      aic7xxx_no_probe = 1;
+  }
+#endif /* LINUX_VERSION_CODE */
+#endif /* CONFIG_PCI */
   /*
    * EISA/VL-bus card signature probe.
    */
   slot = MINSLOT;
-  while ( (slot <= MAXSLOT) && !(aic7xxx_no_probe) )
+  while ( (slot <= MAXSLOT) && 
+         !(aic7xxx_no_probe) )
   {
     base = SLOTBASE(slot) + MINREG;
 
@@ -9293,6 +9353,10 @@
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
        AHC_AIC7860_FE,                                       7,
        32, C46 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_38602, AHC_AIC7860,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7860_FE,                                       7,
+       32, C46 },
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AHC_AIC7860,
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
        AHC_AIC7860_FE,                                       7,
@@ -9471,6 +9535,23 @@
           temp_p->pci_device_fn = pdev->devfn;
           temp_p->base = pdev->base_address[0];
           temp_p->mbase = pdev->base_address[1];
+          temp_p->base &= PCI_BASE_ADDRESS_IO_MASK;
+          temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK;
+          current_p = list_p;
+          while(current_p)
+          {
+            if ( ((current_p->pci_bus == temp_p->pci_bus) &&
+                  (current_p->pci_device_fn == temp_p->pci_device_fn)) ||
+                  (current_p->base == temp_p->base) )
+            {
+              /* duplicate PCI entry, skip it */
+              kfree(temp_p);
+              temp_p = NULL;
+            }
+            current_p = current_p->next;
+          }
+          if ( temp_p == NULL )
+            continue;
           if (aic7xxx_verbose & VERBOSE_PROBE2)
             printk("aic7xxx: <%s> at PCI %d/%d\n", 
               board_names[aic_pdevs[i].board_name_index],
@@ -9504,11 +9585,6 @@
 #else  /* LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
           temp_p->pci_bus = pci_bus;
           temp_p->pci_device_fn = pci_devfn;
-          if (aic7xxx_verbose & VERBOSE_PROBE2)
-            printk("aic7xxx: <%s> at PCI %d/%d\n", 
-              board_names[aic_pdevs[i].board_name_index],
-              PCI_SLOT(temp_p->pci_device_fn),
-              PCI_FUNC(temp_p->pci_device_fn));
           pcibios_read_config_byte(pci_bus, pci_devfn, PCI_INTERRUPT_LINE,
             &pci_irq);
           temp_p->irq = pci_irq;
@@ -9518,6 +9594,28 @@
           pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_1,
             &mmapbase);
           temp_p->mbase = mmapbase;
+          temp_p->base &= PCI_BASE_ADDRESS_IO_MASK;
+          temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK;
+          current_p = list_p;
+          while(current_p)
+          {
+            if ( ((current_p->pci_bus == temp_p->pci_bus) &&
+                  (current_p->pci_device_fn == temp_p->pci_device_fn)) ||
+                  (current_p->base == temp_p->base) )
+            {
+              /* duplicate PCI entry, skip it */
+              kfree(temp_p);
+              temp_p = NULL;
+            }
+            current_p = current_p->next;
+          }
+          if ( temp_p == NULL )
+            continue;
+          if (aic7xxx_verbose & VERBOSE_PROBE2)
+            printk("aic7xxx: <%s> at PCI %d/%d\n", 
+              board_names[aic_pdevs[i].board_name_index],
+              PCI_SLOT(temp_p->pci_device_fn),
+              PCI_FUNC(temp_p->pci_device_fn));
           pcibios_read_config_word(pci_bus, pci_devfn, PCI_COMMAND, &command);
           if (aic7xxx_verbose & VERBOSE_PROBE2)
           {
@@ -9545,12 +9643,6 @@
 #endif /* AIC7XXX_STRICT_PCI_SETUP */
 #endif /* LINUIX_VERSION_CODE > KERNEL_VERSION(2,1,92) */
 
-          /*
-           * The first bit (LSB) of PCI_BASE_ADDRESS_0 is always set, so
-           * we mask it off.
-           */
-          temp_p->base &= PCI_BASE_ADDRESS_IO_MASK;
-          temp_p->mbase &= PCI_BASE_ADDRESS_MEM_MASK;
           temp_p->unpause = INTEN;
           temp_p->pause = temp_p->unpause | PAUSE;
           if ( ((temp_p->base == 0) &&
@@ -9568,6 +9660,9 @@
           }
 
 #ifdef MMAPIO
+          if ( !(temp_p->flags & AHC_MULTI_CHANNEL) ||
+               ((temp_p->chip != (AHC_AIC7870 | AHC_PCI)) &&
+                (temp_p->chip != (AHC_AIC7880 | AHC_PCI))) )
           {
             unsigned long page_offset, base;
 
@@ -9737,17 +9832,17 @@
               aic_outb(temp_p, aic_inb(temp_p, SFUNCT) | ALT_MODE, SFUNCT);
               /*
                * Set our options...the last two items set our CRC after x byte
-	       * count in target mode...
+               * count in target mode...
                */
               aic_outb(temp_p, AUTO_MSGOUT_DE | DIS_MSGIN_DUALEDGE, OPTIONMODE);
-	      aic_outb(temp_p, 0x00, 0x0b);
-	      aic_outb(temp_p, 0x10, 0x0a);
+              aic_outb(temp_p, 0x00, 0x0b);
+              aic_outb(temp_p, 0x10, 0x0a);
               /*
                * switch back to normal mode...
                */
               aic_outb(temp_p, aic_inb(temp_p, SFUNCT) & ~ALT_MODE, SFUNCT);
               aic_outb(temp_p, CRCVALCHKEN | CRCENDCHKEN | CRCREQCHKEN |
-			       TARGCRCENDEN | TARGCRCCNTEN,
+                               TARGCRCENDEN | TARGCRCCNTEN,
                        CRCCONTROL1);
               aic_outb(temp_p, ((aic_inb(temp_p, DSCOMMAND0) | USCBSIZE32 |
                                  MPARCKEN | CIOPARCKEN | CACHETHEN) & 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx_proc.c linux.pre11.3/drivers/scsi/aic7xxx_proc.c
--- linux.vanilla/drivers/scsi/aic7xxx_proc.c	Tue Jun 15 16:49:51 1999
+++ linux.pre11.3/drivers/scsi/aic7xxx_proc.c	Tue Jul 20 00:02:00 1999
@@ -29,6 +29,8 @@
  *  $Id: aic7xxx_proc.c,v 4.1 1997/06/97 08:23:42 deang Exp $
  *-M*************************************************************************/
 
+#include <linux/config.h>
+
 #define	BLS	(&aic7xxx_buffer[size])
 #define HDRB \
 "             < 2K      2K+     4K+     8K+    16K+    32K+    64K+   128K+"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/aic7xxx_reg.h linux.pre11.3/drivers/scsi/aic7xxx_reg.h
--- linux.vanilla/drivers/scsi/aic7xxx_reg.h	Tue Jun 15 16:49:51 1999
+++ linux.pre11.3/drivers/scsi/aic7xxx_reg.h	Mon Jul 19 23:28:00 1999
@@ -459,11 +459,11 @@
 
 #define	CRCCONTROL1     		0x9d
 #define		CRCONSEEN       	0x80
-#define		TARGCRCCNTEN    	0x40
 #define		CRCVALCHKEN     	0x40
 #define		CRCENDCHKEN     	0x20
 #define		CRCREQCHKEN     	0x10
 #define		TARGCRCENDEN    	0x08
+#define		TARGCRCCNTEN    	0x04
 
 #define	SCSIPHASE       		0x9e
 #define		SP_STATUS       	0x20
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/atp870u.c linux.pre11.3/drivers/scsi/atp870u.c
--- linux.vanilla/drivers/scsi/atp870u.c	Wed Mar 10 21:13:04 1999
+++ linux.pre11.3/drivers/scsi/atp870u.c	Mon Jul 19 23:28:05 1999
@@ -3,7 +3,9 @@
  *
  *  Copyright (C) 1997	Wu Ching Chen
  *  2.1.x update (C) 1998  Krzysztof G. Baranowski
- *
+ *   
+ * Marcelo Tosatti <marcelo@conectiva.com.br> : SMP fixes 
+ * 
  */
 
 #include <linux/module.h>
@@ -17,6 +19,7 @@
 #include <linux/proc_fs.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/spinlock.h>
 #include <linux/pci.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -60,6 +63,7 @@
 
 static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
+	 unsigned long flags;
     unsigned short int	tmpcip,id;
     unsigned char	i,j,h,tarid,lun;
     unsigned char  *prd;
@@ -364,7 +368,10 @@
 	     outb(0x80,tmport);
 	  }   */
 go_42:
+	  spin_lock_irqsave(&io_request_lock, flags);
 	  (*workrequ->scsi_done)(workrequ);
+	  spin_unlock_irqrestore(&io_request_lock, flags);
+
 	  curr_req[h][tarid]=0;
 	  workingu[h]--;
 	  if (wide_idu[h] != 0)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/constants.c linux.pre11.3/drivers/scsi/constants.c
--- linux.vanilla/drivers/scsi/constants.c	Sun Nov  8 15:07:49 1998
+++ linux.pre11.3/drivers/scsi/constants.c	Mon Jul 19 23:27:57 1999
@@ -1,6 +1,8 @@
 /* 
  * ASCII values for a number of symbolic constants, printing functions,
  * etc.
+ * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422)
+ *
  */
 
 #define __NO_VERSION__
@@ -37,7 +39,7 @@
 /* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks",
 /* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown,
 /* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry",  
-/* 13-16 */ unknown, "Recover Buffered Data", "Mode Select", "Reserve",
+/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve",
 /* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
 /* 1c-1d */ "Receive Diagnostic", "Send Diagnostic", 
 /* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
@@ -46,37 +48,57 @@
 
 static const char *group_1_commands[] = {
 /* 20-22 */  unknown, unknown, unknown,
-/* 23-28 */ unknown, unknown, "Read Capacity", unknown, unknown, "Read (10)", 
-/* 29-2d */ unknown, "Write (10)", "Seek (10)", unknown, unknown, 
+/* 23-28 */ unknown, "Define window parameters", "Read Capacity", 
+            unknown, unknown, "Read (10)", 
+/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase", 
+            "Read updated block", 
 /* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal", 
 /* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position", 
 /* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data", 
-/* 38-3c */ "Medium Scan", "Compare","Copy Verify", "Write Buffer", "Read Buffer", 
+/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer", 
+            "Read Buffer", 
 /* 3d-3f */ "Update Block", "Read Long",  "Write Long",
 };
 
 
 static const char *group_2_commands[] = {
 /* 40-41 */ "Change Definition", "Write Same", 
-/* 42-48 */ unknown, "Read TOC", unknown, unknown, unknown, unknown, unknown, 
-/* 49-4f */ unknown, unknown, unknown, "Log Select", "Log Sense", unknown, unknown,
+/* 42-48 */ "Read sub-channel", "Read TOC", "Read header", 
+            "Play audio (10)", unknown, "Play audio msf",
+            "Play audio track/index", 
+/* 49-4f */ "Play track relative (10)", unknown, "Pause/resume", 
+            "Log Select", "Log Sense", unknown, unknown,
 /* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)",
 /* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown,
 /* 5c-5f */ unknown, unknown, unknown,
 };
 
 
+/* The following are 12 byte commands in group 5 */
+static const char *group_5_commands[] = {
+/* a0-a5 */ unknown, unknown, unknown, unknown, unknown,
+            "Move medium/play audio(12)",
+/* a6-a9 */ "Exchange medium", unknown, "Read(12)", "Play track relative(12)", 
+/* aa-ae */ "Write(12)", unknown, "Erase(12)", unknown, 
+            "Write and verify(12)", 
+/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
+/* b2-b4 */ "Search data low(12)", "Set limits(12)", unknown,
+/* b5-b6 */ "Request volume element address", "Send volume tag",
+/* b7-b9 */ "Read defect data(12)", "Read element status", unknown,
+/* ba-bf */ unknown, unknown, unknown, unknown, unknown, unknown,
+};
+
+
 
 #define group(opcode) (((opcode) >> 5) & 7)
 
 #define RESERVED_GROUP  0
 #define VENDOR_GROUP    1
-#define NOTEXT_GROUP    2
 
 static const char **commands[] = {
     group_0_commands, group_1_commands, group_2_commands, 
     (const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP, 
-    (const char **) NOTEXT_GROUP, (const char **) VENDOR_GROUP, 
+    group_5_commands, (const char **) VENDOR_GROUP, 
     (const char **) VENDOR_GROUP
 };
 
@@ -89,9 +111,6 @@
     case RESERVED_GROUP:
 	printk("%s(0x%02x) ", reserved, opcode); 
 	break;
-    case NOTEXT_GROUP:
-	printk("%s(0x%02x) ", unknown, opcode); 
-	break;
     case VENDOR_GROUP:
 	printk("%s(0x%02x) ", vendor, opcode); 
 	break;
@@ -119,15 +138,18 @@
 
 #if (CONSTANTS & CONST_STATUS)
 static const char * statuses[] = {
-/* 0-4 */ "Good", "Check Condition", "Condition Good", unknown, "Busy", 
-/* 5-9 */ unknown, unknown, unknown, "Intermediate Good", unknown, 
-/* a-d */ "Intermediate Good", unknown, "Reservation Conflict", unknown,
-/* e-f */ unknown, unknown,
+/* 0-4 */ "Good", "Check Condition", "Condition Met", unknown, "Busy", 
+/* 5-9 */ unknown, unknown, unknown, "Intermediate", unknown, 
+/* a-c */ "Intermediate-Condition Met", unknown, "Reservation Conflict",
+/* d-10 */ unknown, unknown, unknown, unknown,
+/* 11-14 */ "Command Terminated", unknown, unknown, "Queue Full",
+/* 15-1a */ unknown, unknown, unknown, unknown, unknown, unknown,
+/* 1b-1f */ unknown, unknown, unknown, unknown, unknown,
 };
 #endif
 
 void print_status (int status) {
-    status = (status >> 1) & 0xf;
+    status = (status >> 1) & 0x1f;
 #if (CONSTANTS & CONST_STATUS)
     printk("%s ",statuses[status]);
 #else
@@ -405,8 +427,10 @@
            s = sizeof(SCpnt->sense_buffer);
 	
 	if (!valid)
-	    printk("extra data not valid ");
-	
+	    printk("[valid=0] ");
+	printk("Info fld=0x%x, ", (int)((sense_buffer[3] << 24) |
+	       (sense_buffer[4] << 16) | (sense_buffer[5] << 8) |
+	       sense_buffer[6]));
 	if (sense_buffer[2] & 0x80)
            printk( "FMK ");	/* current command has read a filemark */
 	if (sense_buffer[2] & 0x40)
@@ -427,7 +451,7 @@
 	    error = "Invalid";
 	}
 	
-	printk("%s error ", error);
+	printk("%s ", error);
 	
 #if (CONSTANTS & CONST_SENSE)
 	printk( "%s%s: sense key %s\n", devclass,
@@ -603,7 +627,8 @@
 #if (CONSTANTS & CONST_HOST)
 static const char * hostbyte_table[]={
 "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", 
-"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",NULL};
+"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
+"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL};
 
 void print_hostbyte(int scsiresult)
 {   static int maxcode=0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/dec_esp.c linux.pre11.3/drivers/scsi/dec_esp.c
--- linux.vanilla/drivers/scsi/dec_esp.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/scsi/dec_esp.c	Mon Jul 19 23:28:06 1999
@@ -0,0 +1,351 @@
+/*
+ * dec_esp.c: Driver for SCSI chips on IOASIC based TURBOchannel DECstations
+ *
+ * TURBOchannel changes by Harald Koerfgen
+ *
+ * based on jazz_esp.c:
+ * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ *
+ * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
+ */
+
+#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 "dec_esp.h"
+
+#include <asm/irq.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/dma.h>
+
+#include <asm/pgtable.h>
+
+#include <asm/dec/tc.h>
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/ioasic_ints.h>
+#include <asm/dec/machtype.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static void dma_drain(struct NCR_ESP *esp);
+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, __u32 vaddress, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 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_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static void dma_advance_sg(Scsi_Cmnd * sp);
+
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+volatile unsigned long *scsi_dma_ptr;
+volatile unsigned long *scsi_next_ptr;
+volatile unsigned long *scsi_scr;
+volatile unsigned long *ioasic_ssr;
+volatile unsigned long *scsi_sdr0;
+volatile unsigned long *scsi_sdr1;
+
+static void scsi_dma_int(int, void *, struct pt_regs *);
+
+/***************************************************************** Detection */
+int dec_esp_detect(Scsi_Host_Template * tpnt)
+{
+    struct NCR_ESP *esp;
+    struct ConfigDev *esp_dev;
+
+	if (IOASIC) {
+	esp_dev = 0;
+	esp = esp_allocate(tpnt, (void *) esp_dev);
+	
+		scsi_dma_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_P);
+		scsi_next_ptr = (unsigned long *) (system_base + IOCTL + SCSI_DMA_BP);
+		scsi_scr = (unsigned long *) (system_base + IOCTL + SCSI_SCR);
+		ioasic_ssr = (unsigned long *) (system_base + IOCTL + SSR);
+		scsi_sdr0 = (unsigned long *) (system_base + IOCTL + SCSI_SDR0);
+		scsi_sdr1 = (unsigned long *) (system_base + IOCTL + SCSI_SDR1);
+
+	/* 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 = &dma_drain;
+	esp->dma_invalidate = 0;
+	esp->dma_irq_entry = 0;
+	esp->dma_irq_exit = 0;
+	esp->dma_poll = 0;
+	esp->dma_reset = 0;
+	esp->dma_led_off = 0;
+	esp->dma_led_on = 0;
+	
+	/* virtual DMA functions */
+	esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
+	esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
+		esp->dma_mmu_release_scsi_one = 0;
+		esp->dma_mmu_release_scsi_sgl = 0;
+	esp->dma_advance_sg = &dma_advance_sg;
+
+
+	/* SCSI chip speed */
+		esp->cfreq = 25000000;
+
+	/* 
+	 * we don't give the address of DMA channel, but the number
+	 * of DMA channel, so we can use the jazz DMA functions
+	 * 
+	 */
+	esp->dregs = JAZZ_SCSI_DMA;
+	
+	/* ESP register base */
+		esp->eregs = (struct ESP_regs *) (system_base + SCSI);
+	
+	/* Set the command buffer */
+		esp->esp_command = (volatile unsigned char *) cmd_buffer;
+	
+	/* get virtual dma address for command buffer */
+		esp->esp_command_dvma = KSEG1ADDR((volatile unsigned char *) cmd_buffer);
+	
+		esp->irq = SCSI_INT;
+	request_irq(esp->irq, esp_intr, SA_INTERRUPT, "NCR 53C94 SCSI",
+	            NULL);
+		request_irq(SCSI_DMA_INT, scsi_dma_int, SA_INTERRUPT, "JUNKIO SCSI DMA",
+			    NULL);
+
+	/*
+	 * FIXME, look if the scsi id is availabe from NVRAM
+	 */
+	esp->scsi_id = 7;
+		
+	/* Check for differential SCSI-bus */
+	/* What is this stuff? */
+	esp->diff = 0;
+
+	esp_initialize(esp);
+	
+		printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
+	esps_running = esps_in_use;
+	return esps_in_use;
+    }
+    return 0;
+}
+
+/************************************************************* DMA Functions */
+static void scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	extern volatile unsigned int *isr;
+	unsigned int dummy;
+
+	if (*isr & SCSI_PTR_LOADED) {
+		/* next page */
+		*scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3;
+		*isr &= ~SCSI_PTR_LOADED;
+	} else {
+		printk("Got unexpected SCSI DMA Interrupt! < ");
+		if (*isr & SCSI_PAGOVRRUN)
+			printk("SCSI_PAGOVRRUN ");
+		if (*isr & SCSI_DMA_MEMRDERR)
+			printk("SCSI_DMA_MEMRDERR ");
+		printk(">\n");
+//		panic("stop");
+		*isr &= ~(SCSI_PAGOVRRUN || SCSI_DMA_MEMRDERR);
+	}
+
+	/*
+	 * This driver will only work on IOASIC machines
+	 * so we can avoid an indirect function call here
+	 * and flush the writeback buffer the fast way
+	 */
+	dummy = *isr;
+	dummy = *isr;
+}
+
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+    return fifo_count;
+}
+
+static void dma_drain(struct NCR_ESP *esp)
+{
+	unsigned long nw;
+	unsigned short *p = KSEG1ADDR((unsigned short *) ((*scsi_dma_ptr) >> 3));
+
+    /*
+	 * Is there something in the dma buffers left?
+     */
+	if (nw = *scsi_scr) {
+		switch (nw) {
+		case 1:
+			*p = (unsigned short) *scsi_sdr0;
+			break;
+		case 2:
+			*p++ = (unsigned short) (*scsi_sdr0);
+			*p = (unsigned short) ((*scsi_sdr0) >> 16);
+			break;
+		case 3:
+			*p++ = (unsigned short) (*scsi_sdr0);
+			*p++ = (unsigned short) ((*scsi_sdr0) >> 16);
+			*p = (unsigned short) (*scsi_sdr1);
+			break;
+		default:
+			printk("Strange: %d words in dma buffer left\n", (int) nw);
+			break;
+		}
+	}
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+	return sp->SCp.this_residual;;
+}
+    
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+/*    
+    ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
+	    esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs)));
+ */
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	extern volatile unsigned int *isr;
+	unsigned int dummy;
+
+	if (vaddress & 3)
+		panic("dec_efs.c: unable to handle partial word transfers, yet...");
+
+	dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length);
+
+	*ioasic_ssr &= ~SCSI_DMA_EN;
+	*scsi_scr = 0;
+	*scsi_dma_ptr = vaddress << 3;
+
+	/* prepare for next page */
+	*scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
+	*ioasic_ssr |= (SCSI_DMA_DIR | SCSI_DMA_EN);
+
+	/*
+	 * see above
+	 */
+	dummy = *isr;
+	dummy = *isr;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+	extern volatile unsigned int *isr;
+	unsigned int dummy;
+
+	if (vaddress & 3)
+		panic("dec_efs.c: unable to handle partial word transfers, yet...");
+
+	dma_cache_wback_inv((unsigned long) phys_to_virt(vaddress), length);
+
+	*ioasic_ssr &= ~(SCSI_DMA_DIR | SCSI_DMA_EN);
+	*scsi_scr = 0;
+	*scsi_dma_ptr = vaddress << 3;
+
+	/* prepare for next page */
+	*scsi_next_ptr = ((vaddress + PAGE_SIZE) & PAGE_MASK) << 3;
+	*ioasic_ssr |= SCSI_DMA_EN;
+
+	/*
+	 * see above
+	 */
+	dummy = *isr;
+	dummy = *isr;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(SCSI_DMA_INT);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(SCSI_DMA_INT);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+    return (esp->eregs->esp_status & ESP_STAT_INTR);
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+/*
+ * FIXME: what's this good for?
+ */
+	return 1;
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+    /* 
+     * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
+     * so when (write) is true, it actually means READ!
+     */
+	if (write) {
+	dma_init_read(esp, addr, count);
+    } else {
+	dma_init_write(esp, addr, count);
+    }
+}
+
+/*
+ * These aren't used yet
+ */
+static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+	sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer);
+	sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in);
+}
+
+static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+    int sz = sp->SCp.buffers_residual;
+    struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
+    
+    while (sz >= 0) {
+		sg[sz].dvma_addr = PHYSADDR(sg[sz].addr);
+	sz--;
+    }
+	sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
+}
+
+static void dma_advance_sg(Scsi_Cmnd * sp)
+{    
+	sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/dec_esp.h linux.pre11.3/drivers/scsi/dec_esp.h
--- linux.vanilla/drivers/scsi/dec_esp.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/scsi/dec_esp.h	Mon Jul 19 23:28:06 1999
@@ -0,0 +1,42 @@
+/* dec_esp.h: Defines and structures for the JAZZ SCSI driver.
+ *
+ * DECstation changes Copyright (C) 1998 Harald Koerfgen
+ *
+ * based on jazz_esp.h:
+ * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#ifndef DEC_ESP_H
+#define DEC_ESP_H
+
+#define EREGS_PAD(n)     unchar n[3];
+
+#include "NCR53C9x.h"
+
+
+extern int dec_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);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+			 int hostno, int inout);
+
+#define SCSI_DEC_ESP {                                         \
+		proc_dir:       &proc_scsi_esp,			\
+		proc_info:      &esp_proc_info,			\
+		name:           "PMAZ-AA",			\
+		detect:         dec_esp_detect,			\
+		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, }
+
+#endif /* DEC_ESP_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/eata_dma.c linux.pre11.3/drivers/scsi/eata_dma.c
--- linux.vanilla/drivers/scsi/eata_dma.c	Thu Dec 31 18:10:44 1998
+++ linux.pre11.3/drivers/scsi/eata_dma.c	Tue Jul 20 00:02:10 1999
@@ -31,6 +31,10 @@
  *             mike@i-Connect.Net                           *
  *	       neuffer@mail.uni-mainz.de	            *
  *							    *
+ *
+ * Changes:
+ * 	Marcelo Tosatti, Jul/8/99 : SMP fixes
+ *
  *  This program is free software; you can redistribute it  *
  *  and/or modify it under the terms of the GNU General	    *
  *  Public License as published by the Free Software	    *
@@ -777,7 +781,10 @@
 	       x, sp->pid);
 	DBG(DBG_ABNORM && DBG_DELAY, DELAY(1));
 
+
+	spin_lock_irqsave(&io_request_lock, flags);
 	sp->scsi_done(sp);
+	spin_unlock_irqrestore(&io_request_lock, flags);
     }
     
     HD(cmd)->state = FALSE;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/gdth_proc.c linux.pre11.3/drivers/scsi/gdth_proc.c
--- linux.vanilla/drivers/scsi/gdth_proc.c	Fri Apr 16 22:10:54 1999
+++ linux.pre11.3/drivers/scsi/gdth_proc.c	Tue Jul 20 00:02:18 1999
@@ -3,6 +3,7 @@
  */
 
 #include "gdth_ioctl.h"
+#include <linux/version.h>
 
 int gdth_proc_info(char *buffer,char **start,off_t offset,int length,   
                    int hostno,int inout)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/ide-scsi.c linux.pre11.3/drivers/scsi/ide-scsi.c
--- linux.vanilla/drivers/scsi/ide-scsi.c	Wed Apr 28 19:14:28 1999
+++ linux.pre11.3/drivers/scsi/ide-scsi.c	Tue Jul 20 00:02:57 1999
@@ -1,7 +1,7 @@
 /*
- * linux/drivers/scsi/ide-scsi.c	Version 0.6		Jan  27, 1998
+ * linux/drivers/scsi/ide-scsi.c	Version 0.9		Jul   4, 1999
  *
- * Copyright (C) 1996 - 1998 Gadi Oxman <gadio@netvision.net.il>
+ * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
  */
 
 /*
@@ -25,10 +25,11 @@
  *                       Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
  * Ver 0.7   Dec 04 98   Ignore commands where lun != 0 to avoid multiple
  *                        detection of devices with CONFIG_SCSI_MULTI_LUN
- * Ver 0.8   Feb 05 99   Optical media need translation too. 
+ * Ver 0.8   Feb 05 99   Optical media need translation too. Reverse 0.7.
+ * Ver 0.9   Jul 04 99   Fix a bug in SG_SET_TRANSFORM.
  */
 
-#define IDESCSI_VERSION "0.6"
+#define IDESCSI_VERSION "0.9"
 
 #include <linux/module.h>
 #include <linux/types.h>
@@ -632,9 +633,13 @@
 {
 	ide_drive_t *drive = idescsi_drives[dev->id];
 	idescsi_scsi_t *scsi = drive->driver_data;
+	int enable = (int) arg;
 
 	if (cmd == SG_SET_TRANSFORM) {
-		set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
+		if (enable)
+			set_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
+		else
+			clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
 		return 0;
 	} else if (cmd == SG_GET_TRANSFORM)
 		return put_user(test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform), (int *) arg);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/in2000.h linux.pre11.3/drivers/scsi/in2000.h
--- linux.vanilla/drivers/scsi/in2000.h	Sun Nov  8 15:07:50 1998
+++ linux.pre11.3/drivers/scsi/in2000.h	Tue Jul 20 01:43:00 1999
@@ -67,7 +67,7 @@
    orl %%ecx, %%ecx       \n \
    jz 1f                  \n \
    rep                    \n \
-   insw %%dx              \n \
+   insw (%%dx),%%es:(%%edi) \n \
 1: "                       \
    : "=D" (sp)                   /* output */   \
    : "d" (f), "D" (sp), "c" (i)  /* input */    \
@@ -79,7 +79,7 @@
    orl %%ecx, %%ecx       \n \
    jz 1f                  \n \
    rep                    \n \
-   outsw %%dx             \n \
+   outsw %%ds:(%%esi),(%%dx) \n \
 1: "                       \
    : "=S" (sp)                   /* output */   \
    : "d" (f), "S" (sp), "c" (i)  /* input */    \
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/jazz_esp.c linux.pre11.3/drivers/scsi/jazz_esp.c
--- linux.vanilla/drivers/scsi/jazz_esp.c	Sun Nov  8 15:08:00 1998
+++ linux.pre11.3/drivers/scsi/jazz_esp.c	Mon Jul 19 23:28:05 1999
@@ -1,7 +1,7 @@
 /*
  * jazz_esp.c: Driver for SCSI chip on Mips Magnum Boards (JAZZ architecture)
  *
- * Copyright (C) 1997 Thomas Boegndoerfer (tsbogend@alpha.franken.de)
+ * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
  *
  * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
  */
@@ -161,7 +161,7 @@
 {
     
     ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
-	    esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs)));
+	    esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_residue((int)esp->dregs)));
 }
 
 static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/megaraid.c linux.pre11.3/drivers/scsi/megaraid.c
--- linux.vanilla/drivers/scsi/megaraid.c	Thu May 27 22:11:56 1999
+++ linux.pre11.3/drivers/scsi/megaraid.c	Tue Jul 20 00:03:10 1999
@@ -9,14 +9,14 @@
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Version : 1.00
+ * Version : 1.01
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
  * Supported controllers: MegaRAID 418, 428, 438, 466, 762
  * 
  * Maintainer: Jeff L Jones <jeffreyj@ami.com>
- *
+ *             Xi Shine Chen <xic@ami.com>
  * History:
  *
  * Version 0.90:
@@ -38,10 +38,10 @@
  *     Removed setting of SA_INTERRUPT flag when requesting Irq.
  *
  * Version 0.92ac:
- *      Small changes to the comments/formatting. Plus a couple of
+ *     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>
+ *     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>                          
@@ -73,14 +73,15 @@
  *
  * Version 0.96:
  *     762 fully supported.
+ *
  * Version 0.97:
  *     Changed megaraid_command to use wait_queue.
  *     Fixed bug of undesirably detecting HP onboard controllers which
- *      are disabled.
+ *       are disabled.
  *     
  * Version 1.00:
  *     Checks to see if an irq ocurred while in isr, and runs through
- *        routine again.
+ *       routine again.
  *     Copies mailbox to temp area before processing in isr
  *     Added barrier() in busy wait to fix volatility bug
  *     Uses separate list for freed Scbs, keeps track of cmd state
@@ -88,6 +89,11 @@
  *     Full multi-io commands working stablely without previous problems
  *     Added skipXX LILO option for Madrona motherboard support
  *
+ * Version 1.01:
+ *     Fixed bug in mega_cmd_done() for megamgr control commands,
+ *       the host_byte in the result code from the scsi request to 
+ *       scsi midlayer is set to DID_BAD_TARGET when adapter's 
+ *       returned codes are 0xF0 and oxF4.  
  *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
@@ -100,6 +106,7 @@
 
 #define CRLFSTR "\n"
 
+#include <linux/config.h>
 #include <linux/version.h>
 
 #ifdef MODULE
@@ -132,6 +139,7 @@
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/malloc.h>	/* for kmalloc() */
+#include <linux/config.h>	/* for CONFIG_PCI */
 #if LINUX_VERSION_CODE < 0x20100
 #include <linux/bios32.h>
 #else
@@ -482,6 +490,8 @@
 {
   int islogical;
   Scsi_Cmnd *SCpnt;
+  mega_passthru *pthru;
+  mega_mailbox *mbox;
 
   if (pScb == NULL) {
 	TRACE(("NULL pScb in mega_cmd_done!"));
@@ -489,7 +499,9 @@
   }
 
   SCpnt = pScb->SCpnt;
-  freeSCB(megaCfg, pScb);
+  /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
+  pthru = &pScb->pthru;
+  mbox = (mega_mailbox *) &pScb->mboxData;
 
   if (SCpnt == NULL) {
 	TRACE(("NULL SCpnt in mega_cmd_done!"));
@@ -507,23 +519,48 @@
       !islogical) {
     status = 0xF0;
   }
- 
-  SCpnt->result = 0;  /* clear result; otherwise, success returns corrupt
-                         value */
 
+/* clear result; otherwise, success returns corrupt value */ 
+ SCpnt->result = 0;  
+
+if (SCpnt->cmnd[0] & 0x80)	/* ioctl from megamgr */{
+    /*printk(KERN_WARNING "***megamgr cmnd status= %x h\n ", status); */
+    switch (status) {
+      case 0xF0:
+      case 0xF4:
+	SCpnt->result=(DID_BAD_TARGET<<16)|status;
+        break;
+      default:
+	SCpnt->result|=status;
+   }/*end of switch*/
+}
+else{
   /* Convert MegaRAID status to Linux error code */
   switch (status) {
-  case 0x00: /* SUCCESS */
-  case 0x02: /* ERROR_ABORTED */
+  case 0x00: /* SUCCESS , i.e. SCSI_STATUS_GOOD*/
     SCpnt->result |= (DID_OK << 16);
     break;
-  case 0x8:  /* ERR_DEST_DRIVE_FAILED */
-    SCpnt->result |= (DID_BUS_BUSY << 16);
+  case 0x02: /* ERROR_ABORTED, i.e. SCSI_STATUS_CHECK_CONDITION */
+	/*set sense_buffer and result fields*/
+       if( mbox->cmd==MEGA_MBOXCMD_PASSTHRU ){
+	  memcpy( SCpnt->sense_buffer , pthru->reqsensearea, 14);
+          SCpnt->result = (DRIVER_SENSE<<24)|(DID_ERROR << 16)|status; 
+       }
+       else{
+ 	  SCpnt->sense_buffer[0]=0x70;
+	  SCpnt->sense_buffer[2]=ABORTED_COMMAND;
+          SCpnt->result |= (CHECK_CONDITION << 1);
+       }
+    break;
+  case 0x08:  /* ERR_DEST_DRIVE_FAILED, i.e. SCSI_STATUS_BUSY */
+    SCpnt->result |= (DID_BUS_BUSY << 16)|status;
     break;
-  default:
+  default: 
     SCpnt->result |= (DID_BAD_TARGET << 16);
     break;
   }
+ }
+  freeSCB(megaCfg, pScb);
 
   /* Add Scsi_Command to end of completed queue */
   ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
@@ -741,7 +778,6 @@
 
   if (data[0] == 0x03) {	/* passthrough command */
     unsigned char cdblen = data[2];
-
     pthru = &pScb->pthru;
     memset (pthru, 0, sizeof (mega_passthru));
     pthru->islogical = (data[cdblen+3] & 0x80) ? 1:0;
@@ -953,7 +989,7 @@
   u_char byte;
   u_long cmdDone;
   Scsi_Cmnd *SCpnt;
-  
+
   mboxData[0x1] = (pScb ? pScb->idx + 1: 0x0);   /* Set cmdid */
   mboxData[0xF] = 1;		/* Set busy */
 
@@ -963,6 +999,10 @@
   }
 #endif
 
+#if DEBUG
+  showMbox(pScb);
+#endif
+
   /* Wait until mailbox is free */
   while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox!!\n");
@@ -984,9 +1024,9 @@
     callDone(SCpnt);
     return 0;
   }
+
   pLastScb = pScb;
 
-  
   /* Copy mailbox data into host structure */
   memcpy (mbox, mboxData, 16);
 
@@ -995,7 +1035,7 @@
 
     /* Issue interrupt (non-blocking) command */
     if (megaCfg->flag & BOARD_QUARTZ) {
-      mbox->mraid_poll = 0;
+       mbox->mraid_poll = 0;
       mbox->mraid_ack = 0;
       WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x1);
     }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/megaraid.h linux.pre11.3/drivers/scsi/megaraid.h
--- linux.vanilla/drivers/scsi/megaraid.h	Thu May 27 22:11:56 1999
+++ linux.pre11.3/drivers/scsi/megaraid.h	Tue Jul 20 01:43:01 1999
@@ -1,6 +1,6 @@
 #ifndef __MEGARAID_H__
 #define __MEGARAID_H__
-
+ 
 #ifndef LINUX_VERSION_CODE
 #include <linux/version.h>
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/ncr53c8xx.c linux.pre11.3/drivers/scsi/ncr53c8xx.c
--- linux.vanilla/drivers/scsi/ncr53c8xx.c	Fri Apr 16 22:10:54 1999
+++ linux.pre11.3/drivers/scsi/ncr53c8xx.c	Mon Jul 19 23:28:00 1999
@@ -5003,7 +5003,7 @@
 		**	Force ordered tag if necessary to avoid timeouts 
 		**	and to preserve interactivity.
 		*/
-		if (lp && lp->tags_stime + (3*HZ) <= jiffies) {
+		if (lp && time_before_eq(lp->tags_stime + 3*HZ, jiffies)) {
 			if (lp->tags_smap) {
 				order = M_ORDERED_TAG;
 				if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){ 
@@ -9850,7 +9850,8 @@
 		/* PCI_CACHE_LINE_SIZE value is in 32-bit words. */
 		cache_line_size = 64 / sizeof(u_int32);
 		if (initverbose >= 2)
-			printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n", cache_line_size);
+			printk("ncr53c8xx: setting PCI_CACHE_LINE_SIZE to %d (fixup)\n",
+			       cache_line_size);
 		pcibios_write_config_byte(bus, device_fn,
 					  PCI_CACHE_LINE_SIZE, cache_line_size);
 		pcibios_read_config_byte(bus, device_fn,
@@ -9858,7 +9859,7 @@
 	}
 
 	if (!latency_timer) {
-		latency_timer = 128;
+		latency_timer = 64;
 		if (initverbose >= 2)
 			printk("ncr53c8xx: setting PCI_LATENCY_TIMER to %d bus clocks (fixup)\n", latency_timer);
 		pcibios_write_config_byte(bus, device_fn,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc.c linux.pre11.3/drivers/scsi/qlogicfc.c
--- linux.vanilla/drivers/scsi/qlogicfc.c	Fri Apr 16 22:10:54 1999
+++ linux.pre11.3/drivers/scsi/qlogicfc.c	Tue Jul 20 00:03:25 1999
@@ -1,5 +1,5 @@
 /*
- * QLogic ISP2100 SCSI-FCP
+ * QLogic ISP2x00 SCSI-FCP
  * Written by Erik H. Moe, ehm@cris.com
  * Copyright 1995, Erik H. Moe
  *
@@ -17,7 +17,7 @@
 /* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
 
 /* This is a version of the isp1020 driver which was modified by
- * Chris Loveland <cwl@iol.unh.edu> to support the isp2100
+ * Chris Loveland <cwl@iol.unh.edu> to support the isp2100 and isp2200
  */
 
 /*
@@ -63,28 +63,30 @@
 
 /* Configuration section **************************************************** */
 
-/* Set the following macro to 1 to reload the ISP2100's firmware.  This is
-   version 1.15.19 of the firmware. */
+/* Set the following macro to 1 to reload the ISP2x00's firmware.  This is
+   version 1.15.37 of the isp2100's firmware and version 2.00.16 of the 
+   isp2200's firmware. 
+*/
 
 #define RELOAD_FIRMWARE		1
 
 #define USE_NVRAM_DEFAULTS      1
 
-#define ISP2100_PORTDB          1
+#define ISP2x00_PORTDB          1
 
 /* Set the following to 1 to include fabric support, fabric support is 
  * currently not as well tested as the other aspects of the driver */
 
-#define ISP2100_FABRIC          0
+#define ISP2x00_FABRIC          0
 
 /*  Macros used for debugging */
 /*
-#define DEBUG_ISP2100		1
-#define DEBUG_ISP2100_INT	1
-#define DEBUG_ISP2100_INTR	1
-#define DEBUG_ISP2100_SETUP	1
+#define DEBUG_ISP2x00		1
+#define DEBUG_ISP2x00_INT	1
+#define DEBUG_ISP2x00_INTR	1
+#define DEBUG_ISP2x00_SETUP	1
 
-#define DEBUG_ISP2100_FABRIC    1
+#define DEBUG_ISP2x00_FABRIC    1
 */
 /* #define TRACE_ISP             1 */
 
@@ -127,51 +129,49 @@
 #define TRACE(w, i, a)
 #endif
 
-#if DEBUG_ISP2100_FABRIC
+#if DEBUG_ISP2x00_FABRIC
 #define DEBUG_FABRIC(x)	x
 #else
 #define DEBUG_FABRIC(x)
-#endif				/* DEBUG_ISP2100_FABRIC */
+#endif				/* DEBUG_ISP2x00_FABRIC */
 
 
-#if DEBUG_ISP2100
-#define ENTER(x)	printk("isp2100 : entering %s()\n", x);
-#define LEAVE(x)	printk("isp2100 : leaving %s()\n", x);
+#if DEBUG_ISP2x00
+#define ENTER(x)	printk("isp2x00 : entering %s()\n", x);
+#define LEAVE(x)	printk("isp2x00 : leaving %s()\n", x);
 #define DEBUG(x)	x
 #else
 #define ENTER(x)
 #define LEAVE(x)
 #define DEBUG(x)
-#endif				/* DEBUG_ISP2100 */
+#endif				/* DEBUG_ISP2x00 */
 
-#if DEBUG_ISP2100_INTR
-#define ENTER_INTR(x)	printk("isp2100 : entering %s()\n", x);
-#define LEAVE_INTR(x)	printk("isp2100 : leaving %s()\n", x);
+#if DEBUG_ISP2x00_INTR
+#define ENTER_INTR(x)	printk("isp2x00 : entering %s()\n", x);
+#define LEAVE_INTR(x)	printk("isp2x00 : leaving %s()\n", x);
 #define DEBUG_INTR(x)	x
 #else
 #define ENTER_INTR(x)
 #define LEAVE_INTR(x)
 #define DEBUG_INTR(x)
-#endif				/* DEBUG ISP2100_INTR */
+#endif				/* DEBUG ISP2x00_INTR */
 
 
-#if defined(__i386__)
-#define virt_to_bus_low32(x)   virt_to_bus(x)
-#define virt_to_bus_high32(x)  0x0
-#define bus_to_virt_low32(x)   bus_to_virt(x)
-#define bus_to_virt_high32(x)  0x0
-#elif defined(__alpha__)
+#if BITS_PER_LONG > 32
 #define virt_to_bus_low32(x)   ((u32) (0xffffffff & virt_to_bus(x)))
 #define virt_to_bus_high32(x)  ((u32) (0xffffffff & (virt_to_bus(x)>>32)))
 #define bus_to_virt_low32(x)   ((u32) (0xffffffff & bus_to_virt(x)))
 #define bus_to_virt_high32(x)  ((u32) (0xffffffff & (bus_to_virt(x)>>32)))
+#else
+#define virt_to_bus_low32(x)   virt_to_bus(x)
+#define virt_to_bus_high32(x)  0x0
+#define bus_to_virt_low32(x)   bus_to_virt(x)
+#define bus_to_virt_high32(x)  0x0
 #endif
 
-#define ISP2100_REV_ID	1
+#define ISP2100_REV_ID1	       1
 #define ISP2100_REV_ID3        3
-
-#define MAX_TARGETS	16
-#define MAX_LUNS	8
+#define ISP2200_REV_ID5        5
 
 /* host configuration and control registers */
 #define HOST_HCCR	0xc0	/* host command and control */
@@ -219,6 +219,8 @@
 #define PORT_DB_CHANGED                 0x8014
 #define CHANGE_NOTIFICATION             0x8015
 #define SCSI_COMMAND_COMPLETE           0x8020
+#define POINT_TO_POINT_UP               0x8030
+#define CONNECTION_MODE                 0x8036
 
 struct Entry_header {
 	u_char entry_type;
@@ -228,19 +230,48 @@
 };
 
 /* entry header type commands */
+#if BITS_PER_LONG > 32
 #define ENTRY_COMMAND		0x19
 #define ENTRY_CONTINUATION	0x0a
+#else
+#define ENTRY_COMMAND		0x11
+#define ENTRY_CONTINUATION	0x02
+#endif
+
 #define ENTRY_STATUS		0x03
 #define ENTRY_MARKER		0x04
 
+
 /* entry header flag definitions */
 #define EFLAG_BUSY		2
 #define EFLAG_BAD_HEADER	4
 #define EFLAG_BAD_PAYLOAD	8
 
+#if BITS_PER_LONG > 32
+struct dataseg {
+	u_int d_base;
+	u_int d_base_hi;
+	u_int d_count;
+};
+
+struct Command_Entry {
+	struct Entry_header hdr;
+	u_int handle;
+	u_char target_lun;
+	u_char target_id;
+	u_short expanded_lun;
+	u_short control_flags;
+	u_short rsvd2;
+	u_short time_out;
+	u_short segment_cnt;
+	u_char cdb[16];
+	u_int total_byte_cnt;
+	struct dataseg dataseg[DATASEGS_PER_COMMAND];
+};
+
+#else
 struct dataseg {
-	u_int d_base_lo;
-	u_int d_base_high;
+	u_int d_base;
 	u_int d_count;
 };
 
@@ -249,16 +280,19 @@
 	u_int handle;
 	u_char target_lun;
 	u_char target_id;
-	u_short rsvd1;
+	u_short expanded_lun;
 	u_short control_flags;
 	u_short rsvd2;
 	u_short time_out;
 	u_short segment_cnt;
 	u_char cdb[16];
 	u_int total_byte_cnt;
-	struct dataseg dataseg[2];
+	struct dataseg dataseg[DATASEGS_PER_COMMAND];
 };
 
+#endif
+
+
 /* command entry control flag definitions */
 #define CFLAG_NODISC		0x01
 #define CFLAG_HEAD_TAG		0x02
@@ -268,23 +302,18 @@
 #define CFLAG_READ		0x20
 #define CFLAG_WRITE		0x40
 
-struct Ext_Command_Entry {
+#if BITS_PER_LONG > 32
+struct Continuation_Entry {
 	struct Entry_header hdr;
-	u_int handle;
-	u_char target_lun;
-	u_char target_id;
-	u_short cdb_length;
-	u_short control_flags;
-	u_short rsvd;
-	u_short time_out;
-	u_short segment_cnt;
-	u_char cdb[44];
+	struct dataseg dataseg[DATASEGS_PER_CONT];
 };
-
+#else
 struct Continuation_Entry {
 	struct Entry_header hdr;
-	struct dataseg dataseg[5];
+        u32 rsvd;
+	struct dataseg dataseg[DATASEGS_PER_CONT];
 };
+#endif
 
 struct Marker_Entry {
 	struct Entry_header hdr;
@@ -292,7 +321,7 @@
 	u_char target_lun;
 	u_char target_id;
 	u_char modifier;
-	u_char rsvd;
+	u_char expanded_lun;
 	u_char rsvds[52];
 };
 
@@ -549,7 +578,7 @@
 	u_int response_high;
 	u_short sub_len;
 	u_short res2;
-	u_short data[22];
+	u_char data[44];
 };
 
 /* address of instance of this struct is passed to adapter to initialize things
@@ -574,6 +603,17 @@
 	u_int req_queue_addr_high;
 	u_int res_queue_addr_lo;
 	u_int res_queue_addr_high;
+        /* the rest of this structure only applies to the isp2200 */
+        u_short lun_enables;
+        u_char cmd_resource_cnt;
+        u_char notify_resource_cnt;
+        u_short timeout;
+        u_short reserved3;
+        u_short add_firm_opts;
+        u_char res_accum_timer;
+        u_char irq_delay_timer;
+        u_short special_options;
+        u_short reserved4[13];
 };
 
 /*
@@ -583,16 +623,24 @@
 #define RES_QUEUE_LEN		((QLOGICFC_REQ_QUEUE_LEN + 1) / 8 - 1)
 #define QUEUE_ENTRY_LEN		64
 
-#if ISP2100_FABRIC
+#if ISP2x00_FABRIC
 #define QLOGICFC_MAX_ID    0xff
 #else
-#define QLOGICFC_MAX_ID    0x80
+#define QLOGICFC_MAX_ID    0x7d
 #endif
 
-struct isp2100_hostdata {
+#define QLOGICFC_MAX_LOOP_ID 0x7d
+
+/* adapter_state values */
+#define AS_FIRMWARE_DEAD      -1
+#define AS_LOOP_DOWN           0
+#define AS_LOOP_GOOD           1
+#define AS_REDO_PORTDB         2
+
+struct isp2x00_hostdata {
 	u_char revision;
 	struct pci_dev *pci_dev;
-	/* result and request queues (shared with isp2100): */
+	/* result and request queues (shared with isp2x00): */
 	u_int req_in_ptr;	/* index of next request slot */
 	u_int res_out_ptr;	/* index of next result slot */
 
@@ -602,7 +650,7 @@
 	char res[RES_QUEUE_LEN + 1][QUEUE_ENTRY_LEN];
 	char req[QLOGICFC_REQ_QUEUE_LEN + 1][QUEUE_ENTRY_LEN];
 	struct init_cb control_block;
-	int loop_up;
+	int adapter_state;
 	unsigned long int tag_ages[126];
 	Scsi_Cmnd *handle_ptrs[QLOGICFC_REQ_QUEUE_LEN + 1];
 	unsigned long handle_serials[QLOGICFC_REQ_QUEUE_LEN + 1];
@@ -611,6 +659,7 @@
 	u64 wwn;
 	u_int port_id;
 	u_char queued;
+	u_char host_id;
 };
 
 
@@ -620,177 +669,187 @@
 						    QLOGICFC_REQ_QUEUE_LEN)
 #define RES_QUEUE_DEPTH(in, out)	QUEUE_DEPTH(in, out, RES_QUEUE_LEN)
 
-static void isp2100_enable_irqs(struct Scsi_Host *);
-static void isp2100_disable_irqs(struct Scsi_Host *);
-static int isp2100_init(struct Scsi_Host *);
-static int isp2100_reset_hardware(struct Scsi_Host *);
-static int isp2100_mbox_command(struct Scsi_Host *, u_short[]);
-static int isp2100_return_status(struct Status_Entry *);
-static void isp2100_intr_handler(int, void *, struct pt_regs *);
-static void do_isp2100_intr_handler(int, void *, struct pt_regs *);
-static int isp2100_make_portdb(struct Scsi_Host *);
+static void isp2x00_enable_irqs(struct Scsi_Host *);
+static void isp2x00_disable_irqs(struct Scsi_Host *);
+static int isp2x00_init(struct Scsi_Host *);
+static int isp2x00_reset_hardware(struct Scsi_Host *);
+static int isp2x00_mbox_command(struct Scsi_Host *, u_short[]);
+static int isp2x00_return_status(struct Status_Entry *);
+static void isp2x00_intr_handler(int, void *, struct pt_regs *);
+static void do_isp2x00_intr_handler(int, void *, struct pt_regs *);
+static int isp2x00_make_portdb(struct Scsi_Host *);
 
-#if ISP2100_FABRIC
-static int isp2100_init_fabric(struct Scsi_Host *, struct id_name_map *, int);
+#if ISP2x00_FABRIC
+static int isp2x00_init_fabric(struct Scsi_Host *, struct id_name_map *, int);
 #endif
 
 #if USE_NVRAM_DEFAULTS
-static int isp2100_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);
-static u_short isp2100_read_nvram_word(struct Scsi_Host *, u_short);
+static int isp2x00_get_nvram_defaults(struct Scsi_Host *, struct init_cb *);
+static u_short isp2x00_read_nvram_word(struct Scsi_Host *, u_short);
 #endif
 
-#if DEBUG_ISP2100
-static void isp2100_print_scsi_cmd(Scsi_Cmnd *);
+#if DEBUG_ISP2x00
+static void isp2x00_print_scsi_cmd(Scsi_Cmnd *);
 #endif
 
-static void isp2100_print_status_entry(struct Status_Entry *);
+#if DEBUG_ISP2x00_INTR
+static void isp2x00_print_status_entry(struct Status_Entry *);
+#endif
 
-static struct proc_dir_entry proc_scsi_isp2100 =
+static struct proc_dir_entry proc_scsi_isp2x00 =
 {
-	PROC_SCSI_QLOGICFC, 7, "isp2100",
+	PROC_SCSI_QLOGICFC, 7, "isp2x00",
 	S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
 
-static inline void isp2100_enable_irqs(struct Scsi_Host *host)
+static inline void isp2x00_enable_irqs(struct Scsi_Host *host)
 {
 	outw(ISP_EN_INT | ISP_EN_RISC, host->io_port + PCI_INTER_CTL);
 }
 
 
-static inline void isp2100_disable_irqs(struct Scsi_Host *host)
+static inline void isp2x00_disable_irqs(struct Scsi_Host *host)
 {
 	outw(0x0, host->io_port + PCI_INTER_CTL);
 }
 
 
-int isp2100_detect(Scsi_Host_Template * tmpt)
+int isp2x00_detect(Scsi_Host_Template * tmpt)
 {
 	int hosts = 0;
 	int wait_time;
 	struct Scsi_Host *host = NULL;
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 	struct pci_dev *pdev = NULL;
+	unsigned short device_ids[2];
+	int i;
 
-	ENTER("isp2100_detect");
 
-	tmpt->proc_dir = &proc_scsi_isp2100;
+	ENTER("isp2x00_detect");
+
+       	device_ids[0] = PCI_DEVICE_ID_QLOGIC_ISP2100;
+	device_ids[1] = PCI_DEVICE_ID_QLOGIC_ISP2200;
+
+	tmpt->proc_dir = &proc_scsi_isp2x00;
 
 	if (pci_present() == 0) {
 		printk("qlogicfc : PCI not present\n");
 		return 0;
 	}
-	while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, pdev))) {
 
-		host = scsi_register(tmpt, sizeof(struct isp2100_hostdata));
-		host->max_id = QLOGICFC_MAX_ID + 1;
-		host->hostt->use_new_eh_code = 1;
-		hostdata = (struct isp2100_hostdata *) host->hostdata;
-
-		memset(hostdata, 0, sizeof(struct isp2100_hostdata));
-		hostdata->pci_dev = pdev;
-
-		hostdata->queued = 0;
-		/* set up the control block */
-		hostdata->control_block.version = 0x0f;
-		hostdata->control_block.firm_opts = 0x010c;
-		hostdata->control_block.max_frame_len = 2048;
-		hostdata->control_block.max_iocb = 256;
-		hostdata->control_block.exec_throttle = 8;
-		hostdata->control_block.retry_delay = 5;
-		hostdata->control_block.retry_cnt = 0;
-		hostdata->control_block.node_name[0] = 0x0020;
-		hostdata->control_block.node_name[1] = 0xE000;
-		hostdata->control_block.node_name[2] = 0x008B;
-		hostdata->control_block.node_name[3] = 0x0000;
-		hostdata->control_block.hard_addr = 0x0003;
-		hostdata->control_block.req_queue_len = QLOGICFC_REQ_QUEUE_LEN + 1;
-		hostdata->control_block.res_queue_len = RES_QUEUE_LEN + 1;
-		hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(&hostdata->res);
-		hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(&hostdata->res);
-		hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(&hostdata->req);
-		hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(&hostdata->req);
-
-		hostdata->loop_up = 0;
-
-		if (isp2100_init(host) || isp2100_reset_hardware(host)) {
-			scsi_unregister(host);
-			continue;
-		}
-		host->this_id = 0;
+	for (i=0; i<2; i++){
+	        while ((pdev = pci_find_device(PCI_VENDOR_ID_QLOGIC, device_ids[i], pdev))) {
 
-		if (request_irq(host->irq, do_isp2100_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
-			printk("qlogicfc : interrupt %d already in use\n",
-			       host->irq);
-			scsi_unregister(host);
-			continue;
-		}
-		if (check_region(host->io_port, 0xff)) {
-			printk("qlogicfc : i/o region 0x%lx-0x%lx already "
-			       "in use\n",
-			       host->io_port, host->io_port + 0xff);
-			free_irq(host->irq, host);
-			scsi_unregister(host);
-			continue;
-		}
-		request_region(host->io_port, 0xff, "qlogicfc");
+		        host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
+			host->max_id = QLOGICFC_MAX_ID + 1;
+			host->hostt->use_new_eh_code = 1;
+			hostdata = (struct isp2x00_hostdata *) host->hostdata;
+
+			memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
+			hostdata->pci_dev = pdev;
+
+			hostdata->queued = 0;
+			/* set up the control block */
+			hostdata->control_block.version = 0x1;
+			hostdata->control_block.firm_opts = 0x0108;
+			hostdata->control_block.max_frame_len = 2048;
+			hostdata->control_block.max_iocb = 256;
+			hostdata->control_block.exec_throttle = 8;
+			hostdata->control_block.retry_delay = 5;
+			hostdata->control_block.retry_cnt = 1;
+			hostdata->control_block.node_name[0] = 0x0020;
+			hostdata->control_block.node_name[1] = 0xE000;
+			hostdata->control_block.node_name[2] = 0x008B;
+			hostdata->control_block.node_name[3] = 0x0000;
+			hostdata->control_block.hard_addr = 0x0003;
+			hostdata->control_block.req_queue_len = QLOGICFC_REQ_QUEUE_LEN + 1;
+			hostdata->control_block.res_queue_len = RES_QUEUE_LEN + 1;
+			hostdata->control_block.res_queue_addr_lo = virt_to_bus_low32(&hostdata->res);
+			hostdata->control_block.res_queue_addr_high = virt_to_bus_high32(&hostdata->res);
+			hostdata->control_block.req_queue_addr_lo = virt_to_bus_low32(&hostdata->req);
+			hostdata->control_block.req_queue_addr_high = virt_to_bus_high32(&hostdata->req);
+
+
+			hostdata->adapter_state = AS_LOOP_DOWN;
+			hostdata->host_id = hosts;
+		
+			if (isp2x00_init(host) || isp2x00_reset_hardware(host)) {
+			        scsi_unregister(host);
+				continue;
+			}
+			host->this_id = 0;
 
-		outw(0x0, host->io_port + PCI_SEMAPHORE);
-		outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
-		isp2100_enable_irqs(host);
-		/* wait for the loop to come up */
-		for (wait_time = jiffies + 10 * HZ; wait_time > jiffies && hostdata->loop_up == 0;)
-			barrier();
+			if (request_irq(host->irq, do_isp2x00_intr_handler, SA_INTERRUPT | SA_SHIRQ, "qlogicfc", host)) {
+			        printk("qlogicfc%d : interrupt %d already in use\n",
+				       hostdata->host_id, host->irq);
+				scsi_unregister(host);
+				continue;
+			}
+			if (check_region(host->io_port, 0xff)) {
+			        printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "
+				       "in use\n",
+				       hostdata->host_id, host->io_port, host->io_port + 0xff);
+				free_irq(host->irq, host);
+				scsi_unregister(host);
+				continue;
+			}
+			request_region(host->io_port, 0xff, "qlogicfc");
 
-		if (hostdata->loop_up == 0) {
-			printk("qlogicfc: loop is not up\n");
-			release_region(host->io_port, 0xff);
-			free_irq(host->irq, host);
-			scsi_unregister(host);
-			continue;
+			outw(0x0, host->io_port + PCI_SEMAPHORE);
+			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
+			isp2x00_enable_irqs(host);
+			/* wait for the loop to come up */
+			for (wait_time = jiffies + 10 * HZ; wait_time > jiffies && hostdata->adapter_state == AS_LOOP_DOWN;)
+			        barrier();
+
+			if (hostdata->adapter_state == AS_LOOP_DOWN) {
+			        printk("qlogicfc%d : link is not up\n", hostdata->host_id);
+			}
+			hosts++;
 		}
-		hosts++;
 	}
 
 
-	/* this busy loop should not be needed but the isp2100 seems to need 
+	/* this busy loop should not be needed but the isp2x00 seems to need 
 	   some time before recognizing it is attached to a fabric */
 
-#if ISP2100_FABRIC
+#if ISP2x00_FABRIC
 	for (wait_time = jiffies + 5 * HZ; wait_time > jiffies;)
 		barrier();
 #endif
 
-	LEAVE("isp2100_detect");
+	LEAVE("isp2x00_detect");
 
 	return hosts;
 }
 
 
-static int isp2100_make_portdb(struct Scsi_Host *host)
+static int isp2x00_make_portdb(struct Scsi_Host *host)
 {
 
 	short param[8];
 	int i, j;
 	struct id_name_map temp[QLOGICFC_MAX_ID + 1];
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 
-	isp2100_disable_irqs(host);
+	isp2x00_disable_irqs(host);
 
 	memset(temp, 0, sizeof(temp));
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
-#if ISP2100_FABRIC
+#if ISP2x00_FABRIC
 	for (i = 0x81; i < QLOGICFC_MAX_ID; i++) {
 		param[0] = MBOX_PORT_LOGOUT;
 		param[1] = i << 8;
 		param[2] = 0;
 		param[3] = 0;
 
-		isp2100_mbox_command(host, param);
+		isp2x00_mbox_command(host, param);
 
 		if (param[0] != MBOX_COMMAND_COMPLETE) {
-			printk("logout failed %x  %x\n", i, param[0]);
+
+			DEBUG_FABRIC(printk("qlogicfc%d : logout failed %x  %x\n", hostdata->host_id, i, param[0]));
 		}
 	}
 #endif
@@ -798,7 +857,7 @@
 
 	param[0] = MBOX_GET_INIT_SCSI_ID;
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	if (param[0] == MBOX_COMMAND_COMPLETE) {
 		hostdata->port_id = ((u_int) param[3]) << 16;
@@ -807,16 +866,17 @@
 		temp[0].wwn = hostdata->wwn;
 	}
 	else {
-	        printk("qlogicfc: error getting scsi id.\n");
+	        printk("qlogicfc%d : error getting scsi id.\n", hostdata->host_id);
 	}
 
-	for (i = 1, j = 1; i <= QLOGICFC_MAX_ID; i++) {
-	        temp[i].loop_id = temp[0].loop_id;
-
-		param[0] = MBOX_GET_PORT_NAME;
+        for (i = 0; i <=QLOGICFC_MAX_ID; i++)
+                temp[i].loop_id = temp[0].loop_id;
+   
+        for (i = 0, j = 1; i <= QLOGICFC_MAX_LOOP_ID; i++) {
+                param[0] = MBOX_GET_PORT_NAME;
 		param[1] = (i << 8) & 0xff00;
 
-		isp2100_mbox_command(host, param);
+		isp2x00_mbox_command(host, param);
 
 		if (param[0] == MBOX_COMMAND_COMPLETE) {
 			temp[j].loop_id = i;
@@ -835,8 +895,8 @@
 	}
 
 
-#if ISP2100_FABRIC
-	isp2100_init_fabric(host, temp, j);
+#if ISP2x00_FABRIC
+	isp2x00_init_fabric(host, temp, j);
 #endif
 
 	for (i = 0; i <= QLOGICFC_MAX_ID; i++) {
@@ -856,7 +916,7 @@
 				}
 			}
 			if (j == QLOGICFC_MAX_ID + 1)
-				printk("qlogicfc.c: Too many scsi devices, no more room in port map.\n");
+				printk("qlogicfc%d : Too many scsi devices, no more room in port map.\n", hostdata->host_id);
 			if (!hostdata->port_db[j].wwn) {
 				hostdata->port_db[j].loop_id = temp[i].loop_id;
 				hostdata->port_db[j].wwn = temp[i].wwn;
@@ -866,42 +926,70 @@
 
 	}
 
-	isp2100_enable_irqs(host);
+	isp2x00_enable_irqs(host);
 
 	return 0;
 }
 
 
-#if ISP2100_FABRIC
+#if ISP2x00_FABRIC
+
+#define FABRIC_PORT          0x7e
+#define FABRIC_CONTROLLER    0x7f
+#define FABRIC_SNS           0x80
 
-int isp2100_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int j)
+int isp2x00_init_fabric(struct Scsi_Host *host, struct id_name_map *port_db, int cur_scsi_id)
 {
 
 	u_short param[8];
 	u64 wwn;
 	int done = 0;
 	u_short loop_id = 0x81;
-	u_short scsi_id = j;
+	u_short scsi_id = cur_scsi_id;
 	u_int port_id;
 	struct sns_cb req;
 	u_char sns_response[608];
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
-	DEBUG_FABRIC(printk("qlogicfc.c: Checking for a fabric.\n"));
+	DEBUG_FABRIC(printk("qlogicfc%d : Checking for a fabric.\n", hostdata->host_id));
 	param[0] = MBOX_GET_PORT_NAME;
-	param[1] = 0x7E00;
+	param[1] = (u16)FABRIC_PORT << 8;
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		DEBUG_FABRIC(printk("fabric check result %x\n", param[0]));
+		DEBUG_FABRIC(printk("qlogicfc%d : fabric check result %x\n", hostdata->host_id, param[0]));
 		return 0;
 	}
-	printk("qlogicfc.c: Fabric found.\n");
+	printk("qlogicfc%d : Fabric found.\n", hostdata->host_id);
 
 
+	memset(&req, 0, sizeof(req));
+	
+	req.len = 8;
+	req.response_low = virt_to_bus_low32(sns_response);
+	req.response_high = virt_to_bus_high32(sns_response);
+	req.sub_len = 22;
+	req.data[0] = 0x17;
+	req.data[1] = 0x02;
+	req.data[8] = (u_char) (hostdata->port_id & 0xff);
+	req.data[9] = (u_char) (hostdata->port_id >> 8 & 0xff);
+	req.data[10] = (u_char) (hostdata->port_id >> 16 & 0xff);
+	req.data[13] = 0x01;
+	param[0] = MBOX_SEND_SNS;
+	param[1] = 30;
+	param[2] = virt_to_bus_low32(&req) >> 16;
+	param[3] = virt_to_bus_low32(&req);
+	param[6] = virt_to_bus_high32(&req) >> 16;
+	param[7] = virt_to_bus_high32(&req);
+	
+	isp2x00_mbox_command(host, param);
+	
+	if (param[0] != MBOX_COMMAND_COMPLETE)
+	        printk("qlogicfc%d : error sending RFC-4\n", hostdata->host_id);	       
+
 	port_id = hostdata->port_id;
 	while (!done) {
 		memset(&req, 0, sizeof(req));
@@ -910,9 +998,11 @@
 		req.response_low = virt_to_bus_low32(sns_response);
 		req.response_high = virt_to_bus_high32(sns_response);
 		req.sub_len = 6;
-		req.data[0] = 0x0100;
-		req.data[4] = (u_short) (port_id & 0xffff);
-		req.data[5] = (u_short) (port_id >> 16 & 0xffff);
+		req.data[0] = 0x00;
+		req.data[1] = 0x01;
+		req.data[8] = (u_char) (port_id & 0xff);
+		req.data[9] = (u_char) (port_id >> 8 & 0xff);
+		req.data[10] = (u_char) (port_id >> 16 & 0xff);
 
 		param[0] = MBOX_SEND_SNS;
 		param[1] = 14;
@@ -921,10 +1011,10 @@
 		param[6] = virt_to_bus_high32(&req) >> 16;
 		param[7] = virt_to_bus_high32(&req);
 
-		isp2100_mbox_command(host, param);
+		isp2x00_mbox_command(host, param);
 
 		if (param[0] == MBOX_COMMAND_COMPLETE) {
-			DEBUG_FABRIC(printk("found node %02x%02x%02x%02x%02x%02x%02x%02x ", sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27]));
+			DEBUG_FABRIC(printk("qlogicfc%d : found node %02x%02x%02x%02x%02x%02x%02x%02x ", hostdata->host_id, sns_response[20], sns_response[21], sns_response[22], sns_response[23], sns_response[24], sns_response[25], sns_response[26], sns_response[27]));
 			DEBUG_FABRIC(printk("  port id: %02x%02x%02x\n", sns_response[17], sns_response[18], sns_response[19]));
 			port_id = ((u_int) sns_response[17]) << 16;
 			port_id |= ((u_int) sns_response[18]) << 8;
@@ -938,13 +1028,13 @@
 			wwn |= ((u64) sns_response[26]) << 8;
 			wwn |= ((u64) sns_response[27]);
 			if (hostdata->port_id >> 8 != port_id >> 8) {
-				DEBUG_FABRIC(printk("adding a fabric port: %x\n", port_id));
+				DEBUG_FABRIC(printk("qlogicfc%d : adding a fabric port: %x\n", hostdata->host_id, port_id));
 				param[0] = MBOX_PORT_LOGIN;
 				param[1] = loop_id << 8;
 				param[2] = (u_short) (port_id >> 16);
 				param[3] = (u_short) (port_id);
 
-				isp2100_mbox_command(host, param);
+				isp2x00_mbox_command(host, param);
 
 				if (param[0] == MBOX_COMMAND_COMPLETE) {
 					port_db[scsi_id].wwn = wwn;
@@ -952,15 +1042,22 @@
 					loop_id++;
 					scsi_id++;
 				} else {
-					printk("qlogicfc.c: Error performing port login %x\n", param[0]);
-					DEBUG_FABRIC(printk("loop_id: %x\n", loop_id));
+					printk("qlogicfc%d : Error performing port login %x\n", hostdata->host_id, param[0]);
+					DEBUG_FABRIC(printk("qlogicfc%d : loop_id: %x\n", hostdata->host_id, loop_id));
+					param[0] = MBOX_PORT_LOGOUT;
+					param[1] = loop_id << 8;
+					param[2] = 0;
+					param[3] = 0;
+
+					isp2x00_mbox_command(host, param);
+					
 				}
 
 			}
 			if (hostdata->port_id == port_id)
 				done = 1;
 		} else {
-			printk("qlogicfc.c: Get All Next failed %x.\n", param[0]);
+			printk("qlogicfc%d : Get All Next failed %x.\n", hostdata->host_id, param[0]);
 			return 0;
 		}
 	}
@@ -968,42 +1065,42 @@
 	return 1;
 }
 
-#endif				/* ISP2100_FABRIC */
+#endif				/* ISP2x00_FABRIC */
 
 
-int isp2100_release(struct Scsi_Host *host)
+int isp2x00_release(struct Scsi_Host *host)
 {
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 
-	ENTER("isp2100_release");
+	ENTER("isp2x00_release");
 
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
 	outw(0x0, host->io_port + PCI_INTER_CTL);
 	free_irq(host->irq, host);
 
 	release_region(host->io_port, 0xff);
 
-	LEAVE("isp2100_release");
+	LEAVE("isp2x00_release");
 
 	return 0;
 }
 
 
-const char *isp2100_info(struct Scsi_Host *host)
+const char *isp2x00_info(struct Scsi_Host *host)
 {
 	static char buf[80];
-	struct isp2100_hostdata *hostdata;
-	ENTER("isp2100_info");
+	struct isp2x00_hostdata *hostdata;
+	ENTER("isp2x00_info");
 
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 	sprintf(buf,
-		"QLogic ISP2100 SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
-		hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
+		"QLogic ISP%04x SCSI on PCI bus %02x device %02x irq %d base 0x%lx",
+		hostdata->pci_dev->device, hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq,
 		host->io_port);
 
 
-	LEAVE("isp2100_info");
+	LEAVE("isp2x00_info");
 
 	return buf;
 }
@@ -1015,7 +1112,7 @@
  * interrupt handler may call this routine as part of
  * request-completion handling).
  */
-int isp2100_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
+int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
 {
 	int i, sg_count, n, num_free;
 	u_int in_ptr, out_ptr;
@@ -1024,25 +1121,26 @@
 	struct Command_Entry *cmd;
 	struct Continuation_Entry *cont;
 	struct Scsi_Host *host;
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 
-	ENTER("isp2100_queuecommand");
+	ENTER("isp2x00_queuecommand");
 
 	host = Cmnd->host;
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 	Cmnd->scsi_done = done;
 
-	DEBUG(isp2100_print_scsi_cmd(Cmnd));
+	DEBUG(isp2x00_print_scsi_cmd(Cmnd));
 
-	if (hostdata->loop_up == 2) {
-		hostdata->loop_up = 1;
-		isp2100_make_portdb(host);
+	if (hostdata->adapter_state == AS_REDO_PORTDB) {
+		hostdata->adapter_state = AS_LOOP_GOOD;
+		isp2x00_make_portdb(host);
+		printk("qlogicfc%d : Port Database\n", hostdata->host_id);
 		for (i = 0; hostdata->port_db[i].wwn != 0; i++) {
-			DEBUG(printk("wwn: %08x%08x  scsi_id: %x  loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id));
+			printk("wwn: %08x%08x  scsi_id: %x  loop_id: %x\n", (u_int) (hostdata->port_db[i].wwn >> 32), (u_int) hostdata->port_db[i].wwn, i, hostdata->port_db[i].loop_id);
 		}
 	}
-	if (hostdata->loop_up == -1) {
-		printk("qlogicfc.c: The firmware is dead, just return.\n");
+	if (hostdata->adapter_state == AS_FIRMWARE_DEAD) {
+		printk("qlogicfc%d : The firmware is dead, just return.\n", hostdata->host_id);
 		host->max_id = 0;
 		return 0;
 	}
@@ -1050,13 +1148,13 @@
 	out_ptr = inw(host->io_port + MBOX4);
 	in_ptr = hostdata->req_in_ptr;
 
-	DEBUG(printk("qlogicfc : request queue depth %d\n",
+	DEBUG(printk("qlogicfc%d : request queue depth %d\n", hostdata->host_id,
 		     REQ_QUEUE_DEPTH(in_ptr, out_ptr)));
 
 	cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
 	in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
 	if (in_ptr == out_ptr) {
-		DEBUG(printk("qlogicfc : request queue overflow\n"));
+		DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
 		return 1;
 	}
 	if (hostdata->send_marker) {
@@ -1064,7 +1162,7 @@
 
 		TRACE("queue marker", in_ptr, 0);
 
-		DEBUG(printk("qlogicfc : adding marker entry\n"));
+		DEBUG(printk("qlogicfc%d : adding marker entry\n", hostdata->host_id));
 		marker = (struct Marker_Entry *) cmd;
 		memset(marker, 0, sizeof(struct Marker_Entry));
 
@@ -1077,7 +1175,7 @@
 		if (((in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN) == out_ptr) {
 			outw(in_ptr, host->io_port + MBOX4);
 			hostdata->req_in_ptr = in_ptr;
-			DEBUG(printk("qlogicfc : request queue overflow\n"));
+			DEBUG(printk("qlogicfc%d : request queue overflow\n", hostdata->host_id));
 			return 1;
 		}
 		cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0];
@@ -1094,19 +1192,27 @@
 		cmd->handle = i;
 		hostdata->handle_ptrs[i] = Cmnd;
 		hostdata->handle_serials[i] = Cmnd->serial_number;
-	} else
-		printk("qlogicfc: no handle slots, this should not happen.\n");
+	} else {
+		printk("qlogicfc%d : no handle slots, this should not happen.\n", hostdata->host_id);
+		printk("hostdata->queued is %x, in_ptr: %x\n", hostdata->queued, in_ptr);
+		for (i = 0; i <= QLOGICFC_REQ_QUEUE_LEN; i++){
+			if (!hostdata->handle_ptrs[i]){
+				printk("slot %d has %p\n", i, hostdata->handle_ptrs[i]);
+			}
+		}
+	}
 
 	cmd->hdr.entry_type = ENTRY_COMMAND;
 	cmd->hdr.entry_cnt = 1;
 	cmd->target_lun = Cmnd->lun;
-#if ISP2100_PORTDB
+	cmd->expanded_lun = Cmnd->lun;
+#if ISP2x00_PORTDB
 	cmd->target_id = hostdata->port_db[Cmnd->target].loop_id;
 #else
 	cmd->target_id = Cmnd->target;
 #endif
 	cmd->total_byte_cnt = (u_int) Cmnd->request_bufflen;
-	cmd->time_out = (SCSI_TIMEOUT / HZ) * 5;
+	cmd->time_out = 0;
 	memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len);
 
 	if (Cmnd->use_sg) {
@@ -1115,15 +1221,18 @@
 		ds = cmd->dataseg;
 		/* fill in first two sg entries: */
 		n = sg_count;
-		if (n > 2)
-			n = 2;
+		if (n > DATASEGS_PER_COMMAND)
+			n = DATASEGS_PER_COMMAND;
+
 		for (i = 0; i < n; i++) {
-			ds[i].d_base_lo = virt_to_bus_low32(sg->address);
-			ds[i].d_base_high = virt_to_bus_high32(sg->address);
+			ds[i].d_base = virt_to_bus_low32(sg->address);
+#if BITS_PER_LONG > 32
+			ds[i].d_base_hi = virt_to_bus_high32(sg->address);
+#endif
 			ds[i].d_count = sg->length;
 			++sg;
 		}
-		sg_count -= 2;
+		sg_count -= DATASEGS_PER_COMMAND;
 
 		while (sg_count > 0) {
 			++cmd->hdr.entry_cnt;
@@ -1132,28 +1241,31 @@
 			memset(cont, 0, sizeof(struct Continuation_Entry));
 			in_ptr = (in_ptr + 1) & QLOGICFC_REQ_QUEUE_LEN;
 			if (in_ptr == out_ptr) {
-				DEBUG(printk("isp2100: unexpected request queue overflow\n"));
+				DEBUG(printk("qlogicfc%d : unexpected request queue overflow\n", hostdata->host_id));
 				return 1;
 			}
 			TRACE("queue continuation", in_ptr, 0);
 			cont->hdr.entry_type = ENTRY_CONTINUATION;
 			ds = cont->dataseg;
 			n = sg_count;
-			if (n > 5)
-				n = 5;
+			if (n > DATASEGS_PER_CONT)
+				n = DATASEGS_PER_CONT;
 			for (i = 0; i < n; ++i) {
-				ds[i].d_base_lo = virt_to_bus_low32(sg->address);
-				ds[i].d_base_high = virt_to_bus_high32(sg->address);
+				ds[i].d_base = virt_to_bus_low32(sg->address);
+#if BITS_PER_LONG > 32
+				ds[i].d_base_hi = virt_to_bus_high32(sg->address);
+#endif
 				ds[i].d_count = sg->length;
 				++sg;
 			}
 			sg_count -= n;
 		}
 	} else {
-		cmd->dataseg[0].d_base_lo = virt_to_bus_low32(Cmnd->request_buffer);
-		cmd->dataseg[0].d_base_high = virt_to_bus_high32(Cmnd->request_buffer);
-		cmd->dataseg[0].d_count =
-		    (u_int) Cmnd->request_bufflen;
+		cmd->dataseg[0].d_base = virt_to_bus_low32(Cmnd->request_buffer);
+#if BITS_PER_LONG > 32
+		cmd->dataseg[0].d_base_hi = virt_to_bus_high32(Cmnd->request_buffer);
+#endif
+		cmd->dataseg[0].d_count = (u_int) Cmnd->request_bufflen;
 		cmd->segment_cnt = 1;
 	}
 
@@ -1161,12 +1273,15 @@
 	case WRITE_10:
 	case WRITE_6:
 	case WRITE_BUFFER:
+	case MODE_SELECT:
 		cmd->control_flags = CFLAG_WRITE;
 		break;
 	case REQUEST_SENSE:
 		/* scsi.c expects sense info in a different buffer */
-		cmd->dataseg[0].d_base_lo = virt_to_bus_low32(Cmnd->sense_buffer);
-		cmd->dataseg[0].d_base_high = virt_to_bus_high32(Cmnd->sense_buffer);
+		cmd->dataseg[0].d_base = virt_to_bus_low32(Cmnd->sense_buffer);
+#if BITS_PER_LONG > 32
+		cmd->dataseg[0].d_base_hi = virt_to_bus_high32(Cmnd->request_buffer);
+#endif
 		cmd->segment_cnt = 1;
 		cmd->control_flags = CFLAG_READ;
 		break;
@@ -1197,6 +1312,7 @@
 	hostdata->req_in_ptr = in_ptr;
 
 	hostdata->queued++;
+
 	num_free = QLOGICFC_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr);
 	num_free = (num_free > 2) ? num_free - 2 : 0;
 	host->can_queue = hostdata->queued + num_free;
@@ -1207,11 +1323,11 @@
 	/* this is really gross */
 	if (host->can_queue <= host->host_busy){
 	        if (host->can_queue+2 < host->host_busy) 
-			DEBUG(printk("qlogicfc.c crosses its fingers.\n"));
+			DEBUG(printk("qlogicfc%d.c crosses its fingers.\n", hostdata->host_id));
 		host->can_queue = host->host_busy + 1;
 	}
 
-	LEAVE("isp2100_queuecommand");
+	LEAVE("isp2x00_queuecommand");
 
 	return 0;
 }
@@ -1220,33 +1336,33 @@
 #define ASYNC_EVENT_INTERRUPT	0x01
 
 
-void do_isp2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+void do_isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&io_request_lock, flags);
-	isp2100_intr_handler(irq, dev_id, regs);
+	isp2x00_intr_handler(irq, dev_id, regs);
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
-void isp2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	Scsi_Cmnd *Cmnd;
 	struct Status_Entry *sts;
 	struct Scsi_Host *host = dev_id;
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 	u_int in_ptr, out_ptr, handle, num_free;
 	u_short status;
 
-	ENTER_INTR("isp2100_intr_handler");
+	ENTER_INTR("isp2x00_intr_handler");
 
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
-	DEBUG_INTR(printk("qlogicfc : interrupt on line %d\n", irq));
+	DEBUG_INTR(printk("qlogicfc%d : interrupt on line %d\n", hostdata->host_id, irq));
 
 	if (!(inw(host->io_port + PCI_INTER_STS) & 0x08)) {
 		/* spurious interrupts can happen legally */
-		DEBUG_INTR(printk("qlogicfc: got spurious interrupt\n"));
+		DEBUG_INTR(printk("qlogicfc%d : got spurious interrupt\n", hostdata->host_id));
 		return;
 	}
 	in_ptr = inw(host->io_port + MBOX5);
@@ -1255,26 +1371,32 @@
 	if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) {
 		status = inw(host->io_port + MBOX0);
 
-		DEBUG_INTR(printk("qlogicfc : mbox completion status: %x\n",
-				  status));
+		DEBUG_INTR(printk("qlogicfc%d : mbox completion status: %x\n",
+				  hostdata->host_id, status));
 
 		switch (status) {
 		case LOOP_UP:
-			hostdata->loop_up = 2;
+		case POINT_TO_POINT_UP:
+		        printk("qlogicfc%d : link is up\n", hostdata->host_id);
+			hostdata->adapter_state = AS_REDO_PORTDB;
 			break;
 		case LOOP_DOWN:
-			hostdata->loop_up = 0;
+		        printk("qlogicfc%d : link is down\n", hostdata->host_id);
+			hostdata->adapter_state = AS_LOOP_DOWN;
+			break;
+		case CONNECTION_MODE:
+		        printk("received CONNECTION_MODE irq %x\n", inw(host->io_port + MBOX1));
 			break;
 		case LIP_OCCURED:
 		case CHANGE_NOTIFICATION:
 		case PORT_DB_CHANGED:
 		case LIP_RECEIVED:
-			if (hostdata->loop_up == 1)
-				hostdata->loop_up = 2;
+			if (hostdata->adapter_state == AS_LOOP_GOOD)
+				hostdata->adapter_state = AS_REDO_PORTDB;
 			break;
 		case SYSTEM_ERROR:
-			printk("The firmware just choked.\n");
-			hostdata->loop_up = -1;
+			printk("qlogicfc%d : The firmware just choked.\n", hostdata->host_id);
+			hostdata->adapter_state = AS_FIRMWARE_DEAD;
 			break;
 		case SCSI_COMMAND_COMPLETE:
 			handle = inw(host->io_port + MBOX1) | (inw(host->io_port + MBOX2) << 16);
@@ -1286,7 +1408,7 @@
 				Cmnd->result = 0x0;
 				(*Cmnd->scsi_done) (Cmnd);
 			} else
-				printk("qlogicfc.c: got a null value out of handle_ptrs, this sucks\n");
+				printk("qlogicfc%d.c : got a null value out of handle_ptrs, this sucks\n", hostdata->host_id);
 			break;
 		case MBOX_COMMAND_COMPLETE:
 		case INVALID_COMMAND:
@@ -1301,37 +1423,54 @@
 			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
 			return;
 		default:
-			printk("qlogicfc: got an unknown status? %x\n", status);
+			printk("qlogicfc%d : got an unknown status? %x\n", hostdata->host_id, status);
 		}
 		outw(0x0, host->io_port + PCI_SEMAPHORE);
 	} else {
-		DEBUG_INTR(printk("qlogicfc : response queue update\n"));
-		DEBUG_INTR(printk("qlogicfc : response queue depth %d\n", RES_QUEUE_DEPTH(in_ptr, out_ptr)));
+		DEBUG_INTR(printk("qlogicfc%d : response queue update\n", hostdata->host_id));
+		DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));
 
 		while (out_ptr != in_ptr) {
 			sts = (struct Status_Entry *) &hostdata->res[out_ptr][0];
 			out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
                  
 			TRACE("done", out_ptr, Cmnd);
-			DEBUG_INTR(isp2100_print_status_entry(sts));
-			if (sts->hdr.entry_type == ENTRY_STATUS) {
-				Cmnd = hostdata->handle_ptrs[sts->handle];
-				Cmnd->result = isp2100_return_status(sts);
+			DEBUG_INTR(isp2x00_print_status_entry(sts));
+			if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[sts->handle])) {
+				Cmnd->result = isp2x00_return_status(sts);
 				hostdata->handle_ptrs[sts->handle] = NULL;
 				hostdata->queued--;
-				if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number) {
+
+				/* 
+				 * if any of the following are true we do not
+				 * call scsi_done.  if the status is CS_ABORTED
+				 * we dont have to call done because the upper
+				 * level should already know its aborted.
+				 */
+				if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number 
+				    || sts->completion_status == CS_ABORTED){
 					hostdata->handle_serials[sts->handle] = 0;
 					outw(out_ptr, host->io_port + MBOX5);
 					continue;
 				}
-				hostdata->handle_serials[sts->handle] = 0;
+				/*
+				 * if we get back an error indicating the port
+				 * is not there or if the link is down and 
+				 * this is a device that used to be there 
+				 * allow the command to timeout.
+				 * the device may well be back in a couple of
+				 * seconds.
+				 */
+				if ((hostdata->adapter_state == AS_LOOP_DOWN || sts->completion_status == CS_PORT_UNAVAILABLE || sts->completion_status == CS_PORT_LOGGED_OUT || sts->completion_status == CS_PORT_CONFIG_CHANGED) && hostdata->port_db[Cmnd->target].wwn){
+					outw(out_ptr, host->io_port + MBOX5);
+					continue;
+				}
 			} else {
 				outw(out_ptr, host->io_port + MBOX5);
 				continue;
 			}
 
 			if (sts->completion_status == CS_RESET_OCCURRED
-			    || sts->completion_status == CS_ABORTED
 			    || (sts->status_flags & STF_BUS_RESET))
 				hostdata->send_marker = 1;
 
@@ -1345,7 +1484,7 @@
 			if (Cmnd->scsi_done != NULL) {
 				(*Cmnd->scsi_done) (Cmnd);
 			} else
-				printk("Ouch, scsi done is NULL\n");
+				printk("qlogicfc%d : Ouch, scsi done is NULL\n", hostdata->host_id);
 		}
 		hostdata->res_out_ptr = out_ptr;
 	}
@@ -1363,19 +1502,19 @@
 
 	if (host->can_queue <= host->host_busy){
 	        if (host->can_queue+2 < host->host_busy) 
-		        DEBUG(printk("qlogicfc crosses its fingers.\n"));
+		        DEBUG(printk("qlogicfc%d : crosses its fingers.\n", hostdata->host_id));
 		host->can_queue = host->host_busy + 1;
 	}
 
 	outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
-	LEAVE_INTR("isp2100_intr_handler");
+	LEAVE_INTR("isp2x00_intr_handler");
 }
 
 
-static int isp2100_return_status(struct Status_Entry *sts)
+static int isp2x00_return_status(struct Status_Entry *sts)
 {
 	int host_status = DID_ERROR;
-#if DEBUG_ISP2100_INTR
+#if DEBUG_ISP2x00_INTR
 	static char *reason[] =
 	{
 		"DID_OK",
@@ -1389,9 +1528,9 @@
 		"DID_RESET",
 		"DID_BAD_INTR"
 	};
-#endif				/* DEBUG_ISP2100_INTR */
+#endif				/* DEBUG_ISP2x00_INTR */
 
-	ENTER("isp2100_return_status");
+	ENTER("isp2x00_return_status");
 
 	DEBUG(printk("qlogicfc : completion status = 0x%04x\n",
 		     sts->completion_status));
@@ -1436,93 +1575,105 @@
 	DEBUG_INTR(printk("qlogicfc : host status (%s) scsi status %x\n",
 			  reason[host_status], sts->scsi_status));
 
-	LEAVE("isp2100_return_status");
+	LEAVE("isp2x00_return_status");
 
 	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
 }
 
 
-int isp2100_abort(Scsi_Cmnd * Cmnd)
+int isp2x00_abort(Scsi_Cmnd * Cmnd)
 {
 	u_short param[8];
 	int i;
 	struct Scsi_Host *host;
-	struct isp2100_hostdata *hostdata;
-	int return_status = SCSI_ABORT_SUCCESS;
+	struct isp2x00_hostdata *hostdata;
+	int return_status = SUCCESS;
 
-	ENTER("isp2100_abort");
+	ENTER("isp2x00_abort");
 
 	host = Cmnd->host;
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
 	for (i = 0; i < QLOGICFC_REQ_QUEUE_LEN; i++)
 		if (hostdata->handle_ptrs[i] == Cmnd)
 			break;
 
-	if (i == QLOGICFC_REQ_QUEUE_LEN)
-		return SCSI_ABORT_ERROR;
+	if (i == QLOGICFC_REQ_QUEUE_LEN){
+		return SUCCESS;
+	}
 
-	isp2100_disable_irqs(host);
+	isp2x00_disable_irqs(host);
 
 	param[0] = MBOX_ABORT_IOCB;
+#if ISP2x00_PORTDB
+	param[1] = (((u_short) hostdata->port_db[Cmnd->target].loop_id) << 8) | Cmnd->lun;
+#else
 	param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun;
-	param[2] = i >> 16;
-	param[3] = i & 0xffff;
+#endif
+	param[2] = i & 0xffff;
+	param[3] = i >> 16;
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc : scsi abort failure: %x\n", param[0]);
+		printk("qlogicfc%d : scsi abort failure: %x\n", hostdata->host_id, param[0]);
 		if (param[0] == 0x4005)
 			Cmnd->result = DID_ERROR << 16;
 		if (param[0] == 0x4006)
 			Cmnd->result = DID_BAD_TARGET << 16;
-		(*Cmnd->scsi_done) (Cmnd);
-		return_status = SCSI_ABORT_ERROR;
+		return_status = FAILED;
+	}
+
+	if (return_status != SUCCESS){
+		param[0] = MBOX_GET_FIRMWARE_STATE;
+		isp2x00_mbox_command(host, param);
+		printk("qlogicfc%d : abort failed\n", hostdata->host_id);
+		printk("qlogicfc%d : firmware status is %x %x\n", hostdata->host_id, param[0], param[1]);
 	}
-	isp2100_enable_irqs(host);
 
-	LEAVE("isp2100_abort");
+	isp2x00_enable_irqs(host);
+
+	LEAVE("isp2x00_abort");
 
 	return return_status;
 }
 
 
-int isp2100_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags)
+int isp2x00_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags)
 {
 	u_short param[8];
 	struct Scsi_Host *host;
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 	int return_status = SCSI_RESET_SUCCESS;
 
-	ENTER("isp2100_reset");
+	ENTER("isp2x00_reset");
 
 	host = Cmnd->host;
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 	param[0] = MBOX_BUS_RESET;
 	param[1] = 3;
 
-	isp2100_disable_irqs(host);
+	isp2x00_disable_irqs(host);
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc : scsi bus reset failure: %x\n", param[0]);
+		printk("qlogicfc%d : scsi bus reset failure: %x\n", hostdata->host_id, param[0]);
 		return_status = SCSI_RESET_ERROR;
 	}
-	isp2100_enable_irqs(host);
+	isp2x00_enable_irqs(host);
 
-	LEAVE("isp2100_reset");
+	LEAVE("isp2x00_reset");
 
 	return return_status;;
 }
 
 
-int isp2100_biosparam(Disk * disk, kdev_t n, int ip[])
+int isp2x00_biosparam(Disk * disk, kdev_t n, int ip[])
 {
 	int size = disk->capacity;
 
-	ENTER("isp2100_biosparam");
+	ENTER("isp2x00_biosparam");
 
 	ip[0] = 64;
 	ip[1] = 32;
@@ -1532,19 +1683,21 @@
 		ip[1] = 63;
 		ip[2] = size / (ip[0] * ip[1]);
 	}
-	LEAVE("isp2100_biosparam");
+	LEAVE("isp2x00_biosparam");
 
 	return 0;
 }
 
 
-static int isp2100_reset_hardware(struct Scsi_Host *host)
+static int isp2x00_reset_hardware(struct Scsi_Host *host)
 {
 	u_short param[8];
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 	int loop_count;
 
-	ENTER("isp2100_reset_hardware");
+	ENTER("isp2x00_reset_hardware");
+
+	hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
 	outw(0x01, host->io_port + ISP_CTRL_STATUS);
 	outw(HCCR_RESET, host->io_port + HOST_HCCR);
@@ -1555,35 +1708,46 @@
 	while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY)
 		barrier();
 	if (!loop_count)
-		printk("qlogicfc: reset_hardware loop timeout\n");
+		printk("qlogicfc%d : reset_hardware loop timeout\n", hostdata->host_id);
 
 
 
-#if DEBUG_ISP2100
-	printk("qlogicfc : mbox 0 0x%04x \n", inw(host->io_port + MBOX0));
-	printk("qlogicfc : mbox 1 0x%04x \n", inw(host->io_port + MBOX1));
-	printk("qlogicfc : mbox 2 0x%04x \n", inw(host->io_port + MBOX2));
-	printk("qlogicfc : mbox 3 0x%04x \n", inw(host->io_port + MBOX3));
-	printk("qlogicfc : mbox 4 0x%04x \n", inw(host->io_port + MBOX4));
-	printk("qlogicfc : mbox 5 0x%04x \n", inw(host->io_port + MBOX5));
-	printk("qlogicfc : mbox 6 0x%04x \n", inw(host->io_port + MBOX6));
-	printk("qlogicfc : mbox 7 0x%04x \n", inw(host->io_port + MBOX7));
-#endif				/* DEBUG_ISP2100 */
+#if DEBUG_ISP2x00
+	printk("qlogicfc%d : mbox 0 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX0));
+	printk("qlogicfc%d : mbox 1 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX1));
+	printk("qlogicfc%d : mbox 2 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX2));
+	printk("qlogicfc%d : mbox 3 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX3));
+	printk("qlogicfc%d : mbox 4 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX4));
+	printk("qlogicfc%d : mbox 5 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX5));
+	printk("qlogicfc%d : mbox 6 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX6));
+	printk("qlogicfc%d : mbox 7 0x%04x \n", hostdata->host_id,  inw(host->io_port + MBOX7));
+#endif				/* DEBUG_ISP2x00 */
 
-	DEBUG(printk("qlogicfc : verifying checksum\n"));
+	DEBUG(printk("qlogicfc%d : verifying checksum\n", hostdata->host_id));
 
 #if RELOAD_FIRMWARE
 	{
 		int i;
-		for (i = 0; i < risc_code_length01; i++) {
+		unsigned short * risc_code = NULL;
+		unsigned short risc_code_len = 0;
+		if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2100){
+		        risc_code = risc_code2100;
+			risc_code_len = risc_code_length2100;
+		}
+		else if (hostdata->pci_dev->device == PCI_DEVICE_ID_QLOGIC_ISP2200){
+		        risc_code = risc_code2200;
+			risc_code_len = risc_code_length2200;
+		}
+
+		for (i = 0; i < risc_code_len; i++) {
 			param[0] = MBOX_WRITE_RAM_WORD;
 			param[1] = risc_code_addr01 + i;
-			param[2] = risc_code01[i];
+			param[2] = risc_code[i];
 
-			isp2100_mbox_command(host, param);
+			isp2x00_mbox_command(host, param);
 
 			if (param[0] != MBOX_COMMAND_COMPLETE) {
-				printk("qlogicfc : firmware load failure\n");
+				printk("qlogicfc%d : firmware load failure\n", hostdata->host_id);
 				return 1;
 			}
 		}
@@ -1593,36 +1757,34 @@
 	param[0] = MBOX_VERIFY_CHECKSUM;
 	param[1] = risc_code_addr01;
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc : ram checksum failure\n");
+		printk("qlogicfc%d : ram checksum failure\n", hostdata->host_id);
 		return 1;
 	}
-	DEBUG(printk("qlogicfc : executing firmware\n"));
+	DEBUG(printk("qlogicfc%d : executing firmware\n", hostdata->host_id));
 
 	param[0] = MBOX_EXEC_FIRMWARE;
 	param[1] = risc_code_addr01;
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	param[0] = MBOX_ABOUT_FIRMWARE;
 
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc : about firmware failure\n");
+		printk("qlogicfc%d : about firmware failure\n", hostdata->host_id);
 		return 1;
 	}
-	DEBUG(printk("qlogicfc : firmware major revision %d\n", param[1]));
-	DEBUG(printk("qlogicfc : firmware minor revision %d\n", param[2]));
-
-	hostdata = (struct isp2100_hostdata *) host->hostdata;
+	DEBUG(printk("qlogicfc%d : firmware major revision %d\n", hostdata->host_id,  param[1]));
+	DEBUG(printk("qlogicfc%d : firmware minor revision %d\n", hostdata->host_id,  param[2]));
 
 #ifdef USE_NVRAM_DEFAULTS
 
-	if (isp2100_get_nvram_defaults(host, &hostdata->control_block) != 0) {
-		printk("qlogicfc: Could not read from NVRAM\n");
+	if (isp2x00_get_nvram_defaults(host, &hostdata->control_block) != 0) {
+		printk("qlogicfc%d : Could not read from NVRAM\n", hostdata->host_id);
 	}
 #endif
 
@@ -1642,38 +1804,38 @@
 	param[5] = 0;
 	param[6] = (u_short) (virt_to_bus_high32(&hostdata->control_block) >> 16);
 	param[7] = (u_short) (virt_to_bus_high32(&hostdata->control_block) & 0xffff);
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc.c: Ouch 0x%04x\n", param[0]);
+		printk("qlogicfc%d.c: Ouch 0x%04x\n", hostdata->host_id,  param[0]);
 		return 1;
 	}
 	param[0] = MBOX_GET_FIRMWARE_STATE;
-	isp2100_mbox_command(host, param);
+	isp2x00_mbox_command(host, param);
 	if (param[0] != MBOX_COMMAND_COMPLETE) {
-		printk("qlogicfc.c: 0x%04x\n", param[0]);
+		printk("qlogicfc%d.c: 0x%04x\n", hostdata->host_id,  param[0]);
 		return 1;
 	}
 
-	LEAVE("isp2100_reset_hardware");
+	LEAVE("isp2x00_reset_hardware");
 
 	return 0;
 }
 
 #ifdef USE_NVRAM_DEFAULTS
 
-static int isp2100_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block)
+static int isp2x00_get_nvram_defaults(struct Scsi_Host *host, struct init_cb *control_block)
 {
 
 	u_short value;
-	if (isp2100_read_nvram_word(host, 0) != 0x5349)
+	if (isp2x00_read_nvram_word(host, 0) != 0x5349)
 		return 1;
 
-	value = isp2100_read_nvram_word(host, 8);
-	control_block->node_name[0] = isp2100_read_nvram_word(host, 9);
-	control_block->node_name[1] = isp2100_read_nvram_word(host, 10);
-	control_block->node_name[2] = isp2100_read_nvram_word(host, 11);
-	control_block->node_name[3] = isp2100_read_nvram_word(host, 12);
-	control_block->hard_addr = isp2100_read_nvram_word(host, 13);
+	value = isp2x00_read_nvram_word(host, 8);
+	control_block->node_name[0] = isp2x00_read_nvram_word(host, 9);
+	control_block->node_name[1] = isp2x00_read_nvram_word(host, 10);
+	control_block->node_name[2] = isp2x00_read_nvram_word(host, 11);
+	control_block->node_name[3] = isp2x00_read_nvram_word(host, 12);
+	control_block->hard_addr = isp2x00_read_nvram_word(host, 13);
 
 	return 0;
 
@@ -1681,54 +1843,53 @@
 
 #endif
 
-static int isp2100_init(struct Scsi_Host *sh)
+static int isp2x00_init(struct Scsi_Host *sh)
 {
 	u_int io_base;
-	struct isp2100_hostdata *hostdata;
+	struct isp2x00_hostdata *hostdata;
 	u_char revision;
 	u_int irq;
 	u_short command;
 	struct pci_dev *pdev;
 
 
-	ENTER("isp2100_init");
+	ENTER("isp2x00_init");
 
-	hostdata = (struct isp2100_hostdata *) sh->hostdata;
+	hostdata = (struct isp2x00_hostdata *) sh->hostdata;
 	pdev = hostdata->pci_dev;
 
 	if (pci_read_config_word(pdev, PCI_COMMAND, &command)
 	  || pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision)) {
-		printk("qlogicfc : error reading PCI configuration\n");
+		printk("qlogicfc%d : error reading PCI configuration\n", hostdata->host_id);
 		return 1;
 	}
 	io_base = pdev->base_address[0];
 	irq = pdev->irq;
 
 
-
 	if (pdev->vendor != PCI_VENDOR_ID_QLOGIC) {
-		printk("qlogicfc : 0x%04x is not QLogic vendor ID\n",
+		printk("qlogicfc%d : 0x%04x is not QLogic vendor ID\n", hostdata->host_id, 
 		       pdev->vendor);
 		return 1;
 	}
-	if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100) {
-		printk("qlogicfc : 0x%04x does not match ISP2100 device id\n",
+	if (pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2100 && pdev->device != PCI_DEVICE_ID_QLOGIC_ISP2200) {
+		printk("qlogicfc%d : 0x%04x does not match ISP2100 or ISP2200 device id\n", hostdata->host_id, 
 		       pdev->device);
 		return 1;
 	}
 	if (command & PCI_COMMAND_IO && (io_base & 3) == 1)
 		io_base &= PCI_BASE_ADDRESS_IO_MASK;
 	else {
-		printk("qlogicfc : i/o mapping is disabled\n");
+		printk("qlogicfc%d : i/o mapping is disabled\n", hostdata->host_id);
 		return 1;
 	}
 
 	if (!(command & PCI_COMMAND_MASTER)) {
-		printk("qlogicfc : bus mastering is disabled\n");
+		printk("qlogicfc%d : bus mastering is disabled\n", hostdata->host_id);
 		return 1;
 	}
-	if (revision != ISP2100_REV_ID && revision != ISP2100_REV_ID3)
-		printk("qlogicfc : new isp2100 revision ID (%d)\n", revision);
+	if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5)
+		printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id,  revision);
 
 
 	hostdata->revision = revision;
@@ -1736,7 +1897,7 @@
 	sh->irq = irq;
 	sh->io_port = io_base;
 
-	LEAVE("isp2100_init");
+	LEAVE("isp2x00_init");
 
 	return 0;
 }
@@ -1746,7 +1907,7 @@
 #define NVRAM_DELAY() udelay(10)	/* 10 microsecond delay */
 
 
-u_short isp2100_read_nvram_word(struct Scsi_Host * host, u_short byte)
+u_short isp2x00_read_nvram_word(struct Scsi_Host * host, u_short byte)
 {
 	int i;
 	u_short value, output, input;
@@ -1795,26 +1956,27 @@
  * currently, this is only called during initialization or abort/reset,
  * at which times interrupts are disabled, so polling is OK, I guess...
  */
-static int isp2100_mbox_command(struct Scsi_Host *host, u_short param[])
+static int isp2x00_mbox_command(struct Scsi_Host *host, u_short param[])
 {
 	int loop_count;
-	struct isp2100_hostdata *hostdata = (struct isp2100_hostdata *) host->hostdata;
+	struct isp2x00_hostdata *hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
-	if (mbox_param[param[0]] == 0)
+	if (mbox_param[param[0]] == 0 || hostdata->adapter_state == AS_FIRMWARE_DEAD)
 		return 1;
 
 	loop_count = DEFAULT_LOOP_COUNT;
 	while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080)
 		barrier();
 	if (!loop_count) {
-		printk("qlogicfc: mbox_command loop timeout #1\n");
+		printk("qlogicfc%d : mbox_command loop timeout #1\n", hostdata->host_id);
 		param[0] = 0x4006;
+		hostdata->adapter_state = AS_FIRMWARE_DEAD;
 		return 1;
 	}
 	hostdata->mbox_done = 0;
 
 	if (mbox_param[param[0]] == 0)
-		printk("qlogicfc: invalid mbox command\n");
+		printk("qlogicfc%d : invalid mbox command\n", hostdata->host_id);
 
 	if (mbox_param[param[0]] & 0x80)
 		outw(param[7], host->io_port + MBOX7);
@@ -1843,10 +2005,11 @@
 		}
 
 		if (!loop_count) {
-			printk("qlogicfc: mbox_command loop timeout #2\n");
+			hostdata->adapter_state = AS_FIRMWARE_DEAD;
+			printk("qlogicfc%d : mbox_command loop timeout #2\n", hostdata->host_id);
 			break;
 		}
-		isp2100_intr_handler(host->irq, host, NULL);
+		isp2x00_intr_handler(host->irq, host, NULL);
 
 		if (hostdata->mbox_done == 1)
 			break;
@@ -1858,7 +2021,7 @@
 		barrier();
 	}
 	if (!loop_count)
-		printk("qlogicfc: mbox_command loop timeout #3\n");
+		printk("qlogicfc%d : mbox_command loop timeout #3\n", hostdata->host_id);
 
 	param[7] = inw(host->io_port + MBOX7);
 	param[6] = inw(host->io_port + MBOX6);
@@ -1873,19 +2036,21 @@
 	outw(0x0, host->io_port + PCI_SEMAPHORE);
 
 	if (inw(host->io_port + HOST_HCCR) & 0x0080) {
-		printk("mbox op is still pending\n");
+		hostdata->adapter_state = AS_FIRMWARE_DEAD;
+		printk("qlogicfc%d : mbox op is still pending\n", hostdata->host_id);
 	}
 	return 0;
 }
 
+#if DEBUG_ISP2x00_INTR
 
-void isp2100_print_status_entry(struct Status_Entry *status)
+void isp2x00_print_status_entry(struct Status_Entry *status)
 {
-	printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
+	printk("qlogicfc : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", 
 	status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
 	printk("qlogicfc : scsi status = 0x%04x, completion status = 0x%04x\n",
 	       status->scsi_status, status->completion_status);
-	printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n",
+	printk("qlogicfc : state flags = 0x%04x, status flags = 0x%04x\n", 
 	       status->state_flags, status->status_flags);
 	printk("qlogicfc : response info length = 0x%04x, request sense length = 0x%04x\n",
 	       status->res_info_len, status->req_sense_len);
@@ -1893,15 +2058,16 @@
 
 }
 
+#endif                         /* DEBUG_ISP2x00_INTR */
 
 
-#if DEBUG_ISP2100
+#if DEBUG_ISP2x00
 
-void isp2100_print_scsi_cmd(Scsi_Cmnd * cmd)
+void isp2x00_print_scsi_cmd(Scsi_Cmnd * cmd)
 {
 	int i;
 
-	printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
+	printk("qlogicfc : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", 
 	       cmd->target, cmd->lun, cmd->cmd_len);
 	printk("qlogicfc : command = ");
 	for (i = 0; i < cmd->cmd_len; i++)
@@ -1909,7 +2075,7 @@
 	printk("\n");
 }
 
-#endif				/* DEBUG_ISP2100 */
+#endif				/* DEBUG_ISP2x00 */
 
 
 #ifdef MODULE
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc.h linux.pre11.3/drivers/scsi/qlogicfc.h
--- linux.vanilla/drivers/scsi/qlogicfc.h	Wed Mar 10 21:13:05 1999
+++ linux.pre11.3/drivers/scsi/qlogicfc.h	Tue Jul 20 00:03:25 1999
@@ -1,5 +1,5 @@
 /*
- * QLogic ISP2100 SCSI-FCP
+ * QLogic ISP2x00 SCSI-FCP
  * 
  * Written by Erik H. Moe, ehm@cris.com
  * Copyright 1995, Erik H. Moe
@@ -18,7 +18,7 @@
 /* Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> */
 
 /* This is a version of the isp1020 driver which was modified by
- * Chris Loveland <cwl@iol.unh.edu> to support the isp2100
+ * Chris Loveland <cwl@iol.unh.edu> to support the isp2x00
  */
 
 
@@ -61,39 +61,48 @@
  * requests are queued serially and the scatter/gather limit is
  * determined for each queue request anew.
  */
-#define QLOGICFC_REQ_QUEUE_LEN	63	/* must be power of two - 1 */
-#define QLOGICFC_MAX_SG(ql)	(2 + (((ql) > 0) ? 5*((ql) - 1) : 0))
+
+#if BITS_PER_LONG > 32
+#define DATASEGS_PER_COMMAND 2
+#define DATASEGS_PER_CONT 5
+#else
+#define DATASEGS_PER_COMMAND 3
+#define DATASEGS_PER_CONT 7
+#endif
+
+#define QLOGICFC_REQ_QUEUE_LEN	127	/* must be power of two - 1 */
+#define QLOGICFC_MAX_SG(ql)	(DATASEGS_PER_COMMAND + (((ql) > 0) ? DATASEGS_PER_CONT*((ql) - 1) : 0))
 #define QLOGICFC_CMD_PER_LUN    8
 
-int isp2100_detect(Scsi_Host_Template *);
-int isp2100_release(struct Scsi_Host *);
-const char * isp2100_info(struct Scsi_Host *);
-int isp2100_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
-int isp2100_abort(Scsi_Cmnd *);
-int isp2100_reset(Scsi_Cmnd *, unsigned int);
-int isp2100_biosparam(Disk *, kdev_t, int[]);
+int isp2x00_detect(Scsi_Host_Template *);
+int isp2x00_release(struct Scsi_Host *);
+const char * isp2x00_info(struct Scsi_Host *);
+int isp2x00_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
+int isp2x00_abort(Scsi_Cmnd *);
+int isp2x00_reset(Scsi_Cmnd *, unsigned int);
+int isp2x00_biosparam(Disk *, kdev_t, int[]);
 
 #ifndef NULL
 #define NULL (0)
 #endif
 
-extern struct proc_dir_entry proc_scsi_isp2100;
+extern struct proc_dir_entry proc_scsi_isp2x00;
 
 #define QLOGICFC {							   \
-        detect:                 isp2100_detect,                            \
-        release:                isp2100_release,                           \
-        info:                   isp2100_info,                              \
-        queuecommand:           isp2100_queuecommand,                      \
-        abort:                  isp2100_abort,                             \
-        reset:                  isp2100_reset,                             \
-        bios_param:             isp2100_biosparam,                         \
+        detect:                 isp2x00_detect,                            \
+        release:                isp2x00_release,                           \
+        info:                   isp2x00_info,                              \
+        queuecommand:           isp2x00_queuecommand,                      \
+        eh_abort_handler:       isp2x00_abort,                             \
+        reset:                  isp2x00_reset,                             \
+        bios_param:             isp2x00_biosparam,                         \
         can_queue:              QLOGICFC_REQ_QUEUE_LEN,                    \
         this_id:                -1,                                        \
         sg_tablesize:           QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN),   \
-        cmd_per_lun:            QLOGICFC_CMD_PER_LUN,                      \
+	cmd_per_lun:		QLOGICFC_CMD_PER_LUN, 			   \
         present:                0,                                         \
         unchecked_isa_dma:      0,                                         \
-        use_clustering:         DISABLE_CLUSTERING                         \
+        use_clustering:         ENABLE_CLUSTERING 			   \
 }
 
 #endif /* _QLOGICFC_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicfc_asm.c linux.pre11.3/drivers/scsi/qlogicfc_asm.c
--- linux.vanilla/drivers/scsi/qlogicfc_asm.c	Fri Apr 16 22:10:55 1999
+++ linux.pre11.3/drivers/scsi/qlogicfc_asm.c	Tue Jul 20 00:03:26 1999
@@ -1,160 +1,141 @@
-/************************************************************************
- *									*
- * 	 --- ISP2100 Fabric Initiator/Target Firmware ---               *
- *									*
- *									*
- ************************************************************************
- *                                                                      *
- *                              NOTICE                                  *
- *                                                                      *
- *                 COPYRIGHT 1998 QLOGIC CORPORATION                    *
- *                       ALL RIGHTS RESERVED                            *
- *                                                                      *
- ************************************************************************
- */
 
 /*
- *	Firmware Version 1.15.19 (14:58 Jan 19, 1999)
+ *	Firmware Version 1.15.37 (15:37 May 03, 1999)
  */
 
-unsigned short risc_code_version = 1*1024+15;
-
-unsigned char firmware_version[] = {1,15,19};
-
-#define FW_VERSION_STRING "1.15.19"
-
 unsigned short risc_code_addr01 = 0x1000 ;
+unsigned short risc_code_length2100 = 0x65db;
+unsigned short risc_code_length2200 = 0x81bd;
 
-unsigned short risc_code01[] = { 
-	0x0078, 0x1029, 0x0000, 0x65e6, 0x0000, 0x2043, 0x4f50, 0x5952,
+unsigned short risc_code2100[] = { 
+	0x0078, 0x1029, 0x0000, 0x65db, 0x0000, 0x2043, 0x4f50, 0x5952,
 	0x4947, 0x4854, 0x2031, 0x3939, 0x3620, 0x514c, 0x4f47, 0x4943,
 	0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
 	0x3231, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
 	0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3135, 0x2020, 0x2020,
-	0x2400, 0x20c1, 0x0021, 0x20a1, 0x75e6, 0x2009, 0x0000, 0x20a9,
-	0x071a, 0x41a4, 0x3400, 0x20c9, 0x7aff, 0x2091, 0x2000, 0x2059,
-	0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x20a0, 0x2051, 0x7600,
+	0x2400, 0x20c1, 0x0021, 0x20a1, 0x75db, 0x2009, 0x0000, 0x20a9,
+	0x0725, 0x41a4, 0x3400, 0x20c9, 0x7aff, 0x2091, 0x2000, 0x2059,
+	0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x209a, 0x2051, 0x7600,
 	0x2a70, 0x705b, 0x9500, 0x705f, 0xffff, 0x7057, 0x94f9, 0x7063,
-	0x0300, 0x1078, 0x1282, 0x20a1, 0x7d00, 0x715c, 0x810d, 0x810d,
+	0x0300, 0x1078, 0x127a, 0x20a1, 0x7d00, 0x715c, 0x810d, 0x810d,
 	0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0007, 0xa112, 0xa00e,
 	0x21a8, 0x41a4, 0x3400, 0x8211, 0x00c0, 0x1058, 0x715c, 0x3400,
 	0xa102, 0x0040, 0x1068, 0x0048, 0x1068, 0x20a8, 0xa00e, 0x41a4,
-	0x1078, 0x1249, 0x1078, 0x136e, 0x1078, 0x14f3, 0x1078, 0x19c8,
-	0x1078, 0x3615, 0x1078, 0x5b94, 0x1078, 0x12f9, 0x1078, 0x242f,
-	0x1078, 0x3c56, 0x1078, 0x3a2e, 0x1078, 0x4494, 0x1078, 0x1e5b,
-	0x1078, 0x46d3, 0x1078, 0x4174, 0x1078, 0x1d7a, 0x1078, 0x1e3a,
+	0x1078, 0x1241, 0x1078, 0x1366, 0x1078, 0x14eb, 0x1078, 0x19c0,
+	0x1078, 0x360d, 0x1078, 0x5b8c, 0x1078, 0x12f1, 0x1078, 0x2429,
+	0x1078, 0x3c4e, 0x1078, 0x3a26, 0x1078, 0x448c, 0x1078, 0x1e55,
+	0x1078, 0x46cb, 0x1078, 0x416c, 0x1078, 0x1d74, 0x1078, 0x1e34,
 	0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x109d, 0x7820, 0xa086,
 	0x0002, 0x00c0, 0x109d, 0x7823, 0x4000, 0x0068, 0x1095, 0x781b,
 	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
 	0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003,
-	0x00c0, 0x10bd, 0x1078, 0x2d8d, 0x1078, 0x2457, 0x1078, 0x3ca6,
-	0x1078, 0x3b19, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
-	0x10c1, 0x1078, 0x44ac, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078,
-	0x10aa, 0x1078, 0x5866, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x114b,
-	0x10cd, 0x11c6, 0x1246, 0x1247, 0x1248, 0x1078, 0x12d5, 0x007c,
-	0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2eb2, 0x2079, 0x0100,
-	0x7844, 0xa005, 0x00c0, 0x113c, 0x2011, 0x3542, 0x1078, 0x456e,
+	0x00c0, 0x10bd, 0x1078, 0x2d7e, 0x1078, 0x2451, 0x1078, 0x3c9e,
+	0x1078, 0x3b11, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
+	0x10c1, 0x1078, 0x44a4, 0x0078, 0x10a4, 0x1079, 0x10c5, 0x0078,
+	0x10aa, 0x1078, 0x585e, 0x0078, 0x10b9, 0x10cf, 0x10d0, 0x1143,
+	0x10cd, 0x11be, 0x123e, 0x123f, 0x1240, 0x1078, 0x12cd, 0x007c,
+	0x127e, 0x0f7e, 0x2091, 0x8000, 0x1078, 0x2ea3, 0x2079, 0x0100,
+	0x7844, 0xa005, 0x00c0, 0x1134, 0x2011, 0x353a, 0x1078, 0x4566,
 	0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010,
-	0x73b8, 0x1078, 0x2d4a, 0x1078, 0x56b1, 0x2011, 0x0004, 0x1078,
-	0x6953, 0x1078, 0x39c8, 0x70c7, 0x0000, 0x70bf, 0x0000, 0x70c3,
-	0x0000, 0x1078, 0x113f, 0x2011, 0x0000, 0x2079, 0x7651, 0x7804,
-	0xd0ac, 0x0040, 0x1104, 0xc295, 0x70a4, 0xa005, 0x0040, 0x1109,
-	0xc29d, 0x72be, 0xa296, 0x0004, 0x0040, 0x112a, 0x2011, 0x0001,
-	0x1078, 0x6953, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
-	0x0f7f, 0x1078, 0x2150, 0x2011, 0x0005, 0x1078, 0x57c0, 0x1078,
-	0x4c7a, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f,
-	0x0078, 0x113e, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
-	0x2011, 0x0005, 0x1078, 0x57c0, 0x1078, 0x4c7a, 0x0c7e, 0x2061,
+	0x73b8, 0x1078, 0x2d3b, 0x1078, 0x56a9, 0x2011, 0x0004, 0x1078,
+	0x694d, 0x1078, 0x39c0, 0x70c7, 0x0000, 0x70c3, 0x0000, 0x1078,
+	0x1137, 0x72bc, 0x2079, 0x7651, 0x7804, 0xd0ac, 0x0040, 0x1101,
+	0xc295, 0x72be, 0xa296, 0x0004, 0x0040, 0x1122, 0x2011, 0x0001,
+	0x1078, 0x694d, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
+	0x0f7f, 0x1078, 0x214a, 0x2011, 0x0005, 0x1078, 0x57b8, 0x1078,
+	0x4c72, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f, 0x127f,
+	0x0078, 0x1136, 0x708b, 0x0000, 0x708f, 0xffff, 0x7003, 0x0002,
+	0x2011, 0x0005, 0x1078, 0x57b8, 0x1078, 0x4c72, 0x0c7e, 0x2061,
 	0x0100, 0x60e3, 0x0008, 0x0c7f, 0x0f7f, 0x127f, 0x007c, 0x0c7e,
-	0x20a9, 0x0082, 0x2009, 0x007e, 0x1078, 0x380d, 0x8108, 0x00f0,
-	0x1144, 0x0c7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086,
-	0xffff, 0x0040, 0x1159, 0x1078, 0x2150, 0x1078, 0x4c7a, 0x0078,
-	0x11c4, 0x70bc, 0xd09c, 0x0040, 0x1181, 0xd084, 0x0040, 0x1181,
+	0x20a9, 0x0082, 0x2009, 0x007e, 0x1078, 0x3805, 0x8108, 0x00f0,
+	0x113c, 0x0c7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x708c, 0xa086,
+	0xffff, 0x0040, 0x1151, 0x1078, 0x214a, 0x1078, 0x4c72, 0x0078,
+	0x11bc, 0x70bc, 0xd09c, 0x0040, 0x1179, 0xd084, 0x0040, 0x1179,
 	0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
-	0x0040, 0x1181, 0x70c0, 0xa086, 0xffff, 0x0040, 0x117d, 0x1078,
-	0x2245, 0x1078, 0x4c7a, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078,
-	0x227d, 0x1078, 0x4c7a, 0x0078, 0x11c4, 0x70c4, 0xa005, 0x00c0,
-	0x11c4, 0x7088, 0xa005, 0x00c0, 0x11c4, 0x2001, 0x7652, 0x2004,
-	0xd0ac, 0x0040, 0x11a7, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x017e, 0x1078, 0x3825, 0x00c0, 0x119a, 0x6000, 0xd0ec,
-	0x00c0, 0x11a2, 0x017f, 0x8108, 0x00f0, 0x1191, 0x0c7f, 0x157f,
-	0x0078, 0x11a7, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x11c4, 0x7003,
-	0x0003, 0x708f, 0xffff, 0x2001, 0x0000, 0x1078, 0x202b, 0x1078,
-	0x2dc8, 0x2001, 0x7837, 0x2004, 0xa086, 0x0005, 0x00c0, 0x11bc,
-	0x2011, 0x0000, 0x1078, 0x57c0, 0x2011, 0x0000, 0x1078, 0x57ca,
-	0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x127f, 0x007c, 0x017e, 0x0f7e,
+	0x0040, 0x1179, 0x70c0, 0xa086, 0xffff, 0x0040, 0x1175, 0x1078,
+	0x223f, 0x1078, 0x4c72, 0x2011, 0x0001, 0x2019, 0x0000, 0x1078,
+	0x2277, 0x1078, 0x4c72, 0x0078, 0x11bc, 0x70c4, 0xa005, 0x00c0,
+	0x11bc, 0x7088, 0xa005, 0x00c0, 0x11bc, 0x2001, 0x7652, 0x2004,
+	0xd0ac, 0x0040, 0x119f, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
+	0x0000, 0x017e, 0x1078, 0x381d, 0x00c0, 0x1192, 0x6000, 0xd0ec,
+	0x00c0, 0x119a, 0x017f, 0x8108, 0x00f0, 0x1189, 0x0c7f, 0x157f,
+	0x0078, 0x119f, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x11bc, 0x7003,
+	0x0003, 0x708f, 0xffff, 0x2001, 0x0000, 0x1078, 0x2025, 0x1078,
+	0x2db9, 0x2001, 0x7837, 0x2004, 0xa086, 0x0005, 0x00c0, 0x11b4,
+	0x2011, 0x0000, 0x1078, 0x57b8, 0x2011, 0x0000, 0x1078, 0x57c2,
+	0x1078, 0x4c72, 0x1078, 0x4d32, 0x127f, 0x007c, 0x017e, 0x0f7e,
 	0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x7940, 0xa18c, 0x0010,
-	0x7942, 0x7924, 0xd1b4, 0x0040, 0x11d7, 0x7827, 0x0040, 0xd19c,
-	0x0040, 0x11dc, 0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900,
-	0xa18a, 0x0003, 0x0050, 0x1202, 0x7954, 0xd1ac, 0x00c0, 0x1202,
-	0x2009, 0x00f8, 0x1078, 0x35e4, 0x7843, 0x0090, 0x7843, 0x0010,
-	0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11fa, 0x7824, 0xd0ac,
-	0x00c0, 0x1236, 0x00f0, 0x11f2, 0x2001, 0x0001, 0x1078, 0x202b,
-	0x0078, 0x123f, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0008,
-	0x00e0, 0x1208, 0x2091, 0x6000, 0x00f0, 0x1208, 0x7853, 0x0400,
-	0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x35e4, 0x20a9, 0x000e,
-	0x0005, 0x00f0, 0x1218, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843,
+	0x7942, 0x7924, 0xd1b4, 0x0040, 0x11cf, 0x7827, 0x0040, 0xd19c,
+	0x0040, 0x11d4, 0x7827, 0x0008, 0x007e, 0x037e, 0x157e, 0x7900,
+	0xa18a, 0x0003, 0x0050, 0x11fa, 0x7954, 0xd1ac, 0x00c0, 0x11fa,
+	0x2009, 0x00f8, 0x1078, 0x35dc, 0x7843, 0x0090, 0x7843, 0x0010,
+	0x20a9, 0x09c4, 0x7820, 0xd09c, 0x00c0, 0x11f2, 0x7824, 0xd0ac,
+	0x00c0, 0x122e, 0x00f0, 0x11ea, 0x2001, 0x0001, 0x1078, 0x2025,
+	0x0078, 0x1237, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0008,
+	0x00e0, 0x1200, 0x2091, 0x6000, 0x00f0, 0x1200, 0x7853, 0x0400,
+	0x782f, 0x0000, 0x2009, 0x00f8, 0x1078, 0x35dc, 0x20a9, 0x000e,
+	0x0005, 0x00f0, 0x1210, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843,
 	0x0010, 0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040,
-	0x122d, 0x7824, 0xd0ac, 0x00c0, 0x1236, 0x8319, 0x00c0, 0x1223,
-	0x2001, 0x0001, 0x1078, 0x202b, 0x0078, 0x123d, 0x7828, 0xc09d,
+	0x1225, 0x7824, 0xd0ac, 0x00c0, 0x122e, 0x8319, 0x00c0, 0x121b,
+	0x2001, 0x0001, 0x1078, 0x2025, 0x0078, 0x1235, 0x7828, 0xc09d,
 	0x782a, 0x7827, 0x0008, 0x7827, 0x0040, 0x7853, 0x0400, 0x157f,
 	0x037f, 0x007f, 0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c,
 	0x007c, 0x2a70, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
-	0x1255, 0x704f, 0xffff, 0x0078, 0x1257, 0x704f, 0x0000, 0x7053,
+	0x124d, 0x704f, 0xffff, 0x0078, 0x124f, 0x704f, 0x0000, 0x7053,
 	0xffff, 0x7067, 0x0000, 0x706b, 0x0000, 0x2061, 0x7820, 0x6003,
 	0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013,
 	0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061,
 	0x7828, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f,
 	0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f,
-	0x0000, 0x007c, 0x1078, 0x12a8, 0x2011, 0x0000, 0x81ff, 0x0040,
-	0x12a7, 0xa186, 0x0001, 0x00c0, 0x1297, 0x705f, 0x8fff, 0x7057,
-	0x8501, 0x7063, 0x0100, 0x705b, 0x8500, 0x0078, 0x12a5, 0xa186,
-	0x0002, 0x00c0, 0x129f, 0x2011, 0x0000, 0x0078, 0x12a5, 0xa186,
-	0x0005, 0x00c0, 0x12a5, 0x2011, 0x0001, 0x1078, 0x12cf, 0x007c,
-	0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12cf, 0x2019, 0xaaaa,
+	0x0000, 0x007c, 0x1078, 0x12a0, 0x2011, 0x0000, 0x81ff, 0x0040,
+	0x129f, 0xa186, 0x0001, 0x00c0, 0x128f, 0x705f, 0x8fff, 0x7057,
+	0x8501, 0x7063, 0x0100, 0x705b, 0x8500, 0x0078, 0x129d, 0xa186,
+	0x0002, 0x00c0, 0x1297, 0x2011, 0x0000, 0x0078, 0x129d, 0xa186,
+	0x0005, 0x00c0, 0x129d, 0x2011, 0x0001, 0x1078, 0x12c7, 0x007c,
+	0x2009, 0x0000, 0x2011, 0x0000, 0x1078, 0x12c7, 0x2019, 0xaaaa,
 	0x2061, 0xffff, 0x2362, 0x2c24, 0x2061, 0x7fff, 0x2c04, 0xa406,
-	0x0040, 0x12bd, 0xc18d, 0x0078, 0x12ca, 0xc185, 0x2011, 0x0001,
-	0x1078, 0x12cf, 0x2061, 0xffff, 0x2362, 0x2c04, 0xa306, 0x00c0,
-	0x12ca, 0xc195, 0x2011, 0x0001, 0x1078, 0x12cf, 0x007c, 0x3800,
+	0x0040, 0x12b5, 0xc18d, 0x0078, 0x12c2, 0xc185, 0x2011, 0x0001,
+	0x1078, 0x12c7, 0x2061, 0xffff, 0x2362, 0x2c04, 0xa306, 0x00c0,
+	0x12c2, 0xc195, 0x2011, 0x0001, 0x1078, 0x12c7, 0x007c, 0x3800,
 	0xa084, 0xfffc, 0xa205, 0x20c0, 0x007c, 0x2091, 0x8000, 0x0068,
-	0x12d7, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, 0xa084, 0x0000,
-	0x00c0, 0x12dd, 0x017f, 0x792e, 0x007f, 0x782a, 0x007f, 0x7826,
+	0x12cf, 0x007e, 0x017e, 0x2079, 0x0000, 0x7818, 0xa084, 0x0000,
+	0x00c0, 0x12d5, 0x017f, 0x792e, 0x007f, 0x782a, 0x007f, 0x7826,
 	0x3900, 0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000,
-	0x2091, 0x4080, 0x2079, 0x7600, 0x7803, 0x0005, 0x0078, 0x12f6,
+	0x2091, 0x4080, 0x2079, 0x7600, 0x7803, 0x0005, 0x0078, 0x12ee,
 	0x007c, 0x2071, 0x7600, 0x7158, 0x712e, 0x2021, 0x0001, 0xa190,
-	0x002d, 0xa298, 0x002d, 0x0048, 0x130f, 0x705c, 0xa302, 0x00c8,
-	0x130f, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x1301, 0x200b,
+	0x002d, 0xa298, 0x002d, 0x0048, 0x1307, 0x705c, 0xa302, 0x00c8,
+	0x1307, 0x220a, 0x2208, 0x2310, 0x8420, 0x0078, 0x12f9, 0x200b,
 	0x0000, 0x749e, 0x74a2, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0x7600, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x1322, 0xa06e,
-	0x0078, 0x132c, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e,
+	0x2071, 0x7600, 0x70a0, 0xa0ea, 0x0010, 0x00c8, 0x131a, 0xa06e,
+	0x0078, 0x1324, 0x8001, 0x70a2, 0x702c, 0x2068, 0x2d04, 0x702e,
 	0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e,
 	0x2071, 0x7600, 0x127e, 0x2091, 0x8000, 0x70a0, 0x8001, 0x00c8,
-	0x133c, 0xa06e, 0x0078, 0x1345, 0x70a2, 0x702c, 0x2068, 0x2d04,
+	0x1334, 0xa06e, 0x0078, 0x133d, 0x70a2, 0x702c, 0x2068, 0x2d04,
 	0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x127f, 0x0e7f, 0x007c,
 	0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x702c, 0x206a,
 	0x2d00, 0x702e, 0x70a0, 0x8000, 0x70a2, 0x127f, 0x0e7f, 0x007c,
-	0x8dff, 0x0040, 0x1364, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078,
-	0x1348, 0x0d7f, 0x0078, 0x1358, 0x007c, 0x0e7e, 0x2071, 0x7600,
+	0x8dff, 0x0040, 0x135c, 0x6804, 0x6807, 0x0000, 0x007e, 0x1078,
+	0x1340, 0x0d7f, 0x0078, 0x1350, 0x007c, 0x0e7e, 0x2071, 0x7600,
 	0x70a0, 0xa08a, 0x0010, 0xa00d, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
 	0x7859, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071,
 	0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x0e7f, 0x007c, 0x0e7e,
 	0x2270, 0x700b, 0x0000, 0x2071, 0x7859, 0x7018, 0xa088, 0x7862,
 	0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0,
-	0x1397, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a8, 0x0f7f, 0x0e7f,
-	0x007c, 0x0e7e, 0x2071, 0x7859, 0x7004, 0xa005, 0x00c0, 0x13a6,
-	0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a8, 0x0f7f, 0x0e7f, 0x007c,
-	0x7000, 0x0079, 0x13ab, 0x13af, 0x1419, 0x1436, 0x1436, 0x7018,
-	0x711c, 0xa106, 0x00c0, 0x13b7, 0x7007, 0x0000, 0x007c, 0x0d7e,
+	0x138f, 0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a0, 0x0f7f, 0x0e7f,
+	0x007c, 0x0e7e, 0x2071, 0x7859, 0x7004, 0xa005, 0x00c0, 0x139e,
+	0x0f7e, 0x2079, 0x0010, 0x1078, 0x13a0, 0x0f7f, 0x0e7f, 0x007c,
+	0x7000, 0x0079, 0x13a3, 0x13a7, 0x1411, 0x142e, 0x142e, 0x7018,
+	0x711c, 0xa106, 0x00c0, 0x13af, 0x7007, 0x0000, 0x007c, 0x0d7e,
 	0xa180, 0x7862, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007,
 	0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c,
 	0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804,
-	0x0d7f, 0xd084, 0x0040, 0x13d9, 0x7007, 0x0001, 0x1078, 0x13de,
-	0x007c, 0x7007, 0x0002, 0x1078, 0x13f4, 0x007c, 0x017e, 0x027e,
-	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13e9, 0x2110,
+	0x0d7f, 0xd084, 0x0040, 0x13d1, 0x7007, 0x0001, 0x1078, 0x13d6,
+	0x007c, 0x7007, 0x0002, 0x1078, 0x13ec, 0x007c, 0x017e, 0x027e,
+	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x13e1, 0x2110,
 	0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
 	0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e,
 	0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c,
-	0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1408, 0x2110, 0xa006,
+	0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1400, 0x2110, 0xa006,
 	0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
 	0x0001, 0x3300, 0x7016, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f,
 	0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0x76e5, 0x20a1, 0x0018,
@@ -167,1088 +148,1088 @@
 	0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b,
 	0x7711, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e,
 	0x2071, 0x7859, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002,
-	0xd1fc, 0x0040, 0x1479, 0xa18c, 0x0700, 0x0040, 0x1476, 0x7008,
-	0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1479, 0x7004, 0x1079,
-	0x147d, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13a8, 0x1485, 0x14a7,
-	0x14c1, 0x14ea, 0x1483, 0x0078, 0x1483, 0x137e, 0x147e, 0x157e,
+	0xd1fc, 0x0040, 0x1471, 0xa18c, 0x0700, 0x0040, 0x146e, 0x7008,
+	0xa080, 0x0002, 0x2003, 0x0200, 0x0078, 0x1471, 0x7004, 0x1079,
+	0x1475, 0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x13a0, 0x147d, 0x149f,
+	0x14b9, 0x14e2, 0x147b, 0x0078, 0x147b, 0x137e, 0x147e, 0x157e,
 	0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8,
 	0x53a5, 0x3400, 0x7016, 0x157f, 0x147f, 0x137f, 0x700c, 0xa005,
-	0x0040, 0x14ae, 0x1078, 0x13de, 0x007c, 0x7008, 0xa080, 0x0002,
-	0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x13a8, 0x007c, 0x700c,
-	0xa005, 0x0040, 0x14ae, 0x1078, 0x13f4, 0x007c, 0x0d7e, 0x7008,
+	0x0040, 0x14a6, 0x1078, 0x13d6, 0x007c, 0x7008, 0xa080, 0x0002,
+	0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x13a0, 0x007c, 0x700c,
+	0xa005, 0x0040, 0x14a6, 0x1078, 0x13ec, 0x007c, 0x0d7e, 0x7008,
 	0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c,
-	0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x13a8,
+	0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x13a0,
 	0x007c, 0x137e, 0x147e, 0x157e, 0x2001, 0x76e3, 0x2004, 0xa080,
 	0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x20a9, 0x0020,
-	0x53a5, 0x2001, 0x76e5, 0x2004, 0xd0bc, 0x0040, 0x14e0, 0x2001,
+	0x53a5, 0x2001, 0x76e5, 0x2004, 0xd0bc, 0x0040, 0x14d8, 0x2001,
 	0x76ee, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020, 0x53a5,
-	0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x3d4f, 0x1078,
-	0x13a8, 0x007c, 0x2001, 0x7713, 0x2003, 0x0100, 0x7007, 0x0000,
-	0x1078, 0x13a8, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030,
+	0x157f, 0x147f, 0x137f, 0x7007, 0x0000, 0x1078, 0x3d47, 0x1078,
+	0x13a0, 0x007c, 0x2001, 0x7713, 0x2003, 0x0100, 0x7007, 0x0000,
+	0x1078, 0x13a0, 0x007c, 0x127e, 0x2091, 0x2100, 0x2079, 0x0030,
 	0x2071, 0x786a, 0x7003, 0x0000, 0x700f, 0x7870, 0x7013, 0x7870,
 	0x780f, 0x0070, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079,
-	0x1509, 0x1511, 0x1557, 0x1511, 0x1511, 0x1511, 0x153c, 0x1520,
-	0x1515, 0xa085, 0x0001, 0x0078, 0x1571, 0x684c, 0xd0bc, 0x0040,
-	0x1511, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x155f,
-	0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1511, 0x684c, 0xd0bc,
-	0x0040, 0x1511, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004,
-	0x6832, 0x6858, 0x0078, 0x1567, 0xa18c, 0x00ff, 0xa186, 0x0015,
-	0x00c0, 0x1511, 0x684c, 0xd0ac, 0x0040, 0x1511, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004,
-	0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x1567, 0x684c,
-	0xd0ac, 0x0040, 0x1511, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c,
-	0x000f, 0xa188, 0x1c84, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826,
+	0x1501, 0x1509, 0x154f, 0x1509, 0x1509, 0x1509, 0x1534, 0x1518,
+	0x150d, 0xa085, 0x0001, 0x0078, 0x1569, 0x684c, 0xd0bc, 0x0040,
+	0x1509, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x1557,
+	0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1509, 0x684c, 0xd0bc,
+	0x0040, 0x1509, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
+	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004,
+	0x6832, 0x6858, 0x0078, 0x155f, 0xa18c, 0x00ff, 0xa186, 0x0015,
+	0x00c0, 0x1509, 0x684c, 0xd0ac, 0x0040, 0x1509, 0x6804, 0x681a,
+	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004,
+	0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x155f, 0x684c,
+	0xd0ac, 0x0040, 0x1509, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c,
+	0x000f, 0xa188, 0x1c7e, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826,
 	0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980,
 	0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a,
-	0x2004, 0x82ff, 0x0040, 0x158c, 0xa280, 0x0004, 0x0d7e, 0x206c,
-	0x684c, 0xd0dc, 0x00c0, 0x1588, 0x1078, 0x1504, 0x10c0, 0x12d5,
+	0x2004, 0x82ff, 0x0040, 0x1584, 0xa280, 0x0004, 0x0d7e, 0x206c,
+	0x684c, 0xd0dc, 0x00c0, 0x1580, 0x1078, 0x14fc, 0x10c0, 0x12cd,
 	0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e,
 	0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0,
-	0x15a0, 0x7206, 0x2001, 0x15b4, 0x007e, 0x2260, 0x0078, 0x16cc,
+	0x1598, 0x7206, 0x2001, 0x15ac, 0x007e, 0x2260, 0x0078, 0x16c4,
 	0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182,
-	0x788b, 0x0048, 0x15ad, 0x2009, 0x7870, 0x710e, 0x7000, 0xa005,
-	0x00c0, 0x15b4, 0x1078, 0x16b5, 0x127f, 0x007c, 0x127e, 0x027e,
+	0x788b, 0x0048, 0x15a5, 0x2009, 0x7870, 0x710e, 0x7000, 0xa005,
+	0x00c0, 0x15ac, 0x1078, 0x16ad, 0x127f, 0x007c, 0x127e, 0x027e,
 	0x037e, 0x0c7e, 0x007e, 0x2091, 0x2100, 0x007f, 0x047f, 0x037f,
 	0x027f, 0x0d7e, 0x0c7e, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e,
-	0xa005, 0x0040, 0x1608, 0x6808, 0xa005, 0x0040, 0x166e, 0x7000,
-	0xa005, 0x00c0, 0x15d5, 0x0078, 0x1602, 0x700c, 0x7110, 0xa106,
-	0x00c0, 0x1672, 0x7004, 0xa406, 0x00c0, 0x1602, 0x2001, 0x0005,
-	0x2004, 0xd08c, 0x0040, 0x15eb, 0x047e, 0x1078, 0x178d, 0x047f,
-	0x2460, 0x0078, 0x15cb, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0,
-	0x15de, 0x7804, 0xa084, 0x6000, 0x0040, 0x15fc, 0xa086, 0x6000,
-	0x0040, 0x15fc, 0x0078, 0x15de, 0x7803, 0x0004, 0x7003, 0x0000,
-	0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5c29, 0x0078, 0x1672,
-	0x6808, 0xa005, 0x0040, 0x166e, 0x7000, 0xa005, 0x00c0, 0x1612,
-	0x0078, 0x166e, 0x700c, 0x7110, 0xa106, 0x00c0, 0x161b, 0x7004,
-	0xa406, 0x00c0, 0x166e, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040,
-	0x1628, 0x047e, 0x1078, 0x178d, 0x047f, 0x2460, 0x0078, 0x1608,
-	0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x161b, 0x2001, 0x0005,
-	0x2004, 0xd08c, 0x00c0, 0x1621, 0x7804, 0xa084, 0x6000, 0x0040,
-	0x163f, 0xa086, 0x6000, 0x0040, 0x163f, 0x0078, 0x161b, 0x7007,
-	0x0000, 0xa016, 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x1660,
-	0xa08e, 0x0002, 0x00c0, 0x166e, 0x0c7e, 0x0e7e, 0x6818, 0x2060,
-	0x1078, 0x1c59, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x165c,
-	0x7308, 0x720c, 0x0078, 0x165e, 0x7310, 0x7214, 0x0e7f, 0x0c7f,
+	0xa005, 0x0040, 0x1600, 0x6808, 0xa005, 0x0040, 0x1666, 0x7000,
+	0xa005, 0x00c0, 0x15cd, 0x0078, 0x15fa, 0x700c, 0x7110, 0xa106,
+	0x00c0, 0x166a, 0x7004, 0xa406, 0x00c0, 0x15fa, 0x2001, 0x0005,
+	0x2004, 0xd08c, 0x0040, 0x15e3, 0x047e, 0x1078, 0x1785, 0x047f,
+	0x2460, 0x0078, 0x15c3, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0,
+	0x15d6, 0x7804, 0xa084, 0x6000, 0x0040, 0x15f4, 0xa086, 0x6000,
+	0x0040, 0x15f4, 0x0078, 0x15d6, 0x7803, 0x0004, 0x7003, 0x0000,
+	0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x5c21, 0x0078, 0x166a,
+	0x6808, 0xa005, 0x0040, 0x1666, 0x7000, 0xa005, 0x00c0, 0x160a,
+	0x0078, 0x1666, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1613, 0x7004,
+	0xa406, 0x00c0, 0x1666, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040,
+	0x1620, 0x047e, 0x1078, 0x1785, 0x047f, 0x2460, 0x0078, 0x1600,
+	0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1613, 0x2001, 0x0005,
+	0x2004, 0xd08c, 0x00c0, 0x1619, 0x7804, 0xa084, 0x6000, 0x0040,
+	0x1637, 0xa086, 0x6000, 0x0040, 0x1637, 0x0078, 0x1613, 0x7007,
+	0x0000, 0xa016, 0x2218, 0x7000, 0xa08e, 0x0001, 0x0040, 0x1658,
+	0xa08e, 0x0002, 0x00c0, 0x1666, 0x0c7e, 0x0e7e, 0x6818, 0x2060,
+	0x1078, 0x1c53, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0, 0x1654,
+	0x7308, 0x720c, 0x0078, 0x1656, 0x7310, 0x7214, 0x0e7f, 0x0c7f,
 	0x7820, 0xa318, 0x7824, 0xa211, 0x6810, 0xa300, 0x6812, 0x6814,
 	0xa201, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x2009, 0x0048,
-	0x1078, 0x5c29, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, 0x0e7e,
-	0x2071, 0x786a, 0x7000, 0xa086, 0x0000, 0x0040, 0x16b2, 0x7004,
-	0xac06, 0x00c0, 0x16a3, 0x2079, 0x0030, 0x7804, 0xd0fc, 0x00c0,
-	0x169f, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x1685, 0x7803,
-	0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1691, 0x7803, 0x0002, 0x7803,
-	0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x0078, 0x16a3, 0x1078,
-	0x178d, 0x0078, 0x167a, 0x157e, 0x20a9, 0x0009, 0x2009, 0x7870,
-	0x2104, 0xac06, 0x00c0, 0x16ad, 0x200a, 0xa188, 0x0003, 0x00f0,
-	0x16a8, 0x157f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106,
-	0x00c0, 0x16bd, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060,
+	0x1078, 0x5c21, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e, 0x0e7e,
+	0x2071, 0x786a, 0x7000, 0xa086, 0x0000, 0x0040, 0x16aa, 0x7004,
+	0xac06, 0x00c0, 0x169b, 0x2079, 0x0030, 0x7804, 0xd0fc, 0x00c0,
+	0x1697, 0x2001, 0x0207, 0x2004, 0xd09c, 0x00c0, 0x167d, 0x7803,
+	0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1689, 0x7803, 0x0002, 0x7803,
+	0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x0078, 0x169b, 0x1078,
+	0x1785, 0x0078, 0x1672, 0x157e, 0x20a9, 0x0009, 0x2009, 0x7870,
+	0x2104, 0xac06, 0x00c0, 0x16a5, 0x200a, 0xa188, 0x0003, 0x00f0,
+	0x16a0, 0x157f, 0x0e7f, 0x0f7f, 0x007c, 0x700c, 0x7110, 0xa106,
+	0x00c0, 0x16b5, 0x7003, 0x0000, 0x007c, 0x2104, 0x7006, 0x2060,
 	0x8108, 0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0x788b, 0x0048,
-	0x16cb, 0x2009, 0x7870, 0x7112, 0x8cff, 0x00c0, 0x16d3, 0x1078,
-	0x1958, 0x0078, 0x16fa, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406,
-	0x00c0, 0x16de, 0x682c, 0xa306, 0x0040, 0x16e2, 0x1078, 0x1ca4,
-	0x00c0, 0x16cf, 0x684c, 0xd0f4, 0x00c0, 0x16cf, 0x6824, 0x2050,
+	0x16c3, 0x2009, 0x7870, 0x7112, 0x8cff, 0x00c0, 0x16cb, 0x1078,
+	0x1950, 0x0078, 0x16f2, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406,
+	0x00c0, 0x16d6, 0x682c, 0xa306, 0x0040, 0x16da, 0x1078, 0x1c9e,
+	0x00c0, 0x16c7, 0x684c, 0xd0f4, 0x00c0, 0x16c7, 0x6824, 0x2050,
 	0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009,
-	0x0011, 0x1078, 0x16fb, 0x0040, 0x16f9, 0x2009, 0x0001, 0x1078,
-	0x16fb, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x1788, 0xa03e, 0x2730,
-	0x6850, 0xd0fc, 0x00c0, 0x171a, 0x0d7e, 0x2804, 0xac68, 0x2900,
-	0x0079, 0x170a, 0x176a, 0x172a, 0x172a, 0x176a, 0x176a, 0x1762,
-	0x176a, 0x172a, 0x176a, 0x1730, 0x1730, 0x176a, 0x176a, 0x176a,
-	0x1759, 0x1730, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20,
-	0x0d7e, 0xd99c, 0x0040, 0x176d, 0x2804, 0xac68, 0x6f08, 0x6e0c,
-	0x0078, 0x176d, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x176d,
-	0x7b0c, 0xd3bc, 0x0040, 0x1751, 0x7004, 0x0e7e, 0x2070, 0x701c,
-	0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1751, 0x7b08, 0xa39c, 0x0fff,
-	0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x174c, 0x6810,
-	0xa302, 0x0048, 0x174c, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078,
-	0x1753, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078,
-	0x176d, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
-	0x00c0, 0x176a, 0x0d7f, 0x1078, 0x1c40, 0x00c0, 0x16fb, 0xa00e,
-	0x0078, 0x1788, 0x0d7f, 0x1078, 0x12d5, 0x7b22, 0x7a26, 0x7d32,
+	0x0011, 0x1078, 0x16f3, 0x0040, 0x16f1, 0x2009, 0x0001, 0x1078,
+	0x16f3, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x1780, 0xa03e, 0x2730,
+	0x6850, 0xd0fc, 0x00c0, 0x1712, 0x0d7e, 0x2804, 0xac68, 0x2900,
+	0x0079, 0x1702, 0x1762, 0x1722, 0x1722, 0x1762, 0x1762, 0x175a,
+	0x1762, 0x1722, 0x1762, 0x1728, 0x1728, 0x1762, 0x1762, 0x1762,
+	0x1751, 0x1728, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20,
+	0x0d7e, 0xd99c, 0x0040, 0x1765, 0x2804, 0xac68, 0x6f08, 0x6e0c,
+	0x0078, 0x1765, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1765,
+	0x7b0c, 0xd3bc, 0x0040, 0x1749, 0x7004, 0x0e7e, 0x2070, 0x701c,
+	0x0e7f, 0xa086, 0x0008, 0x00c0, 0x1749, 0x7b08, 0xa39c, 0x0fff,
+	0x2d20, 0x0d7f, 0x0d7e, 0x6a14, 0x82ff, 0x00c0, 0x1744, 0x6810,
+	0xa302, 0x0048, 0x1744, 0x6b10, 0x2011, 0x0000, 0x2468, 0x0078,
+	0x174b, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078,
+	0x1765, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e,
+	0x00c0, 0x1762, 0x0d7f, 0x1078, 0x1c3a, 0x00c0, 0x16f3, 0xa00e,
+	0x0078, 0x1780, 0x0d7f, 0x1078, 0x12cd, 0x7b22, 0x7a26, 0x7d32,
 	0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x0d7f,
 	0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x2300, 0x6b10,
-	0xa302, 0x6812, 0x2200, 0x6a14, 0xa203, 0x6816, 0x1078, 0x1c40,
-	0x007c, 0x1078, 0x12d5, 0x1078, 0x12d5, 0x127e, 0x2091, 0x2100,
+	0xa302, 0x6812, 0x2200, 0x6a14, 0xa203, 0x6816, 0x1078, 0x1c3a,
+	0x007c, 0x1078, 0x12cd, 0x1078, 0x12cd, 0x127e, 0x2091, 0x2100,
 	0x007e, 0x017e, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
-	0xa184, 0x0700, 0x00c0, 0x178b, 0xa184, 0x0003, 0xa086, 0x0003,
-	0x0040, 0x178b, 0x7000, 0x0079, 0x17a5, 0x17ad, 0x17af, 0x1887,
-	0x18ef, 0x1906, 0x17ad, 0x17ad, 0x17ad, 0x1078, 0x12d5, 0x8001,
-	0x7002, 0xa184, 0x0880, 0x00c0, 0x17c4, 0x8aff, 0x0040, 0x1827,
-	0x2009, 0x0001, 0x1078, 0x16fb, 0x0040, 0x1918, 0x2009, 0x0001,
-	0x1078, 0x16fb, 0x0078, 0x1918, 0x7803, 0x0004, 0x7003, 0x0000,
-	0xd1bc, 0x00c0, 0x180f, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x7820,
+	0xa184, 0x0700, 0x00c0, 0x1783, 0xa184, 0x0003, 0xa086, 0x0003,
+	0x0040, 0x1783, 0x7000, 0x0079, 0x179d, 0x17a5, 0x17a7, 0x187f,
+	0x18e7, 0x18fe, 0x17a5, 0x17a5, 0x17a5, 0x1078, 0x12cd, 0x8001,
+	0x7002, 0xa184, 0x0880, 0x00c0, 0x17bc, 0x8aff, 0x0040, 0x181f,
+	0x2009, 0x0001, 0x1078, 0x16f3, 0x0040, 0x1910, 0x2009, 0x0001,
+	0x1078, 0x16f3, 0x0078, 0x1910, 0x7803, 0x0004, 0x7003, 0x0000,
+	0xd1bc, 0x00c0, 0x1807, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x7820,
 	0x686e, 0xa31a, 0x7824, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x7820,
 	0x6910, 0xa100, 0x6812, 0x7824, 0x6914, 0xa101, 0x6816, 0x037f,
-	0x027f, 0x7830, 0x681e, 0x7834, 0x6822, 0x1078, 0x1c59, 0x2a00,
+	0x027f, 0x7830, 0x681e, 0x7834, 0x6822, 0x1078, 0x1c53, 0x2a00,
 	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x6850,
-	0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1801, 0x684c,
-	0xd0e4, 0x0040, 0x1801, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078,
-	0x5c29, 0x7808, 0xd0ec, 0x00c0, 0x180b, 0x7803, 0x0009, 0x7003,
-	0x0004, 0x0078, 0x1918, 0x1078, 0x16b5, 0x0078, 0x1918, 0x057e,
-	0x7d0c, 0xd5bc, 0x00c0, 0x1816, 0x1078, 0x7592, 0x057f, 0x1078,
-	0x191c, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x684c,
-	0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x183f, 0x7003, 0x0000,
-	0x6808, 0x8001, 0x680a, 0x00c0, 0x183b, 0x7004, 0x2060, 0x2009,
-	0x0048, 0x1078, 0x5c29, 0x1078, 0x16b5, 0x0078, 0x1918, 0x7814,
+	0xc0fd, 0x6852, 0x6808, 0x8001, 0x680a, 0x00c0, 0x17f9, 0x684c,
+	0xd0e4, 0x0040, 0x17f9, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078,
+	0x5c21, 0x7808, 0xd0ec, 0x00c0, 0x1803, 0x7803, 0x0009, 0x7003,
+	0x0004, 0x0078, 0x1910, 0x1078, 0x16ad, 0x0078, 0x1910, 0x057e,
+	0x7d0c, 0xd5bc, 0x00c0, 0x180e, 0x1078, 0x7587, 0x057f, 0x1078,
+	0x1914, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
+	0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x684c,
+	0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x1837, 0x7003, 0x0000,
+	0x6808, 0x8001, 0x680a, 0x00c0, 0x1833, 0x7004, 0x2060, 0x2009,
+	0x0048, 0x1078, 0x5c21, 0x1078, 0x16ad, 0x0078, 0x1910, 0x7814,
 	0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000, 0x6816, 0x7814,
 	0x7908, 0xa18c, 0x0fff, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214,
 	0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b,
-	0x1078, 0x1983, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001,
-	0x7804, 0xd0fc, 0x0040, 0x1860, 0x7803, 0x0002, 0x7803, 0x0004,
+	0x1078, 0x197b, 0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001,
+	0x7804, 0xd0fc, 0x0040, 0x1858, 0x7803, 0x0002, 0x7803, 0x0004,
 	0x780f, 0x0070, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048,
-	0x1078, 0x5c29, 0x1078, 0x19a6, 0x0040, 0x183b, 0x7908, 0xd1ec,
-	0x00c0, 0x187e, 0x2009, 0x0009, 0x0078, 0x1880, 0x2009, 0x0019,
-	0x7902, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x8001,
-	0x7002, 0xd194, 0x0040, 0x1899, 0x7804, 0xd0fc, 0x00c0, 0x1795,
-	0x8aff, 0x0040, 0x1918, 0x2009, 0x0001, 0x1078, 0x16fb, 0x0078,
-	0x1918, 0xa184, 0x0880, 0x00c0, 0x18a6, 0x8aff, 0x0040, 0x1918,
-	0x2009, 0x0001, 0x1078, 0x16fb, 0x0078, 0x1918, 0x7803, 0x0004,
-	0x7003, 0x0000, 0xd1bc, 0x00c0, 0x18da, 0x027e, 0x037e, 0x6b28,
-	0x6a2c, 0x1078, 0x1c59, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, 0xac68,
-	0x6034, 0xd09c, 0x00c0, 0x18ca, 0x6808, 0x2008, 0xa31a, 0x680c,
+	0x1078, 0x5c21, 0x1078, 0x199e, 0x0040, 0x1833, 0x7908, 0xd1ec,
+	0x00c0, 0x1876, 0x2009, 0x0009, 0x0078, 0x1878, 0x2009, 0x0019,
+	0x7902, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x8001,
+	0x7002, 0xd194, 0x0040, 0x1891, 0x7804, 0xd0fc, 0x00c0, 0x178d,
+	0x8aff, 0x0040, 0x1910, 0x2009, 0x0001, 0x1078, 0x16f3, 0x0078,
+	0x1910, 0xa184, 0x0880, 0x00c0, 0x189e, 0x8aff, 0x0040, 0x1910,
+	0x2009, 0x0001, 0x1078, 0x16f3, 0x0078, 0x1910, 0x7803, 0x0004,
+	0x7003, 0x0000, 0xd1bc, 0x00c0, 0x18d2, 0x027e, 0x037e, 0x6b28,
+	0x6a2c, 0x1078, 0x1c53, 0x0d7e, 0x0f7e, 0x2d78, 0x2804, 0xac68,
+	0x6034, 0xd09c, 0x00c0, 0x18c2, 0x6808, 0x2008, 0xa31a, 0x680c,
 	0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101, 0x7816,
-	0x0078, 0x18d6, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, 0x7810,
+	0x0078, 0x18ce, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213, 0x7810,
 	0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f, 0x0d7f,
-	0x0078, 0x17cf, 0x057e, 0x7d0c, 0x1078, 0x7592, 0x057f, 0x1078,
-	0x191c, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1918, 0x7803,
-	0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x1902, 0x6808,
-	0x8001, 0x680a, 0x00c0, 0x1902, 0x7004, 0x2060, 0x2009, 0x0048,
-	0x1078, 0x5c29, 0x1078, 0x16b5, 0x0078, 0x1918, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x1902,
-	0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x16cc,
-	0x017f, 0x007f, 0x127f, 0x007c, 0x1078, 0x192d, 0x20e1, 0x9028,
+	0x0078, 0x17c7, 0x057e, 0x7d0c, 0x1078, 0x7587, 0x057f, 0x1078,
+	0x1914, 0x682b, 0xffff, 0x682f, 0xffff, 0x697c, 0x6912, 0x6980,
+	0x6916, 0x7803, 0x0009, 0x7003, 0x0003, 0x0078, 0x1910, 0x7803,
+	0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0040, 0x18fa, 0x6808,
+	0x8001, 0x680a, 0x00c0, 0x18fa, 0x7004, 0x2060, 0x2009, 0x0048,
+	0x1078, 0x5c21, 0x1078, 0x16ad, 0x0078, 0x1910, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0040, 0x18fa,
+	0x2068, 0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x1078, 0x16c4,
+	0x017f, 0x007f, 0x127f, 0x007c, 0x1078, 0x1925, 0x20e1, 0x9028,
 	0x700f, 0x7870, 0x7013, 0x7870, 0x2001, 0x015d, 0x200c, 0x810a,
 	0x2102, 0x2001, 0x0138, 0x2202, 0x007c, 0x2001, 0x0138, 0x2014,
 	0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc,
-	0x00c0, 0x194a, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0,
-	0x194a, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x194a, 0x8421,
-	0x00c0, 0x1934, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204,
-	0xa005, 0x00c0, 0x1957, 0x8109, 0x00c0, 0x194f, 0x007c, 0x007c,
-	0x1078, 0x194b, 0x0040, 0x1980, 0x7908, 0xd1ec, 0x00c0, 0x1970,
-	0x1078, 0x19a6, 0x0040, 0x1970, 0x7803, 0x0009, 0x7904, 0xd1fc,
-	0x0040, 0x1966, 0x7803, 0x0006, 0x1078, 0x194b, 0x0040, 0x1980,
-	0x780c, 0xd0a4, 0x00c0, 0x1980, 0x7007, 0x0000, 0x1078, 0x19a6,
-	0x0040, 0x1982, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x1982,
-	0x1078, 0x191c, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200,
-	0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x192d, 0x20e1, 0x7000,
+	0x00c0, 0x1942, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0,
+	0x1942, 0x2001, 0x0111, 0x201c, 0x83ff, 0x00c0, 0x1942, 0x8421,
+	0x00c0, 0x192c, 0x007c, 0x2011, 0x0201, 0x2009, 0x003c, 0x2204,
+	0xa005, 0x00c0, 0x194f, 0x8109, 0x00c0, 0x1947, 0x007c, 0x007c,
+	0x1078, 0x1943, 0x0040, 0x1978, 0x7908, 0xd1ec, 0x00c0, 0x1968,
+	0x1078, 0x199e, 0x0040, 0x1968, 0x7803, 0x0009, 0x7904, 0xd1fc,
+	0x0040, 0x195e, 0x7803, 0x0006, 0x1078, 0x1943, 0x0040, 0x1978,
+	0x780c, 0xd0a4, 0x00c0, 0x1978, 0x7007, 0x0000, 0x1078, 0x199e,
+	0x0040, 0x197a, 0x7803, 0x0019, 0x7003, 0x0003, 0x0078, 0x197a,
+	0x1078, 0x1914, 0x007c, 0x3c00, 0x007e, 0x0e7e, 0x2071, 0x0200,
+	0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1925, 0x20e1, 0x7000,
 	0x7324, 0x7420, 0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f,
 	0x712e, 0x702f, 0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001,
 	0x0138, 0x2202, 0x0e7f, 0x007f, 0x20e0, 0x007c, 0x3c00, 0x007e,
-	0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x19b3, 0xa085,
-	0x0001, 0x0078, 0x19c5, 0x2001, 0x020a, 0x81ff, 0x0040, 0x19be,
+	0x7908, 0xa18c, 0x0fff, 0xa182, 0x0009, 0x0048, 0x19ab, 0xa085,
+	0x0001, 0x0078, 0x19bd, 0x2001, 0x020a, 0x81ff, 0x0040, 0x19b6,
 	0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1, 0x7000,
 	0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x007f, 0x20e0, 0x007c,
 	0x0e7e, 0x2071, 0x788b, 0x7003, 0x0000, 0x0e7f, 0x007c, 0x0d7e,
-	0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1a4a, 0x6934,
-	0xa184, 0x0007, 0x0079, 0x19dc, 0x19e4, 0x1a35, 0x19e4, 0x19e4,
-	0x19e4, 0x1a1a, 0x19f7, 0x19e6, 0x1078, 0x12d5, 0x684c, 0xd0b4,
-	0x0040, 0x1b4c, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
-	0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1a3d, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x19e4, 0x684c, 0xd0b4,
-	0x0040, 0x1b4c, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+	0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1a42, 0x6934,
+	0xa184, 0x0007, 0x0079, 0x19d4, 0x19dc, 0x1a2d, 0x19dc, 0x19dc,
+	0x19dc, 0x1a12, 0x19ef, 0x19de, 0x1078, 0x12cd, 0x684c, 0xd0b4,
+	0x0040, 0x1b46, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
+	0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1a35, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x19dc, 0x684c, 0xd0b4,
+	0x0040, 0x1b46, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812,
 	0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d,
-	0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6958,
-	0x0078, 0x1a46, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1a4a,
-	0x684c, 0xd0b4, 0x0040, 0x1b4c, 0x6804, 0x681a, 0xa080, 0x000d,
-	0x2004, 0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6958,
-	0xa006, 0x682e, 0x682a, 0x0078, 0x1a46, 0x684c, 0xd0b4, 0x0040,
-	0x1789, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834,
-	0xa084, 0x000f, 0xa080, 0x1c84, 0x2004, 0x6832, 0x6926, 0x684c,
+	0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6958,
+	0x0078, 0x1a3e, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0, 0x1a42,
+	0x684c, 0xd0b4, 0x0040, 0x1b46, 0x6804, 0x681a, 0xa080, 0x000d,
+	0x2004, 0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6958,
+	0xa006, 0x682e, 0x682a, 0x0078, 0x1a3e, 0x684c, 0xd0b4, 0x0040,
+	0x1781, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a, 0x6834,
+	0xa084, 0x000f, 0xa080, 0x1c7e, 0x2004, 0x6832, 0x6926, 0x684c,
 	0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020, 0x7804,
-	0xd0fc, 0x10c0, 0x1b50, 0x0e7e, 0x0d7e, 0x2071, 0x788b, 0x7000,
-	0xa005, 0x00c0, 0x1ac6, 0x0c7e, 0x7206, 0xa280, 0x0004, 0x205c,
-	0x7004, 0x2068, 0x6818, 0x0d7e, 0x2068, 0x686c, 0x7812, 0x6890,
-	0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a, 0x2079, 0x0100,
-	0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, 0x6824, 0x2050, 0x6818,
-	0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f, 0x6908, 0xa184,
-	0x0007, 0x0040, 0x1a88, 0x017e, 0x2009, 0x0008, 0xa102, 0x017f,
-	0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081, 0x0000, 0x781e,
-	0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106,
-	0x00c0, 0x1a9f, 0x6928, 0x6810, 0xa106, 0x0040, 0x1aac, 0x037e,
-	0x047e, 0x6b14, 0x6c10, 0x1078, 0x1ca4, 0x047f, 0x037f, 0x0040,
-	0x1aac, 0x0c7f, 0x0078, 0x1ac6, 0x8aff, 0x00c0, 0x1ab4, 0x0c7f,
-	0xa085, 0x0001, 0x0078, 0x1ac6, 0x127e, 0x2091, 0x8000, 0x2079,
-	0x0020, 0x2009, 0x0001, 0x1078, 0x1aca, 0x0040, 0x1ac3, 0x2009,
-	0x0001, 0x1078, 0x1aca, 0x127f, 0x0c7f, 0xa006, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e, 0x037e, 0x027e,
-	0x8aff, 0x0040, 0x1b45, 0x700c, 0x7214, 0xa202, 0x7010, 0x7218,
-	0xa203, 0x0048, 0x1b44, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0,
-	0x1af7, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1ae7, 0x1b26,
-	0x1b07, 0x1b07, 0x1b26, 0x1b26, 0x1b1e, 0x1b26, 0x1b07, 0x1b26,
-	0x1b0d, 0x1b0d, 0x1b26, 0x1b26, 0x1b26, 0x1b15, 0x1b0d, 0xc0fc,
-	0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1b2a,
-	0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x1b29, 0x6b08,
-	0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1b29, 0x6b10, 0x6a14, 0x6d00,
-	0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1b29, 0x0d7f, 0x0d7e, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b26, 0x0d7f, 0x1078,
-	0x1c40, 0x00c0, 0x1ad0, 0xa00e, 0x0078, 0x1b45, 0x0d7f, 0x1078,
-	0x12d5, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e,
-	0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c,
-	0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012,
-	0x1078, 0x1c40, 0x0078, 0x1b45, 0xa006, 0x027f, 0x037f, 0x047f,
-	0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x12d5, 0x1078, 0x12d5,
-	0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x2079, 0x0020, 0x2071, 0x788b, 0x2b68, 0x6818, 0x2060,
-	0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0, 0x1b4e, 0x7000,
-	0x0079, 0x1b6a, 0x1c11, 0x1b6e, 0x1bde, 0x1c0f, 0x8001, 0x7002,
-	0xd19c, 0x00c0, 0x1b82, 0x8aff, 0x0040, 0x1ba1, 0x2009, 0x0001,
-	0x1078, 0x1aca, 0x0040, 0x1c11, 0x2009, 0x0001, 0x1078, 0x1aca,
-	0x0078, 0x1c11, 0x7803, 0x0004, 0xd194, 0x0040, 0x1b92, 0x6850,
-	0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1b97, 0x684c, 0xc0f5, 0x684e,
-	0x0078, 0x1b97, 0x1078, 0x1c59, 0x6850, 0xc0fd, 0x6852, 0x2a00,
-	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000, 0x0078,
-	0x1c11, 0x711c, 0x81ff, 0x0040, 0x1bb7, 0x7918, 0x7922, 0x7827,
-	0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002, 0x700c, 0xa100,
-	0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078, 0x1c11, 0x0f7e,
-	0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079, 0x0100, 0x7a14,
-	0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820, 0xd0bc, 0x00c0,
-	0x1bc5, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4, 0x007f, 0xa102,
-	0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f,
-	0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1c11, 0x8001, 0x7002,
-	0xd194, 0x0040, 0x1bf3, 0x7804, 0xd0fc, 0x00c0, 0x1b60, 0xd19c,
-	0x00c0, 0x1c0d, 0x8aff, 0x0040, 0x1c11, 0x2009, 0x0001, 0x1078,
-	0x1aca, 0x0078, 0x1c11, 0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078,
-	0x1c59, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c, 0x00c0, 0x1c06,
-	0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1c0a, 0x6810, 0xa31a,
-	0x6814, 0xa213, 0x0d7f, 0x0078, 0x1b92, 0x0078, 0x1b92, 0x1078,
-	0x12d5, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f,
-	0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x788b, 0x7000, 0xa086, 0x0000,
-	0x0040, 0x1c3d, 0x2079, 0x0020, 0x20e1, 0x9040, 0x7804, 0xd0fc,
-	0x0040, 0x1c24, 0x1078, 0x1b50, 0x7000, 0xa086, 0x0000, 0x00c0,
-	0x1c24, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0, 0x1c33, 0x20e1,
-	0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x0f7f, 0x007c,
-	0x8840, 0x2804, 0xa005, 0x00c0, 0x1c54, 0x6004, 0xa005, 0x0040,
-	0x1c56, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x1c84,
-	0x2044, 0x88ff, 0x1040, 0x12d5, 0x8a51, 0x007c, 0x2051, 0x0000,
-	0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0, 0x1c73, 0x2c00,
-	0xad06, 0x0040, 0x1c68, 0x6000, 0xa005, 0x00c0, 0x1c68, 0x2d00,
-	0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080, 0x1c94, 0x2044,
-	0x88ff, 0x1040, 0x12d5, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019,
-	0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b,
-	0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1c79, 0x1c75, 0x0000,
-	0x0000, 0x1c83, 0x0000, 0x1c79, 0x0000, 0x1c80, 0x1c7d, 0x0000,
-	0x0000, 0x0000, 0x1c83, 0x1c80, 0x0000, 0x1c7b, 0x1c7b, 0x0000,
-	0x0000, 0x1c83, 0x0000, 0x1c7b, 0x0000, 0x1c81, 0x1c81, 0x0000,
-	0x0000, 0x0000, 0x1c83, 0x1c81, 0x0a7e, 0x097e, 0x087e, 0x6858,
-	0xa055, 0x0040, 0x1d45, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0,
-	0x1c84, 0xa986, 0x0007, 0x0040, 0x1cbd, 0xa986, 0x000e, 0x0040,
-	0x1cbd, 0xa986, 0x000f, 0x00c0, 0x1cc1, 0x605c, 0xa422, 0x6060,
-	0xa31a, 0x2804, 0xa045, 0x00c0, 0x1ccf, 0x0050, 0x1cc9, 0x0078,
-	0x1d45, 0x6004, 0xa065, 0x0040, 0x1d45, 0x0078, 0x1cac, 0x2804,
-	0xa005, 0x0040, 0x1ced, 0xac68, 0xd99c, 0x00c0, 0x1cdd, 0x6808,
-	0xa422, 0x680c, 0xa31b, 0x0078, 0x1ce1, 0x6810, 0xa422, 0x6814,
-	0xa31b, 0x0048, 0x1d0c, 0x2300, 0xa405, 0x0040, 0x1cf3, 0x8a51,
-	0x0040, 0x1d45, 0x8840, 0x0078, 0x1ccf, 0x6004, 0xa065, 0x0040,
-	0x1d45, 0x0078, 0x1cac, 0x8a51, 0x0040, 0x1d45, 0x8840, 0x2804,
-	0xa005, 0x00c0, 0x1d06, 0x6004, 0xa065, 0x0040, 0x1d45, 0x6034,
-	0xa0cc, 0x000f, 0xa9c0, 0x1c84, 0x2804, 0x2040, 0x2b68, 0x6850,
-	0xc0fc, 0x6852, 0x0078, 0x1d39, 0x8422, 0x8420, 0x831a, 0xa399,
-	0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0,
-	0x1d27, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048,
-	0x12d5, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x1d33, 0x6910,
-	0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x12d5, 0x6800,
-	0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd,
-	0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f,
-	0x007f, 0x007f, 0xa006, 0x0078, 0x1d4a, 0x087f, 0x097f, 0x0a7f,
-	0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007,
-	0x0079, 0x1d52, 0x1d5a, 0x1d5b, 0x1d5e, 0x1d61, 0x1d66, 0x1d69,
-	0x1d6e, 0x1d73, 0x007c, 0x1078, 0x1b50, 0x007c, 0x1078, 0x178d,
-	0x007c, 0x1078, 0x178d, 0x1078, 0x1b50, 0x007c, 0x1078, 0x145e,
-	0x007c, 0x1078, 0x1b50, 0x1078, 0x145e, 0x007c, 0x1078, 0x178d,
-	0x1078, 0x145e, 0x007c, 0x1078, 0x178d, 0x1078, 0x1b50, 0x1078,
-	0x145e, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071,
-	0x7b80, 0x2069, 0x7600, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004,
-	0x1078, 0x2058, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c,
-	0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x1d98,
-	0x1dbc, 0x1da0, 0x1da4, 0x1da8, 0x1dae, 0x1db2, 0x1db6, 0x1dba,
-	0x1078, 0x417d, 0x0078, 0x1dbc, 0x1078, 0x41ac, 0x0078, 0x1dbc,
-	0x1078, 0x417d, 0x1078, 0x41ac, 0x0078, 0x1dbc, 0x1078, 0x1dbe,
-	0x0078, 0x1dbc, 0x1078, 0x1dbe, 0x0078, 0x1dbc, 0x1078, 0x1dbe,
-	0x0078, 0x1dbc, 0x1078, 0x1dbe, 0x127f, 0x007c, 0x007e, 0x017e,
-	0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1dc8, 0x1078, 0x12d5,
-	0xa184, 0x0030, 0x0040, 0x1dd9, 0x6a00, 0xa286, 0x0003, 0x00c0,
-	0x1dd3, 0x1078, 0x12d5, 0x1078, 0x357b, 0x20e1, 0x9010, 0x0078,
-	0x1de5, 0xa184, 0x00c0, 0x0040, 0x1ddf, 0x1078, 0x12d5, 0xa184,
-	0x0300, 0x0040, 0x1de5, 0x20e1, 0x9020, 0x7932, 0x027f, 0x017f,
-	0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071, 0x7600, 0x7128,
-	0x2001, 0x7823, 0x2102, 0x2001, 0x782b, 0x2102, 0xa182, 0x0211,
-	0x00c8, 0x1dfe, 0x2009, 0x0008, 0x0078, 0x1e28, 0xa182, 0x0259,
-	0x00c8, 0x1e06, 0x2009, 0x0007, 0x0078, 0x1e28, 0xa182, 0x02c1,
-	0x00c8, 0x1e0e, 0x2009, 0x0006, 0x0078, 0x1e28, 0xa182, 0x0349,
-	0x00c8, 0x1e16, 0x2009, 0x0005, 0x0078, 0x1e28, 0xa182, 0x0421,
-	0x00c8, 0x1e1e, 0x2009, 0x0004, 0x0078, 0x1e28, 0xa182, 0x0581,
-	0x00c8, 0x1e26, 0x2009, 0x0003, 0x0078, 0x1e28, 0x2009, 0x0002,
-	0x2079, 0x0200, 0x7912, 0xa182, 0x0005, 0x00c8, 0x1e32, 0x7916,
-	0x0078, 0x1e34, 0x7817, 0x0004, 0x1078, 0x2058, 0x0f7f, 0x0e7f,
-	0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071,
-	0x7600, 0x6024, 0x6026, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb,
-	0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f,
-	0x0080, 0x602f, 0x0000, 0x6007, 0x0caf, 0x600f, 0x00ff, 0x602b,
-	0x002f, 0x127f, 0x007c, 0x2001, 0x762d, 0x2003, 0x0000, 0x2001,
-	0x762c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e,
-	0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x1e73, 0xa184,
-	0x0007, 0x0079, 0x1e79, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079,
-	0x1e79, 0x1ea5, 0x1e81, 0x1e85, 0x1e89, 0x1e8f, 0x1e93, 0x1e99,
-	0x1e9f, 0x1078, 0x46e6, 0x0078, 0x1ea5, 0x1078, 0x47d5, 0x0078,
-	0x1ea5, 0x1078, 0x47d5, 0x1078, 0x46e6, 0x0078, 0x1ea5, 0x1078,
-	0x1eaa, 0x0078, 0x1ea5, 0x1078, 0x46e6, 0x1078, 0x1eaa, 0x0078,
-	0x1ea5, 0x1078, 0x47d5, 0x1078, 0x1eaa, 0x0078, 0x1ea5, 0x1078,
-	0x47d5, 0x1078, 0x46e6, 0x1078, 0x1eaa, 0x027f, 0x017f, 0x007f,
-	0x127f, 0x007c, 0xd1ac, 0x0040, 0x1f5e, 0x017e, 0x047e, 0x0c7e,
-	0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00, 0x0040, 0x1ed9,
-	0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x1ed9, 0x7130,
-	0xd18c, 0x00c0, 0x1ed9, 0x2011, 0x7652, 0x2214, 0xd2ec, 0x0040,
-	0x1ecd, 0xc18d, 0x7132, 0x0078, 0x1ed9, 0x6240, 0xa294, 0x0010,
-	0x0040, 0x1f1b, 0x6248, 0xa294, 0xff00, 0xa296, 0xff00, 0x00c0,
-	0x1f1b, 0x037e, 0x73b8, 0x2011, 0x8013, 0x1078, 0x2d4a, 0x037f,
-	0x7130, 0xc185, 0x7132, 0x2011, 0x7652, 0x220c, 0xd1a4, 0x0040,
-	0x1f03, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100, 0x1078, 0x46b4,
-	0x2019, 0x000e, 0x1078, 0x74d9, 0xa484, 0x00ff, 0xa080, 0x232f,
-	0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006, 0x2009, 0x000e,
-	0x1078, 0x7541, 0x017f, 0xd1ac, 0x00c0, 0x1f0c, 0x2019, 0x0004,
-	0x1078, 0x2299, 0x0078, 0x1f1b, 0x157e, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x1078, 0x3825, 0x00c0, 0x1f17, 0x1078, 0x3621, 0x8108,
-	0x00f0, 0x1f11, 0x157f, 0x0c7f, 0x047f, 0x6043, 0x0000, 0x2009,
-	0x00f7, 0x1078, 0x35e4, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086,
-	0x0000, 0x0040, 0x1f33, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079,
-	0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x57c0,
-	0x2011, 0x0002, 0x1078, 0x57ca, 0x1078, 0x56d6, 0x1078, 0x45eb,
-	0x037e, 0x2019, 0x0000, 0x1078, 0x5768, 0x037f, 0x60e3, 0x0000,
-	0x017f, 0x2001, 0x7600, 0x2014, 0xa296, 0x0004, 0x00c0, 0x1f56,
-	0xd19c, 0x00c0, 0x1f56, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001,
-	0x2001, 0x7620, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040,
-	0x1fff, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086, 0x0001, 0x00c0,
-	0x1f82, 0x017e, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140,
-	0x7803, 0x1000, 0x7803, 0x0000, 0x2079, 0x7836, 0x7807, 0x0000,
-	0x7833, 0x0000, 0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x017f, 0x0f7f,
-	0x0078, 0x1fff, 0x0f7f, 0x017e, 0x6220, 0xd2b4, 0x0040, 0x1fb7,
-	0x1078, 0x45eb, 0x1078, 0x5582, 0x6027, 0x0004, 0x0d7e, 0x2069,
-	0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1f9a, 0x6803, 0x1000,
-	0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7836, 0x6028, 0xa09a,
-	0x0002, 0x00c8, 0x1faa, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x5574,
-	0x0078, 0x1ffe, 0x2019, 0x783f, 0x2304, 0xa065, 0x0040, 0x1fb4,
-	0x2009, 0x0027, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x1ffe, 0xd2bc,
-	0x0040, 0x1ffe, 0x1078, 0x45f9, 0x6017, 0x0010, 0x6027, 0x0004,
-	0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1fcc,
+	0xd0fc, 0x10c0, 0x1b4a, 0x0e7e, 0x0d7e, 0x2071, 0x788b, 0x7000,
+	0xa005, 0x00c0, 0x1ac0, 0x0c7e, 0x7206, 0xa280, 0x0004, 0x205c,
+	0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068, 0x686c,
+	0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200, 0x781a,
+	0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68, 0x6824,
+	0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
+	0x6908, 0xa184, 0x0007, 0x0040, 0x1a82, 0x017e, 0x2009, 0x0008,
+	0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081,
+	0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c,
+	0x6814, 0xa106, 0x00c0, 0x1a99, 0x6928, 0x6810, 0xa106, 0x0040,
+	0x1aa6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x1c9e, 0x047f,
+	0x037f, 0x0040, 0x1aa6, 0x0c7f, 0x0078, 0x1ac0, 0x8aff, 0x00c0,
+	0x1aae, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1ac0, 0x127e, 0x2091,
+	0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1ac4, 0x0040,
+	0x1abd, 0x2009, 0x0001, 0x1078, 0x1ac4, 0x127f, 0x0c7f, 0xa006,
+	0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e,
+	0x037e, 0x027e, 0x8aff, 0x0040, 0x1b3f, 0x700c, 0x7214, 0xa202,
+	0x7010, 0x7218, 0xa203, 0x0048, 0x1b3e, 0xa03e, 0x2730, 0x6850,
+	0xd0fc, 0x00c0, 0x1af1, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079,
+	0x1ae1, 0x1b20, 0x1b01, 0x1b01, 0x1b20, 0x1b20, 0x1b18, 0x1b20,
+	0x1b01, 0x1b20, 0x1b07, 0x1b07, 0x1b20, 0x1b20, 0x1b20, 0x1b0f,
+	0x1b07, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0xd99c,
+	0x0040, 0x1b24, 0x0d7e, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078,
+	0x1b23, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0078, 0x1b23, 0x6b10,
+	0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x1b23, 0x0d7f,
+	0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1b20,
+	0x0d7f, 0x1078, 0x1c3a, 0x00c0, 0x1aca, 0xa00e, 0x0078, 0x1b3f,
+	0x0d7f, 0x1078, 0x12cd, 0x0d7f, 0x7b22, 0x7a26, 0x7d32, 0x7c36,
+	0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300,
+	0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010,
+	0xa201, 0x7012, 0x1078, 0x1c3a, 0x0078, 0x1b3f, 0xa006, 0x027f,
+	0x037f, 0x047f, 0x057f, 0x067f, 0x077f, 0x007c, 0x1078, 0x12cd,
+	0x1078, 0x12cd, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e,
+	0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0x788b, 0x2b68,
+	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0,
+	0x1b48, 0x7000, 0x0079, 0x1b64, 0x1c0b, 0x1b68, 0x1bd8, 0x1c09,
+	0x8001, 0x7002, 0xd19c, 0x00c0, 0x1b7c, 0x8aff, 0x0040, 0x1b9b,
+	0x2009, 0x0001, 0x1078, 0x1ac4, 0x0040, 0x1c0b, 0x2009, 0x0001,
+	0x1078, 0x1ac4, 0x0078, 0x1c0b, 0x7803, 0x0004, 0xd194, 0x0040,
+	0x1b8c, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1b91, 0x684c,
+	0xc0f5, 0x684e, 0x0078, 0x1b91, 0x1078, 0x1c53, 0x6850, 0xc0fd,
+	0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003,
+	0x0000, 0x0078, 0x1c0b, 0x711c, 0x81ff, 0x0040, 0x1bb1, 0x7918,
+	0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002,
+	0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078,
+	0x1c0b, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079,
+	0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x7820,
+	0xd0bc, 0x00c0, 0x1bbf, 0x79c8, 0x007f, 0xa102, 0x78ca, 0x79c4,
+	0x007f, 0xa102, 0x78c6, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816,
+	0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003, 0x0000, 0x0078, 0x1c0b,
+	0x8001, 0x7002, 0xd194, 0x0040, 0x1bed, 0x7804, 0xd0fc, 0x00c0,
+	0x1b5a, 0xd19c, 0x00c0, 0x1c07, 0x8aff, 0x0040, 0x1c0b, 0x2009,
+	0x0001, 0x1078, 0x1ac4, 0x0078, 0x1c0b, 0x027e, 0x037e, 0x6b28,
+	0x6a2c, 0x1078, 0x1c53, 0x0d7e, 0x2804, 0xac68, 0x6034, 0xd09c,
+	0x00c0, 0x1c00, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0078, 0x1c04,
+	0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f, 0x0078, 0x1b8c, 0x0078,
+	0x1b8c, 0x1078, 0x12cd, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x017f,
+	0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x788b, 0x7000,
+	0xa086, 0x0000, 0x0040, 0x1c37, 0x2079, 0x0020, 0x20e1, 0x9040,
+	0x7804, 0xd0fc, 0x0040, 0x1c1e, 0x1078, 0x1b4a, 0x7000, 0xa086,
+	0x0000, 0x00c0, 0x1c1e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0,
+	0x1c2d, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f,
+	0x0f7f, 0x007c, 0x8840, 0x2804, 0xa005, 0x00c0, 0x1c4e, 0x6004,
+	0xa005, 0x0040, 0x1c50, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f,
+	0xa080, 0x1c7e, 0x2044, 0x88ff, 0x1040, 0x12cd, 0x8a51, 0x007c,
+	0x2051, 0x0000, 0x007c, 0x8a50, 0x8841, 0x2804, 0xa005, 0x00c0,
+	0x1c6d, 0x2c00, 0xad06, 0x0040, 0x1c62, 0x6000, 0xa005, 0x00c0,
+	0x1c62, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084, 0x000f, 0xa080,
+	0x1c8e, 0x2044, 0x88ff, 0x1040, 0x12cd, 0x007c, 0x0000, 0x0011,
+	0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029, 0x0000, 0x000f,
+	0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000, 0x0000, 0x1c73,
+	0x1c6f, 0x0000, 0x0000, 0x1c7d, 0x0000, 0x1c73, 0x0000, 0x1c7a,
+	0x1c77, 0x0000, 0x0000, 0x0000, 0x1c7d, 0x1c7a, 0x0000, 0x1c75,
+	0x1c75, 0x0000, 0x0000, 0x1c7d, 0x0000, 0x1c75, 0x0000, 0x1c7b,
+	0x1c7b, 0x0000, 0x0000, 0x0000, 0x1c7d, 0x1c7b, 0x0a7e, 0x097e,
+	0x087e, 0x6858, 0xa055, 0x0040, 0x1d3f, 0x2d60, 0x6034, 0xa0cc,
+	0x000f, 0xa9c0, 0x1c7e, 0xa986, 0x0007, 0x0040, 0x1cb7, 0xa986,
+	0x000e, 0x0040, 0x1cb7, 0xa986, 0x000f, 0x00c0, 0x1cbb, 0x605c,
+	0xa422, 0x6060, 0xa31a, 0x2804, 0xa045, 0x00c0, 0x1cc9, 0x0050,
+	0x1cc3, 0x0078, 0x1d3f, 0x6004, 0xa065, 0x0040, 0x1d3f, 0x0078,
+	0x1ca6, 0x2804, 0xa005, 0x0040, 0x1ce7, 0xac68, 0xd99c, 0x00c0,
+	0x1cd7, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0078, 0x1cdb, 0x6810,
+	0xa422, 0x6814, 0xa31b, 0x0048, 0x1d06, 0x2300, 0xa405, 0x0040,
+	0x1ced, 0x8a51, 0x0040, 0x1d3f, 0x8840, 0x0078, 0x1cc9, 0x6004,
+	0xa065, 0x0040, 0x1d3f, 0x0078, 0x1ca6, 0x8a51, 0x0040, 0x1d3f,
+	0x8840, 0x2804, 0xa005, 0x00c0, 0x1d00, 0x6004, 0xa065, 0x0040,
+	0x1d3f, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x1c7e, 0x2804, 0x2040,
+	0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0078, 0x1d33, 0x8422, 0x8420,
+	0x831a, 0xa399, 0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f,
+	0xd99c, 0x00c0, 0x1d21, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
+	0xa11b, 0x1048, 0x12cd, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078,
+	0x1d2d, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048,
+	0x12cd, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22,
+	0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00,
+	0x6826, 0x007f, 0x007f, 0x007f, 0xa006, 0x0078, 0x1d44, 0x087f,
+	0x097f, 0x0a7f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004,
+	0xa084, 0x0007, 0x0079, 0x1d4c, 0x1d54, 0x1d55, 0x1d58, 0x1d5b,
+	0x1d60, 0x1d63, 0x1d68, 0x1d6d, 0x007c, 0x1078, 0x1b4a, 0x007c,
+	0x1078, 0x1785, 0x007c, 0x1078, 0x1785, 0x1078, 0x1b4a, 0x007c,
+	0x1078, 0x1456, 0x007c, 0x1078, 0x1b4a, 0x1078, 0x1456, 0x007c,
+	0x1078, 0x1785, 0x1078, 0x1456, 0x007c, 0x1078, 0x1785, 0x1078,
+	0x1b4a, 0x1078, 0x1456, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079,
+	0x0200, 0x2071, 0x7b80, 0x2069, 0x7600, 0x2009, 0x0004, 0x7912,
+	0x7817, 0x0004, 0x1078, 0x2052, 0x781b, 0x0002, 0x20e1, 0x8700,
+	0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007,
+	0x0079, 0x1d92, 0x1db6, 0x1d9a, 0x1d9e, 0x1da2, 0x1da8, 0x1dac,
+	0x1db0, 0x1db4, 0x1078, 0x4175, 0x0078, 0x1db6, 0x1078, 0x41a4,
+	0x0078, 0x1db6, 0x1078, 0x4175, 0x1078, 0x41a4, 0x0078, 0x1db6,
+	0x1078, 0x1db8, 0x0078, 0x1db6, 0x1078, 0x1db8, 0x0078, 0x1db6,
+	0x1078, 0x1db8, 0x0078, 0x1db6, 0x1078, 0x1db8, 0x127f, 0x007c,
+	0x007e, 0x017e, 0x027e, 0x7930, 0xa184, 0x0003, 0x0040, 0x1dc2,
+	0x1078, 0x12cd, 0xa184, 0x0030, 0x0040, 0x1dd3, 0x6a00, 0xa286,
+	0x0003, 0x00c0, 0x1dcd, 0x1078, 0x12cd, 0x1078, 0x3573, 0x20e1,
+	0x9010, 0x0078, 0x1ddf, 0xa184, 0x00c0, 0x0040, 0x1dd9, 0x1078,
+	0x12cd, 0xa184, 0x0300, 0x0040, 0x1ddf, 0x20e1, 0x9020, 0x7932,
+	0x027f, 0x017f, 0x007f, 0x007c, 0x017e, 0x0e7e, 0x0f7e, 0x2071,
+	0x7600, 0x7128, 0x2001, 0x7823, 0x2102, 0x2001, 0x782b, 0x2102,
+	0xa182, 0x0211, 0x00c8, 0x1df8, 0x2009, 0x0008, 0x0078, 0x1e22,
+	0xa182, 0x0259, 0x00c8, 0x1e00, 0x2009, 0x0007, 0x0078, 0x1e22,
+	0xa182, 0x02c1, 0x00c8, 0x1e08, 0x2009, 0x0006, 0x0078, 0x1e22,
+	0xa182, 0x0349, 0x00c8, 0x1e10, 0x2009, 0x0005, 0x0078, 0x1e22,
+	0xa182, 0x0421, 0x00c8, 0x1e18, 0x2009, 0x0004, 0x0078, 0x1e22,
+	0xa182, 0x0581, 0x00c8, 0x1e20, 0x2009, 0x0003, 0x0078, 0x1e22,
+	0x2009, 0x0002, 0x2079, 0x0200, 0x7912, 0xa182, 0x0005, 0x00c8,
+	0x1e2c, 0x7916, 0x0078, 0x1e2e, 0x7817, 0x0004, 0x1078, 0x2052,
+	0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x127e, 0x2091, 0x2200, 0x2061,
+	0x0100, 0x2071, 0x7600, 0x6024, 0x6026, 0x6033, 0x00ef, 0x60e7,
+	0x0000, 0x60eb, 0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043,
+	0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007, 0x0caf, 0x600f,
+	0x00ff, 0x602b, 0x002f, 0x127f, 0x007c, 0x2001, 0x762d, 0x2003,
+	0x0000, 0x2001, 0x762c, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091,
+	0x2200, 0x007e, 0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0,
+	0x1e6d, 0xa184, 0x0007, 0x0079, 0x1e73, 0xa195, 0x0004, 0xa284,
+	0x0007, 0x0079, 0x1e73, 0x1e9f, 0x1e7b, 0x1e7f, 0x1e83, 0x1e89,
+	0x1e8d, 0x1e93, 0x1e99, 0x1078, 0x46de, 0x0078, 0x1e9f, 0x1078,
+	0x47cd, 0x0078, 0x1e9f, 0x1078, 0x47cd, 0x1078, 0x46de, 0x0078,
+	0x1e9f, 0x1078, 0x1ea4, 0x0078, 0x1e9f, 0x1078, 0x46de, 0x1078,
+	0x1ea4, 0x0078, 0x1e9f, 0x1078, 0x47cd, 0x1078, 0x1ea4, 0x0078,
+	0x1e9f, 0x1078, 0x47cd, 0x1078, 0x46de, 0x1078, 0x1ea4, 0x027f,
+	0x017f, 0x007f, 0x127f, 0x007c, 0xd1ac, 0x0040, 0x1f58, 0x017e,
+	0x047e, 0x0c7e, 0x644c, 0x74ba, 0xa48c, 0xff00, 0xa196, 0xff00,
+	0x0040, 0x1ed3, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040,
+	0x1ed3, 0x7130, 0xd18c, 0x00c0, 0x1ed3, 0x2011, 0x7652, 0x2214,
+	0xd2ec, 0x0040, 0x1ec7, 0xc18d, 0x7132, 0x0078, 0x1ed3, 0x6240,
+	0xa294, 0x0010, 0x0040, 0x1f15, 0x6248, 0xa294, 0xff00, 0xa296,
+	0xff00, 0x00c0, 0x1f15, 0x037e, 0x73b8, 0x2011, 0x8013, 0x1078,
+	0x2d3b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0x7652, 0x220c,
+	0xd1a4, 0x0040, 0x1efd, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100,
+	0x1078, 0x46ac, 0x2019, 0x000e, 0x1078, 0x74ce, 0xa484, 0x00ff,
+	0xa080, 0x2329, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006,
+	0x2009, 0x000e, 0x1078, 0x7536, 0x017f, 0xd1ac, 0x00c0, 0x1f06,
+	0x2019, 0x0004, 0x1078, 0x2293, 0x0078, 0x1f15, 0x157e, 0x20a9,
+	0x007f, 0x2009, 0x0000, 0x1078, 0x381d, 0x00c0, 0x1f11, 0x1078,
+	0x3619, 0x8108, 0x00f0, 0x1f0b, 0x157f, 0x0c7f, 0x047f, 0x6043,
+	0x0000, 0x2009, 0x00f7, 0x1078, 0x35dc, 0x0f7e, 0x2079, 0x7849,
+	0x783c, 0xa086, 0x0000, 0x0040, 0x1f2d, 0x6027, 0x0004, 0x783f,
+	0x0000, 0x2079, 0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003,
+	0x1078, 0x57b8, 0x2011, 0x0002, 0x1078, 0x57c2, 0x1078, 0x56ce,
+	0x1078, 0x45e3, 0x037e, 0x2019, 0x0000, 0x1078, 0x5760, 0x037f,
+	0x60e3, 0x0000, 0x017f, 0x2001, 0x7600, 0x2014, 0xa296, 0x0004,
+	0x00c0, 0x1f50, 0xd19c, 0x00c0, 0x1f50, 0x6228, 0xc29d, 0x622a,
+	0x2003, 0x0001, 0x2001, 0x7620, 0x2003, 0x0000, 0x6027, 0x0020,
+	0xd194, 0x0040, 0x1ff9, 0x0f7e, 0x2079, 0x7849, 0x783c, 0xa086,
+	0x0001, 0x00c0, 0x1f7c, 0x017e, 0x6027, 0x0004, 0x783f, 0x0000,
+	0x2079, 0x0140, 0x7803, 0x1000, 0x7803, 0x0000, 0x2079, 0x7836,
+	0x7807, 0x0000, 0x7833, 0x0000, 0x1078, 0x4c72, 0x1078, 0x4d32,
+	0x017f, 0x0f7f, 0x0078, 0x1ff9, 0x0f7f, 0x017e, 0x6220, 0xd2b4,
+	0x0040, 0x1fb1, 0x1078, 0x45e3, 0x1078, 0x557a, 0x6027, 0x0004,
+	0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x1f94,
 	0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0x7836,
-	0x6044, 0xa09a, 0x0002, 0x00c8, 0x1fed, 0x8000, 0x6046, 0x603c,
-	0x0c7f, 0xa005, 0x0040, 0x1ffe, 0x1078, 0x45f0, 0xa080, 0x0007,
-	0x2004, 0xa086, 0x0006, 0x00c0, 0x1fe9, 0x6017, 0x0012, 0x0078,
-	0x1ffe, 0x6017, 0x0016, 0x0078, 0x1ffe, 0x037e, 0x2019, 0x0001,
-	0x1078, 0x5768, 0x037f, 0x2019, 0x7845, 0x2304, 0xa065, 0x0040,
-	0x1ffd, 0x2009, 0x004f, 0x1078, 0x5c29, 0x0c7f, 0x017f, 0xd19c,
-	0x0040, 0x2027, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003,
-	0x1078, 0x57c0, 0x2011, 0x0002, 0x1078, 0x57ca, 0x1078, 0x56d6,
-	0x1078, 0x45eb, 0x037e, 0x2019, 0x0000, 0x1078, 0x5768, 0x037f,
-	0x60e3, 0x0000, 0x1078, 0x75b0, 0x1078, 0x75ce, 0x2001, 0x7600,
-	0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x11c6, 0x017f, 0xa18c,
-	0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x71b0, 0x70b2, 0xa116,
-	0x0040, 0x2051, 0x81ff, 0x0040, 0x2043, 0x2011, 0x8011, 0x1078,
-	0x2d4a, 0x0078, 0x2051, 0x2011, 0x8012, 0x1078, 0x2d4a, 0x037e,
-	0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078, 0x2299, 0x0c7f,
-	0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c,
-	0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x2073,
-	0x2204, 0x60f2, 0xa192, 0x0005, 0x00c8, 0x206a, 0xa190, 0x207c,
-	0x0078, 0x206c, 0x2011, 0x2080, 0x2204, 0x60ee, 0x027f, 0x007f,
-	0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420,
-	0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8,
-	0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0x2130, 0xa094,
-	0xff00, 0x00c0, 0x208e, 0x81ff, 0x0040, 0x2092, 0x1078, 0x4330,
-	0x0078, 0x2099, 0xa080, 0x232f, 0x200c, 0xa18c, 0xff00, 0x810f,
-	0xa006, 0x007c, 0xa080, 0x232f, 0x200c, 0xa18c, 0x00ff, 0x007c,
-	0x20c0, 0x20c4, 0x20c8, 0x20ce, 0x20d4, 0x20da, 0x20e0, 0x20e8,
-	0x20f0, 0x20f6, 0x20fc, 0x2104, 0x210c, 0x2114, 0x211c, 0x2126,
-	0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130,
-	0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130, 0x2130,
-	0x107e, 0x007e, 0x0078, 0x2149, 0x107e, 0x007e, 0x0078, 0x2149,
-	0x107e, 0x007e, 0x1078, 0x1e64, 0x0078, 0x2149, 0x107e, 0x007e,
-	0x1078, 0x1e64, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b,
-	0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b, 0x0078, 0x2149,
-	0x107e, 0x007e, 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x0078, 0x2149,
-	0x107e, 0x007e, 0x1078, 0x1e64, 0x1078, 0x1d4b, 0x0078, 0x2149,
-	0x107e, 0x007e, 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e,
-	0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64,
-	0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64,
-	0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b,
-	0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1d4b,
-	0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e, 0x1078, 0x1e64,
-	0x1078, 0x1d4b, 0x1078, 0x1d90, 0x0078, 0x2149, 0x107e, 0x007e,
-	0x1078, 0x1e64, 0x1078, 0x1d4b, 0x1078, 0x1d90, 0x0078, 0x2149,
-	0x0005, 0x0078, 0x2130, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079,
-	0x2139, 0x2149, 0x20c6, 0x20ca, 0x20d0, 0x20d6, 0x20dc, 0x20e2,
-	0x20ea, 0x20f2, 0x20f8, 0x20fe, 0x2106, 0x210e, 0x2116, 0x211e,
-	0x2128, 0x0008, 0x2133, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c,
-	0x0c7e, 0x027e, 0x2041, 0x007e, 0x70bc, 0xd09c, 0x0040, 0x215a,
-	0x2041, 0x007f, 0x2001, 0x010c, 0x203c, 0x727c, 0x82ff, 0x0040,
-	0x21a5, 0x037e, 0x738c, 0xa38e, 0xffff, 0x00c0, 0x2169, 0x2019,
-	0x0001, 0x8314, 0xa2e0, 0x7cc0, 0x2c04, 0xa38c, 0x0001, 0x0040,
-	0x2176, 0xa084, 0xff00, 0x8007, 0x0078, 0x2178, 0xa084, 0x00ff,
-	0xa70e, 0x0040, 0x219a, 0xa08e, 0x00ff, 0x0040, 0x21a0, 0x2009,
-	0x0000, 0x1078, 0x2085, 0x1078, 0x37ee, 0x00c0, 0x219d, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2194, 0x1078, 0x21f7,
-	0x0040, 0x219d, 0x0078, 0x219a, 0x1078, 0x22fb, 0x1078, 0x221e,
-	0x0040, 0x219d, 0x8318, 0x0078, 0x2169, 0x738e, 0x0078, 0x21a2,
-	0x708f, 0xffff, 0x037f, 0x0078, 0x21f4, 0xa780, 0x232f, 0x203c,
-	0xa7bc, 0xff00, 0x873f, 0x708c, 0xa096, 0xffff, 0x0040, 0x21b7,
-	0xa812, 0x00c8, 0x21c7, 0x708f, 0xffff, 0x0078, 0x21f1, 0x2009,
-	0x0000, 0x70bc, 0xd09c, 0x0040, 0x21c2, 0xd094, 0x0040, 0x21c2,
-	0x2009, 0x007e, 0x2100, 0xa802, 0x20a8, 0x0078, 0x21cb, 0x2008,
-	0x2810, 0xa202, 0x20a8, 0x2700, 0x157e, 0x017e, 0xa106, 0x0040,
-	0x21e8, 0x1078, 0x37ee, 0x00c0, 0x21f1, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x00c0, 0x21e2, 0x1078, 0x21f7, 0x0040, 0x21f1,
-	0x0078, 0x21e8, 0x1078, 0x22fb, 0x1078, 0x221e, 0x0040, 0x21f1,
-	0x017f, 0x8108, 0x157f, 0x00f0, 0x21cb, 0x708f, 0xffff, 0x0078,
-	0x21f4, 0x017f, 0x157f, 0x718e, 0x027f, 0x0c7f, 0x007c, 0x017e,
-	0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2219,
-	0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd,
-	0x2001, 0x0000, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088,
-	0x8000, 0x708a, 0x127f, 0x2009, 0x0004, 0x1078, 0x5c29, 0xa085,
-	0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x017e, 0x077e,
-	0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2240, 0x2d00,
-	0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
-	0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000,
-	0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001,
-	0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, 0x027e, 0x2009,
-	0x0080, 0x1078, 0x37ee, 0x00c0, 0x2253, 0x1078, 0x2256, 0x0040,
-	0x2253, 0x70c3, 0xffff, 0x027f, 0x0c7f, 0x007c, 0x017e, 0x077e,
-	0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b9c, 0x0040, 0x2278, 0x2d00,
-	0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
-	0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x70c4, 0x8000,
-	0x70c6, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001,
-	0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e, 0x0d7e, 0x2009,
-	0x007f, 0x1078, 0x37ee, 0x00c0, 0x2296, 0x2c68, 0x1078, 0x5b9c,
-	0x0040, 0x2296, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
-	0x2009, 0x0022, 0x1078, 0x5c29, 0xa085, 0x0001, 0x0d7f, 0x0c7f,
-	0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x4969,
-	0x1078, 0x4919, 0x1078, 0x6103, 0x20a9, 0x007f, 0x2009, 0x0000,
-	0x017e, 0x1078, 0x3825, 0x00c0, 0x22b1, 0x1078, 0x39a6, 0x1078,
-	0x3621, 0x017f, 0x8108, 0x00f0, 0x22a8, 0x027f, 0x037f, 0x067f,
-	0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e,
-	0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029, 0x1078, 0x4962,
-	0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x017f, 0x2e60, 0x1078,
-	0x39a6, 0x6210, 0x6314, 0x1078, 0x3621, 0x6212, 0x6316, 0x017f,
-	0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x6018,
-	0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x22f1, 0x2071, 0x7600,
-	0x7088, 0xa005, 0x0040, 0x22ee, 0x8001, 0x708a, 0x007f, 0x0e7f,
-	0x007c, 0x2071, 0x7600, 0x70c4, 0xa005, 0x0040, 0x22ee, 0x8001,
-	0x70c6, 0x0078, 0x22ee, 0x6000, 0xc08c, 0x6002, 0x007c, 0x0e7e,
-	0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x81ff, 0x00c0, 0x230c,
-	0x20a9, 0x0001, 0x0078, 0x2310, 0x20a9, 0x007f, 0x2011, 0x0000,
-	0x027e, 0xa2e0, 0x7720, 0x2c64, 0x8cff, 0x0040, 0x2322, 0x2019,
-	0x0029, 0x1078, 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b,
-	0x1078, 0x39a6, 0x027f, 0x8210, 0x00f0, 0x2310, 0x027e, 0x027f,
-	0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x7eef,
-	0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9,
-	0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd,
-	0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3,
-	0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2,
-	0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7,
-	0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098,
-	0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080,
-	0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072,
-	0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067,
-	0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055,
-	0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b,
-	0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a,
-	0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e,
-	0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025,
-	0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010,
-	0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800,
-	0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000,
-	0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000,
-	0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000,
-	0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000,
-	0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000,
-	0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000,
-	0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000,
-	0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000,
-	0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500,
-	0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000,
+	0x6028, 0xa09a, 0x0002, 0x00c8, 0x1fa4, 0x8000, 0x602a, 0x0c7f,
+	0x1078, 0x556c, 0x0078, 0x1ff8, 0x2019, 0x783f, 0x2304, 0xa065,
+	0x0040, 0x1fae, 0x2009, 0x0027, 0x1078, 0x5c21, 0x0c7f, 0x0078,
+	0x1ff8, 0xd2bc, 0x0040, 0x1ff8, 0x1078, 0x45f1, 0x6017, 0x0010,
+	0x6027, 0x0004, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
+	0x0040, 0x1fc6, 0x6803, 0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e,
+	0x2061, 0x7836, 0x6044, 0xa09a, 0x0002, 0x00c8, 0x1fe7, 0x8000,
+	0x6046, 0x603c, 0x0c7f, 0xa005, 0x0040, 0x1ff8, 0x1078, 0x45e8,
+	0xa080, 0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x1fe3, 0x6017,
+	0x0012, 0x0078, 0x1ff8, 0x6017, 0x0016, 0x0078, 0x1ff8, 0x037e,
+	0x2019, 0x0001, 0x1078, 0x5760, 0x037f, 0x2019, 0x7845, 0x2304,
+	0xa065, 0x0040, 0x1ff7, 0x2009, 0x004f, 0x1078, 0x5c21, 0x0c7f,
+	0x017f, 0xd19c, 0x0040, 0x2021, 0x017e, 0x6028, 0xc09c, 0x602a,
+	0x2011, 0x0003, 0x1078, 0x57b8, 0x2011, 0x0002, 0x1078, 0x57c2,
+	0x1078, 0x56ce, 0x1078, 0x45e3, 0x037e, 0x2019, 0x0000, 0x1078,
+	0x5760, 0x037f, 0x60e3, 0x0000, 0x1078, 0x75a5, 0x1078, 0x75c3,
+	0x2001, 0x7600, 0x2003, 0x0004, 0x6027, 0x0008, 0x1078, 0x11be,
+	0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c, 0x007e, 0x017e, 0x027e,
+	0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7600, 0x71b0,
+	0x70b2, 0xa116, 0x0040, 0x204b, 0x81ff, 0x0040, 0x203d, 0x2011,
+	0x8011, 0x1078, 0x2d3b, 0x0078, 0x204b, 0x2011, 0x8012, 0x1078,
+	0x2d3b, 0x037e, 0x0c7e, 0x2061, 0x0100, 0x2019, 0x0028, 0x1078,
+	0x2293, 0x0c7f, 0x037f, 0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f,
+	0x007f, 0x007c, 0x0c7e, 0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100,
+	0xa190, 0x206d, 0x2204, 0x60f2, 0xa192, 0x0005, 0x00c8, 0x2064,
+	0xa190, 0x2076, 0x0078, 0x2066, 0x2011, 0x207a, 0x2204, 0x60ee,
+	0x027f, 0x007f, 0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840,
+	0x0580, 0x0420, 0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8,
+	0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028,
+	0x2130, 0xa094, 0xff00, 0x00c0, 0x2088, 0x81ff, 0x0040, 0x208c,
+	0x1078, 0x4328, 0x0078, 0x2093, 0xa080, 0x2329, 0x200c, 0xa18c,
+	0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x2329, 0x200c, 0xa18c,
+	0x00ff, 0x007c, 0x20ba, 0x20be, 0x20c2, 0x20c8, 0x20ce, 0x20d4,
+	0x20da, 0x20e2, 0x20ea, 0x20f0, 0x20f6, 0x20fe, 0x2106, 0x210e,
+	0x2116, 0x2120, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a,
+	0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a, 0x212a,
+	0x212a, 0x212a, 0x107e, 0x007e, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x0078, 0x2143,
+	0x107e, 0x007e, 0x1078, 0x1e5e, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x1078, 0x1d45, 0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1d45,
+	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45,
+	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45,
+	0x0078, 0x2143, 0x107e, 0x007e, 0x1078, 0x1d8a, 0x0078, 0x2143,
+	0x107e, 0x007e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x1078, 0x1e5e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x1078, 0x1e5e, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143, 0x107e, 0x007e,
+	0x1078, 0x1e5e, 0x1078, 0x1d45, 0x1078, 0x1d8a, 0x0078, 0x2143,
+	0x107e, 0x007e, 0x1078, 0x1e5e, 0x1078, 0x1d45, 0x1078, 0x1d8a,
+	0x0078, 0x2143, 0x0005, 0x0078, 0x212a, 0xb084, 0x003c, 0x8004,
+	0x8004, 0x0079, 0x2133, 0x2143, 0x20c0, 0x20c4, 0x20ca, 0x20d0,
+	0x20d6, 0x20dc, 0x20e4, 0x20ec, 0x20f2, 0x20f8, 0x2100, 0x2108,
+	0x2110, 0x2118, 0x2122, 0x0008, 0x212d, 0x007f, 0x107f, 0x2091,
+	0x8001, 0x007c, 0x0c7e, 0x027e, 0x2041, 0x007e, 0x70bc, 0xd09c,
+	0x0040, 0x2154, 0x2041, 0x007f, 0x2001, 0x010c, 0x203c, 0x727c,
+	0x82ff, 0x0040, 0x219f, 0x037e, 0x738c, 0xa38e, 0xffff, 0x00c0,
+	0x2163, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x7cc0, 0x2c04, 0xa38c,
+	0x0001, 0x0040, 0x2170, 0xa084, 0xff00, 0x8007, 0x0078, 0x2172,
+	0xa084, 0x00ff, 0xa70e, 0x0040, 0x2194, 0xa08e, 0x00ff, 0x0040,
+	0x219a, 0x2009, 0x0000, 0x1078, 0x207f, 0x1078, 0x37e6, 0x00c0,
+	0x2197, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x218e,
+	0x1078, 0x21f1, 0x0040, 0x2197, 0x0078, 0x2194, 0x1078, 0x22f5,
+	0x1078, 0x2218, 0x0040, 0x2197, 0x8318, 0x0078, 0x2163, 0x738e,
+	0x0078, 0x219c, 0x708f, 0xffff, 0x037f, 0x0078, 0x21ee, 0xa780,
+	0x2329, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x708c, 0xa096, 0xffff,
+	0x0040, 0x21b1, 0xa812, 0x00c8, 0x21c1, 0x708f, 0xffff, 0x0078,
+	0x21eb, 0x2009, 0x0000, 0x70bc, 0xd09c, 0x0040, 0x21bc, 0xd094,
+	0x0040, 0x21bc, 0x2009, 0x007e, 0x2100, 0xa802, 0x20a8, 0x0078,
+	0x21c5, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x157e, 0x017e,
+	0xa106, 0x0040, 0x21e2, 0x1078, 0x37e6, 0x00c0, 0x21eb, 0x6004,
+	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x21dc, 0x1078, 0x21f1,
+	0x0040, 0x21eb, 0x0078, 0x21e2, 0x1078, 0x22f5, 0x1078, 0x2218,
+	0x0040, 0x21eb, 0x017f, 0x8108, 0x157f, 0x00f0, 0x21c5, 0x708f,
+	0xffff, 0x0078, 0x21ee, 0x017f, 0x157f, 0x718e, 0x027f, 0x0c7f,
+	0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b94,
+	0x0040, 0x2213, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000,
+	0x1078, 0x37b5, 0x2001, 0x0000, 0x1078, 0x37c9, 0x127e, 0x2091,
+	0x8000, 0x7088, 0x8000, 0x708a, 0x127f, 0x2009, 0x0004, 0x1078,
+	0x5c21, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c,
+	0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b94, 0x0040,
+	0x223a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078,
+	0x37b5, 0x2001, 0x0002, 0x1078, 0x37c9, 0x127e, 0x2091, 0x8000,
+	0x7088, 0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c21,
+	0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e,
+	0x027e, 0x2009, 0x0080, 0x1078, 0x37e6, 0x00c0, 0x224d, 0x1078,
+	0x2250, 0x0040, 0x224d, 0x70c3, 0xffff, 0x027f, 0x0c7f, 0x007c,
+	0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x5b94, 0x0040,
+	0x2272, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078,
+	0x37b5, 0x2001, 0x0002, 0x1078, 0x37c9, 0x127e, 0x2091, 0x8000,
+	0x70c4, 0x8000, 0x70c6, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c21,
+	0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e,
+	0x0d7e, 0x2009, 0x007f, 0x1078, 0x37e6, 0x00c0, 0x2290, 0x2c68,
+	0x1078, 0x5b94, 0x0040, 0x2290, 0x2d00, 0x601a, 0x6312, 0x601f,
+	0x0001, 0x620a, 0x2009, 0x0022, 0x1078, 0x5c21, 0xa085, 0x0001,
+	0x0d7f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x067e, 0x037e, 0x027e,
+	0x1078, 0x4961, 0x1078, 0x4911, 0x1078, 0x60f9, 0x20a9, 0x007f,
+	0x2009, 0x0000, 0x017e, 0x1078, 0x381d, 0x00c0, 0x22ab, 0x1078,
+	0x399e, 0x1078, 0x3619, 0x017f, 0x8108, 0x00f0, 0x22a2, 0x027f,
+	0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x037e,
+	0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029,
+	0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, 0x7370, 0x017f,
+	0x2e60, 0x1078, 0x399e, 0x6210, 0x6314, 0x1078, 0x3619, 0x6212,
+	0x6316, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e,
+	0x007e, 0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x22eb,
+	0x2071, 0x7600, 0x7088, 0xa005, 0x0040, 0x22e8, 0x8001, 0x708a,
+	0x007f, 0x0e7f, 0x007c, 0x2071, 0x7600, 0x70c4, 0xa005, 0x0040,
+	0x22e8, 0x8001, 0x70c6, 0x0078, 0x22e8, 0x6000, 0xc08c, 0x6002,
+	0x007c, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x81ff,
+	0x00c0, 0x2306, 0x20a9, 0x0001, 0x0078, 0x230a, 0x20a9, 0x007f,
+	0x2011, 0x0000, 0x027e, 0xa2e0, 0x7720, 0x2c64, 0x8cff, 0x0040,
+	0x231c, 0x2019, 0x0029, 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08,
+	0x1078, 0x7370, 0x1078, 0x399e, 0x027f, 0x8210, 0x00f0, 0x230a,
+	0x027e, 0x027f, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
+	0x007c, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc,
+	0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1,
+	0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6,
+	0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4,
+	0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa,
+	0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d,
+	0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282,
+	0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074,
+	0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a,
+	0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559,
+	0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d,
+	0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043,
+	0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932,
+	0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227,
+	0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18,
+	0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000,
+	0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000,
+	0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00,
+	0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900,
+	0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200,
+	0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00,
+	0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600,
+	0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00,
+	0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900,
+	0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000,
+	0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000,
+	0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
 	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071,
-	0x766d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a, 0x703e,
-	0x7033, 0x767d, 0x7037, 0x767d, 0x7007, 0x0001, 0x2061, 0x76bd,
-	0x6003, 0x0002, 0x007c, 0x0090, 0x2456, 0x0068, 0x2456, 0x2071,
-	0x766d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2456, 0x2a60, 0x7820,
-	0xa08e, 0x0069, 0x00c0, 0x253d, 0x0079, 0x24da, 0x007c, 0x2071,
-	0x766d, 0x7004, 0x0079, 0x245c, 0x2460, 0x2461, 0x246b, 0x247d,
-	0x007c, 0x0090, 0x246a, 0x0068, 0x246a, 0x2b78, 0x7818, 0xd084,
-	0x0040, 0x2489, 0x007c, 0x2b78, 0x2061, 0x76bd, 0x6008, 0xa08e,
-	0x0100, 0x0040, 0x2478, 0xa086, 0x0200, 0x0040, 0x2535, 0x007c,
-	0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068, 0x6834,
-	0xa086, 0x0103, 0x0040, 0x2485, 0x007c, 0x2a60, 0x2b78, 0x7018,
-	0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2492, 0x61b0,
-	0x0079, 0x249a, 0x2100, 0xa08a, 0x0036, 0x00c8, 0x2531, 0x61b0,
-	0x0079, 0x24da, 0x2513, 0x2545, 0x254d, 0x2551, 0x2559, 0x255f,
-	0x2563, 0x256c, 0x2570, 0x2578, 0x257c, 0x2531, 0x2531, 0x2531,
-	0x2580, 0x2531, 0x2590, 0x25a7, 0x25be, 0x263a, 0x263f, 0x266c,
-	0x26b9, 0x26c8, 0x26e9, 0x271f, 0x2729, 0x2736, 0x2749, 0x2761,
-	0x276a, 0x27a7, 0x27ad, 0x2531, 0x27bd, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x27c1, 0x27c7, 0x2531, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x2531, 0x2531, 0x27cf, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x27dc, 0x27e2, 0x2531, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x2578, 0x257c, 0x2531, 0x2531, 0x27f4, 0x2531,
-	0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531, 0x2531,
-	0x2531, 0x2531, 0x2841, 0x290e, 0x2922, 0x2929, 0x298c, 0x29e7,
-	0x29f2, 0x2a34, 0x2a41, 0x2a4e, 0x2a51, 0x27f8, 0x2a7a, 0x2ac1,
-	0x2ace, 0x2bc8, 0x2cb6, 0x2cdd, 0x2dd5, 0x2de3, 0x2df0, 0x2e2a,
-	0x713c, 0x0078, 0x2513, 0x2021, 0x4000, 0x1078, 0x2d24, 0x127e,
-	0x2091, 0x8000, 0x0068, 0x2520, 0x7818, 0xd084, 0x0040, 0x2523,
-	0x127f, 0x0078, 0x2517, 0x781b, 0x0001, 0x7c22, 0x7926, 0x7a2a,
-	0x7b2e, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091, 0x5000, 0x127f,
-	0x007c, 0x2021, 0x4001, 0x0078, 0x2515, 0x2021, 0x4002, 0x0078,
-	0x2515, 0x2021, 0x4003, 0x0078, 0x2515, 0x2021, 0x4005, 0x0078,
-	0x2515, 0x2021, 0x4006, 0x0078, 0x2515, 0xa02e, 0x2520, 0x7b28,
-	0x7a2c, 0x7824, 0x7930, 0x0078, 0x2d33, 0x7823, 0x0004, 0x7824,
-	0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078,
-	0x2d37, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078, 0x2513, 0x7924,
-	0x2114, 0x0078, 0x2513, 0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9,
-	0x0007, 0x53a3, 0x0078, 0x2513, 0x7824, 0x2060, 0x0078, 0x2582,
-	0x2009, 0x0001, 0x2011, 0x000f, 0x2019, 0x0013, 0x0078, 0x2513,
-	0x7d38, 0x7c3c, 0x0078, 0x2547, 0x7d38, 0x7c3c, 0x0078, 0x2553,
-	0x2061, 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109,
-	0x00c0, 0x2584, 0x2010, 0xa005, 0x0040, 0x2513, 0x0078, 0x2539,
-	0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2541, 0x8019,
-	0x0040, 0x2541, 0x604a, 0x6142, 0x782c, 0x6052, 0x7828, 0x6056,
-	0xa006, 0x605a, 0x605e, 0x1078, 0x3c71, 0x0078, 0x2513, 0x2061,
-	0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2541, 0x8019, 0x0040,
-	0x2541, 0x604e, 0x6146, 0x782c, 0x6062, 0x7828, 0x6066, 0xa006,
-	0x606a, 0x606e, 0x1078, 0x3a47, 0x0078, 0x2513, 0xa02e, 0x2520,
-	0x81ff, 0x00c0, 0x253d, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005,
-	0x20a1, 0x7674, 0x41a1, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x2009,
-	0x0020, 0x1078, 0x2d33, 0x701b, 0x25d6, 0x007c, 0x6834, 0x2008,
-	0xa084, 0x00ff, 0xa096, 0x0011, 0x0040, 0x25e2, 0xa096, 0x0019,
-	0x00c0, 0x253d, 0x810f, 0xa18c, 0x00ff, 0x0040, 0x253d, 0x710e,
-	0x700c, 0x8001, 0x0040, 0x2613, 0x700e, 0x1078, 0x2cfb, 0x0040,
-	0x253d, 0x2009, 0x0020, 0x2061, 0x76bd, 0x6224, 0x6328, 0x642c,
-	0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
-	0x0000, 0x1078, 0x2d33, 0x701b, 0x2606, 0x007c, 0x6834, 0xa084,
-	0x00ff, 0xa096, 0x0002, 0x0040, 0x2611, 0xa096, 0x000a, 0x00c0,
-	0x253d, 0x0078, 0x25e8, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a,
-	0x1078, 0x3722, 0x00c0, 0x2621, 0x7007, 0x0003, 0x701b, 0x2623,
-	0x007c, 0x1078, 0x3b0a, 0x127e, 0x2091, 0x8000, 0x20a9, 0x0005,
-	0x2099, 0x7674, 0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1,
-	0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009, 0x0020, 0x127f,
-	0x0078, 0x2d37, 0x6198, 0x7824, 0x609a, 0x0078, 0x2513, 0x2091,
-	0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f,
-	0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061,
-	0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a,
-	0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000,
-	0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0, 0xa08a, 0x0003,
-	0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, 0x00c0, 0x253d, 0x1078,
-	0x2d13, 0x0040, 0x2541, 0x7c28, 0x7d2c, 0x1078, 0x3969, 0xd28c,
-	0x00c0, 0x267e, 0x1078, 0x38f9, 0x0078, 0x2680, 0x1078, 0x3935,
-	0x00c0, 0x26aa, 0x2061, 0x7d00, 0x127e, 0x2091, 0x8000, 0x6000,
-	0xa086, 0x0000, 0x0040, 0x2698, 0x6010, 0xa06d, 0x0040, 0x2698,
-	0x683c, 0xa406, 0x00c0, 0x2698, 0x6840, 0xa506, 0x0040, 0x26a3,
-	0x127f, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8,
-	0x253d, 0x0078, 0x2684, 0x1078, 0x6738, 0x127f, 0x0040, 0x253d,
-	0x0078, 0x2513, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b0a, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x6b47, 0x1078, 0x3a7a, 0x127f, 0x0078,
-	0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541,
-	0x1078, 0x38ae, 0x1078, 0x397a, 0x0040, 0x253d, 0x0078, 0x2513,
-	0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x2031,
-	0x000f, 0x1078, 0x38ae, 0x8631, 0x00c8, 0x26d1, 0x2019, 0x0005,
-	0x1078, 0x399b, 0x0040, 0x253d, 0x7828, 0xa08a, 0x1000, 0x00c8,
-	0x2541, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x457b, 0x0078,
-	0x2513, 0x127e, 0x2091, 0x8000, 0x81ff, 0x00c0, 0x2719, 0x2029,
-	0x00ff, 0x644c, 0x2400, 0xa506, 0x0040, 0x2713, 0x2508, 0x1078,
-	0x3825, 0x00c0, 0x2713, 0x2031, 0x000f, 0x1078, 0x38ae, 0x8631,
-	0x00c8, 0x26fd, 0x2019, 0x0004, 0x1078, 0x399b, 0x0040, 0x2719,
-	0x7824, 0xa08a, 0x1000, 0x00c8, 0x271c, 0x8003, 0x800b, 0x810b,
-	0xa108, 0x1078, 0x457b, 0x8529, 0x00c8, 0x26f2, 0x127f, 0x0078,
-	0x2513, 0x127f, 0x0078, 0x253d, 0x127f, 0x0078, 0x2541, 0x1078,
-	0x2d13, 0x0040, 0x2541, 0x1078, 0x38de, 0x1078, 0x3969, 0x0078,
-	0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541,
-	0x1078, 0x38c7, 0x1078, 0x3969, 0x0078, 0x2513, 0x81ff, 0x00c0,
-	0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3938, 0x0040,
-	0x253d, 0x1078, 0x376a, 0x1078, 0x38f2, 0x1078, 0x3969, 0x0078,
-	0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x38ae, 0x62a0,
-	0x2019, 0x0005, 0x0c7e, 0x1078, 0x39a6, 0x0c7f, 0x1078, 0x4962,
-	0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x1078, 0x3969, 0x0078,
-	0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3969, 0x2208,
-	0x0078, 0x2513, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0x76ff, 0x6810,
-	0x6914, 0xa10a, 0x00c8, 0x2776, 0x2009, 0x0000, 0x6816, 0x2011,
-	0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069, 0x7720, 0x2d04,
-	0xa075, 0x0040, 0x278b, 0x704c, 0x1078, 0x2795, 0xa210, 0x7080,
-	0x1078, 0x2795, 0xa318, 0x8d68, 0x00f0, 0x277f, 0x2300, 0xa218,
-	0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2513, 0x0f7e, 0x017e, 0xa07d,
-	0x0040, 0x27a4, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0040,
-	0x27a4, 0x2178, 0x0078, 0x279c, 0x017f, 0x0f7f, 0x007c, 0x2069,
-	0x76ff, 0x6910, 0x629c, 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d,
-	0x614c, 0xa190, 0x232f, 0x2214, 0xa294, 0x00ff, 0x6068, 0xa084,
-	0xff00, 0xa215, 0x6364, 0x0078, 0x2513, 0x613c, 0x6240, 0x0078,
-	0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x0078, 0x2513, 0x1078,
-	0x2d13, 0x0040, 0x2541, 0x6244, 0x6338, 0x0078, 0x2513, 0x613c,
-	0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0x7651, 0x831f,
-	0xa305, 0x6816, 0x0078, 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541,
-	0x0078, 0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x7828, 0xa00d,
-	0x0040, 0x2541, 0x782c, 0xa005, 0x0040, 0x2541, 0x6244, 0x6146,
-	0x6338, 0x603a, 0x0078, 0x2513, 0x7d38, 0x7c3c, 0x0078, 0x25c0,
-	0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x253d, 0x624c,
-	0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2810, 0x2001, 0x7640,
-	0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d37,
-	0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x253d, 0x0c7e, 0x1078,
-	0x2cfb, 0x0c7f, 0x0040, 0x253d, 0x6837, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x1078, 0x6a41, 0x0040, 0x253d, 0x7007, 0x0003, 0x701b,
-	0x2832, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x253d, 0xad80,
-	0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
-	0x2d37, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x2009, 0x001c, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2d33, 0x701b, 0x2850, 0x007c,
-	0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x2541, 0x6804, 0xd0ac,
-	0x0040, 0x285d, 0xd0a4, 0x0040, 0x2541, 0xd094, 0x0040, 0x2868,
-	0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf, 0x6106, 0x0c7f,
-	0xd08c, 0x0040, 0x2873, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18d,
-	0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002,
-	0x0048, 0x2888, 0xd084, 0x0040, 0x2888, 0x6a28, 0xa28a, 0x007f,
-	0x00c8, 0x2541, 0xa288, 0x232f, 0x210c, 0xa18c, 0x00ff, 0x6152,
-	0xd0dc, 0x0040, 0x2891, 0x6828, 0xa08a, 0x007f, 0x00c8, 0x2541,
-	0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x2541, 0xa08a, 0x0841,
-	0x00c8, 0x2541, 0xa084, 0x0007, 0x00c0, 0x2541, 0x680c, 0xa005,
-	0x0040, 0x2541, 0x6810, 0xa005, 0x0040, 0x2541, 0x6848, 0x6940,
-	0xa10a, 0x00c8, 0x2541, 0x8001, 0x0040, 0x2541, 0x684c, 0x6944,
-	0xa10a, 0x00c8, 0x2541, 0x8001, 0x0040, 0x2541, 0x20a9, 0x001c,
-	0x2d98, 0x2069, 0x7651, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff,
-	0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078, 0x3c71, 0x1078,
-	0x3a47, 0x6000, 0xa086, 0x0000, 0x00c0, 0x290c, 0x6808, 0x602a,
-	0x1078, 0x1dea, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f,
-	0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4,
-	0x0040, 0x28ec, 0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f,
-	0x8217, 0x831f, 0x0078, 0x28ee, 0xa084, 0xf0ff, 0x6006, 0x610a,
-	0x620e, 0x6312, 0x1078, 0x4607, 0x0c7e, 0x2061, 0x0100, 0x602f,
-	0x0040, 0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005, 0x0040, 0x2908,
-	0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x357b, 0x0078, 0x290c,
-	0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2513, 0x6000, 0xa086,
-	0x0000, 0x0040, 0x253d, 0x2069, 0x7651, 0x7830, 0x6842, 0x7834,
-	0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x0078, 0x2d37, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x357b, 0x0078,
-	0x2513, 0x81ff, 0x00c0, 0x253d, 0x617c, 0x81ff, 0x0040, 0x2943,
-	0x703f, 0x0000, 0x2001, 0x7cc0, 0x2009, 0x0040, 0x7a2c, 0x7b28,
-	0x7c3c, 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078, 0x2d37, 0x701b,
-	0x2510, 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0x7cc0,
-	0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2019, 0xffff, 0x43a4, 0x654c,
-	0xa588, 0x232f, 0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011,
-	0x0002, 0x2100, 0xa506, 0x0040, 0x2975, 0x1078, 0x3825, 0x00c0,
-	0x2975, 0x6014, 0x821c, 0x0048, 0x296d, 0xa398, 0x7cc0, 0xa085,
-	0xff00, 0x8007, 0x201a, 0x0078, 0x2974, 0xa398, 0x7cc0, 0x2324,
-	0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080,
-	0x00c8, 0x297c, 0x0078, 0x2959, 0x8201, 0x8007, 0x2d0c, 0xa105,
-	0x206a, 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2099, 0x7cc0,
-	0x1078, 0x35c4, 0x0078, 0x2932, 0x1078, 0x2d13, 0x0040, 0x2541,
-	0x0c7e, 0x1078, 0x2cfb, 0x0c7f, 0x0040, 0x253d, 0x2001, 0x7652,
-	0x2004, 0xd0b4, 0x0040, 0x29b9, 0x6000, 0xd08c, 0x00c0, 0x29b9,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x29b9, 0x6837,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a79, 0x0040, 0x253d,
-	0x7007, 0x0003, 0x701b, 0x29b5, 0x007c, 0x1078, 0x2d13, 0x0040,
-	0x2541, 0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3,
-	0x20a9, 0x0002, 0xac80, 0x0004, 0x2098, 0xad80, 0x0004, 0x20a0,
-	0x1078, 0x35c4, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80,
-	0x0006, 0x20a0, 0x1078, 0x35c4, 0x20a9, 0x0004, 0xac80, 0x000a,
-	0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x35c4, 0x2d00, 0x2009,
-	0x0029, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d37, 0x81ff,
-	0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541, 0x1078, 0x3985,
-	0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d, 0x7828, 0xa08a, 0x1000,
-	0x00c8, 0x2541, 0x1078, 0x2d13, 0x0040, 0x2541, 0x2031, 0x000f,
-	0x1078, 0x38ae, 0x8631, 0x00c8, 0x2a00, 0x2019, 0x0004, 0x1078,
-	0x399b, 0x7924, 0x810f, 0x7a28, 0x1078, 0x2a10, 0x0078, 0x2513,
-	0xa186, 0x00ff, 0x0040, 0x2a18, 0x1078, 0x2a28, 0x0078, 0x2a27,
+	0x8000, 0x2071, 0x766d, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016,
+	0x703a, 0x703e, 0x7033, 0x767d, 0x7037, 0x767d, 0x7007, 0x0001,
+	0x2061, 0x76bd, 0x6003, 0x0002, 0x007c, 0x0090, 0x2450, 0x0068,
+	0x2450, 0x2071, 0x766d, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2450,
+	0x2a60, 0x7820, 0xa08e, 0x0069, 0x00c0, 0x2537, 0x0079, 0x24d4,
+	0x007c, 0x2071, 0x766d, 0x7004, 0x0079, 0x2456, 0x245a, 0x245b,
+	0x2465, 0x2477, 0x007c, 0x0090, 0x2464, 0x0068, 0x2464, 0x2b78,
+	0x7818, 0xd084, 0x0040, 0x2483, 0x007c, 0x2b78, 0x2061, 0x76bd,
+	0x6008, 0xa08e, 0x0100, 0x0040, 0x2472, 0xa086, 0x0200, 0x0040,
+	0x252f, 0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010,
+	0x2068, 0x6834, 0xa086, 0x0103, 0x0040, 0x247f, 0x007c, 0x2a60,
+	0x2b78, 0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8,
+	0x248c, 0x61b0, 0x0079, 0x2494, 0x2100, 0xa08a, 0x0036, 0x00c8,
+	0x252b, 0x61b0, 0x0079, 0x24d4, 0x250d, 0x253f, 0x2547, 0x254b,
+	0x2553, 0x2559, 0x255d, 0x2566, 0x256a, 0x2572, 0x2576, 0x252b,
+	0x252b, 0x252b, 0x257a, 0x252b, 0x258a, 0x25a1, 0x25b8, 0x2634,
+	0x2639, 0x2666, 0x26b3, 0x26c2, 0x26e3, 0x2719, 0x2723, 0x2730,
+	0x2743, 0x275b, 0x2764, 0x27a1, 0x27a7, 0x252b, 0x27b7, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x27bb, 0x27c1, 0x252b, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x27c9, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x27d6, 0x27dc, 0x252b, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x2572, 0x2576, 0x252b, 0x252b,
+	0x27ee, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b, 0x252b,
+	0x252b, 0x252b, 0x252b, 0x252b, 0x283b, 0x2908, 0x291c, 0x2923,
+	0x2986, 0x29d7, 0x29e2, 0x2a24, 0x2a31, 0x2a3e, 0x2a41, 0x27f2,
+	0x2a6a, 0x2ab1, 0x2abe, 0x2bb9, 0x2ca7, 0x2cce, 0x2dc6, 0x2dd4,
+	0x2de1, 0x2e1b, 0x713c, 0x0078, 0x250d, 0x2021, 0x4000, 0x1078,
+	0x2d15, 0x127e, 0x2091, 0x8000, 0x0068, 0x251a, 0x7818, 0xd084,
+	0x0040, 0x251d, 0x127f, 0x0078, 0x2511, 0x781b, 0x0001, 0x7c22,
+	0x7926, 0x7a2a, 0x7b2e, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091,
+	0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x250f, 0x2021,
+	0x4002, 0x0078, 0x250f, 0x2021, 0x4003, 0x0078, 0x250f, 0x2021,
+	0x4005, 0x0078, 0x250f, 0x2021, 0x4006, 0x0078, 0x250f, 0xa02e,
+	0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x2d24, 0x7823,
+	0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824,
+	0x7930, 0x0078, 0x2d28, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078,
+	0x250d, 0x7924, 0x2114, 0x0078, 0x250d, 0x2099, 0x0009, 0x20a1,
+	0x0009, 0x20a9, 0x0007, 0x53a3, 0x0078, 0x250d, 0x7824, 0x2060,
+	0x0078, 0x257c, 0x2009, 0x0001, 0x2011, 0x000f, 0x2019, 0x0025,
+	0x0078, 0x250d, 0x7d38, 0x7c3c, 0x0078, 0x2541, 0x7d38, 0x7c3c,
+	0x0078, 0x254d, 0x2061, 0x1000, 0x610c, 0xa006, 0x2c14, 0xa200,
+	0x8c60, 0x8109, 0x00c0, 0x257e, 0x2010, 0xa005, 0x0040, 0x250d,
+	0x0078, 0x2533, 0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8,
+	0x253b, 0x8019, 0x0040, 0x253b, 0x604a, 0x6142, 0x782c, 0x6052,
+	0x7828, 0x6056, 0xa006, 0x605a, 0x605e, 0x1078, 0x3c69, 0x0078,
+	0x250d, 0x2061, 0x7651, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x253b,
+	0x8019, 0x0040, 0x253b, 0x604e, 0x6146, 0x782c, 0x6062, 0x7828,
+	0x6066, 0xa006, 0x606a, 0x606e, 0x1078, 0x3a3f, 0x0078, 0x250d,
+	0xa02e, 0x2520, 0x81ff, 0x00c0, 0x2537, 0x7924, 0x7b28, 0x7a2c,
+	0x20a9, 0x0005, 0x20a1, 0x7674, 0x41a1, 0x1078, 0x2cec, 0x0040,
+	0x2537, 0x2009, 0x0020, 0x1078, 0x2d24, 0x701b, 0x25d0, 0x007c,
+	0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0040, 0x25dc,
+	0xa096, 0x0019, 0x00c0, 0x2537, 0x810f, 0xa18c, 0x00ff, 0x0040,
+	0x2537, 0x710e, 0x700c, 0x8001, 0x0040, 0x260d, 0x700e, 0x1078,
+	0x2cec, 0x0040, 0x2537, 0x2009, 0x0020, 0x2061, 0x76bd, 0x6224,
+	0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1,
+	0x0000, 0xa5a9, 0x0000, 0x1078, 0x2d24, 0x701b, 0x2600, 0x007c,
+	0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x260b, 0xa096,
+	0x000a, 0x00c0, 0x2537, 0x0078, 0x25e2, 0x7010, 0x2068, 0x6838,
+	0xc0fd, 0x683a, 0x1078, 0x371a, 0x00c0, 0x261b, 0x7007, 0x0003,
+	0x701b, 0x261d, 0x007c, 0x1078, 0x3b02, 0x127e, 0x2091, 0x8000,
+	0x20a9, 0x0005, 0x2099, 0x7674, 0x530a, 0x2100, 0xa210, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d, 0x2009,
+	0x0020, 0x127f, 0x0078, 0x2d28, 0x6198, 0x7824, 0x609a, 0x0078,
+	0x250d, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953, 0x782b,
+	0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832, 0x3f00,
+	0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c, 0x8007,
+	0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b, 0x0001,
+	0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1, 0x00f0,
+	0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff, 0x00c0,
+	0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, 0x7c28, 0x7d2c, 0x1078,
+	0x3961, 0xd28c, 0x00c0, 0x2678, 0x1078, 0x38f1, 0x0078, 0x267a,
+	0x1078, 0x392d, 0x00c0, 0x26a4, 0x2061, 0x7d00, 0x127e, 0x2091,
+	0x8000, 0x6000, 0xa086, 0x0000, 0x0040, 0x2692, 0x6010, 0xa06d,
+	0x0040, 0x2692, 0x683c, 0xa406, 0x00c0, 0x2692, 0x6840, 0xa506,
+	0x0040, 0x269d, 0x127f, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004,
+	0xac02, 0x00c8, 0x2537, 0x0078, 0x267e, 0x1078, 0x6732, 0x127f,
+	0x0040, 0x2537, 0x0078, 0x250d, 0xa00e, 0x2001, 0x0005, 0x1078,
+	0x3b02, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b3c, 0x1078, 0x3a72,
+	0x127f, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04,
+	0x0040, 0x253b, 0x1078, 0x38a6, 0x1078, 0x3972, 0x0040, 0x2537,
+	0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040,
+	0x253b, 0x2031, 0x000f, 0x1078, 0x38a6, 0x8631, 0x00c8, 0x26cb,
+	0x2019, 0x0005, 0x1078, 0x3993, 0x0040, 0x2537, 0x7828, 0xa08a,
+	0x1000, 0x00c8, 0x253b, 0x8003, 0x800b, 0x810b, 0xa108, 0x1078,
+	0x4573, 0x0078, 0x250d, 0x127e, 0x2091, 0x8000, 0x81ff, 0x00c0,
+	0x2713, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506, 0x0040, 0x270d,
+	0x2508, 0x1078, 0x381d, 0x00c0, 0x270d, 0x2031, 0x000f, 0x1078,
+	0x38a6, 0x8631, 0x00c8, 0x26f7, 0x2019, 0x0004, 0x1078, 0x3993,
+	0x0040, 0x2713, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2716, 0x8003,
+	0x800b, 0x810b, 0xa108, 0x1078, 0x4573, 0x8529, 0x00c8, 0x26ec,
+	0x127f, 0x0078, 0x250d, 0x127f, 0x0078, 0x2537, 0x127f, 0x0078,
+	0x253b, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, 0x38d6, 0x1078,
+	0x3961, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04,
+	0x0040, 0x253b, 0x1078, 0x38bf, 0x1078, 0x3961, 0x0078, 0x250d,
+	0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078,
+	0x3930, 0x0040, 0x2537, 0x1078, 0x3762, 0x1078, 0x38ea, 0x1078,
+	0x3961, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078,
+	0x38a6, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078, 0x399e, 0x0c7f,
+	0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, 0x7370, 0x1078,
+	0x3961, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078,
+	0x3961, 0x2208, 0x0078, 0x250d, 0x157e, 0x0d7e, 0x0e7e, 0x2069,
+	0x76ff, 0x6810, 0x6914, 0xa10a, 0x00c8, 0x2770, 0x2009, 0x0000,
+	0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069,
+	0x7720, 0x2d04, 0xa075, 0x0040, 0x2785, 0x704c, 0x1078, 0x278f,
+	0xa210, 0x7080, 0x1078, 0x278f, 0xa318, 0x8d68, 0x00f0, 0x2779,
+	0x2300, 0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x250d, 0x0f7e,
+	0x017e, 0xa07d, 0x0040, 0x279e, 0x2001, 0x0000, 0x8000, 0x2f0c,
+	0x81ff, 0x0040, 0x279e, 0x2178, 0x0078, 0x2796, 0x017f, 0x0f7f,
+	0x007c, 0x2069, 0x76ff, 0x6910, 0x629c, 0x0078, 0x250d, 0x81ff,
+	0x00c0, 0x2537, 0x614c, 0xa190, 0x2329, 0x2214, 0xa294, 0x00ff,
+	0x6068, 0xa084, 0xff00, 0xa215, 0x6364, 0x0078, 0x250d, 0x613c,
+	0x6240, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x0078,
+	0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x6244, 0x6338, 0x0078,
+	0x250d, 0x613c, 0x6240, 0x7824, 0x603e, 0x7b28, 0x6342, 0x2069,
+	0x7651, 0x831f, 0xa305, 0x6816, 0x0078, 0x250d, 0x1078, 0x2d04,
+	0x0040, 0x253b, 0x0078, 0x250d, 0x1078, 0x2d04, 0x0040, 0x253b,
+	0x7828, 0xa00d, 0x0040, 0x253b, 0x782c, 0xa005, 0x0040, 0x253b,
+	0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x250d, 0x7d38, 0x7c3c,
+	0x0078, 0x25ba, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8,
+	0x2537, 0x624c, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x280a,
+	0x2001, 0x7640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0x0078, 0x2d28, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040,
+	0x253b, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2537,
+	0x0c7e, 0x1078, 0x2cec, 0x0c7f, 0x0040, 0x2537, 0x6837, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a36, 0x0040, 0x2537, 0x7007,
+	0x0003, 0x701b, 0x282c, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040,
+	0x2537, 0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c,
+	0x7d38, 0x0078, 0x2d28, 0x1078, 0x2cec, 0x0040, 0x2537, 0x2009,
+	0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2d24, 0x701b,
+	0x284a, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040, 0x253b,
+	0x6804, 0xd0ac, 0x0040, 0x2857, 0xd0a4, 0x0040, 0x253b, 0xd094,
+	0x0040, 0x2862, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c, 0xffdf,
+	0x6106, 0x0c7f, 0xd08c, 0x0040, 0x286d, 0x0c7e, 0x2061, 0x0100,
+	0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100, 0x210c,
+	0xa18a, 0x0002, 0x0048, 0x2882, 0xd084, 0x0040, 0x2882, 0x6a28,
+	0xa28a, 0x007f, 0x00c8, 0x253b, 0xa288, 0x2329, 0x210c, 0xa18c,
+	0x00ff, 0x6152, 0xd0dc, 0x0040, 0x288b, 0x6828, 0xa08a, 0x007f,
+	0x00c8, 0x253b, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0048, 0x253b,
+	0xa08a, 0x0841, 0x00c8, 0x253b, 0xa084, 0x0007, 0x00c0, 0x253b,
+	0x680c, 0xa005, 0x0040, 0x253b, 0x6810, 0xa005, 0x0040, 0x253b,
+	0x6848, 0x6940, 0xa10a, 0x00c8, 0x253b, 0x8001, 0x0040, 0x253b,
+	0x684c, 0x6944, 0xa10a, 0x00c8, 0x253b, 0x8001, 0x0040, 0x253b,
+	0x20a9, 0x001c, 0x2d98, 0x2069, 0x7651, 0x2da0, 0x53a3, 0x6814,
+	0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff, 0x6042, 0x1078,
+	0x3c69, 0x1078, 0x3a3f, 0x6000, 0xa086, 0x0000, 0x00c0, 0x2906,
+	0x6808, 0x602a, 0x1078, 0x1de4, 0x6818, 0x691c, 0x6a20, 0x6b24,
+	0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e, 0x6322,
+	0x6c04, 0xd4f4, 0x0040, 0x28e6, 0x6830, 0x6934, 0x6a38, 0x6b3c,
+	0x8007, 0x810f, 0x8217, 0x831f, 0x0078, 0x28e8, 0xa084, 0xf0ff,
+	0x6006, 0x610a, 0x620e, 0x6312, 0x1078, 0x45ff, 0x0c7e, 0x2061,
+	0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x60b4, 0xa005,
+	0x0040, 0x2902, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x3573,
+	0x0078, 0x2906, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x250d,
+	0x6000, 0xa086, 0x0000, 0x0040, 0x2537, 0x2069, 0x7651, 0x7830,
+	0x6842, 0x7834, 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28,
+	0x7c3c, 0x7d38, 0x0078, 0x2d28, 0x81ff, 0x00c0, 0x2537, 0x1078,
+	0x3573, 0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x617c, 0x81ff,
+	0x0040, 0x293d, 0x703f, 0x0000, 0x2001, 0x7cc0, 0x2009, 0x0040,
+	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x127e, 0x2091, 0x8000, 0x1078,
+	0x2d28, 0x701b, 0x250a, 0x127f, 0x007c, 0x703f, 0x0001, 0x0d7e,
+	0x2069, 0x7cc0, 0x20a9, 0x0040, 0x20a1, 0x7cc0, 0x2019, 0xffff,
+	0x43a4, 0x654c, 0xa588, 0x2329, 0x210c, 0xa18c, 0x00ff, 0x216a,
+	0xa00e, 0x2011, 0x0002, 0x2100, 0xa506, 0x0040, 0x296f, 0x1078,
+	0x381d, 0x00c0, 0x296f, 0x6014, 0x821c, 0x0048, 0x2967, 0xa398,
+	0x7cc0, 0xa085, 0xff00, 0x8007, 0x201a, 0x0078, 0x296e, 0xa398,
+	0x7cc0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a, 0x8210, 0x8108,
+	0xa182, 0x0080, 0x00c8, 0x2976, 0x0078, 0x2953, 0x8201, 0x8007,
+	0x2d0c, 0xa105, 0x206a, 0x0d7f, 0x20a9, 0x0040, 0x20a1, 0x7cc0,
+	0x2099, 0x7cc0, 0x1078, 0x35bc, 0x0078, 0x292c, 0x1078, 0x2d04,
+	0x0040, 0x253b, 0x0c7e, 0x1078, 0x2cec, 0x0c7f, 0x0040, 0x2537,
+	0x2001, 0x7652, 0x2004, 0xd0b4, 0x0040, 0x29b3, 0x6000, 0xd08c,
+	0x00c0, 0x29b3, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
+	0x29b3, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x6a6e,
+	0x0040, 0x2537, 0x7007, 0x0003, 0x701b, 0x29af, 0x007c, 0x1078,
+	0x2d04, 0x0040, 0x253b, 0x20a9, 0x0029, 0x2c98, 0xade8, 0x0002,
+	0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80,
+	0x0006, 0x20a0, 0x1078, 0x35bc, 0x20a9, 0x0004, 0xac80, 0x000a,
+	0x2098, 0xad80, 0x000a, 0x20a0, 0x1078, 0x35bc, 0x2d00, 0x2009,
+	0x0029, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078, 0x2d28, 0x81ff,
+	0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b, 0x1078, 0x397d,
+	0x0078, 0x250d, 0x81ff, 0x00c0, 0x2537, 0x7828, 0xa08a, 0x1000,
+	0x00c8, 0x253b, 0x1078, 0x2d04, 0x0040, 0x253b, 0x2031, 0x000f,
+	0x1078, 0x38a6, 0x8631, 0x00c8, 0x29f0, 0x2019, 0x0004, 0x1078,
+	0x3993, 0x7924, 0x810f, 0x7a28, 0x1078, 0x2a00, 0x0078, 0x250d,
+	0xa186, 0x00ff, 0x0040, 0x2a08, 0x1078, 0x2a18, 0x0078, 0x2a17,
 	0x2029, 0x007e, 0x2061, 0x7600, 0x644c, 0x2400, 0xa506, 0x0040,
-	0x2a24, 0x2508, 0x1078, 0x2a28, 0x8529, 0x00c8, 0x2a1d, 0x007c,
-	0x1078, 0x3825, 0x00c0, 0x2a33, 0x2200, 0x8003, 0x800b, 0x810b,
-	0xa108, 0x1078, 0x457b, 0x007c, 0x81ff, 0x00c0, 0x253d, 0x1078,
-	0x2d13, 0x0040, 0x2541, 0x1078, 0x38ae, 0x1078, 0x3990, 0x0078,
-	0x2513, 0x81ff, 0x00c0, 0x253d, 0x1078, 0x2d13, 0x0040, 0x2541,
-	0x1078, 0x38ae, 0x1078, 0x397a, 0x0078, 0x2513, 0x6100, 0x0078,
-	0x2513, 0x1078, 0x2d13, 0x0040, 0x2541, 0x6004, 0xa086, 0x0707,
-	0x0040, 0x2541, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x253d, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x2a6a,
+	0x2a14, 0x2508, 0x1078, 0x2a18, 0x8529, 0x00c8, 0x2a0d, 0x007c,
+	0x1078, 0x381d, 0x00c0, 0x2a23, 0x2200, 0x8003, 0x800b, 0x810b,
+	0xa108, 0x1078, 0x4573, 0x007c, 0x81ff, 0x00c0, 0x2537, 0x1078,
+	0x2d04, 0x0040, 0x253b, 0x1078, 0x38a6, 0x1078, 0x3988, 0x0078,
+	0x250d, 0x81ff, 0x00c0, 0x2537, 0x1078, 0x2d04, 0x0040, 0x253b,
+	0x1078, 0x38a6, 0x1078, 0x3972, 0x0078, 0x250d, 0x6100, 0x0078,
+	0x250d, 0x1078, 0x2d04, 0x0040, 0x253b, 0x6004, 0xa086, 0x0707,
+	0x0040, 0x253b, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0,
+	0x2537, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x2a5a,
 	0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a,
 	0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200,
-	0x0078, 0x2513, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0040,
-	0x2a84, 0x81ff, 0x00c0, 0x253d, 0x7828, 0xa08a, 0x1000, 0x00c8,
-	0x2541, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040,
-	0x2a98, 0xa182, 0x007f, 0x00c8, 0x2541, 0x2100, 0x1078, 0x209a,
+	0x0078, 0x250d, 0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0040,
+	0x2a74, 0x81ff, 0x00c0, 0x2537, 0x7828, 0xa08a, 0x1000, 0x00c8,
+	0x253b, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0040,
+	0x2a88, 0xa182, 0x007f, 0x00c8, 0x253b, 0x2100, 0x1078, 0x2094,
 	0x027e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7849, 0x601b,
 	0x0000, 0x601f, 0x0000, 0x2061, 0x0100, 0x6030, 0xa084, 0x00ff,
 	0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
-	0x001e, 0x2011, 0x35a0, 0x1078, 0x45fe, 0x7924, 0xa18c, 0xff00,
-	0x810f, 0x7a28, 0x1078, 0x2a10, 0x127f, 0x0c7f, 0x027f, 0x0078,
-	0x2513, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x37ee,
-	0x2c08, 0x0c7f, 0x00c0, 0x2541, 0x0078, 0x2513, 0x81ff, 0x00c0,
-	0x253d, 0x60bc, 0xd09c, 0x0040, 0x253d, 0x1078, 0x2cfb, 0x0040,
-	0x253d, 0x6823, 0x0000, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x1078, 0x2d33, 0x701b, 0x2ae5, 0x007c, 0x2009, 0x0080, 0x1078,
-	0x3825, 0x00c0, 0x2af2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x0040, 0x2af6, 0x2021, 0x400a, 0x0078, 0x2515, 0x0d7e, 0xade8,
+	0x001e, 0x2011, 0x3598, 0x1078, 0x45f6, 0x7924, 0xa18c, 0xff00,
+	0x810f, 0x7a28, 0x1078, 0x2a00, 0x127f, 0x0c7f, 0x027f, 0x0078,
+	0x250d, 0x7924, 0xa18c, 0xff00, 0x810f, 0x0c7e, 0x1078, 0x37e6,
+	0x2c08, 0x0c7f, 0x00c0, 0x253b, 0x0078, 0x250d, 0x81ff, 0x00c0,
+	0x2537, 0x60bc, 0xd09c, 0x0040, 0x2537, 0x1078, 0x2cec, 0x0040,
+	0x2537, 0x6823, 0x0000, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
+	0x1078, 0x2d24, 0x701b, 0x2ad5, 0x007c, 0x2009, 0x0080, 0x1078,
+	0x381d, 0x00c0, 0x2ae2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x0040, 0x2ae6, 0x2021, 0x400a, 0x0078, 0x250f, 0x0d7e, 0xade8,
 	0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820,
-	0xa0be, 0x0100, 0x0040, 0x2b68, 0xa0be, 0x0112, 0x0040, 0x2b68,
-	0xa0be, 0x0113, 0x0040, 0x2b68, 0xa0be, 0x0114, 0x0040, 0x2b68,
-	0xa0be, 0x0117, 0x0040, 0x2b68, 0xa0be, 0x011a, 0x0040, 0x2b68,
-	0xa0be, 0x0121, 0x0040, 0x2b5e, 0xa0be, 0x0131, 0x0040, 0x2b5e,
-	0xa0be, 0x0171, 0x0040, 0x2b68, 0xa0be, 0x0173, 0x0040, 0x2b68,
-	0xa0be, 0x01a1, 0x00c0, 0x2b31, 0x6830, 0x8007, 0x6832, 0x0078,
-	0x2b6e, 0xa0be, 0x0212, 0x0040, 0x2b64, 0xa0be, 0x0213, 0x0040,
-	0x2b64, 0xa0be, 0x0214, 0x0040, 0x2b56, 0xa0be, 0x0217, 0x0040,
-	0x2b50, 0xa0be, 0x021a, 0x00c0, 0x2b4a, 0x6838, 0x8007, 0x683a,
-	0x0078, 0x2b68, 0xa0be, 0x0300, 0x0040, 0x2b68, 0x0078, 0x2541,
-	0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x2ba4, 0xad80, 0x000e,
-	0x20a9, 0x0001, 0x1078, 0x2ba4, 0x0078, 0x2b68, 0xad80, 0x000c,
-	0x1078, 0x2bb2, 0x0078, 0x2b6e, 0xad80, 0x000e, 0x1078, 0x2bb2,
-	0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x2ba4, 0x0c7e, 0x1078,
-	0x2cfb, 0x0040, 0x2b99, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119,
-	0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883, 0x0000,
-	0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000, 0x0c7f,
-	0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000,
-	0x1078, 0x6a5d, 0x0040, 0x253d, 0x7007, 0x0003, 0x701b, 0x2b9d,
-	0x007c, 0x0c7f, 0x0d7f, 0x0078, 0x253d, 0x6820, 0xa086, 0x8001,
-	0x0040, 0x253d, 0x0078, 0x2513, 0x017e, 0x2008, 0x2044, 0x8000,
-	0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x00f0, 0x2ba6,
-	0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008, 0x2044, 0x8000,
-	0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108, 0x2a0a,
-	0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f, 0x017f, 0x007c,
-	0x81ff, 0x00c0, 0x253d, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f,
-	0xa182, 0x0080, 0x0048, 0x2541, 0xa182, 0x00ff, 0x00c8, 0x2541,
-	0x7a2c, 0x7b28, 0x6064, 0xa306, 0x00c0, 0x2be6, 0x6068, 0xa24e,
-	0x0040, 0x2541, 0xa9cc, 0xff00, 0x0040, 0x2541, 0x0c7e, 0x1078,
-	0x2c5a, 0x2c68, 0x0c7f, 0x0040, 0x2c0d, 0xa0c6, 0x4000, 0x00c0,
-	0x2bf3, 0x0078, 0x2c0a, 0xa0c6, 0x4007, 0x00c0, 0x2bfa, 0x2408,
-	0x0078, 0x2c0a, 0xa0c6, 0x4008, 0x00c0, 0x2c02, 0x2708, 0x2610,
-	0x0078, 0x2c0a, 0xa0c6, 0x4009, 0x00c0, 0x2c08, 0x0078, 0x2c0a,
-	0x2001, 0x4006, 0x2020, 0x0078, 0x2515, 0x017e, 0x0b7e, 0x0c7e,
-	0x0e7e, 0x2c70, 0x1078, 0x5b9c, 0x0040, 0x2c48, 0x2d00, 0x601a,
-	0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x2cfb, 0x0c7f, 0x2b70,
-	0x0040, 0x253d, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x22bb,
-	0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
-	0x0002, 0x1078, 0x37d1, 0x127e, 0x2091, 0x8000, 0x7088, 0x8000,
-	0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c29, 0xa085, 0x0001,
-	0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x253d, 0x7007, 0x0003,
-	0x701b, 0x2c53, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0, 0x2513,
-	0x0078, 0x253d, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080,
-	0x20a9, 0x007f, 0x2071, 0x77a0, 0x2e04, 0xa005, 0x00c0, 0x2c6e,
-	0x2100, 0xa406, 0x0040, 0x2cab, 0x0078, 0x2c9f, 0x2068, 0x6f10,
-	0x2700, 0xa306, 0x00c0, 0x2c90, 0x6e14, 0x2600, 0xa206, 0x00c0,
-	0x2c90, 0x2400, 0xa106, 0x00c0, 0x2c8c, 0x2d60, 0xd884, 0x0040,
-	0x2cb1, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2cb1,
-	0x2001, 0x4000, 0x0078, 0x2cb2, 0x2001, 0x4007, 0x0078, 0x2cb2,
-	0x2400, 0xa106, 0x00c0, 0x2c9f, 0x6e14, 0x87ff, 0x00c0, 0x2c9b,
-	0x86ff, 0x0040, 0x2cab, 0x2001, 0x4008, 0x0078, 0x2cb2, 0x8420,
-	0x8e70, 0x00f0, 0x2c64, 0x2001, 0x4009, 0x0078, 0x2cb2, 0x2001,
-	0x0001, 0x0078, 0x2cb2, 0x1078, 0x37ee, 0x00c0, 0x2ca7, 0x6312,
-	0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff, 0x00c0,
-	0x253d, 0x1078, 0x2cfb, 0x0040, 0x253d, 0x6837, 0x0000, 0x7824,
-	0xa005, 0x0040, 0x2541, 0xa096, 0x00ff, 0x0040, 0x2ccb, 0xa092,
-	0x0004, 0x00c8, 0x2541, 0x2010, 0x2d18, 0x1078, 0x227d, 0x0040,
-	0x253d, 0x7007, 0x0003, 0x701b, 0x2cd6, 0x007c, 0x6830, 0xa086,
-	0x0100, 0x0040, 0x253d, 0x0078, 0x2513, 0x81ff, 0x00c0, 0x253d,
-	0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048, 0x2541,
-	0xa182, 0x00ff, 0x00c8, 0x2541, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x697f, 0x00c0, 0x2cf8, 0x1078, 0x380d, 0x127f, 0x0078, 0x2513,
-	0x127f, 0x0078, 0x253d, 0x1078, 0x132f, 0x0040, 0x2d12, 0xa006,
-	0x6802, 0x7010, 0xa005, 0x00c0, 0x2d0a, 0x2d00, 0x7012, 0x7016,
-	0x0078, 0x2d10, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016,
-	0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x1078,
-	0x3825, 0x00c0, 0x2d21, 0xa6b4, 0x00ff, 0xa682, 0x0010, 0x0048,
-	0x2d22, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff, 0x0040,
-	0x2d2f, 0x2168, 0x6904, 0x1078, 0x1348, 0x0078, 0x2d26, 0x7112,
-	0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2d39, 0x2031,
-	0x0000, 0x2061, 0x76bd, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a,
-	0x642e, 0x6532, 0x2c10, 0x1078, 0x137f, 0x7007, 0x0002, 0x701b,
-	0x2513, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079, 0x0000,
-	0x2001, 0x767b, 0x2004, 0xa005, 0x00c0, 0x2d65, 0x0068, 0x2d65,
-	0x7818, 0xd084, 0x00c0, 0x2d65, 0x781b, 0x0001, 0x7a22, 0x7b26,
-	0x7c2a, 0x2091, 0x4080, 0x0078, 0x2d8a, 0x017e, 0x0c7e, 0x0e7e,
-	0x2071, 0x766d, 0x7138, 0xa182, 0x0008, 0x0048, 0x2d73, 0x7030,
-	0x2060, 0x0078, 0x2d84, 0x7030, 0xa0e0, 0x0008, 0xac82, 0x76bd,
-	0x0048, 0x2d7c, 0x2061, 0x767d, 0x2c00, 0x7032, 0x81ff, 0x00c0,
-	0x2d82, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x0e7f,
-	0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071, 0x766d,
-	0x7038, 0xa005, 0x0040, 0x2dc6, 0x127e, 0x2091, 0x8000, 0x0068,
-	0x2dc5, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x2dc4,
-	0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004,
-	0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a,
-	0xa005, 0x00c0, 0x2dba, 0x7033, 0x767d, 0x7037, 0x767d, 0x0c7f,
-	0x0078, 0x2dc4, 0xac80, 0x0008, 0xa0fa, 0x76bd, 0x0048, 0x2dc2,
-	0x2001, 0x767d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f, 0x007c,
-	0x027e, 0x2001, 0x7652, 0x2004, 0xd0c4, 0x0040, 0x2dd3, 0x2011,
-	0x8014, 0x1078, 0x2d4a, 0x027f, 0x007c, 0x81ff, 0x00c0, 0x253d,
-	0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078, 0x357b,
-	0x127f, 0x0078, 0x2513, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x00c0,
-	0x2dee, 0x61c8, 0xa10d, 0x61ca, 0x0078, 0x2513, 0x0078, 0x2541,
-	0x81ff, 0x00c0, 0x253d, 0x6000, 0xa086, 0x0003, 0x00c0, 0x253d,
-	0x2001, 0x7652, 0x2004, 0xd0a4, 0x00c0, 0x253d, 0x1078, 0x2d13,
-	0x0040, 0x2541, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
-	0x2e0d, 0x7828, 0xa005, 0x0040, 0x2513, 0x0c7e, 0x1078, 0x2cfb,
-	0x0c7f, 0x0040, 0x253d, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x1078, 0x6ae6, 0x0040, 0x253d, 0x7007, 0x0003,
-	0x701b, 0x2e23, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x253d,
-	0x0078, 0x2513, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x253d, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x2cfb,
-	0x0040, 0x253d, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000,
-	0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x3825,
-	0x00c0, 0x2e70, 0x6004, 0xa0c6, 0x0707, 0x0040, 0x2e70, 0xa084,
-	0x00ff, 0xa0c6, 0x0006, 0x00c0, 0x2e70, 0x87ff, 0x0040, 0x2e63,
-	0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078,
-	0x2bb2, 0x0078, 0x2e6c, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9,
-	0x0004, 0x53a3, 0x1078, 0x2bb2, 0x21a2, 0x94a0, 0xa6b0, 0x0005,
-	0x8108, 0xa186, 0x007e, 0x0040, 0x2e7b, 0xa686, 0x0028, 0x0040,
-	0x2e84, 0x0078, 0x2e46, 0x86ff, 0x00c0, 0x2e82, 0x7120, 0x810b,
-	0x0078, 0x2513, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600, 0x7022,
-	0x772a, 0x2061, 0x76bd, 0x6007, 0x0000, 0x6612, 0x7024, 0x600e,
-	0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x137f, 0x7007,
-	0x0002, 0x701b, 0x2e9c, 0x007c, 0x702c, 0xa005, 0x00c0, 0x2eae,
-	0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061, 0x76bd,
-	0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x2e46, 0x7120, 0x810b,
-	0x0078, 0x2513, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100, 0x2071,
-	0x7600, 0x6044, 0xd0a4, 0x00c0, 0x2edb, 0xd084, 0x0040, 0x2ec4,
-	0x1078, 0x3004, 0x0078, 0x2ed7, 0xd08c, 0x0040, 0x2ecb, 0x1078,
-	0x2f1b, 0x0078, 0x2ed7, 0xd094, 0x0040, 0x2ed2, 0x1078, 0x2efe,
-	0x0078, 0x2ed7, 0xd09c, 0x0040, 0x2ed7, 0x1078, 0x2ee5, 0x0e7f,
-	0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0, 0x2ee2,
-	0xc19d, 0x612a, 0x017f, 0x0078, 0x2ed7, 0x6043, 0x0040, 0x6043,
-	0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000, 0x2009,
-	0x7cc0, 0x200b, 0x0000, 0x707f, 0x0000, 0x7073, 0x000f, 0x2009,
-	0x000f, 0x2011, 0x353b, 0x1078, 0x45fe, 0x007c, 0x7070, 0xa005,
-	0x00c0, 0x2f1a, 0x2011, 0x353b, 0x1078, 0x456e, 0x6043, 0x0020,
-	0x6043, 0x0000, 0x6044, 0xd08c, 0x00c0, 0x2f16, 0x7083, 0x0000,
-	0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x2f1a, 0x7077, 0x0000,
-	0x0078, 0x2f1a, 0x007c, 0x7074, 0xa08a, 0x0003, 0x00c8, 0x2f24,
-	0x1079, 0x2f27, 0x0078, 0x2f26, 0x1078, 0x12d5, 0x007c, 0x2f2a,
-	0x2f79, 0x3003, 0x0f7e, 0x7077, 0x0001, 0x20e1, 0xa000, 0x20e1,
-	0x8700, 0x1078, 0x1dea, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2079,
-	0x7b00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000, 0x780f,
-	0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000, 0x781f,
-	0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000, 0x782f,
-	0x0000, 0x2079, 0x7b0c, 0x207b, 0x1101, 0x7807, 0x0000, 0x2099,
-	0x7605, 0x20a1, 0x7b0e, 0x20a9, 0x0004, 0x53a3, 0x2079, 0x7b12,
-	0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0x7b00, 0x20a1, 0x020b,
-	0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000, 0x1078,
-	0x3562, 0x0f7f, 0x707b, 0x0000, 0x6043, 0x0008, 0x6043, 0x0000,
-	0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000, 0xa025, 0x0040, 0x2fed,
-	0x6020, 0xd0b4, 0x00c0, 0x2feb, 0x7184, 0x81ff, 0x0040, 0x2fd4,
-	0xa486, 0x000c, 0x00c0, 0x2fdf, 0xa480, 0x0018, 0x8004, 0x20a8,
-	0x2011, 0x7b80, 0x2019, 0x7b00, 0x220c, 0x2304, 0xa106, 0x00c0,
-	0x2fab, 0x8210, 0x8318, 0x00f0, 0x2f94, 0x6043, 0x0004, 0x608b,
-	0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7077, 0x0002, 0x7083,
-	0x0002, 0x0078, 0x2feb, 0x2069, 0x7b80, 0x6930, 0xa18e, 0x1101,
-	0x00c0, 0x2fdf, 0x6834, 0xa005, 0x00c0, 0x2fdf, 0x6900, 0xa18c,
-	0x00ff, 0x00c0, 0x2fbf, 0x6804, 0xa005, 0x0040, 0x2fd4, 0x2011,
-	0x7b8e, 0x2019, 0x7605, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102,
-	0x0048, 0x2fd2, 0x00c0, 0x2fdf, 0x8210, 0x8318, 0x00f0, 0x2fc5,
-	0x0078, 0x2fdf, 0x7087, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043,
-	0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x2feb, 0x60c3,
-	0x000c, 0x1078, 0x3562, 0x0d7f, 0x007c, 0x6020, 0xd0b4, 0x00c0,
-	0x2feb, 0x60c3, 0x000c, 0x2011, 0x7840, 0x2013, 0x0000, 0x707b,
-	0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078,
-	0x5579, 0x0078, 0x2feb, 0x007c, 0x7080, 0xa08a, 0x001d, 0x00c8,
-	0x300d, 0x1079, 0x3010, 0x0078, 0x300f, 0x1078, 0x12d5, 0x007c,
-	0x3034, 0x3043, 0x3074, 0x3089, 0x30b9, 0x30e1, 0x3111, 0x313b,
-	0x316b, 0x3191, 0x31da, 0x31fc, 0x3220, 0x3236, 0x325e, 0x3271,
-	0x327a, 0x3293, 0x32c1, 0x32e9, 0x3317, 0x3341, 0x3384, 0x33b5,
-	0x33d7, 0x3415, 0x343b, 0x3454, 0x3461, 0x7003, 0x0007, 0x6004,
-	0xa084, 0xfff9, 0x6006, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0,
-	0x6043, 0x0002, 0x7083, 0x0001, 0x2009, 0x07d0, 0x2011, 0x3542,
-	0x1078, 0x4561, 0x007c, 0x0f7e, 0x7078, 0xa086, 0x0014, 0x00c0,
-	0x3072, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3072, 0x2079,
-	0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3070, 0x7834, 0xa005,
-	0x00c0, 0x3070, 0x7a38, 0xd2fc, 0x0040, 0x3066, 0x70a4, 0xa005,
-	0x00c0, 0x3066, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x2011, 0x3542,
-	0x1078, 0x456e, 0x7083, 0x0010, 0x1078, 0x327a, 0x0078, 0x3072,
-	0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0003, 0x6043, 0x0004,
-	0x1078, 0x35cc, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a,
-	0x20a3, 0x0000, 0x00f0, 0x3080, 0x60c3, 0x0014, 0x1078, 0x3562,
-	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x30b7, 0x2011, 0x3542,
-	0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x30b3, 0x2079, 0x7b80,
-	0x7a30, 0xa296, 0x1102, 0x00c0, 0x30b3, 0x7834, 0xa005, 0x00c0,
-	0x30b3, 0x7a38, 0xd2fc, 0x0040, 0x30ad, 0x70a4, 0xa005, 0x00c0,
-	0x30ad, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0004, 0x1078,
-	0x30b9, 0x0078, 0x30b7, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
-	0x007c, 0x7083, 0x0005, 0x1078, 0x35cc, 0x20a3, 0x1103, 0x20a3,
-	0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x30d3,
-	0x714c, 0xa186, 0xffff, 0x0040, 0x30d3, 0x1078, 0x3506, 0x0040,
-	0x30d3, 0x1078, 0x35fb, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
-	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x310f, 0x2011, 0x3542,
-	0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x310b, 0x2079, 0x7b80,
-	0x7a30, 0xa296, 0x1103, 0x00c0, 0x310b, 0x7834, 0xa005, 0x00c0,
-	0x310b, 0x7a38, 0xd2fc, 0x0040, 0x3105, 0x70a4, 0xa005, 0x00c0,
-	0x3105, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0006, 0x1078,
-	0x3111, 0x0078, 0x310f, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
-	0x007c, 0x7083, 0x0007, 0x1078, 0x35cc, 0x20a3, 0x1104, 0x20a3,
-	0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x312d,
-	0x7150, 0xa186, 0xffff, 0x0040, 0x312d, 0xa180, 0x232f, 0x200c,
-	0xa18c, 0xff00, 0x810f, 0x1078, 0x3506, 0x20a9, 0x0008, 0x2298,
-	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3169,
-	0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3165,
-	0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3165, 0x7834,
-	0xa005, 0x00c0, 0x3165, 0x7a38, 0xd2fc, 0x0040, 0x315f, 0x70a4,
-	0xa005, 0x00c0, 0x315f, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083,
-	0x0008, 0x1078, 0x316b, 0x0078, 0x3169, 0x7083, 0x0002, 0x707b,
-	0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009, 0x1078, 0x35cc, 0x20a3,
-	0x1105, 0x20a3, 0x0100, 0x3430, 0x706c, 0xa005, 0x00c0, 0x317e,
-	0x1078, 0x3470, 0x0040, 0x318e, 0x0078, 0x3188, 0x20a9, 0x0008,
-	0x2099, 0x7b8e, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x1078, 0x3562, 0x0078, 0x3190, 0x1078, 0x302d,
-	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x31d8, 0x2011, 0x3542,
-	0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x31d4, 0x2079, 0x7b80,
-	0x7a30, 0xa296, 0x1105, 0x00c0, 0x31d4, 0x7834, 0x2011, 0x0100,
-	0xa21e, 0x00c0, 0x31bd, 0x7a38, 0xd2fc, 0x0040, 0x31b7, 0x70a4,
-	0xa005, 0x00c0, 0x31b7, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083,
-	0x000a, 0x1078, 0x31da, 0x0078, 0x31d8, 0xa005, 0x00c0, 0x31d4,
-	0x7a38, 0xd2fc, 0x0040, 0x31cc, 0x70a4, 0xa005, 0x00c0, 0x31cc,
-	0x1078, 0x35fb, 0x70a7, 0x0001, 0x707f, 0x0000, 0x7083, 0x000e,
-	0x1078, 0x325e, 0x0078, 0x31d8, 0x7083, 0x0002, 0x707b, 0x0000,
-	0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011, 0x7b0e, 0x22a0, 0x20a9,
-	0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009, 0x0000,
-	0x41a4, 0x1078, 0x35cc, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x6030,
-	0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
-	0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
-	0x321e, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084, 0x00c0,
-	0x321a, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0, 0x321a,
-	0x7834, 0xa005, 0x00c0, 0x321a, 0x7083, 0x000c, 0x1078, 0x3220,
-	0x0078, 0x321e, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c,
-	0x7083, 0x000d, 0x1078, 0x35cc, 0x20a3, 0x1107, 0x20a3, 0x0000,
-	0x2099, 0x7b8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078,
-	0xa005, 0x0040, 0x325c, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086,
-	0x0084, 0x00c0, 0x3258, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107,
-	0x00c0, 0x3258, 0x7834, 0xa005, 0x00c0, 0x3258, 0x707f, 0x0001,
-	0x1078, 0x35be, 0x7083, 0x000e, 0x1078, 0x325e, 0x0078, 0x325c,
-	0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000f,
-	0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005,
-	0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x3542, 0x1078, 0x4561,
-	0x007c, 0x7078, 0xa005, 0x0040, 0x3279, 0x2011, 0x3542, 0x1078,
-	0x456e, 0x007c, 0x7083, 0x0011, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018, 0xa080,
-	0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014,
-	0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x32bf,
-	0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x32bd,
-	0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x32bd, 0x7834,
-	0xa005, 0x00c0, 0x32bd, 0x7a38, 0xd2fc, 0x0040, 0x32b7, 0x70a4,
-	0xa005, 0x00c0, 0x32b7, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083,
-	0x0012, 0x1078, 0x32c1, 0x0078, 0x32bf, 0x707b, 0x0000, 0x0f7f,
-	0x007c, 0x7083, 0x0013, 0x1078, 0x35d8, 0x20a3, 0x1103, 0x20a3,
-	0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa005, 0x00c0, 0x32db,
-	0x714c, 0xa186, 0xffff, 0x0040, 0x32db, 0x1078, 0x3506, 0x0040,
-	0x32db, 0x1078, 0x35fb, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
-	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3315, 0x2011, 0x3542,
-	0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3313, 0x2079, 0x7b80,
-	0x7a30, 0xa296, 0x1104, 0x00c0, 0x3313, 0x7834, 0xa005, 0x00c0,
-	0x3313, 0x7a38, 0xd2fc, 0x0040, 0x330d, 0x70a4, 0xa005, 0x00c0,
-	0x330d, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x7083, 0x0014, 0x1078,
-	0x3317, 0x0078, 0x3315, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
-	0x0015, 0x1078, 0x35d8, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430,
-	0x2011, 0x7b8e, 0x706c, 0xa006, 0x00c0, 0x3333, 0x7150, 0xa186,
-	0xffff, 0x0040, 0x3333, 0xa180, 0x232f, 0x200c, 0xa18c, 0xff00,
-	0x810f, 0x1078, 0x3506, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
-	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x3382, 0x2011, 0x3542,
-	0x1078, 0x456e, 0xa086, 0x0014, 0x00c0, 0x3380, 0x2079, 0x7b80,
-	0x7a30, 0xa296, 0x1105, 0x00c0, 0x3380, 0x7834, 0x2011, 0x0100,
-	0xa21e, 0x00c0, 0x3369, 0x7a38, 0xd2fc, 0x0040, 0x3367, 0x70a4,
-	0xa005, 0x00c0, 0x3367, 0x1078, 0x35fb, 0x70a7, 0x0001, 0x0078,
-	0x337a, 0xa005, 0x00c0, 0x3380, 0x7a38, 0xd2fc, 0x0040, 0x3378,
-	0x70a4, 0xa005, 0x00c0, 0x3378, 0x1078, 0x35fb, 0x70a7, 0x0001,
-	0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x3384, 0x0078, 0x3382,
+	0xa0be, 0x0100, 0x0040, 0x2b59, 0xa0be, 0x0112, 0x0040, 0x2b59,
+	0xa0be, 0x0113, 0x0040, 0x2b59, 0xa0be, 0x0114, 0x0040, 0x2b59,
+	0xa0be, 0x0117, 0x0040, 0x2b59, 0xa0be, 0x011a, 0x0040, 0x2b59,
+	0xa0be, 0x0121, 0x0040, 0x2b4f, 0xa0be, 0x0131, 0x0040, 0x2b4f,
+	0xa0be, 0x0171, 0x0040, 0x2b59, 0xa0be, 0x0173, 0x0040, 0x2b59,
+	0xa0be, 0x01a1, 0x00c0, 0x2b21, 0x6830, 0x8007, 0x6832, 0x0078,
+	0x2b5f, 0xa0be, 0x0212, 0x0040, 0x2b55, 0xa0be, 0x0213, 0x0040,
+	0x2b55, 0xa0be, 0x0214, 0x0040, 0x2b47, 0xa0be, 0x0217, 0x0040,
+	0x2b41, 0xa0be, 0x021a, 0x00c0, 0x2b3a, 0x6838, 0x8007, 0x683a,
+	0x0078, 0x2b59, 0xa0be, 0x0300, 0x0040, 0x2b59, 0x0d7f, 0x0078,
+	0x253b, 0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x2b95, 0xad80,
+	0x000e, 0x20a9, 0x0001, 0x1078, 0x2b95, 0x0078, 0x2b59, 0xad80,
+	0x000c, 0x1078, 0x2ba3, 0x0078, 0x2b5f, 0xad80, 0x000e, 0x1078,
+	0x2ba3, 0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x2b95, 0x0c7e,
+	0x1078, 0x2cec, 0x0040, 0x2b8a, 0x6838, 0xc0fd, 0x683a, 0x6837,
+	0x0119, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883,
+	0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000,
+	0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823,
+	0x0000, 0x1078, 0x6a52, 0x0040, 0x2537, 0x7007, 0x0003, 0x701b,
+	0x2b8e, 0x007c, 0x0c7f, 0x0d7f, 0x0078, 0x2537, 0x6820, 0xa086,
+	0x8001, 0x0040, 0x2537, 0x0078, 0x250d, 0x017e, 0x2008, 0x2044,
+	0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x00f0,
+	0x2b97, 0x017f, 0x007c, 0x017e, 0x0a7e, 0x0b7e, 0x2008, 0x2044,
+	0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108,
+	0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x0b7f, 0x0a7f, 0x017f,
+	0x007c, 0x81ff, 0x00c0, 0x2537, 0x7924, 0x2140, 0xa18c, 0xff00,
+	0x810f, 0xa182, 0x0080, 0x0048, 0x253b, 0xa182, 0x00ff, 0x00c8,
+	0x253b, 0x7a2c, 0x7b28, 0x6064, 0xa306, 0x00c0, 0x2bd7, 0x6068,
+	0xa24e, 0x0040, 0x253b, 0xa9cc, 0xff00, 0x0040, 0x253b, 0x0c7e,
+	0x1078, 0x2c4b, 0x2c68, 0x0c7f, 0x0040, 0x2bfe, 0xa0c6, 0x4000,
+	0x00c0, 0x2be4, 0x0078, 0x2bfb, 0xa0c6, 0x4007, 0x00c0, 0x2beb,
+	0x2408, 0x0078, 0x2bfb, 0xa0c6, 0x4008, 0x00c0, 0x2bf3, 0x2708,
+	0x2610, 0x0078, 0x2bfb, 0xa0c6, 0x4009, 0x00c0, 0x2bf9, 0x0078,
+	0x2bfb, 0x2001, 0x4006, 0x2020, 0x0078, 0x250f, 0x017e, 0x0b7e,
+	0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x5b94, 0x0040, 0x2c39, 0x2d00,
+	0x601a, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x2cec, 0x0c7f,
+	0x2b70, 0x0040, 0x2537, 0x6837, 0x0000, 0x2d00, 0x6012, 0x6833,
+	0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078,
+	0x22b5, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078, 0x37b5,
+	0x2001, 0x0002, 0x1078, 0x37c9, 0x127e, 0x2091, 0x8000, 0x7088,
+	0x8000, 0x708a, 0x127f, 0x2009, 0x0002, 0x1078, 0x5c21, 0xa085,
+	0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f, 0x0040, 0x2537, 0x7007,
+	0x0003, 0x701b, 0x2c44, 0x007c, 0x6830, 0xa086, 0x0100, 0x00c0,
+	0x250d, 0x0078, 0x2537, 0x0e7e, 0x0d7e, 0x2029, 0x0000, 0x2021,
+	0x0080, 0x20a9, 0x007f, 0x2071, 0x77a0, 0x2e04, 0xa005, 0x00c0,
+	0x2c5f, 0x2100, 0xa406, 0x0040, 0x2c9c, 0x0078, 0x2c90, 0x2068,
+	0x6f10, 0x2700, 0xa306, 0x00c0, 0x2c81, 0x6e14, 0x2600, 0xa206,
+	0x00c0, 0x2c81, 0x2400, 0xa106, 0x00c0, 0x2c7d, 0x2d60, 0xd884,
+	0x0040, 0x2ca2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
+	0x2ca2, 0x2001, 0x4000, 0x0078, 0x2ca3, 0x2001, 0x4007, 0x0078,
+	0x2ca3, 0x2400, 0xa106, 0x00c0, 0x2c90, 0x6e14, 0x87ff, 0x00c0,
+	0x2c8c, 0x86ff, 0x0040, 0x2c9c, 0x2001, 0x4008, 0x0078, 0x2ca3,
+	0x8420, 0x8e70, 0x00f0, 0x2c55, 0x2001, 0x4009, 0x0078, 0x2ca3,
+	0x2001, 0x0001, 0x0078, 0x2ca3, 0x1078, 0x37e6, 0x00c0, 0x2c98,
+	0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff,
+	0x00c0, 0x2537, 0x1078, 0x2cec, 0x0040, 0x2537, 0x6837, 0x0000,
+	0x7824, 0xa005, 0x0040, 0x253b, 0xa096, 0x00ff, 0x0040, 0x2cbc,
+	0xa092, 0x0004, 0x00c8, 0x253b, 0x2010, 0x2d18, 0x1078, 0x2277,
+	0x0040, 0x2537, 0x7007, 0x0003, 0x701b, 0x2cc7, 0x007c, 0x6830,
+	0xa086, 0x0100, 0x0040, 0x2537, 0x0078, 0x250d, 0x81ff, 0x00c0,
+	0x2537, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048,
+	0x253b, 0xa182, 0x00ff, 0x00c8, 0x253b, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x6979, 0x00c0, 0x2ce9, 0x1078, 0x3805, 0x127f, 0x0078,
+	0x250d, 0x127f, 0x0078, 0x2537, 0x1078, 0x1327, 0x0040, 0x2d03,
+	0xa006, 0x6802, 0x7010, 0xa005, 0x00c0, 0x2cfb, 0x2d00, 0x7012,
+	0x7016, 0x0078, 0x2d01, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006,
+	0x7016, 0xad80, 0x000d, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff,
+	0x1078, 0x381d, 0x00c0, 0x2d12, 0xa6b4, 0x00ff, 0xa682, 0x0010,
+	0x0048, 0x2d13, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff,
+	0x0040, 0x2d20, 0x2168, 0x6904, 0x1078, 0x1340, 0x0078, 0x2d17,
+	0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x2d2a,
+	0x2031, 0x0000, 0x2061, 0x76bd, 0x6606, 0x6112, 0x600e, 0x6226,
+	0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x1377, 0x7007, 0x0002,
+	0x701b, 0x250d, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079,
+	0x0000, 0x2001, 0x767b, 0x2004, 0xa005, 0x00c0, 0x2d56, 0x0068,
+	0x2d56, 0x7818, 0xd084, 0x00c0, 0x2d56, 0x781b, 0x0001, 0x7a22,
+	0x7b26, 0x7c2a, 0x2091, 0x4080, 0x0078, 0x2d7b, 0x017e, 0x0c7e,
+	0x0e7e, 0x2071, 0x766d, 0x7138, 0xa182, 0x0008, 0x0048, 0x2d64,
+	0x7030, 0x2060, 0x0078, 0x2d75, 0x7030, 0xa0e0, 0x0008, 0xac82,
+	0x76bd, 0x0048, 0x2d6d, 0x2061, 0x767d, 0x2c00, 0x7032, 0x81ff,
+	0x00c0, 0x2d73, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a,
+	0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071,
+	0x766d, 0x7038, 0xa005, 0x0040, 0x2db7, 0x127e, 0x2091, 0x8000,
+	0x0068, 0x2db6, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0,
+	0x2db5, 0x0c7e, 0x781b, 0x0001, 0x7034, 0x2060, 0x2c04, 0x7822,
+	0x6004, 0x7826, 0x6008, 0x782a, 0x2091, 0x4080, 0x7038, 0x8001,
+	0x703a, 0xa005, 0x00c0, 0x2dab, 0x7033, 0x767d, 0x7037, 0x767d,
+	0x0c7f, 0x0078, 0x2db5, 0xac80, 0x0008, 0xa0fa, 0x76bd, 0x0048,
+	0x2db3, 0x2001, 0x767d, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f,
+	0x007c, 0x027e, 0x2001, 0x7652, 0x2004, 0xd0c4, 0x0040, 0x2dc4,
+	0x2011, 0x8014, 0x1078, 0x2d3b, 0x027f, 0x007c, 0x81ff, 0x00c0,
+	0x2537, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x1078,
+	0x3573, 0x127f, 0x0078, 0x250d, 0x7824, 0x2008, 0xa18c, 0xfffd,
+	0x00c0, 0x2ddf, 0x61c8, 0xa10d, 0x61ca, 0x0078, 0x250d, 0x0078,
+	0x253b, 0x81ff, 0x00c0, 0x2537, 0x6000, 0xa086, 0x0003, 0x00c0,
+	0x2537, 0x2001, 0x7652, 0x2004, 0xd0a4, 0x00c0, 0x2537, 0x1078,
+	0x2d04, 0x0040, 0x253b, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x00c0, 0x2dfe, 0x7828, 0xa005, 0x0040, 0x250d, 0x0c7e, 0x1078,
+	0x2cec, 0x0c7f, 0x0040, 0x2537, 0x6837, 0x0000, 0x6833, 0x0000,
+	0x6838, 0xc0fd, 0x683a, 0x1078, 0x6adb, 0x0040, 0x2537, 0x7007,
+	0x0003, 0x701b, 0x2e14, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040,
+	0x2537, 0x0078, 0x250d, 0x2001, 0x7600, 0x2004, 0xa086, 0x0003,
+	0x00c0, 0x2537, 0x7f24, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078,
+	0x2cec, 0x0040, 0x2537, 0x2009, 0x0000, 0x2031, 0x0000, 0x7023,
+	0x0000, 0x702f, 0x0000, 0xad80, 0x0005, 0x7026, 0x20a0, 0x1078,
+	0x381d, 0x00c0, 0x2e61, 0x6004, 0xa0c6, 0x0707, 0x0040, 0x2e61,
+	0xa084, 0x00ff, 0xa0c6, 0x0006, 0x00c0, 0x2e61, 0x87ff, 0x0040,
+	0x2e54, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3,
+	0x1078, 0x2ba3, 0x0078, 0x2e5d, 0xac80, 0x000a, 0x2098, 0x3400,
+	0x20a9, 0x0004, 0x53a3, 0x1078, 0x2ba3, 0x21a2, 0x94a0, 0xa6b0,
+	0x0005, 0x8108, 0xa186, 0x007e, 0x0040, 0x2e6c, 0xa686, 0x0028,
+	0x0040, 0x2e75, 0x0078, 0x2e37, 0x86ff, 0x00c0, 0x2e73, 0x7120,
+	0x810b, 0x0078, 0x250d, 0x702f, 0x0001, 0x711e, 0x7020, 0xa600,
+	0x7022, 0x772a, 0x2061, 0x76bd, 0x6007, 0x0000, 0x6612, 0x7024,
+	0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x1377,
+	0x7007, 0x0002, 0x701b, 0x2e8d, 0x007c, 0x702c, 0xa005, 0x00c0,
+	0x2e9f, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000, 0x2061,
+	0x76bd, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x2e37, 0x7120,
+	0x810b, 0x0078, 0x250d, 0x127e, 0x0c7e, 0x0e7e, 0x2061, 0x0100,
+	0x2071, 0x7600, 0x6044, 0xd0a4, 0x00c0, 0x2ecc, 0xd084, 0x0040,
+	0x2eb5, 0x1078, 0x2ff7, 0x0078, 0x2ec8, 0xd08c, 0x0040, 0x2ebc,
+	0x1078, 0x2f0e, 0x0078, 0x2ec8, 0xd094, 0x0040, 0x2ec3, 0x1078,
+	0x2ef1, 0x0078, 0x2ec8, 0xd09c, 0x0040, 0x2ec8, 0x1078, 0x2ed6,
+	0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c, 0x00c0,
+	0x2ed3, 0xc19d, 0x612a, 0x017f, 0x0078, 0x2ec8, 0x6043, 0x0040,
+	0x6043, 0x0000, 0x706f, 0x0000, 0x7087, 0x0001, 0x70a7, 0x0000,
+	0x70bf, 0x0000, 0x2009, 0x7cc0, 0x200b, 0x0000, 0x707f, 0x0000,
+	0x7073, 0x000f, 0x2009, 0x000f, 0x2011, 0x3533, 0x1078, 0x45f6,
+	0x007c, 0x7070, 0xa005, 0x00c0, 0x2f0d, 0x2011, 0x3533, 0x1078,
+	0x4566, 0x6043, 0x0020, 0x6043, 0x0000, 0x6044, 0xd08c, 0x00c0,
+	0x2f09, 0x7083, 0x0000, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078,
+	0x2f0d, 0x7077, 0x0000, 0x0078, 0x2f0d, 0x007c, 0x7074, 0xa08a,
+	0x0003, 0x00c8, 0x2f17, 0x1079, 0x2f1a, 0x0078, 0x2f19, 0x1078,
+	0x12cd, 0x007c, 0x2f1d, 0x2f6c, 0x2ff6, 0x0f7e, 0x7077, 0x0001,
+	0x20e1, 0xa000, 0x20e1, 0x8700, 0x1078, 0x1de4, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2079, 0x7b00, 0x207b, 0x2200, 0x7807, 0x00ef,
+	0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000,
+	0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff,
+	0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0x7b0c, 0x207b, 0x1101,
+	0x7807, 0x0000, 0x2099, 0x7605, 0x20a1, 0x7b0e, 0x20a9, 0x0004,
+	0x53a3, 0x2079, 0x7b12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099,
+	0x7b00, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c,
+	0x600f, 0x0000, 0x1078, 0x355a, 0x0f7f, 0x707b, 0x0000, 0x6043,
+	0x0008, 0x6043, 0x0000, 0x007c, 0x0d7e, 0x7078, 0x707b, 0x0000,
+	0xa025, 0x0040, 0x2fe0, 0x6020, 0xd0b4, 0x00c0, 0x2fde, 0x7184,
+	0x81ff, 0x0040, 0x2fc7, 0xa486, 0x000c, 0x00c0, 0x2fd2, 0xa480,
+	0x0018, 0x8004, 0x20a8, 0x2011, 0x7b80, 0x2019, 0x7b00, 0x220c,
+	0x2304, 0xa106, 0x00c0, 0x2f9e, 0x8210, 0x8318, 0x00f0, 0x2f87,
+	0x6043, 0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006,
+	0x7077, 0x0002, 0x7083, 0x0002, 0x0078, 0x2fde, 0x2069, 0x7b80,
+	0x6930, 0xa18e, 0x1101, 0x00c0, 0x2fd2, 0x6834, 0xa005, 0x00c0,
+	0x2fd2, 0x6900, 0xa18c, 0x00ff, 0x00c0, 0x2fb2, 0x6804, 0xa005,
+	0x0040, 0x2fc7, 0x2011, 0x7b8e, 0x2019, 0x7605, 0x20a9, 0x0004,
+	0x220c, 0x2304, 0xa102, 0x0048, 0x2fc5, 0x00c0, 0x2fd2, 0x8210,
+	0x8318, 0x00f0, 0x2fb8, 0x0078, 0x2fd2, 0x7087, 0x0000, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9,
+	0x0014, 0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4,
+	0x00c0, 0x2fde, 0x60c3, 0x000c, 0x1078, 0x355a, 0x0d7f, 0x007c,
+	0x6020, 0xd0b4, 0x00c0, 0x2fde, 0x60c3, 0x000c, 0x2011, 0x7840,
+	0x2013, 0x0000, 0x707b, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056,
+	0x60a7, 0x9575, 0x1078, 0x5571, 0x0078, 0x2fde, 0x007c, 0x7080,
+	0xa08a, 0x001d, 0x00c8, 0x3000, 0x1079, 0x3003, 0x0078, 0x3002,
+	0x1078, 0x12cd, 0x007c, 0x3027, 0x3036, 0x3067, 0x307c, 0x30ac,
+	0x30d4, 0x3104, 0x312e, 0x315e, 0x3184, 0x31cd, 0x31ef, 0x3213,
+	0x3229, 0x3251, 0x3264, 0x326d, 0x3286, 0x32b4, 0x32dc, 0x330a,
+	0x3334, 0x337c, 0x33ad, 0x33cf, 0x340d, 0x3433, 0x344c, 0x3459,
+	0x7003, 0x0007, 0x6004, 0xa084, 0xfff9, 0x6006, 0x007c, 0x608b,
+	0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, 0x7083, 0x0001, 0x2009,
+	0x07d0, 0x2011, 0x353a, 0x1078, 0x4559, 0x007c, 0x0f7e, 0x7078,
+	0xa086, 0x0014, 0x00c0, 0x3065, 0x6043, 0x0000, 0x6020, 0xd0b4,
+	0x00c0, 0x3065, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0,
+	0x3063, 0x7834, 0xa005, 0x00c0, 0x3063, 0x7a38, 0xd2fc, 0x0040,
+	0x3059, 0x70a4, 0xa005, 0x00c0, 0x3059, 0x1078, 0x35f3, 0x70a7,
+	0x0001, 0x2011, 0x353a, 0x1078, 0x4566, 0x7083, 0x0010, 0x1078,
+	0x326d, 0x0078, 0x3065, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
+	0x0003, 0x6043, 0x0004, 0x1078, 0x35c4, 0x20a3, 0x1102, 0x20a3,
+	0x0000, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x3073, 0x60c3,
+	0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+	0x30aa, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0,
+	0x30a6, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x30a6,
+	0x7834, 0xa005, 0x00c0, 0x30a6, 0x7a38, 0xd2fc, 0x0040, 0x30a0,
+	0x70a4, 0xa005, 0x00c0, 0x30a0, 0x1078, 0x35f3, 0x70a7, 0x0001,
+	0x7083, 0x0004, 0x1078, 0x30ac, 0x0078, 0x30aa, 0x7083, 0x0002,
+	0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0005, 0x1078, 0x35c4,
+	0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c,
+	0xa005, 0x00c0, 0x30c6, 0x714c, 0xa186, 0xffff, 0x0040, 0x30c6,
+	0x1078, 0x34fe, 0x0040, 0x30c6, 0x1078, 0x35f3, 0x20a9, 0x0008,
+	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+	0x3102, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0,
+	0x30fe, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x30fe,
+	0x7834, 0xa005, 0x00c0, 0x30fe, 0x7a38, 0xd2fc, 0x0040, 0x30f8,
+	0x70a4, 0xa005, 0x00c0, 0x30f8, 0x1078, 0x35f3, 0x70a7, 0x0001,
+	0x7083, 0x0006, 0x1078, 0x3104, 0x0078, 0x3102, 0x7083, 0x0002,
+	0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0007, 0x1078, 0x35c4,
+	0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c,
+	0xa005, 0x00c0, 0x3120, 0x7150, 0xa186, 0xffff, 0x0040, 0x3120,
+	0xa180, 0x2329, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x34fe,
+	0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078,
+	0xa005, 0x0040, 0x315c, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086,
+	0x0014, 0x00c0, 0x3158, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104,
+	0x00c0, 0x3158, 0x7834, 0xa005, 0x00c0, 0x3158, 0x7a38, 0xd2fc,
+	0x0040, 0x3152, 0x70a4, 0xa005, 0x00c0, 0x3152, 0x1078, 0x35f3,
+	0x70a7, 0x0001, 0x7083, 0x0008, 0x1078, 0x315e, 0x0078, 0x315c,
+	0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0009,
+	0x1078, 0x35c4, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x706c,
+	0xa005, 0x00c0, 0x3171, 0x1078, 0x3468, 0x0040, 0x3181, 0x0078,
+	0x317b, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x355a, 0x0078,
+	0x3183, 0x1078, 0x3020, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+	0x31cb, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0,
+	0x31c7, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x31c7,
+	0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x31b0, 0x7a38, 0xd2fc,
+	0x0040, 0x31aa, 0x70a4, 0xa005, 0x00c0, 0x31aa, 0x1078, 0x35f3,
+	0x70a7, 0x0001, 0x7083, 0x000a, 0x1078, 0x31cd, 0x0078, 0x31cb,
+	0xa005, 0x00c0, 0x31c7, 0x7a38, 0xd2fc, 0x0040, 0x31bf, 0x70a4,
+	0xa005, 0x00c0, 0x31bf, 0x1078, 0x35f3, 0x70a7, 0x0001, 0x707f,
+	0x0000, 0x7083, 0x000e, 0x1078, 0x3251, 0x0078, 0x31cb, 0x7083,
+	0x0002, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x000b, 0x2011,
+	0x7b0e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9,
+	0x0002, 0x2009, 0x0000, 0x41a4, 0x1078, 0x35c4, 0x20a3, 0x1106,
+	0x20a3, 0x0000, 0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9,
+	0x0042, 0x53a6, 0x60c3, 0x0084, 0x1078, 0x355a, 0x007c, 0x0f7e,
+	0x7078, 0xa005, 0x0040, 0x3211, 0x2011, 0x353a, 0x1078, 0x4566,
+	0xa086, 0x0084, 0x00c0, 0x320d, 0x2079, 0x7b80, 0x7a30, 0xa296,
+	0x1106, 0x00c0, 0x320d, 0x7834, 0xa005, 0x00c0, 0x320d, 0x7083,
+	0x000c, 0x1078, 0x3213, 0x0078, 0x3211, 0x7083, 0x0002, 0x707b,
+	0x0000, 0x0f7f, 0x007c, 0x7083, 0x000d, 0x1078, 0x35c4, 0x20a3,
+	0x1107, 0x20a3, 0x0000, 0x2099, 0x7b8e, 0x20a9, 0x0040, 0x53a6,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x1078, 0x355a,
+	0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040, 0x324f, 0x2011, 0x353a,
+	0x1078, 0x4566, 0xa086, 0x0084, 0x00c0, 0x324b, 0x2079, 0x7b80,
+	0x7a30, 0xa296, 0x1107, 0x00c0, 0x324b, 0x7834, 0xa005, 0x00c0,
+	0x324b, 0x707f, 0x0001, 0x1078, 0x35b6, 0x7083, 0x000e, 0x1078,
+	0x3251, 0x0078, 0x324f, 0x7083, 0x0002, 0x707b, 0x0000, 0x0f7f,
+	0x007c, 0x7083, 0x000f, 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f,
+	0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011,
+	0x353a, 0x1078, 0x4559, 0x007c, 0x7078, 0xa005, 0x0040, 0x326c,
+	0x2011, 0x353a, 0x1078, 0x4566, 0x007c, 0x7083, 0x0011, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478,
+	0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8,
+	0x53a6, 0x60c3, 0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078,
+	0xa005, 0x0040, 0x32b2, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086,
+	0x0014, 0x00c0, 0x32b0, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1103,
+	0x00c0, 0x32b0, 0x7834, 0xa005, 0x00c0, 0x32b0, 0x7a38, 0xd2fc,
+	0x0040, 0x32aa, 0x70a4, 0xa005, 0x00c0, 0x32aa, 0x1078, 0x35f3,
+	0x70a7, 0x0001, 0x7083, 0x0012, 0x1078, 0x32b4, 0x0078, 0x32b2,
+	0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083, 0x0013, 0x1078, 0x35d0,
+	0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c,
+	0xa005, 0x00c0, 0x32ce, 0x714c, 0xa186, 0xffff, 0x0040, 0x32ce,
+	0x1078, 0x34fe, 0x0040, 0x32ce, 0x1078, 0x35f3, 0x20a9, 0x0008,
+	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+	0x3308, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0,
+	0x3306, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3306,
+	0x7834, 0xa005, 0x00c0, 0x3306, 0x7a38, 0xd2fc, 0x0040, 0x3300,
+	0x70a4, 0xa005, 0x00c0, 0x3300, 0x1078, 0x35f3, 0x70a7, 0x0001,
+	0x7083, 0x0014, 0x1078, 0x330a, 0x0078, 0x3308, 0x707b, 0x0000,
+	0x0f7f, 0x007c, 0x7083, 0x0015, 0x1078, 0x35d0, 0x20a3, 0x1104,
+	0x20a3, 0x0000, 0x3430, 0x2011, 0x7b8e, 0x706c, 0xa006, 0x00c0,
+	0x3326, 0x7150, 0xa186, 0xffff, 0x0040, 0x3326, 0xa180, 0x2329,
+	0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x34fe, 0x20a9, 0x0008,
+	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x0014, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005, 0x0040,
+	0x337a, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0014, 0x00c0,
+	0x3378, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1105, 0x00c0, 0x3378,
+	0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x3361, 0x7a38, 0xd2f4,
+	0x0040, 0x3354, 0x70bf, 0x0008, 0xd2fc, 0x0040, 0x335f, 0x70a4,
+	0xa005, 0x00c0, 0x335f, 0x1078, 0x35f3, 0x70a7, 0x0001, 0x0078,
+	0x3372, 0xa005, 0x00c0, 0x3378, 0x7a38, 0xd2fc, 0x0040, 0x3370,
+	0x70a4, 0xa005, 0x00c0, 0x3370, 0x1078, 0x35f3, 0x70a7, 0x0001,
+	0x707f, 0x0000, 0x7083, 0x0016, 0x1078, 0x337c, 0x0078, 0x337a,
 	0x707b, 0x0000, 0x0f7f, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
 	0x2099, 0x7b80, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6, 0x3430,
-	0x2011, 0x7b8e, 0x7083, 0x0017, 0x0078, 0x3398, 0x7083, 0x001b,
-	0x706c, 0xa005, 0x00c0, 0x33a2, 0x1078, 0x3470, 0x0040, 0x33b2,
-	0x0078, 0x33ac, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x3562,
-	0x0078, 0x33b4, 0x1078, 0x302d, 0x007c, 0x0f7e, 0x7078, 0xa005,
-	0x0040, 0x33d5, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084,
-	0x00c0, 0x33d3, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0,
-	0x33d3, 0x7834, 0xa005, 0x00c0, 0x33d3, 0x7083, 0x0018, 0x1078,
-	0x33d7, 0x0078, 0x33d5, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
-	0x0019, 0x1078, 0x35d8, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430,
+	0x2011, 0x7b8e, 0x7083, 0x0017, 0x0078, 0x3390, 0x7083, 0x001b,
+	0x706c, 0xa005, 0x00c0, 0x339a, 0x1078, 0x3468, 0x0040, 0x33aa,
+	0x0078, 0x33a4, 0x20a9, 0x0008, 0x2099, 0x7b8e, 0x26a0, 0x53a6,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x355a,
+	0x0078, 0x33ac, 0x1078, 0x3020, 0x007c, 0x0f7e, 0x7078, 0xa005,
+	0x0040, 0x33cd, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0084,
+	0x00c0, 0x33cb, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1106, 0x00c0,
+	0x33cb, 0x7834, 0xa005, 0x00c0, 0x33cb, 0x7083, 0x0018, 0x1078,
+	0x33cf, 0x0078, 0x33cd, 0x707b, 0x0000, 0x0f7f, 0x007c, 0x7083,
+	0x0019, 0x1078, 0x35d0, 0x20a3, 0x1106, 0x20a3, 0x0000, 0x3430,
 	0x2099, 0x7b8e, 0x2039, 0x7b0e, 0x27a0, 0x20a9, 0x0040, 0x53a3,
 	0x2728, 0x2514, 0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294,
 	0x00ff, 0x8007, 0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0,
-	0x7b0e, 0x2414, 0xa38c, 0x0001, 0x0040, 0x3402, 0xa294, 0xff00,
-	0x0078, 0x3405, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798,
+	0x7b0e, 0x2414, 0xa38c, 0x0001, 0x0040, 0x33fa, 0xa294, 0xff00,
+	0x0078, 0x33fd, 0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798,
 	0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0084, 0x1078, 0x3562, 0x007c, 0x0f7e, 0x7078, 0xa005,
-	0x0040, 0x3439, 0x2011, 0x3542, 0x1078, 0x456e, 0xa086, 0x0084,
-	0x00c0, 0x3437, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107, 0x00c0,
-	0x3437, 0x7834, 0xa005, 0x00c0, 0x3437, 0x707f, 0x0001, 0x1078,
-	0x35be, 0x7083, 0x001a, 0x1078, 0x343b, 0x0078, 0x3439, 0x707b,
+	0x60c3, 0x0084, 0x1078, 0x355a, 0x007c, 0x0f7e, 0x7078, 0xa005,
+	0x0040, 0x3431, 0x2011, 0x353a, 0x1078, 0x4566, 0xa086, 0x0084,
+	0x00c0, 0x342f, 0x2079, 0x7b80, 0x7a30, 0xa296, 0x1107, 0x00c0,
+	0x342f, 0x7834, 0xa005, 0x00c0, 0x342f, 0x707f, 0x0001, 0x1078,
+	0x35b6, 0x7083, 0x001a, 0x1078, 0x3433, 0x0078, 0x3431, 0x707b,
 	0x0000, 0x0f7f, 0x007c, 0x7083, 0x001b, 0x20e1, 0x9080, 0x20e1,
 	0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b, 0x7478, 0xa480, 0x0018,
 	0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3,
-	0x0084, 0x1078, 0x3562, 0x007c, 0x7078, 0xa005, 0x0040, 0x3460,
-	0x2011, 0x3542, 0x1078, 0x456e, 0x7083, 0x001c, 0x1078, 0x3461,
+	0x0084, 0x1078, 0x355a, 0x007c, 0x7078, 0xa005, 0x0040, 0x3458,
+	0x2011, 0x353a, 0x1078, 0x4566, 0x7083, 0x001c, 0x1078, 0x3459,
 	0x007c, 0x707b, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043,
-	0x0001, 0x2009, 0x07d0, 0x2011, 0x3542, 0x1078, 0x4561, 0x007c,
+	0x0001, 0x2009, 0x07d0, 0x2011, 0x353a, 0x1078, 0x4559, 0x007c,
 	0x087e, 0x097e, 0x2029, 0x7652, 0x252c, 0x20a9, 0x0008, 0x2041,
 	0x7b0e, 0x28a0, 0x2099, 0x7b8e, 0x53a3, 0x20a9, 0x0008, 0x2011,
-	0x0007, 0xd5d4, 0x0040, 0x3486, 0x2011, 0x0000, 0x2800, 0xa200,
-	0x200c, 0xa1a6, 0xffff, 0x00c0, 0x3498, 0xd5d4, 0x0040, 0x3493,
-	0x8210, 0x0078, 0x3494, 0x8211, 0x00f0, 0x3486, 0x0078, 0x34fd,
-	0x82ff, 0x00c0, 0x34aa, 0xd5d4, 0x0040, 0x34a4, 0xa1a6, 0x3fff,
-	0x0040, 0x3490, 0x0078, 0x34a8, 0xa1a6, 0x3fff, 0x0040, 0x34fd,
+	0x0007, 0xd5d4, 0x0040, 0x347e, 0x2011, 0x0000, 0x2800, 0xa200,
+	0x200c, 0xa1a6, 0xffff, 0x00c0, 0x3490, 0xd5d4, 0x0040, 0x348b,
+	0x8210, 0x0078, 0x348c, 0x8211, 0x00f0, 0x347e, 0x0078, 0x34f5,
+	0x82ff, 0x00c0, 0x34a2, 0xd5d4, 0x0040, 0x349c, 0xa1a6, 0x3fff,
+	0x0040, 0x3488, 0x0078, 0x34a0, 0xa1a6, 0x3fff, 0x0040, 0x34f5,
 	0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0040,
-	0x34b3, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x34ba, 0x8423,
-	0x0078, 0x34bb, 0x8424, 0x00c8, 0x34c8, 0xd5d4, 0x0040, 0x34c3,
-	0x8319, 0x0078, 0x34c4, 0x8318, 0x00f0, 0x34b4, 0x0078, 0x34fd,
-	0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x34cc, 0x2328,
-	0x8529, 0xa2be, 0x0007, 0x0040, 0x34e0, 0x007e, 0x2039, 0x0007,
-	0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, 0x34dc,
-	0x754e, 0xa5c8, 0x232f, 0x292c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
+	0x34ab, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0040, 0x34b2, 0x8423,
+	0x0078, 0x34b3, 0x8424, 0x00c8, 0x34c0, 0xd5d4, 0x0040, 0x34bb,
+	0x8319, 0x0078, 0x34bc, 0x8318, 0x00f0, 0x34ac, 0x0078, 0x34f5,
+	0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x00f0, 0x34c4, 0x2328,
+	0x8529, 0xa2be, 0x0007, 0x0040, 0x34d8, 0x007e, 0x2039, 0x0007,
+	0x2200, 0xa73a, 0x007f, 0x27a8, 0xa5a8, 0x0010, 0x00f0, 0x34d4,
+	0x754e, 0xa5c8, 0x2329, 0x292c, 0xa5ac, 0x00ff, 0x6532, 0x60e7,
 	0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x706f, 0x0001,
 	0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0xa085, 0x0001, 0x0078, 0x3503, 0xa006, 0x0078, 0x3503,
-	0xa006, 0x1078, 0x12d5, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021,
-	0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x3513, 0x8420,
-	0x8001, 0x0078, 0x350b, 0x2118, 0x84ff, 0x0040, 0x351c, 0xa39a,
-	0x0010, 0x8421, 0x00c0, 0x3517, 0x2021, 0x0001, 0x83ff, 0x0040,
-	0x3525, 0x8423, 0x8319, 0x00c0, 0x3521, 0xa238, 0x2704, 0xa42c,
-	0x00c0, 0x353a, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x232f, 0x242c,
+	0x0000, 0xa085, 0x0001, 0x0078, 0x34fb, 0xa006, 0x0078, 0x34fb,
+	0xa006, 0x1078, 0x12cd, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021,
+	0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x350b, 0x8420,
+	0x8001, 0x0078, 0x3503, 0x2118, 0x84ff, 0x0040, 0x3514, 0xa39a,
+	0x0010, 0x8421, 0x00c0, 0x350f, 0x2021, 0x0001, 0x83ff, 0x0040,
+	0x351d, 0x8423, 0x8319, 0x00c0, 0x3519, 0xa238, 0x2704, 0xa42c,
+	0x00c0, 0x3532, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x2329, 0x242c,
 	0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0001,
 	0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7073, 0x0000,
 	0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2079, 0x0100, 0x2071, 0x0140,
-	0x1078, 0x5582, 0x7004, 0xa084, 0x4000, 0x0040, 0x3553, 0x7003,
+	0x1078, 0x557a, 0x7004, 0xa084, 0x4000, 0x0040, 0x354b, 0x7003,
 	0x1000, 0x7003, 0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0x7620,
 	0x2073, 0x0000, 0x7843, 0x0090, 0x7843, 0x0010, 0x127f, 0x0f7f,
 	0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0x7840, 0x2013,
 	0x0000, 0x707b, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3, 0x0056,
-	0x60a7, 0x9575, 0x1078, 0x5579, 0x2009, 0x07d0, 0x2011, 0x3542,
-	0x1078, 0x45fe, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x2009, 0x00f7, 0x1078, 0x35e4, 0x2061, 0x7849, 0x601b,
+	0x60a7, 0x9575, 0x1078, 0x5571, 0x2009, 0x07d0, 0x2011, 0x353a,
+	0x1078, 0x45f6, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e, 0x2091,
+	0x8000, 0x2009, 0x00f7, 0x1078, 0x35dc, 0x2061, 0x7849, 0x601b,
 	0x0000, 0x601f, 0x0000, 0x2061, 0x7600, 0x6003, 0x0001, 0x2061,
 	0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011,
-	0x35a0, 0x1078, 0x4561, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c,
+	0x3598, 0x1078, 0x4559, 0x127f, 0x0c7f, 0x027f, 0x017f, 0x007c,
 	0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x0100, 0x1078,
-	0x5582, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x35b4,
-	0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x202b,
-	0x1078, 0x357b, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040,
+	0x557a, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000, 0x0040, 0x35ac,
+	0x7003, 0x1000, 0x7003, 0x0000, 0x2001, 0x0001, 0x1078, 0x2025,
+	0x1078, 0x3573, 0x127f, 0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040,
 	0x20a1, 0x7cc0, 0x2099, 0x7b8e, 0x3304, 0x8007, 0x20a2, 0x9398,
-	0x94a0, 0x00f0, 0x35c4, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x94a0, 0x00f0, 0x35bc, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000,
 	0x2099, 0x7b00, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c,
 	0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x7b80, 0x20a1, 0x020b,
 	0x20a9, 0x000c, 0x53a6, 0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100,
-	0x810f, 0x2001, 0x762c, 0x2004, 0xa005, 0x00c0, 0x35f5, 0x6030,
-	0xa084, 0x00ff, 0xa105, 0x0078, 0x35f7, 0xa185, 0x00f7, 0x604a,
+	0x810f, 0x2001, 0x762c, 0x2004, 0xa005, 0x00c0, 0x35ed, 0x6030,
+	0xa084, 0x00ff, 0xa105, 0x0078, 0x35ef, 0xa185, 0x00f7, 0x604a,
 	0x007f, 0x0c7f, 0x007c, 0x017e, 0x047e, 0x2001, 0x7652, 0x2004,
-	0xd0a4, 0x0040, 0x360e, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078,
-	0x7541, 0x2001, 0x760c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a,
-	0x1078, 0x2299, 0x047f, 0x017f, 0x007c, 0x157e, 0x20a9, 0x00ff,
-	0x2009, 0x7720, 0xa006, 0x200a, 0x8108, 0x00f0, 0x361b, 0x157f,
+	0xd0a4, 0x0040, 0x3606, 0xa006, 0x2020, 0x2009, 0x002a, 0x1078,
+	0x7536, 0x2001, 0x760c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a,
+	0x1078, 0x2293, 0x047f, 0x017f, 0x007c, 0x157e, 0x20a9, 0x00ff,
+	0x2009, 0x7720, 0xa006, 0x200a, 0x8108, 0x00f0, 0x3613, 0x157f,
 	0x007c, 0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0x7651,
 	0xa006, 0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198,
-	0x232f, 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98,
+	0x2329, 0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98,
 	0x0006, 0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0,
 	0x40a4, 0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e,
 	0x6062, 0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e,
@@ -1256,500 +1237,500 @@
 	0x61a2, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084,
 	0x00ff, 0x6042, 0x147f, 0x137f, 0x157f, 0x037f, 0x0d7f, 0x007c,
 	0x127e, 0x2091, 0x8000, 0x6944, 0xa1b4, 0x00ff, 0xa682, 0x0010,
-	0x00c8, 0x3715, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8,
-	0x371b, 0x2001, 0x760c, 0x2004, 0xa084, 0x0003, 0x00c0, 0x36fe,
-	0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x36ec, 0x6004, 0xa084,
-	0x00ff, 0xa08e, 0x0006, 0x00c0, 0x36f2, 0x6078, 0xa00d, 0x0040,
-	0x3697, 0xa680, 0x75d5, 0x2004, 0xa10c, 0x00c0, 0x36e6, 0x607c,
-	0xa00d, 0x0040, 0x36b3, 0xa680, 0x75d5, 0x2004, 0xa10c, 0x0040,
-	0x36b3, 0x694c, 0xd1fc, 0x00c0, 0x36a9, 0x1078, 0x37ae, 0x0078,
-	0x36e1, 0x1078, 0x377f, 0x694c, 0xd1ec, 0x00c0, 0x36e1, 0x1078,
-	0x38c7, 0x0078, 0x36e1, 0x694c, 0xa184, 0xa000, 0x0040, 0x36d1,
-	0xd1ec, 0x0040, 0x36ca, 0xd1fc, 0x0040, 0x36c2, 0x1078, 0x38de,
-	0x0078, 0x36cd, 0xa680, 0x75d5, 0x200c, 0x607c, 0xa105, 0x607e,
-	0x0078, 0x36d1, 0xd1fc, 0x0040, 0x36d1, 0x1078, 0x377f, 0x0078,
-	0x36e1, 0x6050, 0xa00d, 0x0040, 0x36dc, 0x2d00, 0x200a, 0x6803,
-	0x0000, 0x6052, 0x0078, 0x36e1, 0x2d00, 0x6052, 0x604e, 0x6803,
-	0x0000, 0x1078, 0x4844, 0xa006, 0x127f, 0x007c, 0x2001, 0x0005,
-	0x2009, 0x0000, 0x0078, 0x371f, 0x2001, 0x0028, 0x2009, 0x0000,
-	0x0078, 0x371f, 0xa082, 0x0006, 0x00c8, 0x36fe, 0x60a0, 0xd0bc,
-	0x0040, 0x368d, 0x2001, 0x0028, 0x0078, 0x3711, 0x2009, 0x760c,
-	0x210c, 0xd18c, 0x0040, 0x3708, 0x2001, 0x0004, 0x0078, 0x3711,
-	0xd184, 0x0040, 0x370f, 0x2001, 0x0004, 0x0078, 0x3711, 0x2001,
-	0x0029, 0x2009, 0x0000, 0x0078, 0x371f, 0x2001, 0x0029, 0x2009,
-	0x0000, 0x0078, 0x371f, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
+	0x00c8, 0x370d, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8,
+	0x3713, 0x2001, 0x760c, 0x2004, 0xa084, 0x0003, 0x00c0, 0x36f6,
+	0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x36e4, 0x6004, 0xa084,
+	0x00ff, 0xa08e, 0x0006, 0x00c0, 0x36ea, 0x6078, 0xa00d, 0x0040,
+	0x368f, 0xa680, 0x75ca, 0x2004, 0xa10c, 0x00c0, 0x36de, 0x607c,
+	0xa00d, 0x0040, 0x36ab, 0xa680, 0x75ca, 0x2004, 0xa10c, 0x0040,
+	0x36ab, 0x694c, 0xd1fc, 0x00c0, 0x36a1, 0x1078, 0x37a6, 0x0078,
+	0x36d9, 0x1078, 0x3777, 0x694c, 0xd1ec, 0x00c0, 0x36d9, 0x1078,
+	0x38bf, 0x0078, 0x36d9, 0x694c, 0xa184, 0xa000, 0x0040, 0x36c9,
+	0xd1ec, 0x0040, 0x36c2, 0xd1fc, 0x0040, 0x36ba, 0x1078, 0x38d6,
+	0x0078, 0x36c5, 0xa680, 0x75ca, 0x200c, 0x607c, 0xa105, 0x607e,
+	0x0078, 0x36c9, 0xd1fc, 0x0040, 0x36c9, 0x1078, 0x3777, 0x0078,
+	0x36d9, 0x6050, 0xa00d, 0x0040, 0x36d4, 0x2d00, 0x200a, 0x6803,
+	0x0000, 0x6052, 0x0078, 0x36d9, 0x2d00, 0x6052, 0x604e, 0x6803,
+	0x0000, 0x1078, 0x483c, 0xa006, 0x127f, 0x007c, 0x2001, 0x0005,
+	0x2009, 0x0000, 0x0078, 0x3717, 0x2001, 0x0028, 0x2009, 0x0000,
+	0x0078, 0x3717, 0xa082, 0x0006, 0x00c8, 0x36f6, 0x60a0, 0xd0bc,
+	0x0040, 0x3685, 0x2001, 0x0028, 0x0078, 0x3709, 0x2009, 0x760c,
+	0x210c, 0xd18c, 0x0040, 0x3700, 0x2001, 0x0004, 0x0078, 0x3709,
+	0xd184, 0x0040, 0x3707, 0x2001, 0x0004, 0x0078, 0x3709, 0x2001,
+	0x0029, 0x2009, 0x0000, 0x0078, 0x3717, 0x2001, 0x0029, 0x2009,
+	0x0000, 0x0078, 0x3717, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005,
 	0x127f, 0x007c, 0x6944, 0xa1b4, 0x00ff, 0xa682, 0x0010, 0x00c8,
-	0x3764, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x3754,
-	0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x3754, 0x6004, 0xa084,
-	0x00ff, 0xa08e, 0x0006, 0x00c0, 0x375a, 0x684c, 0xd0ec, 0x0040,
-	0x3747, 0x1078, 0x38de, 0x1078, 0x377f, 0x0078, 0x374f, 0x1078,
-	0x377f, 0x684c, 0xd0fc, 0x0040, 0x374f, 0x1078, 0x38c7, 0x1078,
-	0x38f2, 0xa006, 0x0078, 0x3768, 0x2001, 0x0028, 0x2009, 0x0000,
-	0x0078, 0x3768, 0xa082, 0x0006, 0x0048, 0x373d, 0x2001, 0x0029,
-	0x2009, 0x0000, 0x0078, 0x3768, 0x2001, 0x0029, 0x2009, 0x0000,
+	0x375c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x374c,
+	0xa188, 0x7720, 0x2104, 0xa065, 0x0040, 0x374c, 0x6004, 0xa084,
+	0x00ff, 0xa08e, 0x0006, 0x00c0, 0x3752, 0x684c, 0xd0ec, 0x0040,
+	0x373f, 0x1078, 0x38d6, 0x1078, 0x3777, 0x0078, 0x3747, 0x1078,
+	0x3777, 0x684c, 0xd0fc, 0x0040, 0x3747, 0x1078, 0x38bf, 0x1078,
+	0x38ea, 0xa006, 0x0078, 0x3760, 0x2001, 0x0028, 0x2009, 0x0000,
+	0x0078, 0x3760, 0xa082, 0x0006, 0x0048, 0x3735, 0x2001, 0x0029,
+	0x2009, 0x0000, 0x0078, 0x3760, 0x2001, 0x0029, 0x2009, 0x0000,
 	0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050, 0xa00d, 0x0040,
-	0x3778, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c,
-	0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x3776, 0x127e,
-	0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x378b, 0x6802, 0x2d00,
+	0x3770, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x127f, 0x007c,
+	0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x376e, 0x127e,
+	0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x3783, 0x6802, 0x2d00,
 	0x604e, 0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000,
-	0x0078, 0x3789, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040,
-	0x37a0, 0x6800, 0xa005, 0x00c0, 0x379e, 0x6052, 0x604e, 0xad05,
-	0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x37ad, 0x6800, 0xa005,
-	0x00c0, 0x37ab, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000,
-	0x6084, 0xa00d, 0x0040, 0x37b8, 0x2d00, 0x200a, 0x6086, 0x007c,
-	0x2d00, 0x6086, 0x6082, 0x0078, 0x37b7, 0x127e, 0x0c7e, 0x027e,
-	0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x37cb,
-	0xc285, 0x0078, 0x37cc, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f,
+	0x0078, 0x3781, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0040,
+	0x3798, 0x6800, 0xa005, 0x00c0, 0x3796, 0x6052, 0x604e, 0xad05,
+	0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x37a5, 0x6800, 0xa005,
+	0x00c0, 0x37a3, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803, 0x0000,
+	0x6084, 0xa00d, 0x0040, 0x37b0, 0x2d00, 0x200a, 0x6086, 0x007c,
+	0x2d00, 0x6086, 0x6082, 0x0078, 0x37af, 0x127e, 0x0c7e, 0x027e,
+	0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040, 0x37c3,
+	0xc285, 0x0078, 0x37c4, 0xc284, 0x6202, 0x027f, 0x0c7f, 0x127f,
 	0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204,
 	0xa294, 0xff00, 0xa215, 0x6206, 0x0c7f, 0x127f, 0x007c, 0x127e,
 	0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0xa294, 0x00ff,
 	0x8007, 0xa215, 0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182,
-	0x00ff, 0x0048, 0x37f7, 0xa085, 0x0001, 0x0078, 0x380b, 0xa190,
-	0x7720, 0x2204, 0xa065, 0x00c0, 0x380a, 0x017e, 0x0d7e, 0x1078,
-	0x1314, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x37f3, 0x2c00, 0x2012,
-	0x1078, 0x3621, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182, 0x00ff,
-	0x0048, 0x3816, 0xa085, 0x0001, 0x0078, 0x3823, 0x0d7e, 0xa190,
-	0x7720, 0x2204, 0xa06d, 0x0040, 0x3821, 0x2013, 0x0000, 0x1078,
-	0x1348, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182, 0x00ff,
-	0x0048, 0x382e, 0xa085, 0x0001, 0x0078, 0x3835, 0xa188, 0x7720,
-	0x2104, 0xa065, 0x0040, 0x382a, 0xa006, 0x017f, 0x007c, 0x0d7e,
+	0x00ff, 0x0048, 0x37ef, 0xa085, 0x0001, 0x0078, 0x3803, 0xa190,
+	0x7720, 0x2204, 0xa065, 0x00c0, 0x3802, 0x017e, 0x0d7e, 0x1078,
+	0x130c, 0x2d60, 0x0d7f, 0x017f, 0x0040, 0x37eb, 0x2c00, 0x2012,
+	0x1078, 0x3619, 0xa006, 0x027f, 0x007c, 0x027e, 0xa182, 0x00ff,
+	0x0048, 0x380e, 0xa085, 0x0001, 0x0078, 0x381b, 0x0d7e, 0xa190,
+	0x7720, 0x2204, 0xa06d, 0x0040, 0x3819, 0x2013, 0x0000, 0x1078,
+	0x1340, 0x0d7f, 0xa006, 0x027f, 0x007c, 0x017e, 0xa182, 0x00ff,
+	0x0048, 0x3826, 0xa085, 0x0001, 0x0078, 0x382d, 0xa188, 0x7720,
+	0x2104, 0xa065, 0x0040, 0x3822, 0xa006, 0x017f, 0x007c, 0x0d7e,
 	0x157e, 0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000,
 	0xc08c, 0x6002, 0x2069, 0x7b8e, 0x6808, 0x605e, 0x6810, 0x6062,
-	0x6138, 0xa10a, 0x0048, 0x384d, 0x603a, 0x6814, 0x6066, 0x2099,
+	0x6138, 0xa10a, 0x0048, 0x3845, 0x603a, 0x6814, 0x6066, 0x2099,
 	0x7b96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099,
 	0x7b9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069,
 	0x7bae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818,
-	0x6076, 0xa182, 0x0211, 0x00c8, 0x3871, 0x2009, 0x0008, 0x0078,
-	0x389b, 0xa182, 0x0259, 0x00c8, 0x3879, 0x2009, 0x0007, 0x0078,
-	0x389b, 0xa182, 0x02c1, 0x00c8, 0x3881, 0x2009, 0x0006, 0x0078,
-	0x389b, 0xa182, 0x0349, 0x00c8, 0x3889, 0x2009, 0x0005, 0x0078,
-	0x389b, 0xa182, 0x0421, 0x00c8, 0x3891, 0x2009, 0x0004, 0x0078,
-	0x389b, 0xa182, 0x0581, 0x00c8, 0x3899, 0x2009, 0x0003, 0x0078,
-	0x389b, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f,
+	0x6076, 0xa182, 0x0211, 0x00c8, 0x3869, 0x2009, 0x0008, 0x0078,
+	0x3893, 0xa182, 0x0259, 0x00c8, 0x3871, 0x2009, 0x0007, 0x0078,
+	0x3893, 0xa182, 0x02c1, 0x00c8, 0x3879, 0x2009, 0x0006, 0x0078,
+	0x3893, 0xa182, 0x0349, 0x00c8, 0x3881, 0x2009, 0x0005, 0x0078,
+	0x3893, 0xa182, 0x0421, 0x00c8, 0x3889, 0x2009, 0x0004, 0x0078,
+	0x3893, 0xa182, 0x0581, 0x00c8, 0x3891, 0x2009, 0x0003, 0x0078,
+	0x3893, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f,
 	0x007c, 0x0e7e, 0x2071, 0x7b8d, 0x2e04, 0x6896, 0x2071, 0x7b8e,
-	0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001, 0x75d5,
+	0x7004, 0x689a, 0x701c, 0x689e, 0x0e7f, 0x007c, 0x2001, 0x75ca,
 	0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x6178, 0xa10d, 0x617a,
-	0x127f, 0x007c, 0x2001, 0x75d5, 0xa600, 0x2004, 0x8002, 0x127e,
+	0x127f, 0x007c, 0x2001, 0x75ca, 0xa600, 0x2004, 0x8002, 0x127e,
 	0x2091, 0x8000, 0x6178, 0xa10c, 0x617a, 0x127f, 0x007c, 0x2001,
-	0x75d5, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, 0x617c,
-	0xa10c, 0x617e, 0x127f, 0x0078, 0x38d7, 0x1078, 0x376a, 0x1078,
-	0x3938, 0x00c0, 0x38d5, 0x1078, 0x38f2, 0x007c, 0x2001, 0x75d5,
+	0x75ca, 0xa600, 0x2004, 0x8002, 0x127e, 0x2091, 0x8000, 0x617c,
+	0xa10c, 0x617e, 0x127f, 0x0078, 0x38cf, 0x1078, 0x3762, 0x1078,
+	0x3930, 0x00c0, 0x38cd, 0x1078, 0x38ea, 0x007c, 0x2001, 0x75ca,
 	0xa600, 0x2004, 0x127e, 0x2091, 0x8000, 0x617c, 0xa10d, 0x617e,
-	0x127f, 0x0078, 0x38ed, 0x1078, 0x37ae, 0x1078, 0x38fc, 0x00c0,
-	0x38eb, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4844, 0x127f,
-	0x007c, 0xa01e, 0x0078, 0x38fe, 0x2019, 0x0001, 0xa00e, 0x127e,
-	0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x391e,
-	0x8dff, 0x0040, 0x3933, 0x83ff, 0x0040, 0x3916, 0x6844, 0xa084,
-	0x00ff, 0xa606, 0x0040, 0x3923, 0x0078, 0x391e, 0x683c, 0xa406,
-	0x00c0, 0x391e, 0x6840, 0xa506, 0x0040, 0x3923, 0x2d08, 0x6800,
-	0x2068, 0x0078, 0x3908, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x392b,
-	0x624e, 0x0078, 0x392e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0,
-	0x3933, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x393a,
-	0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x3968,
-	0x83ff, 0x0040, 0x394b, 0x6844, 0xa084, 0x00ff, 0xa606, 0x0040,
-	0x3958, 0x0078, 0x3953, 0x683c, 0xa406, 0x00c0, 0x3953, 0x6840,
-	0xa506, 0x0040, 0x3958, 0x2d08, 0x6800, 0x2068, 0x0078, 0x393d,
-	0x6a00, 0x6080, 0xad06, 0x00c0, 0x3960, 0x6282, 0x0078, 0x3963,
-	0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3968, 0x6186, 0x8dff,
-	0x007c, 0x2001, 0x75d5, 0xa600, 0x2004, 0x6178, 0xa10c, 0x0040,
-	0x3973, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x3979, 0xa295,
-	0x0002, 0x007c, 0x1078, 0x39c5, 0x0040, 0x3982, 0x1078, 0x6a16,
-	0x0078, 0x3984, 0xa085, 0x0001, 0x007c, 0x1078, 0x39c5, 0x0040,
-	0x398d, 0x1078, 0x69a5, 0x0078, 0x398f, 0xa085, 0x0001, 0x007c,
-	0x1078, 0x39c5, 0x0040, 0x3998, 0x1078, 0x69eb, 0x0078, 0x399a,
-	0xa085, 0x0001, 0x007c, 0x1078, 0x39c5, 0x0040, 0x39a3, 0x1078,
-	0x69c1, 0x0078, 0x39a5, 0xa085, 0x0001, 0x007c, 0x127e, 0x007e,
-	0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x39bd, 0x6800,
-	0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f,
-	0x1078, 0x3a7a, 0x007f, 0x0078, 0x39ac, 0x6083, 0x0000, 0x6087,
+	0x127f, 0x0078, 0x38e5, 0x1078, 0x37a6, 0x1078, 0x38f4, 0x00c0,
+	0x38e3, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x483c, 0x127f,
+	0x007c, 0xa01e, 0x0078, 0x38f6, 0x2019, 0x0001, 0xa00e, 0x127e,
+	0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc, 0x00c0, 0x3916,
+	0x8dff, 0x0040, 0x392b, 0x83ff, 0x0040, 0x390e, 0x6844, 0xa084,
+	0x00ff, 0xa606, 0x0040, 0x391b, 0x0078, 0x3916, 0x683c, 0xa406,
+	0x00c0, 0x3916, 0x6840, 0xa506, 0x0040, 0x391b, 0x2d08, 0x6800,
+	0x2068, 0x0078, 0x3900, 0x6a00, 0x604c, 0xad06, 0x00c0, 0x3923,
+	0x624e, 0x0078, 0x3926, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0,
+	0x392b, 0x6152, 0x8dff, 0x127f, 0x007c, 0xa01e, 0x0078, 0x3932,
+	0x2019, 0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x0040, 0x3960,
+	0x83ff, 0x0040, 0x3943, 0x6844, 0xa084, 0x00ff, 0xa606, 0x0040,
+	0x3950, 0x0078, 0x394b, 0x683c, 0xa406, 0x00c0, 0x394b, 0x6840,
+	0xa506, 0x0040, 0x3950, 0x2d08, 0x6800, 0x2068, 0x0078, 0x3935,
+	0x6a00, 0x6080, 0xad06, 0x00c0, 0x3958, 0x6282, 0x0078, 0x395b,
+	0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x3960, 0x6186, 0x8dff,
+	0x007c, 0x2001, 0x75ca, 0xa600, 0x2004, 0x6178, 0xa10c, 0x0040,
+	0x396b, 0x2011, 0x0001, 0x617c, 0xa10c, 0x0040, 0x3971, 0xa295,
+	0x0002, 0x007c, 0x1078, 0x39bd, 0x0040, 0x397a, 0x1078, 0x6a0b,
+	0x0078, 0x397c, 0xa085, 0x0001, 0x007c, 0x1078, 0x39bd, 0x0040,
+	0x3985, 0x1078, 0x699a, 0x0078, 0x3987, 0xa085, 0x0001, 0x007c,
+	0x1078, 0x39bd, 0x0040, 0x3990, 0x1078, 0x69e0, 0x0078, 0x3992,
+	0xa085, 0x0001, 0x007c, 0x1078, 0x39bd, 0x0040, 0x399b, 0x1078,
+	0x69b6, 0x0078, 0x399d, 0xa085, 0x0001, 0x007c, 0x127e, 0x007e,
+	0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d, 0x0040, 0x39b5, 0x6800,
+	0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b34,
+	0x1078, 0x3a72, 0x007f, 0x0078, 0x39a4, 0x6083, 0x0000, 0x6087,
 	0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c,
-	0x0f7e, 0x2079, 0x7651, 0x7804, 0xd0a4, 0x0040, 0x39f1, 0x157e,
-	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3825,
-	0x00c0, 0x39e5, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006,
-	0x00c0, 0x39e5, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0,
-	0x39d5, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x39f3, 0x1078,
-	0x45fe, 0x0f7f, 0x007c, 0x2011, 0x39f3, 0x1078, 0x456e, 0x157e,
-	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x3825,
-	0x00c0, 0x3a1f, 0x6000, 0xd0ec, 0x0040, 0x3a1f, 0x047e, 0x62a0,
-	0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x7541,
-	0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x4962,
-	0x1078, 0x48a5, 0x2009, 0x0000, 0x1078, 0x737b, 0x047f, 0x017f,
-	0x8108, 0x00f0, 0x39fd, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018,
+	0x0f7e, 0x2079, 0x7651, 0x7804, 0xd0a4, 0x0040, 0x39e9, 0x157e,
+	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x381d,
+	0x00c0, 0x39dd, 0x6004, 0xa084, 0xff00, 0x8007, 0xa086, 0x0006,
+	0x00c0, 0x39dd, 0x6000, 0xc0ed, 0x6002, 0x017f, 0x8108, 0x00f0,
+	0x39cd, 0x0c7f, 0x157f, 0x2009, 0x07d0, 0x2011, 0x39eb, 0x1078,
+	0x45f6, 0x0f7f, 0x007c, 0x2011, 0x39eb, 0x1078, 0x4566, 0x157e,
+	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x381d,
+	0x00c0, 0x3a17, 0x6000, 0xd0ec, 0x0040, 0x3a17, 0x047e, 0x62a0,
+	0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0x7536,
+	0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x2019, 0x0029, 0x1078, 0x495a,
+	0x1078, 0x489d, 0x2009, 0x0000, 0x1078, 0x7370, 0x047f, 0x017f,
+	0x8108, 0x00f0, 0x39f5, 0x0c7f, 0x157f, 0x007c, 0x0c7e, 0x6018,
 	0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x2071, 0x76ff,
 	0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017, 0x0000,
 	0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000,
 	0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x007c, 0x0e7e,
-	0x2071, 0x76ff, 0x684c, 0xa005, 0x00c0, 0x3a55, 0x7028, 0xc085,
-	0x702a, 0xa085, 0x0001, 0x0078, 0x3a78, 0x6a60, 0x7236, 0x6b64,
+	0x2071, 0x76ff, 0x684c, 0xa005, 0x00c0, 0x3a4d, 0x7028, 0xc085,
+	0x702a, 0xa085, 0x0001, 0x0078, 0x3a70, 0x6a60, 0x7236, 0x6b64,
 	0x733a, 0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c,
 	0x702e, 0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x8007, 0x8006,
 	0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
 	0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
-	0x0e7f, 0x007c, 0x0e7e, 0x6838, 0xd0fc, 0x00c0, 0x3acb, 0x6804,
-	0xa00d, 0x0040, 0x3a99, 0x0d7e, 0x0e7e, 0x2071, 0x7600, 0x027e,
+	0x0e7f, 0x007c, 0x0e7e, 0x6838, 0xd0fc, 0x00c0, 0x3ac3, 0x6804,
+	0xa00d, 0x0040, 0x3a91, 0x0d7e, 0x0e7e, 0x2071, 0x7600, 0x027e,
 	0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff,
-	0x00c0, 0x3a8a, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f,
-	0x0d7f, 0x2071, 0x76ff, 0x701c, 0xa005, 0x00c0, 0x3adc, 0x0068,
-	0x3ada, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3ada, 0x6934,
-	0xa186, 0x0103, 0x00c0, 0x3aed, 0x6948, 0x6844, 0xa105, 0x00c0,
-	0x3acd, 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0,
-	0x3ada, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001,
+	0x00c0, 0x3a82, 0x702e, 0x70a0, 0xa200, 0x70a2, 0x027f, 0x0e7f,
+	0x0d7f, 0x2071, 0x76ff, 0x701c, 0xa005, 0x00c0, 0x3ad4, 0x0068,
+	0x3ad2, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3ad2, 0x6934,
+	0xa186, 0x0103, 0x00c0, 0x3ae5, 0x6948, 0x6844, 0xa105, 0x00c0,
+	0x3ac5, 0x2009, 0x8020, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0,
+	0x3ad2, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001,
 	0x2091, 0x4080, 0x2071, 0x7600, 0x702c, 0x206a, 0x2d00, 0x702e,
 	0x70a0, 0x8000, 0x70a2, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100,
-	0x00c0, 0x3ada, 0x6868, 0xa005, 0x00c0, 0x3ada, 0x2009, 0x8020,
-	0x0078, 0x3ab3, 0x2071, 0x76ff, 0x2d08, 0x206b, 0x0000, 0x7010,
-	0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3aea, 0x6902,
-	0x0078, 0x3aeb, 0x711e, 0x0078, 0x3acb, 0xa18c, 0x00ff, 0xa186,
-	0x0017, 0x0040, 0x3afb, 0xa186, 0x001e, 0x0040, 0x3afb, 0xa18e,
-	0x001f, 0x00c0, 0x3ada, 0x684c, 0xd0cc, 0x0040, 0x3ada, 0x6850,
-	0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x3ada, 0x2009, 0x8021,
-	0x0078, 0x3ab3, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
+	0x00c0, 0x3ad2, 0x6868, 0xa005, 0x00c0, 0x3ad2, 0x2009, 0x8020,
+	0x0078, 0x3aab, 0x2071, 0x76ff, 0x2d08, 0x206b, 0x0000, 0x7010,
+	0x8000, 0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x3ae2, 0x6902,
+	0x0078, 0x3ae3, 0x711e, 0x0078, 0x3ac3, 0xa18c, 0x00ff, 0xa186,
+	0x0017, 0x0040, 0x3af3, 0xa186, 0x001e, 0x0040, 0x3af3, 0xa18e,
+	0x001f, 0x00c0, 0x3ad2, 0x684c, 0xd0cc, 0x0040, 0x3ad2, 0x6850,
+	0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x3ad2, 0x2009, 0x8021,
+	0x0078, 0x3aab, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c, 0xad80,
 	0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0x684a, 0x6952,
-	0x007c, 0x2071, 0x76ff, 0x7004, 0x0079, 0x3b1e, 0x3b26, 0x3b35,
-	0x3bc5, 0x3bc6, 0x3bd6, 0x3bdc, 0x3b27, 0x3bb3, 0x007c, 0x127e,
-	0x2091, 0x8000, 0x0068, 0x3b34, 0x2009, 0x000d, 0x7030, 0x200a,
+	0x007c, 0x2071, 0x76ff, 0x7004, 0x0079, 0x3b16, 0x3b1e, 0x3b2d,
+	0x3bbd, 0x3bbe, 0x3bce, 0x3bd4, 0x3b1f, 0x3bab, 0x007c, 0x127e,
+	0x2091, 0x8000, 0x0068, 0x3b2c, 0x2009, 0x000d, 0x7030, 0x200a,
 	0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x701c, 0xa06d, 0x0040,
-	0x3bb2, 0x0e7e, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3b94,
-	0x6934, 0xa186, 0x0103, 0x00c0, 0x3b6a, 0x6948, 0x6844, 0xa105,
-	0x00c0, 0x3b87, 0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068,
-	0x3b66, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3b66, 0x7122,
+	0x3baa, 0x0e7e, 0x2071, 0x7651, 0x7004, 0xd09c, 0x0040, 0x3b8c,
+	0x6934, 0xa186, 0x0103, 0x00c0, 0x3b62, 0x6948, 0x6844, 0xa105,
+	0x00c0, 0x3b7f, 0x2009, 0x8020, 0x127e, 0x2091, 0x8000, 0x0068,
+	0x3b5e, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x3b5e, 0x7122,
 	0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x127f, 0x0e7f, 0x1078, 0x3c0f, 0x0078, 0x3bb2, 0x127f, 0x0e7f,
-	0x0078, 0x3bb2, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x3b78,
-	0xa186, 0x001e, 0x0040, 0x3b78, 0xa18e, 0x001f, 0x00c0, 0x3b94,
-	0x684c, 0xd0cc, 0x0040, 0x3b94, 0x6850, 0xa084, 0x00ff, 0xa086,
-	0x0001, 0x00c0, 0x3b94, 0x2009, 0x8021, 0x0078, 0x3b4c, 0x6844,
-	0xa086, 0x0100, 0x00c0, 0x3b94, 0x6868, 0xa005, 0x00c0, 0x3b94,
-	0x2009, 0x8020, 0x0078, 0x3b4c, 0x0e7f, 0x1078, 0x3c23, 0x0040,
-	0x3bb2, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003,
-	0x00c0, 0x3ba9, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x3ba9,
-	0x710e, 0x7007, 0x0003, 0x1078, 0x3c43, 0x7050, 0xa086, 0x0100,
-	0x0040, 0x3bc6, 0x007c, 0x701c, 0xa06d, 0x0040, 0x3bc4, 0x1078,
-	0x3c23, 0x0040, 0x3bc4, 0x7007, 0x0003, 0x1078, 0x3c43, 0x7050,
-	0xa086, 0x0100, 0x0040, 0x3bc6, 0x007c, 0x007c, 0x7050, 0xa09e,
-	0x0100, 0x00c0, 0x3bcf, 0x7007, 0x0004, 0x0078, 0x3bd6, 0xa086,
-	0x0200, 0x00c0, 0x3bd5, 0x7007, 0x0005, 0x007c, 0x1078, 0x3bdd,
-	0x7006, 0x1078, 0x3c0f, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108,
-	0xa102, 0x0048, 0x3bea, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
-	0x0078, 0x3bf4, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3bf4,
+	0x127f, 0x0e7f, 0x1078, 0x3c07, 0x0078, 0x3baa, 0x127f, 0x0e7f,
+	0x0078, 0x3baa, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0040, 0x3b70,
+	0xa186, 0x001e, 0x0040, 0x3b70, 0xa18e, 0x001f, 0x00c0, 0x3b8c,
+	0x684c, 0xd0cc, 0x0040, 0x3b8c, 0x6850, 0xa084, 0x00ff, 0xa086,
+	0x0001, 0x00c0, 0x3b8c, 0x2009, 0x8021, 0x0078, 0x3b44, 0x6844,
+	0xa086, 0x0100, 0x00c0, 0x3b8c, 0x6868, 0xa005, 0x00c0, 0x3b8c,
+	0x2009, 0x8020, 0x0078, 0x3b44, 0x0e7f, 0x1078, 0x3c1b, 0x0040,
+	0x3baa, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003,
+	0x00c0, 0x3ba1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x3ba1,
+	0x710e, 0x7007, 0x0003, 0x1078, 0x3c3b, 0x7050, 0xa086, 0x0100,
+	0x0040, 0x3bbe, 0x007c, 0x701c, 0xa06d, 0x0040, 0x3bbc, 0x1078,
+	0x3c1b, 0x0040, 0x3bbc, 0x7007, 0x0003, 0x1078, 0x3c3b, 0x7050,
+	0xa086, 0x0100, 0x0040, 0x3bbe, 0x007c, 0x007c, 0x7050, 0xa09e,
+	0x0100, 0x00c0, 0x3bc7, 0x7007, 0x0004, 0x0078, 0x3bce, 0xa086,
+	0x0200, 0x00c0, 0x3bcd, 0x7007, 0x0005, 0x007c, 0x1078, 0x3bd5,
+	0x7006, 0x1078, 0x3c07, 0x007c, 0x007c, 0x702c, 0x7130, 0x8108,
+	0xa102, 0x0048, 0x3be2, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
+	0x0078, 0x3bec, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x3bec,
 	0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001, 0x700e,
-	0x00c0, 0x3c08, 0x127e, 0x2091, 0x8000, 0x0068, 0x3c0b, 0x2001,
+	0x00c0, 0x3c00, 0x127e, 0x2091, 0x8000, 0x0068, 0x3c03, 0x2001,
 	0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x127f, 0x007c,
 	0x2001, 0x0007, 0x007c, 0x2001, 0x0006, 0x127f, 0x007c, 0x701c,
-	0xa06d, 0x0040, 0x3c22, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001,
-	0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x3c1f, 0x701a, 0x127f,
-	0x1078, 0x1348, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e,
-	0x0040, 0x3c32, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3c32, 0xa006,
-	0x0078, 0x3c42, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x3c3c,
-	0x2300, 0xa005, 0x0078, 0x3c42, 0x0048, 0x3c41, 0xa302, 0x0078,
-	0x3c42, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056,
+	0xa06d, 0x0040, 0x3c1a, 0x127e, 0x2091, 0x8000, 0x7010, 0x8001,
+	0x7012, 0x2d04, 0x701e, 0xa005, 0x00c0, 0x3c17, 0x701a, 0x127f,
+	0x1078, 0x1340, 0x007c, 0x2019, 0x000d, 0x2304, 0x230c, 0xa10e,
+	0x0040, 0x3c2a, 0x2304, 0x230c, 0xa10e, 0x0040, 0x3c2a, 0xa006,
+	0x0078, 0x3c3a, 0x732c, 0x8319, 0x7130, 0xa102, 0x00c0, 0x3c34,
+	0x2300, 0xa005, 0x0078, 0x3c3a, 0x0048, 0x3c39, 0xa302, 0x0078,
+	0x3c3a, 0x8002, 0x007c, 0x2d00, 0x7026, 0xa080, 0x000d, 0x7056,
 	0x7053, 0x0000, 0x127e, 0x2091, 0x8000, 0x2009, 0x7859, 0x2104,
-	0xc08d, 0x200a, 0x127f, 0x1078, 0x1399, 0x007c, 0x2071, 0x76cd,
+	0xc08d, 0x200a, 0x127f, 0x1078, 0x1391, 0x007c, 0x2071, 0x76cd,
 	0x7003, 0x0000, 0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001,
 	0x704f, 0x0000, 0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040,
 	0x7083, 0x0000, 0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000,
-	0x007c, 0x0e7e, 0x2071, 0x76cd, 0x6848, 0xa005, 0x00c0, 0x3c7f,
-	0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x3ca4, 0x6a50,
+	0x007c, 0x0e7e, 0x2071, 0x76cd, 0x6848, 0xa005, 0x00c0, 0x3c77,
+	0x7028, 0xc085, 0x702a, 0xa085, 0x0001, 0x0078, 0x3c9c, 0x6a50,
 	0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a, 0x685c, 0x7042,
 	0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009, 0x000c, 0x200a,
 	0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210,
 	0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084, 0x702a, 0x7007,
 	0x0001, 0x700f, 0x0000, 0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071,
-	0x76cd, 0x7004, 0x1079, 0x3d04, 0x700c, 0x0079, 0x3caf, 0x3cb4,
-	0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x007c, 0x700c, 0x0079, 0x3cb8,
-	0x3cbd, 0x3d02, 0x3d02, 0x3d03, 0x3d03, 0x7830, 0x7930, 0xa106,
-	0x0040, 0x3cc7, 0x7830, 0x7930, 0xa106, 0x00c0, 0x3ced, 0x7030,
-	0xa10a, 0x0040, 0x3ced, 0x00c8, 0x3ccf, 0x712c, 0xa10a, 0xa18a,
-	0x0002, 0x00c8, 0x3cee, 0x1078, 0x1314, 0x0040, 0x3ced, 0x2d00,
+	0x76cd, 0x7004, 0x1079, 0x3cfc, 0x700c, 0x0079, 0x3ca7, 0x3cac,
+	0x3ca1, 0x3ca1, 0x3ca1, 0x3ca1, 0x007c, 0x700c, 0x0079, 0x3cb0,
+	0x3cb5, 0x3cfa, 0x3cfa, 0x3cfb, 0x3cfb, 0x7830, 0x7930, 0xa106,
+	0x0040, 0x3cbf, 0x7830, 0x7930, 0xa106, 0x00c0, 0x3ce5, 0x7030,
+	0xa10a, 0x0040, 0x3ce5, 0x00c8, 0x3cc7, 0x712c, 0xa10a, 0xa18a,
+	0x0002, 0x00c8, 0x3ce6, 0x1078, 0x130c, 0x0040, 0x3ce5, 0x2d00,
 	0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057, 0x0000, 0x127e,
 	0x007e, 0x2091, 0x8000, 0x2009, 0x7859, 0x2104, 0xc085, 0x200a,
-	0x007f, 0x700e, 0x127f, 0x1078, 0x1399, 0x007c, 0x1078, 0x1314,
-	0x0040, 0x3ced, 0x2d00, 0x705a, 0x1078, 0x1314, 0x00c0, 0x3cfa,
-	0x0078, 0x3cd9, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004,
-	0x0078, 0x3cdd, 0x007c, 0x007c, 0x3d15, 0x3d16, 0x3d4d, 0x3d4e,
-	0x3d02, 0x3d84, 0x3d89, 0x3dc0, 0x3dc1, 0x3ddc, 0x3ddd, 0x3dde,
-	0x3ddf, 0x3de0, 0x3de1, 0x3e4a, 0x3e74, 0x007c, 0x700c, 0x0079,
-	0x3d19, 0x3d1e, 0x3d21, 0x3d31, 0x3d4c, 0x3d4c, 0x1078, 0x3cb5,
-	0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x4153,
-	0x0040, 0x3d2e, 0x2091, 0x8000, 0x1078, 0x3cb5, 0x0d7f, 0x0078,
-	0x3d3a, 0x127e, 0x8001, 0x700e, 0x1078, 0x4153, 0x7058, 0x2068,
+	0x007f, 0x700e, 0x127f, 0x1078, 0x1391, 0x007c, 0x1078, 0x130c,
+	0x0040, 0x3ce5, 0x2d00, 0x705a, 0x1078, 0x130c, 0x00c0, 0x3cf2,
+	0x0078, 0x3cd1, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004,
+	0x0078, 0x3cd5, 0x007c, 0x007c, 0x3d0d, 0x3d0e, 0x3d45, 0x3d46,
+	0x3cfa, 0x3d7c, 0x3d81, 0x3db8, 0x3db9, 0x3dd4, 0x3dd5, 0x3dd6,
+	0x3dd7, 0x3dd8, 0x3dd9, 0x3e42, 0x3e6c, 0x007c, 0x700c, 0x0079,
+	0x3d11, 0x3d16, 0x3d19, 0x3d29, 0x3d44, 0x3d44, 0x1078, 0x3cad,
+	0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x414b,
+	0x0040, 0x3d26, 0x2091, 0x8000, 0x1078, 0x3cad, 0x0d7f, 0x0078,
+	0x3d32, 0x127e, 0x8001, 0x700e, 0x1078, 0x414b, 0x7058, 0x2068,
 	0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084,
-	0x00ff, 0xa08a, 0x0020, 0x00c8, 0x3d49, 0x1079, 0x3d64, 0x127f,
-	0x007c, 0x127f, 0x1078, 0x3de2, 0x007c, 0x007c, 0x007c, 0x0e7e,
-	0x2071, 0x76cd, 0x700c, 0x0079, 0x3d55, 0x3d5a, 0x3d5a, 0x3d5a,
-	0x3d5c, 0x3d60, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3d62,
-	0x700f, 0x0002, 0x0e7f, 0x007c, 0x3de2, 0x3de2, 0x3dfe, 0x3de2,
-	0x3ee9, 0x3de2, 0x3de2, 0x3de2, 0x3de2, 0x3de2, 0x3dfe, 0x3f2e,
-	0x3f77, 0x3fcf, 0x3fe2, 0x3de2, 0x3de2, 0x3e1a, 0x3dfe, 0x3de2,
-	0x3de2, 0x3e30, 0x4069, 0x4086, 0x3de2, 0x3e1a, 0x3de2, 0x3de2,
-	0x3de2, 0x3de2, 0x3e30, 0x4086, 0x7020, 0x2068, 0x1078, 0x1348,
-	0x007c, 0x700c, 0x0079, 0x3d8c, 0x3d91, 0x3d94, 0x3da4, 0x3dbf,
-	0x3dbf, 0x1078, 0x3cb5, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058,
-	0x007e, 0x1078, 0x4153, 0x0040, 0x3da1, 0x2091, 0x8000, 0x1078,
-	0x3cb5, 0x0d7f, 0x0078, 0x3dad, 0x127e, 0x8001, 0x700e, 0x1078,
-	0x4153, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807,
-	0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x3dbc,
-	0x1079, 0x3dc2, 0x127f, 0x007c, 0x127f, 0x1078, 0x3de2, 0x007c,
-	0x007c, 0x007c, 0x3de2, 0x3dfe, 0x3ed3, 0x3de2, 0x3dfe, 0x3de2,
-	0x3dfe, 0x3dfe, 0x3de2, 0x3dfe, 0x3ed3, 0x3dfe, 0x3dfe, 0x3dfe,
-	0x3dfe, 0x3dfe, 0x3de2, 0x3dfe, 0x3ed3, 0x3de2, 0x3de2, 0x3dfe,
-	0x3de2, 0x3de2, 0x3de2, 0x3dfe, 0x007c, 0x007c, 0x007c, 0x007c,
+	0x00ff, 0xa08a, 0x0020, 0x00c8, 0x3d41, 0x1079, 0x3d5c, 0x127f,
+	0x007c, 0x127f, 0x1078, 0x3dda, 0x007c, 0x007c, 0x007c, 0x0e7e,
+	0x2071, 0x76cd, 0x700c, 0x0079, 0x3d4d, 0x3d52, 0x3d52, 0x3d52,
+	0x3d54, 0x3d58, 0x0e7f, 0x007c, 0x700f, 0x0001, 0x0078, 0x3d5a,
+	0x700f, 0x0002, 0x0e7f, 0x007c, 0x3dda, 0x3dda, 0x3df6, 0x3dda,
+	0x3ee1, 0x3dda, 0x3dda, 0x3dda, 0x3dda, 0x3dda, 0x3df6, 0x3f26,
+	0x3f6f, 0x3fc7, 0x3fda, 0x3dda, 0x3dda, 0x3e12, 0x3df6, 0x3dda,
+	0x3dda, 0x3e28, 0x4061, 0x407e, 0x3dda, 0x3e12, 0x3dda, 0x3dda,
+	0x3dda, 0x3dda, 0x3e28, 0x407e, 0x7020, 0x2068, 0x1078, 0x1340,
+	0x007c, 0x700c, 0x0079, 0x3d84, 0x3d89, 0x3d8c, 0x3d9c, 0x3db7,
+	0x3db7, 0x1078, 0x3cad, 0x007c, 0x127e, 0x8001, 0x700e, 0x7058,
+	0x007e, 0x1078, 0x414b, 0x0040, 0x3d99, 0x2091, 0x8000, 0x1078,
+	0x3cad, 0x0d7f, 0x0078, 0x3da5, 0x127e, 0x8001, 0x700e, 0x1078,
+	0x414b, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807,
+	0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x00c8, 0x3db4,
+	0x1079, 0x3dba, 0x127f, 0x007c, 0x127f, 0x1078, 0x3dda, 0x007c,
+	0x007c, 0x007c, 0x3dda, 0x3df6, 0x3ecb, 0x3dda, 0x3df6, 0x3dda,
+	0x3df6, 0x3df6, 0x3dda, 0x3df6, 0x3ecb, 0x3df6, 0x3df6, 0x3df6,
+	0x3df6, 0x3df6, 0x3dda, 0x3df6, 0x3ecb, 0x3dda, 0x3dda, 0x3df6,
+	0x3dda, 0x3dda, 0x3dda, 0x3df6, 0x007c, 0x007c, 0x007c, 0x007c,
 	0x007c, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5,
-	0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a7a, 0x127f, 0x007c,
+	0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a72, 0x127f, 0x007c,
 	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x3a7a, 0x127f, 0x007c, 0x7007, 0x0001,
+	0x2091, 0x8000, 0x1078, 0x3a72, 0x127f, 0x007c, 0x7007, 0x0001,
 	0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x3a7a, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
-	0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a7a,
-	0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3df0,
-	0x8001, 0x00c0, 0x3e27, 0x7007, 0x0001, 0x0078, 0x3eb0, 0x7007,
-	0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3eb0, 0x007c,
+	0x1078, 0x3a72, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084,
+	0x00ff, 0xc0dd, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x3a72,
+	0x127f, 0x007c, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0040, 0x3de8,
+	0x8001, 0x00c0, 0x3e1f, 0x7007, 0x0001, 0x0078, 0x3ea8, 0x7007,
+	0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x3ea8, 0x007c,
 	0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098,
 	0x20a1, 0x76f8, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8,
-	0x3e0c, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3e0c, 0xa080, 0x3ea1,
-	0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x3e94, 0x1078, 0x1314,
-	0x00c0, 0x3e55, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4,
+	0x3e04, 0x6884, 0xa08a, 0x0003, 0x00c8, 0x3e04, 0xa080, 0x3e99,
+	0x2004, 0x70c6, 0x7010, 0xa015, 0x0040, 0x3e8c, 0x1078, 0x130c,
+	0x00c0, 0x3e4d, 0x7007, 0x000f, 0x007c, 0x2d00, 0x7022, 0x70c4,
 	0x2060, 0x6000, 0x6836, 0x6004, 0xad00, 0x7096, 0x6008, 0xa20a,
-	0x00c8, 0x3e64, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b,
-	0xa296, 0x0004, 0x0040, 0x3e6d, 0xa108, 0x719a, 0x810b, 0x719e,
-	0xae90, 0x0022, 0x1078, 0x137f, 0x7090, 0xa08e, 0x0100, 0x0040,
-	0x3e88, 0xa086, 0x0200, 0x0040, 0x3e80, 0x7007, 0x0010, 0x007c,
-	0x7020, 0x2068, 0x1078, 0x1348, 0x7014, 0x2068, 0x0078, 0x3e0c,
+	0x00c8, 0x3e5c, 0xa00e, 0x2200, 0x7112, 0x620c, 0x8003, 0x800b,
+	0xa296, 0x0004, 0x0040, 0x3e65, 0xa108, 0x719a, 0x810b, 0x719e,
+	0xae90, 0x0022, 0x1078, 0x1377, 0x7090, 0xa08e, 0x0100, 0x0040,
+	0x3e80, 0xa086, 0x0200, 0x0040, 0x3e78, 0x7007, 0x0010, 0x007c,
+	0x7020, 0x2068, 0x1078, 0x1340, 0x7014, 0x2068, 0x0078, 0x3e04,
 	0x7020, 0x2068, 0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068,
-	0x6906, 0x711a, 0x0078, 0x3e4a, 0x7014, 0x2068, 0x7007, 0x0001,
-	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x40a3, 0x0078,
-	0x3eb0, 0x3ea4, 0x3ea8, 0x3eac, 0x0002, 0x0011, 0x0007, 0x0004,
+	0x6906, 0x711a, 0x0078, 0x3e42, 0x7014, 0x2068, 0x7007, 0x0001,
+	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x409b, 0x0078,
+	0x3ea8, 0x3e9c, 0x3ea0, 0x3ea4, 0x0002, 0x0011, 0x0007, 0x0004,
 	0x000a, 0x000f, 0x0005, 0x0006, 0x0012, 0x000f, 0x0005, 0x0006,
-	0x2009, 0x762c, 0x210c, 0x81ff, 0x00c0, 0x3ecd, 0x6838, 0xa084,
-	0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3668, 0x00c0, 0x3ec1,
-	0x007c, 0x1078, 0x3b0a, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b3f,
-	0x1078, 0x3a7a, 0x127f, 0x0078, 0x3ec0, 0x2001, 0x0028, 0x2009,
-	0x0000, 0x0078, 0x3ec1, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906,
-	0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x3ee2, 0x7007, 0x0006,
-	0x0078, 0x3ee8, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a,
+	0x2009, 0x762c, 0x210c, 0x81ff, 0x00c0, 0x3ec5, 0x6838, 0xa084,
+	0x00ff, 0x683a, 0x6853, 0x0000, 0x1078, 0x3660, 0x00c0, 0x3eb9,
+	0x007c, 0x1078, 0x3b02, 0x127e, 0x2091, 0x8000, 0x1078, 0x6b34,
+	0x1078, 0x3a72, 0x127f, 0x0078, 0x3eb8, 0x2001, 0x0028, 0x2009,
+	0x0000, 0x0078, 0x3eb9, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906,
+	0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x3eda, 0x7007, 0x0006,
+	0x0078, 0x3ee0, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a,
 	0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848,
-	0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3f14,
-	0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3f14,
-	0xa005, 0x00c0, 0x3f2b, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078,
-	0x3825, 0x00c0, 0x3f2b, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078,
-	0x38ba, 0x067f, 0x0078, 0x3f2b, 0x047e, 0x2011, 0x760c, 0x2224,
-	0xc484, 0xc48c, 0x2412, 0x047f, 0x0c7e, 0x1078, 0x3825, 0x00c0,
-	0x3f27, 0x2091, 0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108,
-	0x00f0, 0x3f1d, 0x0c7f, 0x1078, 0x1348, 0x007c, 0x127e, 0x2091,
+	0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x3f0c,
+	0x2009, 0x0000, 0x20a9, 0x007e, 0xa096, 0x0002, 0x0040, 0x3f0c,
+	0xa005, 0x00c0, 0x3f23, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078,
+	0x381d, 0x00c0, 0x3f23, 0x067e, 0x6e44, 0xa6b4, 0x000f, 0x1078,
+	0x38b2, 0x067f, 0x0078, 0x3f23, 0x047e, 0x2011, 0x760c, 0x2224,
+	0xc484, 0xc48c, 0x2412, 0x047f, 0x0c7e, 0x1078, 0x381d, 0x00c0,
+	0x3f1f, 0x2091, 0x8000, 0x607b, 0x0000, 0x2091, 0x8001, 0x8108,
+	0x00f0, 0x3f15, 0x0c7f, 0x1078, 0x1340, 0x007c, 0x127e, 0x2091,
 	0x8000, 0x7007, 0x0001, 0x2001, 0x7652, 0x2004, 0xd0a4, 0x0040,
-	0x3f6e, 0x6944, 0x1078, 0x416f, 0x6100, 0xd184, 0x0040, 0x3f53,
-	0x6858, 0xa084, 0x00ff, 0x00c0, 0x3f71, 0x6000, 0xd084, 0x0040,
-	0x3f6e, 0x6004, 0xa005, 0x00c0, 0x3f74, 0x6003, 0x0000, 0x600b,
-	0x0000, 0x0078, 0x3f6b, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0,
-	0x3f5b, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff,
-	0x0040, 0x3f6e, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040,
-	0x3f6e, 0x600a, 0x6202, 0x127f, 0x0078, 0x4142, 0x127f, 0x0078,
-	0x413a, 0x127f, 0x0078, 0x4132, 0x127f, 0x0078, 0x4136, 0x127e,
+	0x3f66, 0x6944, 0x1078, 0x4167, 0x6100, 0xd184, 0x0040, 0x3f4b,
+	0x6858, 0xa084, 0x00ff, 0x00c0, 0x3f69, 0x6000, 0xd084, 0x0040,
+	0x3f66, 0x6004, 0xa005, 0x00c0, 0x3f6c, 0x6003, 0x0000, 0x600b,
+	0x0000, 0x0078, 0x3f63, 0x2011, 0x0001, 0x6860, 0xa005, 0x00c0,
+	0x3f53, 0x2001, 0x001e, 0x8000, 0x6016, 0x6858, 0xa084, 0x00ff,
+	0x0040, 0x3f66, 0x6006, 0x6858, 0x8007, 0xa084, 0x00ff, 0x0040,
+	0x3f66, 0x600a, 0x6202, 0x127f, 0x0078, 0x413a, 0x127f, 0x0078,
+	0x4132, 0x127f, 0x0078, 0x412a, 0x127f, 0x0078, 0x412e, 0x127e,
 	0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x7652, 0x2004, 0xd0a4,
-	0x0040, 0x3fcc, 0x6944, 0x1078, 0x416f, 0x6000, 0xa084, 0x0001,
-	0x0040, 0x3fcc, 0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040,
-	0x3fa4, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3f9d, 0x2100,
-	0xa210, 0x0048, 0x3fc9, 0x0078, 0x3fa4, 0x8001, 0x00c0, 0x3fc9,
-	0x2100, 0xa212, 0x0048, 0x3fc9, 0xa484, 0x000c, 0x0040, 0x3fbe,
-	0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3fb6,
-	0x2100, 0xa318, 0x0048, 0x3fc9, 0x0078, 0x3fbe, 0xa082, 0x0004,
-	0x00c0, 0x3fc9, 0x2100, 0xa31a, 0x0048, 0x3fc9, 0x6860, 0xa005,
-	0x0040, 0x3fc4, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078,
-	0x4142, 0x127f, 0x0078, 0x413e, 0x127f, 0x0078, 0x413a, 0x127e,
-	0x2091, 0x8000, 0x7007, 0x0001, 0x6944, 0x1078, 0x416f, 0x6308,
-	0x8318, 0x0048, 0x3fdf, 0x630a, 0x127f, 0x0078, 0x4150, 0x127f,
-	0x0078, 0x413e, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001,
-	0x684c, 0xd0ac, 0x0040, 0x3ff6, 0x027e, 0x2009, 0x0000, 0x2011,
-	0xfcff, 0x1078, 0x46b4, 0x027f, 0x0078, 0x402c, 0x6858, 0xa005,
-	0x0040, 0x4040, 0x685c, 0xa065, 0x0040, 0x403c, 0x2001, 0x762c,
-	0x2004, 0xa005, 0x0040, 0x4008, 0x1078, 0x6aa1, 0x0078, 0x400e,
-	0x6013, 0x0400, 0x2009, 0x0041, 0x1078, 0x5c29, 0x6958, 0xa18c,
-	0xe600, 0xa186, 0x2000, 0x0040, 0x4024, 0xa186, 0x0400, 0x0040,
-	0x4024, 0x6944, 0x0c7e, 0x1078, 0x460c, 0x6000, 0xa084, 0xfdff,
-	0x6002, 0x0c7f, 0x0078, 0x402c, 0x027e, 0x2009, 0x0000, 0x2011,
-	0xfdff, 0x1078, 0x46b4, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x4038,
-	0x6944, 0x1078, 0x460c, 0x6008, 0x8000, 0x0048, 0x4038, 0x600a,
-	0x0c7f, 0x127f, 0x0078, 0x4142, 0x0c7f, 0x127f, 0x0078, 0x413a,
-	0x6954, 0xa186, 0x002a, 0x00c0, 0x404c, 0x2001, 0x760c, 0x200c,
-	0xc194, 0x2102, 0x0078, 0x402c, 0xa186, 0x0020, 0x0040, 0x4061,
-	0xa186, 0x0029, 0x00c0, 0x403c, 0x6944, 0xa18c, 0xff00, 0x810f,
-	0x1078, 0x3825, 0x00c0, 0x402c, 0x6000, 0xc0e4, 0x6002, 0x0078,
-	0x402c, 0x685c, 0xa065, 0x0040, 0x403c, 0x6017, 0x0014, 0x0078,
-	0x402c, 0x6944, 0x1078, 0x416f, 0x6000, 0xa084, 0x0001, 0x0040,
-	0x4082, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x407c, 0x6206,
-	0x2091, 0x8001, 0x0078, 0x4150, 0x2091, 0x8001, 0x6853, 0x0016,
-	0x0078, 0x4149, 0x6853, 0x0007, 0x0078, 0x4149, 0x6834, 0x8007,
-	0xa084, 0x00ff, 0x00c0, 0x4090, 0x1078, 0x3df0, 0x0078, 0x40a2,
-	0x2030, 0x8001, 0x00c0, 0x409a, 0x7007, 0x0001, 0x1078, 0x40a3,
-	0x0078, 0x40a2, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
-	0x704b, 0x40a3, 0x007c, 0x0e7e, 0x2009, 0x762c, 0x210c, 0x81ff,
-	0x00c0, 0x4124, 0x2009, 0x760c, 0x210c, 0xd194, 0x00c0, 0x412e,
-	0x6848, 0x2070, 0xae82, 0x7d00, 0x0048, 0x4113, 0x2001, 0x7615,
-	0x2004, 0xae02, 0x00c8, 0x4113, 0x6944, 0x1078, 0x416f, 0x6100,
-	0xa184, 0x0001, 0x0040, 0x40f9, 0xa184, 0x0100, 0x00c0, 0x4117,
-	0xa184, 0x0200, 0x00c0, 0x411b, 0x601c, 0xa005, 0x00c0, 0x411f,
-	0x711c, 0xa186, 0x0006, 0x00c0, 0x40fe, 0x6853, 0x0000, 0x6803,
+	0x0040, 0x3fc4, 0x6944, 0x1078, 0x4167, 0x6000, 0xa084, 0x0001,
+	0x0040, 0x3fc4, 0x6204, 0x6308, 0x6c48, 0xa484, 0x0003, 0x0040,
+	0x3f9c, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x3f95, 0x2100,
+	0xa210, 0x0048, 0x3fc1, 0x0078, 0x3f9c, 0x8001, 0x00c0, 0x3fc1,
+	0x2100, 0xa212, 0x0048, 0x3fc1, 0xa484, 0x000c, 0x0040, 0x3fb6,
+	0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0, 0x3fae,
+	0x2100, 0xa318, 0x0048, 0x3fc1, 0x0078, 0x3fb6, 0xa082, 0x0004,
+	0x00c0, 0x3fc1, 0x2100, 0xa31a, 0x0048, 0x3fc1, 0x6860, 0xa005,
+	0x0040, 0x3fbc, 0x8000, 0x6016, 0x6206, 0x630a, 0x127f, 0x0078,
+	0x413a, 0x127f, 0x0078, 0x4136, 0x127f, 0x0078, 0x4132, 0x127e,
+	0x2091, 0x8000, 0x7007, 0x0001, 0x6944, 0x1078, 0x4167, 0x6308,
+	0x8318, 0x0048, 0x3fd7, 0x630a, 0x127f, 0x0078, 0x4148, 0x127f,
+	0x0078, 0x4136, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001,
+	0x684c, 0xd0ac, 0x0040, 0x3fee, 0x027e, 0x2009, 0x0000, 0x2011,
+	0xfcff, 0x1078, 0x46ac, 0x027f, 0x0078, 0x4024, 0x6858, 0xa005,
+	0x0040, 0x4038, 0x685c, 0xa065, 0x0040, 0x4034, 0x2001, 0x762c,
+	0x2004, 0xa005, 0x0040, 0x4000, 0x1078, 0x6a96, 0x0078, 0x4006,
+	0x6013, 0x0400, 0x2009, 0x0041, 0x1078, 0x5c21, 0x6958, 0xa18c,
+	0xe600, 0xa186, 0x2000, 0x0040, 0x401c, 0xa186, 0x0400, 0x0040,
+	0x401c, 0x6944, 0x0c7e, 0x1078, 0x4604, 0x6000, 0xa084, 0xfdff,
+	0x6002, 0x0c7f, 0x0078, 0x4024, 0x027e, 0x2009, 0x0000, 0x2011,
+	0xfdff, 0x1078, 0x46ac, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x4030,
+	0x6944, 0x1078, 0x4604, 0x6008, 0x8000, 0x0048, 0x4030, 0x600a,
+	0x0c7f, 0x127f, 0x0078, 0x413a, 0x0c7f, 0x127f, 0x0078, 0x4132,
+	0x6954, 0xa186, 0x002a, 0x00c0, 0x4044, 0x2001, 0x760c, 0x200c,
+	0xc194, 0x2102, 0x0078, 0x4024, 0xa186, 0x0020, 0x0040, 0x4059,
+	0xa186, 0x0029, 0x00c0, 0x4034, 0x6944, 0xa18c, 0xff00, 0x810f,
+	0x1078, 0x381d, 0x00c0, 0x4024, 0x6000, 0xc0e4, 0x6002, 0x0078,
+	0x4024, 0x685c, 0xa065, 0x0040, 0x4034, 0x6017, 0x0014, 0x0078,
+	0x4024, 0x6944, 0x1078, 0x4167, 0x6000, 0xa084, 0x0001, 0x0040,
+	0x407a, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x4074, 0x6206,
+	0x2091, 0x8001, 0x0078, 0x4148, 0x2091, 0x8001, 0x6853, 0x0016,
+	0x0078, 0x4141, 0x6853, 0x0007, 0x0078, 0x4141, 0x6834, 0x8007,
+	0xa084, 0x00ff, 0x00c0, 0x4088, 0x1078, 0x3de8, 0x0078, 0x409a,
+	0x2030, 0x8001, 0x00c0, 0x4092, 0x7007, 0x0001, 0x1078, 0x409b,
+	0x0078, 0x409a, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
+	0x704b, 0x409b, 0x007c, 0x0e7e, 0x2009, 0x762c, 0x210c, 0x81ff,
+	0x00c0, 0x411c, 0x2009, 0x760c, 0x210c, 0xd194, 0x00c0, 0x4126,
+	0x6848, 0x2070, 0xae82, 0x7d00, 0x0048, 0x410b, 0x2001, 0x7615,
+	0x2004, 0xae02, 0x00c8, 0x410b, 0x6944, 0x1078, 0x4167, 0x6100,
+	0xa184, 0x0001, 0x0040, 0x40f1, 0xa184, 0x0100, 0x00c0, 0x410f,
+	0xa184, 0x0200, 0x00c0, 0x4113, 0x601c, 0xa005, 0x00c0, 0x4117,
+	0x711c, 0xa186, 0x0006, 0x00c0, 0x40f6, 0x6853, 0x0000, 0x6803,
 	0x0000, 0x2d08, 0x127e, 0x2091, 0x8000, 0x7010, 0xa005, 0x00c0,
-	0x40f0, 0x7112, 0x7018, 0xa065, 0x0040, 0x4123, 0x6000, 0xd0e4,
-	0x00c0, 0x4128, 0x2e60, 0x1078, 0x4615, 0x127f, 0x0e7f, 0x007c,
-	0x2068, 0x6800, 0xa005, 0x00c0, 0x40f0, 0x6902, 0x127f, 0x0e7f,
-	0x007c, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x4149, 0x6944, 0xa18c,
-	0xff00, 0x810f, 0x1078, 0x3825, 0x00c0, 0x4129, 0x6000, 0xd0e4,
-	0x00c0, 0x4129, 0x711c, 0xa186, 0x0007, 0x00c0, 0x4113, 0x6853,
-	0x0002, 0x0078, 0x412b, 0x6853, 0x0008, 0x0078, 0x412b, 0x6853,
-	0x000e, 0x0078, 0x412b, 0x6853, 0x0017, 0x0078, 0x412b, 0x6853,
-	0x0035, 0x0078, 0x412b, 0x127f, 0x6853, 0x0028, 0x0078, 0x412b,
-	0x127f, 0x6853, 0x0029, 0x0e7f, 0x0078, 0x4149, 0x6853, 0x002a,
-	0x0078, 0x412b, 0x2009, 0x003e, 0x0078, 0x4144, 0x2009, 0x0004,
-	0x0078, 0x4144, 0x2009, 0x0006, 0x0078, 0x4144, 0x2009, 0x0016,
-	0x0078, 0x4144, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105,
-	0x6856, 0x2091, 0x8000, 0x1078, 0x3a7a, 0x2091, 0x8001, 0x007c,
-	0x1078, 0x1348, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048,
-	0x4160, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x416c,
-	0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x416c, 0x7074, 0xa081,
+	0x40e8, 0x7112, 0x7018, 0xa065, 0x0040, 0x411b, 0x6000, 0xd0e4,
+	0x00c0, 0x4120, 0x2e60, 0x1078, 0x460d, 0x127f, 0x0e7f, 0x007c,
+	0x2068, 0x6800, 0xa005, 0x00c0, 0x40e8, 0x6902, 0x127f, 0x0e7f,
+	0x007c, 0x0e7f, 0x6853, 0x0006, 0x0078, 0x4141, 0x6944, 0xa18c,
+	0xff00, 0x810f, 0x1078, 0x381d, 0x00c0, 0x4121, 0x6000, 0xd0e4,
+	0x00c0, 0x4121, 0x711c, 0xa186, 0x0007, 0x00c0, 0x410b, 0x6853,
+	0x0002, 0x0078, 0x4123, 0x6853, 0x0008, 0x0078, 0x4123, 0x6853,
+	0x000e, 0x0078, 0x4123, 0x6853, 0x0017, 0x0078, 0x4123, 0x6853,
+	0x0035, 0x0078, 0x4123, 0x127f, 0x6853, 0x0028, 0x0078, 0x4123,
+	0x127f, 0x6853, 0x0029, 0x0e7f, 0x0078, 0x4141, 0x6853, 0x002a,
+	0x0078, 0x4123, 0x2009, 0x003e, 0x0078, 0x413c, 0x2009, 0x0004,
+	0x0078, 0x413c, 0x2009, 0x0006, 0x0078, 0x413c, 0x2009, 0x0016,
+	0x0078, 0x413c, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105,
+	0x6856, 0x2091, 0x8000, 0x1078, 0x3a72, 0x2091, 0x8001, 0x007c,
+	0x1078, 0x1340, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102, 0x0048,
+	0x4158, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078, 0x4164,
+	0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x4164, 0x7074, 0xa081,
 	0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c, 0x0d7e,
-	0x1078, 0x460c, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204,
+	0x1078, 0x4604, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004, 0x2204,
 	0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002, 0x3d08,
-	0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x418b, 0xa086,
-	0x1000, 0x00c0, 0x41a7, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0,
-	0x4192, 0x3e60, 0xac84, 0x0007, 0x00c0, 0x41a7, 0xac82, 0x7d00,
-	0x0048, 0x41a7, 0x6854, 0xac02, 0x00c8, 0x41a7, 0x2009, 0x0047,
-	0x1078, 0x5c29, 0x7a1c, 0xd284, 0x00c0, 0x417d, 0x007c, 0xa016,
-	0x1078, 0x1572, 0x0078, 0x41a2, 0x157e, 0x137e, 0x147e, 0x20e1,
-	0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x00c0, 0x41d5, 0xa484,
-	0x7000, 0xa086, 0x1000, 0x00c0, 0x41d5, 0x1078, 0x41e2, 0x0040,
-	0x41d5, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, 0x4200, 0x147f,
-	0x137f, 0x157f, 0x2009, 0x783e, 0x2104, 0xa005, 0x00c0, 0x41d1,
-	0x007c, 0x1078, 0x4c7a, 0x0078, 0x41d0, 0x1078, 0x7574, 0x1078,
-	0x41e2, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, 0x137f, 0x157f,
-	0x0078, 0x41d0, 0xa484, 0x01ff, 0x687a, 0xa005, 0x0040, 0x41f4,
+	0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x4183, 0xa086,
+	0x1000, 0x00c0, 0x419f, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x00c0,
+	0x418a, 0x3e60, 0xac84, 0x0007, 0x00c0, 0x419f, 0xac82, 0x7d00,
+	0x0048, 0x419f, 0x6854, 0xac02, 0x00c8, 0x419f, 0x2009, 0x0047,
+	0x1078, 0x5c21, 0x7a1c, 0xd284, 0x00c0, 0x4175, 0x007c, 0xa016,
+	0x1078, 0x156a, 0x0078, 0x419a, 0x157e, 0x137e, 0x147e, 0x20e1,
+	0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x00c0, 0x41cd, 0xa484,
+	0x7000, 0xa086, 0x1000, 0x00c0, 0x41cd, 0x1078, 0x41da, 0x0040,
+	0x41cd, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078, 0x41f8, 0x147f,
+	0x137f, 0x157f, 0x2009, 0x783e, 0x2104, 0xa005, 0x00c0, 0x41c9,
+	0x007c, 0x1078, 0x4c72, 0x0078, 0x41c8, 0x1078, 0x7569, 0x1078,
+	0x41da, 0x20e1, 0x3000, 0x7828, 0x7828, 0x147f, 0x137f, 0x157f,
+	0x0078, 0x41c8, 0xa484, 0x01ff, 0x687a, 0xa005, 0x0040, 0x41ec,
 	0xa080, 0x001f, 0xa084, 0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0,
 	0x2099, 0x020a, 0x53a5, 0x007c, 0x20a9, 0x000c, 0x20e1, 0x1000,
-	0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0078, 0x41f3,
+	0x2ea0, 0x2099, 0x020a, 0x53a5, 0xa085, 0x0001, 0x0078, 0x41eb,
 	0x7000, 0xa084, 0xff00, 0xa08c, 0xf000, 0x8007, 0xa196, 0x0000,
-	0x00c0, 0x420d, 0x0078, 0x4381, 0x007c, 0xa196, 0x2000, 0x00c0,
-	0x421e, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x421a, 0x1078, 0x2eb2,
-	0x0078, 0x420c, 0x1078, 0x4226, 0x0078, 0x420c, 0xa196, 0x8000,
-	0x00c0, 0x420c, 0x1078, 0x4407, 0x0078, 0x420c, 0x0c7e, 0x7110,
-	0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, 0x4233, 0xa196,
-	0x0023, 0x00c0, 0x4328, 0xa08e, 0x0023, 0x00c0, 0x4264, 0x1078,
-	0x447e, 0x0040, 0x4328, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200,
-	0x00c0, 0x424c, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0015,
-	0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0210, 0x00c0, 0x4256,
-	0x2009, 0x0015, 0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0100,
-	0x00c0, 0x4328, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0016,
-	0x1078, 0x5c29, 0x0078, 0x4328, 0xa08e, 0x0022, 0x00c0, 0x4328,
-	0x7030, 0xa08e, 0x0300, 0x00c0, 0x4275, 0x7034, 0xa005, 0x00c0,
-	0x4328, 0x2009, 0x0017, 0x0078, 0x42f4, 0xa08e, 0x0500, 0x00c0,
-	0x4281, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x0018, 0x0078,
-	0x42f4, 0xa08e, 0x2010, 0x00c0, 0x4289, 0x2009, 0x0019, 0x0078,
-	0x42f4, 0xa08e, 0x2110, 0x00c0, 0x4291, 0x2009, 0x001a, 0x0078,
-	0x42f4, 0xa08e, 0x5200, 0x00c0, 0x429d, 0x7034, 0xa005, 0x00c0,
-	0x4328, 0x2009, 0x001b, 0x0078, 0x42f4, 0xa08e, 0x5000, 0x00c0,
-	0x42a9, 0x7034, 0xa005, 0x00c0, 0x4328, 0x2009, 0x001c, 0x0078,
-	0x42f4, 0xa08e, 0x1200, 0x00c0, 0x42b5, 0x7034, 0xa005, 0x00c0,
-	0x4328, 0x2009, 0x0024, 0x0078, 0x42f4, 0xa08c, 0xff00, 0xa18e,
-	0x2400, 0x00c0, 0x42bf, 0x2009, 0x002d, 0x0078, 0x42f4, 0xa08c,
-	0xff00, 0xa18e, 0x5300, 0x00c0, 0x42c9, 0x2009, 0x002a, 0x0078,
-	0x42f4, 0xa08e, 0x0f00, 0x00c0, 0x42d1, 0x2009, 0x0020, 0x0078,
-	0x42f4, 0xa08e, 0x5300, 0x00c0, 0x42d7, 0x0078, 0x42f2, 0xa08e,
-	0x6104, 0x00c0, 0x42f2, 0x2011, 0x7b8d, 0x8208, 0x2204, 0xa082,
+	0x00c0, 0x4205, 0x0078, 0x4379, 0x007c, 0xa196, 0x2000, 0x00c0,
+	0x4216, 0x6900, 0xa18e, 0x0001, 0x00c0, 0x4212, 0x1078, 0x2ea3,
+	0x0078, 0x4204, 0x1078, 0x421e, 0x0078, 0x4204, 0xa196, 0x8000,
+	0x00c0, 0x4204, 0x1078, 0x43ff, 0x0078, 0x4204, 0x0c7e, 0x7110,
+	0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0040, 0x422b, 0xa196,
+	0x0023, 0x00c0, 0x4320, 0xa08e, 0x0023, 0x00c0, 0x425c, 0x1078,
+	0x4476, 0x0040, 0x4320, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200,
+	0x00c0, 0x4244, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x0015,
+	0x1078, 0x5c21, 0x0078, 0x4320, 0xa08e, 0x0210, 0x00c0, 0x424e,
+	0x2009, 0x0015, 0x1078, 0x5c21, 0x0078, 0x4320, 0xa08e, 0x0100,
+	0x00c0, 0x4320, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x0016,
+	0x1078, 0x5c21, 0x0078, 0x4320, 0xa08e, 0x0022, 0x00c0, 0x4320,
+	0x7030, 0xa08e, 0x0300, 0x00c0, 0x426d, 0x7034, 0xa005, 0x00c0,
+	0x4320, 0x2009, 0x0017, 0x0078, 0x42ec, 0xa08e, 0x0500, 0x00c0,
+	0x4279, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x0018, 0x0078,
+	0x42ec, 0xa08e, 0x2010, 0x00c0, 0x4281, 0x2009, 0x0019, 0x0078,
+	0x42ec, 0xa08e, 0x2110, 0x00c0, 0x4289, 0x2009, 0x001a, 0x0078,
+	0x42ec, 0xa08e, 0x5200, 0x00c0, 0x4295, 0x7034, 0xa005, 0x00c0,
+	0x4320, 0x2009, 0x001b, 0x0078, 0x42ec, 0xa08e, 0x5000, 0x00c0,
+	0x42a1, 0x7034, 0xa005, 0x00c0, 0x4320, 0x2009, 0x001c, 0x0078,
+	0x42ec, 0xa08e, 0x1200, 0x00c0, 0x42ad, 0x7034, 0xa005, 0x00c0,
+	0x4320, 0x2009, 0x0024, 0x0078, 0x42ec, 0xa08c, 0xff00, 0xa18e,
+	0x2400, 0x00c0, 0x42b7, 0x2009, 0x002d, 0x0078, 0x42ec, 0xa08c,
+	0xff00, 0xa18e, 0x5300, 0x00c0, 0x42c1, 0x2009, 0x002a, 0x0078,
+	0x42ec, 0xa08e, 0x0f00, 0x00c0, 0x42c9, 0x2009, 0x0020, 0x0078,
+	0x42ec, 0xa08e, 0x5300, 0x00c0, 0x42cf, 0x0078, 0x42ea, 0xa08e,
+	0x6104, 0x00c0, 0x42ea, 0x2011, 0x7b8d, 0x8208, 0x2204, 0xa082,
 	0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108,
-	0x2124, 0x1078, 0x2d4a, 0x8108, 0x00f0, 0x42e4, 0x2009, 0x0023,
-	0x0078, 0x42f4, 0x2009, 0x001d, 0x017e, 0x2011, 0x7b83, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x432a, 0x1078, 0x37ee,
-	0x00c0, 0x432a, 0x6612, 0x6516, 0x86ff, 0x0040, 0x431a, 0x017f,
-	0x017e, 0xa186, 0x0017, 0x00c0, 0x431a, 0x6864, 0xa606, 0x00c0,
-	0x431a, 0x6868, 0xa506, 0xa084, 0xff00, 0x00c0, 0x431a, 0x6000,
-	0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x5b9c, 0x0040, 0x432d, 0x017f,
-	0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5c29,
-	0x0c7f, 0x007c, 0x017f, 0x0078, 0x4328, 0x0c7f, 0x0078, 0x432a,
-	0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x4350,
-	0xa596, 0xfffd, 0x00c0, 0x4340, 0x2009, 0x007f, 0x0078, 0x437d,
-	0xa596, 0xfffe, 0x00c0, 0x4348, 0x2009, 0x007e, 0x0078, 0x437d,
-	0xa596, 0xfffc, 0x00c0, 0x4350, 0x2009, 0x0080, 0x0078, 0x437d,
+	0x2124, 0x1078, 0x2d3b, 0x8108, 0x00f0, 0x42dc, 0x2009, 0x0023,
+	0x0078, 0x42ec, 0x2009, 0x001d, 0x017e, 0x2011, 0x7b83, 0x2204,
+	0x8211, 0x220c, 0x1078, 0x207f, 0x00c0, 0x4322, 0x1078, 0x37e6,
+	0x00c0, 0x4322, 0x6612, 0x6516, 0x86ff, 0x0040, 0x4312, 0x017f,
+	0x017e, 0xa186, 0x0017, 0x00c0, 0x4312, 0x6864, 0xa606, 0x00c0,
+	0x4312, 0x6868, 0xa506, 0xa084, 0xff00, 0x00c0, 0x4312, 0x6000,
+	0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x5b94, 0x0040, 0x4325, 0x017f,
+	0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x5c21,
+	0x0c7f, 0x007c, 0x017f, 0x0078, 0x4320, 0x0c7f, 0x0078, 0x4322,
+	0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff, 0x00c0, 0x4348,
+	0xa596, 0xfffd, 0x00c0, 0x4338, 0x2009, 0x007f, 0x0078, 0x4375,
+	0xa596, 0xfffe, 0x00c0, 0x4340, 0x2009, 0x007e, 0x0078, 0x4375,
+	0xa596, 0xfffc, 0x00c0, 0x4348, 0x2009, 0x0080, 0x0078, 0x4375,
 	0x2011, 0x0000, 0x2021, 0x007e, 0x20a9, 0x0082, 0x2071, 0x779e,
-	0x2e1c, 0x83ff, 0x00c0, 0x4362, 0x82ff, 0x00c0, 0x4371, 0x2410,
-	0x0078, 0x4371, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f,
-	0x00c0, 0x4371, 0x6b14, 0xa31e, 0x00c0, 0x4371, 0x2408, 0x0078,
-	0x437d, 0x8420, 0x8e70, 0x00f0, 0x4358, 0x82ff, 0x00c0, 0x437c,
-	0xa085, 0x0001, 0x0078, 0x437e, 0x2208, 0xa006, 0x0d7f, 0x0e7f,
-	0x007c, 0xa084, 0x0007, 0x0079, 0x4386, 0x007c, 0x438e, 0x438e,
-	0x438e, 0x438e, 0x438e, 0x438f, 0x43a8, 0x43f0, 0x007c, 0x7110,
-	0xd1bc, 0x0040, 0x43a7, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0,
-	0x43a7, 0xac8a, 0x7d00, 0x0048, 0x43a7, 0x6854, 0xac02, 0x00c8,
-	0x43a7, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5c29, 0x007c,
-	0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x43ee, 0x2011, 0x7b83, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x43ee, 0x1078, 0x3825,
-	0x00c0, 0x43ee, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
-	0x00c0, 0x43d3, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x43ee,
+	0x2e1c, 0x83ff, 0x00c0, 0x435a, 0x82ff, 0x00c0, 0x4369, 0x2410,
+	0x0078, 0x4369, 0x2368, 0x6b10, 0x007e, 0x2100, 0xa31e, 0x007f,
+	0x00c0, 0x4369, 0x6b14, 0xa31e, 0x00c0, 0x4369, 0x2408, 0x0078,
+	0x4375, 0x8420, 0x8e70, 0x00f0, 0x4350, 0x82ff, 0x00c0, 0x4374,
+	0xa085, 0x0001, 0x0078, 0x4376, 0x2208, 0xa006, 0x0d7f, 0x0e7f,
+	0x007c, 0xa084, 0x0007, 0x0079, 0x437e, 0x007c, 0x4386, 0x4386,
+	0x4386, 0x4386, 0x4386, 0x4387, 0x43a0, 0x43e8, 0x007c, 0x7110,
+	0xd1bc, 0x0040, 0x439f, 0x7120, 0x2160, 0xac8c, 0x0007, 0x00c0,
+	0x439f, 0xac8a, 0x7d00, 0x0048, 0x439f, 0x6854, 0xac02, 0x00c8,
+	0x439f, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x5c21, 0x007c,
+	0x0c7e, 0x7110, 0xd1bc, 0x00c0, 0x43e6, 0x2011, 0x7b83, 0x2204,
+	0x8211, 0x220c, 0x1078, 0x207f, 0x00c0, 0x43e6, 0x1078, 0x381d,
+	0x00c0, 0x43e6, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006,
+	0x00c0, 0x43cb, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x43e6,
 	0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x2009, 0x0044, 0x1078,
-	0x5c29, 0x0078, 0x43ee, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040,
-	0x43ee, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
-	0x00c0, 0x43e6, 0x6007, 0x0005, 0x0078, 0x43e8, 0x6007, 0x0001,
-	0x6003, 0x0001, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0c7f, 0x007c,
-	0x7110, 0xd1bc, 0x0040, 0x4406, 0x7020, 0x2060, 0xac84, 0x0007,
-	0x00c0, 0x4406, 0xac82, 0x7d00, 0x0048, 0x4406, 0x6854, 0xac02,
-	0x00c8, 0x4406, 0x2009, 0x0045, 0x1078, 0x5c29, 0x007c, 0x7110,
-	0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x4417, 0xa084,
-	0x000f, 0xa08a, 0x0006, 0x10c8, 0x12d5, 0x1079, 0x4418, 0x007c,
-	0x441e, 0x441f, 0x441e, 0x441e, 0x4460, 0x446f, 0x007c, 0x7110,
-	0xd1bc, 0x00c0, 0x445f, 0x700c, 0x7108, 0x1078, 0x2085, 0x00c0,
-	0x445f, 0x1078, 0x37ee, 0x00c0, 0x445f, 0x6612, 0x6516, 0x6204,
-	0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4448, 0x0c7e,
-	0x1078, 0x5b9c, 0x017f, 0x0040, 0x445f, 0x611a, 0x601f, 0x0005,
-	0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x5c29, 0x0078, 0x445f,
-	0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x445f, 0x611a, 0x601f,
-	0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x445b, 0x2009,
-	0x0005, 0x0078, 0x445d, 0x2009, 0x0001, 0x1078, 0x5c29, 0x007c,
-	0x7110, 0xd1bc, 0x0040, 0x446e, 0x1078, 0x447e, 0x0040, 0x446e,
-	0x7124, 0x610a, 0x2009, 0x0089, 0x1078, 0x5c29, 0x007c, 0x7110,
-	0xd1bc, 0x0040, 0x447d, 0x1078, 0x447e, 0x0040, 0x447d, 0x7124,
-	0x610a, 0x2009, 0x008a, 0x1078, 0x5c29, 0x007c, 0x7020, 0x2060,
-	0xac84, 0x0007, 0x00c0, 0x4491, 0xac82, 0x7d00, 0x0048, 0x4491,
-	0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x4491, 0xa085, 0x0001,
-	0x007c, 0xa006, 0x0078, 0x4490, 0x2071, 0x7849, 0x7003, 0x0003,
+	0x5c21, 0x0078, 0x43e6, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040,
+	0x43e6, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
+	0x00c0, 0x43de, 0x6007, 0x0005, 0x0078, 0x43e0, 0x6007, 0x0001,
+	0x6003, 0x0001, 0x1078, 0x486a, 0x1078, 0x4c72, 0x0c7f, 0x007c,
+	0x7110, 0xd1bc, 0x0040, 0x43fe, 0x7020, 0x2060, 0xac84, 0x0007,
+	0x00c0, 0x43fe, 0xac82, 0x7d00, 0x0048, 0x43fe, 0x6854, 0xac02,
+	0x00c8, 0x43fe, 0x2009, 0x0045, 0x1078, 0x5c21, 0x007c, 0x7110,
+	0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x440f, 0xa084,
+	0x000f, 0xa08a, 0x0006, 0x10c8, 0x12cd, 0x1079, 0x4410, 0x007c,
+	0x4416, 0x4417, 0x4416, 0x4416, 0x4458, 0x4467, 0x007c, 0x7110,
+	0xd1bc, 0x00c0, 0x4457, 0x700c, 0x7108, 0x1078, 0x207f, 0x00c0,
+	0x4457, 0x1078, 0x37e6, 0x00c0, 0x4457, 0x6612, 0x6516, 0x6204,
+	0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x00c0, 0x4440, 0x0c7e,
+	0x1078, 0x5b94, 0x017f, 0x0040, 0x4457, 0x611a, 0x601f, 0x0005,
+	0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x5c21, 0x0078, 0x4457,
+	0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x4457, 0x611a, 0x601f,
+	0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x4453, 0x2009,
+	0x0005, 0x0078, 0x4455, 0x2009, 0x0001, 0x1078, 0x5c21, 0x007c,
+	0x7110, 0xd1bc, 0x0040, 0x4466, 0x1078, 0x4476, 0x0040, 0x4466,
+	0x7124, 0x610a, 0x2009, 0x0089, 0x1078, 0x5c21, 0x007c, 0x7110,
+	0xd1bc, 0x0040, 0x4475, 0x1078, 0x4476, 0x0040, 0x4475, 0x7124,
+	0x610a, 0x2009, 0x008a, 0x1078, 0x5c21, 0x007c, 0x7020, 0x2060,
+	0xac84, 0x0007, 0x00c0, 0x4489, 0xac82, 0x7d00, 0x0048, 0x4489,
+	0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x4489, 0xa085, 0x0001,
+	0x007c, 0xa006, 0x0078, 0x4488, 0x2071, 0x7849, 0x7003, 0x0003,
 	0x700f, 0x0361, 0xa006, 0x701a, 0x7012, 0x7017, 0x7d00, 0x7007,
-	0x0000, 0x7026, 0x702b, 0x558f, 0x7032, 0x7037, 0x55d0, 0x703b,
-	0x0002, 0x703f, 0x0000, 0x007c, 0x2071, 0x7849, 0x00e0, 0x455b,
-	0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x4524, 0x700f,
+	0x0000, 0x7026, 0x702b, 0x5587, 0x7032, 0x7037, 0x55c8, 0x703b,
+	0x0002, 0x703f, 0x0000, 0x007c, 0x2071, 0x7849, 0x00e0, 0x4553,
+	0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0, 0x451c, 0x700f,
 	0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000, 0x7138, 0x8109,
-	0x713a, 0x00c0, 0x4522, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104,
-	0xa082, 0x0003, 0x00c8, 0x4522, 0x703c, 0xa086, 0x0001, 0x00c0,
-	0x44ff, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040,
-	0x44dd, 0x6803, 0x1000, 0x0078, 0x44e4, 0x6804, 0xa084, 0x1000,
-	0x0040, 0x44e4, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000,
-	0x2069, 0x7836, 0x6804, 0xa082, 0x0006, 0x00c0, 0x44f1, 0x6807,
-	0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x44f8, 0x6833, 0x0000,
-	0x1078, 0x4c7a, 0x1078, 0x4d3a, 0x0d7f, 0x0078, 0x4522, 0x0d7e,
-	0x2069, 0x7600, 0x6944, 0x6860, 0xa102, 0x00c8, 0x4521, 0x2069,
-	0x7836, 0x6804, 0xa086, 0x0000, 0x00c0, 0x4521, 0x6830, 0xa086,
-	0x0000, 0x00c0, 0x4521, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833,
+	0x713a, 0x00c0, 0x451a, 0x703b, 0x0002, 0x2009, 0x0100, 0x2104,
+	0xa082, 0x0003, 0x00c8, 0x451a, 0x703c, 0xa086, 0x0001, 0x00c0,
+	0x44f7, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040,
+	0x44d5, 0x6803, 0x1000, 0x0078, 0x44dc, 0x6804, 0xa084, 0x1000,
+	0x0040, 0x44dc, 0x6803, 0x0100, 0x6803, 0x0000, 0x703f, 0x0000,
+	0x2069, 0x7836, 0x6804, 0xa082, 0x0006, 0x00c0, 0x44e9, 0x6807,
+	0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x44f0, 0x6833, 0x0000,
+	0x1078, 0x4c72, 0x1078, 0x4d32, 0x0d7f, 0x0078, 0x451a, 0x0d7e,
+	0x2069, 0x7600, 0x6944, 0x6860, 0xa102, 0x00c8, 0x4519, 0x2069,
+	0x7836, 0x6804, 0xa086, 0x0000, 0x00c0, 0x4519, 0x6830, 0xa086,
+	0x0000, 0x00c0, 0x4519, 0x703f, 0x0001, 0x6807, 0x0006, 0x6833,
 	0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069, 0x0140, 0x6803,
-	0x0600, 0x0d7f, 0x0078, 0x4527, 0x127e, 0x2091, 0x8000, 0x7024,
-	0xa00d, 0x0040, 0x4538, 0x7020, 0x8001, 0x7022, 0x00c0, 0x4538,
-	0x7023, 0x0009, 0x8109, 0x7126, 0x00c0, 0x4538, 0x7028, 0x107a,
-	0x7030, 0xa00d, 0x0040, 0x4549, 0x702c, 0x8001, 0x702e, 0x00c0,
-	0x4549, 0x702f, 0x0009, 0x8109, 0x7132, 0x00c0, 0x4549, 0x7034,
-	0x107a, 0x7018, 0xa00d, 0x0040, 0x455a, 0x7008, 0x8001, 0x700a,
-	0x00c0, 0x455a, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x455a,
-	0x701c, 0x107a, 0x127f, 0x7004, 0x0079, 0x455e, 0x4585, 0x4586,
-	0x45a2, 0x0e7e, 0x2071, 0x7849, 0x7018, 0xa005, 0x00c0, 0x456c,
+	0x0600, 0x0d7f, 0x0078, 0x451f, 0x127e, 0x2091, 0x8000, 0x7024,
+	0xa00d, 0x0040, 0x4530, 0x7020, 0x8001, 0x7022, 0x00c0, 0x4530,
+	0x7023, 0x0009, 0x8109, 0x7126, 0x00c0, 0x4530, 0x7028, 0x107a,
+	0x7030, 0xa00d, 0x0040, 0x4541, 0x702c, 0x8001, 0x702e, 0x00c0,
+	0x4541, 0x702f, 0x0009, 0x8109, 0x7132, 0x00c0, 0x4541, 0x7034,
+	0x107a, 0x7018, 0xa00d, 0x0040, 0x4552, 0x7008, 0x8001, 0x700a,
+	0x00c0, 0x4552, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x4552,
+	0x701c, 0x107a, 0x127f, 0x7004, 0x0079, 0x4556, 0x457d, 0x457e,
+	0x459a, 0x0e7e, 0x2071, 0x7849, 0x7018, 0xa005, 0x00c0, 0x4564,
 	0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e,
-	0x2071, 0x7849, 0x701c, 0xa206, 0x00c0, 0x4578, 0x701a, 0x701e,
+	0x2071, 0x7849, 0x701c, 0xa206, 0x00c0, 0x4570, 0x701a, 0x701e,
 	0x007f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7849, 0x6088, 0xa102,
-	0x0048, 0x4583, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078,
-	0x3825, 0x00c0, 0x4598, 0x6088, 0x8001, 0x0048, 0x4598, 0x608a,
-	0x00c0, 0x4598, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f,
-	0x8108, 0xa182, 0x00ff, 0x0048, 0x45a0, 0xa00e, 0x7007, 0x0002,
+	0x0048, 0x457b, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078,
+	0x381d, 0x00c0, 0x4590, 0x6088, 0x8001, 0x0048, 0x4590, 0x608a,
+	0x00c0, 0x4590, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f,
+	0x8108, 0xa182, 0x00ff, 0x0048, 0x4598, 0xa00e, 0x7007, 0x0002,
 	0x7112, 0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x6014,
-	0xa005, 0x0040, 0x45d1, 0x8001, 0x6016, 0x00c0, 0x45d1, 0x611c,
-	0xa186, 0x0003, 0x0040, 0x45b8, 0xa186, 0x0006, 0x00c0, 0x45cf,
-	0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x45cf, 0xa082,
-	0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x45c8, 0x2001, 0x1999,
-	0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x45d1, 0x1078,
-	0x67c9, 0x127f, 0xac88, 0x0008, 0x7116, 0x2001, 0x7616, 0x2004,
-	0xa102, 0x0048, 0x45df, 0x7017, 0x7d00, 0x7007, 0x0000, 0x007c,
+	0xa005, 0x0040, 0x45c9, 0x8001, 0x6016, 0x00c0, 0x45c9, 0x611c,
+	0xa186, 0x0003, 0x0040, 0x45b0, 0xa186, 0x0006, 0x00c0, 0x45c7,
+	0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x45c7, 0xa082,
+	0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x45c0, 0x2001, 0x1999,
+	0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x45c9, 0x1078,
+	0x67c3, 0x127f, 0xac88, 0x0008, 0x7116, 0x2001, 0x7616, 0x2004,
+	0xa102, 0x0048, 0x45d7, 0x7017, 0x7d00, 0x7007, 0x0000, 0x007c,
 	0x0e7e, 0x2071, 0x7849, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b,
 	0x0002, 0x0e7f, 0x007c, 0x2001, 0x7852, 0x2003, 0x0000, 0x007c,
 	0x0e7e, 0x2071, 0x7849, 0x7033, 0x07d0, 0x702f, 0x0009, 0x0e7f,
@@ -1757,1536 +1738,5694 @@
 	0x7849, 0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0c7e,
 	0x2061, 0x78da, 0x0c7f, 0x007c, 0xa184, 0x000f, 0x8003, 0x8003,
 	0x8003, 0xa080, 0x78da, 0x2060, 0x007c, 0x6854, 0xa08a, 0x199a,
-	0x0048, 0x461c, 0x2001, 0x1999, 0xa005, 0x00c0, 0x462c, 0x6944,
-	0x0c7e, 0x1078, 0x460c, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x4631,
-	0x2001, 0x001e, 0x0078, 0x4631, 0xa08e, 0xffff, 0x00c0, 0x4631,
+	0x0048, 0x4614, 0x2001, 0x1999, 0xa005, 0x00c0, 0x4624, 0x6944,
+	0x0c7e, 0x1078, 0x4604, 0x6014, 0x0c7f, 0xa005, 0x00c0, 0x4629,
+	0x2001, 0x001e, 0x0078, 0x4629, 0xa08e, 0xffff, 0x00c0, 0x4629,
 	0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c,
-	0x00c0, 0xa18e, 0x00c0, 0x0040, 0x466c, 0xd0b4, 0x00c0, 0x4648,
-	0xd0bc, 0x00c0, 0x465a, 0x2009, 0x0006, 0x1078, 0x468f, 0x007c,
-	0xd0fc, 0x0040, 0x4655, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040,
-	0x4688, 0xa08e, 0x0000, 0x00c0, 0x4688, 0x2009, 0x0043, 0x1078,
-	0x5c29, 0x007c, 0xd0fc, 0x0040, 0x4667, 0xa084, 0x0003, 0xa08e,
-	0x0003, 0x0040, 0x4688, 0xa08e, 0x0000, 0x00c0, 0x4688, 0x2009,
-	0x0042, 0x1078, 0x5c29, 0x007c, 0xd0fc, 0x0040, 0x467e, 0xa084,
-	0x0003, 0xa08e, 0x0003, 0x0040, 0x4688, 0xa08e, 0x0002, 0x0040,
-	0x4682, 0x2009, 0x0041, 0x1078, 0x5c29, 0x007c, 0x1078, 0x468d,
-	0x0078, 0x467d, 0x2009, 0x0043, 0x1078, 0x5c29, 0x0078, 0x467d,
-	0x2009, 0x0004, 0x1078, 0x468f, 0x007c, 0x2009, 0x0001, 0x6010,
-	0xa0ec, 0xf000, 0x0040, 0x46b3, 0x2068, 0x6952, 0x6800, 0x6012,
-	0xa186, 0x0001, 0x00c0, 0x46ad, 0x694c, 0xa18c, 0x8100, 0xa18e,
-	0x8100, 0x00c0, 0x46ad, 0x0c7e, 0x6944, 0x1078, 0x460c, 0x6204,
-	0x8210, 0x0048, 0x46ac, 0x6206, 0x0c7f, 0x1078, 0x3a7a, 0x6010,
-	0xa06d, 0x10c0, 0x4615, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010,
-	0x2061, 0x78da, 0x6000, 0x81ff, 0x0040, 0x46c1, 0xa205, 0x0078,
-	0x46c2, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x46ba, 0x0c7f,
-	0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x46d2, 0x8001, 0x680a,
+	0x00c0, 0xa18e, 0x00c0, 0x0040, 0x4664, 0xd0b4, 0x00c0, 0x4640,
+	0xd0bc, 0x00c0, 0x4652, 0x2009, 0x0006, 0x1078, 0x4687, 0x007c,
+	0xd0fc, 0x0040, 0x464d, 0xa084, 0x0003, 0xa08e, 0x0003, 0x0040,
+	0x4680, 0xa08e, 0x0000, 0x00c0, 0x4680, 0x2009, 0x0043, 0x1078,
+	0x5c21, 0x007c, 0xd0fc, 0x0040, 0x465f, 0xa084, 0x0003, 0xa08e,
+	0x0003, 0x0040, 0x4680, 0xa08e, 0x0000, 0x00c0, 0x4680, 0x2009,
+	0x0042, 0x1078, 0x5c21, 0x007c, 0xd0fc, 0x0040, 0x4676, 0xa084,
+	0x0003, 0xa08e, 0x0003, 0x0040, 0x4680, 0xa08e, 0x0002, 0x0040,
+	0x467a, 0x2009, 0x0041, 0x1078, 0x5c21, 0x007c, 0x1078, 0x4685,
+	0x0078, 0x4675, 0x2009, 0x0043, 0x1078, 0x5c21, 0x0078, 0x4675,
+	0x2009, 0x0004, 0x1078, 0x4687, 0x007c, 0x2009, 0x0001, 0x6010,
+	0xa0ec, 0xf000, 0x0040, 0x46ab, 0x2068, 0x6952, 0x6800, 0x6012,
+	0xa186, 0x0001, 0x00c0, 0x46a5, 0x694c, 0xa18c, 0x8100, 0xa18e,
+	0x8100, 0x00c0, 0x46a5, 0x0c7e, 0x6944, 0x1078, 0x4604, 0x6204,
+	0x8210, 0x0048, 0x46a4, 0x6206, 0x0c7f, 0x1078, 0x3a72, 0x6010,
+	0xa06d, 0x10c0, 0x460d, 0x007c, 0x157e, 0x0c7e, 0x20a9, 0x0010,
+	0x2061, 0x78da, 0x6000, 0x81ff, 0x0040, 0x46b9, 0xa205, 0x0078,
+	0x46ba, 0xa204, 0x6002, 0xace0, 0x0008, 0x00f0, 0x46b2, 0x0c7f,
+	0x157f, 0x007c, 0x6808, 0xa005, 0x0040, 0x46ca, 0x8001, 0x680a,
 	0xa085, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x2079, 0x7836,
 	0x127f, 0x0d7e, 0x2069, 0x7836, 0x6803, 0x0005, 0x2069, 0x0004,
 	0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027,
-	0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x46ee, 0x46f8, 0x471d,
-	0x4778, 0x46fe, 0x471d, 0x46f6, 0x46f6, 0x46f6, 0x1078, 0x12d5,
-	0x1078, 0x45eb, 0x1078, 0x4c7a, 0x0c7f, 0x007c, 0x62c0, 0x82ff,
-	0x00c0, 0x4704, 0x0c7f, 0x007c, 0x2011, 0x3542, 0x1078, 0x456e,
-	0x7828, 0xa092, 0x0002, 0x00c8, 0x4713, 0x8000, 0x782a, 0x1078,
-	0x3572, 0x0078, 0x4702, 0x1078, 0x3542, 0x7807, 0x0003, 0x7827,
-	0x0000, 0x782b, 0x0000, 0x0078, 0x4702, 0x1078, 0x45eb, 0x3c00,
+	0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x46e6, 0x46f0, 0x4715,
+	0x4770, 0x46f6, 0x4715, 0x46ee, 0x46ee, 0x46ee, 0x1078, 0x12cd,
+	0x1078, 0x45e3, 0x1078, 0x4c72, 0x0c7f, 0x007c, 0x62c0, 0x82ff,
+	0x00c0, 0x46fc, 0x0c7f, 0x007c, 0x2011, 0x353a, 0x1078, 0x4566,
+	0x7828, 0xa092, 0x0002, 0x00c8, 0x470b, 0x8000, 0x782a, 0x1078,
+	0x356a, 0x0078, 0x46fa, 0x1078, 0x353a, 0x7807, 0x0003, 0x7827,
+	0x0000, 0x782b, 0x0000, 0x0078, 0x46fa, 0x1078, 0x45e3, 0x3c00,
 	0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0,
-	0x82ff, 0x0040, 0x473b, 0x62c0, 0x82ff, 0x00c0, 0x473b, 0x782b,
-	0x0000, 0x7824, 0xa065, 0x1040, 0x12d5, 0x2009, 0x0013, 0x1078,
-	0x5c29, 0x0c7f, 0x007c, 0x3900, 0xa082, 0x797a, 0x00c8, 0x4742,
-	0x1078, 0x5b2c, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x12d5, 0x7804,
-	0xa086, 0x0004, 0x0040, 0x47bd, 0x7828, 0xa092, 0x2710, 0x00c8,
-	0x4758, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x5574, 0x0078, 0x4739,
-	0x6104, 0xa186, 0x0003, 0x00c0, 0x476f, 0x0e7e, 0x2071, 0x7600,
-	0x70c8, 0x0e7f, 0xd08c, 0x0040, 0x476f, 0x0c7e, 0x0e7e, 0x2061,
-	0x0100, 0x2071, 0x7600, 0x1078, 0x357b, 0x0e7f, 0x0c7f, 0x1078,
-	0x75c7, 0x2009, 0x0014, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x4739,
-	0x2001, 0x7852, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x478c,
-	0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x12d5, 0x2009, 0x0013,
-	0x1078, 0x5c77, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082,
-	0x797a, 0x00c8, 0x4795, 0x1078, 0x5b2c, 0x7824, 0xa005, 0x1040,
-	0x12d5, 0x781c, 0xa06d, 0x1040, 0x12d5, 0x6800, 0xc0dc, 0x6802,
-	0x7924, 0x2160, 0x1078, 0x5c02, 0x693c, 0x81ff, 0x1040, 0x12d5,
-	0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x47b1, 0x7a1e, 0x0078,
-	0x47b3, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f,
-	0x0c7f, 0x1078, 0x4c7a, 0x0078, 0x478a, 0x6104, 0xa186, 0x0002,
-	0x0040, 0x47c8, 0xa186, 0x0004, 0x0040, 0x47c8, 0x0078, 0x474c,
-	0x7808, 0xac06, 0x0040, 0x474c, 0x1078, 0x4b81, 0x1078, 0x4872,
-	0x0c7f, 0x1078, 0x4c7a, 0x0078, 0x4739, 0x0c7e, 0x6027, 0x0002,
-	0x2011, 0x7855, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x47ef,
-	0x62c4, 0x82ff, 0x00c0, 0x47ef, 0x793c, 0xa1e5, 0x0000, 0x0040,
-	0x47ed, 0x2009, 0x0049, 0x1078, 0x5c29, 0x0c7f, 0x007c, 0x3908,
-	0xa192, 0x797a, 0x00c8, 0x47f6, 0x1078, 0x5b2c, 0x6017, 0x0010,
-	0x793c, 0x81ff, 0x0040, 0x47ed, 0x7944, 0xa192, 0x7530, 0x00c8,
-	0x4815, 0x8108, 0x7946, 0x1078, 0x45f0, 0x793c, 0xa188, 0x0007,
-	0x210c, 0xa18e, 0x0006, 0x00c0, 0x4811, 0x6017, 0x0012, 0x0078,
-	0x47ed, 0x6017, 0x0016, 0x0078, 0x47ed, 0x037e, 0x2019, 0x0001,
-	0x1078, 0x5768, 0x037f, 0x1078, 0x75c7, 0x793c, 0x2160, 0x2009,
-	0x004a, 0x1078, 0x5c29, 0x0078, 0x47ed, 0x007e, 0x017e, 0x0c7e,
+	0x82ff, 0x0040, 0x4733, 0x62c0, 0x82ff, 0x00c0, 0x4733, 0x782b,
+	0x0000, 0x7824, 0xa065, 0x1040, 0x12cd, 0x2009, 0x0013, 0x1078,
+	0x5c21, 0x0c7f, 0x007c, 0x3900, 0xa082, 0x797a, 0x00c8, 0x473a,
+	0x1078, 0x5b24, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x12cd, 0x7804,
+	0xa086, 0x0004, 0x0040, 0x47b5, 0x7828, 0xa092, 0x2710, 0x00c8,
+	0x4750, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x556c, 0x0078, 0x4731,
+	0x6104, 0xa186, 0x0003, 0x00c0, 0x4767, 0x0e7e, 0x2071, 0x7600,
+	0x70c8, 0x0e7f, 0xd08c, 0x0040, 0x4767, 0x0c7e, 0x0e7e, 0x2061,
+	0x0100, 0x2071, 0x7600, 0x1078, 0x3573, 0x0e7f, 0x0c7f, 0x1078,
+	0x75bc, 0x2009, 0x0014, 0x1078, 0x5c21, 0x0c7f, 0x0078, 0x4731,
+	0x2001, 0x7852, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x4784,
+	0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x12cd, 0x2009, 0x0013,
+	0x1078, 0x5c6f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082,
+	0x797a, 0x00c8, 0x478d, 0x1078, 0x5b24, 0x7824, 0xa005, 0x1040,
+	0x12cd, 0x781c, 0xa06d, 0x1040, 0x12cd, 0x6800, 0xc0dc, 0x6802,
+	0x7924, 0x2160, 0x1078, 0x5bfa, 0x693c, 0x81ff, 0x1040, 0x12cd,
+	0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x47a9, 0x7a1e, 0x0078,
+	0x47ab, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f,
+	0x0c7f, 0x1078, 0x4c72, 0x0078, 0x4782, 0x6104, 0xa186, 0x0002,
+	0x0040, 0x47c0, 0xa186, 0x0004, 0x0040, 0x47c0, 0x0078, 0x4744,
+	0x7808, 0xac06, 0x0040, 0x4744, 0x1078, 0x4b79, 0x1078, 0x486a,
+	0x0c7f, 0x1078, 0x4c72, 0x0078, 0x4731, 0x0c7e, 0x6027, 0x0002,
+	0x2011, 0x7855, 0x2013, 0x0000, 0x62c8, 0x82ff, 0x00c0, 0x47e7,
+	0x62c4, 0x82ff, 0x00c0, 0x47e7, 0x793c, 0xa1e5, 0x0000, 0x0040,
+	0x47e5, 0x2009, 0x0049, 0x1078, 0x5c21, 0x0c7f, 0x007c, 0x3908,
+	0xa192, 0x797a, 0x00c8, 0x47ee, 0x1078, 0x5b24, 0x6017, 0x0010,
+	0x793c, 0x81ff, 0x0040, 0x47e5, 0x7944, 0xa192, 0x7530, 0x00c8,
+	0x480d, 0x8108, 0x7946, 0x1078, 0x45e8, 0x793c, 0xa188, 0x0007,
+	0x210c, 0xa18e, 0x0006, 0x00c0, 0x4809, 0x6017, 0x0012, 0x0078,
+	0x47e5, 0x6017, 0x0016, 0x0078, 0x47e5, 0x037e, 0x2019, 0x0001,
+	0x1078, 0x5760, 0x037f, 0x1078, 0x75bc, 0x793c, 0x2160, 0x2009,
+	0x004a, 0x1078, 0x5c21, 0x0078, 0x47e5, 0x007e, 0x017e, 0x0c7e,
 	0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836,
-	0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040, 0x4840, 0xa080,
+	0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0040, 0x4838, 0xa080,
 	0x0003, 0x2102, 0x6112, 0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c,
-	0x6116, 0x6112, 0x0078, 0x483b, 0x0d7e, 0x2069, 0x7836, 0x6000,
-	0xd0d4, 0x0040, 0x4859, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
-	0x00c0, 0x4854, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0079,
-	0x4c82, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0040, 0x486b, 0x6056,
+	0x6116, 0x6112, 0x0078, 0x4833, 0x0d7e, 0x2069, 0x7836, 0x6000,
+	0xd0d4, 0x0040, 0x4851, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
+	0x00c0, 0x484c, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0079,
+	0x4c7a, 0xc0d5, 0x6002, 0x6818, 0xa005, 0x0040, 0x4863, 0x6056,
 	0x605b, 0x0000, 0x007e, 0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069,
-	0x7836, 0x0078, 0x484b, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e,
-	0x0078, 0x484b, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000,
+	0x7836, 0x0078, 0x4843, 0x6056, 0x605a, 0x2c00, 0x681a, 0x681e,
+	0x0078, 0x4843, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000,
 	0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6020, 0x8000, 0x6022,
-	0x6008, 0xa005, 0x0040, 0x488d, 0xa080, 0x0003, 0x2102, 0x610a,
+	0x6008, 0xa005, 0x0040, 0x4885, 0xa080, 0x0003, 0x2102, 0x610a,
 	0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x610e, 0x610a, 0x0078,
-	0x4888, 0x0c7e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6034,
-	0xa005, 0x0040, 0x48a1, 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f,
-	0x007c, 0x613a, 0x6136, 0x0078, 0x489f, 0x0f7e, 0x0e7e, 0x0d7e,
+	0x4880, 0x0c7e, 0x600f, 0x0000, 0x2c08, 0x2061, 0x7836, 0x6034,
+	0xa005, 0x0040, 0x4899, 0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f,
+	0x007c, 0x613a, 0x6136, 0x0078, 0x4897, 0x0f7e, 0x0e7e, 0x0d7e,
 	0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2071, 0x7836, 0x7638,
-	0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x4907, 0x6018,
-	0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x4902, 0x703c, 0xac06,
-	0x00c0, 0x48c7, 0x6003, 0x000a, 0x630a, 0x0078, 0x4902, 0x7038,
-	0xac36, 0x00c0, 0x48cd, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0,
-	0x48db, 0x2c00, 0xaf36, 0x0040, 0x48d9, 0x2f00, 0x7036, 0x0078,
-	0x48db, 0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
-	0x48e4, 0x7e0e, 0x0078, 0x48e5, 0x2678, 0x600f, 0x0000, 0x1078,
-	0x693e, 0x0040, 0x48fd, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
-	0x00c0, 0x4910, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
-	0x6b3f, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x0c7f,
-	0x0078, 0x48b4, 0x2c78, 0x600c, 0x2060, 0x0078, 0x48b4, 0x127f,
+	0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x48ff, 0x6018,
+	0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x48fa, 0x703c, 0xac06,
+	0x00c0, 0x48bf, 0x6003, 0x000a, 0x630a, 0x0078, 0x48fa, 0x7038,
+	0xac36, 0x00c0, 0x48c5, 0x660c, 0x763a, 0x7034, 0xac36, 0x00c0,
+	0x48d3, 0x2c00, 0xaf36, 0x0040, 0x48d1, 0x2f00, 0x7036, 0x0078,
+	0x48d3, 0x7037, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
+	0x48dc, 0x7e0e, 0x0078, 0x48dd, 0x2678, 0x600f, 0x0000, 0x1078,
+	0x6938, 0x0040, 0x48f5, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
+	0x00c0, 0x4908, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x6b34, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x1078, 0x6a96, 0x0c7f,
+	0x0078, 0x48ac, 0x2c78, 0x600c, 0x2060, 0x0078, 0x48ac, 0x127f,
 	0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c,
-	0x601c, 0xa086, 0x0006, 0x00c0, 0x48f2, 0x1078, 0x74fd, 0x0078,
-	0x48fd, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000,
+	0x601c, 0xa086, 0x0006, 0x00c0, 0x48ea, 0x1078, 0x74f2, 0x0078,
+	0x48f5, 0x007e, 0x067e, 0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000,
 	0x127e, 0x2091, 0x8000, 0x2079, 0x7836, 0x7838, 0xa065, 0x0040,
-	0x4950, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0,
-	0x4937, 0x6003, 0x000a, 0x630a, 0x2c30, 0x0078, 0x494d, 0x1078,
-	0x693e, 0x0040, 0x494b, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
-	0x00c0, 0x4959, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
-	0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x007f, 0x0078, 0x4926,
+	0x4948, 0x600c, 0x007e, 0x600f, 0x0000, 0x783c, 0xac06, 0x00c0,
+	0x492f, 0x6003, 0x000a, 0x630a, 0x2c30, 0x0078, 0x4945, 0x1078,
+	0x6938, 0x0040, 0x4943, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003,
+	0x00c0, 0x4951, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x3a72, 0x1078, 0x6a89, 0x1078, 0x6a96, 0x007f, 0x0078, 0x491e,
 	0x7e3a, 0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
-	0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x4942, 0x1078, 0x74fd,
-	0x0078, 0x494b, 0x027e, 0x1078, 0x4976, 0x1078, 0x4a0f, 0x027f,
+	0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x493a, 0x1078, 0x74f2,
+	0x0078, 0x4943, 0x027e, 0x1078, 0x496e, 0x1078, 0x4a07, 0x027f,
 	0x007c, 0x0f7e, 0x127e, 0x2079, 0x7836, 0x2091, 0x8000, 0x1078,
-	0x4aa6, 0x1078, 0x4b0e, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e,
+	0x4a9e, 0x1078, 0x4b06, 0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e,
 	0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
-	0x7836, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x49fe, 0x6018,
-	0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x49f9, 0x7024, 0xac06,
-	0x00c0, 0x49bc, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x49b7,
-	0x1078, 0x5582, 0x68c3, 0x0000, 0x1078, 0x5a32, 0x7027, 0x0000,
-	0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x49ac,
+	0x7836, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0040, 0x49f6, 0x6018,
+	0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x49f1, 0x7024, 0xac06,
+	0x00c0, 0x49b4, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x49af,
+	0x1078, 0x557a, 0x68c3, 0x0000, 0x1078, 0x5a2a, 0x7027, 0x0000,
+	0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x49a4,
 	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0040, 0x49b4, 0x6827, 0x0001, 0x037f, 0x0078, 0x49bc, 0x6003,
-	0x0009, 0x630a, 0x0078, 0x49f9, 0x7014, 0xac36, 0x00c0, 0x49c2,
-	0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x49d0, 0x2c00, 0xaf36,
-	0x0040, 0x49ce, 0x2f00, 0x7012, 0x0078, 0x49d0, 0x7013, 0x0000,
-	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x49d9, 0x7e0e, 0x0078,
-	0x49da, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x693e,
-	0x0040, 0x49f2, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4a06, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f, 0x1078, 0x3a7a,
-	0x1078, 0x6a94, 0x1078, 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078,
-	0x4984, 0x2c78, 0x600c, 0x2060, 0x0078, 0x4984, 0x127f, 0x007f,
+	0x0040, 0x49ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x49b4, 0x6003,
+	0x0009, 0x630a, 0x0078, 0x49f1, 0x7014, 0xac36, 0x00c0, 0x49ba,
+	0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x49c8, 0x2c00, 0xaf36,
+	0x0040, 0x49c6, 0x2f00, 0x7012, 0x0078, 0x49c8, 0x7013, 0x0000,
+	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x49d1, 0x7e0e, 0x0078,
+	0x49d2, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x6938,
+	0x0040, 0x49ea, 0x601c, 0xa086, 0x0003, 0x00c0, 0x49fe, 0x6837,
+	0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b34, 0x1078, 0x3a72,
+	0x1078, 0x6a89, 0x1078, 0x6a96, 0x1078, 0x58fa, 0x0c7f, 0x0078,
+	0x497c, 0x2c78, 0x600c, 0x2060, 0x0078, 0x497c, 0x127f, 0x007f,
 	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086,
-	0x0006, 0x00c0, 0x49e7, 0x1078, 0x74fd, 0x0078, 0x49f2, 0x0c7e,
+	0x0006, 0x00c0, 0x49df, 0x1078, 0x74f2, 0x0078, 0x49ea, 0x0c7e,
 	0x007e, 0x127e, 0x2091, 0x8000, 0xa280, 0x7720, 0x2004, 0xa065,
-	0x0040, 0x4aa2, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x7836,
-	0x6654, 0x7018, 0xac06, 0x00c0, 0x4a26, 0x761a, 0x701c, 0xac06,
-	0x00c0, 0x4a32, 0x86ff, 0x00c0, 0x4a31, 0x7018, 0x701e, 0x0078,
-	0x4a32, 0x761e, 0x6058, 0xa07d, 0x0040, 0x4a37, 0x7e56, 0xa6ed,
-	0x0000, 0x0040, 0x4a3d, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b,
-	0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x37a2, 0x0040,
-	0x4a9e, 0x7624, 0x86ff, 0x0040, 0x4a8e, 0xa680, 0x0004, 0x2004,
-	0xad06, 0x00c0, 0x4a8e, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x4a85, 0x1078, 0x5582, 0x68c3, 0x0000, 0x1078, 0x5a32,
+	0x0040, 0x4a9a, 0x0f7e, 0x0e7e, 0x0d7e, 0x067e, 0x2071, 0x7836,
+	0x6654, 0x7018, 0xac06, 0x00c0, 0x4a1e, 0x761a, 0x701c, 0xac06,
+	0x00c0, 0x4a2a, 0x86ff, 0x00c0, 0x4a29, 0x7018, 0x701e, 0x0078,
+	0x4a2a, 0x761e, 0x6058, 0xa07d, 0x0040, 0x4a2f, 0x7e56, 0xa6ed,
+	0x0000, 0x0040, 0x4a35, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b,
+	0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x379a, 0x0040,
+	0x4a96, 0x7624, 0x86ff, 0x0040, 0x4a86, 0xa680, 0x0004, 0x2004,
+	0xad06, 0x00c0, 0x4a86, 0x0d7e, 0x2069, 0x0100, 0x68c0, 0xa005,
+	0x0040, 0x4a7d, 0x1078, 0x557a, 0x68c3, 0x0000, 0x1078, 0x5a2a,
 	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0040, 0x4a6e, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0040, 0x4a76, 0x6827, 0x0001, 0x037f, 0x0d7f,
-	0x0c7e, 0x603c, 0xa005, 0x0040, 0x4a7f, 0x8001, 0x603e, 0x2660,
-	0x1078, 0x6aa1, 0x0c7f, 0x0078, 0x4a8e, 0x0d7f, 0x0c7e, 0x2660,
-	0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x4a45, 0x8dff, 0x0040,
-	0x4a9a, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b3f,
-	0x1078, 0x3a7a, 0x1078, 0x5902, 0x0078, 0x4a45, 0x067f, 0x0d7f,
+	0x0040, 0x4a66, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0040, 0x4a6e, 0x6827, 0x0001, 0x037f, 0x0d7f,
+	0x0c7e, 0x603c, 0xa005, 0x0040, 0x4a77, 0x8001, 0x603e, 0x2660,
+	0x1078, 0x6a96, 0x0c7f, 0x0078, 0x4a86, 0x0d7f, 0x0c7e, 0x2660,
+	0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078, 0x4a3d, 0x8dff, 0x0040,
+	0x4a92, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x6b34,
+	0x1078, 0x3a72, 0x1078, 0x58fa, 0x0078, 0x4a3d, 0x067f, 0x0d7f,
 	0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e,
-	0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x4afe,
-	0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x4ae3,
-	0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4add, 0x1078, 0x5582,
-	0x68c3, 0x0000, 0x1078, 0x5a32, 0x7827, 0x0000, 0x037e, 0x2069,
-	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x4ad2, 0x6803, 0x0100,
-	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4ada,
-	0x6827, 0x0001, 0x037f, 0x0078, 0x4ae3, 0x6003, 0x0009, 0x630a,
-	0x2c30, 0x0078, 0x4afb, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040,
-	0x4af7, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4b05, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078,
-	0x6aa1, 0x1078, 0x5902, 0x007f, 0x0078, 0x4aad, 0x7e16, 0x7e12,
+	0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x4af6,
+	0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x4adb,
+	0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x4ad5, 0x1078, 0x557a,
+	0x68c3, 0x0000, 0x1078, 0x5a2a, 0x7827, 0x0000, 0x037e, 0x2069,
+	0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x4aca, 0x6803, 0x0100,
+	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4ad2,
+	0x6827, 0x0001, 0x037f, 0x0078, 0x4adb, 0x6003, 0x0009, 0x630a,
+	0x2c30, 0x0078, 0x4af3, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040,
+	0x4aef, 0x601c, 0xa086, 0x0003, 0x00c0, 0x4afd, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x1078,
+	0x6a96, 0x1078, 0x58fa, 0x007f, 0x0078, 0x4aa5, 0x7e16, 0x7e12,
 	0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c, 0xa086, 0x0006,
-	0x00c0, 0x4aee, 0x1078, 0x74fd, 0x0078, 0x4af7, 0x007e, 0x067e,
-	0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040, 0x4b7a, 0x6054, 0x007e,
+	0x00c0, 0x4ae6, 0x1078, 0x74f2, 0x0078, 0x4aef, 0x007e, 0x067e,
+	0x0c7e, 0x0d7e, 0x7818, 0xa065, 0x0040, 0x4b72, 0x6054, 0x007e,
 	0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002,
-	0x1078, 0x37a2, 0x0040, 0x4b77, 0x7e24, 0x86ff, 0x0040, 0x4b69,
-	0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x4b69, 0x0d7e, 0x2069,
-	0x0100, 0x68c0, 0xa005, 0x0040, 0x4b60, 0x1078, 0x5582, 0x68c3,
-	0x0000, 0x1078, 0x5a32, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140,
-	0x6b04, 0xa384, 0x1000, 0x0040, 0x4b49, 0x6803, 0x0100, 0x6803,
-	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4b51, 0x6827,
-	0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4b5a,
-	0x8001, 0x603e, 0x2660, 0x1078, 0x6aa1, 0x0c7f, 0x0078, 0x4b69,
+	0x1078, 0x379a, 0x0040, 0x4b6f, 0x7e24, 0x86ff, 0x0040, 0x4b61,
+	0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x4b61, 0x0d7e, 0x2069,
+	0x0100, 0x68c0, 0xa005, 0x0040, 0x4b58, 0x1078, 0x557a, 0x68c3,
+	0x0000, 0x1078, 0x5a2a, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140,
+	0x6b04, 0xa384, 0x1000, 0x0040, 0x4b41, 0x6803, 0x0100, 0x6803,
+	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x4b49, 0x6827,
+	0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x4b52,
+	0x8001, 0x603e, 0x2660, 0x1078, 0x6a96, 0x0c7f, 0x0078, 0x4b61,
 	0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078,
-	0x4b20, 0x8dff, 0x0040, 0x4b73, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x3a7a, 0x1078, 0x5902, 0x0078, 0x4b20, 0x007f,
-	0x0078, 0x4b13, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
+	0x4b18, 0x8dff, 0x0040, 0x4b6b, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x1078, 0x3a72, 0x1078, 0x58fa, 0x0078, 0x4b18, 0x007f,
+	0x0078, 0x4b0b, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
 	0x007c, 0x0e7e, 0x0c7e, 0x2071, 0x7836, 0x7004, 0xa084, 0x0007,
-	0x0079, 0x4b8a, 0x4b94, 0x4b97, 0x4bb0, 0x4bcc, 0x4c11, 0x4b94,
-	0x4b94, 0x4b92, 0x1078, 0x12d5, 0x0c7f, 0x0e7f, 0x007c, 0x7024,
-	0xa065, 0x0040, 0x4ba5, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
-	0x0040, 0x4bac, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027,
-	0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4ba5,
-	0x6018, 0x2060, 0x1078, 0x37a2, 0x6000, 0xc0dc, 0x6002, 0x7020,
-	0x8001, 0x7022, 0x0040, 0x4bc1, 0x6054, 0xa015, 0x0040, 0x4bc8,
+	0x0079, 0x4b82, 0x4b8c, 0x4b8f, 0x4ba8, 0x4bc4, 0x4c09, 0x4b8c,
+	0x4b8c, 0x4b8a, 0x1078, 0x12cd, 0x0c7f, 0x0e7f, 0x007c, 0x7024,
+	0xa065, 0x0040, 0x4b9d, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015,
+	0x0040, 0x4ba4, 0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027,
+	0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7216, 0x7212, 0x0078, 0x4b9d,
+	0x6018, 0x2060, 0x1078, 0x379a, 0x6000, 0xc0dc, 0x6002, 0x7020,
+	0x8001, 0x7022, 0x0040, 0x4bb9, 0x6054, 0xa015, 0x0040, 0x4bc0,
 	0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
-	0x7218, 0x721e, 0x0078, 0x4bc1, 0x7024, 0xa065, 0x0040, 0x4c0e,
-	0x700c, 0xac06, 0x00c0, 0x4be3, 0x1078, 0x5902, 0x600c, 0xa015,
-	0x0040, 0x4bdf, 0x720e, 0x600f, 0x0000, 0x0078, 0x4c0c, 0x720e,
-	0x720a, 0x0078, 0x4c0c, 0x7014, 0xac06, 0x00c0, 0x4bf6, 0x1078,
-	0x5902, 0x600c, 0xa015, 0x0040, 0x4bf2, 0x7216, 0x600f, 0x0000,
-	0x0078, 0x4c0c, 0x7216, 0x7212, 0x0078, 0x4c0c, 0x6018, 0x2060,
-	0x1078, 0x37a2, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x5902, 0x701c,
-	0xa065, 0x0040, 0x4c0c, 0x6054, 0xa015, 0x0040, 0x4c0a, 0x721e,
-	0x0078, 0x4c0c, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f,
-	0x007c, 0x7024, 0xa065, 0x0040, 0x4c1e, 0x1078, 0x5902, 0x600c,
-	0xa015, 0x0040, 0x4c25, 0x720e, 0x600f, 0x0000, 0x1078, 0x5a32,
+	0x7218, 0x721e, 0x0078, 0x4bb9, 0x7024, 0xa065, 0x0040, 0x4c06,
+	0x700c, 0xac06, 0x00c0, 0x4bdb, 0x1078, 0x58fa, 0x600c, 0xa015,
+	0x0040, 0x4bd7, 0x720e, 0x600f, 0x0000, 0x0078, 0x4c04, 0x720e,
+	0x720a, 0x0078, 0x4c04, 0x7014, 0xac06, 0x00c0, 0x4bee, 0x1078,
+	0x58fa, 0x600c, 0xa015, 0x0040, 0x4bea, 0x7216, 0x600f, 0x0000,
+	0x0078, 0x4c04, 0x7216, 0x7212, 0x0078, 0x4c04, 0x6018, 0x2060,
+	0x1078, 0x379a, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x58fa, 0x701c,
+	0xa065, 0x0040, 0x4c04, 0x6054, 0xa015, 0x0040, 0x4c02, 0x721e,
+	0x0078, 0x4c04, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f, 0x0e7f,
+	0x007c, 0x7024, 0xa065, 0x0040, 0x4c16, 0x1078, 0x58fa, 0x600c,
+	0xa015, 0x0040, 0x4c1d, 0x720e, 0x600f, 0x0000, 0x1078, 0x5a2a,
 	0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a, 0x0078,
-	0x4c1e, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa084, 0x0003, 0x0079,
-	0x4c31, 0x4c37, 0x4c39, 0x4c5f, 0x4c37, 0x1078, 0x12d5, 0x0d7f,
-	0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4c55, 0x683c,
-	0xa065, 0x0040, 0x4c4a, 0x600c, 0xa015, 0x0040, 0x4c51, 0x6a3a,
+	0x4c16, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa084, 0x0003, 0x0079,
+	0x4c29, 0x4c2f, 0x4c31, 0x4c57, 0x4c2f, 0x1078, 0x12cd, 0x0d7f,
+	0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x4c4d, 0x683c,
+	0xa065, 0x0040, 0x4c42, 0x600c, 0xa015, 0x0040, 0x4c49, 0x6a3a,
 	0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c7f, 0x0d7f,
-	0x007c, 0x683a, 0x6836, 0x0078, 0x4c4a, 0x6843, 0x0000, 0x6838,
-	0xa065, 0x0040, 0x4c4a, 0x6003, 0x0003, 0x0078, 0x4c4a, 0x0c7e,
-	0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4c77,
-	0x600c, 0xa015, 0x0040, 0x4c73, 0x6a3a, 0x600f, 0x0000, 0x683f,
-	0x0000, 0x0078, 0x4c77, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f,
+	0x007c, 0x683a, 0x6836, 0x0078, 0x4c42, 0x6843, 0x0000, 0x6838,
+	0xa065, 0x0040, 0x4c42, 0x6003, 0x0003, 0x0078, 0x4c42, 0x0c7e,
+	0x6843, 0x0000, 0x6847, 0x0000, 0x683c, 0xa065, 0x0040, 0x4c6f,
+	0x600c, 0xa015, 0x0040, 0x4c6b, 0x6a3a, 0x600f, 0x0000, 0x683f,
+	0x0000, 0x0078, 0x4c6f, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f,
 	0x0d7f, 0x007c, 0x0d7e, 0x2069, 0x7836, 0x6804, 0xa084, 0x0007,
-	0x0079, 0x4c82, 0x4c8c, 0x4d29, 0x4d29, 0x4d29, 0x4d29, 0x4d2b,
-	0x4d29, 0x4c8a, 0x1078, 0x12d5, 0x6820, 0xa005, 0x00c0, 0x4c92,
-	0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4ca1, 0x6807,
-	0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, 0x0d7f,
-	0x007c, 0x6814, 0xa065, 0x0040, 0x4caf, 0x6807, 0x0001, 0x6826,
-	0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e,
-	0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x4d24, 0x704c, 0xa00d,
-	0x0040, 0x4cbe, 0x7088, 0xa005, 0x0040, 0x4cd6, 0x7054, 0xa075,
-	0x0040, 0x4cc7, 0xa20e, 0x0040, 0x4d24, 0x0078, 0x4ccc, 0x6818,
-	0xa20e, 0x0040, 0x4d24, 0x2070, 0x704c, 0xa00d, 0x0040, 0x4cbe,
-	0x7088, 0xa005, 0x00c0, 0x4cbe, 0x2e00, 0x681e, 0x733c, 0x7038,
-	0xa302, 0x00c8, 0x4cbe, 0x1078, 0x5bd1, 0x0040, 0x4d24, 0x8318,
+	0x0079, 0x4c7a, 0x4c84, 0x4d21, 0x4d21, 0x4d21, 0x4d21, 0x4d23,
+	0x4d21, 0x4c82, 0x1078, 0x12cd, 0x6820, 0xa005, 0x00c0, 0x4c8a,
+	0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4c99, 0x6807,
+	0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d69, 0x0c7f, 0x0d7f,
+	0x007c, 0x6814, 0xa065, 0x0040, 0x4ca7, 0x6807, 0x0001, 0x6826,
+	0x682b, 0x0000, 0x1078, 0x4d69, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e,
+	0x037e, 0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x4d1c, 0x704c, 0xa00d,
+	0x0040, 0x4cb6, 0x7088, 0xa005, 0x0040, 0x4cce, 0x7054, 0xa075,
+	0x0040, 0x4cbf, 0xa20e, 0x0040, 0x4d1c, 0x0078, 0x4cc4, 0x6818,
+	0xa20e, 0x0040, 0x4d1c, 0x2070, 0x704c, 0xa00d, 0x0040, 0x4cb6,
+	0x7088, 0xa005, 0x00c0, 0x4cb6, 0x2e00, 0x681e, 0x733c, 0x7038,
+	0xa302, 0x00c8, 0x4cb6, 0x1078, 0x5bc9, 0x0040, 0x4d1c, 0x8318,
 	0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0015, 0x2004, 0xa08a,
-	0x199a, 0x0048, 0x4ced, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b,
+	0x199a, 0x0048, 0x4ce5, 0x2001, 0x1999, 0x8003, 0x801b, 0x831b,
 	0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc, 0x0040,
-	0x4d06, 0x7100, 0xd1f4, 0x0040, 0x4d02, 0x7114, 0xa18c, 0x00ff,
-	0x0078, 0x4d0b, 0x2009, 0x0000, 0x0078, 0x4d0b, 0xa1e0, 0x232f,
-	0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x51c2,
+	0x4cfe, 0x7100, 0xd1f4, 0x0040, 0x4cfa, 0x7114, 0xa18c, 0x00ff,
+	0x0078, 0x4d03, 0x2009, 0x0000, 0x0078, 0x4d03, 0xa1e0, 0x2329,
+	0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078, 0x51ba,
 	0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26, 0x682b,
 	0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040, 0x0f7f,
 	0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f, 0x0078,
-	0x4d22, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4d37,
-	0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d71, 0x0c7f,
+	0x4d1a, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x4d2f,
+	0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x4d69, 0x0c7f,
 	0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0x7836, 0x6830, 0xa086,
-	0x0000, 0x00c0, 0x4d58, 0x6838, 0xa07d, 0x0040, 0x4d58, 0x6833,
+	0x0000, 0x00c0, 0x4d50, 0x6838, 0xa07d, 0x0040, 0x4d50, 0x6833,
 	0x0001, 0x683e, 0x6847, 0x0000, 0x127e, 0x0f7e, 0x2091, 0x2200,
-	0x027f, 0x1078, 0x1a4c, 0x00c0, 0x4d5b, 0x127f, 0x1078, 0x5457,
+	0x027f, 0x1078, 0x1a44, 0x00c0, 0x4d53, 0x127f, 0x1078, 0x544f,
 	0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843, 0x0000, 0x7803, 0x0002,
-	0x780c, 0xa015, 0x0040, 0x4d6d, 0x6a3a, 0x780f, 0x0000, 0x6833,
-	0x0000, 0x683f, 0x0000, 0x0078, 0x4d58, 0x683a, 0x6836, 0x0078,
-	0x4d67, 0x601c, 0xa084, 0x000f, 0x1079, 0x4d77, 0x007c, 0x4d80,
-	0x4d85, 0x508c, 0x5182, 0x4d85, 0x508c, 0x5182, 0x4d80, 0x4d85,
-	0x1078, 0x4b81, 0x1078, 0x4c7a, 0x007c, 0x157e, 0x137e, 0x147e,
-	0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, 0x6118,
-	0x2178, 0x79a0, 0xd1bc, 0x0040, 0x4da2, 0x7900, 0xd1f4, 0x0040,
-	0x4d9e, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x4da7, 0x2009, 0x0000,
-	0x0078, 0x4da7, 0xa1f8, 0x232f, 0x2f0c, 0xa18c, 0x00ff, 0x2c78,
-	0x2061, 0x0100, 0x619a, 0x1079, 0x4db3, 0x0f7f, 0x0c7f, 0x147f,
-	0x137f, 0x157f, 0x007c, 0x4de5, 0x4e1d, 0x4e35, 0x4eb4, 0x4ee1,
-	0x4ee9, 0x4f0a, 0x4f1b, 0x4f2c, 0x4f34, 0x4f45, 0x4f34, 0x4f8d,
-	0x4f1b, 0x4fae, 0x4fb6, 0x4f2c, 0x4fb6, 0x4fc7, 0x4de3, 0x4de3,
-	0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3, 0x4de3,
-	0x4de3, 0x4de3, 0x5640, 0x5655, 0x5678, 0x569c, 0x4f0a, 0x4de3,
-	0x4f0a, 0x4f34, 0x4de3, 0x4e35, 0x4eb4, 0x4de3, 0x5b4c, 0x4f34,
-	0x4de3, 0x5b6f, 0x4f34, 0x1078, 0x12d5, 0x20a1, 0x020b, 0x1078,
-	0x4fdc, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x7651,
-	0x6804, 0xd084, 0x0040, 0x4dff, 0x6828, 0x20a3, 0x0000, 0x017e,
-	0x1078, 0x209a, 0x21a2, 0x017f, 0x0d7f, 0x0078, 0x4e04, 0x0d7f,
+	0x780c, 0xa015, 0x0040, 0x4d65, 0x6a3a, 0x780f, 0x0000, 0x6833,
+	0x0000, 0x683f, 0x0000, 0x0078, 0x4d50, 0x683a, 0x6836, 0x0078,
+	0x4d5f, 0x601c, 0xa084, 0x000f, 0x1079, 0x4d6f, 0x007c, 0x4d78,
+	0x4d7d, 0x5084, 0x517a, 0x4d7d, 0x5084, 0x517a, 0x4d78, 0x4d7d,
+	0x1078, 0x4b79, 0x1078, 0x4c72, 0x007c, 0x157e, 0x137e, 0x147e,
+	0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x6118,
+	0x2178, 0x79a0, 0xd1bc, 0x0040, 0x4d9a, 0x7900, 0xd1f4, 0x0040,
+	0x4d96, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x4d9f, 0x2009, 0x0000,
+	0x0078, 0x4d9f, 0xa1f8, 0x2329, 0x2f0c, 0xa18c, 0x00ff, 0x2c78,
+	0x2061, 0x0100, 0x619a, 0x1079, 0x4dab, 0x0f7f, 0x0c7f, 0x147f,
+	0x137f, 0x157f, 0x007c, 0x4ddd, 0x4e15, 0x4e2d, 0x4eac, 0x4ed9,
+	0x4ee1, 0x4f02, 0x4f13, 0x4f24, 0x4f2c, 0x4f3d, 0x4f2c, 0x4f85,
+	0x4f13, 0x4fa6, 0x4fae, 0x4f24, 0x4fae, 0x4fbf, 0x4ddb, 0x4ddb,
+	0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddb,
+	0x4ddb, 0x4ddb, 0x5638, 0x564d, 0x5670, 0x5694, 0x4f02, 0x4ddb,
+	0x4f02, 0x4f2c, 0x4ddb, 0x4e2d, 0x4eac, 0x4ddb, 0x5b44, 0x4f2c,
+	0x4ddb, 0x5b67, 0x4f2c, 0x1078, 0x12cd, 0x20a1, 0x020b, 0x1078,
+	0x4fd4, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x0d7e, 0x2069, 0x7651,
+	0x6804, 0xd084, 0x0040, 0x4df7, 0x6828, 0x20a3, 0x0000, 0x017e,
+	0x1078, 0x2094, 0x21a2, 0x017f, 0x0d7f, 0x0078, 0x4dfc, 0x0d7f,
 	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x7605,
 	0x53a6, 0x20a9, 0x0004, 0x2099, 0x7601, 0x53a6, 0x20a3, 0x0000,
 	0x6030, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x001c, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x4fdc, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030,
+	0x60c3, 0x001c, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078,
+	0x4fd4, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6030,
 	0xa084, 0x00ff, 0x20a2, 0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6,
-	0x60c3, 0x0010, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x4fdc, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0,
-	0x4e48, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4e4a,
+	0x60c3, 0x0010, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078,
+	0x4fd4, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0,
+	0x4e40, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0078, 0x4e42,
 	0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0xa086, 0x007e, 0x00c0, 0x4e83, 0x2099, 0x7820, 0x33a6, 0x9398,
+	0xa086, 0x007e, 0x00c0, 0x4e7b, 0x2099, 0x7820, 0x33a6, 0x9398,
 	0x33a6, 0x9398, 0x3304, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6,
 	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
 	0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099,
-	0x7601, 0x53a6, 0x20a9, 0x0010, 0x20a3, 0x0000, 0x00f0, 0x4e74,
+	0x7601, 0x53a6, 0x20a9, 0x0010, 0x20a3, 0x0000, 0x00f0, 0x4e6c,
 	0x2099, 0x7828, 0x33a6, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x00f0,
-	0x4e7d, 0x0078, 0x4ea3, 0x2099, 0x7820, 0x20a9, 0x0008, 0x53a6,
+	0x4e75, 0x0078, 0x4e9b, 0x2099, 0x7820, 0x20a9, 0x0008, 0x53a6,
 	0x20a9, 0x0004, 0x2099, 0x7605, 0x53a6, 0x20a9, 0x0004, 0x2099,
-	0x7601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e94,
-	0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e9a, 0x2099, 0x7828,
+	0x7601, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e8c,
+	0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x4e92, 0x2099, 0x7828,
 	0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0,
-	0x4ea5, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4eab, 0x60c3,
-	0x0074, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fdc,
+	0x4e9d, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x4ea3, 0x60c3,
+	0x0074, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x4fd4,
 	0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000,
 	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079,
-	0x7651, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4ed0, 0xa085, 0x0020,
-	0xd1a4, 0x0040, 0x4ed5, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x556e,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x5000, 0x0078,
-	0x4e4a, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x2110, 0x20a3,
+	0x7651, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x4ec8, 0xa085, 0x0020,
+	0xd1a4, 0x0040, 0x4ecd, 0xa085, 0x0010, 0xa085, 0x0002, 0x20a2,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x5566,
+	0x007c, 0x20a1, 0x020b, 0x1078, 0x4fd4, 0x20a3, 0x5000, 0x0078,
+	0x4e42, 0x20a1, 0x020b, 0x1078, 0x4fd4, 0x20a3, 0x2110, 0x20a3,
 	0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3, 0x0200,
+	0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3, 0x0200,
 	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
-	0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3,
+	0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3,
 	0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3,
-	0x0008, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x1078, 0x5053,
-	0x20a3, 0x0200, 0x0078, 0x4e4a, 0x20a1, 0x020b, 0x1078, 0x5053,
+	0x0008, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x1078, 0x504b,
+	0x20a3, 0x0200, 0x0078, 0x4e42, 0x20a1, 0x020b, 0x1078, 0x504b,
 	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x7810, 0x20a2,
-	0x60c3, 0x0008, 0x1078, 0x556e, 0x007c, 0x0d7e, 0x20a1, 0x020b,
-	0x1078, 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
-	0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4f6b, 0x6998,
-	0xa184, 0xc000, 0x00c0, 0x4f67, 0xd1ec, 0x0040, 0x4f63, 0x20a3,
-	0x2100, 0x0078, 0x4f6d, 0x20a3, 0x0100, 0x0078, 0x4f6d, 0x20a3,
-	0x0400, 0x0078, 0x4f6d, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2,
+	0x60c3, 0x0008, 0x1078, 0x5566, 0x007c, 0x0d7e, 0x20a1, 0x020b,
+	0x1078, 0x504b, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800,
+	0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x4f63, 0x6998,
+	0xa184, 0xc000, 0x00c0, 0x4f5f, 0xd1ec, 0x0040, 0x4f5b, 0x20a3,
+	0x2100, 0x0078, 0x4f65, 0x20a3, 0x0100, 0x0078, 0x4f65, 0x20a3,
+	0x0400, 0x0078, 0x4f65, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2,
 	0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0x7651, 0x7904, 0x0f7f,
-	0xd1ac, 0x00c0, 0x4f7d, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4f82,
+	0xd1ac, 0x00c0, 0x4f75, 0xa085, 0x0020, 0xd1a4, 0x0040, 0x4f7a,
 	0xa085, 0x0010, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2, 0x60c3,
-	0x0014, 0x1078, 0x556e, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x5053, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
+	0x0014, 0x1078, 0x5566, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078,
+	0x504b, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
 	0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b,
-	0x1078, 0x5053, 0x20a3, 0x0200, 0x0078, 0x4deb, 0x20a1, 0x020b,
-	0x1078, 0x5053, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
-	0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x556e, 0x007c, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x5053, 0x20a3,
+	0x0000, 0x60c3, 0x0014, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b,
+	0x1078, 0x504b, 0x20a3, 0x0200, 0x0078, 0x4de3, 0x20a1, 0x020b,
+	0x1078, 0x504b, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003,
+	0x20a3, 0x2a00, 0x60c3, 0x0008, 0x1078, 0x5566, 0x007c, 0x20e1,
+	0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x1078, 0x504b, 0x20a3,
 	0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3,
-	0x0008, 0x1078, 0x556e, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
+	0x0008, 0x1078, 0x5566, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
 	0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0,
-	0x4fef, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x501d, 0xa286,
-	0x007f, 0x00c0, 0x4ffa, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd,
-	0x0078, 0x5011, 0xd2bc, 0x0040, 0x5019, 0xa286, 0x0080, 0x0d7e,
-	0x00c0, 0x5008, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x5011,
+	0x4fe7, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x0078, 0x5015, 0xa286,
+	0x007f, 0x00c0, 0x4ff2, 0x0d7e, 0x20a3, 0x22ff, 0x20a3, 0xfffd,
+	0x0078, 0x5009, 0xd2bc, 0x0040, 0x5011, 0xa286, 0x0080, 0x0d7e,
+	0x00c0, 0x5000, 0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0078, 0x5009,
 	0xa2e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x2200, 0x20a2, 0x6814,
 	0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
-	0x5021, 0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230,
-	0x22a2, 0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2,
+	0x5019, 0x20a3, 0x2200, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230,
+	0x22a2, 0x20a3, 0x0129, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2,
 	0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x027f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
 	0x20a3, 0x02ff, 0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0x7619,
 	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000,
-	0x0078, 0x5025, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02,
+	0x0078, 0x501d, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02,
 	0x20a3, 0x0000, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5072,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x506a,
 	0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x2300, 0x20a2,
 	0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x0078, 0x507a, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x555d,
+	0x0078, 0x5072, 0x20a3, 0x2300, 0x6298, 0x22a2, 0x20a3, 0x0000,
+	0x6230, 0x22a2, 0x20a3, 0x0198, 0x20a3, 0x0000, 0x1078, 0x5555,
 	0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000,
 	0x20a3, 0x0000, 0x027f, 0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a,
-	0x0085, 0x1048, 0x12d5, 0xa08a, 0x008c, 0x10c8, 0x12d5, 0x6118,
-	0x2178, 0x79a0, 0xd1bc, 0x0040, 0x50aa, 0x7900, 0xd1f4, 0x0040,
-	0x50a6, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x50af, 0x2009, 0x0000,
-	0x0078, 0x50af, 0xa1f8, 0x232f, 0x2f0c, 0xa18c, 0x00ff, 0x2c78,
-	0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x1079, 0x50ba, 0x0f7f,
-	0x0c7f, 0x007c, 0x50c3, 0x50ce, 0x50e8, 0x50c1, 0x50c1, 0x50c1,
-	0x50c3, 0x1078, 0x12d5, 0x147e, 0x20a1, 0x020b, 0x1078, 0x50fb,
-	0x60c3, 0x0000, 0x1078, 0x556e, 0x147f, 0x007c, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x5128, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
+	0x0085, 0x1048, 0x12cd, 0xa08a, 0x008c, 0x10c8, 0x12cd, 0x6118,
+	0x2178, 0x79a0, 0xd1bc, 0x0040, 0x50a2, 0x7900, 0xd1f4, 0x0040,
+	0x509e, 0x7914, 0xa18c, 0x00ff, 0x0078, 0x50a7, 0x2009, 0x0000,
+	0x0078, 0x50a7, 0xa1f8, 0x2329, 0x2f0c, 0xa18c, 0x00ff, 0x2c78,
+	0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x1079, 0x50b2, 0x0f7f,
+	0x0c7f, 0x007c, 0x50bb, 0x50c6, 0x50e0, 0x50b9, 0x50b9, 0x50b9,
+	0x50bb, 0x1078, 0x12cd, 0x147e, 0x20a1, 0x020b, 0x1078, 0x50f3,
+	0x60c3, 0x0000, 0x1078, 0x5566, 0x147f, 0x007c, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x5120, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
 	0x20a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x556e, 0x147f, 0x007c,
-	0x147e, 0x20a1, 0x020b, 0x1078, 0x5155, 0x20a3, 0x0003, 0x20a3,
+	0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x5566, 0x147f, 0x007c,
+	0x147e, 0x20a1, 0x020b, 0x1078, 0x514d, 0x20a3, 0x0003, 0x20a3,
 	0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078,
-	0x556e, 0x147f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x511a,
+	0x5566, 0x147f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x5112,
 	0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
 	0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x0078, 0x5122, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000,
-	0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0078, 0x5025,
+	0x0078, 0x511a, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000,
+	0x6230, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0078, 0x501d,
 	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa092, 0x007e, 0x0048, 0x5147, 0x0d7e, 0xa0e8, 0x7720,
+	0x2004, 0xa092, 0x007e, 0x0048, 0x513f, 0x0d7e, 0xa0e8, 0x7720,
 	0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069,
-	0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x514f, 0x20a3,
+	0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5147, 0x20a3,
 	0x8400, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
-	0x00d1, 0x20a3, 0x0000, 0x0078, 0x507e, 0x027e, 0x20e1, 0x9080,
+	0x00d1, 0x20a3, 0x0000, 0x0078, 0x5076, 0x027e, 0x20e1, 0x9080,
 	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e,
-	0x0048, 0x5174, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085,
+	0x0048, 0x516c, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085,
 	0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x0078, 0x517c, 0x20a3, 0x8500, 0x6298, 0x22a2,
+	0x2da6, 0x0d7f, 0x0078, 0x5174, 0x20a3, 0x8500, 0x6298, 0x22a2,
 	0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x00d1, 0x20a3, 0x0000,
-	0x0078, 0x507e, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040,
-	0x1048, 0x12d5, 0xa08a, 0x0050, 0x10c8, 0x12d5, 0x7918, 0x2160,
-	0x61a0, 0xd1bc, 0x0040, 0x51a1, 0x6100, 0xd1f4, 0x0040, 0x519d,
-	0x6114, 0xa18c, 0x00ff, 0x0078, 0x51a6, 0x2009, 0x0000, 0x0078,
-	0x51a6, 0xa1e0, 0x232f, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100,
-	0x619a, 0xa082, 0x0040, 0x1079, 0x51b0, 0x0f7f, 0x0c7f, 0x007c,
-	0x51c2, 0x52aa, 0x5252, 0x53d2, 0x51c0, 0x51c0, 0x51c0, 0x51c0,
-	0x51c0, 0x51c0, 0x51c0, 0x581b, 0x582c, 0x583d, 0x584e, 0x51c0,
-	0x1078, 0x12d5, 0x0d7e, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x5215, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff, 0x21a2, 0xa016,
+	0x0078, 0x5076, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040,
+	0x1048, 0x12cd, 0xa08a, 0x0050, 0x10c8, 0x12cd, 0x7918, 0x2160,
+	0x61a0, 0xd1bc, 0x0040, 0x5199, 0x6100, 0xd1f4, 0x0040, 0x5195,
+	0x6114, 0xa18c, 0x00ff, 0x0078, 0x519e, 0x2009, 0x0000, 0x0078,
+	0x519e, 0xa1e0, 0x2329, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100,
+	0x619a, 0xa082, 0x0040, 0x1079, 0x51a8, 0x0f7f, 0x0c7f, 0x007c,
+	0x51ba, 0x52a2, 0x524a, 0x53ca, 0x51b8, 0x51b8, 0x51b8, 0x51b8,
+	0x51b8, 0x51b8, 0x51b8, 0x5813, 0x5824, 0x5835, 0x5846, 0x51b8,
+	0x1078, 0x12cd, 0x0d7e, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
+	0x520d, 0x7910, 0x2168, 0x6944, 0xa18c, 0x00ff, 0x21a2, 0xa016,
 	0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184, 0x0006, 0x8004, 0x20a2,
-	0xd1ac, 0x0040, 0x51df, 0x20a3, 0x0002, 0x0078, 0x51eb, 0xd1b4,
-	0x0040, 0x51e6, 0x20a3, 0x0001, 0x0078, 0x51eb, 0x20a3, 0x0000,
-	0x2230, 0x0078, 0x51ed, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0xad80,
-	0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x51f1, 0x22a2,
+	0xd1ac, 0x0040, 0x51d7, 0x20a3, 0x0002, 0x0078, 0x51e3, 0xd1b4,
+	0x0040, 0x51de, 0x20a3, 0x0001, 0x0078, 0x51e3, 0x20a3, 0x0000,
+	0x2230, 0x0078, 0x51e5, 0x6a80, 0x6e7c, 0x20a9, 0x0008, 0xad80,
+	0x0017, 0x200c, 0x810f, 0x21a2, 0x8000, 0x00f0, 0x51e9, 0x22a2,
 	0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080, 0x6014, 0xa084, 0x0004,
 	0xa085, 0x0009, 0x6016, 0x2001, 0x7852, 0x2003, 0x07d0, 0x2001,
 	0x7851, 0x2003, 0x0009, 0x2001, 0x7857, 0x2003, 0x0002, 0x1078,
-	0x1504, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1,
+	0x14fc, 0x147f, 0x157f, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x20e1,
 	0x4000, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff,
 	0x2202, 0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040,
-	0x523b, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0600,
+	0x5233, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085, 0x0600,
 	0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6,
-	0x0d7f, 0x0078, 0x5243, 0x20a3, 0x0600, 0x6198, 0x21a2, 0x20a3,
+	0x0d7f, 0x0078, 0x523b, 0x20a3, 0x0600, 0x6198, 0x21a2, 0x20a3,
 	0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3, 0x0000, 0x22a2,
 	0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x5272, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2,
+	0x1078, 0x526a, 0x7810, 0x2068, 0x6860, 0x20a2, 0x685c, 0x20a2,
 	0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x60c3, 0x000c, 0x1078, 0x556e, 0x147f, 0x137f, 0x157f,
+	0x20a2, 0x60c3, 0x000c, 0x1078, 0x5566, 0x147f, 0x137f, 0x157f,
 	0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5290, 0x0d7e, 0xa0e8,
+	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x5288, 0x0d7e, 0xa0e8,
 	0x7720, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5298,
+	0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x5290,
 	0x20a3, 0x0500, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2,
-	0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, 0x20a3,
+	0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2, 0x20a3,
 	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
 	0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x539a, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0, 0x52c7, 0x7810,
-	0xa084, 0x0700, 0x8007, 0x1079, 0x52cf, 0x0078, 0x52ca, 0xa006,
-	0x1079, 0x52cf, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x52d9,
-	0x533b, 0x533f, 0x5362, 0x536f, 0x5381, 0x5385, 0x52d7, 0x1078,
-	0x12d5, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000,
-	0x00c0, 0x52ec, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2,
-	0x037f, 0x017f, 0x0078, 0x5366, 0xa186, 0x0001, 0x00c0, 0x5336,
+	0x1078, 0x5392, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x00c0, 0x52bf, 0x7810,
+	0xa084, 0x0700, 0x8007, 0x1079, 0x52c7, 0x0078, 0x52c2, 0xa006,
+	0x1079, 0x52c7, 0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x52d1,
+	0x5333, 0x5337, 0x535a, 0x5367, 0x5379, 0x537d, 0x52cf, 0x1078,
+	0x12cd, 0x017e, 0x037e, 0x694c, 0xa18c, 0x0003, 0xa186, 0x0000,
+	0x00c0, 0x52e4, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2,
+	0x037f, 0x017f, 0x0078, 0x535e, 0xa186, 0x0001, 0x00c0, 0x532e,
 	0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874,
 	0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300,
-	0x0040, 0x5335, 0xd3c4, 0x0040, 0x5307, 0x687c, 0xa108, 0xd3cc,
-	0x0040, 0x530c, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80,
-	0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x5311, 0x157f,
-	0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x5335, 0x20a1,
+	0x0040, 0x532d, 0xd3c4, 0x0040, 0x52ff, 0x687c, 0xa108, 0xd3cc,
+	0x0040, 0x5304, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80,
+	0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x5309, 0x157f,
+	0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x532d, 0x20a1,
 	0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x0700, 0x6298,
 	0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0898, 0x20a2,
-	0x1078, 0x555d, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f,
-	0x1078, 0x556e, 0x007c, 0x20a3, 0x0008, 0x0078, 0x5364, 0x20a3,
+	0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f, 0x017f,
+	0x1078, 0x5566, 0x007c, 0x20a3, 0x0008, 0x0078, 0x535c, 0x20a3,
 	0x0302, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3,
 	0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3,
 	0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500,
 	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078,
-	0x556e, 0x007c, 0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x556e, 0x007c, 0x20a3,
+	0x5566, 0x007c, 0x20a3, 0x0028, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x60c3, 0x0018, 0x1078, 0x5566, 0x007c, 0x20a3,
 	0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x556e,
-	0x007c, 0x20a3, 0x0008, 0x0078, 0x5364, 0x037e, 0x7b10, 0xa384,
-	0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x5393, 0x22a2,
-	0x037f, 0x0078, 0x5364, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f,
-	0x0078, 0x5366, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x53b8, 0x0d7e, 0xa0e8,
+	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x5566,
+	0x007c, 0x20a3, 0x0008, 0x0078, 0x535c, 0x037e, 0x7b10, 0xa384,
+	0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x538b, 0x22a2,
+	0x037f, 0x0078, 0x535c, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x037f,
+	0x0078, 0x535e, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818,
+	0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x53b0, 0x0d7e, 0xa0e8,
 	0x7720, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x53c0,
+	0x2069, 0x7619, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x53b8,
 	0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2,
-	0x20a3, 0x0898, 0x20a3, 0x0000, 0x1078, 0x555d, 0x22a2, 0x20a3,
+	0x20a3, 0x0898, 0x20a3, 0x0000, 0x1078, 0x5555, 0x22a2, 0x20a3,
 	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
 	0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x017e, 0x037e,
-	0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x53e5, 0x037f, 0x017f,
-	0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x53ed, 0x53ed, 0x53ef,
-	0x53ed, 0x53ed, 0x53ed, 0x5414, 0x53ed, 0x1078, 0x12d5, 0x7910,
+	0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x53dd, 0x037f, 0x017f,
+	0x147f, 0x137f, 0x157f, 0x0d7f, 0x007c, 0x53e5, 0x53e5, 0x53e7,
+	0x53e5, 0x53e5, 0x53e5, 0x540c, 0x53e5, 0x1078, 0x12cd, 0x7910,
 	0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009,
-	0x0003, 0x1078, 0x541e, 0x0d7e, 0x2069, 0x7651, 0x6804, 0xd0bc,
-	0x0040, 0x5409, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078,
-	0x540b, 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
-	0x0001, 0x1078, 0x556e, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003,
-	0x1078, 0x541e, 0x20a3, 0x7f00, 0x0078, 0x540c, 0x027e, 0x20e1,
+	0x0003, 0x1078, 0x5416, 0x0d7e, 0x2069, 0x7651, 0x6804, 0xd0bc,
+	0x0040, 0x5401, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078,
+	0x5403, 0x20a3, 0x3f00, 0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
+	0x0001, 0x1078, 0x5566, 0x007c, 0x20a1, 0x020b, 0x2009, 0x0003,
+	0x1078, 0x5416, 0x20a3, 0x7f00, 0x0078, 0x5404, 0x027e, 0x20e1,
 	0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc,
-	0x0040, 0x543c, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085,
+	0x0040, 0x5434, 0x0d7e, 0xa0e8, 0x7720, 0x2d6c, 0x6810, 0xa085,
 	0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x7619, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x0078, 0x5444, 0x20a3, 0x0100, 0x6298, 0x22a2,
+	0x2da6, 0x0d7f, 0x0078, 0x543c, 0x20a3, 0x0100, 0x6298, 0x22a2,
 	0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008,
-	0x21a2, 0x1078, 0x555d, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
+	0x21a2, 0x1078, 0x5555, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
 	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0e7e,
 	0x0d7e, 0x0c7e, 0x057e, 0x047e, 0x037e, 0x2061, 0x0100, 0x2071,
 	0x7600, 0x6130, 0x7818, 0x2068, 0x68a0, 0x2028, 0xd0bc, 0x00c0,
-	0x5470, 0xa080, 0x232f, 0x2014, 0xa294, 0x00ff, 0x0078, 0x5474,
+	0x5468, 0xa080, 0x2329, 0x2014, 0xa294, 0x00ff, 0x0078, 0x546c,
 	0x6910, 0x6a14, 0x7364, 0x7468, 0x781c, 0xa086, 0x0006, 0x0040,
-	0x54c8, 0xd5bc, 0x0040, 0x5484, 0xa185, 0x0100, 0x6062, 0x6266,
-	0x636a, 0x646e, 0x0078, 0x548a, 0x6063, 0x0100, 0x6266, 0x606b,
+	0x54c0, 0xd5bc, 0x0040, 0x547c, 0xa185, 0x0100, 0x6062, 0x6266,
+	0x636a, 0x646e, 0x0078, 0x5482, 0x6063, 0x0100, 0x6266, 0x606b,
 	0x0000, 0x616e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000,
 	0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
 	0x6082, 0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010,
 	0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab,
 	0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048,
-	0x54bc, 0x6a00, 0xd2f4, 0x0040, 0x54ba, 0x6a14, 0xa294, 0x00ff,
-	0x0078, 0x54bc, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x1078,
-	0x45f0, 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
+	0x54b4, 0x6a00, 0xd2f4, 0x0040, 0x54b2, 0x6a14, 0xa294, 0x00ff,
+	0x0078, 0x54b4, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016, 0x1078,
+	0x45e8, 0x037f, 0x047f, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
 	0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040,
-	0x5517, 0xd5bc, 0x0040, 0x54dc, 0xa185, 0x0100, 0x6062, 0x6266,
-	0x636a, 0x646e, 0x0078, 0x54e2, 0x6063, 0x0100, 0x6266, 0x606b,
+	0x550f, 0xd5bc, 0x0040, 0x54d4, 0xa185, 0x0100, 0x6062, 0x6266,
+	0x636a, 0x646e, 0x0078, 0x54da, 0x6063, 0x0100, 0x6266, 0x606b,
 	0x0000, 0x616e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
 	0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
 	0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
 	0x60c6, 0x707c, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
-	0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x5512, 0x6a00,
-	0xd2f4, 0x0040, 0x5510, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5512,
-	0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x54bf, 0xd5bc,
-	0x0040, 0x5522, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
-	0x0078, 0x5528, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e,
+	0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0048, 0x550a, 0x6a00,
+	0xd2f4, 0x0040, 0x5508, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x550a,
+	0x2011, 0x0000, 0x629e, 0x6017, 0x0012, 0x0078, 0x54b7, 0xd5bc,
+	0x0040, 0x551a, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
+	0x0078, 0x5520, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e,
 	0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff,
 	0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
 	0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
 	0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
-	0x0000, 0xa582, 0x0080, 0x0048, 0x5558, 0x6a00, 0xd2f4, 0x0040,
-	0x5556, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5558, 0x2011, 0x0000,
-	0x629e, 0x6017, 0x0016, 0x0078, 0x54bf, 0x7a18, 0xa280, 0x0023,
+	0x0000, 0xa582, 0x0080, 0x0048, 0x5550, 0x6a00, 0xd2f4, 0x0040,
+	0x554e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x5550, 0x2011, 0x0000,
+	0x629e, 0x6017, 0x0016, 0x0078, 0x54b7, 0x7a18, 0xa280, 0x0023,
 	0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e,
 	0x2069, 0x7836, 0x6843, 0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080,
-	0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x5579, 0x1078, 0x45e0,
+	0x60a3, 0x0056, 0x60a7, 0x9575, 0x1078, 0x5571, 0x1078, 0x45d8,
 	0x007c, 0x007e, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016,
 	0x007f, 0x007c, 0x007e, 0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084,
 	0x0004, 0xa085, 0x0008, 0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e,
-	0x0d7e, 0x017e, 0x027e, 0x1078, 0x45eb, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55cc, 0x1078, 0x5582,
+	0x0d7e, 0x017e, 0x027e, 0x1078, 0x45e3, 0x2061, 0x0100, 0x2069,
+	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55c4, 0x1078, 0x557a,
 	0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e, 0x2061, 0x7836, 0x6128,
-	0xa192, 0x0002, 0x00c8, 0x55b9, 0x8108, 0x612a, 0x6124, 0x0c7f,
-	0x81ff, 0x0040, 0x55c7, 0x1078, 0x45e0, 0x1078, 0x5579, 0x0078,
-	0x55c7, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x55c4, 0x1078, 0x75c7,
-	0x2009, 0x0014, 0x1078, 0x5c29, 0x0c7f, 0x0078, 0x55c7, 0x027f,
-	0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x357b, 0x0078, 0x55c7,
-	0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x45f9, 0x2071,
-	0x7836, 0x713c, 0x81ff, 0x0040, 0x55fa, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x5600, 0x6803, 0x1000,
-	0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x5768, 0x037f,
-	0x713c, 0x2160, 0x1078, 0x75c7, 0x2009, 0x004a, 0x1078, 0x5c29,
-	0x0078, 0x55fa, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
-	0x7144, 0xa192, 0x0002, 0x00c8, 0x55ea, 0x8108, 0x7146, 0x1078,
-	0x45f0, 0x0078, 0x55fa, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e,
+	0xa192, 0x0002, 0x00c8, 0x55b1, 0x8108, 0x612a, 0x6124, 0x0c7f,
+	0x81ff, 0x0040, 0x55bf, 0x1078, 0x45d8, 0x1078, 0x5571, 0x0078,
+	0x55bf, 0x6124, 0xa1e5, 0x0000, 0x0040, 0x55bc, 0x1078, 0x75bc,
+	0x2009, 0x0014, 0x1078, 0x5c21, 0x0c7f, 0x0078, 0x55bf, 0x027f,
+	0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x1078, 0x3573, 0x0078, 0x55bf,
+	0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x45f1, 0x2071,
+	0x7836, 0x713c, 0x81ff, 0x0040, 0x55f2, 0x2061, 0x0100, 0x2069,
+	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x55f8, 0x6803, 0x1000,
+	0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x5760, 0x037f,
+	0x713c, 0x2160, 0x1078, 0x75bc, 0x2009, 0x004a, 0x1078, 0x5c21,
+	0x0078, 0x55f2, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
+	0x7144, 0xa192, 0x0002, 0x00c8, 0x55e2, 0x8108, 0x7146, 0x1078,
+	0x45e8, 0x0078, 0x55f2, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e,
 	0x047e, 0x007e, 0x127e, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0,
-	0x2071, 0x7836, 0x7018, 0x2068, 0x8dff, 0x0040, 0x5637, 0x68a0,
-	0xa406, 0x0040, 0x5627, 0x6854, 0x2068, 0x0078, 0x561c, 0x6010,
+	0x2071, 0x7836, 0x7018, 0x2068, 0x8dff, 0x0040, 0x562f, 0x68a0,
+	0xa406, 0x0040, 0x561f, 0x6854, 0x2068, 0x0078, 0x5614, 0x6010,
 	0x2060, 0x643c, 0x6540, 0x6644, 0xa6b4, 0x000f, 0x2d60, 0x1078,
-	0x38f9, 0x0040, 0x5637, 0x1078, 0x5902, 0xa085, 0x0001, 0x127f,
+	0x38f1, 0x0040, 0x562f, 0x1078, 0x58fa, 0xa085, 0x0001, 0x127f,
 	0x007f, 0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
-	0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4fdc, 0x20a3, 0x0f00,
+	0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x4fd4, 0x20a3, 0x0f00,
 	0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008,
-	0x1078, 0x556e, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x5053, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9,
+	0x1078, 0x5566, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x504b, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a9,
 	0x0006, 0x2011, 0x7640, 0x2019, 0x7641, 0x23a6, 0x22a6, 0xa398,
-	0x0002, 0xa290, 0x0002, 0x00f0, 0x5665, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x001c, 0x1078, 0x556e, 0x147f, 0x157f, 0x007c,
-	0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x5033,
-	0x1078, 0x504a, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808,
+	0x0002, 0xa290, 0x0002, 0x00f0, 0x565d, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x001c, 0x1078, 0x5566, 0x147f, 0x157f, 0x007c,
+	0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b, 0x1078, 0x502b,
+	0x1078, 0x5042, 0x7810, 0x007e, 0xa080, 0x0015, 0x2098, 0x7808,
 	0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2,
-	0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x556e, 0x027f,
+	0x007f, 0xa080, 0x0001, 0x2004, 0x7812, 0x1078, 0x5566, 0x027f,
 	0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x4fdc, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x556e, 0x147f, 0x157f,
+	0x1078, 0x4fd4, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x5566, 0x147f, 0x157f,
 	0x007c, 0x0e7e, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
-	0x7836, 0x700c, 0x2060, 0x8cff, 0x0040, 0x56cd, 0x1078, 0x6ace,
-	0x00c0, 0x56c4, 0x1078, 0x5e57, 0x600c, 0x007e, 0x1078, 0x5c02,
-	0x1078, 0x5902, 0x0c7f, 0x0078, 0x56bb, 0x700f, 0x0000, 0x700b,
+	0x7836, 0x700c, 0x2060, 0x8cff, 0x0040, 0x56c5, 0x1078, 0x6ac3,
+	0x00c0, 0x56bc, 0x1078, 0x5e4d, 0x600c, 0x007e, 0x1078, 0x5bfa,
+	0x1078, 0x58fa, 0x0c7f, 0x0078, 0x56b3, 0x700f, 0x0000, 0x700b,
 	0x0000, 0x127f, 0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e,
 	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091,
 	0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x7836, 0x7024,
-	0x2060, 0x8cff, 0x0040, 0x5726, 0x1078, 0x5582, 0x68c3, 0x0000,
-	0x1078, 0x45eb, 0x2009, 0x0013, 0x1078, 0x5c29, 0x20a9, 0x01f4,
-	0x6824, 0xd094, 0x0040, 0x5709, 0x6827, 0x0004, 0x7804, 0xa084,
-	0x4000, 0x0040, 0x571b, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
-	0x571b, 0xd084, 0x0040, 0x5710, 0x6827, 0x0001, 0x0078, 0x5712,
-	0x00f0, 0x56f8, 0x7804, 0xa084, 0x1000, 0x0040, 0x571b, 0x7803,
+	0x2060, 0x8cff, 0x0040, 0x571e, 0x1078, 0x557a, 0x68c3, 0x0000,
+	0x1078, 0x45e3, 0x2009, 0x0013, 0x1078, 0x5c21, 0x20a9, 0x01f4,
+	0x6824, 0xd094, 0x0040, 0x5701, 0x6827, 0x0004, 0x7804, 0xa084,
+	0x4000, 0x0040, 0x5713, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078,
+	0x5713, 0xd084, 0x0040, 0x5708, 0x6827, 0x0001, 0x0078, 0x570a,
+	0x00f0, 0x56f0, 0x7804, 0xa084, 0x1000, 0x0040, 0x5713, 0x7803,
 	0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f,
 	0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0x7600,
-	0x2004, 0xa096, 0x0001, 0x0040, 0x575e, 0xa096, 0x0004, 0x0040,
-	0x575e, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x3542, 0x1078,
-	0x456e, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x574c, 0x6827,
-	0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x575e, 0x7803, 0x1000,
-	0x7803, 0x0000, 0x0078, 0x575e, 0xd084, 0x0040, 0x5753, 0x6827,
-	0x0001, 0x0078, 0x5755, 0x00f0, 0x573b, 0x7804, 0xa084, 0x1000,
-	0x0040, 0x575e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f,
+	0x2004, 0xa096, 0x0001, 0x0040, 0x5756, 0xa096, 0x0004, 0x0040,
+	0x5756, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x353a, 0x1078,
+	0x4566, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x5744, 0x6827,
+	0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x5756, 0x7803, 0x1000,
+	0x7803, 0x0000, 0x0078, 0x5756, 0xd084, 0x0040, 0x574b, 0x6827,
+	0x0001, 0x0078, 0x574d, 0x00f0, 0x5733, 0x7804, 0xa084, 0x1000,
+	0x0040, 0x5756, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f,
 	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
 	0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e,
 	0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
-	0x7836, 0x703c, 0x2060, 0x8cff, 0x0040, 0x57b6, 0x6817, 0x0010,
-	0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x45f9, 0x1078, 0x1c19,
-	0xa39d, 0x0000, 0x00c0, 0x5790, 0x2009, 0x0049, 0x1078, 0x5c29,
-	0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x57a3, 0x6827, 0x0004,
-	0x7804, 0xa084, 0x4000, 0x0040, 0x57b5, 0x7803, 0x1000, 0x7803,
-	0x0000, 0x0078, 0x57b5, 0xd094, 0x0040, 0x57aa, 0x6827, 0x0002,
-	0x0078, 0x57ac, 0x00f0, 0x5792, 0x7804, 0xa084, 0x1000, 0x0040,
-	0x57b5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f,
+	0x7836, 0x703c, 0x2060, 0x8cff, 0x0040, 0x57ae, 0x6817, 0x0010,
+	0x68cb, 0x0000, 0x68c7, 0x0000, 0x1078, 0x45f1, 0x1078, 0x1c13,
+	0xa39d, 0x0000, 0x00c0, 0x5788, 0x2009, 0x0049, 0x1078, 0x5c21,
+	0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x579b, 0x6827, 0x0004,
+	0x7804, 0xa084, 0x4000, 0x0040, 0x57ad, 0x7803, 0x1000, 0x7803,
+	0x0000, 0x0078, 0x57ad, 0xd094, 0x0040, 0x57a2, 0x6827, 0x0002,
+	0x0078, 0x57a4, 0x00f0, 0x578a, 0x7804, 0xa084, 0x1000, 0x0040,
+	0x57ad, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f,
 	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
 	0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7836, 0x6a06, 0x127f,
 	0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0x7836,
 	0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
 	0x007e, 0x127e, 0x2071, 0x7836, 0x7614, 0x2660, 0x2678, 0x2091,
-	0x8000, 0x8cff, 0x0040, 0x5814, 0x601c, 0xa206, 0x00c0, 0x580f,
-	0x7014, 0xac36, 0x00c0, 0x57ee, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x00c0, 0x57fc, 0x2c00, 0xaf36, 0x0040, 0x57fa, 0x2f00, 0x7012,
-	0x0078, 0x57fc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
-	0x0040, 0x5805, 0x7e0e, 0x0078, 0x5806, 0x2678, 0x600f, 0x0000,
-	0x1078, 0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, 0x57e1, 0x2c78,
-	0x600c, 0x2060, 0x0078, 0x57e1, 0x127f, 0x007f, 0x067f, 0x0c7f,
+	0x8000, 0x8cff, 0x0040, 0x580c, 0x601c, 0xa206, 0x00c0, 0x5807,
+	0x7014, 0xac36, 0x00c0, 0x57e6, 0x660c, 0x7616, 0x7010, 0xac36,
+	0x00c0, 0x57f4, 0x2c00, 0xaf36, 0x0040, 0x57f2, 0x2f00, 0x7012,
+	0x0078, 0x57f4, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
+	0x0040, 0x57fd, 0x7e0e, 0x0078, 0x57fe, 0x2678, 0x600f, 0x0000,
+	0x1078, 0x6a96, 0x1078, 0x58fa, 0x0c7f, 0x0078, 0x57d9, 0x2c78,
+	0x600c, 0x2060, 0x0078, 0x57d9, 0x127f, 0x007f, 0x067f, 0x0c7f,
 	0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
-	0x20a3, 0x4000, 0x0078, 0x585d, 0x157e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x20a3, 0x2000, 0x0078, 0x585d, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x585d, 0x157e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x5215, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x590d, 0x60c3,
-	0x0020, 0x1078, 0x556e, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e,
-	0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x5875,
-	0xd1bc, 0x00c0, 0x58bf, 0x0078, 0x58ff, 0x2009, 0x017f, 0x200b,
+	0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
+	0x20a3, 0x4000, 0x0078, 0x5855, 0x157e, 0x147e, 0x20a1, 0x020b,
+	0x1078, 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
+	0x20a2, 0x20a3, 0x2000, 0x0078, 0x5855, 0x157e, 0x147e, 0x20a1,
+	0x020b, 0x1078, 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
+	0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x5855, 0x157e, 0x147e,
+	0x20a1, 0x020b, 0x1078, 0x520d, 0x7810, 0x20a2, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x5905, 0x60c3,
+	0x0020, 0x1078, 0x5566, 0x147f, 0x157f, 0x007c, 0x127e, 0x0c7e,
+	0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0, 0x586d,
+	0xd1bc, 0x00c0, 0x58b7, 0x0078, 0x58f7, 0x2009, 0x017f, 0x200b,
 	0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9, 0x001e,
-	0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x58b6, 0x6020,
-	0xd0b4, 0x0040, 0x58b6, 0x6024, 0xd094, 0x00c0, 0x58b6, 0x2104,
-	0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x58b6, 0x00f0, 0x5882,
+	0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x58ae, 0x6020,
+	0xd0b4, 0x0040, 0x58ae, 0x6024, 0xd094, 0x00c0, 0x58ae, 0x2104,
+	0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x58ae, 0x00f0, 0x587a,
 	0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff,
 	0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043, 0x0001,
-	0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x58b5,
-	0x6a04, 0xa294, 0x4000, 0x00c0, 0x58ac, 0x027f, 0x0d7f, 0x007f,
-	0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x58ff, 0x2009,
+	0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0, 0x58ad,
+	0x6a04, 0xa294, 0x4000, 0x00c0, 0x58a4, 0x027f, 0x0d7f, 0x007f,
+	0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x58f7, 0x2009,
 	0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140,
 	0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040,
-	0x58f8, 0x6020, 0xd0bc, 0x0040, 0x58f8, 0x2104, 0xa084, 0x000f,
-	0xa086, 0x0004, 0x00c0, 0x58f8, 0x00f0, 0x58cc, 0x027e, 0x6164,
+	0x58f0, 0x6020, 0xd0bc, 0x0040, 0x58f0, 0x2104, 0xa084, 0x000f,
+	0xa086, 0x0004, 0x00c0, 0x58f0, 0x00f0, 0x58c4, 0x027e, 0x6164,
 	0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d, 0x6088,
 	0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043, 0x0000,
-	0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58f2, 0x027f,
+	0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x58ea, 0x027f,
 	0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0c7f,
 	0x127f, 0x007c, 0x0e7e, 0x2071, 0x7836, 0x7020, 0xa005, 0x0040,
-	0x590b, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2,
-	0x00f0, 0x590f, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
+	0x5903, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008, 0x20a2,
+	0x00f0, 0x5907, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e,
 	0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071,
 	0x7836, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0040,
-	0x59a5, 0x8cff, 0x0040, 0x59a5, 0x601c, 0xa086, 0x0006, 0x00c0,
-	0x59a0, 0x88ff, 0x0040, 0x593c, 0x2800, 0xac06, 0x00c0, 0x59a0,
-	0x2039, 0x0000, 0x0078, 0x5940, 0x6018, 0xa206, 0x00c0, 0x59a0,
-	0x7024, 0xac06, 0x00c0, 0x596e, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x5969, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x5a32,
+	0x599d, 0x8cff, 0x0040, 0x599d, 0x601c, 0xa086, 0x0006, 0x00c0,
+	0x5998, 0x88ff, 0x0040, 0x5934, 0x2800, 0xac06, 0x00c0, 0x5998,
+	0x2039, 0x0000, 0x0078, 0x5938, 0x6018, 0xa206, 0x00c0, 0x5998,
+	0x7024, 0xac06, 0x00c0, 0x5966, 0x2069, 0x0100, 0x68c0, 0xa005,
+	0x0040, 0x5961, 0x6817, 0x0008, 0x68c3, 0x0000, 0x1078, 0x5a2a,
 	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0040, 0x595e, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0040, 0x5966, 0x6827, 0x0001, 0x037f, 0x0078,
-	0x596e, 0x6003, 0x0009, 0x630a, 0x0078, 0x59a0, 0x7014, 0xac36,
-	0x00c0, 0x5974, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x5982,
-	0x2c00, 0xaf36, 0x0040, 0x5980, 0x2f00, 0x7012, 0x0078, 0x5982,
-	0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x598b,
-	0x7e0e, 0x0078, 0x598c, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
-	0x1078, 0x693e, 0x0040, 0x5996, 0x1078, 0x74fd, 0x1078, 0x6aa1,
-	0x1078, 0x5902, 0x88ff, 0x00c0, 0x59af, 0x0c7f, 0x0078, 0x5926,
-	0x2c78, 0x600c, 0x2060, 0x0078, 0x5926, 0xa006, 0x127f, 0x007f,
+	0x0040, 0x5956, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0040, 0x595e, 0x6827, 0x0001, 0x037f, 0x0078,
+	0x5966, 0x6003, 0x0009, 0x630a, 0x0078, 0x5998, 0x7014, 0xac36,
+	0x00c0, 0x596c, 0x660c, 0x7616, 0x7010, 0xac36, 0x00c0, 0x597a,
+	0x2c00, 0xaf36, 0x0040, 0x5978, 0x2f00, 0x7012, 0x0078, 0x597a,
+	0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5983,
+	0x7e0e, 0x0078, 0x5984, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068,
+	0x1078, 0x6938, 0x0040, 0x598e, 0x1078, 0x74f2, 0x1078, 0x6a96,
+	0x1078, 0x58fa, 0x88ff, 0x00c0, 0x59a7, 0x0c7f, 0x0078, 0x591e,
+	0x2c78, 0x600c, 0x2060, 0x0078, 0x591e, 0xa006, 0x127f, 0x007f,
 	0x067f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017,
-	0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x59a6, 0x0f7e, 0x0e7e,
+	0x0000, 0x0c7f, 0xa8c5, 0x0001, 0x0078, 0x599e, 0x0f7e, 0x0e7e,
 	0x0d7e, 0x0c7e, 0x067e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0x7836, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a21,
-	0x601c, 0xa086, 0x0006, 0x00c0, 0x5a1c, 0x88ff, 0x0040, 0x59d6,
-	0x2800, 0xac06, 0x00c0, 0x5a1c, 0x0078, 0x59da, 0x6018, 0xa206,
-	0x00c0, 0x5a1c, 0x703c, 0xac06, 0x00c0, 0x59ec, 0x037e, 0x2019,
-	0x0001, 0x1078, 0x5768, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043,
-	0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x59f2,
-	0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5a00, 0x2c00, 0xaf36,
-	0x0040, 0x59fe, 0x2f00, 0x7036, 0x0078, 0x5a00, 0x7037, 0x0000,
-	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5a09, 0x7e0e, 0x0078,
-	0x5a0a, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x693e,
-	0x0040, 0x5a14, 0x1078, 0x74fd, 0x1078, 0x6aa1, 0x88ff, 0x00c0,
-	0x5a2b, 0x0c7f, 0x0078, 0x59c5, 0x2c78, 0x600c, 0x2060, 0x0078,
-	0x59c5, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f,
+	0x2071, 0x7836, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a19,
+	0x601c, 0xa086, 0x0006, 0x00c0, 0x5a14, 0x88ff, 0x0040, 0x59ce,
+	0x2800, 0xac06, 0x00c0, 0x5a14, 0x0078, 0x59d2, 0x6018, 0xa206,
+	0x00c0, 0x5a14, 0x703c, 0xac06, 0x00c0, 0x59e4, 0x037e, 0x2019,
+	0x0001, 0x1078, 0x5760, 0x7033, 0x0000, 0x703f, 0x0000, 0x7043,
+	0x0000, 0x7047, 0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x59ea,
+	0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x59f8, 0x2c00, 0xaf36,
+	0x0040, 0x59f6, 0x2f00, 0x7036, 0x0078, 0x59f8, 0x7037, 0x0000,
+	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5a01, 0x7e0e, 0x0078,
+	0x5a02, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x6938,
+	0x0040, 0x5a0c, 0x1078, 0x74f2, 0x1078, 0x6a96, 0x88ff, 0x00c0,
+	0x5a23, 0x0c7f, 0x0078, 0x59bd, 0x2c78, 0x600c, 0x2060, 0x0078,
+	0x59bd, 0xa006, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f,
 	0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5, 0x0001,
-	0x0078, 0x5a22, 0x0e7e, 0x2071, 0x7836, 0x2001, 0x7600, 0x2004,
-	0xa086, 0x0002, 0x00c0, 0x5a40, 0x7007, 0x0005, 0x0078, 0x5a42,
+	0x0078, 0x5a1a, 0x0e7e, 0x2071, 0x7836, 0x2001, 0x7600, 0x2004,
+	0xa086, 0x0002, 0x00c0, 0x5a38, 0x7007, 0x0005, 0x0078, 0x5a3a,
 	0x7007, 0x0000, 0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
 	0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x2c10,
-	0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a82, 0x2200, 0xac06,
-	0x00c0, 0x5a7d, 0x7038, 0xac36, 0x00c0, 0x5a60, 0x660c, 0x763a,
-	0x7034, 0xac36, 0x00c0, 0x5a6e, 0x2c00, 0xaf36, 0x0040, 0x5a6c,
-	0x2f00, 0x7036, 0x0078, 0x5a6e, 0x7037, 0x0000, 0x660c, 0x2c00,
-	0xaf06, 0x0040, 0x5a76, 0x7e0e, 0x0078, 0x5a77, 0x2678, 0x600f,
-	0x0000, 0xa085, 0x0001, 0x0078, 0x5a82, 0x2c78, 0x600c, 0x2060,
-	0x0078, 0x5a53, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f,
+	0x7638, 0x2660, 0x2678, 0x8cff, 0x0040, 0x5a7a, 0x2200, 0xac06,
+	0x00c0, 0x5a75, 0x7038, 0xac36, 0x00c0, 0x5a58, 0x660c, 0x763a,
+	0x7034, 0xac36, 0x00c0, 0x5a66, 0x2c00, 0xaf36, 0x0040, 0x5a64,
+	0x2f00, 0x7036, 0x0078, 0x5a66, 0x7037, 0x0000, 0x660c, 0x2c00,
+	0xaf06, 0x0040, 0x5a6e, 0x7e0e, 0x0078, 0x5a6f, 0x2678, 0x600f,
+	0x0000, 0xa085, 0x0001, 0x0078, 0x5a7a, 0x2c78, 0x600c, 0x2060,
+	0x0078, 0x5a4b, 0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f,
 	0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e,
 	0x127e, 0x2091, 0x8000, 0x2071, 0x7836, 0x760c, 0x2660, 0x2678,
-	0x8cff, 0x0040, 0x5b1b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x00c0, 0x5b16, 0x7024, 0xac06, 0x00c0, 0x5ac9, 0x2069, 0x0100,
-	0x68c0, 0xa005, 0x0040, 0x5ac9, 0x1078, 0x5582, 0x68c3, 0x0000,
-	0x1078, 0x5a32, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
-	0xa384, 0x1000, 0x0040, 0x5ac0, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ac8, 0x6827, 0x0001,
-	0x037f, 0x700c, 0xac36, 0x00c0, 0x5acf, 0x660c, 0x760e, 0x7008,
-	0xac36, 0x00c0, 0x5add, 0x2c00, 0xaf36, 0x0040, 0x5adb, 0x2f00,
-	0x700a, 0x0078, 0x5add, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00,
-	0xaf06, 0x0040, 0x5ae6, 0x7e0e, 0x0078, 0x5ae7, 0x2678, 0x600f,
-	0x0000, 0x1078, 0x6aba, 0x00c0, 0x5af1, 0x1078, 0x22dd, 0x0078,
-	0x5b0d, 0x1078, 0x6ace, 0x00c0, 0x5af9, 0x1078, 0x5e57, 0x0078,
-	0x5b0d, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x5b0d, 0x601c,
-	0xa086, 0x0003, 0x00c0, 0x5b23, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x6003, 0x0000, 0x1078,
-	0x6aa1, 0x1078, 0x5902, 0x0c7f, 0x0078, 0x5a98, 0x2c78, 0x600c,
-	0x2060, 0x0078, 0x5a98, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5b04,
-	0x1078, 0x74fd, 0x0078, 0x5b0d, 0x037e, 0x157e, 0x137e, 0x147e,
-	0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x214f, 0x00c0,
-	0x5b3d, 0x8210, 0x8000, 0x0078, 0x5b34, 0xa005, 0x0040, 0x5b47,
+	0x8cff, 0x0040, 0x5b13, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
+	0x00c0, 0x5b0e, 0x7024, 0xac06, 0x00c0, 0x5ac1, 0x2069, 0x0100,
+	0x68c0, 0xa005, 0x0040, 0x5ac1, 0x1078, 0x557a, 0x68c3, 0x0000,
+	0x1078, 0x5a2a, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
+	0xa384, 0x1000, 0x0040, 0x5ab8, 0x6803, 0x0100, 0x6803, 0x0000,
+	0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x5ac0, 0x6827, 0x0001,
+	0x037f, 0x700c, 0xac36, 0x00c0, 0x5ac7, 0x660c, 0x760e, 0x7008,
+	0xac36, 0x00c0, 0x5ad5, 0x2c00, 0xaf36, 0x0040, 0x5ad3, 0x2f00,
+	0x700a, 0x0078, 0x5ad5, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00,
+	0xaf06, 0x0040, 0x5ade, 0x7e0e, 0x0078, 0x5adf, 0x2678, 0x600f,
+	0x0000, 0x1078, 0x6aaf, 0x00c0, 0x5ae9, 0x1078, 0x22d7, 0x0078,
+	0x5b05, 0x1078, 0x6ac3, 0x00c0, 0x5af1, 0x1078, 0x5e4d, 0x0078,
+	0x5b05, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x5b05, 0x601c,
+	0xa086, 0x0003, 0x00c0, 0x5b1b, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x6003, 0x0000, 0x1078,
+	0x6a96, 0x1078, 0x58fa, 0x0c7f, 0x0078, 0x5a90, 0x2c78, 0x600c,
+	0x2060, 0x0078, 0x5a90, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f,
+	0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x5afc,
+	0x1078, 0x74f2, 0x0078, 0x5b05, 0x037e, 0x157e, 0x137e, 0x147e,
+	0x3908, 0xa006, 0xa190, 0x0020, 0x221c, 0xa39e, 0x2149, 0x00c0,
+	0x5b35, 0x8210, 0x8000, 0x0078, 0x5b2c, 0xa005, 0x0040, 0x5b3f,
 	0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8, 0x53a3, 0x147f,
 	0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
-	0x5053, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
+	0x504b, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x514c, 0x20a3, 0x4f47, 0x20a3,
 	0x4943, 0x20a3, 0x2020, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x1078, 0x556e, 0x0d7f, 0x007c, 0x20a1,
-	0x020b, 0x1078, 0x5053, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x1078, 0x5566, 0x0d7f, 0x007c, 0x20a1,
+	0x020b, 0x1078, 0x504b, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3,
 	0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3,
 	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810,
 	0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0018, 0x1078, 0x556e, 0x007c, 0x2061, 0x7d00, 0x2a70, 0x7060,
+	0x0018, 0x1078, 0x5566, 0x007c, 0x2061, 0x7d00, 0x2a70, 0x7060,
 	0x7046, 0x704b, 0x7d00, 0x007c, 0x0e7e, 0x127e, 0x2071, 0x7600,
-	0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5bce, 0x7048,
-	0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bba, 0xace0, 0x0008,
-	0x7054, 0xac02, 0x00c8, 0x5bb6, 0x0078, 0x5ba9, 0x2061, 0x7d00,
-	0x0078, 0x5ba9, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008,
-	0x7054, 0xa502, 0x00c8, 0x5bca, 0x754a, 0xa085, 0x0001, 0x127f,
-	0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bc5, 0xa006, 0x0078,
-	0x5bc7, 0x0e7e, 0x2071, 0x7600, 0x7544, 0xa582, 0x0001, 0x0048,
-	0x5bff, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bec,
-	0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5be8, 0x0078, 0x5bdb,
-	0x2061, 0x7d00, 0x0078, 0x5bdb, 0x6003, 0x0008, 0x8529, 0x7546,
-	0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5bfb, 0x754a, 0xa085,
-	0x0001, 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bf7, 0xa006,
-	0x0078, 0x5bf9, 0xac82, 0x7d00, 0x1048, 0x12d5, 0x2001, 0x7615,
-	0x2004, 0xac02, 0x10c8, 0x12d5, 0xa006, 0x6006, 0x600a, 0x600e,
+	0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0048, 0x5bc6, 0x7048,
+	0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5bb2, 0xace0, 0x0008,
+	0x7054, 0xac02, 0x00c8, 0x5bae, 0x0078, 0x5ba1, 0x2061, 0x7d00,
+	0x0078, 0x5ba1, 0x6003, 0x0008, 0x8529, 0x7546, 0xaca8, 0x0008,
+	0x7054, 0xa502, 0x00c8, 0x5bc2, 0x754a, 0xa085, 0x0001, 0x127f,
+	0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bbd, 0xa006, 0x0078,
+	0x5bbf, 0x0e7e, 0x2071, 0x7600, 0x7544, 0xa582, 0x0001, 0x0048,
+	0x5bf7, 0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040, 0x5be4,
+	0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x5be0, 0x0078, 0x5bd3,
+	0x2061, 0x7d00, 0x0078, 0x5bd3, 0x6003, 0x0008, 0x8529, 0x7546,
+	0xaca8, 0x0008, 0x7054, 0xa502, 0x00c8, 0x5bf3, 0x754a, 0xa085,
+	0x0001, 0x0e7f, 0x007c, 0x704b, 0x7d00, 0x0078, 0x5bef, 0xa006,
+	0x0078, 0x5bf1, 0xac82, 0x7d00, 0x1048, 0x12cd, 0x2001, 0x7615,
+	0x2004, 0xac02, 0x10c8, 0x12cd, 0xa006, 0x6006, 0x600a, 0x600e,
 	0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x2061,
-	0x7600, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5c21,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x0078,
-	0x5c20, 0x601c, 0xa084, 0x000f, 0x0079, 0x5c2e, 0x5c37, 0x5c3f,
-	0x5c5b, 0x5c77, 0x6b4b, 0x6b67, 0x6b83, 0x5c37, 0x5c3f, 0xa18e,
-	0x0047, 0x00c0, 0x5c3e, 0xa016, 0x1078, 0x1572, 0x007c, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x5c49, 0x067f,
-	0x007c, 0x5c59, 0x5d40, 0x5e72, 0x5c59, 0x5ec9, 0x5c59, 0x5c59,
-	0x5c59, 0x5cef, 0x6182, 0x5c59, 0x5c59, 0x5c59, 0x5c59, 0x5c59,
-	0x5c59, 0x1078, 0x12d5, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x12d5, 0x1079, 0x5c65, 0x067f, 0x007c, 0x5c75, 0x5c75, 0x5c75,
-	0x5c75, 0x5c75, 0x5c75, 0x5c75, 0x5c75, 0x65f2, 0x66b8, 0x5c75,
-	0x660b, 0x6664, 0x660b, 0x6664, 0x5c75, 0x1078, 0x12d5, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x5c81, 0x067f,
-	0x007c, 0x5c91, 0x61c0, 0x6266, 0x6328, 0x647c, 0x5c91, 0x5c91,
-	0x5c91, 0x619e, 0x65a7, 0x65ab, 0x5c91, 0x5c91, 0x5c91, 0x5c91,
-	0x65d1, 0x1078, 0x12d5, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0,
+	0x7600, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0040, 0x5c19,
+	0x007c, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, 0x0078,
+	0x5c18, 0x601c, 0xa084, 0x000f, 0x0079, 0x5c26, 0x5c2f, 0x5c37,
+	0x5c53, 0x5c6f, 0x6b40, 0x6b5c, 0x6b78, 0x5c2f, 0x5c37, 0xa18e,
+	0x0047, 0x00c0, 0x5c36, 0xa016, 0x1078, 0x156a, 0x007c, 0x067e,
+	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x5c41, 0x067f,
+	0x007c, 0x5c51, 0x5d38, 0x5e68, 0x5c51, 0x5ebf, 0x5c51, 0x5c51,
+	0x5c51, 0x5ce7, 0x6178, 0x5c51, 0x5c51, 0x5c51, 0x5c51, 0x5c51,
+	0x5c51, 0x1078, 0x12cd, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
+	0x12cd, 0x1079, 0x5c5d, 0x067f, 0x007c, 0x5c6d, 0x5c6d, 0x5c6d,
+	0x5c6d, 0x5c6d, 0x5c6d, 0x5c6d, 0x5c6d, 0x65ec, 0x66b2, 0x5c6d,
+	0x6605, 0x665e, 0x6605, 0x665e, 0x5c6d, 0x1078, 0x12cd, 0x067e,
+	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x5c79, 0x067f,
+	0x007c, 0x5c89, 0x61b6, 0x625c, 0x631e, 0x6476, 0x5c89, 0x5c89,
+	0x5c89, 0x6194, 0x65a1, 0x65a5, 0x5c89, 0x5c89, 0x5c89, 0x5c89,
+	0x65cb, 0x1078, 0x12cd, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0,
 	0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318,
 	0x3428, 0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398,
-	0x0002, 0xa4a0, 0x0002, 0x00f0, 0x5ca1, 0x0e7e, 0x1078, 0x693e,
-	0x0040, 0x5cb8, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
-	0x0e7f, 0x1078, 0x5c02, 0x007c, 0x0d7e, 0x037e, 0x7330, 0xa386,
-	0x0200, 0x00c0, 0x5cc9, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817,
-	0xfffd, 0x6010, 0xa005, 0x0040, 0x5cd3, 0x2068, 0x6807, 0x0000,
-	0x6837, 0x0103, 0x6b32, 0x1078, 0x5c02, 0x037f, 0x0d7f, 0x007c,
+	0x0002, 0xa4a0, 0x0002, 0x00f0, 0x5c99, 0x0e7e, 0x1078, 0x6938,
+	0x0040, 0x5cb0, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
+	0x0e7f, 0x1078, 0x5bfa, 0x007c, 0x0d7e, 0x037e, 0x7330, 0xa386,
+	0x0200, 0x00c0, 0x5cc1, 0x6018, 0x2068, 0x6813, 0x00ff, 0x6817,
+	0xfffd, 0x6010, 0xa005, 0x0040, 0x5ccb, 0x2068, 0x6807, 0x0000,
+	0x6837, 0x0103, 0x6b32, 0x1078, 0x5bfa, 0x037f, 0x0d7f, 0x007c,
 	0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6,
-	0x0015, 0x00c0, 0x5cec, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c,
-	0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x5cad, 0x2100,
-	0xa1b2, 0x0030, 0x10c8, 0x12d5, 0x0079, 0x5cf6, 0x5d28, 0x5d34,
-	0x5d28, 0x5d28, 0x5d28, 0x5d28, 0x5d26, 0x5d26, 0x5d26, 0x5d26,
-	0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26,
-	0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26,
-	0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d28, 0x5d26, 0x5d28,
-	0x5d28, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d28, 0x5d26,
-	0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x5d26, 0x1078, 0x12d5,
-	0x6003, 0x0001, 0x6106, 0x1078, 0x4872, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x4c7a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x4872, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c,
-	0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12d5, 0xa1b6, 0x0013, 0x00c0,
-	0x5d4c, 0x2008, 0x0079, 0x5dd5, 0xa1b6, 0x0027, 0x00c0, 0x5da2,
-	0x1078, 0x4b81, 0x6004, 0x1078, 0x6aba, 0x0040, 0x5d65, 0x1078,
-	0x6ace, 0x0040, 0x5d9a, 0xa08e, 0x0021, 0x0040, 0x5d9e, 0xa08e,
-	0x0022, 0x0040, 0x5d9a, 0x0078, 0x5d95, 0x1078, 0x22dd, 0x2001,
-	0x0007, 0x1078, 0x37d1, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078,
-	0x5e57, 0xa186, 0x007e, 0x00c0, 0x5d7b, 0x2001, 0x762f, 0x2014,
-	0xa295, 0x0001, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019,
-	0x0028, 0x1078, 0x4962, 0x1078, 0x48a5, 0x0c7e, 0x6018, 0xa065,
-	0x0040, 0x5d8c, 0x1078, 0x39a6, 0x0c7f, 0x2c08, 0x1078, 0x737b,
-	0x037f, 0x027f, 0x017f, 0x1078, 0x380d, 0x1078, 0x5c02, 0x1078,
-	0x4c7a, 0x007c, 0x1078, 0x5e57, 0x0078, 0x5d95, 0x1078, 0x5e66,
-	0x0078, 0x5d95, 0xa186, 0x0014, 0x00c0, 0x5d99, 0x1078, 0x4b81,
-	0x1078, 0x22bb, 0x1078, 0x6aba, 0x00c0, 0x5dc2, 0x1078, 0x22dd,
-	0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x5e57, 0xa186, 0x007e,
-	0x00c0, 0x5dc0, 0x2001, 0x762f, 0x200c, 0xa18d, 0x0001, 0x2102,
-	0x0078, 0x5d95, 0x1078, 0x6ace, 0x00c0, 0x5dca, 0x1078, 0x5e57,
-	0x0078, 0x5d95, 0x6004, 0xa08e, 0x0021, 0x0040, 0x5dc6, 0xa08e,
-	0x0022, 0x1040, 0x5e66, 0x0078, 0x5d95, 0x5e07, 0x5e09, 0x5e0d,
-	0x5e11, 0x5e15, 0x5e19, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05,
-	0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05,
-	0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05,
-	0x5e05, 0x5e05, 0x5e05, 0x5e1d, 0x5e23, 0x5e05, 0x5e2d, 0x5e23,
-	0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e23, 0x5e23, 0x5e05,
-	0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x5e05, 0x1078, 0x12d5, 0x0078,
-	0x5e23, 0x2001, 0x000b, 0x0078, 0x5e36, 0x2001, 0x0003, 0x0078,
-	0x5e36, 0x2001, 0x0005, 0x0078, 0x5e36, 0x2001, 0x0001, 0x0078,
-	0x5e36, 0x2001, 0x0009, 0x0078, 0x5e36, 0x1078, 0x12d5, 0x0078,
-	0x5e35, 0x1078, 0x37d1, 0x1078, 0x4b81, 0x6003, 0x0002, 0x6017,
-	0x0028, 0x1078, 0x4c7a, 0x0078, 0x5e35, 0x1078, 0x4b81, 0x6003,
-	0x0004, 0x6017, 0x0028, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x37d1,
-	0x1078, 0x4b81, 0x6003, 0x0002, 0x037e, 0x2019, 0x765c, 0x2304,
-	0xa084, 0xff00, 0x00c0, 0x5e48, 0x2019, 0x0028, 0x0078, 0x5e51,
-	0x8007, 0xa09a, 0x0004, 0x0048, 0x5e44, 0x8003, 0x801b, 0x831b,
-	0xa318, 0x6316, 0x037f, 0x1078, 0x4c7a, 0x0078, 0x5e35, 0x0e7e,
-	0x1078, 0x693e, 0x0040, 0x5e64, 0x6010, 0x2070, 0x7007, 0x0000,
-	0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f, 0x007c, 0x0e7e, 0xacf0,
-	0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001,
-	0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff,
-	0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12d5, 0x6604, 0xa6b6, 0x0028,
-	0x00c0, 0x5e86, 0x1078, 0x6b03, 0x0078, 0x5eb8, 0x6604, 0xa6b6,
-	0x0029, 0x00c0, 0x5e8f, 0x1078, 0x6b1d, 0x0078, 0x5eb8, 0x6604,
-	0xa6b6, 0x001f, 0x00c0, 0x5e98, 0x1078, 0x5c93, 0x0078, 0x5eb8,
-	0x6604, 0xa6b6, 0x0000, 0x00c0, 0x5ea1, 0x1078, 0x5cd8, 0x0078,
-	0x5eb8, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x5eaa, 0x1078, 0x5cbc,
-	0x0078, 0x5eb8, 0xa1b6, 0x0015, 0x00c0, 0x5eb2, 0x1079, 0x5ebd,
-	0x0078, 0x5eb8, 0xa1b6, 0x0016, 0x00c0, 0x5eb9, 0x1079, 0x5ffa,
-	0x007c, 0x1078, 0x5c37, 0x0078, 0x5eb8, 0x5ee1, 0x5ee4, 0x5ee1,
-	0x5f25, 0x5ee1, 0x5f96, 0x5ee1, 0x5ee1, 0x5ee1, 0x5fd2, 0x5ee1,
-	0x5fe8, 0xa1b6, 0x0048, 0x0040, 0x5ed5, 0x20e1, 0x0005, 0x3d18,
-	0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, 0x0e7e, 0xacf0, 0x0004,
-	0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x5c02,
-	0x007c, 0x0005, 0x0005, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078,
-	0xa086, 0x0074, 0x00c0, 0x5f0e, 0x1078, 0x734f, 0x00c0, 0x5f00,
-	0x0d7e, 0x6018, 0x2068, 0x1078, 0x5f12, 0x0d7f, 0x2001, 0x0006,
-	0x1078, 0x37d1, 0x1078, 0x22dd, 0x1078, 0x5c02, 0x0078, 0x5f10,
-	0x2001, 0x000a, 0x1078, 0x37d1, 0x1078, 0x22dd, 0x6003, 0x0001,
-	0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x5f10, 0x1078, 0x5f86,
-	0x0e7f, 0x007c, 0x6800, 0xd084, 0x0040, 0x5f24, 0x2001, 0x0000,
-	0x1078, 0x37bd, 0x2069, 0x7651, 0x6804, 0xd0a4, 0x0040, 0x5f24,
-	0x2001, 0x0006, 0x1078, 0x37df, 0x007c, 0x0d7e, 0x2011, 0x761e,
-	0x2204, 0xa086, 0x0074, 0x00c0, 0x5f82, 0x1078, 0x60d4, 0x6018,
-	0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5f4d,
-	0xa286, 0x0080, 0x00c0, 0x5f76, 0x6813, 0x00ff, 0x6817, 0xfffc,
-	0x6010, 0xa005, 0x0040, 0x5f6c, 0x2068, 0x6807, 0x0000, 0x6837,
-	0x0103, 0x6833, 0x0200, 0x0078, 0x5f6c, 0x0e7e, 0x0f7e, 0x6813,
-	0x00ff, 0x6817, 0xfffe, 0x2071, 0x762f, 0x2e04, 0xa085, 0x0003,
-	0x2072, 0x2071, 0x7b80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff,
-	0x2069, 0x7619, 0x206a, 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x761a,
-	0x206a, 0x78ea, 0x0f7f, 0x0e7f, 0x2001, 0x0006, 0x1078, 0x37d1,
-	0x1078, 0x22dd, 0x1078, 0x5c02, 0x0078, 0x5f84, 0x2001, 0x0004,
-	0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x4872,
-	0x0078, 0x5f84, 0x1078, 0x5f86, 0x0d7f, 0x007c, 0x2001, 0x7600,
-	0x2004, 0xa086, 0x0003, 0x0040, 0x5f91, 0x2001, 0x0007, 0x1078,
-	0x37d1, 0x1078, 0x22dd, 0x1078, 0x5c02, 0x007c, 0x0e7e, 0x2071,
-	0x7600, 0x7078, 0xa086, 0x0014, 0x00c0, 0x5fcc, 0x7000, 0xa086,
-	0x0003, 0x00c0, 0x5fa9, 0x6010, 0xa005, 0x00c0, 0x5fa9, 0x1078,
-	0x2dc8, 0x0d7e, 0x6018, 0x2068, 0x1078, 0x38a1, 0x1078, 0x5f12,
-	0x0d7f, 0x1078, 0x60de, 0x00c0, 0x5fcc, 0x2001, 0x0006, 0x1078,
-	0x37d1, 0x0e7e, 0x6010, 0xa005, 0x0040, 0x5fc5, 0x2070, 0x7007,
-	0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078, 0x22dd,
-	0x1078, 0x5c02, 0x0078, 0x5fd0, 0x1078, 0x5e57, 0x1078, 0x5f86,
-	0x0e7f, 0x007c, 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0,
-	0x5fe5, 0x2001, 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007,
-	0x0001, 0x1078, 0x4872, 0x0078, 0x5fe7, 0x1078, 0x5f86, 0x007c,
-	0x2011, 0x761e, 0x2204, 0xa086, 0x0004, 0x00c0, 0x5ff7, 0x2001,
-	0x0007, 0x1078, 0x37d1, 0x1078, 0x5c02, 0x0078, 0x5ff9, 0x1078,
-	0x5f86, 0x007c, 0x5ee1, 0x6006, 0x5ee1, 0x602c, 0x5ee1, 0x6087,
-	0x5ee1, 0x5ee1, 0x5ee1, 0x609c, 0x5ee1, 0x60af, 0x0c7e, 0x1078,
-	0x60c2, 0x00c0, 0x601b, 0x2001, 0x0000, 0x1078, 0x37bd, 0x2001,
-	0x0002, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
-	0x4872, 0x0078, 0x602a, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00,
-	0xa086, 0x1900, 0x00c0, 0x6028, 0x1078, 0x5c02, 0x0078, 0x602a,
-	0x1078, 0x5f86, 0x0c7f, 0x007c, 0x1078, 0x60d1, 0x00c0, 0x6040,
-	0x2001, 0x0000, 0x1078, 0x37bd, 0x2001, 0x0002, 0x1078, 0x37d1,
-	0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4872, 0x0078, 0x6062,
-	0x1078, 0x5e57, 0x2009, 0x7b8e, 0x2134, 0xa6b4, 0x00ff, 0xa686,
-	0x0005, 0x0040, 0x6063, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00,
-	0xa086, 0x1900, 0x00c0, 0x6060, 0xa686, 0x0009, 0x0040, 0x6063,
-	0x2001, 0x0004, 0x1078, 0x37d1, 0x1078, 0x5c02, 0x0078, 0x6062,
-	0x1078, 0x5f86, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e,
-	0x0040, 0x6071, 0x6838, 0xd0fc, 0x0040, 0x6071, 0x0d7f, 0x0078,
-	0x6060, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040,
-	0x6082, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f,
-	0x0078, 0x6062, 0x1078, 0x22bb, 0x0d7f, 0x0078, 0x6060, 0x1078,
-	0x60d1, 0x00c0, 0x6097, 0x2001, 0x0004, 0x1078, 0x37d1, 0x6003,
-	0x0001, 0x6007, 0x0003, 0x1078, 0x4872, 0x0078, 0x609b, 0x1078,
-	0x5e57, 0x1078, 0x5f86, 0x007c, 0x1078, 0x60d1, 0x00c0, 0x60ac,
-	0x2001, 0x0008, 0x1078, 0x37d1, 0x6003, 0x0001, 0x6007, 0x0005,
-	0x1078, 0x4872, 0x0078, 0x60ae, 0x1078, 0x5f86, 0x007c, 0x1078,
-	0x60d1, 0x00c0, 0x60bf, 0x2001, 0x000a, 0x1078, 0x37d1, 0x6003,
-	0x0001, 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x60c1, 0x1078,
-	0x5f86, 0x007c, 0x2009, 0x7b8e, 0x2104, 0xa086, 0x0003, 0x00c0,
-	0x60d0, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00,
-	0x007c, 0xa085, 0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006,
-	0x2164, 0x1078, 0x3837, 0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071,
-	0x7b8c, 0x7004, 0xa086, 0x0014, 0x00c0, 0x6101, 0x7008, 0xa086,
-	0x0800, 0x00c0, 0x6101, 0x700c, 0xd0ec, 0x0040, 0x60ff, 0xa084,
-	0x0f00, 0xa086, 0x0100, 0x00c0, 0x60ff, 0x7024, 0xd0a4, 0x0040,
-	0x60ff, 0xd08c, 0x0040, 0x60ff, 0xa006, 0x0078, 0x6101, 0xa085,
-	0x0001, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e,
-	0x047e, 0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f,
-	0x252c, 0x2021, 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600,
-	0x7244, 0x7060, 0xa202, 0x00c8, 0x6158, 0x1078, 0x7559, 0x0040,
-	0x6150, 0x671c, 0xa786, 0x0001, 0x0040, 0x6150, 0xa786, 0x0007,
-	0x0040, 0x6150, 0x2500, 0xac06, 0x0040, 0x6150, 0x2400, 0xac06,
-	0x0040, 0x6150, 0x0c7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x613a,
-	0x1078, 0x1676, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x614d,
-	0xa786, 0x0003, 0x00c0, 0x6162, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x1078, 0x6aa1, 0x0c7f,
-	0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x6158, 0x0078, 0x6118,
-	0x127f, 0x007f, 0x027f, 0x047f, 0x057f, 0x077f, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x007c, 0xa786, 0x0006, 0x00c0, 0x6144, 0x1078, 0x74fd,
-	0x0078, 0x614d, 0x220c, 0x2304, 0xa106, 0x00c0, 0x6175, 0x8210,
-	0x8318, 0x00f0, 0x616a, 0xa006, 0x007c, 0x2304, 0xa102, 0x0048,
-	0x617d, 0x2001, 0x0001, 0x0078, 0x617f, 0x2001, 0x0000, 0xa18d,
-	0x0001, 0x007c, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5, 0x1078,
-	0x6aba, 0x0040, 0x6191, 0x1078, 0x6ace, 0x0040, 0x619a, 0x0078,
-	0x6193, 0x1078, 0x22dd, 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078,
-	0x4c7a, 0x007c, 0x1078, 0x5e57, 0x0078, 0x6193, 0xa182, 0x0040,
-	0x0079, 0x61a2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2,
-	0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b2, 0x61b4, 0x61b4, 0x61b4,
-	0x61b4, 0x61b2, 0x1078, 0x12d5, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x4825, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c,
-	0xa186, 0x0013, 0x00c0, 0x61c9, 0x6004, 0xa082, 0x0040, 0x0079,
-	0x623f, 0xa186, 0x0027, 0x00c0, 0x61e6, 0x1078, 0x4b81, 0x1078,
-	0x22bb, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, 0x0040, 0x61e0,
-	0x6837, 0x0103, 0x684b, 0x0029, 0x1078, 0x3a7a, 0x1078, 0x6a94,
-	0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0xa186, 0x0014,
-	0x00c0, 0x61ef, 0x6004, 0xa082, 0x0040, 0x0079, 0x620f, 0xa186,
-	0x0047, 0x10c0, 0x12d5, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040,
-	0x620c, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078,
-	0x46e6, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002,
-	0x00c0, 0x620c, 0x0078, 0x6266, 0x1078, 0x5c37, 0x007c, 0x6221,
-	0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f, 0x621f,
-	0x621f, 0x621f, 0x6238, 0x6238, 0x6238, 0x6238, 0x621f, 0x1078,
-	0x12d5, 0x1078, 0x4b81, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e,
-	0x0040, 0x6232, 0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x3a7a,
-	0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c,
-	0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x6251,
-	0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f, 0x624f,
-	0x624f, 0x624f, 0x625f, 0x625f, 0x625f, 0x625f, 0x624f, 0x1078,
-	0x12d5, 0x1078, 0x4b81, 0x6003, 0x0002, 0x1078, 0x4c7a, 0x6010,
-	0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078,
-	0x4b81, 0x6003, 0x000f, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x626a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627c,
-	0x6305, 0x631d, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a, 0x627a,
-	0x627a, 0x627a, 0x1078, 0x12d5, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c,
-	0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x62e9,
-	0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x62ae, 0xa186, 0x0028,
-	0x00c0, 0x6298, 0x1078, 0x6aa8, 0x684b, 0x001c, 0x0078, 0x62b0,
-	0xd6dc, 0x0040, 0x62a3, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c,
-	0x6b5e, 0x0078, 0x62b0, 0xd6d4, 0x0040, 0x62ae, 0x684b, 0x0007,
-	0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x62b0, 0x684b, 0x0000,
-	0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x62c3, 0x7328,
-	0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019,
-	0x1078, 0x6727, 0x037f, 0xd6cc, 0x0040, 0x62f9, 0x7124, 0x695a,
-	0xa192, 0x0021, 0x00c8, 0x62d7, 0x2071, 0x7b98, 0x831c, 0x2300,
-	0xae18, 0xad90, 0x001d, 0x1078, 0x6727, 0x0078, 0x62f9, 0x6838,
-	0xd0fc, 0x0040, 0x62e0, 0x2009, 0x0020, 0x695a, 0x0078, 0x62cc,
-	0x0f7e, 0x2d78, 0x1078, 0x66bf, 0x0f7f, 0x1078, 0x6714, 0x0078,
-	0x62fb, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac,
-	0x0040, 0x62f9, 0x6810, 0x6914, 0xa115, 0x0040, 0x62f9, 0x1078,
-	0x646d, 0x1078, 0x3a7a, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
-	0x0d7f, 0x0e7f, 0x1078, 0x5c02, 0x007c, 0x0f7e, 0x6003, 0x0003,
-	0x2079, 0x7b8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
-	0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19cf,
-	0x1078, 0x4891, 0x1078, 0x4d3a, 0x007c, 0x6003, 0x0004, 0x6110,
-	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c,
-	0xa182, 0x0040, 0x0079, 0x632c, 0x633c, 0x633c, 0x633c, 0x633c,
-	0x633c, 0x633e, 0x63d5, 0x633c, 0x633c, 0x63eb, 0x644d, 0x633c,
-	0x633c, 0x633c, 0x633c, 0x6454, 0x1078, 0x12d5, 0x077e, 0x0f7e,
-	0x0e7e, 0x0d7e, 0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4,
-	0x0fff, 0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c,
-	0x8211, 0x6a3e, 0x86ff, 0x0040, 0x63d0, 0xa694, 0xff00, 0xa284,
-	0x0c00, 0x0040, 0x635f, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284,
-	0x0300, 0x0040, 0x63d0, 0x1078, 0x132f, 0x1040, 0x12d5, 0x2d00,
-	0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a,
-	0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186,
-	0x0002, 0x0040, 0x6399, 0xa186, 0x0028, 0x00c0, 0x6383, 0x684b,
-	0x001c, 0x0078, 0x639b, 0xd6dc, 0x0040, 0x638e, 0x684b, 0x0015,
-	0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x639b, 0xd6d4, 0x0040,
-	0x6399, 0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078,
-	0x639b, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856,
-	0xa01e, 0xd6c4, 0x0040, 0x63b0, 0x7328, 0x732c, 0x6b56, 0x037e,
-	0x2308, 0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6727, 0x037f,
-	0xd6cc, 0x0040, 0x63d0, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8,
-	0x63c4, 0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d,
-	0x1078, 0x6727, 0x0078, 0x63d0, 0x7838, 0xd0fc, 0x0040, 0x63cd,
-	0x2009, 0x0020, 0x695a, 0x0078, 0x63b9, 0x2d78, 0x1078, 0x66bf,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003,
-	0x2079, 0x7b8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078,
-	0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19cf,
-	0x1078, 0x5567, 0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, 0x4c29,
-	0x1078, 0x4d3a, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x644b,
-	0xd1cc, 0x0040, 0x6426, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x641e,
-	0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198,
-	0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318,
-	0x8210, 0x00f0, 0x640d, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e,
-	0x017f, 0x2168, 0x1078, 0x1358, 0x0078, 0x6449, 0x017e, 0x1078,
-	0x1358, 0x0d7f, 0x1078, 0x6714, 0x0078, 0x6449, 0x6837, 0x0103,
-	0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x6445, 0xa086,
-	0x0028, 0x00c0, 0x6437, 0x684b, 0x001c, 0x0078, 0x6447, 0xd1dc,
-	0x0040, 0x643e, 0x684b, 0x0015, 0x0078, 0x6447, 0xd1d4, 0x0040,
-	0x6445, 0x684b, 0x0007, 0x0078, 0x6447, 0x684b, 0x0000, 0x1078,
-	0x3a7a, 0x1078, 0x5c02, 0x0d7f, 0x007c, 0x6003, 0x0002, 0x1078,
-	0x4c29, 0x1078, 0x4d3a, 0x007c, 0x1078, 0x4c29, 0x1078, 0x22bb,
-	0x0d7e, 0x6110, 0x2168, 0x1078, 0x693e, 0x0040, 0x6467, 0x6837,
-	0x0103, 0x684b, 0x0029, 0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f,
-	0x1078, 0x5c02, 0x1078, 0x4d3a, 0x007c, 0x684b, 0x0015, 0xd1fc,
-	0x0040, 0x6479, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189,
-	0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040, 0x0079, 0x6480,
-	0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6492, 0x6490, 0x6536,
-	0x653e, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490, 0x6490,
-	0x1078, 0x12d5, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c,
-	0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c, 0xc7e5,
-	0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x86ff, 0x0040,
-	0x6528, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040, 0x64b3, 0x7018,
-	0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040, 0x6525, 0x1078,
-	0x132f, 0x1040, 0x12d5, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200,
-	0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840,
-	0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040, 0x64ee,
-	0xa186, 0x0028, 0x00c0, 0x64d8, 0x684b, 0x001c, 0x0078, 0x64f0,
-	0xd6dc, 0x0040, 0x64e3, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c,
-	0x6b5e, 0x0078, 0x64f0, 0xd6d4, 0x0040, 0x64ee, 0x684b, 0x0007,
-	0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64f0, 0x684b, 0x0000,
-	0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0040,
-	0x6505, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019, 0x7b98,
-	0xad90, 0x0019, 0x1078, 0x6727, 0x037f, 0xd6cc, 0x0040, 0x6525,
-	0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x6519, 0x2071, 0x7b98,
-	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x6727, 0x0078,
-	0x6525, 0x7838, 0xd0fc, 0x0040, 0x6522, 0x2009, 0x0020, 0x695a,
-	0x0078, 0x650e, 0x2d78, 0x1078, 0x66bf, 0xd6dc, 0x00c0, 0x652b,
-	0xa006, 0x0078, 0x652f, 0x2001, 0x0001, 0x7218, 0x731c, 0x1078,
-	0x15b6, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c, 0x20e1, 0x0005,
-	0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x007c, 0x0d7e, 0x6003,
-	0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x65a5, 0xd1cc,
-	0x0040, 0x6575, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x656d, 0x017e,
-	0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d,
-	0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210,
-	0x00f0, 0x655c, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f,
-	0x2168, 0x1078, 0x1358, 0x0078, 0x65a3, 0x017e, 0x1078, 0x1358,
-	0x0d7f, 0x1078, 0x6714, 0x0078, 0x65a3, 0x6837, 0x0103, 0x6944,
-	0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x6594, 0xa086, 0x0028,
-	0x00c0, 0x6586, 0x684b, 0x001c, 0x0078, 0x65a1, 0xd1dc, 0x0040,
-	0x658d, 0x684b, 0x0015, 0x0078, 0x65a1, 0xd1d4, 0x0040, 0x6594,
-	0x684b, 0x0007, 0x0078, 0x65a1, 0x684b, 0x0000, 0x684c, 0xd0ac,
-	0x0040, 0x65a1, 0x6810, 0x6914, 0xa115, 0x0040, 0x65a1, 0x1078,
-	0x646d, 0x1078, 0x3a7a, 0x1078, 0x5c02, 0x0d7f, 0x007c, 0x1078,
-	0x4b81, 0x0078, 0x65ad, 0x1078, 0x4c29, 0x1078, 0x693e, 0x0040,
-	0x65c4, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x760c,
-	0x210c, 0xd18c, 0x00c0, 0x65cd, 0xd184, 0x00c0, 0x65c9, 0x6108,
-	0x694a, 0x1078, 0x3a7a, 0x0d7f, 0x1078, 0x5c02, 0x1078, 0x4c7a,
-	0x007c, 0x684b, 0x0004, 0x0078, 0x65c1, 0x684b, 0x0004, 0x0078,
-	0x65c1, 0xa182, 0x0040, 0x0079, 0x65d5, 0x65e5, 0x65e5, 0x65e5,
-	0x65e5, 0x65e5, 0x65e7, 0x65e5, 0x65ea, 0x65e5, 0x65e5, 0x65e5,
-	0x65e5, 0x65e5, 0x65e5, 0x65e5, 0x65e5, 0x1078, 0x12d5, 0x1078,
-	0x5c02, 0x007c, 0x007e, 0x027e, 0xa016, 0x1078, 0x1572, 0x027f,
-	0x007f, 0x007c, 0xa182, 0x0085, 0x0079, 0x65f6, 0x65ff, 0x65fd,
-	0x65fd, 0x65fd, 0x65fd, 0x65fd, 0x65fd, 0x1078, 0x12d5, 0x6003,
-	0x0001, 0x6106, 0x1078, 0x4825, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x4c7a, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x6615, 0x6004,
-	0xa082, 0x0085, 0x2008, 0x0079, 0x6649, 0xa186, 0x0027, 0x00c0,
-	0x6636, 0x1078, 0x4b81, 0x1078, 0x22bb, 0x0d7e, 0x6010, 0x2068,
-	0x1078, 0x693e, 0x0040, 0x662c, 0x6837, 0x0103, 0x684b, 0x0029,
-	0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x1078,
-	0x4c7a, 0x007c, 0x1078, 0x5c37, 0x0078, 0x6631, 0xa186, 0x0014,
-	0x00c0, 0x6632, 0x1078, 0x4b81, 0x0d7e, 0x6010, 0x2068, 0x1078,
-	0x693e, 0x0040, 0x662c, 0x6837, 0x0103, 0x684b, 0x0006, 0x0078,
-	0x6628, 0x6652, 0x6650, 0x6650, 0x6650, 0x6650, 0x6650, 0x665b,
-	0x1078, 0x12d5, 0x1078, 0x4b81, 0x6017, 0x0014, 0x6003, 0x000c,
-	0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x6017, 0x0014, 0x6003,
-	0x000e, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x008c, 0x00c8, 0x666e,
-	0xa182, 0x0085, 0x0048, 0x666e, 0x0079, 0x6671, 0x1078, 0x5c37,
-	0x007c, 0x6678, 0x6678, 0x6678, 0x6678, 0x667a, 0x6699, 0x6678,
-	0x1078, 0x12d5, 0x0d7e, 0x1078, 0x6a94, 0x1078, 0x693e, 0x0040,
-	0x6695, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040,
-	0x668d, 0x684b, 0x0006, 0x0078, 0x6691, 0x684b, 0x0005, 0x1078,
-	0x6b47, 0x6847, 0x0000, 0x1078, 0x3a7a, 0x1078, 0x5c02, 0x0d7f,
-	0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x66b4,
-	0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x66aa, 0x684b, 0x0006,
-	0x0078, 0x66ae, 0x684b, 0x0005, 0x1078, 0x6b47, 0x6847, 0x0000,
-	0x1078, 0x3a7a, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x5c02, 0x007c,
-	0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x057e,
-	0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182, 0x0101, 0x00c8,
-	0x66cb, 0x0078, 0x66cd, 0x2009, 0x0100, 0x2130, 0x2069, 0x7b98,
-	0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90, 0x001d, 0x1078,
-	0x6727, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040, 0x66e1, 0x1078,
-	0x1358, 0x1078, 0x132f, 0x0040, 0x670b, 0x8528, 0x6837, 0x0110,
-	0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x00c8, 0x66f7,
-	0x2608, 0xad90, 0x000f, 0x1078, 0x6727, 0x0078, 0x670b, 0xa6b2,
-	0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, 0x1078, 0x6727,
-	0x0078, 0x66e1, 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac,
-	0x0000, 0x0078, 0x6710, 0x0f7f, 0x852f, 0xa5ad, 0x0003, 0x7d36,
-	0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff, 0x0040, 0x6725,
-	0x6804, 0xa07d, 0x0040, 0x6723, 0x6807, 0x0000, 0x1078, 0x3a7a,
-	0x2f68, 0x0078, 0x6718, 0x1078, 0x3a7a, 0x0f7f, 0x007c, 0x157e,
-	0xa184, 0x0001, 0x0040, 0x672d, 0x8108, 0x810c, 0x21a8, 0x2304,
-	0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x672f, 0x157f, 0x007c,
-	0x127e, 0x2091, 0x8000, 0x601c, 0xa084, 0x000f, 0x1079, 0x6742,
-	0x127f, 0x007c, 0x6751, 0x674a, 0x674c, 0x676a, 0x674a, 0x674c,
-	0x674c, 0x674c, 0x1078, 0x12d5, 0xa006, 0x007c, 0xa085, 0x0001,
-	0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040, 0x6767,
-	0xa00e, 0x2001, 0x0005, 0x1078, 0x3b0a, 0x1078, 0x6b47, 0x1078,
-	0x3a7a, 0x1078, 0x5c02, 0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006,
-	0x0078, 0x6765, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d5, 0x1079,
-	0x6772, 0x007c, 0x6782, 0x679f, 0x6784, 0x67b0, 0x679b, 0x6782,
-	0x674c, 0x6751, 0x6751, 0x674c, 0x674c, 0x674c, 0x674c, 0x674c,
-	0x674c, 0x674c, 0x1078, 0x12d5, 0x0d7e, 0x6010, 0x2068, 0x1078,
-	0x693e, 0x0040, 0x678d, 0x1078, 0x6b47, 0x0d7f, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x4825, 0x1078, 0x4c7a,
-	0xa085, 0x0001, 0x007c, 0x1078, 0x1676, 0x0078, 0x6784, 0x0e7e,
-	0x2071, 0x7836, 0x7024, 0xac06, 0x00c0, 0x67a8, 0x1078, 0x56d6,
-	0x1078, 0x560b, 0x0e7f, 0x00c0, 0x6784, 0x1078, 0x674c, 0x007c,
-	0x037e, 0x0e7e, 0x2071, 0x7836, 0x703c, 0xac06, 0x00c0, 0x67c0,
-	0x2019, 0x0000, 0x1078, 0x5768, 0x0e7f, 0x037f, 0x0078, 0x6784,
-	0x1078, 0x5a44, 0x0e7f, 0x037f, 0x00c0, 0x6784, 0x1078, 0x674c,
-	0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079, 0x67d1, 0x0c7f,
-	0x007c, 0x67e0, 0x683d, 0x68e2, 0x67e4, 0x67e0, 0x67e0, 0x71dd,
-	0x5c02, 0x683d, 0x1078, 0x6ace, 0x00c0, 0x67e0, 0x1078, 0x5e57,
-	0x007c, 0x6017, 0x0001, 0x007c, 0x6000, 0xa08a, 0x0010, 0x10c8,
-	0x12d5, 0x1079, 0x67ec, 0x007c, 0x67fc, 0x67fe, 0x681e, 0x6830,
-	0x6830, 0x67fc, 0x67e0, 0x67e0, 0x67e0, 0x6830, 0x6830, 0x67fc,
-	0x67fc, 0x67fc, 0x67fc, 0x683a, 0x1078, 0x12d5, 0x0e7e, 0x6010,
-	0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x7836, 0x7024, 0xac06,
-	0x0040, 0x681a, 0x1078, 0x560b, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0002, 0x6017, 0x0014, 0x1078, 0x4825, 0x1078, 0x4c7a,
-	0x0e7f, 0x007c, 0x6017, 0x0001, 0x0078, 0x6818, 0x0d7e, 0x6010,
-	0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003,
-	0x000b, 0x601f, 0x0002, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x007c,
-	0x0d7e, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852,
-	0x0d7f, 0x007c, 0x1078, 0x5c02, 0x007c, 0x6000, 0xa08a, 0x0010,
-	0x10c8, 0x12d5, 0x1079, 0x6845, 0x007c, 0x6855, 0x67e1, 0x6857,
-	0x6855, 0x6857, 0x6855, 0x6855, 0x6855, 0x67da, 0x67da, 0x6855,
-	0x6855, 0x6855, 0x6855, 0x6855, 0x6855, 0x1078, 0x12d5, 0x0d7e,
-	0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa08a, 0x000c,
-	0x10c8, 0x12d5, 0x1079, 0x6865, 0x007c, 0x6871, 0x6890, 0x6871,
-	0x6890, 0x6871, 0x6890, 0x6873, 0x687c, 0x6871, 0x6890, 0x6871,
-	0x6889, 0x1078, 0x12d5, 0x6004, 0xa08e, 0x0004, 0x0040, 0x688b,
-	0xa08e, 0x0002, 0x0040, 0x688b, 0x6004, 0x1078, 0x6ace, 0x0040,
-	0x68da, 0xa08e, 0x0021, 0x0040, 0x68de, 0xa08e, 0x0022, 0x0040,
-	0x68da, 0x1078, 0x22bb, 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c,
-	0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040, 0x68ca, 0xa186,
-	0x0002, 0x00c0, 0x68b9, 0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0,
-	0x68b9, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x68b9, 0x8001,
-	0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398, 0x1078,
-	0x5b9c, 0x0040, 0x68b9, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0078,
-	0x68ca, 0x0d7f, 0x0c7f, 0x1078, 0x5e57, 0x1078, 0x22bb, 0x0e7e,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x22dd, 0x127f, 0x0e7f, 0x1078,
-	0x5c02, 0x007c, 0x2001, 0x0002, 0x1078, 0x37d1, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0d7f, 0x0c7f,
-	0x0078, 0x68c9, 0x1078, 0x5e57, 0x0078, 0x688d, 0x1078, 0x5e66,
-	0x0078, 0x688d, 0x6000, 0xa08a, 0x0010, 0x10c8, 0x12d5, 0x1079,
-	0x68ea, 0x007c, 0x68fa, 0x68fa, 0x68fa, 0x68fa, 0x68fa, 0x68fa,
-	0x68fa, 0x68fa, 0x68fa, 0x67e0, 0x68fa, 0x67e1, 0x68fc, 0x67e1,
-	0x6905, 0x68fa, 0x1078, 0x12d5, 0x6007, 0x008b, 0x6003, 0x000d,
-	0x1078, 0x4825, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x6a94, 0x1078,
-	0x693e, 0x0040, 0x6927, 0x1078, 0x22bb, 0x0d7e, 0x1078, 0x693e,
-	0x0040, 0x691a, 0x6010, 0x2068, 0x6837, 0x0103, 0x684b, 0x0006,
-	0x1078, 0x3a7a, 0x0d7f, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003,
-	0x0001, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0078, 0x6929, 0x1078,
-	0x5c02, 0x007c, 0xa284, 0x0007, 0x00c0, 0x693b, 0xa282, 0x7d00,
-	0x0048, 0x693b, 0x2001, 0x7615, 0x2004, 0xa202, 0x00c8, 0x693b,
-	0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x693a, 0x027e, 0x0e7e,
-	0x2071, 0x7600, 0x6210, 0x7058, 0xa202, 0x0048, 0x6950, 0x705c,
-	0xa202, 0x00c8, 0x6950, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c,
-	0xa006, 0x0078, 0x694d, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e,
-	0x2091, 0x8000, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7344, 0x7060,
-	0xa302, 0x00c8, 0x6979, 0x601c, 0xa206, 0x00c0, 0x6971, 0x1078,
-	0x6ace, 0x00c0, 0x696d, 0x1078, 0x5e57, 0x0c7e, 0x1078, 0x5c02,
-	0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8, 0x6979, 0x0078,
-	0x695e, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e,
-	0x0c7e, 0x017e, 0xa188, 0x7720, 0x210c, 0x81ff, 0x0040, 0x699c,
-	0x2061, 0x7d00, 0x2071, 0x7600, 0x7344, 0x7060, 0xa302, 0x00c8,
-	0x699c, 0x017e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x699f, 0x611a,
-	0x1078, 0x22bb, 0x1078, 0x5c02, 0xa006, 0x0078, 0x69a1, 0xa085,
-	0x0001, 0x017f, 0x0c7f, 0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x057f, 0x0040, 0x69be,
-	0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b, 0x1078, 0x5c29,
-	0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x69ba, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e,
-	0x1078, 0x5b9c, 0x057f, 0x0040, 0x69e8, 0x6013, 0x0000, 0x651a,
-	0x601f, 0x0003, 0x0c7e, 0x2560, 0x1078, 0x39a6, 0x0c7f, 0x1078,
-	0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078, 0x737b, 0x2009, 0x004c,
-	0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
-	0xa006, 0x0078, 0x69e4, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000,
-	0x62a0, 0x0c7e, 0x1078, 0x5b9c, 0x057f, 0x0040, 0x6a13, 0x6612,
+	0x0015, 0x00c0, 0x5ce4, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c,
+	0x680e, 0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x5ca5, 0x2100,
+	0xa1b2, 0x0030, 0x10c8, 0x12cd, 0x0079, 0x5cee, 0x5d20, 0x5d2c,
+	0x5d20, 0x5d20, 0x5d20, 0x5d20, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e,
+	0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e,
+	0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e,
+	0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d20, 0x5d1e, 0x5d20,
+	0x5d20, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d20, 0x5d1e,
+	0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x5d1e, 0x1078, 0x12cd,
+	0x6003, 0x0001, 0x6106, 0x1078, 0x486a, 0x127e, 0x2091, 0x8000,
+	0x1078, 0x4c72, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
+	0x486a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, 0x007c,
+	0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12cd, 0xa1b6, 0x0013, 0x00c0,
+	0x5d44, 0x2008, 0x0079, 0x5dcb, 0xa1b6, 0x0027, 0x00c0, 0x5d99,
+	0x1078, 0x4b79, 0x6004, 0x1078, 0x6aaf, 0x0040, 0x5d5d, 0x1078,
+	0x6ac3, 0x0040, 0x5d91, 0xa08e, 0x0021, 0x0040, 0x5d95, 0xa08e,
+	0x0022, 0x0040, 0x5d91, 0x0078, 0x5d8c, 0x1078, 0x22d7, 0x2001,
+	0x0007, 0x1078, 0x37c9, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078,
+	0x5e4d, 0xa186, 0x007e, 0x00c0, 0x5d72, 0x2001, 0x762f, 0x2014,
+	0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028,
+	0x1078, 0x495a, 0x1078, 0x489d, 0x0c7e, 0x6018, 0xa065, 0x0040,
+	0x5d83, 0x1078, 0x399e, 0x0c7f, 0x2c08, 0x1078, 0x7370, 0x037f,
+	0x027f, 0x017f, 0x1078, 0x3805, 0x1078, 0x5bfa, 0x1078, 0x4c72,
+	0x007c, 0x1078, 0x5e4d, 0x0078, 0x5d8c, 0x1078, 0x5e5c, 0x0078,
+	0x5d8c, 0xa186, 0x0014, 0x00c0, 0x5d90, 0x1078, 0x4b79, 0x1078,
+	0x22b5, 0x1078, 0x6aaf, 0x00c0, 0x5db8, 0x1078, 0x22d7, 0x6018,
+	0xa080, 0x0028, 0x200c, 0x1078, 0x5e4d, 0xa186, 0x007e, 0x00c0,
+	0x5db6, 0x2001, 0x762f, 0x200c, 0xc185, 0x2102, 0x0078, 0x5d8c,
+	0x1078, 0x6ac3, 0x00c0, 0x5dc0, 0x1078, 0x5e4d, 0x0078, 0x5d8c,
+	0x6004, 0xa08e, 0x0021, 0x0040, 0x5dbc, 0xa08e, 0x0022, 0x1040,
+	0x5e5c, 0x0078, 0x5d8c, 0x5dfd, 0x5dff, 0x5e03, 0x5e07, 0x5e0b,
+	0x5e0f, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb,
+	0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb,
+	0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb, 0x5dfb,
+	0x5dfb, 0x5e13, 0x5e19, 0x5dfb, 0x5e23, 0x5e19, 0x5dfb, 0x5dfb,
+	0x5dfb, 0x5dfb, 0x5dfb, 0x5e19, 0x5e19, 0x5dfb, 0x5dfb, 0x5dfb,
+	0x5dfb, 0x5dfb, 0x5dfb, 0x1078, 0x12cd, 0x0078, 0x5e19, 0x2001,
+	0x000b, 0x0078, 0x5e2c, 0x2001, 0x0003, 0x0078, 0x5e2c, 0x2001,
+	0x0005, 0x0078, 0x5e2c, 0x2001, 0x0001, 0x0078, 0x5e2c, 0x2001,
+	0x0009, 0x0078, 0x5e2c, 0x1078, 0x12cd, 0x0078, 0x5e2b, 0x1078,
+	0x37c9, 0x1078, 0x4b79, 0x6003, 0x0002, 0x6017, 0x0028, 0x1078,
+	0x4c72, 0x0078, 0x5e2b, 0x1078, 0x4b79, 0x6003, 0x0004, 0x6017,
+	0x0028, 0x1078, 0x4c72, 0x007c, 0x1078, 0x37c9, 0x1078, 0x4b79,
+	0x6003, 0x0002, 0x037e, 0x2019, 0x765c, 0x2304, 0xa084, 0xff00,
+	0x00c0, 0x5e3e, 0x2019, 0x0028, 0x0078, 0x5e47, 0x8007, 0xa09a,
+	0x0004, 0x0048, 0x5e3a, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316,
+	0x037f, 0x1078, 0x4c72, 0x0078, 0x5e2b, 0x0e7e, 0x1078, 0x6938,
+	0x0040, 0x5e5a, 0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
+	0x7033, 0x0100, 0x0e7f, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74,
+	0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x0e7f, 0x007c,
+	0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x0d7f, 0xa0b2,
+	0x000c, 0x10c8, 0x12cd, 0x6604, 0xa6b6, 0x0028, 0x00c0, 0x5e7c,
+	0x1078, 0x6af8, 0x0078, 0x5eae, 0x6604, 0xa6b6, 0x0029, 0x00c0,
+	0x5e85, 0x1078, 0x6b12, 0x0078, 0x5eae, 0x6604, 0xa6b6, 0x001f,
+	0x00c0, 0x5e8e, 0x1078, 0x5c8b, 0x0078, 0x5eae, 0x6604, 0xa6b6,
+	0x0000, 0x00c0, 0x5e97, 0x1078, 0x5cd0, 0x0078, 0x5eae, 0x6604,
+	0xa6b6, 0x0022, 0x00c0, 0x5ea0, 0x1078, 0x5cb4, 0x0078, 0x5eae,
+	0xa1b6, 0x0015, 0x00c0, 0x5ea8, 0x1079, 0x5eb3, 0x0078, 0x5eae,
+	0xa1b6, 0x0016, 0x00c0, 0x5eaf, 0x1079, 0x5ff0, 0x007c, 0x1078,
+	0x5c2f, 0x0078, 0x5eae, 0x5ed7, 0x5eda, 0x5ed7, 0x5f1b, 0x5ed7,
+	0x5f8c, 0x5ed7, 0x5ed7, 0x5ed7, 0x5fc8, 0x5ed7, 0x5fde, 0xa1b6,
+	0x0048, 0x0040, 0x5ecb, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
+	0x1078, 0x156a, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000,
+	0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x5bfa, 0x007c, 0x0005,
+	0x0005, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078, 0xa086, 0x0074,
+	0x00c0, 0x5f04, 0x1078, 0x7344, 0x00c0, 0x5ef6, 0x0d7e, 0x6018,
+	0x2068, 0x1078, 0x5f08, 0x0d7f, 0x2001, 0x0006, 0x1078, 0x37c9,
+	0x1078, 0x22d7, 0x1078, 0x5bfa, 0x0078, 0x5f06, 0x2001, 0x000a,
+	0x1078, 0x37c9, 0x1078, 0x22d7, 0x6003, 0x0001, 0x6007, 0x0001,
+	0x1078, 0x486a, 0x0078, 0x5f06, 0x1078, 0x5f7c, 0x0e7f, 0x007c,
+	0x6800, 0xd084, 0x0040, 0x5f1a, 0x2001, 0x0000, 0x1078, 0x37b5,
+	0x2069, 0x7651, 0x6804, 0xd0a4, 0x0040, 0x5f1a, 0x2001, 0x0006,
+	0x1078, 0x37d7, 0x007c, 0x0d7e, 0x2011, 0x761e, 0x2204, 0xa086,
+	0x0074, 0x00c0, 0x5f78, 0x1078, 0x60ca, 0x6018, 0x2068, 0xa080,
+	0x0028, 0x2014, 0xa286, 0x007e, 0x0040, 0x5f43, 0xa286, 0x0080,
+	0x00c0, 0x5f6c, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
+	0x0040, 0x5f62, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833,
+	0x0200, 0x0078, 0x5f62, 0x0e7e, 0x0f7e, 0x6813, 0x00ff, 0x6817,
+	0xfffe, 0x2071, 0x762f, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071,
+	0x7b80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x7619,
+	0x206a, 0x78e6, 0x8e70, 0x2e04, 0x2069, 0x761a, 0x206a, 0x78ea,
+	0x0f7f, 0x0e7f, 0x2001, 0x0006, 0x1078, 0x37c9, 0x1078, 0x22d7,
+	0x1078, 0x5bfa, 0x0078, 0x5f7a, 0x2001, 0x0004, 0x1078, 0x37c9,
+	0x6003, 0x0001, 0x6007, 0x0003, 0x1078, 0x486a, 0x0078, 0x5f7a,
+	0x1078, 0x5f7c, 0x0d7f, 0x007c, 0x2001, 0x7600, 0x2004, 0xa086,
+	0x0003, 0x0040, 0x5f87, 0x2001, 0x0007, 0x1078, 0x37c9, 0x1078,
+	0x22d7, 0x1078, 0x5bfa, 0x007c, 0x0e7e, 0x2071, 0x7600, 0x7078,
+	0xa086, 0x0014, 0x00c0, 0x5fc2, 0x7000, 0xa086, 0x0003, 0x00c0,
+	0x5f9f, 0x6010, 0xa005, 0x00c0, 0x5f9f, 0x1078, 0x2db9, 0x0d7e,
+	0x6018, 0x2068, 0x1078, 0x3899, 0x1078, 0x5f08, 0x0d7f, 0x1078,
+	0x60d4, 0x00c0, 0x5fc2, 0x2001, 0x0006, 0x1078, 0x37c9, 0x0e7e,
+	0x6010, 0xa005, 0x0040, 0x5fbb, 0x2070, 0x7007, 0x0000, 0x7037,
+	0x0103, 0x7033, 0x0200, 0x0e7f, 0x1078, 0x22d7, 0x1078, 0x5bfa,
+	0x0078, 0x5fc6, 0x1078, 0x5e4d, 0x1078, 0x5f7c, 0x0e7f, 0x007c,
+	0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0, 0x5fdb, 0x2001,
+	0x0002, 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
+	0x486a, 0x0078, 0x5fdd, 0x1078, 0x5f7c, 0x007c, 0x2011, 0x761e,
+	0x2204, 0xa086, 0x0004, 0x00c0, 0x5fed, 0x2001, 0x0007, 0x1078,
+	0x37c9, 0x1078, 0x5bfa, 0x0078, 0x5fef, 0x1078, 0x5f7c, 0x007c,
+	0x5ed7, 0x5ffc, 0x5ed7, 0x6022, 0x5ed7, 0x607d, 0x5ed7, 0x5ed7,
+	0x5ed7, 0x6092, 0x5ed7, 0x60a5, 0x0c7e, 0x1078, 0x60b8, 0x00c0,
+	0x6011, 0x2001, 0x0000, 0x1078, 0x37b5, 0x2001, 0x0002, 0x1078,
+	0x37c9, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x486a, 0x0078,
+	0x6020, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900,
+	0x00c0, 0x601e, 0x1078, 0x5bfa, 0x0078, 0x6020, 0x1078, 0x5f7c,
+	0x0c7f, 0x007c, 0x1078, 0x60c7, 0x00c0, 0x6036, 0x2001, 0x0000,
+	0x1078, 0x37b5, 0x2001, 0x0002, 0x1078, 0x37c9, 0x6003, 0x0001,
+	0x6007, 0x0002, 0x1078, 0x486a, 0x0078, 0x6058, 0x1078, 0x5e4d,
+	0x2009, 0x7b8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040,
+	0x6059, 0x2009, 0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900,
+	0x00c0, 0x6056, 0xa686, 0x0009, 0x0040, 0x6059, 0x2001, 0x0004,
+	0x1078, 0x37c9, 0x1078, 0x5bfa, 0x0078, 0x6058, 0x1078, 0x5f7c,
+	0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x6067,
+	0x6838, 0xd0fc, 0x0040, 0x6067, 0x0d7f, 0x0078, 0x6056, 0x6018,
+	0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040, 0x6078, 0x8001,
+	0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f, 0x0078, 0x6058,
+	0x1078, 0x22b5, 0x0d7f, 0x0078, 0x6056, 0x1078, 0x60c7, 0x00c0,
+	0x608d, 0x2001, 0x0004, 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007,
+	0x0003, 0x1078, 0x486a, 0x0078, 0x6091, 0x1078, 0x5e4d, 0x1078,
+	0x5f7c, 0x007c, 0x1078, 0x60c7, 0x00c0, 0x60a2, 0x2001, 0x0008,
+	0x1078, 0x37c9, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x486a,
+	0x0078, 0x60a4, 0x1078, 0x5f7c, 0x007c, 0x1078, 0x60c7, 0x00c0,
+	0x60b5, 0x2001, 0x000a, 0x1078, 0x37c9, 0x6003, 0x0001, 0x6007,
+	0x0001, 0x1078, 0x486a, 0x0078, 0x60b7, 0x1078, 0x5f7c, 0x007c,
+	0x2009, 0x7b8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x60c6, 0x2009,
+	0x7b8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085,
+	0x0001, 0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078,
+	0x382f, 0x017f, 0x0c7f, 0x007c, 0x0e7e, 0x2071, 0x7b8c, 0x7004,
+	0xa086, 0x0014, 0x00c0, 0x60f7, 0x7008, 0xa086, 0x0800, 0x00c0,
+	0x60f7, 0x700c, 0xd0ec, 0x0040, 0x60f5, 0xa084, 0x0f00, 0xa086,
+	0x0100, 0x00c0, 0x60f5, 0x7024, 0xd0a4, 0x0040, 0x60f5, 0xd08c,
+	0x0040, 0x60f5, 0xa006, 0x0078, 0x60f7, 0xa085, 0x0001, 0x0e7f,
+	0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f, 0x252c, 0x2021,
+	0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7244, 0x7060,
+	0xa202, 0x00c8, 0x614e, 0x1078, 0x754e, 0x0040, 0x6146, 0x671c,
+	0xa786, 0x0001, 0x0040, 0x6146, 0xa786, 0x0007, 0x0040, 0x6146,
+	0x2500, 0xac06, 0x0040, 0x6146, 0x2400, 0xac06, 0x0040, 0x6146,
+	0x0c7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x6130, 0x1078, 0x166e,
+	0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x6143, 0xa786, 0x0003,
+	0x00c0, 0x6158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078,
+	0x3a72, 0x1078, 0x6a89, 0x1078, 0x6a96, 0x0c7f, 0xace0, 0x0008,
+	0x7054, 0xac02, 0x00c8, 0x614e, 0x0078, 0x610e, 0x127f, 0x007f,
+	0x027f, 0x047f, 0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c,
+	0xa786, 0x0006, 0x00c0, 0x613a, 0x1078, 0x74f2, 0x0078, 0x6143,
+	0x220c, 0x2304, 0xa106, 0x00c0, 0x616b, 0x8210, 0x8318, 0x00f0,
+	0x6160, 0xa006, 0x007c, 0x2304, 0xa102, 0x0048, 0x6173, 0x2001,
+	0x0001, 0x0078, 0x6175, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c,
+	0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x1078, 0x6aaf, 0x0040,
+	0x6187, 0x1078, 0x6ac3, 0x0040, 0x6190, 0x0078, 0x6189, 0x1078,
+	0x22d7, 0x1078, 0x4b79, 0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c,
+	0x1078, 0x5e4d, 0x0078, 0x6189, 0xa182, 0x0040, 0x0079, 0x6198,
+	0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8, 0x61a8,
+	0x61a8, 0x61a8, 0x61a8, 0x61aa, 0x61aa, 0x61aa, 0x61aa, 0x61a8,
+	0x1078, 0x12cd, 0x6003, 0x0001, 0x6106, 0x1078, 0x481d, 0x127e,
+	0x2091, 0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, 0xa186, 0x0013,
+	0x00c0, 0x61bf, 0x6004, 0xa082, 0x0040, 0x0079, 0x6235, 0xa186,
+	0x0027, 0x00c0, 0x61dc, 0x1078, 0x4b79, 0x1078, 0x22b5, 0x0d7e,
+	0x6110, 0x2168, 0x1078, 0x6938, 0x0040, 0x61d6, 0x6837, 0x0103,
+	0x684b, 0x0029, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x0d7f, 0x1078,
+	0x5bfa, 0x1078, 0x4c72, 0x007c, 0xa186, 0x0014, 0x00c0, 0x61e5,
+	0x6004, 0xa082, 0x0040, 0x0079, 0x6205, 0xa186, 0x0047, 0x10c0,
+	0x12cd, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x6202, 0x127e,
+	0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x46de, 0x027f,
+	0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0, 0x6202,
+	0x0078, 0x625c, 0x1078, 0x5c2f, 0x007c, 0x6217, 0x6215, 0x6215,
+	0x6215, 0x6215, 0x6215, 0x6215, 0x6215, 0x6215, 0x6215, 0x6215,
+	0x622e, 0x622e, 0x622e, 0x622e, 0x6215, 0x1078, 0x12cd, 0x1078,
+	0x4b79, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x6938, 0x0040, 0x6228,
+	0x6837, 0x0103, 0x684b, 0x0006, 0x1078, 0x3a72, 0x1078, 0x6a89,
+	0x0d7f, 0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, 0x1078, 0x4b79,
+	0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, 0x6247, 0x6245, 0x6245,
+	0x6245, 0x6245, 0x6245, 0x6245, 0x6245, 0x6245, 0x6245, 0x6245,
+	0x6255, 0x6255, 0x6255, 0x6255, 0x6245, 0x1078, 0x12cd, 0x1078,
+	0x4b79, 0x6003, 0x0002, 0x1078, 0x4c72, 0x6010, 0xa088, 0x0013,
+	0x2104, 0xa085, 0x0400, 0x200a, 0x007c, 0x1078, 0x4b79, 0x6003,
+	0x000f, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0040, 0x0079, 0x6260,
+	0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6272, 0x62fb, 0x6313,
+	0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6270, 0x6270,
+	0x1078, 0x12cd, 0x0e7e, 0x0d7e, 0x2071, 0x7b8c, 0x6110, 0x2168,
+	0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040, 0x62df, 0xa68c, 0x00ff,
+	0xa186, 0x0002, 0x0040, 0x62a4, 0xa186, 0x0028, 0x00c0, 0x628e,
+	0x1078, 0x6a9d, 0x684b, 0x001c, 0x0078, 0x62a6, 0xd6dc, 0x0040,
+	0x6299, 0x684b, 0x0015, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078,
+	0x62a6, 0xd6d4, 0x0040, 0x62a4, 0x684b, 0x0007, 0x7318, 0x6b62,
+	0x731c, 0x6b5e, 0x0078, 0x62a6, 0x684b, 0x0000, 0x6837, 0x0103,
+	0x6e46, 0xa01e, 0xd6c4, 0x0040, 0x62b9, 0x7328, 0x732c, 0x6b56,
+	0x037e, 0x2308, 0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6721,
+	0x037f, 0xd6cc, 0x0040, 0x62ef, 0x7124, 0x695a, 0xa192, 0x0021,
+	0x00c8, 0x62cd, 0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90,
+	0x001d, 0x1078, 0x6721, 0x0078, 0x62ef, 0x6838, 0xd0fc, 0x0040,
+	0x62d6, 0x2009, 0x0020, 0x695a, 0x0078, 0x62c2, 0x0f7e, 0x2d78,
+	0x1078, 0x66b9, 0x0f7f, 0x1078, 0x670e, 0x0078, 0x62f1, 0x684b,
+	0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x62ef,
+	0x6810, 0x6914, 0xa115, 0x0040, 0x62ef, 0x1078, 0x6467, 0x1078,
+	0x3a72, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x0d7f, 0x0e7f,
+	0x1078, 0x5bfa, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x7b8c,
+	0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16,
+	0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19c7, 0x1078, 0x4889,
+	0x1078, 0x4d32, 0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005,
+	0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x007c, 0xa182, 0x0040,
+	0x0079, 0x6322, 0x6332, 0x6332, 0x6332, 0x6332, 0x6332, 0x6334,
+	0x63cb, 0x6332, 0x6332, 0x63e1, 0x6443, 0x6332, 0x6332, 0x6332,
+	0x6332, 0x644e, 0x1078, 0x12cd, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e,
+	0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
+	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
+	0x86ff, 0x0040, 0x63c6, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040,
+	0x6355, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040,
+	0x63c6, 0x1078, 0x1327, 0x1040, 0x12cd, 0x2d00, 0x784a, 0x7f4c,
+	0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e,
+	0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0040,
+	0x638f, 0xa186, 0x0028, 0x00c0, 0x6379, 0x684b, 0x001c, 0x0078,
+	0x6391, 0xd6dc, 0x0040, 0x6384, 0x684b, 0x0015, 0x7318, 0x6b62,
+	0x731c, 0x6b5e, 0x0078, 0x6391, 0xd6d4, 0x0040, 0x638f, 0x684b,
+	0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x6391, 0x684b,
+	0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4,
+	0x0040, 0x63a6, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308, 0x2019,
+	0x7b98, 0xad90, 0x0019, 0x1078, 0x6721, 0x037f, 0xd6cc, 0x0040,
+	0x63c6, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x63ba, 0x2071,
+	0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x6721,
+	0x0078, 0x63c6, 0x7838, 0xd0fc, 0x0040, 0x63c3, 0x2009, 0x0020,
+	0x695a, 0x0078, 0x63af, 0x2d78, 0x1078, 0x66b9, 0x0d7f, 0x0e7f,
+	0x0f7f, 0x077f, 0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0x7b8c,
+	0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16,
+	0x7e0a, 0x7d0e, 0x0f7f, 0x2c10, 0x1078, 0x19c7, 0x1078, 0x555f,
+	0x007c, 0x0d7e, 0x6003, 0x0002, 0x1078, 0x4c21, 0x1078, 0x4d32,
+	0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x6441, 0xd1cc, 0x0040,
+	0x641c, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x6414, 0x017e, 0x684c,
+	0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009,
+	0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x00f0,
+	0x6403, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f, 0x2168,
+	0x1078, 0x1350, 0x0078, 0x643f, 0x017e, 0x1078, 0x1350, 0x0d7f,
+	0x1078, 0x670e, 0x0078, 0x643f, 0x6837, 0x0103, 0x6944, 0xa184,
+	0x00ff, 0xa186, 0x0002, 0x0040, 0x643b, 0xa086, 0x0028, 0x00c0,
+	0x642d, 0x684b, 0x001c, 0x0078, 0x643d, 0xd1dc, 0x0040, 0x6434,
+	0x684b, 0x0015, 0x0078, 0x643d, 0xd1d4, 0x0040, 0x643b, 0x684b,
+	0x0007, 0x0078, 0x643d, 0x684b, 0x0000, 0x1078, 0x3a72, 0x1078,
+	0x5bfa, 0x0d7f, 0x007c, 0x2019, 0x0001, 0x1078, 0x5760, 0x6003,
+	0x0002, 0x1078, 0x4c21, 0x1078, 0x4d32, 0x007c, 0x1078, 0x4c21,
+	0x1078, 0x22b5, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x6938, 0x0040,
+	0x6461, 0x6837, 0x0103, 0x684b, 0x0029, 0x1078, 0x3a72, 0x1078,
+	0x6a89, 0x0d7f, 0x1078, 0x5bfa, 0x1078, 0x4d32, 0x007c, 0x684b,
+	0x0015, 0xd1fc, 0x0040, 0x6473, 0x684b, 0x0007, 0x8002, 0x8000,
+	0x810a, 0xa189, 0x0000, 0x6962, 0x685e, 0x007c, 0xa182, 0x0040,
+	0x0079, 0x647a, 0x648a, 0x648a, 0x648a, 0x648a, 0x648a, 0x648c,
+	0x648a, 0x6530, 0x6538, 0x648a, 0x648a, 0x648a, 0x648a, 0x648a,
+	0x648a, 0x648a, 0x1078, 0x12cd, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e,
+	0x2071, 0x7b8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
+	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
+	0x86ff, 0x0040, 0x6522, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0040,
+	0x64ad, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0040,
+	0x651f, 0x1078, 0x1327, 0x1040, 0x12cd, 0x2d00, 0x784a, 0x7f4c,
+	0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c,
+	0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x00ff, 0xa186, 0x0002,
+	0x0040, 0x64e8, 0xa186, 0x0028, 0x00c0, 0x64d2, 0x684b, 0x001c,
+	0x0078, 0x64ea, 0xd6dc, 0x0040, 0x64dd, 0x684b, 0x0015, 0x7318,
+	0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64ea, 0xd6d4, 0x0040, 0x64e8,
+	0x684b, 0x0007, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0x0078, 0x64ea,
+	0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e,
+	0xd6c4, 0x0040, 0x64ff, 0x7328, 0x732c, 0x6b56, 0x037e, 0x2308,
+	0x2019, 0x7b98, 0xad90, 0x0019, 0x1078, 0x6721, 0x037f, 0xd6cc,
+	0x0040, 0x651f, 0x7124, 0x695a, 0xa192, 0x0021, 0x00c8, 0x6513,
+	0x2071, 0x7b98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078,
+	0x6721, 0x0078, 0x651f, 0x7838, 0xd0fc, 0x0040, 0x651c, 0x2009,
+	0x0020, 0x695a, 0x0078, 0x6508, 0x2d78, 0x1078, 0x66b9, 0xd6dc,
+	0x00c0, 0x6525, 0xa006, 0x0078, 0x6529, 0x2001, 0x0001, 0x7218,
+	0x731c, 0x1078, 0x15ae, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c,
+	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a, 0x007c,
+	0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040,
+	0x659f, 0xd1cc, 0x0040, 0x656f, 0x6948, 0x6838, 0xd0fc, 0x0040,
+	0x6567, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d,
+	0xa198, 0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012,
+	0x8318, 0x8210, 0x00f0, 0x6556, 0x157f, 0x007f, 0x6852, 0x007f,
+	0x684e, 0x017f, 0x2168, 0x1078, 0x1350, 0x0078, 0x659d, 0x017e,
+	0x1078, 0x1350, 0x0d7f, 0x1078, 0x670e, 0x0078, 0x659d, 0x6837,
+	0x0103, 0x6944, 0xa184, 0x00ff, 0xa186, 0x0002, 0x0040, 0x658e,
+	0xa086, 0x0028, 0x00c0, 0x6580, 0x684b, 0x001c, 0x0078, 0x659b,
+	0xd1dc, 0x0040, 0x6587, 0x684b, 0x0015, 0x0078, 0x659b, 0xd1d4,
+	0x0040, 0x658e, 0x684b, 0x0007, 0x0078, 0x659b, 0x684b, 0x0000,
+	0x684c, 0xd0ac, 0x0040, 0x659b, 0x6810, 0x6914, 0xa115, 0x0040,
+	0x659b, 0x1078, 0x6467, 0x1078, 0x3a72, 0x1078, 0x5bfa, 0x0d7f,
+	0x007c, 0x1078, 0x4b79, 0x0078, 0x65a7, 0x1078, 0x4c21, 0x1078,
+	0x6938, 0x0040, 0x65be, 0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103,
+	0x2009, 0x760c, 0x210c, 0xd18c, 0x00c0, 0x65c7, 0xd184, 0x00c0,
+	0x65c3, 0x6108, 0x694a, 0x1078, 0x3a72, 0x0d7f, 0x1078, 0x5bfa,
+	0x1078, 0x4c72, 0x007c, 0x684b, 0x0004, 0x0078, 0x65bb, 0x684b,
+	0x0004, 0x0078, 0x65bb, 0xa182, 0x0040, 0x0079, 0x65cf, 0x65df,
+	0x65df, 0x65df, 0x65df, 0x65df, 0x65e1, 0x65df, 0x65e4, 0x65df,
+	0x65df, 0x65df, 0x65df, 0x65df, 0x65df, 0x65df, 0x65df, 0x1078,
+	0x12cd, 0x1078, 0x5bfa, 0x007c, 0x007e, 0x027e, 0xa016, 0x1078,
+	0x156a, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085, 0x0079, 0x65f0,
+	0x65f9, 0x65f7, 0x65f7, 0x65f7, 0x65f7, 0x65f7, 0x65f7, 0x1078,
+	0x12cd, 0x6003, 0x0001, 0x6106, 0x1078, 0x481d, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0,
+	0x660f, 0x6004, 0xa082, 0x0085, 0x2008, 0x0079, 0x6643, 0xa186,
+	0x0027, 0x00c0, 0x6630, 0x1078, 0x4b79, 0x1078, 0x22b5, 0x0d7e,
+	0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x6626, 0x6837, 0x0103,
+	0x684b, 0x0029, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x0d7f, 0x1078,
+	0x5bfa, 0x1078, 0x4c72, 0x007c, 0x1078, 0x5c2f, 0x0078, 0x662b,
+	0xa186, 0x0014, 0x00c0, 0x662c, 0x1078, 0x4b79, 0x0d7e, 0x6010,
+	0x2068, 0x1078, 0x6938, 0x0040, 0x6626, 0x6837, 0x0103, 0x684b,
+	0x0006, 0x0078, 0x6622, 0x664c, 0x664a, 0x664a, 0x664a, 0x664a,
+	0x664a, 0x6655, 0x1078, 0x12cd, 0x1078, 0x4b79, 0x6017, 0x0014,
+	0x6003, 0x000c, 0x1078, 0x4c72, 0x007c, 0x1078, 0x4b79, 0x6017,
+	0x0014, 0x6003, 0x000e, 0x1078, 0x4c72, 0x007c, 0xa182, 0x008c,
+	0x00c8, 0x6668, 0xa182, 0x0085, 0x0048, 0x6668, 0x0079, 0x666b,
+	0x1078, 0x5c2f, 0x007c, 0x6672, 0x6672, 0x6672, 0x6672, 0x6674,
+	0x6693, 0x6672, 0x1078, 0x12cd, 0x0d7e, 0x1078, 0x6a89, 0x1078,
+	0x6938, 0x0040, 0x668f, 0x6010, 0x2068, 0x6837, 0x0103, 0x6850,
+	0xd0b4, 0x0040, 0x6687, 0x684b, 0x0006, 0x0078, 0x668b, 0x684b,
+	0x0005, 0x1078, 0x6b3c, 0x6847, 0x0000, 0x1078, 0x3a72, 0x1078,
+	0x5bfa, 0x0d7f, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6938,
+	0x0040, 0x66ae, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x66a4,
+	0x684b, 0x0006, 0x0078, 0x66a8, 0x684b, 0x0005, 0x1078, 0x6b3c,
+	0x6847, 0x0000, 0x1078, 0x3a72, 0x1078, 0x6a89, 0x0d7f, 0x1078,
+	0x5bfa, 0x007c, 0x1078, 0x4b79, 0x1078, 0x5bfa, 0x1078, 0x4c72,
+	0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001, 0xa182,
+	0x0101, 0x00c8, 0x66c5, 0x0078, 0x66c7, 0x2009, 0x0100, 0x2130,
+	0x2069, 0x7b98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
+	0x001d, 0x1078, 0x6721, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0040,
+	0x66db, 0x1078, 0x1350, 0x1078, 0x1327, 0x0040, 0x6705, 0x8528,
+	0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d,
+	0x00c8, 0x66f1, 0x2608, 0xad90, 0x000f, 0x1078, 0x6721, 0x0078,
+	0x6705, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f,
+	0x1078, 0x6721, 0x0078, 0x66db, 0x0f7f, 0x852f, 0xa5ad, 0x0003,
+	0x7d36, 0xa5ac, 0x0000, 0x0078, 0x670a, 0x0f7f, 0x852f, 0xa5ad,
+	0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e, 0x8dff,
+	0x0040, 0x671f, 0x6804, 0xa07d, 0x0040, 0x671d, 0x6807, 0x0000,
+	0x1078, 0x3a72, 0x2f68, 0x0078, 0x6712, 0x1078, 0x3a72, 0x0f7f,
+	0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x6727, 0x8108, 0x810c,
+	0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0, 0x6729,
+	0x157f, 0x007c, 0x127e, 0x2091, 0x8000, 0x601c, 0xa084, 0x000f,
+	0x1079, 0x673c, 0x127f, 0x007c, 0x674b, 0x6744, 0x6746, 0x6764,
+	0x6744, 0x6746, 0x6746, 0x6746, 0x1078, 0x12cd, 0xa006, 0x007c,
+	0xa085, 0x0001, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x6938,
+	0x0040, 0x6761, 0xa00e, 0x2001, 0x0005, 0x1078, 0x3b02, 0x1078,
+	0x6b3c, 0x1078, 0x3a72, 0x1078, 0x5bfa, 0xa085, 0x0001, 0x0d7f,
+	0x007c, 0xa006, 0x0078, 0x675f, 0x6000, 0xa08a, 0x0010, 0x10c8,
+	0x12cd, 0x1079, 0x676c, 0x007c, 0x677c, 0x6799, 0x677e, 0x67aa,
+	0x6795, 0x677c, 0x6746, 0x674b, 0x674b, 0x6746, 0x6746, 0x6746,
+	0x6746, 0x6746, 0x6746, 0x6746, 0x1078, 0x12cd, 0x0d7e, 0x6010,
+	0x2068, 0x1078, 0x6938, 0x0040, 0x6787, 0x1078, 0x6b3c, 0x0d7f,
+	0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x481d,
+	0x1078, 0x4c72, 0xa085, 0x0001, 0x007c, 0x1078, 0x166e, 0x0078,
+	0x677e, 0x0e7e, 0x2071, 0x7836, 0x7024, 0xac06, 0x00c0, 0x67a2,
+	0x1078, 0x56ce, 0x1078, 0x5603, 0x0e7f, 0x00c0, 0x677e, 0x1078,
+	0x6746, 0x007c, 0x037e, 0x0e7e, 0x2071, 0x7836, 0x703c, 0xac06,
+	0x00c0, 0x67ba, 0x2019, 0x0000, 0x1078, 0x5760, 0x0e7f, 0x037f,
+	0x0078, 0x677e, 0x1078, 0x5a3c, 0x0e7f, 0x037f, 0x00c0, 0x677e,
+	0x1078, 0x6746, 0x007c, 0x0c7e, 0x601c, 0xa084, 0x000f, 0x1079,
+	0x67cb, 0x0c7f, 0x007c, 0x67da, 0x6837, 0x68dc, 0x67de, 0x67da,
+	0x67da, 0x71d2, 0x5bfa, 0x6837, 0x1078, 0x6ac3, 0x00c0, 0x67da,
+	0x1078, 0x5e4d, 0x007c, 0x6017, 0x0001, 0x007c, 0x6000, 0xa08a,
+	0x0010, 0x10c8, 0x12cd, 0x1079, 0x67e6, 0x007c, 0x67f6, 0x67f8,
+	0x6818, 0x682a, 0x682a, 0x67f6, 0x67da, 0x67da, 0x67da, 0x682a,
+	0x682a, 0x67f6, 0x67f6, 0x67f6, 0x67f6, 0x6834, 0x1078, 0x12cd,
+	0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x7836,
+	0x7024, 0xac06, 0x0040, 0x6814, 0x1078, 0x5603, 0x6007, 0x0085,
+	0x6003, 0x000b, 0x601f, 0x0002, 0x6017, 0x0014, 0x1078, 0x481d,
+	0x1078, 0x4c72, 0x0e7f, 0x007c, 0x6017, 0x0001, 0x0078, 0x6812,
+	0x0d7e, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x6007,
+	0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078, 0x481d, 0x1078,
+	0x4c72, 0x007c, 0x0d7e, 0x6017, 0x0001, 0x6010, 0x2068, 0x6850,
+	0xc0b5, 0x6852, 0x0d7f, 0x007c, 0x1078, 0x5bfa, 0x007c, 0x6000,
+	0xa08a, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x683f, 0x007c, 0x684f,
+	0x67db, 0x6851, 0x684f, 0x6851, 0x684f, 0x684f, 0x684f, 0x67d4,
+	0x67d4, 0x684f, 0x684f, 0x684f, 0x684f, 0x684f, 0x684f, 0x1078,
+	0x12cd, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f,
+	0xa08a, 0x000c, 0x10c8, 0x12cd, 0x1079, 0x685f, 0x007c, 0x686b,
+	0x688a, 0x686b, 0x688a, 0x686b, 0x688a, 0x686d, 0x6876, 0x686b,
+	0x688a, 0x686b, 0x6883, 0x1078, 0x12cd, 0x6004, 0xa08e, 0x0004,
+	0x0040, 0x6885, 0xa08e, 0x0002, 0x0040, 0x6885, 0x6004, 0x1078,
+	0x6ac3, 0x0040, 0x68d4, 0xa08e, 0x0021, 0x0040, 0x68d8, 0xa08e,
+	0x0022, 0x0040, 0x68d4, 0x1078, 0x22b5, 0x1078, 0x5e4d, 0x1078,
+	0x5bfa, 0x007c, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016, 0x0040,
+	0x68c4, 0xa186, 0x0002, 0x00c0, 0x68b3, 0x6018, 0x2068, 0x68a0,
+	0xd0bc, 0x00c0, 0x68b3, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040,
+	0x68b3, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017,
+	0x0398, 0x1078, 0x5b94, 0x0040, 0x68b3, 0x2d00, 0x601a, 0x601f,
+	0x0001, 0x0078, 0x68c4, 0x0d7f, 0x0c7f, 0x1078, 0x5e4d, 0x1078,
+	0x22b5, 0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x22d7, 0x127f,
+	0x0e7f, 0x1078, 0x5bfa, 0x007c, 0x2001, 0x0002, 0x1078, 0x37c9,
+	0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x486a, 0x1078, 0x4c72,
+	0x0d7f, 0x0c7f, 0x0078, 0x68c3, 0x1078, 0x5e4d, 0x0078, 0x6887,
+	0x1078, 0x5e5c, 0x0078, 0x6887, 0x6000, 0xa08a, 0x0010, 0x10c8,
+	0x12cd, 0x1079, 0x68e4, 0x007c, 0x68f4, 0x68f4, 0x68f4, 0x68f4,
+	0x68f4, 0x68f4, 0x68f4, 0x68f4, 0x68f4, 0x67da, 0x68f4, 0x67db,
+	0x68f6, 0x67db, 0x68ff, 0x68f4, 0x1078, 0x12cd, 0x6007, 0x008b,
+	0x6003, 0x000d, 0x1078, 0x481d, 0x1078, 0x4c72, 0x007c, 0x1078,
+	0x6a89, 0x1078, 0x6938, 0x0040, 0x6921, 0x1078, 0x22b5, 0x0d7e,
+	0x1078, 0x6938, 0x0040, 0x6914, 0x6010, 0x2068, 0x6837, 0x0103,
+	0x684b, 0x0006, 0x1078, 0x3a72, 0x0d7f, 0x601f, 0x0001, 0x6007,
+	0x0001, 0x6003, 0x0001, 0x1078, 0x486a, 0x1078, 0x4c72, 0x0078,
+	0x6923, 0x1078, 0x5bfa, 0x007c, 0xa284, 0x0007, 0x00c0, 0x6935,
+	0xa282, 0x7d00, 0x0048, 0x6935, 0x2001, 0x7615, 0x2004, 0xa202,
+	0x00c8, 0x6935, 0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x6934,
+	0x027e, 0x0e7e, 0x2071, 0x7600, 0x6210, 0x7058, 0xa202, 0x0048,
+	0x694a, 0x705c, 0xa202, 0x00c8, 0x694a, 0xa085, 0x0001, 0x0e7f,
+	0x027f, 0x007c, 0xa006, 0x0078, 0x6947, 0x0e7e, 0x0c7e, 0x037e,
+	0x007e, 0x127e, 0x2091, 0x8000, 0x2061, 0x7d00, 0x2071, 0x7600,
+	0x7344, 0x7060, 0xa302, 0x00c8, 0x6973, 0x601c, 0xa206, 0x00c0,
+	0x696b, 0x1078, 0x6ac3, 0x00c0, 0x6967, 0x1078, 0x5e4d, 0x0c7e,
+	0x1078, 0x5bfa, 0x0c7f, 0xace0, 0x0008, 0x7054, 0xac02, 0x00c8,
+	0x6973, 0x0078, 0x6958, 0x127f, 0x007f, 0x037f, 0x0c7f, 0x0e7f,
+	0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0x7720, 0x210c, 0x81ff,
+	0x0040, 0x6991, 0x2061, 0x7d00, 0x2071, 0x7600, 0x017e, 0x1078,
+	0x5b94, 0x017f, 0x0040, 0x6994, 0x611a, 0x1078, 0x22b5, 0x1078,
+	0x5bfa, 0xa006, 0x0078, 0x6996, 0xa085, 0x0001, 0x017f, 0x0c7f,
+	0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e,
+	0x1078, 0x5b94, 0x057f, 0x0040, 0x69b3, 0x6612, 0x651a, 0x601f,
+	0x0003, 0x2009, 0x004b, 0x1078, 0x5c21, 0xa085, 0x0001, 0x127f,
+	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x69af, 0x0c7e, 0x057e,
+	0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5b94, 0x057f,
+	0x0040, 0x69dd, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e,
+	0x2560, 0x1078, 0x399e, 0x0c7f, 0x1078, 0x495a, 0x1078, 0x489d,
+	0x2c08, 0x1078, 0x7370, 0x2009, 0x004c, 0x1078, 0x5c21, 0xa085,
+	0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x69d9,
+	0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078,
+	0x5b94, 0x057f, 0x0040, 0x6a08, 0x6612, 0x651a, 0x601f, 0x0003,
+	0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078, 0x399e, 0x0c7f, 0x1078,
+	0x495a, 0x1078, 0x489d, 0x2c08, 0x1078, 0x7370, 0x2009, 0x004d,
+	0x1078, 0x5c21, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c,
+	0xa006, 0x0078, 0x6a04, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000,
+	0x62a0, 0x0c7e, 0x1078, 0x5b94, 0x057f, 0x0040, 0x6a33, 0x6612,
 	0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x0c7e, 0x2560, 0x1078,
-	0x39a6, 0x0c7f, 0x1078, 0x4962, 0x1078, 0x48a5, 0x2c08, 0x1078,
-	0x737b, 0x2009, 0x004d, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f,
-	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a0f, 0x0c7e, 0x057e,
-	0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x5b9c, 0x057f,
-	0x0040, 0x6a3e, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005,
-	0x0c7e, 0x2560, 0x1078, 0x39a6, 0x0c7f, 0x1078, 0x4962, 0x1078,
-	0x48a5, 0x2c08, 0x1078, 0x737b, 0x2009, 0x004e, 0x1078, 0x5c29,
-	0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x6a3a, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c,
-	0x017f, 0x0040, 0x6a5a, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00,
-	0x6012, 0x2009, 0x001f, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f,
-	0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a57, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x6a76, 0x660a,
-	0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021, 0x1078,
-	0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x6a73, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c,
-	0x017f, 0x0040, 0x6a91, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
-	0x2009, 0x0000, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f,
-	0x007c, 0xa006, 0x0078, 0x6a8e, 0x027e, 0x0d7e, 0x6218, 0x2268,
-	0x6a3c, 0x82ff, 0x0040, 0x6a9e, 0x8211, 0x6a3e, 0x0d7f, 0x027f,
-	0x007c, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0014, 0x007c,
-	0x067e, 0x0c7e, 0x0d7e, 0x2031, 0x7652, 0x2634, 0xd6e4, 0x0040,
-	0x6ab6, 0x6618, 0x2660, 0x6e44, 0x1078, 0x38de, 0x0d7f, 0x0c7f,
-	0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0002, 0x0040,
-	0x6acb, 0xa08e, 0x0003, 0x0040, 0x6acb, 0xa08e, 0x0004, 0x0040,
-	0x6acb, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x007e, 0x017e,
-	0x6004, 0xa08e, 0x0000, 0x0040, 0x6ae3, 0xa08e, 0x001f, 0x0040,
-	0x6ae3, 0xa08e, 0x0028, 0x0040, 0x6ae3, 0xa08e, 0x0029, 0x0040,
-	0x6ae3, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b9c, 0x017f, 0x0040, 0x6b00,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x1078, 0x22bb, 0x2009,
-	0x0028, 0x1078, 0x5c29, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c,
-	0xa006, 0x0078, 0x6afd, 0xa186, 0x0015, 0x00c0, 0x6b18, 0x2011,
-	0x761e, 0x2204, 0xa086, 0x0074, 0x00c0, 0x6b18, 0x1078, 0x60d4,
-	0x6003, 0x0001, 0x6007, 0x0029, 0x1078, 0x4872, 0x0078, 0x6b1c,
-	0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, 0xa186, 0x0015, 0x00c0,
-	0x6b3a, 0x2011, 0x761e, 0x2204, 0xa086, 0x0014, 0x00c0, 0x6b3a,
-	0x0d7e, 0x6018, 0x2068, 0x1078, 0x38a1, 0x0d7f, 0x1078, 0x60de,
-	0x00c0, 0x6b3a, 0x2001, 0x0006, 0x1078, 0x37d1, 0x1078, 0x5cad,
-	0x0078, 0x6b3e, 0x1078, 0x5e57, 0x1078, 0x5c02, 0x007c, 0x6848,
-	0xa086, 0x0005, 0x00c0, 0x6b46, 0x1078, 0x6b47, 0x007c, 0x6850,
-	0xc0ad, 0x6852, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x12d5, 0x1079, 0x6b55, 0x067f, 0x007c, 0x6b65, 0x6d3c, 0x6e1d,
-	0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b9f, 0x6e8b, 0x6b65,
-	0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x6b65, 0x1078, 0x12d5, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12d5, 0x1079, 0x6b71, 0x067f,
-	0x007c, 0x6b81, 0x718c, 0x6b81, 0x6b81, 0x6b81, 0x6b81, 0x6b81,
-	0x6b81, 0x7167, 0x71d6, 0x6b81, 0x6b81, 0x6b81, 0x6b81, 0x6b81,
-	0x6b81, 0x1078, 0x12d5, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x12d5, 0x1079, 0x6b8d, 0x067f, 0x007c, 0x6b9d, 0x6fd8, 0x704a,
-	0x706c, 0x70b8, 0x6b9d, 0x6b9d, 0x7112, 0x6e97, 0x714f, 0x7153,
-	0x6b9d, 0x6b9d, 0x6b9d, 0x6b9d, 0x6b9d, 0x1078, 0x12d5, 0xa1b2,
-	0x0030, 0x10c8, 0x12d5, 0x2100, 0x0079, 0x6ba6, 0x6bd6, 0x6cb3,
-	0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6,
-	0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6,
-	0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd8, 0x6c07, 0x6c12,
-	0x6c3a, 0x6c40, 0x6c74, 0x6cac, 0x6bd6, 0x6bd6, 0x6cbb, 0x6bd6,
-	0x6bd6, 0x6cc2, 0x6cc9, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6, 0x6bd6,
-	0x6ce6, 0x6bd6, 0x6bd6, 0x6cf1, 0x6bd6, 0x6bd6, 0x1078, 0x12d5,
-	0x1078, 0x3a26, 0x6618, 0x0c7e, 0x2660, 0x1078, 0x3837, 0x0c7f,
+	0x399e, 0x0c7f, 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078,
+	0x7370, 0x2009, 0x004e, 0x1078, 0x5c21, 0xa085, 0x0001, 0x127f,
+	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a2f, 0x0c7e, 0x127e,
+	0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x6a4f,
+	0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x001f,
+	0x1078, 0x5c21, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
+	0x0078, 0x6a4c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
+	0x5b94, 0x017f, 0x0040, 0x6a6b, 0x660a, 0x611a, 0x601f, 0x0008,
+	0x2d00, 0x6012, 0x2009, 0x0021, 0x1078, 0x5c21, 0xa085, 0x0001,
+	0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6a68, 0x0c7e, 0x127e,
+	0x2091, 0x8000, 0x0c7e, 0x1078, 0x5b94, 0x017f, 0x0040, 0x6a86,
+	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078,
+	0x5c21, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
+	0x6a83, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040,
+	0x6a93, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x6013, 0x0000,
+	0x601f, 0x0007, 0x6017, 0x0014, 0x007c, 0x067e, 0x0c7e, 0x0d7e,
+	0x2031, 0x7652, 0x2634, 0xd6e4, 0x0040, 0x6aab, 0x6618, 0x2660,
+	0x6e44, 0x1078, 0x38d6, 0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e,
+	0x017e, 0x6004, 0xa08e, 0x0002, 0x0040, 0x6ac0, 0xa08e, 0x0003,
+	0x0040, 0x6ac0, 0xa08e, 0x0004, 0x0040, 0x6ac0, 0xa085, 0x0001,
+	0x017f, 0x007f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0000,
+	0x0040, 0x6ad8, 0xa08e, 0x001f, 0x0040, 0x6ad8, 0xa08e, 0x0028,
+	0x0040, 0x6ad8, 0xa08e, 0x0029, 0x0040, 0x6ad8, 0xa085, 0x0001,
+	0x017f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e,
+	0x1078, 0x5b94, 0x017f, 0x0040, 0x6af5, 0x611a, 0x601f, 0x0001,
+	0x2d00, 0x6012, 0x1078, 0x22b5, 0x2009, 0x0028, 0x1078, 0x5c21,
+	0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x6af2,
+	0xa186, 0x0015, 0x00c0, 0x6b0d, 0x2011, 0x761e, 0x2204, 0xa086,
+	0x0074, 0x00c0, 0x6b0d, 0x1078, 0x60ca, 0x6003, 0x0001, 0x6007,
+	0x0029, 0x1078, 0x486a, 0x0078, 0x6b11, 0x1078, 0x5e4d, 0x1078,
+	0x5bfa, 0x007c, 0xa186, 0x0015, 0x00c0, 0x6b2f, 0x2011, 0x761e,
+	0x2204, 0xa086, 0x0014, 0x00c0, 0x6b2f, 0x0d7e, 0x6018, 0x2068,
+	0x1078, 0x3899, 0x0d7f, 0x1078, 0x60d4, 0x00c0, 0x6b2f, 0x2001,
+	0x0006, 0x1078, 0x37c9, 0x1078, 0x5ca5, 0x0078, 0x6b33, 0x1078,
+	0x5e4d, 0x1078, 0x5bfa, 0x007c, 0x6848, 0xa086, 0x0005, 0x00c0,
+	0x6b3b, 0x1078, 0x6b3c, 0x007c, 0x6850, 0xc0ad, 0x6852, 0x007c,
+	0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x6b4a,
+	0x067f, 0x007c, 0x6b5a, 0x6d31, 0x6e12, 0x6b5a, 0x6b5a, 0x6b5a,
+	0x6b5a, 0x6b5a, 0x6b94, 0x6e80, 0x6b5a, 0x6b5a, 0x6b5a, 0x6b5a,
+	0x6b5a, 0x6b5a, 0x1078, 0x12cd, 0x067e, 0x6000, 0xa0b2, 0x0010,
+	0x10c8, 0x12cd, 0x1079, 0x6b66, 0x067f, 0x007c, 0x6b76, 0x7181,
+	0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x715c, 0x71cb,
+	0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x6b76, 0x1078, 0x12cd,
+	0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x12cd, 0x1079, 0x6b82,
+	0x067f, 0x007c, 0x6b92, 0x6fcd, 0x703f, 0x7061, 0x70ad, 0x6b92,
+	0x6b92, 0x7107, 0x6e8c, 0x7144, 0x7148, 0x6b92, 0x6b92, 0x6b92,
+	0x6b92, 0x6b92, 0x1078, 0x12cd, 0xa1b2, 0x0030, 0x10c8, 0x12cd,
+	0x2100, 0x0079, 0x6b9b, 0x6bcb, 0x6ca8, 0x6bcb, 0x6bcb, 0x6bcb,
+	0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb,
+	0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb,
+	0x6bcb, 0x6bcb, 0x6bcd, 0x6bfc, 0x6c07, 0x6c2f, 0x6c35, 0x6c69,
+	0x6ca1, 0x6bcb, 0x6bcb, 0x6cb0, 0x6bcb, 0x6bcb, 0x6cb7, 0x6cbe,
+	0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6bcb, 0x6cdb, 0x6bcb, 0x6bcb,
+	0x6ce6, 0x6bcb, 0x6bcb, 0x1078, 0x12cd, 0x1078, 0x3a1e, 0x6618,
+	0x0c7e, 0x2660, 0x1078, 0x382f, 0x0c7f, 0xa6b0, 0x0001, 0x2634,
+	0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x6bee, 0x1078, 0x72ac,
+	0x00c0, 0x6c29, 0x1078, 0x724a, 0x00c0, 0x6bea, 0x6007, 0x0008,
+	0x0078, 0x6ca3, 0x6007, 0x0009, 0x0078, 0x6ca3, 0x1078, 0x7441,
+	0x0040, 0x6bf8, 0x1078, 0x72ac, 0x0040, 0x6be2, 0x0078, 0x6c29,
+	0x6013, 0x1900, 0x0078, 0x6bea, 0x6106, 0x1078, 0x720c, 0x6007,
+	0x0006, 0x0078, 0x6ca3, 0x6007, 0x0007, 0x0078, 0x6ca3, 0x0d7e,
+	0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006,
+	0x0040, 0x6c19, 0xa686, 0x0004, 0x0040, 0x6c19, 0x0d7f, 0x0078,
+	0x6c29, 0x1078, 0x730a, 0x00c0, 0x6c24, 0x1078, 0x3899, 0x6007,
+	0x000a, 0x0d7f, 0x0078, 0x6ca3, 0x6007, 0x000b, 0x0d7f, 0x0078,
+	0x6ca3, 0x1078, 0x22b5, 0x6007, 0x0001, 0x0078, 0x6ca3, 0x1078,
+	0x22b5, 0x6007, 0x000c, 0x0078, 0x6ca3, 0x1078, 0x3a1e, 0x6618,
 	0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048,
-	0x6bf9, 0x1078, 0x72b7, 0x00c0, 0x6c34, 0x1078, 0x7255, 0x00c0,
-	0x6bf5, 0x6007, 0x0008, 0x0078, 0x6cae, 0x6007, 0x0009, 0x0078,
-	0x6cae, 0x1078, 0x744c, 0x0040, 0x6c03, 0x1078, 0x72b7, 0x0040,
-	0x6bed, 0x0078, 0x6c34, 0x6013, 0x1900, 0x0078, 0x6bf5, 0x6106,
-	0x1078, 0x7217, 0x6007, 0x0006, 0x0078, 0x6cae, 0x6007, 0x0007,
-	0x0078, 0x6cae, 0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x6c24, 0xa686, 0x0004, 0x0040,
-	0x6c24, 0x0d7f, 0x0078, 0x6c34, 0x1078, 0x7315, 0x00c0, 0x6c2f,
-	0x1078, 0x38a1, 0x6007, 0x000a, 0x0d7f, 0x0078, 0x6cae, 0x6007,
-	0x000b, 0x0d7f, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x0001,
-	0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x000c, 0x0078, 0x6cae,
-	0x1078, 0x3a26, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff,
-	0xa082, 0x0006, 0x0048, 0x6c61, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0006, 0x00c0, 0x6c34, 0x1078, 0x7324, 0x00c0, 0x6c5b, 0x6007,
-	0x000e, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x000f, 0x0078,
-	0x6cae, 0x1078, 0x744c, 0x0040, 0x6c6e, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x0040, 0x6c53, 0x0078, 0x6c34, 0x6013, 0x1900,
-	0x6007, 0x0009, 0x0078, 0x6cae, 0x1078, 0x3a26, 0x6618, 0xa6b0,
-	0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x6c99,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, 0x6c34, 0x1078,
-	0x734f, 0x00c0, 0x6c93, 0x1078, 0x7255, 0x00c0, 0x6c93, 0x6007,
-	0x0010, 0x0078, 0x6cae, 0x1078, 0x22bb, 0x6007, 0x0011, 0x0078,
-	0x6cae, 0x1078, 0x744c, 0x0040, 0x6ca6, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x0040, 0x6c87, 0x0078, 0x6c34, 0x6013, 0x1900,
-	0x6007, 0x0009, 0x0078, 0x6cae, 0x6007, 0x0012, 0x6003, 0x0001,
-	0x1078, 0x4872, 0x007c, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
-	0x4872, 0x0078, 0x6cb2, 0x6007, 0x0020, 0x6003, 0x0001, 0x1078,
-	0x4872, 0x007c, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078, 0x4872,
-	0x007c, 0x017e, 0x027e, 0x2011, 0x7b88, 0x2214, 0x2c08, 0x1078,
-	0x7514, 0x00c0, 0x6cda, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700,
-	0x0078, 0x6cdf, 0x1078, 0x5c02, 0x2160, 0x6007, 0x0025, 0x6003,
-	0x0001, 0x1078, 0x4872, 0x027f, 0x017f, 0x007c, 0x6106, 0x1078,
-	0x6cf8, 0x6007, 0x002b, 0x0078, 0x6cae, 0x6007, 0x002c, 0x0078,
-	0x6cae, 0x6106, 0x1078, 0x6cfd, 0x6007, 0x002e, 0x0078, 0x6cae,
-	0x0d7e, 0x1078, 0x6d23, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x6d32,
-	0x00c0, 0x6d1c, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084, 0x00ff,
-	0xa115, 0x6212, 0xd1e4, 0x0040, 0x6d11, 0x2009, 0x0001, 0x0078,
-	0x6d18, 0xd1ec, 0x0040, 0x6d1c, 0x2009, 0x0000, 0xa294, 0x00ff,
-	0x1078, 0x22ff, 0x0078, 0x6d20, 0xa085, 0x0001, 0x0078, 0x6d21,
-	0xa006, 0x0d7f, 0x007c, 0x2069, 0x7b8d, 0x6800, 0xa082, 0x0010,
-	0x00c8, 0x6d30, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x6d31,
-	0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0x7b8c, 0x6808, 0xa084,
-	0xff00, 0xa086, 0x0800, 0x007c, 0x6004, 0xa0b2, 0x0030, 0x10c8,
-	0x12d5, 0xa1b6, 0x0013, 0x00c0, 0x6d48, 0x2008, 0x0079, 0x6d5b,
-	0xa1b6, 0x0027, 0x0040, 0x6d50, 0xa1b6, 0x0014, 0x10c0, 0x12d5,
-	0x2001, 0x0007, 0x1078, 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1,
-	0x1078, 0x4c7a, 0x007c, 0x6d8b, 0x6d8d, 0x6d8b, 0x6d8b, 0x6d8b,
-	0x6d8d, 0x6d95, 0x6df8, 0x6dbb, 0x6df8, 0x6dcf, 0x6df8, 0x6d95,
-	0x6df8, 0x6df0, 0x6df8, 0x6df0, 0x6df8, 0x6df8, 0x6d8b, 0x6d8b,
-	0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b,
-	0x6d8b, 0x6d8b, 0x6d8b, 0x6df8, 0x6d8b, 0x6d8b, 0x6df8, 0x6d8b,
-	0x6df8, 0x6df8, 0x6d8b, 0x6d8b, 0x6d8b, 0x6d8b, 0x6df8, 0x6df8,
-	0x6d8b, 0x6df8, 0x6df8, 0x1078, 0x12d5, 0x1078, 0x4b81, 0x6003,
-	0x0002, 0x1078, 0x4c7a, 0x0078, 0x6dfe, 0x0f7e, 0x2079, 0x7651,
-	0x7804, 0x0f7f, 0xd0ac, 0x00c0, 0x6df8, 0x2001, 0x0000, 0x1078,
-	0x37bd, 0x2001, 0x0002, 0x1078, 0x37d1, 0x1078, 0x4b81, 0x601f,
-	0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078, 0x4872, 0x1078,
-	0x4c7a, 0x0c7e, 0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x457b,
-	0x0c7f, 0x0078, 0x6dfe, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6df8, 0xa686,
-	0x0004, 0x0040, 0x6df8, 0x2001, 0x0004, 0x0078, 0x6df6, 0x2001,
-	0x7600, 0x2004, 0xa086, 0x0003, 0x00c0, 0x6dd8, 0x1078, 0x2dc8,
-	0x2001, 0x0006, 0x1078, 0x6dff, 0x6618, 0x0d7e, 0x2668, 0x6e04,
-	0x0d7f, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x6df8,
-	0x2001, 0x0006, 0x0078, 0x6df6, 0x2001, 0x0004, 0x0078, 0x6df6,
-	0x2001, 0x0006, 0x1078, 0x6dff, 0x0078, 0x6df8, 0x1078, 0x37df,
-	0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c, 0x017e,
-	0x0d7e, 0x6118, 0x2168, 0x6900, 0xd184, 0x0040, 0x6e1a, 0x6104,
-	0xa18e, 0x000a, 0x00c0, 0x6e12, 0x699c, 0xd1a4, 0x00c0, 0x6e12,
-	0x2001, 0x0007, 0x1078, 0x37d1, 0x2001, 0x0000, 0x1078, 0x37bd,
-	0x1078, 0x22dd, 0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668,
-	0x6804, 0xa084, 0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8,
-	0x12d5, 0xa1b6, 0x0015, 0x00c0, 0x6e31, 0x1079, 0x6e38, 0x0078,
-	0x6e37, 0xa1b6, 0x0016, 0x10c0, 0x12d5, 0x1079, 0x6e70, 0x007c,
-	0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x6e44,
-	0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x0f7e, 0x2079, 0x7651, 0x7804,
-	0x0f7f, 0xd0ac, 0x00c0, 0x6e60, 0x2001, 0x0000, 0x1078, 0x37bd,
-	0x2001, 0x0002, 0x1078, 0x37d1, 0x601f, 0x0001, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x1078, 0x4872, 0x1078, 0x4c7a, 0x0078, 0x6e6f,
-	0x2011, 0x7b83, 0x220c, 0x017e, 0x0c7e, 0x1078, 0x3825, 0x00c0,
-	0x6e6f, 0x1078, 0x3621, 0x0c7f, 0x017f, 0x1078, 0x5c02, 0x007c,
-	0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x6e7c,
-	0x5ee1, 0x5ee1, 0x5ee1, 0x5ee1, 0x1078, 0x60d1, 0x00c0, 0x6e88,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x4872, 0x0078, 0x6e8a,
-	0x1078, 0x5c02, 0x007c, 0x6004, 0xa08a, 0x0030, 0x10c8, 0x12d5,
-	0x1078, 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182,
-	0x0040, 0x0079, 0x6e9b, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6ead,
-	0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab, 0x6eab,
-	0x6eab, 0x6eab, 0x6eab, 0x1078, 0x12d5, 0x0d7e, 0x0e7e, 0x0f7e,
-	0x157e, 0x047e, 0x027e, 0x6106, 0x2071, 0x7b80, 0x7444, 0xa4a4,
-	0xe600, 0x0040, 0x6f1e, 0xa486, 0x2000, 0x0040, 0x6edd, 0xa486,
-	0x0400, 0x0040, 0x6edd, 0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010,
-	0x00c8, 0x6fb0, 0x0c7e, 0x1078, 0x460c, 0x2c68, 0x0c7f, 0x6a00,
-	0xa284, 0x0001, 0x0040, 0x6f91, 0x1078, 0x46ca, 0x0040, 0x6fbc,
-	0xa295, 0x0200, 0x6a02, 0x0078, 0x6ee3, 0x2009, 0x0001, 0x2011,
-	0x0200, 0x1078, 0x46b4, 0x1078, 0x132f, 0x1040, 0x12d5, 0x6003,
-	0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000,
-	0x6c5a, 0x2c00, 0x685e, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
-	0xa18c, 0x00ff, 0xa10d, 0x6946, 0x684f, 0x0000, 0x6857, 0x0036,
-	0x1078, 0x3a7a, 0xa486, 0x2000, 0x00c0, 0x6f0c, 0x2019, 0x0017,
-	0x1078, 0x74d9, 0x0078, 0x6f7e, 0xa486, 0x0400, 0x00c0, 0x6f16,
-	0x2019, 0x0002, 0x1078, 0x74d9, 0x0078, 0x6f7e, 0xa486, 0x0200,
-	0x00c0, 0x6f1c, 0x1078, 0x74ca, 0x0078, 0x6f7e, 0x7130, 0xa184,
-	0xff00, 0x00c0, 0x6fd0, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8,
-	0x6fd0, 0x0c7e, 0x1078, 0x460c, 0x2c68, 0x0c7f, 0x6a00, 0xa284,
-	0x0001, 0x0040, 0x6fd4, 0xa284, 0x0300, 0x00c0, 0x6fcc, 0x6804,
-	0xa005, 0x0040, 0x6fbc, 0x8001, 0x6806, 0x6003, 0x0007, 0x1078,
-	0x1314, 0x0040, 0x6f85, 0x6013, 0x0000, 0x6803, 0x0000, 0x6837,
-	0x0116, 0x683b, 0x0000, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0,
-	0x8007, 0xa10d, 0x6946, 0x6853, 0x003d, 0x7044, 0xa084, 0x0003,
-	0xa086, 0x0002, 0x00c0, 0x6f60, 0x684f, 0x0040, 0x0078, 0x6f6a,
-	0xa086, 0x0001, 0x00c0, 0x6f68, 0x684f, 0x0080, 0x0078, 0x6f6a,
-	0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x7b90, 0xad90, 0x0015,
-	0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x6f70, 0x200c,
-	0x6982, 0x8000, 0x200c, 0x697e, 0x1078, 0x3a7a, 0x027f, 0x047f,
-	0x157f, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x0078,
-	0x6f7e, 0x2069, 0x7b92, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200,
-	0x00c0, 0x6fb0, 0x2069, 0x7b80, 0x686c, 0xa084, 0x00ff, 0x017e,
-	0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003, 0x0001,
-	0x6007, 0x0043, 0x1078, 0x4825, 0x1078, 0x4c7a, 0x0078, 0x6f7e,
-	0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4825,
-	0x1078, 0x4c7a, 0x0078, 0x6f7e, 0x6013, 0x0300, 0x0078, 0x6fc2,
-	0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x4825,
-	0x1078, 0x4c7a, 0x0078, 0x6f7e, 0x6013, 0x0500, 0x0078, 0x6fc2,
-	0x6013, 0x0600, 0x0078, 0x6f91, 0x6013, 0x0200, 0x0078, 0x6f91,
-	0xa186, 0x0013, 0x00c0, 0x6fea, 0x6004, 0xa08a, 0x0040, 0x1048,
-	0x12d5, 0xa08a, 0x0050, 0x10c8, 0x12d5, 0xa082, 0x0040, 0x2008,
-	0x0079, 0x701b, 0xa186, 0x0047, 0x00c0, 0x6ff0, 0x0078, 0x704a,
-	0xa186, 0x0027, 0x0040, 0x6ff8, 0xa186, 0x0014, 0x10c0, 0x12d5,
-	0x6004, 0xa082, 0x0040, 0x2008, 0x0079, 0x6ffe, 0x700e, 0x7010,
-	0x7010, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e,
-	0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x700e, 0x1078, 0x12d5,
-	0x2001, 0x0007, 0x1078, 0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1,
-	0x1078, 0x4c7a, 0x007c, 0x702b, 0x703b, 0x7034, 0x7044, 0x702b,
-	0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b, 0x702b,
-	0x702b, 0x702b, 0x702b, 0x1078, 0x12d5, 0x6010, 0xa088, 0x0013,
-	0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x4b81, 0x6003, 0x0002,
-	0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x1078, 0x468d, 0x1078,
-	0x5c02, 0x1078, 0x4c7a, 0x007c, 0x1078, 0x4b81, 0x2009, 0x0041,
-	0x0078, 0x7112, 0xa182, 0x0040, 0x0079, 0x704e, 0x705e, 0x7060,
-	0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x7061, 0x705e, 0x705e,
-	0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x705e, 0x1078, 0x12d5,
-	0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x1078, 0x1572, 0x007c, 0xa182, 0x0040, 0x0079, 0x7070,
-	0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080, 0x7080,
-	0x7080, 0x7082, 0x70a5, 0x7080, 0x7080, 0x7080, 0x7080, 0x70a5,
-	0x1078, 0x12d5, 0x1078, 0x4c29, 0x1078, 0x4d3a, 0x6010, 0x0d7e,
-	0x2068, 0x684c, 0xd0fc, 0x0040, 0x7098, 0xa08c, 0x0003, 0xa18e,
-	0x0002, 0x0040, 0x709e, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x7112,
-	0x6003, 0x0007, 0x1078, 0x468d, 0x0d7f, 0x007c, 0x1078, 0x468d,
-	0x1078, 0x5c02, 0x0d7f, 0x0078, 0x709d, 0x037e, 0x1078, 0x4c29,
-	0x1078, 0x4d3a, 0x6010, 0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078,
-	0x74fd, 0x1078, 0x6aa1, 0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c,
-	0xa186, 0x0013, 0x00c0, 0x70c6, 0x6004, 0xa086, 0x0042, 0x10c0,
-	0x12d5, 0x1078, 0x4b81, 0x1078, 0x4c7a, 0x007c, 0xa186, 0x0027,
-	0x0040, 0x70ce, 0xa186, 0x0014, 0x00c0, 0x70de, 0x6004, 0xa086,
-	0x0042, 0x10c0, 0x12d5, 0x2001, 0x0007, 0x1078, 0x37df, 0x1078,
-	0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x70e2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2,
-	0x70f2, 0x70f4, 0x7100, 0x70f2, 0x70f2, 0x70f2, 0x70f2, 0x70f2,
-	0x70f2, 0x70f2, 0x1078, 0x12d5, 0x037e, 0x047e, 0x20e1, 0x0005,
-	0x3d18, 0x3e20, 0x2c10, 0x1078, 0x1572, 0x047f, 0x037f, 0x007c,
-	0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x710c, 0x2009,
-	0x0041, 0x0d7f, 0x0078, 0x7112, 0x6003, 0x0007, 0x1078, 0x468d,
-	0x0d7f, 0x007c, 0xa182, 0x0040, 0x0079, 0x7116, 0x7126, 0x7128,
-	0x7134, 0x7140, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126,
-	0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x7126, 0x1078, 0x12d5,
-	0x6003, 0x0001, 0x6106, 0x1078, 0x4825, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x4c7a, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078,
-	0x4825, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c7a, 0x127f, 0x007c,
-	0x6003, 0x0003, 0x6106, 0x2c10, 0x1078, 0x19cf, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x4891, 0x1078, 0x4d3a, 0x127f, 0x007c, 0x1078,
-	0x4b81, 0x0078, 0x7155, 0x1078, 0x4c29, 0x6110, 0x81ff, 0x0040,
-	0x7162, 0x0d7e, 0x2168, 0x037e, 0x2019, 0x0029, 0x1078, 0x74fd,
-	0x037f, 0x0d7f, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0xa182,
-	0x0085, 0x0079, 0x716b, 0x7172, 0x7172, 0x7172, 0x7174, 0x7172,
-	0x7172, 0x7172, 0x1078, 0x12d5, 0x027e, 0x0e7e, 0x2071, 0x7b80,
-	0x7220, 0x1078, 0x7417, 0x0040, 0x7181, 0x6007, 0x0086, 0x0078,
-	0x7183, 0x6007, 0x0087, 0x6003, 0x0001, 0x1078, 0x4825, 0x1078,
-	0x4c7a, 0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x719d,
-	0x6004, 0xa08a, 0x0085, 0x1048, 0x12d5, 0xa08a, 0x008c, 0x10c8,
-	0x12d5, 0xa082, 0x0085, 0x0079, 0x71b0, 0xa186, 0x0027, 0x0040,
-	0x71a5, 0xa186, 0x0014, 0x10c0, 0x12d5, 0x2001, 0x0007, 0x1078,
-	0x37df, 0x1078, 0x4b81, 0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c,
-	0x71b7, 0x71b9, 0x71b9, 0x71b7, 0x71b7, 0x71b7, 0x71b7, 0x1078,
-	0x12d5, 0x1078, 0x4b81, 0x1078, 0x5c02, 0x1078, 0x4c7a, 0x007c,
-	0xa182, 0x0085, 0x1048, 0x12d5, 0xa182, 0x008c, 0x10c8, 0x12d5,
-	0xa182, 0x0085, 0x0079, 0x71cc, 0x71d3, 0x71d3, 0x71d3, 0x71d5,
-	0x71d3, 0x71d3, 0x71d3, 0x1078, 0x12d5, 0x007c, 0x1078, 0x4b81,
-	0x1078, 0x6aa1, 0x1078, 0x4c7a, 0x007c, 0x037e, 0x2019, 0x000b,
-	0x1078, 0x71e6, 0x601f, 0x0006, 0x037f, 0x007c, 0x127e, 0x037e,
-	0x087e, 0x2091, 0x8000, 0x2c40, 0x1078, 0x5915, 0x00c0, 0x7213,
-	0x1078, 0x59b6, 0x00c0, 0x7213, 0x6000, 0xa086, 0x0000, 0x0040,
-	0x7213, 0x601c, 0xa086, 0x0007, 0x0040, 0x7213, 0x0d7e, 0x6000,
-	0xa086, 0x0004, 0x00c0, 0x7206, 0x1078, 0x1676, 0x6010, 0x2068,
-	0x1078, 0x693e, 0x0040, 0x720e, 0x1078, 0x74fd, 0x0d7f, 0x6013,
-	0x0000, 0x601f, 0x0007, 0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e,
-	0x0c7e, 0x037e, 0x157e, 0x2079, 0x7b80, 0x7838, 0xa08c, 0x00ff,
-	0x783c, 0x1078, 0x2085, 0x00c0, 0x724e, 0x017e, 0x0c7e, 0x1078,
-	0x3825, 0x00c0, 0x724e, 0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9,
-	0x0004, 0x1078, 0x616a, 0x00c0, 0x724e, 0x017f, 0x027f, 0x027e,
-	0x017e, 0x2019, 0x0029, 0x1078, 0x5a8a, 0x1078, 0x4962, 0x1078,
-	0x48a5, 0x017f, 0x1078, 0x737b, 0x1078, 0x39a6, 0x017f, 0x1078,
-	0x3621, 0x6612, 0x6516, 0xa006, 0x0078, 0x7250, 0x0c7f, 0x017f,
-	0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e,
-	0x2009, 0x761e, 0x2104, 0xa086, 0x0074, 0x00c0, 0x72ac, 0x2069,
-	0x7b8e, 0x690c, 0xa182, 0x0100, 0x0048, 0x729c, 0x6908, 0xa184,
-	0x8000, 0x0040, 0x72a8, 0xa184, 0x0800, 0x0040, 0x72a8, 0x6910,
-	0xa18a, 0x0001, 0x0048, 0x72a0, 0x6914, 0x2069, 0x7bae, 0x6904,
-	0x81ff, 0x00c0, 0x7294, 0x690c, 0xa182, 0x0100, 0x0048, 0x729c,
-	0x6908, 0x81ff, 0x00c0, 0x7298, 0x6910, 0xa18a, 0x0001, 0x0048,
-	0x72a0, 0x6918, 0xa18a, 0x0001, 0x0048, 0x72a8, 0x0078, 0x72b2,
-	0x6013, 0x0100, 0x0078, 0x72ae, 0x6013, 0x0300, 0x0078, 0x72ae,
-	0x6013, 0x0500, 0x0078, 0x72ae, 0x6013, 0x0700, 0x0078, 0x72ae,
-	0x6013, 0x0900, 0x0078, 0x72ae, 0x6013, 0x0b00, 0x0078, 0x72ae,
-	0x6013, 0x0f00, 0x0078, 0x72ae, 0x6013, 0x2d00, 0xa085, 0x0001,
-	0x0078, 0x72b3, 0xa006, 0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e,
-	0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394,
-	0x00ff, 0xa286, 0x0006, 0x0040, 0x72db, 0xa286, 0x0004, 0x0040,
-	0x72db, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x72db,
-	0xa286, 0x0004, 0x0040, 0x72db, 0x0c7e, 0x2d60, 0x1078, 0x3837,
-	0x0c7f, 0x0078, 0x730e, 0x2011, 0x7b96, 0xad98, 0x000a, 0x20a9,
-	0x0004, 0x1078, 0x616a, 0x00c0, 0x730f, 0x2011, 0x7b9a, 0xad98,
-	0x0006, 0x20a9, 0x0004, 0x1078, 0x616a, 0x00c0, 0x730f, 0x047e,
-	0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0x7652,
-	0x210c, 0xd1a4, 0x0040, 0x7303, 0x2009, 0x0029, 0x1078, 0x7541,
-	0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x4962, 0x1078,
-	0x48a5, 0x2c08, 0x1078, 0x737b, 0x017f, 0x047f, 0xa006, 0x157f,
-	0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x7b8e,
-	0x6800, 0xa086, 0x0800, 0x0040, 0x7321, 0x6013, 0x0000, 0x0078,
-	0x7322, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e,
-	0x037e, 0x157e, 0x2079, 0x7b8c, 0x7930, 0x7834, 0x1078, 0x2085,
-	0x00c0, 0x7348, 0x1078, 0x3825, 0x00c0, 0x7348, 0x2011, 0x7b90,
-	0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x616a, 0x00c0, 0x7348,
-	0x2011, 0x7b94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x616a,
-	0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e,
-	0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0x7b83, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x2085, 0x00c0, 0x7374, 0x1078, 0x3825,
-	0x00c0, 0x7374, 0x2011, 0x7b96, 0xac98, 0x000a, 0x20a9, 0x0004,
-	0x1078, 0x616a, 0x00c0, 0x7374, 0x2011, 0x7b9a, 0xac98, 0x0006,
-	0x20a9, 0x0004, 0x1078, 0x616a, 0x157f, 0x037f, 0x027f, 0x017f,
-	0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e,
-	0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2029, 0x783f, 0x252c,
-	0x2021, 0x7845, 0x2424, 0x2061, 0x7d00, 0x2071, 0x7600, 0x7644,
-	0x7060, 0x8001, 0xa602, 0x00c8, 0x73e0, 0x2100, 0xac06, 0x0040,
-	0x73d6, 0x1078, 0x7559, 0x0040, 0x73d6, 0x671c, 0xa786, 0x0001,
-	0x0040, 0x73f5, 0xa786, 0x0007, 0x0040, 0x73d6, 0x2500, 0xac06,
-	0x0040, 0x73d6, 0x2400, 0xac06, 0x0040, 0x73d6, 0x1078, 0x756d,
-	0x00c0, 0x73d6, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x73bc,
-	0x017e, 0x1078, 0x1676, 0x017f, 0x6010, 0x2068, 0x1078, 0x693e,
-	0x0040, 0x73d3, 0xa786, 0x0003, 0x00c0, 0x73e9, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x017e, 0x1078, 0x6b3f, 0x1078, 0x3a7a,
-	0x017f, 0x1078, 0x6a94, 0x0d7f, 0x1078, 0x6aa1, 0xace0, 0x0008,
-	0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x73e0, 0x0078, 0x738d,
-	0x127f, 0x027f, 0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f,
-	0x007c, 0xa786, 0x0006, 0x00c0, 0x73c6, 0xa386, 0x0005, 0x0040,
-	0x73d6, 0x1078, 0x74fd, 0x0078, 0x73d3, 0x1078, 0x756d, 0x00c0,
-	0x73d6, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x00c0, 0x73d6,
-	0x6000, 0xa086, 0x0002, 0x00c0, 0x73d6, 0x1078, 0x6aba, 0x0040,
-	0x7411, 0x1078, 0x6ace, 0x00c0, 0x73d6, 0x1078, 0x5e57, 0x0078,
-	0x7413, 0x1078, 0x22dd, 0x1078, 0x6aa1, 0x0078, 0x73d6, 0x0c7e,
-	0x0e7e, 0x017e, 0x2c08, 0x2170, 0x1078, 0x7514, 0x017f, 0x0040,
-	0x7426, 0x601c, 0xa084, 0x000f, 0x1079, 0x7429, 0x0e7f, 0x0c7f,
-	0x007c, 0x7431, 0x7431, 0x7431, 0x7431, 0x7431, 0x7431, 0x7433,
-	0x7431, 0xa006, 0x007c, 0x047e, 0x017e, 0x7018, 0xa080, 0x0028,
-	0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x1078,
-	0x7541, 0x017f, 0x047f, 0x037e, 0x2019, 0x0002, 0x1078, 0x71e6,
-	0x037f, 0xa085, 0x0001, 0x007c, 0x2001, 0x0001, 0x1078, 0x37bd,
-	0x157e, 0x017e, 0x027e, 0x037e, 0x20a9, 0x0004, 0x2019, 0x7605,
-	0x2011, 0x7b96, 0x1078, 0x616a, 0x037f, 0x027f, 0x017f, 0x157f,
-	0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e,
-	0x127e, 0x2091, 0x8000, 0x2061, 0x7d00, 0x2079, 0x0001, 0x8fff,
-	0x0040, 0x74bd, 0x2071, 0x7600, 0x7644, 0x7060, 0x8001, 0xa602,
-	0x00c8, 0x74bd, 0x88ff, 0x0040, 0x7483, 0x2800, 0xac06, 0x00c0,
-	0x74b3, 0x2079, 0x0000, 0x1078, 0x7559, 0x0040, 0x74b3, 0x2400,
-	0xac06, 0x0040, 0x74b3, 0x671c, 0xa786, 0x0006, 0x00c0, 0x74b3,
-	0xa786, 0x0007, 0x0040, 0x74b3, 0x88ff, 0x00c0, 0x749b, 0x6018,
-	0xa206, 0x00c0, 0x74b3, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0,
-	0x74a3, 0x1078, 0x1676, 0x6010, 0x2068, 0x1078, 0x693e, 0x0040,
-	0x74ad, 0x047e, 0x1078, 0x74fd, 0x047f, 0x0d7f, 0x1078, 0x6aa1,
-	0x88ff, 0x00c0, 0x74c6, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004,
-	0xac02, 0x00c8, 0x74bd, 0x0078, 0x746f, 0xa006, 0x127f, 0x027f,
-	0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001,
-	0x0078, 0x74be, 0x087e, 0x2041, 0x0000, 0x2c20, 0x2019, 0x0002,
-	0x6218, 0x1078, 0x5915, 0x1078, 0x59b6, 0x1078, 0x7462, 0x087f,
-	0x007c, 0x027e, 0x047e, 0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x3825, 0x00c0,
-	0x74f2, 0x2c10, 0x2041, 0x0000, 0x1078, 0x5915, 0x1078, 0x59b6,
-	0x1078, 0x7462, 0x037f, 0x017f, 0x8108, 0x00f0, 0x74e3, 0x157f,
-	0x0c7f, 0x087f, 0x047f, 0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff,
-	0x0040, 0x7511, 0x6800, 0xa07d, 0x0040, 0x750e, 0x6803, 0x0000,
-	0x6b52, 0x1078, 0x3a7a, 0x2f68, 0x0078, 0x7502, 0x6b52, 0x1078,
-	0x3a7a, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061,
-	0x7d00, 0x2071, 0x7600, 0x7444, 0x7060, 0x8001, 0xa402, 0x00c8,
-	0x753c, 0x2100, 0xac06, 0x0040, 0x752e, 0x6000, 0xa086, 0x0000,
-	0x0040, 0x752e, 0x6008, 0xa206, 0x0040, 0x7538, 0xace0, 0x0008,
-	0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x753c, 0x0078, 0x7519,
-	0xa085, 0x0001, 0x0078, 0x753d, 0xa006, 0x037f, 0x047f, 0x0e7f,
-	0x007c, 0x0d7e, 0x007e, 0x1078, 0x132f, 0x007f, 0x1040, 0x12d5,
-	0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000,
-	0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0x1078, 0x3a7a, 0x0d7f,
-	0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0x756c, 0xa786, 0x0001,
-	0x0040, 0x756c, 0xa786, 0x000a, 0x0040, 0x756c, 0xa786, 0x0009,
-	0x0040, 0x756c, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018, 0x2070,
-	0x70a0, 0xa206, 0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091,
-	0x8000, 0x2071, 0x7640, 0xd5a4, 0x0040, 0x7581, 0x7034, 0x8000,
-	0x7036, 0xd5b4, 0x0040, 0x7587, 0x7030, 0x8000, 0x7032, 0xd5ac,
-	0x0040, 0x758e, 0x2071, 0x764a, 0x1078, 0x75bd, 0x0e7f, 0x007f,
-	0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
-	0x7640, 0xd5a4, 0x0040, 0x759f, 0x7034, 0x8000, 0x7036, 0xd5b4,
-	0x0040, 0x75a5, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x75ac,
-	0x2071, 0x764a, 0x1078, 0x75bd, 0x0e7f, 0x007f, 0x127f, 0x007c,
-	0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7642, 0x1078,
-	0x75bd, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x2e04, 0x8000, 0x2072,
-	0x00c8, 0x75c6, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e,
-	0x2071, 0x7640, 0x1078, 0x75bd, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
-	0x7644, 0x1078, 0x75bd, 0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004,
-	0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400,
-	0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0xaaff
+	0x6c56, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x00c0, 0x6c29,
+	0x1078, 0x7319, 0x00c0, 0x6c50, 0x6007, 0x000e, 0x0078, 0x6ca3,
+	0x1078, 0x22b5, 0x6007, 0x000f, 0x0078, 0x6ca3, 0x1078, 0x7441,
+	0x0040, 0x6c63, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040,
+	0x6c48, 0x0078, 0x6c29, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078,
+	0x6ca3, 0x1078, 0x3a1e, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684,
+	0x00ff, 0xa082, 0x0006, 0x0048, 0x6c8e, 0xa6b4, 0xff00, 0x8637,
+	0xa686, 0x0006, 0x00c0, 0x6c29, 0x1078, 0x7344, 0x00c0, 0x6c88,
+	0x1078, 0x724a, 0x00c0, 0x6c88, 0x6007, 0x0010, 0x0078, 0x6ca3,
+	0x1078, 0x22b5, 0x6007, 0x0011, 0x0078, 0x6ca3, 0x1078, 0x7441,
+	0x0040, 0x6c9b, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0040,
+	0x6c7c, 0x0078, 0x6c29, 0x6013, 0x1900, 0x6007, 0x0009, 0x0078,
+	0x6ca3, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x486a, 0x007c,
+	0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x486a, 0x0078, 0x6ca7,
+	0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x486a, 0x007c, 0x6007,
+	0x0023, 0x6003, 0x0001, 0x1078, 0x486a, 0x007c, 0x017e, 0x027e,
+	0x2011, 0x7b88, 0x2214, 0x2c08, 0x1078, 0x7509, 0x00c0, 0x6ccf,
+	0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x0078, 0x6cd4, 0x1078,
+	0x5bfa, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x486a,
+	0x027f, 0x017f, 0x007c, 0x6106, 0x1078, 0x6ced, 0x6007, 0x002b,
+	0x0078, 0x6ca3, 0x6007, 0x002c, 0x0078, 0x6ca3, 0x6106, 0x1078,
+	0x6cf2, 0x6007, 0x002e, 0x0078, 0x6ca3, 0x0d7e, 0x1078, 0x6d18,
+	0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x6d27, 0x00c0, 0x6d11, 0x680c,
+	0xa08c, 0xff00, 0x6824, 0xa084, 0x00ff, 0xa115, 0x6212, 0xd1e4,
+	0x0040, 0x6d06, 0x2009, 0x0001, 0x0078, 0x6d0d, 0xd1ec, 0x0040,
+	0x6d11, 0x2009, 0x0000, 0xa294, 0x00ff, 0x1078, 0x22f9, 0x0078,
+	0x6d15, 0xa085, 0x0001, 0x0078, 0x6d16, 0xa006, 0x0d7f, 0x007c,
+	0x2069, 0x7b8d, 0x6800, 0xa082, 0x0010, 0x00c8, 0x6d25, 0x6013,
+	0x0000, 0xa085, 0x0001, 0x0078, 0x6d26, 0xa006, 0x007c, 0x6013,
+	0x0000, 0x2069, 0x7b8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800,
+	0x007c, 0x6004, 0xa0b2, 0x0030, 0x10c8, 0x12cd, 0xa1b6, 0x0013,
+	0x00c0, 0x6d3d, 0x2008, 0x0079, 0x6d50, 0xa1b6, 0x0027, 0x0040,
+	0x6d45, 0xa1b6, 0x0014, 0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078,
+	0x37d7, 0x1078, 0x4b79, 0x1078, 0x6a96, 0x1078, 0x4c72, 0x007c,
+	0x6d80, 0x6d82, 0x6d80, 0x6d80, 0x6d80, 0x6d82, 0x6d8a, 0x6ded,
+	0x6db0, 0x6ded, 0x6dc4, 0x6ded, 0x6d8a, 0x6ded, 0x6de5, 0x6ded,
+	0x6de5, 0x6ded, 0x6ded, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80,
+	0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80, 0x6d80,
+	0x6ded, 0x6d80, 0x6d80, 0x6ded, 0x6d80, 0x6ded, 0x6ded, 0x6d80,
+	0x6d80, 0x6d80, 0x6d80, 0x6ded, 0x6ded, 0x6d80, 0x6ded, 0x6ded,
+	0x1078, 0x12cd, 0x1078, 0x4b79, 0x6003, 0x0002, 0x1078, 0x4c72,
+	0x0078, 0x6df3, 0x0f7e, 0x2079, 0x7651, 0x7804, 0x0f7f, 0xd0ac,
+	0x00c0, 0x6ded, 0x2001, 0x0000, 0x1078, 0x37b5, 0x2001, 0x0002,
+	0x1078, 0x37c9, 0x1078, 0x4b79, 0x601f, 0x0001, 0x6003, 0x0001,
+	0x6007, 0x0002, 0x1078, 0x486a, 0x1078, 0x4c72, 0x0c7e, 0x6118,
+	0x2160, 0x2009, 0x0001, 0x1078, 0x4573, 0x0c7f, 0x0078, 0x6df3,
+	0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00, 0x8637,
+	0xa686, 0x0006, 0x0040, 0x6ded, 0xa686, 0x0004, 0x0040, 0x6ded,
+	0x2001, 0x0004, 0x0078, 0x6deb, 0x2001, 0x7600, 0x2004, 0xa086,
+	0x0003, 0x00c0, 0x6dcd, 0x1078, 0x2db9, 0x2001, 0x0006, 0x1078,
+	0x6df4, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00,
+	0x8637, 0xa686, 0x0006, 0x0040, 0x6ded, 0x2001, 0x0006, 0x0078,
+	0x6deb, 0x2001, 0x0004, 0x0078, 0x6deb, 0x2001, 0x0006, 0x1078,
+	0x6df4, 0x0078, 0x6ded, 0x1078, 0x37d7, 0x1078, 0x4b79, 0x1078,
+	0x5bfa, 0x1078, 0x4c72, 0x007c, 0x017e, 0x0d7e, 0x6118, 0x2168,
+	0x6900, 0xd184, 0x0040, 0x6e0f, 0x6104, 0xa18e, 0x000a, 0x00c0,
+	0x6e07, 0x699c, 0xd1a4, 0x00c0, 0x6e07, 0x2001, 0x0007, 0x1078,
+	0x37c9, 0x2001, 0x0000, 0x1078, 0x37b5, 0x1078, 0x22d7, 0x0d7f,
+	0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00,
+	0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x12cd, 0xa1b6, 0x0015,
+	0x00c0, 0x6e26, 0x1079, 0x6e2d, 0x0078, 0x6e2c, 0xa1b6, 0x0016,
+	0x10c0, 0x12cd, 0x1079, 0x6e65, 0x007c, 0x5ed7, 0x5ed7, 0x5ed7,
+	0x5ed7, 0x5ed7, 0x5ed7, 0x5ed7, 0x6e39, 0x5ed7, 0x5ed7, 0x5ed7,
+	0x5ed7, 0x0f7e, 0x2079, 0x7651, 0x7804, 0x0f7f, 0xd0ac, 0x00c0,
+	0x6e55, 0x2001, 0x0000, 0x1078, 0x37b5, 0x2001, 0x0002, 0x1078,
+	0x37c9, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
+	0x486a, 0x1078, 0x4c72, 0x0078, 0x6e64, 0x2011, 0x7b83, 0x220c,
+	0x017e, 0x0c7e, 0x1078, 0x381d, 0x00c0, 0x6e64, 0x1078, 0x3619,
+	0x0c7f, 0x017f, 0x1078, 0x5bfa, 0x007c, 0x5ed7, 0x5ed7, 0x5ed7,
+	0x5ed7, 0x5ed7, 0x5ed7, 0x5ed7, 0x6e71, 0x5ed7, 0x5ed7, 0x5ed7,
+	0x5ed7, 0x1078, 0x60c7, 0x00c0, 0x6e7d, 0x6003, 0x0001, 0x6007,
+	0x0001, 0x1078, 0x486a, 0x0078, 0x6e7f, 0x1078, 0x5bfa, 0x007c,
+	0x6004, 0xa08a, 0x0030, 0x10c8, 0x12cd, 0x1078, 0x4b79, 0x1078,
+	0x6a96, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0040, 0x0079, 0x6e90,
+	0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea2, 0x6ea0, 0x6ea0, 0x6ea0,
+	0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0, 0x6ea0,
+	0x1078, 0x12cd, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e, 0x027e,
+	0x6106, 0x2071, 0x7b80, 0x7444, 0xa4a4, 0xe600, 0x0040, 0x6f13,
+	0xa486, 0x2000, 0x0040, 0x6ed2, 0xa486, 0x0400, 0x0040, 0x6ed2,
+	0x7130, 0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, 0x6fa5, 0x0c7e,
+	0x1078, 0x4604, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001, 0x0040,
+	0x6f86, 0x1078, 0x46c2, 0x0040, 0x6fb1, 0xa295, 0x0200, 0x6a02,
+	0x0078, 0x6ed8, 0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x46ac,
+	0x1078, 0x1327, 0x1040, 0x12cd, 0x6003, 0x0007, 0x2d00, 0x6837,
+	0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e,
+	0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0xa18c, 0x00ff, 0xa10d,
+	0x6946, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x3a72, 0xa486,
+	0x2000, 0x00c0, 0x6f01, 0x2019, 0x0017, 0x1078, 0x74ce, 0x0078,
+	0x6f73, 0xa486, 0x0400, 0x00c0, 0x6f0b, 0x2019, 0x0002, 0x1078,
+	0x74ce, 0x0078, 0x6f73, 0xa486, 0x0200, 0x00c0, 0x6f11, 0x1078,
+	0x74bf, 0x0078, 0x6f73, 0x7130, 0xa184, 0xff00, 0x00c0, 0x6fc5,
+	0xa18c, 0x00ff, 0xa182, 0x0010, 0x00c8, 0x6fc5, 0x0c7e, 0x1078,
+	0x4604, 0x2c68, 0x0c7f, 0x6a00, 0xa284, 0x0001, 0x0040, 0x6fc9,
+	0xa284, 0x0300, 0x00c0, 0x6fc1, 0x6804, 0xa005, 0x0040, 0x6fb1,
+	0x8001, 0x6806, 0x6003, 0x0007, 0x1078, 0x130c, 0x0040, 0x6f7a,
+	0x6013, 0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000,
+	0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0xa10d, 0x6946,
+	0x6853, 0x003d, 0x7044, 0xa084, 0x0003, 0xa086, 0x0002, 0x00c0,
+	0x6f55, 0x684f, 0x0040, 0x0078, 0x6f5f, 0xa086, 0x0001, 0x00c0,
+	0x6f5d, 0x684f, 0x0080, 0x0078, 0x6f5f, 0x684f, 0x0000, 0x20a9,
+	0x000a, 0x2001, 0x7b90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112,
+	0x8000, 0x8210, 0x00f0, 0x6f65, 0x200c, 0x6982, 0x8000, 0x200c,
+	0x697e, 0x1078, 0x3a72, 0x027f, 0x047f, 0x157f, 0x0f7f, 0x0e7f,
+	0x0d7f, 0x007c, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041,
+	0x1078, 0x481d, 0x1078, 0x4c72, 0x0078, 0x6f73, 0x2069, 0x7b92,
+	0x2d04, 0xa084, 0xff00, 0xa086, 0x1200, 0x00c0, 0x6fa5, 0x2069,
+	0x7b80, 0x686c, 0xa084, 0x00ff, 0x017e, 0x6110, 0xa18c, 0x0700,
+	0xa10d, 0x6112, 0x017f, 0x6003, 0x0001, 0x6007, 0x0043, 0x1078,
+	0x481d, 0x1078, 0x4c72, 0x0078, 0x6f73, 0x6013, 0x0200, 0x6003,
+	0x0001, 0x6007, 0x0041, 0x1078, 0x481d, 0x1078, 0x4c72, 0x0078,
+	0x6f73, 0x6013, 0x0300, 0x0078, 0x6fb7, 0x6013, 0x0100, 0x6003,
+	0x0001, 0x6007, 0x0041, 0x1078, 0x481d, 0x1078, 0x4c72, 0x0078,
+	0x6f73, 0x6013, 0x0500, 0x0078, 0x6fb7, 0x6013, 0x0600, 0x0078,
+	0x6f86, 0x6013, 0x0200, 0x0078, 0x6f86, 0xa186, 0x0013, 0x00c0,
+	0x6fdf, 0x6004, 0xa08a, 0x0040, 0x1048, 0x12cd, 0xa08a, 0x0050,
+	0x10c8, 0x12cd, 0xa082, 0x0040, 0x2008, 0x0079, 0x7010, 0xa186,
+	0x0047, 0x00c0, 0x6fe5, 0x0078, 0x703f, 0xa186, 0x0027, 0x0040,
+	0x6fed, 0xa186, 0x0014, 0x10c0, 0x12cd, 0x6004, 0xa082, 0x0040,
+	0x2008, 0x0079, 0x6ff3, 0x7003, 0x7005, 0x7005, 0x7003, 0x7003,
+	0x7003, 0x7003, 0x7003, 0x7003, 0x7003, 0x7003, 0x7003, 0x7003,
+	0x7003, 0x7003, 0x7003, 0x1078, 0x12cd, 0x2001, 0x0007, 0x1078,
+	0x37d7, 0x1078, 0x4b79, 0x1078, 0x6a96, 0x1078, 0x4c72, 0x007c,
+	0x7020, 0x7030, 0x7029, 0x7039, 0x7020, 0x7020, 0x7020, 0x7020,
+	0x7020, 0x7020, 0x7020, 0x7020, 0x7020, 0x7020, 0x7020, 0x7020,
+	0x1078, 0x12cd, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400,
+	0x200a, 0x1078, 0x4b79, 0x6003, 0x0002, 0x1078, 0x4c72, 0x007c,
+	0x1078, 0x4b79, 0x1078, 0x4685, 0x1078, 0x5bfa, 0x1078, 0x4c72,
+	0x007c, 0x1078, 0x4b79, 0x2009, 0x0041, 0x0078, 0x7107, 0xa182,
+	0x0040, 0x0079, 0x7043, 0x7053, 0x7055, 0x7053, 0x7053, 0x7053,
+	0x7053, 0x7053, 0x7056, 0x7053, 0x7053, 0x7053, 0x7053, 0x7053,
+	0x7053, 0x7053, 0x7053, 0x1078, 0x12cd, 0x007c, 0x6003, 0x0004,
+	0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x156a,
+	0x007c, 0xa182, 0x0040, 0x0079, 0x7065, 0x7075, 0x7075, 0x7075,
+	0x7075, 0x7075, 0x7075, 0x7075, 0x7075, 0x7075, 0x7077, 0x709a,
+	0x7075, 0x7075, 0x7075, 0x7075, 0x709a, 0x1078, 0x12cd, 0x1078,
+	0x4c21, 0x1078, 0x4d32, 0x6010, 0x0d7e, 0x2068, 0x684c, 0xd0fc,
+	0x0040, 0x708d, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0040, 0x7093,
+	0x2009, 0x0041, 0x0d7f, 0x0078, 0x7107, 0x6003, 0x0007, 0x1078,
+	0x4685, 0x0d7f, 0x007c, 0x1078, 0x4685, 0x1078, 0x5bfa, 0x0d7f,
+	0x0078, 0x7092, 0x037e, 0x1078, 0x4c21, 0x1078, 0x4d32, 0x6010,
+	0x0d7e, 0x2068, 0x2019, 0x0004, 0x1078, 0x74f2, 0x1078, 0x6a96,
+	0x6017, 0x0028, 0x0d7f, 0x037f, 0x007c, 0xa186, 0x0013, 0x00c0,
+	0x70bb, 0x6004, 0xa086, 0x0042, 0x10c0, 0x12cd, 0x1078, 0x4b79,
+	0x1078, 0x4c72, 0x007c, 0xa186, 0x0027, 0x0040, 0x70c3, 0xa186,
+	0x0014, 0x00c0, 0x70d3, 0x6004, 0xa086, 0x0042, 0x10c0, 0x12cd,
+	0x2001, 0x0007, 0x1078, 0x37d7, 0x1078, 0x4b79, 0x1078, 0x6a96,
+	0x1078, 0x4c72, 0x007c, 0xa182, 0x0040, 0x0079, 0x70d7, 0x70e7,
+	0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e9, 0x70f5,
+	0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x70e7, 0x1078,
+	0x12cd, 0x037e, 0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10,
+	0x1078, 0x156a, 0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068,
+	0x684c, 0xd0fc, 0x0040, 0x7101, 0x2009, 0x0041, 0x0d7f, 0x0078,
+	0x7107, 0x6003, 0x0007, 0x1078, 0x4685, 0x0d7f, 0x007c, 0xa182,
+	0x0040, 0x0079, 0x710b, 0x711b, 0x711d, 0x7129, 0x7135, 0x711b,
+	0x711b, 0x711b, 0x711b, 0x711b, 0x711b, 0x711b, 0x711b, 0x711b,
+	0x711b, 0x711b, 0x711b, 0x1078, 0x12cd, 0x6003, 0x0001, 0x6106,
+	0x1078, 0x481d, 0x127e, 0x2091, 0x8000, 0x1078, 0x4c72, 0x127f,
+	0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x481d, 0x127e, 0x2091,
+	0x8000, 0x1078, 0x4c72, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106,
+	0x2c10, 0x1078, 0x19c7, 0x127e, 0x2091, 0x8000, 0x1078, 0x4889,
+	0x1078, 0x4d32, 0x127f, 0x007c, 0x1078, 0x4b79, 0x0078, 0x714a,
+	0x1078, 0x4c21, 0x6110, 0x81ff, 0x0040, 0x7157, 0x0d7e, 0x2168,
+	0x037e, 0x2019, 0x0029, 0x1078, 0x74f2, 0x037f, 0x0d7f, 0x1078,
+	0x6a96, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0085, 0x0079, 0x7160,
+	0x7167, 0x7167, 0x7167, 0x7169, 0x7167, 0x7167, 0x7167, 0x1078,
+	0x12cd, 0x027e, 0x0e7e, 0x2071, 0x7b80, 0x7220, 0x1078, 0x740c,
+	0x0040, 0x7176, 0x6007, 0x0086, 0x0078, 0x7178, 0x6007, 0x0087,
+	0x6003, 0x0001, 0x1078, 0x481d, 0x1078, 0x4c72, 0x0e7f, 0x027f,
+	0x007c, 0xa186, 0x0013, 0x00c0, 0x7192, 0x6004, 0xa08a, 0x0085,
+	0x1048, 0x12cd, 0xa08a, 0x008c, 0x10c8, 0x12cd, 0xa082, 0x0085,
+	0x0079, 0x71a5, 0xa186, 0x0027, 0x0040, 0x719a, 0xa186, 0x0014,
+	0x10c0, 0x12cd, 0x2001, 0x0007, 0x1078, 0x37d7, 0x1078, 0x4b79,
+	0x1078, 0x6a96, 0x1078, 0x4c72, 0x007c, 0x71ac, 0x71ae, 0x71ae,
+	0x71ac, 0x71ac, 0x71ac, 0x71ac, 0x1078, 0x12cd, 0x1078, 0x4b79,
+	0x1078, 0x5bfa, 0x1078, 0x4c72, 0x007c, 0xa182, 0x0085, 0x1048,
+	0x12cd, 0xa182, 0x008c, 0x10c8, 0x12cd, 0xa182, 0x0085, 0x0079,
+	0x71c1, 0x71c8, 0x71c8, 0x71c8, 0x71ca, 0x71c8, 0x71c8, 0x71c8,
+	0x1078, 0x12cd, 0x007c, 0x1078, 0x4b79, 0x1078, 0x6a96, 0x1078,
+	0x4c72, 0x007c, 0x037e, 0x2019, 0x000b, 0x1078, 0x71db, 0x601f,
+	0x0006, 0x037f, 0x007c, 0x127e, 0x037e, 0x087e, 0x2091, 0x8000,
+	0x2c40, 0x1078, 0x590d, 0x00c0, 0x7208, 0x1078, 0x59ae, 0x00c0,
+	0x7208, 0x6000, 0xa086, 0x0000, 0x0040, 0x7208, 0x601c, 0xa086,
+	0x0007, 0x0040, 0x7208, 0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0,
+	0x71fb, 0x1078, 0x166e, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040,
+	0x7203, 0x1078, 0x74f2, 0x0d7f, 0x6013, 0x0000, 0x601f, 0x0007,
+	0x087f, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e, 0x157e,
+	0x2079, 0x7b80, 0x7838, 0xa08c, 0x00ff, 0x783c, 0x1078, 0x207f,
+	0x00c0, 0x7243, 0x017e, 0x0c7e, 0x1078, 0x381d, 0x00c0, 0x7243,
+	0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6160,
+	0x00c0, 0x7243, 0x017f, 0x027f, 0x027e, 0x017e, 0x2019, 0x0029,
+	0x1078, 0x5a82, 0x1078, 0x495a, 0x1078, 0x489d, 0x017f, 0x1078,
+	0x7370, 0x1078, 0x399e, 0x017f, 0x1078, 0x3619, 0x6612, 0x6516,
+	0xa006, 0x0078, 0x7245, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f,
+	0x0f7f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x2009, 0x761e, 0x2104,
+	0xa086, 0x0074, 0x00c0, 0x72a1, 0x2069, 0x7b8e, 0x690c, 0xa182,
+	0x0100, 0x0048, 0x7291, 0x6908, 0xa184, 0x8000, 0x0040, 0x729d,
+	0xa184, 0x0800, 0x0040, 0x729d, 0x6910, 0xa18a, 0x0001, 0x0048,
+	0x7295, 0x6914, 0x2069, 0x7bae, 0x6904, 0x81ff, 0x00c0, 0x7289,
+	0x690c, 0xa182, 0x0100, 0x0048, 0x7291, 0x6908, 0x81ff, 0x00c0,
+	0x728d, 0x6910, 0xa18a, 0x0001, 0x0048, 0x7295, 0x6918, 0xa18a,
+	0x0001, 0x0048, 0x729d, 0x0078, 0x72a7, 0x6013, 0x0100, 0x0078,
+	0x72a3, 0x6013, 0x0300, 0x0078, 0x72a3, 0x6013, 0x0500, 0x0078,
+	0x72a3, 0x6013, 0x0700, 0x0078, 0x72a3, 0x6013, 0x0900, 0x0078,
+	0x72a3, 0x6013, 0x0b00, 0x0078, 0x72a3, 0x6013, 0x0f00, 0x0078,
+	0x72a3, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078, 0x72a8, 0xa006,
+	0x017f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x027e, 0x037e,
+	0x157e, 0x6218, 0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006,
+	0x0040, 0x72d0, 0xa286, 0x0004, 0x0040, 0x72d0, 0xa394, 0xff00,
+	0x8217, 0xa286, 0x0006, 0x0040, 0x72d0, 0xa286, 0x0004, 0x0040,
+	0x72d0, 0x0c7e, 0x2d60, 0x1078, 0x382f, 0x0c7f, 0x0078, 0x7303,
+	0x2011, 0x7b96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6160,
+	0x00c0, 0x7304, 0x2011, 0x7b9a, 0xad98, 0x0006, 0x20a9, 0x0004,
+	0x1078, 0x6160, 0x00c0, 0x7304, 0x047e, 0x017e, 0x6aa0, 0xa294,
+	0x00ff, 0x8227, 0xa006, 0x2009, 0x7652, 0x210c, 0xd1a4, 0x0040,
+	0x72f8, 0x2009, 0x0029, 0x1078, 0x7536, 0x6800, 0xc0e5, 0x6802,
+	0x2019, 0x0029, 0x1078, 0x495a, 0x1078, 0x489d, 0x2c08, 0x1078,
+	0x7370, 0x017f, 0x047f, 0xa006, 0x157f, 0x037f, 0x027f, 0x0d7f,
+	0x0c7f, 0x007c, 0x0d7e, 0x2069, 0x7b8e, 0x6800, 0xa086, 0x0800,
+	0x0040, 0x7316, 0x6013, 0x0000, 0x0078, 0x7317, 0xa006, 0x0d7f,
+	0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2079,
+	0x7b8c, 0x7930, 0x7834, 0x1078, 0x207f, 0x00c0, 0x733d, 0x1078,
+	0x381d, 0x00c0, 0x733d, 0x2011, 0x7b90, 0xac98, 0x000a, 0x20a9,
+	0x0004, 0x1078, 0x6160, 0x00c0, 0x733d, 0x2011, 0x7b94, 0xac98,
+	0x0006, 0x20a9, 0x0004, 0x1078, 0x6160, 0x157f, 0x037f, 0x027f,
+	0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e, 0x007e, 0x017e, 0x027e,
+	0x037e, 0x157e, 0x2011, 0x7b83, 0x2204, 0x8211, 0x220c, 0x1078,
+	0x207f, 0x00c0, 0x7369, 0x1078, 0x381d, 0x00c0, 0x7369, 0x2011,
+	0x7b96, 0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x6160, 0x00c0,
+	0x7369, 0x2011, 0x7b9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078,
+	0x6160, 0x157f, 0x037f, 0x027f, 0x017f, 0x007f, 0x0c7f, 0x007c,
+	0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e, 0x127e,
+	0x2091, 0x8000, 0x2029, 0x783f, 0x252c, 0x2021, 0x7845, 0x2424,
+	0x2061, 0x7d00, 0x2071, 0x7600, 0x7644, 0x7060, 0x8001, 0xa602,
+	0x00c8, 0x73d5, 0x2100, 0xac06, 0x0040, 0x73cb, 0x1078, 0x754e,
+	0x0040, 0x73cb, 0x671c, 0xa786, 0x0001, 0x0040, 0x73ea, 0xa786,
+	0x0007, 0x0040, 0x73cb, 0x2500, 0xac06, 0x0040, 0x73cb, 0x2400,
+	0xac06, 0x0040, 0x73cb, 0x1078, 0x7562, 0x00c0, 0x73cb, 0x0d7e,
+	0x6000, 0xa086, 0x0004, 0x00c0, 0x73b1, 0x017e, 0x1078, 0x166e,
+	0x017f, 0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x73c8, 0xa786,
+	0x0003, 0x00c0, 0x73de, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
+	0x017e, 0x1078, 0x6b34, 0x1078, 0x3a72, 0x017f, 0x1078, 0x6a89,
+	0x0d7f, 0x1078, 0x6a96, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004,
+	0xac02, 0x00c8, 0x73d5, 0x0078, 0x7382, 0x127f, 0x027f, 0x047f,
+	0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006,
+	0x00c0, 0x73bb, 0xa386, 0x0005, 0x0040, 0x73cb, 0x1078, 0x74f2,
+	0x0078, 0x73c8, 0x1078, 0x7562, 0x00c0, 0x73cb, 0xa180, 0x0001,
+	0x2004, 0xa086, 0x0018, 0x00c0, 0x73cb, 0x6000, 0xa086, 0x0002,
+	0x00c0, 0x73cb, 0x1078, 0x6aaf, 0x0040, 0x7406, 0x1078, 0x6ac3,
+	0x00c0, 0x73cb, 0x1078, 0x5e4d, 0x0078, 0x7408, 0x1078, 0x22d7,
+	0x1078, 0x6a96, 0x0078, 0x73cb, 0x0c7e, 0x0e7e, 0x017e, 0x2c08,
+	0x2170, 0x1078, 0x7509, 0x017f, 0x0040, 0x741b, 0x601c, 0xa084,
+	0x000f, 0x1079, 0x741e, 0x0e7f, 0x0c7f, 0x007c, 0x7426, 0x7426,
+	0x7426, 0x7426, 0x7426, 0x7426, 0x7428, 0x7426, 0xa006, 0x007c,
+	0x047e, 0x017e, 0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff,
+	0x8427, 0x2c00, 0x2009, 0x0020, 0x1078, 0x7536, 0x017f, 0x047f,
+	0x037e, 0x2019, 0x0002, 0x1078, 0x71db, 0x037f, 0xa085, 0x0001,
+	0x007c, 0x2001, 0x0001, 0x1078, 0x37b5, 0x157e, 0x017e, 0x027e,
+	0x037e, 0x20a9, 0x0004, 0x2019, 0x7605, 0x2011, 0x7b96, 0x1078,
+	0x6160, 0x037f, 0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e,
+	0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000,
+	0x2061, 0x7d00, 0x2079, 0x0001, 0x8fff, 0x0040, 0x74b2, 0x2071,
+	0x7600, 0x7644, 0x7060, 0x8001, 0xa602, 0x00c8, 0x74b2, 0x88ff,
+	0x0040, 0x7478, 0x2800, 0xac06, 0x00c0, 0x74a8, 0x2079, 0x0000,
+	0x1078, 0x754e, 0x0040, 0x74a8, 0x2400, 0xac06, 0x0040, 0x74a8,
+	0x671c, 0xa786, 0x0006, 0x00c0, 0x74a8, 0xa786, 0x0007, 0x0040,
+	0x74a8, 0x88ff, 0x00c0, 0x7490, 0x6018, 0xa206, 0x00c0, 0x74a8,
+	0x0d7e, 0x6000, 0xa086, 0x0004, 0x00c0, 0x7498, 0x1078, 0x166e,
+	0x6010, 0x2068, 0x1078, 0x6938, 0x0040, 0x74a2, 0x047e, 0x1078,
+	0x74f2, 0x047f, 0x0d7f, 0x1078, 0x6a96, 0x88ff, 0x00c0, 0x74bb,
+	0xace0, 0x0008, 0x2001, 0x7615, 0x2004, 0xac02, 0x00c8, 0x74b2,
+	0x0078, 0x7464, 0xa006, 0x127f, 0x027f, 0x067f, 0x077f, 0x0c7f,
+	0x0e7f, 0x0f7f, 0x007c, 0xa8c5, 0x0001, 0x0078, 0x74b3, 0x087e,
+	0x2041, 0x0000, 0x2c20, 0x2019, 0x0002, 0x6218, 0x1078, 0x590d,
+	0x1078, 0x59ae, 0x1078, 0x7457, 0x087f, 0x007c, 0x027e, 0x047e,
+	0x087e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000,
+	0x017e, 0x037e, 0x1078, 0x381d, 0x00c0, 0x74e7, 0x2c10, 0x2041,
+	0x0000, 0x1078, 0x590d, 0x1078, 0x59ae, 0x1078, 0x7457, 0x037f,
+	0x017f, 0x8108, 0x00f0, 0x74d8, 0x157f, 0x0c7f, 0x087f, 0x047f,
+	0x027f, 0x007c, 0x017e, 0x0f7e, 0x8dff, 0x0040, 0x7506, 0x6800,
+	0xa07d, 0x0040, 0x7503, 0x6803, 0x0000, 0x6b52, 0x1078, 0x3a72,
+	0x2f68, 0x0078, 0x74f7, 0x6b52, 0x1078, 0x3a72, 0x0f7f, 0x017f,
+	0x007c, 0x0e7e, 0x047e, 0x037e, 0x2061, 0x7d00, 0x2071, 0x7600,
+	0x7444, 0x7060, 0x8001, 0xa402, 0x00c8, 0x7531, 0x2100, 0xac06,
+	0x0040, 0x7523, 0x6000, 0xa086, 0x0000, 0x0040, 0x7523, 0x6008,
+	0xa206, 0x0040, 0x752d, 0xace0, 0x0008, 0x2001, 0x7615, 0x2004,
+	0xac02, 0x00c8, 0x7531, 0x0078, 0x750e, 0xa085, 0x0001, 0x0078,
+	0x7532, 0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e,
+	0x1078, 0x1327, 0x007f, 0x1040, 0x12cd, 0x6837, 0x010d, 0x6803,
+	0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x685e, 0x6956, 0x6c46,
+	0x684f, 0x0000, 0x1078, 0x3a72, 0x0d7f, 0x007c, 0x6700, 0xa786,
+	0x0000, 0x0040, 0x7561, 0xa786, 0x0001, 0x0040, 0x7561, 0xa786,
+	0x000a, 0x0040, 0x7561, 0xa786, 0x0009, 0x0040, 0x7561, 0xa085,
+	0x0001, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x70a0, 0xa206, 0x0e7f,
+	0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7640,
+	0xd5a4, 0x0040, 0x7576, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040,
+	0x757c, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0x7583, 0x2071,
+	0x764a, 0x1078, 0x75b2, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e,
+	0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x7640, 0xd5a4, 0x0040,
+	0x7594, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0x759a, 0x7030,
+	0x8000, 0x7032, 0xd5ac, 0x0040, 0x75a1, 0x2071, 0x764a, 0x1078,
+	0x75b2, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e,
+	0x2091, 0x8000, 0x2071, 0x7642, 0x1078, 0x75b2, 0x0e7f, 0x007f,
+	0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0x75bb, 0x8e70,
+	0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0x7640, 0x1078,
+	0x75b2, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0x7644, 0x1078, 0x75b2,
+	0x0e7f, 0x007c, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020,
+	0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000,
+	0x4000, 0x8000, 0x2212
+};
+
+/*
+ *	Firmware Version 2.00.16 (09:36 Jun 29, 1999)
+ */
+
+unsigned short risc_code2200[] = { 
+	0x0470, 0x0000, 0x0000, 0x81bd, 0x0000, 0x0002, 0x0000, 0x0010,
+	0x0027, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
+	0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
+	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972,
+	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
+	0x322e, 0x3030, 0x2e31, 0x3620, 0x2020, 0x2020, 0x2400, 0x20c1,
+	0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0x96ff, 0x2091,
+	0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x2490,
+	0x2051, 0x9200, 0x2a70, 0x2029, 0xb100, 0x2031, 0xffff, 0x2039,
+	0xb0f5, 0x2021, 0x0200, 0x0804, 0x136b, 0x20a1, 0x91bd, 0xa00e,
+	0x20a9, 0x0743, 0x41a4, 0x3400, 0x755e, 0x7662, 0x775a, 0x7466,
+	0x746a, 0x20a1, 0x9900, 0x7160, 0x810d, 0x810d, 0x810d, 0x810d,
+	0xa18c, 0x000f, 0x2001, 0x0009, 0xa112, 0xa00e, 0x21a8, 0x41a4,
+	0x3400, 0x8211, 0x1dd8, 0x7160, 0x3400, 0xa102, 0x0120, 0x0218,
+	0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0x9200,
+	0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001,
+	0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0,
+	0x2009, 0x9200, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
+	0x41a4, 0x080c, 0x1322, 0x080c, 0x14b6, 0x080c, 0x1649, 0x080c,
+	0x1c81, 0x080c, 0x41d4, 0x080c, 0x7494, 0x080c, 0x1439, 0x080c,
+	0x2819, 0x080c, 0x4e42, 0x080c, 0x4757, 0x080c, 0x5874, 0x080c,
+	0x56c0, 0x080c, 0x2138, 0x080c, 0x5ed0, 0x080c, 0x532f, 0x080c,
+	0x206a, 0x080c, 0x210e, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004,
+	0x10c7, 0x7820, 0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04,
+	0x10bf, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70,
+	0x7003, 0x0000, 0x2a70, 0x7000, 0xa08e, 0x0003, 0x1168, 0x080c,
+	0x36d4, 0x080c, 0x2840, 0x080c, 0x4e90, 0x080c, 0x493b, 0x080c,
+	0x58b1, 0x080c, 0x56d8, 0x0c70, 0x000b, 0x0c88, 0x10e8, 0x10e9,
+	0x11b8, 0x10e6, 0x123f, 0x131f, 0x1320, 0x1321, 0x080c, 0x13fe,
+	0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x080c, 0x4dc5, 0x0150,
+	0x080c, 0x4deb, 0x11f8, 0x2079, 0x0100, 0x7828, 0xa085, 0x1800,
+	0x782a, 0x00c0, 0x080c, 0x4d10, 0x7088, 0xa086, 0x0026, 0x1904,
+	0x119d, 0x2079, 0x0100, 0x7827, 0xffff, 0x782b, 0x1c2b, 0x2011,
+	0x4ce2, 0x080c, 0x5731, 0x2011, 0x8030, 0x2019, 0x0000, 0x7087,
+	0x0000, 0x00a8, 0x080c, 0x3a6a, 0x2079, 0x0100, 0x7844, 0xa005,
+	0x1904, 0x119d, 0x2011, 0x40af, 0x080c, 0x5731, 0x780f, 0x03ff,
+	0x7840, 0xa084, 0xfffb, 0x7842, 0x2011, 0x8010, 0x73c4, 0x080c,
+	0x3698, 0x080c, 0x706b, 0x2011, 0x0004, 0x080c, 0x82f3, 0x080c,
+	0x46a8, 0x080c, 0x4dc5, 0x0158, 0x080c, 0x41bd, 0x0140, 0x7087,
+	0x0001, 0x70bf, 0x0000, 0x080c, 0x3bfd, 0x0804, 0x119d, 0x70d3,
+	0x0000, 0x70cf, 0x0000, 0x706f, 0x0000, 0x7073, 0x0000, 0x080c,
+	0x11a0, 0x72c8, 0x080c, 0x4dc5, 0x1160, 0x2011, 0x0000, 0x2001,
+	0x0204, 0x2004, 0x2019, 0x94c8, 0x201a, 0x704f, 0xffff, 0x7053,
+	0x00ef, 0x2079, 0x9251, 0x7804, 0xd0ac, 0x0108, 0xc295, 0x72ca,
+	0x080c, 0x4dc5, 0x0118, 0xa296, 0x0004, 0x0500, 0x2011, 0x0001,
+	0x080c, 0x82f3, 0x080c, 0x854a, 0x7097, 0x0000, 0x709b, 0xffff,
+	0x7003, 0x0002, 0x00fe, 0x080c, 0x251c, 0x2011, 0x0005, 0x080c,
+	0x718f, 0x080c, 0x6462, 0x080c, 0x4dc5, 0x0130, 0x00c6, 0x2061,
+	0x0100, 0x60e3, 0x0008, 0x00ce, 0x012e, 0x00c8, 0x080c, 0x854a,
+	0x7097, 0x0000, 0x709b, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005,
+	0x080c, 0x718f, 0x080c, 0x6462, 0x080c, 0x4dc5, 0x0130, 0x00c6,
+	0x2061, 0x0100, 0x60e3, 0x0008, 0x00ce, 0x00fe, 0x012e, 0x0005,
+	0x00c6, 0x080c, 0x4dc5, 0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9,
+	0x0082, 0x080c, 0x4dc5, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009,
+	0x007e, 0x080c, 0x441f, 0x8108, 0x1f04, 0x11b1, 0x00ce, 0x0005,
+	0x0126, 0x2091, 0x8000, 0x7098, 0xa086, 0xffff, 0x0130, 0x080c,
+	0x251c, 0x080c, 0x6462, 0x0804, 0x123d, 0x70c8, 0xd0ac, 0x1110,
+	0xd09c, 0x0558, 0xd084, 0x0548, 0x0006, 0x70c8, 0xa084, 0x0030,
+	0x000e, 0x1138, 0x00f6, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e,
+	0x00fe, 0xd08c, 0x01d0, 0x70cc, 0xa086, 0xffff, 0x0190, 0x080c,
+	0x25fd, 0x080c, 0x6462, 0x70c8, 0xd094, 0x1904, 0x123d, 0x2011,
+	0x0001, 0x2019, 0x0000, 0x080c, 0x2631, 0x080c, 0x6462, 0x0804,
+	0x123d, 0x70d0, 0xa005, 0x1904, 0x123d, 0x7094, 0xa005, 0x1904,
+	0x123d, 0x70c8, 0xd0a4, 0x0110, 0xd0b4, 0x05f8, 0x2001, 0x9252,
+	0x2004, 0xd0ac, 0x01c0, 0x0156, 0x00c6, 0x20a9, 0x007f, 0x2009,
+	0x0000, 0x0016, 0x080c, 0x4434, 0x1118, 0x6000, 0xd0ec, 0x1138,
+	0x001e, 0x8108, 0x1f04, 0x1209, 0x00ce, 0x015e, 0x0020, 0x001e,
+	0x00ce, 0x015e, 0x0410, 0x00f6, 0x2079, 0x0100, 0x780c, 0xc0b5,
+	0x780e, 0x00fe, 0x7003, 0x0003, 0x709b, 0xffff, 0xa006, 0x080c,
+	0x23ba, 0x080c, 0x370a, 0x2001, 0x94e6, 0x2004, 0xa086, 0x0005,
+	0x1120, 0x2011, 0x0000, 0x080c, 0x718f, 0x2011, 0x0000, 0x080c,
+	0x7199, 0x080c, 0x6462, 0x080c, 0x651c, 0x012e, 0x0005, 0x0016,
+	0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7,
+	0x080c, 0x4186, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4,
+	0x0110, 0x7827, 0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006,
+	0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904, 0x12a5, 0x080c, 0x4dd7,
+	0x0158, 0x080c, 0x4deb, 0x1128, 0x2001, 0x94d7, 0x2003, 0x0000,
+	0x0070, 0x080c, 0x4dcd, 0x0dc0, 0x2001, 0x94d7, 0x2003, 0xaaaa,
+	0x2001, 0x94d8, 0x2003, 0x0001, 0x080c, 0x4d10, 0x0058, 0x080c,
+	0x4dc5, 0x0140, 0x2009, 0x00f8, 0x080c, 0x4186, 0x7843, 0x0090,
+	0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c,
+	0x4dc5, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x130d, 0x1f04, 0x1284,
+	0x0070, 0x7824, 0x080c, 0x4de1, 0x0118, 0xd0ac, 0x1904, 0x130d,
+	0xa084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x130d, 0x2001,
+	0x0001, 0x080c, 0x23ba, 0x0804, 0x1318, 0x7850, 0xa084, 0x0180,
+	0x7852, 0x782f, 0x0020, 0x20a9, 0x0050, 0x1d04, 0x12ad, 0x2091,
+	0x6000, 0x1f04, 0x12ad, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400,
+	0x7852, 0x782f, 0x0000, 0x080c, 0x4dd7, 0x0158, 0x080c, 0x4deb,
+	0x1128, 0x2001, 0x94d7, 0x2003, 0x0000, 0x0070, 0x080c, 0x4dcd,
+	0x0dc0, 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003,
+	0x0001, 0x080c, 0x4d10, 0x0020, 0x2009, 0x00f8, 0x080c, 0x4186,
+	0x20a9, 0x000e, 0xe000, 0x1f04, 0x12da, 0x7850, 0xa084, 0x0180,
+	0xa085, 0x1400, 0x7852, 0x080c, 0x4dc5, 0x0120, 0x7843, 0x0090,
+	0x7843, 0x0010, 0x2019, 0x61a8, 0x7820, 0xd09c, 0x1130, 0x080c,
+	0x4dc5, 0x0130, 0x7824, 0xd0ac, 0x11c0, 0x8319, 0x1da8, 0x0080,
+	0x7827, 0x1800, 0xe000, 0xe000, 0x7824, 0x080c, 0x4de1, 0x0110,
+	0xd0ac, 0x1158, 0xa084, 0x1800, 0x0d80, 0x7003, 0x0001, 0x0028,
+	0x2001, 0x0001, 0x080c, 0x23ba, 0x0028, 0x7827, 0x0048, 0x7828,
+	0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400, 0x7852,
+	0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x001e, 0x0005, 0x0005,
+	0x0005, 0x0005, 0x2a70, 0x2001, 0x94d7, 0x2003, 0x0000, 0x7087,
+	0x0000, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0218, 0x704f,
+	0xffff, 0x0010, 0x704f, 0x0000, 0x7057, 0xffff, 0x706f, 0x0000,
+	0x7073, 0x0000, 0x080c, 0x854a, 0x2061, 0x94c7, 0x6003, 0x0909,
+	0x6007, 0x0000, 0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff,
+	0x6017, 0x0003, 0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0x94cf,
+	0x6003, 0x8800, 0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200,
+	0x6013, 0x00ff, 0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000,
+	0x2061, 0x94df, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943,
+	0x600f, 0x2020, 0x0005, 0x04a0, 0x2011, 0x0000, 0x81ff, 0x0570,
+	0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039, 0xa501, 0x2021,
+	0x0100, 0x2029, 0xa500, 0x00e8, 0xa186, 0x0002, 0x1118, 0x2011,
+	0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011, 0x0001, 0x0088,
+	0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058, 0xa186, 0x000a,
+	0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055, 0x1110, 0x2011,
+	0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0804, 0x104d,
+	0xa00e, 0x2011, 0x0003, 0x2019, 0x13a7, 0x0804, 0x13f8, 0x2019,
+	0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04,
+	0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011, 0x0000, 0x2019,
+	0x13ba, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362,
+	0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000, 0xe000, 0x2c04,
+	0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d, 0x0008, 0xc185,
+	0x2011, 0x0002, 0x2019, 0x13d5, 0x0418, 0x2061, 0xffff, 0x2019,
+	0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04, 0x2262, 0xa306,
+	0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff,
+	0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110, 0xc195, 0x0008,
+	0xc19d, 0x2011, 0x0001, 0x2019, 0x13f6, 0x0010, 0x0804, 0x136c,
+	0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837, 0x2091, 0x8000,
+	0x0e04, 0x1400, 0x0006, 0x0016, 0x2079, 0x0000, 0x7818, 0xd084,
+	0x1de8, 0x001e, 0x792e, 0x000e, 0x782a, 0x000e, 0x7826, 0x3900,
+	0x783a, 0x7823, 0x8002, 0x781b, 0x0001, 0x2091, 0x5000, 0x0156,
+	0x0146, 0x20a9, 0x0010, 0x20a1, 0x95e6, 0x2091, 0x2000, 0x40a1,
+	0x20a9, 0x0010, 0x2091, 0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091,
+	0x2400, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2600, 0x40a1, 0x014e,
+	0x015e, 0x2079, 0x9200, 0x7803, 0x0005, 0x2091, 0x4080, 0x0cf8,
+	0x0005, 0x2071, 0x9200, 0x715c, 0x712e, 0x2021, 0x0001, 0xa190,
+	0x0030, 0xa298, 0x0030, 0x0240, 0x7060, 0xa302, 0x1228, 0x220a,
+	0x2208, 0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7060,
+	0xa086, 0x9200, 0x0128, 0x7063, 0x9200, 0x2011, 0x1000, 0x0c48,
+	0x200b, 0x0000, 0x74aa, 0x74ae, 0x70df, 0x0010, 0x0005, 0x00e6,
+	0x0126, 0x2091, 0x8000, 0x2071, 0x9200, 0x70ac, 0x0016, 0x2008,
+	0x70dc, 0xa16a, 0x2100, 0x001e, 0x0268, 0x8001, 0x70ae, 0x702c,
+	0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e,
+	0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0x9200, 0x0126,
+	0x2091, 0x8000, 0x70ac, 0x8001, 0x0260, 0x70ae, 0x702c, 0x2068,
+	0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e, 0x00ee,
+	0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071,
+	0x9200, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000, 0x70ae,
+	0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807, 0x0000,
+	0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071, 0x9200,
+	0x70ac, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6, 0x2071,
+	0x9508, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x2071,
+	0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005, 0x00e6,
+	0x2270, 0x700b, 0x0000, 0x2071, 0x9508, 0x7018, 0xa088, 0x9511,
+	0x220a, 0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x1128,
+	0x00f6, 0x2079, 0x0010, 0x0081, 0x00fe, 0x00ee, 0x0005, 0x00e6,
+	0x2071, 0x9508, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010,
+	0x0019, 0x00fe, 0x00ee, 0x0005, 0x7000, 0x0002, 0x14f3, 0x1557,
+	0x1574, 0x1574, 0x1f79, 0x7018, 0x711c, 0xa106, 0x1118, 0x7007,
+	0x0000, 0x0005, 0x00d6, 0xa180, 0x9511, 0x2004, 0x700a, 0x2068,
+	0x8108, 0xa18c, 0x0007, 0x711e, 0x7803, 0x0026, 0x6824, 0x7832,
+	0x6828, 0x7836, 0x682c, 0x783a, 0x6830, 0x783e, 0x6810, 0x700e,
+	0x680c, 0x7016, 0x6804, 0x00de, 0xd084, 0x0120, 0x7007, 0x0001,
+	0x0029, 0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026,
+	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210, 0x2110, 0xa006,
+	0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803, 0x0041,
+	0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156,
+	0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c, 0x2011,
+	0x0040, 0xa182, 0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x22a8,
+	0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300, 0x7016, 0x7803,
+	0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005, 0x0136,
+	0x0146, 0x0156, 0x2099, 0x930e, 0x20a1, 0x0018, 0x20a9, 0x0008,
+	0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0041,
+	0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b, 0x9309, 0x012e,
+	0x015e, 0x014e, 0x013e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2001,
+	0x933d, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026, 0x2001, 0x933e,
+	0x20ac, 0x53a6, 0x2099, 0x933f, 0x20a1, 0x0018, 0x20a9, 0x0008,
+	0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000, 0x7803, 0x0001,
+	0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b, 0x933a, 0x012e,
+	0x015e, 0x014e, 0x013e, 0x0005, 0x0016, 0x00e6, 0x2071, 0x9508,
+	0x00f6, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002, 0xd1fc, 0x0120,
+	0xa18c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005,
+	0x14ec, 0x15b8, 0x15e2, 0x1608, 0x1638, 0x1f96, 0x15b7, 0x0cf8,
+	0xa18c, 0x0700, 0x1508, 0x0136, 0x0146, 0x0156, 0x7014, 0x20a0,
+	0x2099, 0x0014, 0x7803, 0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400,
+	0x7016, 0x015e, 0x014e, 0x013e, 0x700c, 0xa005, 0x0530, 0x080c,
+	0x151e, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007,
+	0x0000, 0x080c, 0x14ec, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003,
+	0x0200, 0x0ca8, 0xa18c, 0x0700, 0x1130, 0x700c, 0xa005, 0x0168,
+	0x080c, 0x1533, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200,
+	0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, 0x00d6, 0x7008, 0x2068,
+	0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c, 0x6832,
+	0x680b, 0x0100, 0x00de, 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005,
+	0xa18c, 0x0700, 0x1540, 0x0136, 0x0146, 0x0156, 0x2001, 0x930c,
+	0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040,
+	0x20a9, 0x0020, 0x53a5, 0x2001, 0x930e, 0x2004, 0xd0bc, 0x0148,
+	0x2001, 0x9317, 0x2004, 0xa080, 0x000d, 0x20a0, 0x20a9, 0x0020,
+	0x53a5, 0x015e, 0x014e, 0x013e, 0x7007, 0x0000, 0x080c, 0x4f27,
+	0x080c, 0x14ec, 0x0005, 0x2011, 0x8003, 0x080c, 0x3698, 0x0cf8,
+	0xa18c, 0x0700, 0x1148, 0x2001, 0x933c, 0x2003, 0x0100, 0x7007,
+	0x0000, 0x080c, 0x14ec, 0x0005, 0x2011, 0x8004, 0x080c, 0x3698,
+	0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079, 0x0030, 0x2071, 0x9519,
+	0x7003, 0x0000, 0x700f, 0x9520, 0x7013, 0x9520, 0x780f, 0x00f0,
+	0x012e, 0x0005, 0x6934, 0xa184, 0x0007, 0x0002, 0x1666, 0x16ab,
+	0x1666, 0x1666, 0x166a, 0x1693, 0x167a, 0x1671, 0xa085, 0x0001,
+	0x0804, 0x16c5, 0xa186, 0x0024, 0x05f0, 0xa186, 0x002c, 0x05d8,
+	0x0ca8, 0x684c, 0xd0bc, 0x0d90, 0x6860, 0x682e, 0x685c, 0x682a,
+	0x6858, 0x04c8, 0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d38, 0x684c,
+	0xd0bc, 0x0d20, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
+	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005,
+	0x6832, 0x6858, 0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x1970,
+	0x684c, 0xd0ac, 0x0958, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004,
+	0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, 0x6832, 0xa006, 0x682e,
+	0x682a, 0x6858, 0x0080, 0x684c, 0xd0ac, 0x0904, 0x1666, 0xa006,
+	0x682e, 0x682a, 0x6858, 0xa18c, 0x000f, 0xa188, 0x1f59, 0x210d,
+	0x6932, 0x2d08, 0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006,
+	0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x0005, 0x20e1, 0x0007,
+	0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x82ff, 0x0178, 0xa280,
+	0x0004, 0x00d6, 0x206c, 0x684c, 0xd0dc, 0x1120, 0x080c, 0x165a,
+	0x190c, 0x13fe, 0x6808, 0x8000, 0x680a, 0x00de, 0x0126, 0x0046,
+	0x0036, 0x0026, 0x2091, 0x2200, 0x002e, 0x003e, 0x004e, 0x7000,
+	0xa005, 0x0178, 0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a,
+	0x8108, 0xa182, 0x953b, 0x0210, 0x2009, 0x9520, 0x710e, 0x012e,
+	0x0005, 0x7206, 0x2001, 0x16f7, 0x0006, 0x2260, 0x0804, 0x17e8,
+	0x0126, 0x0026, 0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e,
+	0x004e, 0x003e, 0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168,
+	0x6a62, 0x6b5e, 0xa005, 0x05b8, 0x6808, 0xa005, 0x0904, 0x177c,
+	0x7000, 0xa005, 0x1108, 0x0430, 0x700c, 0x7110, 0xa106, 0x1904,
+	0x1784, 0x7004, 0xa406, 0x11f0, 0x2001, 0x0005, 0x2004, 0xd08c,
+	0x0130, 0x0046, 0x080c, 0x1942, 0x004e, 0x2460, 0x0c28, 0x2001,
+	0x0207, 0x2004, 0xd09c, 0x1d80, 0x7804, 0xa084, 0x6000, 0x0120,
+	0xa086, 0x6000, 0x0108, 0x0c40, 0x7803, 0x0004, 0x7003, 0x0000,
+	0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x15f0, 0x2009, 0x0048,
+	0x080c, 0x7518, 0x04c8, 0x6808, 0xa005, 0x0570, 0x7000, 0xa005,
+	0x0558, 0x700c, 0x7110, 0xa106, 0x1118, 0x7004, 0xa406, 0x1520,
+	0x2001, 0x0005, 0x2004, 0xd08c, 0x0130, 0x0046, 0x080c, 0x1942,
+	0x004e, 0x2460, 0x0c40, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1d80,
+	0x2001, 0x0005, 0x2004, 0xd08c, 0x1d80, 0x7804, 0xa084, 0x6000,
+	0x0118, 0xa086, 0x6000, 0x1d20, 0x7818, 0x6812, 0x781c, 0x6816,
+	0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x1120,
+	0x2009, 0x0048, 0x080c, 0x7518, 0x00ce, 0x00de, 0x012e, 0x0005,
+	0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, 0x080c, 0x1c26, 0x0026,
+	0x2071, 0x9519, 0x7000, 0xa086, 0x0000, 0x0580, 0x7004, 0xac06,
+	0x11f8, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x01c8, 0x7804,
+	0xd0fc, 0x1198, 0x2001, 0x0207, 0x2004, 0xd09c, 0x1dc0, 0x7803,
+	0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803, 0x0002, 0x7803, 0x0009,
+	0x7003, 0x0003, 0x7007, 0x0000, 0x0018, 0x080c, 0x1942, 0x08d0,
+	0x0156, 0x20a9, 0x0009, 0x2009, 0x9520, 0x2104, 0xac06, 0x1108,
+	0x200a, 0xa188, 0x0003, 0x1f04, 0x17bd, 0x015e, 0x002e, 0x2001,
+	0x015d, 0x201c, 0x831a, 0x2302, 0x2001, 0x0138, 0x2202, 0x004e,
+	0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c, 0x7110, 0xa106,
+	0x0904, 0x182c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108,
+	0x2124, 0x8108, 0xa182, 0x953b, 0x0210, 0x2009, 0x9520, 0x7112,
+	0x8cff, 0x05a0, 0x6010, 0x2068, 0x2d58, 0x6828, 0xa406, 0x1598,
+	0x682c, 0xa306, 0x1580, 0x684c, 0xd0f4, 0x1540, 0x6850, 0xd0f4,
+	0x1130, 0x7803, 0x0004, 0x6810, 0x781a, 0x6814, 0x781e, 0x6824,
+	0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc, 0x000f,
+	0x6834, 0xa08c, 0x00ff, 0xa186, 0x0024, 0x0118, 0xa186, 0x002c,
+	0x1120, 0x2009, 0x0011, 0x00d9, 0x0038, 0x2009, 0x0011, 0x00b9,
+	0x0118, 0x2009, 0x0001, 0x0099, 0x2d58, 0x0005, 0x7803, 0x0004,
+	0x080c, 0x1be2, 0x0cd0, 0x601c, 0xa086, 0x0008, 0x1108, 0x0858,
+	0x080c, 0x1fa7, 0x1d98, 0x0838, 0x7003, 0x0000, 0x0005, 0x8aff,
+	0x0904, 0x191c, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11b8, 0xd0f4,
+	0x1538, 0x00d6, 0x2805, 0xac68, 0x2900, 0x0002, 0x18b6, 0x1867,
+	0x1867, 0x18b6, 0x18b9, 0x18ae, 0x18b6, 0x1867, 0x18b6, 0x1878,
+	0x1878, 0x18b6, 0x18b9, 0x18b6, 0x18a6, 0x1878, 0x7803, 0x0004,
+	0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x00d6, 0xd99c,
+	0x0904, 0x1909, 0x2805, 0xac68, 0x6f08, 0x6e0c, 0x0804, 0x1909,
+	0xc0f4, 0x6852, 0x6b6c, 0x6a70, 0x00d6, 0x0804, 0x1910, 0x2d10,
+	0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096, 0x0024,
+	0x0904, 0x18e9, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0804, 0x1909,
+	0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff, 0xa096,
+	0x002c, 0x0904, 0x18c6, 0x7b0c, 0xd3bc, 0x01c0, 0x7004, 0x00e6,
+	0x2070, 0x701c, 0x00ee, 0xa086, 0x0008, 0x1180, 0x7b08, 0xa39c,
+	0x0fff, 0x2d20, 0x7a1c, 0x82ff, 0x1120, 0x7818, 0xa302, 0x0208,
+	0x7b18, 0xa016, 0x7a1e, 0x7b1a, 0x2468, 0x0010, 0x6b10, 0x6a14,
+	0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0804, 0x1909, 0x00de, 0x00d6,
+	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1140, 0x00de, 0x080c,
+	0x1f1b, 0x1904, 0x182f, 0xa00e, 0x0804, 0x191c, 0x00de, 0x080c,
+	0x13fe, 0x2d10, 0x00de, 0x00d6, 0x6834, 0x2268, 0xa084, 0x00ff,
+	0xa096, 0x0024, 0x0530, 0xa096, 0x002c, 0x1d80, 0x6b10, 0xa3a6,
+	0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6, 0x080c, 0x59f4, 0x2268,
+	0x2d10, 0x00de, 0x00d6, 0x7314, 0x685c, 0xa086, 0x0001, 0x1120,
+	0x6868, 0xa005, 0x0108, 0x2018, 0x2268, 0x2011, 0x0000, 0x6d00,
+	0x6c04, 0x6f08, 0x6e0c, 0x780f, 0x00f0, 0xe000, 0xe000, 0xe000,
+	0x0400, 0x6b08, 0xa3a6, 0xffff, 0x1130, 0x2d10, 0x00de, 0x00d6,
+	0x080c, 0x59f4, 0x2268, 0x2d10, 0x00de, 0x00d6, 0x7314, 0x685c,
+	0xa086, 0x0001, 0x1120, 0x6868, 0xa005, 0x0108, 0x2018, 0x2268,
+	0x2011, 0x0000, 0x6d00, 0x6c04, 0x780f, 0x00f0, 0xe000, 0xe000,
+	0xe000, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902,
+	0x7000, 0x8000, 0x7002, 0x00de, 0x6828, 0xa300, 0x682a, 0x682c,
+	0xa201, 0x682e, 0x080c, 0x1f1b, 0x0005, 0x080c, 0x13fe, 0x7803,
+	0x0004, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, 0x0000,
+	0x080c, 0x1c02, 0x080c, 0x82ee, 0x0170, 0x6808, 0x8001, 0x680a,
+	0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff,
+	0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x80f6, 0x0804, 0x1b4b,
+	0x080c, 0x13fe, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, 0x2b68,
+	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1978,
+	0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, 0x195f,
+	0x1961, 0x1aa6, 0x1b20, 0x1b3a, 0x195f, 0x195f, 0x195f, 0x080c,
+	0x13fe, 0x8001, 0x7002, 0xa184, 0x0880, 0x1904, 0x19a8, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x0024, 0x0130, 0x6834, 0xa084, 0x00ff,
+	0xa086, 0x002c, 0x1518, 0x6864, 0x8000, 0x6866, 0xd19c, 0x0140,
+	0x7004, 0x2060, 0x2009, 0x0102, 0x080c, 0x7518, 0x0804, 0x1a64,
+	0x8aff, 0x0130, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b,
+	0x7004, 0x2060, 0x2009, 0x0106, 0x080c, 0x7518, 0x7007, 0x0000,
+	0x7803, 0x0009, 0x7003, 0x0003, 0x0804, 0x1b4b, 0xd19c, 0x1904,
+	0x1a49, 0x8aff, 0x0904, 0x1a49, 0x2009, 0x0001, 0x080c, 0x182f,
+	0x0904, 0x1b4b, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b,
+	0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x1904, 0x1a18, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x0024, 0x0130, 0x6834, 0xa084, 0x00ff,
+	0xa086, 0x002c, 0x1138, 0xd19c, 0x0128, 0x6864, 0x8000, 0x6866,
+	0x0804, 0x1978, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30, 0x7f34,
+	0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004, 0xa005,
+	0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003, 0x0004,
+	0x0070, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x0140, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x002c, 0x0110, 0x080c, 0x1b4f, 0x6b28,
+	0x6a2c, 0x2400, 0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a,
+	0x6a2e, 0x003e, 0x002e, 0x6e1e, 0x6f22, 0x080c, 0x1f31, 0x2a00,
+	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852,
+	0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4, 0x0130, 0x7004,
+	0x2060, 0x2009, 0x0048, 0x080c, 0x7518, 0x7000, 0xa086, 0x0004,
+	0x0904, 0x1b4b, 0x7003, 0x0000, 0x080c, 0x17d5, 0x0804, 0x1b4b,
+	0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0x9171, 0x005e, 0x080c,
+	0x1c02, 0x7004, 0x7007, 0x0000, 0x2060, 0x601c, 0xa086, 0x0009,
+	0x1198, 0x790c, 0x0016, 0x2009, 0x0106, 0x080c, 0x7518, 0x001e,
+	0xd0ec, 0x1118, 0x2009, 0x0009, 0x0010, 0x2009, 0x0019, 0x7902,
+	0x7003, 0x0003, 0x0804, 0x1b4b, 0x682b, 0xffff, 0x682f, 0xffff,
+	0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0804,
+	0x1b4b, 0x7818, 0x6812, 0x7a1c, 0x6a16, 0xd19c, 0x0118, 0xa205,
+	0x1904, 0x19a8, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x1180,
+	0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060,
+	0x2009, 0x0048, 0x080c, 0x7518, 0x080c, 0x17d5, 0x0804, 0x1b4b,
+	0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff,
+	0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104, 0x8004,
+	0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x080c, 0x1c40, 0x7803,
+	0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8,
+	0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x00f0, 0x7004, 0x7007,
+	0x0000, 0x2060, 0x2009, 0x0048, 0x080c, 0x7518, 0x080c, 0x1c62,
+	0x0958, 0x7908, 0xd1ec, 0x1118, 0x2009, 0x0009, 0x0010, 0x2009,
+	0x0019, 0x7902, 0x7003, 0x0003, 0x0804, 0x1b4b, 0x8001, 0x7002,
+	0xd194, 0x0178, 0x7804, 0xd0fc, 0x1904, 0x194a, 0xd09c, 0x11a8,
+	0x8aff, 0x0904, 0x1b4b, 0x2009, 0x0001, 0x080c, 0x182f, 0x0804,
+	0x1b4b, 0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1b4b, 0x2009,
+	0x0001, 0x080c, 0x182f, 0x0804, 0x1b4b, 0x7803, 0x0004, 0x7003,
+	0x0000, 0xd1bc, 0x1904, 0x1b0d, 0x0026, 0x0036, 0x7c20, 0x7d24,
+	0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201,
+	0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009,
+	0x7003, 0x0004, 0x0020, 0x0016, 0x080c, 0x1b4f, 0x001e, 0x6b28,
+	0x6a2c, 0x080c, 0x1f31, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c,
+	0x1128, 0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a,
+	0x6814, 0xa213, 0x00de, 0xd194, 0x0904, 0x19e9, 0x2a00, 0x6826,
+	0x2c00, 0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a,
+	0x6a2e, 0x003e, 0x002e, 0x0804, 0x1a64, 0x0056, 0x7d0c, 0x080c,
+	0x9171, 0x005e, 0x080c, 0x1c02, 0x682b, 0xffff, 0x682f, 0xffff,
+	0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e, 0x0458,
+	0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d, 0x0180, 0x6808,
+	0x8001, 0x680a, 0x1160, 0x7004, 0x2060, 0x2009, 0x0048, 0x601c,
+	0xa086, 0x0009, 0x1110, 0x080c, 0x13fe, 0x080c, 0x7518, 0x080c,
+	0x17d5, 0x0088, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060,
+	0x6010, 0xa005, 0x0da0, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28,
+	0x6b2c, 0x080c, 0x17e8, 0x001e, 0x000e, 0x012e, 0x0005, 0x700c,
+	0x7110, 0xa106, 0x0904, 0x1bd6, 0x7004, 0x0016, 0x210c, 0xa106,
+	0x001e, 0x0904, 0x1bd6, 0x00d6, 0x00c6, 0x216c, 0x2d00, 0xa005,
+	0x0904, 0x1bd4, 0x6810, 0x2068, 0x6834, 0xa084, 0x00ff, 0xa086,
+	0x0024, 0x0904, 0x1bd4, 0x6834, 0xa084, 0x00ff, 0xa086, 0x002c,
+	0x0904, 0x1bd4, 0x6850, 0xd0fc, 0x0558, 0x8108, 0x2104, 0x6b2c,
+	0xa306, 0x1904, 0x1bd4, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904,
+	0x1bd4, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870,
+	0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034,
+	0xd09c, 0x0150, 0x6830, 0x2005, 0x00d6, 0xac68, 0x6808, 0x783a,
+	0x680c, 0x783e, 0x00de, 0x0490, 0xa006, 0x783a, 0x783e, 0x0470,
+	0x8108, 0x2104, 0xa005, 0x1580, 0x8108, 0x2104, 0xa005, 0x1560,
+	0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160, 0x6834,
+	0xd09c, 0x1170, 0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872,
+	0x6000, 0x7832, 0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0070,
+	0x6010, 0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832,
+	0x6004, 0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x6810, 0x781a,
+	0x6814, 0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011,
+	0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8,
+	0x0005, 0x0005, 0x0ca1, 0x01e0, 0x7908, 0xd1ec, 0x1160, 0x080c,
+	0x1c62, 0x0148, 0x7803, 0x0009, 0x7904, 0xd1fc, 0x0de8, 0x7803,
+	0x0006, 0x0c29, 0x0168, 0x780c, 0xd0a4, 0x1150, 0x7007, 0x0000,
+	0x080c, 0x1c62, 0x0130, 0x7803, 0x0019, 0x7003, 0x0003, 0x0008,
+	0x0009, 0x0005, 0x00c6, 0x0411, 0x20e1, 0x9028, 0x700c, 0x7110,
+	0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060, 0x6010, 0x2060,
+	0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182, 0x953b, 0x0210,
+	0x2009, 0x9520, 0x7112, 0x0c50, 0x2001, 0x015d, 0x200c, 0x810a,
+	0x2102, 0x2001, 0x0138, 0x2202, 0x00ce, 0x0005, 0x2001, 0x0138,
+	0x2014, 0x2003, 0x0000, 0x2021, 0xb015, 0x2001, 0x0141, 0x201c,
+	0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0xa39c, 0x0048, 0x1138,
+	0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005,
+	0x3c00, 0x0006, 0x00e6, 0x2071, 0x0200, 0x7808, 0xa084, 0xf000,
+	0xa10d, 0x08e1, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028,
+	0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037,
+	0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202, 0x00ee, 0x000e,
+	0x20e0, 0x0005, 0x3c00, 0x0006, 0x7908, 0xa18c, 0x0fff, 0xa182,
+	0x0009, 0x0218, 0xa085, 0x0001, 0x0088, 0x2001, 0x020a, 0x81ff,
+	0x0130, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c, 0x200c, 0x20e1,
+	0x7000, 0x200c, 0x200c, 0x7003, 0x0000, 0xa006, 0x000e, 0x20e0,
+	0x0005, 0x00e6, 0x2071, 0x953b, 0x7003, 0x0000, 0x00ee, 0x0005,
+	0x00d6, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x1904, 0x1d0d,
+	0x6934, 0xa184, 0x0007, 0x0002, 0x1c9c, 0x1cf8, 0x1c9c, 0x1c9e,
+	0x1c9c, 0x1cdf, 0x1cbe, 0x1cad, 0x080c, 0x13fe, 0x2100, 0xa084,
+	0x00ff, 0xa086, 0x0013, 0x0904, 0x1cf8, 0x2100, 0xa084, 0x00ff,
+	0xa086, 0x001b, 0x0904, 0x1cf8, 0x0c78, 0x684c, 0xd0b4, 0x0904,
+	0x1e15, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c,
+	0x680a, 0x6880, 0x680e, 0x6958, 0x0804, 0x1d00, 0x6834, 0xa084,
+	0x00ff, 0xa086, 0x001e, 0x19c0, 0x684c, 0xd0b4, 0x0904, 0x1e15,
+	0x6860, 0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a,
+	0x6880, 0x680e, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084,
+	0x000f, 0xa080, 0x1f59, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c,
+	0x00ff, 0xa186, 0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x1e15,
+	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
+	0x1f59, 0x2005, 0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088,
+	0x684c, 0xd0b4, 0x0904, 0x191d, 0x6958, 0xa006, 0x682e, 0x682a,
+	0x2d00, 0x681a, 0x6834, 0xa084, 0x000f, 0xa080, 0x1f59, 0x2005,
+	0x6832, 0x6926, 0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6,
+	0x2079, 0x0020, 0x7804, 0xd0fc, 0x190c, 0x1e3b, 0x00e6, 0x00d6,
+	0x2071, 0x953b, 0x7000, 0xa005, 0x1904, 0x1d81, 0x00c6, 0x7206,
+	0xa280, 0x0004, 0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818,
+	0x00d6, 0x2068, 0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040,
+	0x2079, 0x0200, 0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe,
+	0x00de, 0x2b68, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040,
+	0x6034, 0xa0cc, 0x000f, 0x6908, 0xa184, 0x0007, 0x0128, 0x0016,
+	0x2009, 0x0008, 0xa102, 0x001e, 0xa108, 0x791a, 0x7116, 0x701e,
+	0x680c, 0xa081, 0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012,
+	0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928, 0x6810, 0xa106,
+	0x0158, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x1fa7, 0x004e,
+	0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce, 0xa085,
+	0x0001, 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020, 0x2009,
+	0x0001, 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e, 0x00ce,
+	0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066, 0x0056,
+	0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1e0e, 0x700c, 0x7214,
+	0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x1e0d, 0xa705, 0x0904,
+	0x1e0d, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6, 0x2805,
+	0xac68, 0x2900, 0x0002, 0x1ddc, 0x1dc1, 0x1dc1, 0x1ddc, 0x1ddc,
+	0x1dd5, 0x1ddc, 0x1dc1, 0x1ddc, 0x1dc6, 0x1dc6, 0x1ddc, 0x1ddc,
+	0x1ddc, 0x1dcd, 0x1dc6, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c,
+	0x6c20, 0xd99c, 0x05c8, 0x00d6, 0x2805, 0xac68, 0x6f08, 0x6e0c,
+	0x0490, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x0468, 0x6b10, 0x6a14,
+	0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0430, 0x00de, 0x00d6, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c, 0x1f1b,
+	0x1904, 0x1d8b, 0xa00e, 0x0490, 0x2d10, 0x00de, 0x00d6, 0x6834,
+	0xa084, 0x00ff, 0xa086, 0x0013, 0x2268, 0x09d8, 0x2d10, 0x00de,
+	0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086, 0x001b, 0x2268, 0x09b0,
+	0x00de, 0x080c, 0x13fe, 0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36,
+	0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000, 0x7002, 0x6828, 0xa300,
+	0x682a, 0x682c, 0xa201, 0x682e, 0x700c, 0xa300, 0x700e, 0x7010,
+	0xa201, 0x7012, 0x080c, 0x1f1b, 0x0008, 0xa006, 0x002e, 0x003e,
+	0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x13fe, 0x2001,
+	0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003,
+	0x0000, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x82ee,
+	0x0118, 0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x80f6, 0x20e1,
+	0x9040, 0x080c, 0x7366, 0x2011, 0x0000, 0x080c, 0x7199, 0x080c,
+	0x651c, 0x0804, 0x1ef0, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016,
+	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020, 0x2071, 0x953b,
+	0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700,
+	0x1930, 0x7000, 0x0002, 0x1ef0, 0x1e57, 0x1ec3, 0x1eee, 0x8001,
+	0x7002, 0xd19c, 0x1170, 0x8aff, 0x0540, 0x2009, 0x0001, 0x080c,
+	0x1d85, 0x0904, 0x1ef0, 0x2009, 0x0001, 0x080c, 0x1d85, 0x0804,
+	0x1ef0, 0x7803, 0x0004, 0xd194, 0x0148, 0x6850, 0xc0fc, 0x6852,
+	0x8aff, 0x1148, 0x684c, 0xc0f5, 0x684e, 0x0028, 0x080c, 0x1f31,
+	0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800,
+	0x6832, 0x7003, 0x0000, 0x0804, 0x1ef0, 0x711c, 0x81ff, 0x0190,
+	0x7918, 0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000,
+	0x7002, 0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012,
+	0x0804, 0x1ef0, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006,
+	0x2079, 0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816,
+	0x7820, 0xd0bc, 0x1de8, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006,
+	0x0016, 0x79c4, 0x000e, 0xa102, 0x78c6, 0x000e, 0x78ca, 0xa284,
+	0x0004, 0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008,
+	0x7003, 0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804,
+	0xd0fc, 0x1904, 0x1e4b, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009,
+	0x0001, 0x080c, 0x1d85, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c,
+	0x080c, 0x1f31, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128,
+	0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814,
+	0xa213, 0x00de, 0x0804, 0x1e76, 0x0804, 0x1e76, 0x080c, 0x13fe,
+	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005,
+	0x00f6, 0x00e6, 0x2071, 0x953b, 0x7000, 0xa086, 0x0000, 0x01c0,
+	0x2079, 0x0020, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x0dd8, 0x080c,
+	0x1e3b, 0x7000, 0xa086, 0x0000, 0x1da8, 0x7803, 0x0004, 0x7804,
+	0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000,
+	0x00ee, 0x00fe, 0x0005, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004,
+	0xa005, 0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080,
+	0x1f59, 0x2045, 0x88ff, 0x090c, 0x13fe, 0x8a51, 0x0005, 0x2050,
+	0x0005, 0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06,
+	0x0120, 0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034,
+	0xa084, 0x000f, 0xa080, 0x1f69, 0x2045, 0x88ff, 0x090c, 0x13fe,
+	0x0005, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025,
+	0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000,
+	0x0000, 0x0000, 0x1f4e, 0x1f4a, 0x1f4e, 0x1f4e, 0x1f58, 0x0000,
+	0x1f4e, 0x0000, 0x1f55, 0x1f52, 0x1f55, 0x1f55, 0x0000, 0x1f58,
+	0x1f55, 0x0000, 0x1f50, 0x1f50, 0x0000, 0x1f50, 0x1f58, 0x0000,
+	0x1f50, 0x0000, 0x1f56, 0x1f56, 0x0000, 0x1f56, 0x0000, 0x1f58,
+	0x1f56, 0x0136, 0x0146, 0x0156, 0x2099, 0x9359, 0x20a1, 0x0018,
+	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126, 0x2091, 0x8000,
+	0x7803, 0x0041, 0x7007, 0x0005, 0x7000, 0xc094, 0x7002, 0x700b,
+	0x9354, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005, 0x2099, 0x0014,
+	0x7803, 0x0040, 0x2001, 0x9359, 0x2004, 0x2010, 0x080c, 0x59a7,
+	0x080c, 0x5949, 0x7007, 0x0000, 0x080c, 0x14ec, 0x0005, 0x00a6,
+	0x0096, 0x0086, 0x6858, 0xa055, 0x0904, 0x2036, 0x2d60, 0x6034,
+	0xa0cc, 0x000f, 0xa9c0, 0x1f59, 0xa986, 0x0007, 0x0130, 0xa986,
+	0x000e, 0x0118, 0xa986, 0x000f, 0x1120, 0x605c, 0xa422, 0x6060,
+	0xa31a, 0x2805, 0xa045, 0x1140, 0x0310, 0x0804, 0x2036, 0x6004,
+	0xa065, 0x0904, 0x2036, 0x0c18, 0x2805, 0xa005, 0x01a8, 0xac68,
+	0xd99c, 0x1128, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0020, 0x6810,
+	0xa422, 0x6814, 0xa31b, 0x0620, 0x2300, 0xa405, 0x0150, 0x8a51,
+	0x0904, 0x2036, 0x8840, 0x0c40, 0x6004, 0xa065, 0x0904, 0x2036,
+	0x0830, 0x8a51, 0x0904, 0x2036, 0x8840, 0x2805, 0xa005, 0x1158,
+	0x6004, 0xa065, 0x0904, 0x2036, 0x6034, 0xa0cc, 0x000f, 0xa9c0,
+	0x1f59, 0x2805, 0x2040, 0x2b68, 0x6850, 0xc0fc, 0x6852, 0x0458,
+	0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x00d6, 0x2b68, 0x6c6e,
+	0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908, 0x2400, 0xa122, 0x690c,
+	0x2300, 0xa11b, 0x0a0c, 0x13fe, 0x6800, 0xa420, 0x6804, 0xa319,
+	0x0060, 0x6910, 0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x0a0c,
+	0x13fe, 0x6800, 0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22,
+	0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00,
+	0x6826, 0x000e, 0x000e, 0x000e, 0xa006, 0x0028, 0x008e, 0x009e,
+	0x00ae, 0xa085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xa084,
+	0x0007, 0x0002, 0x204a, 0x204b, 0x204e, 0x2051, 0x2056, 0x2059,
+	0x205e, 0x2063, 0x0005, 0x080c, 0x1e3b, 0x0005, 0x080c, 0x1942,
+	0x0005, 0x080c, 0x1942, 0x080c, 0x1e3b, 0x0005, 0x080c, 0x159c,
+	0x0005, 0x080c, 0x1e3b, 0x080c, 0x159c, 0x0005, 0x080c, 0x1942,
+	0x080c, 0x159c, 0x0005, 0x080c, 0x1942, 0x080c, 0x1e3b, 0x080c,
+	0x159c, 0x0005, 0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071,
+	0x9780, 0x2069, 0x9200, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004,
+	0x080c, 0x23e6, 0x781b, 0x0002, 0x783b, 0x001f, 0x20e1, 0x8700,
+	0x012e, 0x0005, 0x0126, 0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c,
+	0x210b, 0xa084, 0x0007, 0x0002, 0x20a6, 0x2094, 0x2097, 0x209a,
+	0x209f, 0x20a1, 0x20a3, 0x20a5, 0x080c, 0x5338, 0x0078, 0x080c,
+	0x536c, 0x0060, 0x080c, 0x5338, 0x080c, 0x536c, 0x0038, 0x0041,
+	0x0028, 0x0031, 0x0018, 0x0021, 0x0008, 0x0011, 0x012e, 0x0005,
+	0x0006, 0x0016, 0x0026, 0x7930, 0xa184, 0x0003, 0x0118, 0x20e1,
+	0x9040, 0x00b8, 0xa184, 0x0030, 0x0150, 0x6a00, 0xa286, 0x0003,
+	0x1108, 0x0010, 0x080c, 0x4105, 0x20e1, 0x9010, 0x0050, 0xa184,
+	0x00c0, 0x0110, 0x080c, 0x13fe, 0xa184, 0x0300, 0x0110, 0x20e1,
+	0x9020, 0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6,
+	0x00f6, 0x2071, 0x9200, 0x7128, 0x2001, 0x94ca, 0x2102, 0x2001,
+	0x94d2, 0x2102, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400,
+	0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1,
+	0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009,
+	0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040,
+	0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002,
+	0x2079, 0x0200, 0x7912, 0x7817, 0x0004, 0x080c, 0x23e6, 0x00fe,
+	0x00ee, 0x001e, 0x0005, 0x7938, 0x080c, 0x13fe, 0x0126, 0x2091,
+	0x2400, 0x2061, 0x0100, 0x2071, 0x9200, 0x6024, 0x6026, 0x080c,
+	0x2425, 0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132,
+	0x6136, 0x080c, 0x2435, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008,
+	0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000,
+	0x6007, 0x0c9f, 0x600f, 0x03ff, 0x602b, 0x002f, 0x012e, 0x0005,
+	0x2001, 0x9230, 0x2003, 0x0000, 0x2001, 0x922f, 0x2003, 0x0001,
+	0x0005, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026, 0x6124,
+	0x0066, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x006e, 0x11c0,
+	0x6020, 0xd0bc, 0x01a8, 0xd1bc, 0x0198, 0x783c, 0xa005, 0x0180,
+	0x00e6, 0x0006, 0x2070, 0x701c, 0xa086, 0x0009, 0x000e, 0x00ee,
+	0x1138, 0x00e6, 0x783c, 0x2070, 0x7008, 0xd0fc, 0x00ee, 0x1130,
+	0xa184, 0x1c2c, 0x1118, 0xa184, 0x0007, 0x002a, 0xa195, 0x0004,
+	0xa284, 0x0007, 0x0002, 0x2195, 0x217b, 0x217e, 0x2181, 0x2186,
+	0x2188, 0x218c, 0x2190, 0x080c, 0x5ee3, 0x00b8, 0x080c, 0x5fbe,
+	0x00a0, 0x080c, 0x5fbe, 0x080c, 0x5ee3, 0x0078, 0x0099, 0x0068,
+	0x080c, 0x5ee3, 0x0079, 0x0048, 0x080c, 0x5fbe, 0x0059, 0x0028,
+	0x080c, 0x5fbe, 0x080c, 0x5ee3, 0x0029, 0x002e, 0x001e, 0x000e,
+	0x012e, 0x0005, 0xd19c, 0x1904, 0x238f, 0x080c, 0x4dc5, 0x01a0,
+	0x080c, 0x4deb, 0x15c0, 0x6024, 0xa084, 0x1800, 0x1108, 0x0498,
+	0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, 0x0001,
+	0x080c, 0x4d10, 0x0804, 0x238f, 0xd1ac, 0x1528, 0x6024, 0xd0dc,
+	0x1130, 0xd0e4, 0x1148, 0xd0d4, 0x1180, 0x0804, 0x238f, 0x2001,
+	0x94d8, 0x2003, 0x0000, 0x0068, 0xa085, 0x0001, 0x080c, 0x4e05,
+	0x2001, 0x94d8, 0x2003, 0x0002, 0x0020, 0x2001, 0x94d8, 0x2003,
+	0x0003, 0x0016, 0x2001, 0x9200, 0x2003, 0x0001, 0x080c, 0x4d10,
+	0x001e, 0x0804, 0x238f, 0x6220, 0xd1bc, 0x0568, 0xd2bc, 0x0558,
+	0x783c, 0xa005, 0x0540, 0x00e6, 0x2070, 0x7008, 0xd0fc, 0x00ee,
+	0x0510, 0x6028, 0xc0bc, 0x602a, 0x0026, 0x0036, 0x6288, 0x638c,
+	0x608b, 0xbc91, 0x608f, 0xffff, 0x6043, 0x0001, 0xe000, 0xe000,
+	0x6027, 0x0080, 0x6017, 0x0000, 0x6043, 0x0000, 0x628a, 0x638e,
+	0x003e, 0x002e, 0x0016, 0x2001, 0x9295, 0x200c, 0xc184, 0x2102,
+	0x001e, 0x0804, 0x23b6, 0xd1ac, 0x0904, 0x22d7, 0x080c, 0x4dc5,
+	0x1550, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036, 0x2001, 0x94d8,
+	0x080c, 0x4de1, 0x11d8, 0x2011, 0x9225, 0x2204, 0xa005, 0x1140,
+	0x8000, 0x2012, 0x2011, 0x8036, 0x2019, 0x0001, 0x080c, 0x3698,
+	0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, 0x2003, 0x0001,
+	0x080c, 0x4d10, 0x003e, 0x002e, 0x000e, 0x0005, 0x003e, 0x002e,
+	0x000e, 0x080c, 0x4ca5, 0x0016, 0x0046, 0x00c6, 0x644c, 0xa486,
+	0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043, 0x0090, 0x6043,
+	0x0010, 0x74c6, 0xa48c, 0xff00, 0xa196, 0xff00, 0x01e8, 0x7050,
+	0xa084, 0x00ff, 0x810f, 0xa116, 0x01b8, 0x7130, 0xd18c, 0x11a0,
+	0x2011, 0x9252, 0x2214, 0xd2ec, 0x0118, 0xc18d, 0x7132, 0x0060,
+	0x6240, 0xa294, 0x0010, 0x0904, 0x22ad, 0x6248, 0xa294, 0xff00,
+	0xa296, 0xff00, 0x1904, 0x22ad, 0x70bc, 0xa005, 0x1138, 0x0036,
+	0x73c4, 0x2011, 0x8013, 0x080c, 0x3698, 0x003e, 0x7130, 0xc185,
+	0x7132, 0x2011, 0x9252, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009,
+	0x0001, 0x2011, 0x0100, 0x080c, 0x585b, 0x2019, 0x000e, 0x080c,
+	0x9071, 0xa484, 0x00ff, 0xa080, 0x2719, 0x200d, 0xa18c, 0xff00,
+	0x810f, 0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0x90d7, 0x001e,
+	0xd1ac, 0x1128, 0x2019, 0x0004, 0x080c, 0x264b, 0x0070, 0x0156,
+	0x20a9, 0x007f, 0x2009, 0x0000, 0x080c, 0x4434, 0x1110, 0x080c,
+	0x41e0, 0x8108, 0x1f04, 0x22a4, 0x015e, 0x00ce, 0x004e, 0x2011,
+	0x0003, 0x080c, 0x718f, 0x2011, 0x0002, 0x080c, 0x7199, 0x080c,
+	0x708d, 0x080c, 0x57a1, 0x0036, 0x2019, 0x0000, 0x080c, 0x7110,
+	0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0x9200, 0x2014, 0xa296,
+	0x0004, 0x1128, 0xd19c, 0x1118, 0x6228, 0xc29d, 0x622a, 0x2003,
+	0x0001, 0x2001, 0x9222, 0x2003, 0x0000, 0x6027, 0x0020, 0xd194,
+	0x0904, 0x238f, 0x0016, 0x6220, 0xd2b4, 0x0904, 0x2340, 0x080c,
+	0x57a1, 0x080c, 0x6f1e, 0x6027, 0x0004, 0x00f6, 0x2019, 0x94ee,
+	0x2304, 0xa07d, 0x0570, 0x7804, 0xa086, 0x0032, 0x1550, 0x00d6,
+	0x00c6, 0x00e6, 0x2069, 0x0140, 0x618c, 0x6288, 0x7818, 0x608e,
+	0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003, 0x8001, 0x1df0,
+	0x6043, 0x0000, 0x6803, 0x1000, 0x6803, 0x0000, 0x618e, 0x628a,
+	0x080c, 0x6389, 0x080c, 0x6462, 0x7810, 0x2070, 0x7037, 0x0103,
+	0x2f60, 0x080c, 0x74f2, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e,
+	0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000,
+	0x0120, 0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061,
+	0x94e5, 0x6028, 0xa09a, 0x0002, 0x1238, 0x8000, 0x602a, 0x00ce,
+	0x080c, 0x6f11, 0x0804, 0x238e, 0x2019, 0x94ee, 0x2304, 0xa065,
+	0x0120, 0x2009, 0x0027, 0x080c, 0x7518, 0x00ce, 0x0804, 0x238e,
+	0xd2bc, 0x0904, 0x238e, 0x080c, 0x57ae, 0x6017, 0x0010, 0x6027,
+	0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120,
+	0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0x94e5,
+	0x6044, 0xa09a, 0x0002, 0x12e0, 0x8000, 0x6046, 0x603c, 0x00ce,
+	0xa005, 0x0560, 0x2009, 0x07d0, 0x080c, 0x57a6, 0xa080, 0x0007,
+	0x2004, 0xa086, 0x0006, 0x1118, 0x6017, 0x0012, 0x00f8, 0xa080,
+	0x0007, 0x2004, 0xa086, 0x0009, 0x0db8, 0x6017, 0x0016, 0x00b0,
+	0x0036, 0x2019, 0x0001, 0x080c, 0x7110, 0x003e, 0x2019, 0x94f4,
+	0x2304, 0xa065, 0x0150, 0x2009, 0x004f, 0x601c, 0xa086, 0x0009,
+	0x1110, 0x2009, 0x0105, 0x080c, 0x7518, 0x00ce, 0x001e, 0xd19c,
+	0x0528, 0x0016, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x080c,
+	0x718f, 0x2011, 0x0002, 0x080c, 0x7199, 0x080c, 0x708d, 0x080c,
+	0x57a1, 0x0036, 0x2019, 0x0000, 0x080c, 0x7110, 0x003e, 0x60e3,
+	0x0000, 0x080c, 0x918b, 0x080c, 0x91a6, 0x2001, 0x9200, 0x2003,
+	0x0004, 0x6027, 0x0008, 0x080c, 0x123f, 0x001e, 0xa18c, 0xffd0,
+	0x6126, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126,
+	0x2091, 0x8000, 0x2071, 0x9200, 0x71bc, 0x70be, 0xa116, 0x01b8,
+	0x81ff, 0x0128, 0x2011, 0x8011, 0x080c, 0x3698, 0x0080, 0x2011,
+	0x8012, 0x080c, 0x3698, 0x0036, 0x00c6, 0x080c, 0x2480, 0x2061,
+	0x0100, 0x2019, 0x0028, 0x080c, 0x264b, 0x00ce, 0x003e, 0x012e,
+	0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6,
+	0x0006, 0x0026, 0x2061, 0x0100, 0xa190, 0x23f9, 0x2205, 0x60f2,
+	0x2011, 0x2406, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce,
+	0x0005, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0,
+	0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8,
+	0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094,
+	0xff00, 0x1110, 0x81ff, 0x0118, 0x080c, 0x550c, 0x0038, 0xa080,
+	0x2719, 0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080,
+	0x2719, 0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140,
+	0x2001, 0x9214, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852,
+	0x6856, 0x1f04, 0x2430, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026,
+	0x2069, 0x0140, 0x2001, 0x9214, 0x2102, 0x8114, 0x8214, 0x8214,
+	0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128,
+	0xa184, 0x000f, 0xa080, 0x91ac, 0x2005, 0x6856, 0x8211, 0x1f04,
+	0x2445, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x9200,
+	0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005,
+	0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980,
+	0xa116, 0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001,
+	0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x2475,
+	0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005,
+	0x2001, 0x9252, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006,
+	0x0046, 0x2020, 0x2009, 0x002e, 0x080c, 0x90d7, 0x004e, 0x0005,
+	0x24b0, 0x24b4, 0x24b8, 0x24be, 0x24c4, 0x24ca, 0x24d0, 0x24d8,
+	0x24df, 0x24e4, 0x24e9, 0x24f0, 0x24f7, 0x24fe, 0x2505, 0x250e,
+	0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517,
+	0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517, 0x2517,
+	0x0106, 0x0006, 0x0804, 0x2519, 0x0106, 0x0006, 0x0804, 0x2519,
+	0x0106, 0x0006, 0x080c, 0x2141, 0x0804, 0x2519, 0x0106, 0x0006,
+	0x080c, 0x2141, 0x0804, 0x2519, 0x0106, 0x0006, 0x080c, 0x203c,
+	0x0804, 0x2519, 0x0106, 0x0006, 0x080c, 0x203c, 0x0804, 0x2519,
+	0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x203c, 0x0804, 0x2519,
+	0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x203c, 0x04d0, 0x0106,
+	0x0006, 0x080c, 0x2082, 0x04a8, 0x0106, 0x0006, 0x080c, 0x2082,
+	0x0480, 0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x2082, 0x0448,
+	0x0106, 0x0006, 0x080c, 0x2141, 0x080c, 0x2082, 0x0410, 0x0106,
+	0x0006, 0x080c, 0x203c, 0x080c, 0x2082, 0x00d8, 0x0106, 0x0006,
+	0x080c, 0x203c, 0x080c, 0x2082, 0x00a0, 0x0106, 0x0006, 0x080c,
+	0x2141, 0x080c, 0x203c, 0x080c, 0x2082, 0x0058, 0x0106, 0x0006,
+	0x080c, 0x2141, 0x080c, 0x203c, 0x080c, 0x2082, 0x0010, 0xe000,
+	0x0cf0, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x2041, 0x007e,
+	0x70c8, 0xd09c, 0x0110, 0x2041, 0x007f, 0xd094, 0x2001, 0x9214,
+	0x203c, 0x15d8, 0x7284, 0x82ff, 0x05c0, 0x0036, 0x7398, 0xa38e,
+	0xffff, 0x1110, 0x2019, 0x0001, 0x8314, 0xa2e0, 0x98c0, 0x2c04,
+	0xa38c, 0x0001, 0x0120, 0xa084, 0xff00, 0x8007, 0x0010, 0xa084,
+	0x00ff, 0xa70e, 0x01c8, 0xa08e, 0x00ff, 0x01d0, 0x2009, 0x0000,
+	0x080c, 0x240b, 0x080c, 0x4400, 0x1188, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x0006, 0x1120, 0x080c, 0x25b1, 0x0140, 0x0028, 0x080c,
+	0x26ad, 0x080c, 0x25d7, 0x0110, 0x8318, 0x08b0, 0x739a, 0x0010,
+	0x709b, 0xffff, 0x003e, 0x0804, 0x25ae, 0xa780, 0x2719, 0x203d,
+	0xa7bc, 0xff00, 0x873f, 0x7098, 0xa096, 0xffff, 0x0128, 0xa812,
+	0x12c8, 0x709b, 0xffff, 0x04b8, 0x2009, 0x0000, 0x70c8, 0xd09c,
+	0x0120, 0xd094, 0x0110, 0x2009, 0x007e, 0x2001, 0x94d7, 0x2004,
+	0xa005, 0x0120, 0x2009, 0x007e, 0x2041, 0x007f, 0x2100, 0xa802,
+	0x20a8, 0x0020, 0x2008, 0x2810, 0xa202, 0x20a8, 0x2700, 0x0156,
+	0x0016, 0xa106, 0x0180, 0x080c, 0x4400, 0x11a8, 0x6004, 0xa084,
+	0x00ff, 0xa086, 0x0006, 0x1118, 0x00a1, 0x0168, 0x0020, 0x080c,
+	0x26ad, 0x04a9, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x258e,
+	0x709b, 0xffff, 0x0018, 0x001e, 0x015e, 0x719a, 0x002e, 0x00ce,
+	0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x749c,
+	0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c,
+	0x43d1, 0x2001, 0x0000, 0x080c, 0x43e3, 0x0126, 0x2091, 0x8000,
+	0x7094, 0x8000, 0x7096, 0x012e, 0x2009, 0x0004, 0x080c, 0x7518,
+	0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016,
+	0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c, 0x749c, 0x01c8, 0x2d00,
+	0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001,
+	0x0002, 0x080c, 0x43e3, 0x0126, 0x2091, 0x8000, 0x7094, 0x8000,
+	0x7096, 0x012e, 0x2009, 0x0002, 0x080c, 0x7518, 0xa085, 0x0001,
+	0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009,
+	0x0080, 0x080c, 0x4400, 0x1120, 0x0031, 0x0110, 0x70cf, 0xffff,
+	0x002e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68,
+	0x080c, 0x749c, 0x01c8, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001,
+	0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, 0x080c, 0x43e3, 0x0126,
+	0x2091, 0x8000, 0x70d0, 0x8000, 0x70d2, 0x012e, 0x2009, 0x0002,
+	0x080c, 0x7518, 0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e,
+	0x0005, 0x00c6, 0x00d6, 0x2009, 0x007f, 0x080c, 0x4400, 0x1180,
+	0x2c68, 0x080c, 0x749c, 0x0160, 0x2d00, 0x601a, 0x6312, 0x601f,
+	0x0001, 0x620a, 0x2009, 0x0022, 0x080c, 0x7518, 0xa085, 0x0001,
+	0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026,
+	0x080c, 0x6133, 0x080c, 0x60dc, 0x080c, 0x7a8c, 0x20a9, 0x007f,
+	0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1120, 0x080c, 0x460d,
+	0x080c, 0x41e0, 0x001e, 0x8108, 0x1f04, 0x265a, 0x002e, 0x003e,
+	0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026,
+	0x0016, 0x6218, 0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c,
+	0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c,
+	0x8ee4, 0x008e, 0x001e, 0x2e60, 0x080c, 0x460d, 0x6210, 0x6314,
+	0x080c, 0x41e0, 0x6212, 0x6316, 0x001e, 0x002e, 0x003e, 0x00ce,
+	0x00ee, 0x0005, 0x00e6, 0x0006, 0x6018, 0xa080, 0x0028, 0x2004,
+	0xa086, 0x0080, 0x0150, 0x2071, 0x9200, 0x7094, 0xa005, 0x0110,
+	0x8001, 0x7096, 0x000e, 0x00ee, 0x0005, 0x2071, 0x9200, 0x70d0,
+	0xa005, 0x0dc0, 0x8001, 0x70d2, 0x0ca8, 0x6000, 0xc08c, 0x6002,
+	0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x0156,
+	0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0098, 0x2001, 0x9252,
+	0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020,
+	0x2009, 0x002d, 0x080c, 0x90d7, 0x004e, 0x20a9, 0x00ff, 0x2011,
+	0x0000, 0x0026, 0xa288, 0x936e, 0x210c, 0x81ff, 0x0508, 0x8fff,
+	0x0559, 0x2019, 0x0029, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000,
+	0x080c, 0x606d, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff,
+	0x2001, 0x0004, 0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016,
+	0x2c08, 0x080c, 0x8ee4, 0x001e, 0x008e, 0x2160, 0x080c, 0x460d,
+	0x002e, 0x8210, 0x1f04, 0x26d1, 0x015e, 0x001e, 0x002e, 0x003e,
+	0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001,
+	0x9252, 0x2004, 0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220,
+	0x8427, 0x2009, 0x0029, 0x080c, 0x90d7, 0x001e, 0x002e, 0x004e,
+	0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc,
+	0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1,
+	0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6,
+	0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4,
+	0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa,
+	0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d,
+	0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282,
+	0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074,
+	0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a,
+	0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559,
+	0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d,
+	0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043,
+	0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932,
+	0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227,
+	0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18,
+	0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000,
+	0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000,
+	0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00,
+	0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900,
+	0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200,
+	0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00,
+	0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600,
+	0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00,
+	0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900,
+	0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000,
+	0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000,
+	0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
+	0x8000, 0x2071, 0x9296, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016,
+	0x703a, 0x703e, 0x7033, 0x92a6, 0x7037, 0x92a6, 0x7007, 0x0001,
+	0x2061, 0x92e6, 0x6003, 0x0002, 0x0005, 0x1004, 0x283f, 0x0e04,
+	0x283f, 0x2071, 0x9296, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60,
+	0x7820, 0xa08e, 0x0069, 0x1904, 0x2924, 0x0804, 0x28bd, 0x0005,
+	0x2071, 0x9296, 0x7004, 0x0002, 0x2848, 0x2849, 0x2852, 0x2863,
+	0x0005, 0x1004, 0x2851, 0x0e04, 0x2851, 0x2b78, 0x7818, 0xd084,
+	0x01e8, 0x0005, 0x2b78, 0x2061, 0x92e6, 0x6008, 0xa08e, 0x0100,
+	0x0128, 0xa086, 0x0200, 0x0904, 0x291e, 0x0005, 0x7014, 0x2068,
+	0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103,
+	0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820,
+	0xa08a, 0x0040, 0x1210, 0x61bc, 0x0042, 0x2100, 0xa08a, 0x003f,
+	0x1a04, 0x291b, 0x61bc, 0x0804, 0x28bd, 0x28ff, 0x292a, 0x2932,
+	0x2936, 0x293e, 0x2944, 0x2948, 0x2951, 0x2954, 0x295e, 0x2961,
+	0x291b, 0x291b, 0x291b, 0x2964, 0x291b, 0x2973, 0x298a, 0x29a1,
+	0x2a18, 0x2a1d, 0x2a46, 0x2a97, 0x2aa8, 0x2ac6, 0x2af2, 0x2afc,
+	0x2b09, 0x2b1c, 0x2b3c, 0x2b45, 0x2b7b, 0x2b81, 0x291b, 0x2ba4,
+	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2ba8, 0x2bae, 0x291b,
+	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2bb6,
+	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x2bc3, 0x2bc9, 0x291b,
+	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x0002, 0x2bdb, 0x2c2e,
+	0x2c88, 0x2c98, 0x291b, 0x2cb2, 0x309c, 0x291b, 0x291b, 0x291b,
+	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x295e, 0x2961,
+	0x291b, 0x291b, 0x309e, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b,
+	0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x291b, 0x30a2, 0x31e7,
+	0x31fb, 0x3215, 0x3276, 0x32c7, 0x32d2, 0x3309, 0x3318, 0x3327,
+	0x3336, 0x335e, 0x33a8, 0x340a, 0x3417, 0x3501, 0x35f6, 0x361f,
+	0x3716, 0x3732, 0x373e, 0x3777, 0x381e, 0x3878, 0x38ff, 0x3908,
+	0x390b, 0x3920, 0x393b, 0x39ab, 0x3a5b, 0x713c, 0x0000, 0x2021,
+	0x4000, 0x080c, 0x3675, 0x0126, 0x2091, 0x8000, 0x0e04, 0x290b,
+	0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a,
+	0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091,
+	0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002,
+	0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021,
+	0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
+	0x0804, 0x3682, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520,
+	0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3685, 0x7924, 0x7828,
+	0x2114, 0x200a, 0x0804, 0x28ff, 0x7924, 0x2114, 0x0804, 0x28ff,
+	0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x0804,
+	0x28ff, 0x7824, 0x2060, 0x0090, 0x2009, 0x0002, 0x2011, 0x0000,
+	0x2019, 0x0010, 0x783b, 0x0027, 0x0804, 0x28ff, 0x7d38, 0x7c3c,
+	0x0858, 0x7d38, 0x7c3c, 0x08a0, 0x2061, 0x1000, 0xe10c, 0xa006,
+	0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8, 0x2010, 0xa005, 0x0904,
+	0x28ff, 0x0804, 0x2921, 0x2069, 0x9251, 0x7824, 0x7930, 0xa11a,
+	0x1a04, 0x2927, 0x8019, 0x0904, 0x2927, 0x684a, 0x6942, 0x782c,
+	0x6852, 0x7828, 0x6856, 0xa006, 0x685a, 0x685e, 0x080c, 0x4e5d,
+	0x0804, 0x28ff, 0x2069, 0x9251, 0x7824, 0x7934, 0xa11a, 0x1a04,
+	0x2927, 0x8019, 0x0904, 0x2927, 0x684e, 0x6946, 0x782c, 0x6862,
+	0x7828, 0x6866, 0xa006, 0x686a, 0x686e, 0x080c, 0x47d8, 0x0804,
+	0x28ff, 0xa02e, 0x2520, 0x81ff, 0x1904, 0x2924, 0x7924, 0x7b28,
+	0x7a2c, 0x20a9, 0x0005, 0x20a1, 0x929d, 0x41a1, 0x080c, 0x3641,
+	0x0904, 0x2924, 0x2009, 0x0023, 0x080c, 0x3682, 0x701b, 0x29b9,
+	0x0005, 0x6834, 0x2008, 0xa084, 0x00ff, 0xa096, 0x0011, 0x0120,
+	0xa096, 0x0019, 0x1904, 0x2924, 0x810f, 0xa18c, 0x00ff, 0x0904,
+	0x2924, 0x710e, 0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3641,
+	0x0904, 0x2924, 0x2009, 0x0023, 0x2061, 0x92e6, 0x6224, 0x6328,
+	0x642c, 0x6530, 0xa290, 0x0046, 0xa399, 0x0000, 0xa4a1, 0x0000,
+	0xa5a9, 0x0000, 0x080c, 0x3682, 0x701b, 0x29e7, 0x0005, 0x6834,
+	0xa084, 0x00ff, 0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904,
+	0x2924, 0x08c0, 0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c,
+	0x4337, 0x1128, 0x7007, 0x0003, 0x701b, 0x2a01, 0x0005, 0x080c,
+	0x492c, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0x929d,
+	0x530a, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+	0x0000, 0xad80, 0x000d, 0x2009, 0x0023, 0x012e, 0x0804, 0x3685,
+	0x61a4, 0x7824, 0x60a6, 0x0804, 0x28ff, 0x2091, 0x8000, 0x7823,
+	0x4000, 0x7827, 0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009,
+	0x017f, 0x2104, 0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200,
+	0x2061, 0x0200, 0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd,
+	0x2104, 0x783e, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080,
+	0x2071, 0x0010, 0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904,
+	0x2924, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x4434, 0x1904,
+	0x2927, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804,
+	0x2927, 0x7c28, 0x7d2c, 0x080c, 0x45d4, 0xd28c, 0x1118, 0x080c,
+	0x457f, 0x0010, 0x080c, 0x45ad, 0x1518, 0x2061, 0x9900, 0x0126,
+	0x2091, 0x8000, 0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d,
+	0x0130, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e,
+	0xace0, 0x000c, 0x2001, 0x9216, 0x2004, 0xac02, 0x1a04, 0x2924,
+	0x0c30, 0x080c, 0x80f6, 0x012e, 0x0904, 0x2924, 0x0804, 0x28ff,
+	0xa00e, 0x2001, 0x0005, 0x080c, 0x492c, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x852d, 0x080c, 0x4809, 0x012e, 0x0804, 0x28ff, 0x81ff,
+	0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x44d4,
+	0x0904, 0x2924, 0x080c, 0x45e0, 0x0904, 0x2924, 0x0804, 0x28ff,
+	0x81ff, 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, 0x080c,
+	0x4644, 0x0904, 0x2924, 0x2019, 0x0005, 0x080c, 0x45fb, 0x0904,
+	0x2924, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2927, 0x8003, 0x800b,
+	0x810b, 0xa108, 0x080c, 0x573d, 0x0804, 0x28ff, 0x0126, 0x2091,
+	0x8000, 0x81ff, 0x1508, 0x2029, 0x00ff, 0x644c, 0x2400, 0xa506,
+	0x01b0, 0x2508, 0x080c, 0x4434, 0x1190, 0x080c, 0x4644, 0x01a0,
+	0x2019, 0x0004, 0x080c, 0x45fb, 0x0178, 0x7824, 0xa08a, 0x1000,
+	0x1270, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x573d, 0x8529,
+	0x1e28, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, 0x2924, 0x012e,
+	0x0804, 0x2927, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x453a,
+	0x080c, 0x45d4, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x080c,
+	0x3656, 0x0904, 0x2927, 0x080c, 0x452b, 0x080c, 0x45d4, 0x0804,
+	0x28ff, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927,
+	0x080c, 0x45af, 0x0904, 0x2924, 0x080c, 0x4373, 0x080c, 0x4578,
+	0x080c, 0x45d4, 0x0804, 0x28ff, 0x080c, 0x3656, 0x0904, 0x2927,
+	0x080c, 0x44d4, 0x0904, 0x2924, 0x62a0, 0x2019, 0x0005, 0x00c6,
+	0x080c, 0x460d, 0x2061, 0x0000, 0x080c, 0x6127, 0x0086, 0x2041,
+	0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x00ce,
+	0x080c, 0x45d4, 0x0804, 0x28ff, 0x080c, 0x3656, 0x0904, 0x2927,
+	0x080c, 0x45d4, 0x2208, 0x0804, 0x28ff, 0x0156, 0x00d6, 0x00e6,
+	0x2069, 0x9328, 0x6810, 0x6914, 0xa10a, 0x1210, 0x2009, 0x0000,
+	0x6816, 0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x007e, 0x2069,
+	0x936e, 0x2d04, 0xa075, 0x0130, 0x704c, 0x0071, 0xa210, 0x7080,
+	0x0059, 0xa318, 0x8d68, 0x1f04, 0x2b59, 0x2300, 0xa218, 0x00ee,
+	0x00de, 0x015e, 0x0804, 0x28ff, 0x00f6, 0x0016, 0xa07d, 0x0140,
+	0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff, 0x0110, 0x2178, 0x0cd0,
+	0x001e, 0x00fe, 0x0005, 0x2069, 0x9328, 0x6910, 0x62a8, 0x0804,
+	0x28ff, 0x81ff, 0x1904, 0x2924, 0x614c, 0xa190, 0x2719, 0x2215,
+	0xa294, 0x00ff, 0x636c, 0x83ff, 0x0108, 0x6270, 0x67c8, 0xd79c,
+	0x0118, 0x2031, 0x0001, 0x0060, 0xd7ac, 0x0118, 0x2031, 0x0003,
+	0x0038, 0xd7a4, 0x0118, 0x2031, 0x0002, 0x0010, 0x2031, 0x0000,
+	0x7e3a, 0x7f3e, 0x0804, 0x28ff, 0x613c, 0x6240, 0x0804, 0x28ff,
+	0x080c, 0x3666, 0x0904, 0x2927, 0x0804, 0x28ff, 0x080c, 0x3666,
+	0x0904, 0x2927, 0x6244, 0x6338, 0x0804, 0x28ff, 0x613c, 0x6240,
+	0x7824, 0x603e, 0x7b28, 0x6342, 0x2069, 0x9251, 0x831f, 0xa305,
+	0x6816, 0x0804, 0x28ff, 0x080c, 0x3666, 0x0904, 0x2927, 0x0804,
+	0x28ff, 0x080c, 0x3666, 0x0904, 0x2927, 0x7828, 0xa00d, 0x0904,
+	0x2927, 0x782c, 0xa005, 0x0904, 0x2927, 0x6244, 0x6146, 0x6338,
+	0x603a, 0x0804, 0x28ff, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003,
+	0x1904, 0x2924, 0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c,
+	0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0x9214, 0x2004, 0xa085,
+	0xff00, 0x0078, 0xa182, 0x007f, 0x1698, 0xa188, 0x2719, 0x210d,
+	0xa18c, 0x00ff, 0x2001, 0x9214, 0x2004, 0xa116, 0x0548, 0x810f,
+	0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0x749c, 0x000e,
+	0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001, 0x080c, 0x3641,
+	0x01d0, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838,
+	0xc0fd, 0x683a, 0x701b, 0x2c81, 0x2d00, 0x6012, 0x2009, 0x0032,
+	0x080c, 0x7518, 0x012e, 0x00ce, 0x0005, 0x00ce, 0x0804, 0x2924,
+	0x00ce, 0x0804, 0x2927, 0x080c, 0x74f2, 0x0cb8, 0x2001, 0x9200,
+	0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x00c6, 0x2061, 0x0100,
+	0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001,
+	0x9214, 0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x1698,
+	0xa188, 0x2719, 0x210d, 0xa18c, 0x00ff, 0x2001, 0x9214, 0x2004,
+	0xa116, 0x0548, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006,
+	0x080c, 0x749c, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc05, 0x601f,
+	0x0001, 0x080c, 0x3641, 0x01d0, 0x6837, 0x0000, 0x7007, 0x0003,
+	0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x2c81, 0x2d00,
+	0x6012, 0x2009, 0x0032, 0x080c, 0x7518, 0x012e, 0x00ce, 0x0005,
+	0x00ce, 0x0804, 0x2924, 0x00ce, 0x0804, 0x2927, 0x080c, 0x74f2,
+	0x0cb8, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff,
+	0x2061, 0x9566, 0x0126, 0x2091, 0x8000, 0x6000, 0xd084, 0x0128,
+	0x6104, 0x6208, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804, 0x2927,
+	0x81ff, 0x1904, 0x2924, 0x080c, 0x4dc5, 0x0904, 0x2924, 0x0126,
+	0x2091, 0x8000, 0x6244, 0x6064, 0xa202, 0x0248, 0xa085, 0x0001,
+	0x080c, 0x2455, 0x080c, 0x3bfd, 0x012e, 0x0804, 0x28ff, 0x012e,
+	0x0804, 0x2927, 0x0126, 0x2091, 0x8000, 0x7824, 0xa084, 0x0007,
+	0x0002, 0x2cc4, 0x2ccd, 0x2cd4, 0x2cc1, 0x2cc1, 0x2cc1, 0x2cc1,
+	0x2cc1, 0x012e, 0x0804, 0x2927, 0x2009, 0x0114, 0x2104, 0xa085,
+	0x0800, 0x200a, 0x080c, 0x2e1e, 0x0070, 0x2009, 0x010b, 0x200b,
+	0x0010, 0x080c, 0x2e1e, 0x0038, 0x81ff, 0x0128, 0x012e, 0x2021,
+	0x400b, 0x0804, 0x2901, 0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6,
+	0x00d6, 0x00e6, 0x00f6, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001,
+	0x0138, 0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034,
+	0x2001, 0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c,
+	0x302f, 0x080c, 0x2f99, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6,
+	0x2d60, 0x2071, 0x953b, 0x2079, 0x0020, 0x2011, 0x0001, 0x080c,
+	0x2f45, 0x080c, 0x2f45, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x2ea6,
+	0x080c, 0x2f6d, 0x080c, 0x2eea, 0x080c, 0x2e65, 0x080c, 0x2e96,
+	0x00f6, 0x2079, 0x0100, 0x7824, 0xd094, 0x01d8, 0x7817, 0x0010,
+	0x2079, 0x0140, 0x2001, 0x0109, 0x2004, 0xd0ac, 0x11a8, 0x7804,
+	0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086, 0x7817, 0x0032,
+	0x7824, 0xd0ac, 0x1148, 0xd0bc, 0x0dd8, 0x7827, 0x0080, 0xa026,
+	0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x2e06, 0x00fe,
+	0x0804, 0x2dd0, 0x00fe, 0x1d04, 0x2d55, 0x2091, 0x6000, 0x8420,
+	0xa486, 0x0064, 0x1150, 0x8948, 0x2001, 0x007a, 0x2602, 0x2001,
+	0x007b, 0x2502, 0x080c, 0x2e06, 0x0088, 0x87ff, 0x0140, 0x2001,
+	0x0201, 0x2004, 0xa005, 0x1904, 0x2d10, 0x8739, 0x0038, 0x2001,
+	0x9519, 0x2004, 0xa086, 0x0000, 0x1904, 0x2d10, 0x2001, 0x0033,
+	0x2003, 0x00f0, 0x8631, 0x1208, 0x8529, 0x2500, 0xa605, 0x0904,
+	0x2dd0, 0x7824, 0xd0bc, 0x0128, 0x2900, 0xaa05, 0xab05, 0x1904,
+	0x2dd0, 0x6033, 0x000d, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824,
+	0xd0ac, 0x1148, 0x2001, 0x9519, 0x2003, 0x0003, 0x2001, 0x0030,
+	0x2003, 0x0009, 0x0040, 0x6027, 0x0001, 0x2001, 0x0075, 0x2004,
+	0xa005, 0x0108, 0x6026, 0x2c00, 0x601a, 0x20e1, 0x9040, 0x2d00,
+	0x681a, 0x6833, 0x000d, 0x7824, 0xd0a4, 0x1180, 0x6827, 0x0000,
+	0x00c6, 0x20a9, 0x0008, 0x2061, 0x0020, 0x6003, 0x0008, 0x2001,
+	0x0203, 0x2004, 0x1f04, 0x2da5, 0x00ce, 0x0040, 0x6827, 0x0001,
+	0x2001, 0x0074, 0x2004, 0xa005, 0x0108, 0x6826, 0x00f6, 0x00c6,
+	0x2079, 0x0100, 0x2061, 0x0020, 0x7827, 0x0002, 0x2001, 0x0072,
+	0x2004, 0xa084, 0xfff8, 0x601a, 0x0006, 0x2001, 0x0073, 0x2004,
+	0x601e, 0x78c6, 0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x2cfd,
+	0x2061, 0x0100, 0x6027, 0x0002, 0x20e1, 0x9028, 0x6050, 0xa084,
+	0xf7ef, 0x6052, 0x602f, 0x0000, 0x001e, 0x61e2, 0x001e, 0x6106,
+	0x7824, 0xa084, 0x0003, 0xa086, 0x0002, 0x0148, 0x602c, 0xc0ac,
+	0x602e, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x2908,
+	0x2a10, 0x2b18, 0x2b00, 0xaa05, 0xa905, 0x00fe, 0x00ee, 0x00de,
+	0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e, 0x0804,
+	0x28ff, 0x012e, 0x2021, 0x400c, 0x0804, 0x2901, 0x2001, 0x0105,
+	0x2003, 0x0010, 0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020,
+	0x2003, 0x0004, 0x2001, 0x9519, 0x2003, 0x0000, 0x2001, 0x953b,
+	0x2003, 0x0000, 0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079,
+	0x0100, 0x7850, 0xa084, 0x0990, 0x7852, 0x782c, 0xa085, 0x0020,
+	0x782e, 0x20a9, 0x0008, 0x1d04, 0x2e2b, 0x2091, 0x6000, 0x1f04,
+	0x2e2b, 0x7850, 0xa085, 0x0400, 0x7852, 0x784b, 0xf7f7, 0x7843,
+	0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x2e3d,
+	0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000,
+	0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850,
+	0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000,
+	0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7843,
+	0x0000, 0x2003, 0x0000, 0x00fe, 0x0005, 0x7824, 0xd0ac, 0x11c8,
+	0x00f6, 0x00e6, 0x2071, 0x9519, 0x2079, 0x0030, 0x2001, 0x0201,
+	0x2004, 0xa005, 0x0160, 0x7000, 0xa086, 0x0000, 0x1140, 0x0051,
+	0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x7803, 0x0019, 0x00ee,
+	0x00fe, 0x0005, 0x780c, 0xa08c, 0x0070, 0x0178, 0x2009, 0x007a,
+	0x260a, 0x2009, 0x007b, 0x250a, 0xd0b4, 0x0108, 0x8a50, 0xd0ac,
+	0x0108, 0x8948, 0xd0a4, 0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079,
+	0x0200, 0x781c, 0xd084, 0x0140, 0x20e1, 0x0007, 0x20e1, 0x2000,
+	0x2001, 0x020a, 0x2004, 0x0ca8, 0x00fe, 0x0005, 0x00e6, 0x2071,
+	0x0100, 0x2009, 0x9214, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166,
+	0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078,
+	0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa,
+	0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af,
+	0x95d5, 0x7027, 0x0080, 0x7017, 0x0032, 0x080c, 0x2f6d, 0x7024,
+	0xd0ac, 0x1120, 0xd0bc, 0x0dc8, 0x7027, 0x0080, 0x00f6, 0x00e6,
+	0x2071, 0x9519, 0x2079, 0x0030, 0x2011, 0x0011, 0x080c, 0x2f45,
+	0x2011, 0x0001, 0x080c, 0x2f45, 0x00ee, 0x00fe, 0x7017, 0x0000,
+	0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x9519, 0x2079, 0x0030,
+	0x7904, 0xd1fc, 0x0904, 0x2f42, 0x7803, 0x0002, 0xa026, 0xd19c,
+	0x1904, 0x2f3e, 0x7000, 0x0002, 0x2f42, 0x2f00, 0x2f24, 0x2f3e,
+	0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002, 0x2011, 0x0001,
+	0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000, 0x7820, 0x7924,
+	0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201, 0x200c, 0x81ff,
+	0x0de8, 0x080c, 0x2e82, 0x2009, 0x0001, 0x7808, 0xd0ec, 0x0110,
+	0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002, 0xa184, 0x0880,
+	0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001, 0x00b1, 0x0090,
+	0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120, 0x6000, 0x601a,
+	0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870, 0x7803, 0x0004,
+	0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024, 0xa005, 0x0520,
+	0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804, 0x7832, 0x8840,
+	0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840, 0x2804, 0x7826,
+	0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018, 0xa802, 0xa08a,
+	0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004, 0x601a, 0x2001,
+	0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6,
+	0x2071, 0x953b, 0x2079, 0x0020, 0x7904, 0xd1fc, 0x01f0, 0x7803,
+	0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x2f95, 0x2f80, 0x2f8c,
+	0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001, 0x080c, 0x2f45,
+	0x0160, 0x080c, 0x2f45, 0x0048, 0x8001, 0x7002, 0x7804, 0xd0fc,
+	0x1d30, 0x2011, 0x0001, 0x080c, 0x2f45, 0x00ce, 0x00ee, 0x00fe,
+	0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x601b, 0x0004,
+	0x2061, 0x0100, 0x60cf, 0x0400, 0x6004, 0xc0ac, 0xa085, 0x0200,
+	0x6006, 0x2001, 0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001,
+	0x0076, 0x2024, 0x2001, 0x0077, 0x201c, 0x080c, 0x3089, 0x6833,
+	0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138,
+	0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d,
+	0x04a1, 0x1d90, 0x2d00, 0x681a, 0x0088, 0x080c, 0x3089, 0x6833,
+	0x000d, 0x2070, 0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076,
+	0x2004, 0x2072, 0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020,
+	0x2079, 0x0100, 0x6013, 0x0400, 0x20e1, 0x9040, 0x2001, 0x0072,
+	0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073,
+	0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a,
+	0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010,
+	0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006,
+	0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003,
+	0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040,
+	0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60,
+	0x00c6, 0x080c, 0x3641, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006,
+	0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6,
+	0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078,
+	0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3089, 0x2d60, 0x6833,
+	0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138,
+	0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d,
+	0x080c, 0x2ffd, 0x1d88, 0x2d00, 0x681a, 0x00d8, 0x0491, 0x2d60,
+	0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a, 0x2001,
+	0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006, 0x2001,
+	0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073, 0x2004,
+	0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1178,
+	0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000, 0x2001,
+	0x9519, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x00ee,
+	0x0005, 0x080c, 0x147c, 0x0178, 0xa006, 0x6802, 0x7010, 0xa005,
+	0x1120, 0x2d00, 0x7012, 0x7016, 0x0020, 0x7014, 0x6802, 0x2d00,
+	0x7016, 0xad80, 0x000d, 0x0005, 0x0804, 0x28ff, 0x7d38, 0x7c3c,
+	0x0804, 0x29a3, 0x080c, 0x3641, 0x0904, 0x2924, 0x080c, 0x4dc5,
+	0x0110, 0x080c, 0x41c5, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c,
+	0x7d38, 0x080c, 0x3682, 0x701b, 0x30b6, 0x0005, 0xade8, 0x000d,
+	0x6800, 0xa005, 0x0904, 0x2927, 0x6804, 0xd0ac, 0x0118, 0xd0a4,
+	0x0904, 0x2927, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104, 0xa18d,
+	0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100, 0x6104,
+	0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c, 0xffef, 0x6106, 0x00ce,
+	0x2009, 0x0100, 0x210c, 0xa18a, 0x0002, 0x0268, 0xd084, 0x0158,
+	0x6a28, 0xa28a, 0x007f, 0x1a04, 0x2927, 0xa288, 0x2719, 0x210d,
+	0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0130, 0x6828, 0xa08a, 0x007f,
+	0x1a04, 0x2927, 0x604e, 0x6808, 0xa08a, 0x0100, 0x0a04, 0x2927,
+	0xa08a, 0x0841, 0x1a04, 0x2927, 0xa084, 0x0007, 0x1904, 0x2927,
+	0x680c, 0xa005, 0x0904, 0x2927, 0x6810, 0xa005, 0x0904, 0x2927,
+	0x6848, 0x6940, 0xa10a, 0x1a04, 0x2927, 0x8001, 0x0904, 0x2927,
+	0x684c, 0x6944, 0xa10a, 0x1a04, 0x2927, 0x8001, 0x0904, 0x2927,
+	0x6804, 0xd0fc, 0x01f8, 0x080c, 0x3641, 0x0904, 0x2924, 0x2009,
+	0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290, 0x0038, 0xa399,
+	0x0000, 0x080c, 0x3682, 0x701b, 0x312e, 0x0005, 0xade8, 0x000d,
+	0x20a9, 0x0014, 0x2d98, 0x2069, 0x926d, 0x2da0, 0x53a3, 0x7010,
+	0xa0e8, 0x000d, 0x20a9, 0x001c, 0x2d98, 0x2069, 0x9251, 0x2da0,
+	0x53a3, 0x6814, 0xa08c, 0x00ff, 0x613e, 0x8007, 0xa084, 0x00ff,
+	0x6042, 0x080c, 0x4e5d, 0x080c, 0x4780, 0x080c, 0x47d8, 0x6000,
+	0xa086, 0x0000, 0x1904, 0x31e5, 0x6808, 0x602a, 0x080c, 0x20ce,
+	0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f,
+	0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830,
+	0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010,
+	0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x080c, 0x57bc,
+	0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000, 0x20a9, 0x0001,
+	0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109,
+	0x080c, 0x532a, 0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00,
+	0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003,
+	0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3184, 0x00ce, 0x2069,
+	0x9251, 0x2001, 0x94d7, 0x6a80, 0xa294, 0x0030, 0xa28e, 0x0000,
+	0x0178, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020, 0x0148, 0x2003,
+	0xaaaa, 0x2001, 0x0204, 0x2004, 0x2009, 0x94c8, 0x200a, 0x0008,
+	0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000,
+	0x00ce, 0x080c, 0x4dc5, 0x0128, 0x080c, 0x3912, 0x0110, 0x080c,
+	0x2455, 0x60c0, 0xa005, 0x01a8, 0x6003, 0x0001, 0x2091, 0x301d,
+	0x080c, 0x4dc5, 0x1158, 0x2011, 0x4ce2, 0x080c, 0x5731, 0x2001,
+	0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0038, 0x080c, 0x4105,
+	0x0020, 0x6003, 0x0004, 0x2091, 0x301d, 0x0804, 0x28ff, 0x6000,
+	0xa086, 0x0000, 0x0904, 0x2924, 0x2069, 0x9251, 0x7830, 0x6842,
+	0x7834, 0x6846, 0x2d00, 0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c,
+	0x7d38, 0x0804, 0x3685, 0x81ff, 0x1904, 0x2924, 0x080c, 0x4dc5,
+	0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200, 0x2003,
+	0x0001, 0x080c, 0x4d10, 0x0038, 0xa006, 0x080c, 0x2455, 0x080c,
+	0x41c5, 0x080c, 0x4105, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924,
+	0x080c, 0x4dc5, 0x1110, 0x0804, 0x2924, 0x6184, 0x81ff, 0x0198,
+	0x703f, 0x0000, 0x2001, 0x98c0, 0x2009, 0x0040, 0x7a2c, 0x7b28,
+	0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3685, 0x701b,
+	0x28fd, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069, 0x98c0,
+	0x20a9, 0x0040, 0x20a1, 0x98c0, 0x2019, 0xffff, 0x43a4, 0x654c,
+	0xa588, 0x2719, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011,
+	0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x4434, 0x1190, 0x6014,
+	0x821c, 0x0238, 0xa398, 0x98c0, 0xa085, 0xff00, 0x8007, 0x201a,
+	0x0038, 0xa398, 0x98c0, 0x2324, 0xa4a4, 0xff00, 0xa405, 0x201a,
+	0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201, 0x8007,
+	0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1, 0x98c0,
+	0x2099, 0x98c0, 0x080c, 0x4166, 0x0804, 0x3222, 0x080c, 0x3666,
+	0x0904, 0x2927, 0x00c6, 0x080c, 0x3641, 0x00ce, 0x0904, 0x2924,
+	0x080c, 0x4dc5, 0x0500, 0x2001, 0x9252, 0x2004, 0xd0b4, 0x01d8,
+	0x6000, 0xd08c, 0x11c0, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x1190, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x8476,
+	0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x329f, 0x0005, 0x080c,
+	0x3666, 0x0904, 0x2927, 0x20a9, 0x002d, 0x2c98, 0xade8, 0x0002,
+	0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80,
+	0x0006, 0x20a0, 0x080c, 0x4166, 0x20a9, 0x0004, 0xac80, 0x000a,
+	0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4166, 0x2d00, 0x2009,
+	0x002f, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, 0x81ff,
+	0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c, 0x45e9,
+	0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x7828, 0xa08a, 0x1000,
+	0x1a04, 0x2927, 0x080c, 0x3666, 0x0904, 0x2927, 0x080c, 0x4644,
+	0x0904, 0x2924, 0x2019, 0x0004, 0x080c, 0x45fb, 0x7924, 0x810f,
+	0x7a28, 0x0011, 0x0804, 0x28ff, 0xa186, 0x00ff, 0x0110, 0x0071,
+	0x0060, 0x2029, 0x007e, 0x2061, 0x9200, 0x644c, 0x2400, 0xa506,
+	0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c, 0x4434,
+	0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c, 0x573d,
+	0x0005, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927,
+	0x080c, 0x44d4, 0x0904, 0x2924, 0x080c, 0x45f2, 0x0804, 0x28ff,
+	0x81ff, 0x1904, 0x2924, 0x080c, 0x3656, 0x0904, 0x2927, 0x080c,
+	0x44d4, 0x0904, 0x2924, 0x080c, 0x45e0, 0x0804, 0x28ff, 0x6100,
+	0x2001, 0x94d8, 0x2014, 0xa282, 0x0003, 0x1210, 0x0804, 0x28ff,
+	0x2011, 0x0000, 0x0804, 0x28ff, 0x0804, 0x28ff, 0x080c, 0x3666,
+	0x0904, 0x2927, 0x6004, 0xa086, 0x0707, 0x0904, 0x2927, 0x2001,
+	0x9200, 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x00d6, 0xace8,
+	0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007,
+	0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
+	0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x28ff, 0x7824, 0xa09c,
+	0x00ff, 0xa39a, 0x0003, 0x1a04, 0x2924, 0x624c, 0xa294, 0x00ff,
+	0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001, 0x9240, 0x2009,
+	0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685, 0x81ff,
+	0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927, 0x6004, 0xa084,
+	0x00ff, 0xa086, 0x0006, 0x1904, 0x2924, 0x00c6, 0x080c, 0x3641,
+	0x00ce, 0x0904, 0x2924, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
+	0x080c, 0x8428, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3399,
+	0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0xad80, 0x000e,
+	0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3685,
+	0x7824, 0xa084, 0x00ff, 0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904,
+	0x2924, 0x080c, 0x4dc5, 0x0128, 0xa006, 0x080c, 0x2455, 0x080c,
+	0x41c5, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x2927, 0x7924, 0xa18c,
+	0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182, 0x007f, 0x1a04,
+	0x2927, 0x2100, 0x080c, 0x241f, 0x0026, 0x00c6, 0x0126, 0x2091,
+	0x8000, 0x2061, 0x94f8, 0x601b, 0x0000, 0x601f, 0x0000, 0x080c,
+	0x4dc5, 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200,
+	0x2003, 0x0001, 0x080c, 0x4d10, 0x00a0, 0x2061, 0x0100, 0x2001,
+	0x9214, 0x2004, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043,
+	0x0090, 0x6043, 0x0010, 0x2009, 0x001e, 0x2011, 0x412a, 0x080c,
+	0x57b3, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4dc5, 0x1110,
+	0x2009, 0x00ff, 0x7a28, 0x080c, 0x32ec, 0x012e, 0x00ce, 0x002e,
+	0x0804, 0x28ff, 0x7924, 0xa18c, 0xff00, 0x810f, 0x00c6, 0x080c,
+	0x4400, 0x2c08, 0x00ce, 0x1904, 0x2927, 0x0804, 0x28ff, 0x81ff,
+	0x1904, 0x2924, 0x60c8, 0xd0ac, 0x1118, 0xd09c, 0x0904, 0x2924,
+	0x080c, 0x3641, 0x0904, 0x2924, 0x7924, 0x7a2c, 0x7b28, 0x7c3c,
+	0x7d38, 0x080c, 0x3682, 0x701b, 0x342e, 0x0005, 0x2009, 0x0080,
+	0x080c, 0x4434, 0x1130, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x0120, 0x2021, 0x400a, 0x0804, 0x2901, 0x00d6, 0xade8, 0x000d,
+	0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be,
+	0x0100, 0x0904, 0x34a1, 0xa0be, 0x0112, 0x0904, 0x34a1, 0xa0be,
+	0x0113, 0x0904, 0x34a1, 0xa0be, 0x0114, 0x0904, 0x34a1, 0xa0be,
+	0x0117, 0x0904, 0x34a1, 0xa0be, 0x011a, 0x0904, 0x34a1, 0xa0be,
+	0x0121, 0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8,
+	0xa0be, 0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007,
+	0x6832, 0x04a0, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528,
+	0xa0be, 0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a,
+	0x1120, 0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8,
+	0x00de, 0x0804, 0x2927, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c,
+	0x34dd, 0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x34dd, 0x0048,
+	0xad80, 0x000c, 0x080c, 0x34eb, 0x0048, 0xad80, 0x000e, 0x080c,
+	0x34eb, 0xad80, 0x000c, 0x20a9, 0x0001, 0x04b9, 0x00c6, 0x080c,
+	0x3641, 0x0540, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853,
+	0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883,
+	0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000,
+	0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823,
+	0x0000, 0x080c, 0x8442, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b,
+	0x34d6, 0x0005, 0x00ce, 0x00de, 0x0804, 0x2924, 0x6820, 0xa086,
+	0x8001, 0x0904, 0x2924, 0x0804, 0x28ff, 0x0016, 0x2008, 0x2044,
+	0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108, 0x1f04,
+	0x34df, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008, 0x2044,
+	0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a, 0x8108,
+	0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae, 0x001e,
+	0x0005, 0x81ff, 0x1904, 0x2924, 0x7924, 0x2140, 0xa18c, 0xff00,
+	0x810f, 0x60c8, 0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x2927,
+	0xa182, 0x00ff, 0x1a04, 0x2927, 0x7a2c, 0x7b28, 0x606c, 0xa306,
+	0x1140, 0x6070, 0xa24e, 0x0904, 0x2927, 0xa9cc, 0xff00, 0x0904,
+	0x2927, 0x00c6, 0x080c, 0x359b, 0x2c68, 0x00ce, 0x01c0, 0xa0c6,
+	0x4000, 0x1108, 0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060,
+	0xa0c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009,
+	0x1108, 0x0010, 0x2001, 0x4006, 0x2020, 0x0804, 0x2901, 0x2d00,
+	0x7022, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x749c,
+	0x05b8, 0x2d00, 0x601a, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c,
+	0x3641, 0x00ce, 0x2b70, 0x1140, 0x080c, 0x74f2, 0x00ee, 0x00ce,
+	0x00be, 0x001e, 0x0804, 0x2924, 0x6837, 0x0000, 0x683b, 0x0000,
+	0x2d00, 0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0xd88c, 0x0108,
+	0xc0f5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x266c, 0x012e,
+	0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002,
+	0x080c, 0x43e3, 0x2009, 0x0002, 0x080c, 0x7518, 0xa085, 0x0001,
+	0x00ee, 0x00ce, 0x00be, 0x001e, 0x0904, 0x2924, 0x7007, 0x0003,
+	0x701b, 0x358b, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x2924,
+	0x7020, 0x2060, 0x2009, 0x0000, 0x080c, 0x46a5, 0x1110, 0x2009,
+	0x0001, 0x0804, 0x28ff, 0x00e6, 0x00d6, 0x2029, 0x0000, 0x2001,
+	0x9232, 0x2004, 0xd0ac, 0x0138, 0x2021, 0x0000, 0x20a9, 0x00ff,
+	0x2071, 0x936e, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071,
+	0x93ee, 0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1548, 0x2428,
+	0xc5fd, 0x0430, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14,
+	0x2600, 0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884,
+	0x0540, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1510, 0x2001,
+	0x4000, 0x0400, 0x2001, 0x4007, 0x00e8, 0x2400, 0xa106, 0x1140,
+	0x6e14, 0x87ff, 0x1110, 0x86ff, 0x09d0, 0x2001, 0x4008, 0x0090,
+	0x8420, 0x8e70, 0x1f04, 0x35b1, 0x85ff, 0x1130, 0x2001, 0x4009,
+	0x0048, 0x2001, 0x0001, 0x0030, 0x080c, 0x4400, 0x1dd0, 0x6312,
+	0x6216, 0xa006, 0xa005, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x1904,
+	0x2924, 0x080c, 0x3641, 0x0904, 0x2924, 0x6837, 0x0000, 0x6838,
+	0xc0fd, 0x683a, 0x7824, 0xa005, 0x0904, 0x2927, 0xa096, 0x00ff,
+	0x0120, 0xa092, 0x0004, 0x1a04, 0x2927, 0x2010, 0x2d18, 0x080c,
+	0x2631, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3618, 0x0005,
+	0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, 0x7924,
+	0xa18c, 0xff00, 0x810f, 0x60c8, 0xd0ac, 0x1120, 0xa182, 0x0080,
+	0x0a04, 0x2927, 0xa182, 0x00ff, 0x1a04, 0x2927, 0x0126, 0x2091,
+	0x8000, 0x080c, 0x831a, 0x1150, 0xa190, 0x936e, 0x2204, 0xa065,
+	0x0128, 0x080c, 0x41e0, 0x012e, 0x0804, 0x28ff, 0x012e, 0x0804,
+	0x2924, 0x080c, 0x147c, 0x0188, 0xa006, 0x6802, 0x7010, 0xa005,
+	0x1120, 0x2d00, 0x7012, 0x7016, 0x0030, 0x7014, 0x6802, 0x2060,
+	0x2d00, 0x6006, 0x7016, 0xad80, 0x000d, 0x0005, 0x7924, 0x810f,
+	0xa18c, 0x00ff, 0x080c, 0x4434, 0x1130, 0x7e28, 0xa684, 0x3fff,
+	0xa082, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x7e24, 0x860f,
+	0xa18c, 0x00ff, 0x080c, 0x4434, 0x1128, 0xa6b4, 0x00ff, 0xa682,
+	0x4000, 0x0208, 0xa066, 0x8cff, 0x0005, 0x0016, 0x7110, 0x81ff,
+	0x0128, 0x2168, 0x6904, 0x080c, 0x1493, 0x0cc8, 0x7112, 0x7116,
+	0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061,
+	0x92e6, 0x6606, 0x6112, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532,
+	0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x28ff, 0x0005,
+	0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001, 0x92a4,
+	0x2004, 0xa005, 0x1168, 0x0e04, 0x36b0, 0x7818, 0xd084, 0x1140,
+	0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001, 0x2091, 0x4080, 0x0408,
+	0x0016, 0x00c6, 0x00e6, 0x2071, 0x9296, 0x7138, 0xa182, 0x0010,
+	0x0218, 0x7030, 0x2060, 0x0078, 0x7030, 0xa0e0, 0x0004, 0xac82,
+	0x92e6, 0x0210, 0x2061, 0x92a6, 0x2c00, 0x7032, 0x81ff, 0x1108,
+	0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a, 0x00ee, 0x00ce,
+	0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x9296, 0x7038,
+	0xa005, 0x0570, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3707, 0x00f6,
+	0x2079, 0x0000, 0x7818, 0xd084, 0x1508, 0x00c6, 0x7034, 0x2060,
+	0x2c04, 0x7822, 0x6004, 0x7826, 0x6008, 0x782a, 0x781b, 0x0001,
+	0x2091, 0x4080, 0x7038, 0x8001, 0x703a, 0xa005, 0x1130, 0x7033,
+	0x92a6, 0x7037, 0x92a6, 0x00ce, 0x0048, 0xac80, 0x0004, 0xa0fa,
+	0x92e6, 0x0210, 0x2001, 0x92a6, 0x7036, 0x00ce, 0x00fe, 0x012e,
+	0x00ee, 0x0005, 0x0026, 0x2001, 0x9252, 0x2004, 0xd0c4, 0x0120,
+	0x2011, 0x8014, 0x080c, 0x3698, 0x002e, 0x0005, 0x81ff, 0x1904,
+	0x2924, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0x6032, 0x080c,
+	0x4dc5, 0x1158, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200,
+	0x2003, 0x0001, 0x080c, 0x4d10, 0x0010, 0x080c, 0x4105, 0x012e,
+	0x0804, 0x28ff, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128, 0x61d4,
+	0xa10d, 0x61d6, 0x0804, 0x28ff, 0x0804, 0x2927, 0x81ff, 0x1904,
+	0x2924, 0x6000, 0xa086, 0x0003, 0x1904, 0x2924, 0x2001, 0x9252,
+	0x2004, 0xd0a4, 0x1904, 0x2924, 0x080c, 0x3666, 0x0904, 0x2927,
+	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828, 0xa005,
+	0x0904, 0x28ff, 0x00c6, 0x080c, 0x3641, 0x00ce, 0x0904, 0x2924,
+	0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c,
+	0x84d7, 0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x3770, 0x0005,
+	0x6830, 0xa086, 0x0100, 0x0904, 0x2924, 0x0804, 0x28ff, 0x2001,
+	0x9200, 0x2004, 0xa086, 0x0003, 0x1904, 0x2924, 0x7f24, 0x7a2c,
+	0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3641, 0x0904, 0x2924, 0x2009,
+	0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80,
+	0x0005, 0x7026, 0x20a0, 0x080c, 0x4434, 0x15e0, 0x6004, 0xa0c4,
+	0x00ff, 0xa8c6, 0x0006, 0x0150, 0xa0c4, 0xff00, 0xa8c6, 0x0600,
+	0x0128, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1660, 0xd784, 0x0150,
+	0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c,
+	0x34eb, 0x0048, 0xac80, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004,
+	0x53a3, 0x080c, 0x34eb, 0xa186, 0x007e, 0x0178, 0xa186, 0x0080,
+	0x0160, 0x6004, 0xa084, 0x00ff, 0xa0c2, 0x0006, 0x1210, 0xc1fd,
+	0x0020, 0x080c, 0x46a5, 0x1108, 0xc1fd, 0x21a2, 0xc1fc, 0x94a0,
+	0xa6b0, 0x0005, 0x8108, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x0118,
+	0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100, 0x0148,
+	0x0018, 0xa186, 0x007e, 0x0128, 0xa686, 0x0028, 0x0150, 0x0804,
+	0x3793, 0x86ff, 0x1120, 0x7120, 0x810b, 0x0804, 0x28ff, 0x702f,
+	0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0x92e6,
+	0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e,
+	0x6532, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3809,
+	0x0005, 0x702c, 0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728,
+	0x2031, 0x0000, 0x2061, 0x92e6, 0x6224, 0x6328, 0x642c, 0x6530,
+	0x0804, 0x3793, 0x7120, 0x810b, 0x0804, 0x28ff, 0x2029, 0x007e,
+	0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2,
+	0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa184, 0x00ff,
+	0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa284,
+	0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04,
+	0x2927, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502,
+	0x0a04, 0x2927, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04,
+	0x2927, 0xa502, 0x0a04, 0x2927, 0xa384, 0x00ff, 0xa0e2, 0x0020,
+	0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa484, 0xff00, 0x8007,
+	0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927, 0xa484,
+	0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x2927, 0xa502, 0x0a04, 0x2927,
+	0x2061, 0x94df, 0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x28ff,
+	0x080c, 0x3641, 0x0904, 0x2924, 0x2009, 0x0015, 0x7a2c, 0x7b28,
+	0x7c3c, 0x7d38, 0x080c, 0x3682, 0x701b, 0x3887, 0x0005, 0xade8,
+	0x000d, 0x6800, 0xa005, 0x0904, 0x2927, 0x6804, 0x2008, 0xa18c,
+	0xfff8, 0x1904, 0x2927, 0x680c, 0xa005, 0x0904, 0x2927, 0xa082,
+	0xff01, 0x1a04, 0x2927, 0x6810, 0xa082, 0x005c, 0x0a04, 0x2927,
+	0x6824, 0x2008, 0xa082, 0x0008, 0x0a04, 0x2927, 0xa182, 0x0400,
+	0x1a04, 0x2927, 0x080c, 0x5a84, 0x6944, 0x6820, 0xa102, 0x0a04,
+	0x2927, 0x6828, 0x6944, 0x810c, 0xa102, 0x0a04, 0x2927, 0x6840,
+	0xa082, 0x000f, 0x1a04, 0x2927, 0x00d6, 0x080c, 0x145f, 0x0904,
+	0x2924, 0x2d00, 0x00de, 0x684e, 0x00d6, 0x6848, 0xa005, 0x0148,
+	0x2008, 0x2069, 0x9200, 0x68dc, 0xa108, 0x68a8, 0xa102, 0x1208,
+	0x69de, 0x00de, 0x20a9, 0x0015, 0x2d98, 0x2069, 0x9281, 0x2da0,
+	0x53a3, 0x080c, 0x5957, 0x0904, 0x2924, 0x080c, 0x5885, 0x1904,
+	0x2924, 0x00c6, 0x2061, 0x0100, 0x6104, 0xa18d, 0x8000, 0x6106,
+	0x610c, 0xa18d, 0x0100, 0x610e, 0x2061, 0x0140, 0x610c, 0xa18d,
+	0x0100, 0x6902, 0x6b10, 0x2061, 0x9519, 0x6316, 0x080c, 0x4716,
+	0x2001, 0x9295, 0x2003, 0x0000, 0x00ce, 0x0804, 0x28ff, 0xe000,
+	0xe000, 0xe000, 0xe000, 0xe000, 0xe000, 0xe000, 0x0804, 0x28ff,
+	0x7824, 0x0804, 0x28ff, 0x7824, 0x00e6, 0x2071, 0x9281, 0x00ee,
+	0x0804, 0x28ff, 0x0006, 0x2001, 0x9252, 0x2004, 0xd0cc, 0x000e,
+	0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xd0bc, 0x000e, 0x0005,
+	0x6164, 0x7a24, 0x6300, 0x82ff, 0x1118, 0x7926, 0x0804, 0x28ff,
+	0x83ff, 0x1904, 0x2927, 0x2001, 0xfff0, 0xa200, 0x1a04, 0x2927,
+	0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0a04, 0x2927, 0x7926,
+	0x6266, 0x0804, 0x28ff, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003,
+	0x1904, 0x2924, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x080c, 0x3641,
+	0x0904, 0x2924, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000,
+	0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0x936e,
+	0x2c64, 0x8cff, 0x01b8, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
+	0x0130, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600, 0x1158, 0x6014,
+	0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105, 0x8007, 0x20a2, 0x94a0,
+	0xa398, 0x0002, 0x8108, 0xa182, 0x00ff, 0x0120, 0xa386, 0x002a,
+	0x0148, 0x08e0, 0x83ff, 0x1120, 0x7120, 0x810c, 0x0804, 0x28ff,
+	0x702f, 0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0x92e6,
+	0x6007, 0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e,
+	0x6732, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3999,
+	0x0005, 0x702c, 0xa005, 0x1158, 0x711c, 0x7024, 0x20a0, 0x2019,
+	0x0000, 0x6424, 0x6528, 0x662c, 0x6730, 0x0804, 0x3956, 0x7120,
+	0x810c, 0x0804, 0x28ff, 0x81ff, 0x1904, 0x2924, 0x60c8, 0xd0ac,
+	0x1118, 0xd09c, 0x0904, 0x2924, 0x080c, 0x3641, 0x0904, 0x2924,
+	0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3682, 0x701b,
+	0x39c2, 0x0005, 0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000,
+	0x0148, 0xa0be, 0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de,
+	0x0804, 0x2927, 0x6820, 0x6924, 0x080c, 0x240b, 0x1500, 0x080c,
+	0x4400, 0x11e8, 0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c,
+	0x3641, 0x01a8, 0x080c, 0x3641, 0x0190, 0x00ce, 0x00de, 0x6837,
+	0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x080c, 0x845c,
+	0x0904, 0x2924, 0x7007, 0x0003, 0x701b, 0x39fa, 0x0005, 0x00de,
+	0x0804, 0x2924, 0x7120, 0x080c, 0x441f, 0x6820, 0xa086, 0x8001,
+	0x0904, 0x2924, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006,
+	0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4166, 0x000e, 0xade8,
+	0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0x92e6, 0x6007,
+	0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6,
+	0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x2927, 0x2009, 0x0004,
+	0x0804, 0x3685, 0xa7c6, 0x7200, 0x1904, 0x2927, 0xa6c2, 0x0054,
+	0x0a04, 0x2927, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e,
+	0x6532, 0x2c10, 0x080c, 0x14c7, 0x7007, 0x0002, 0x701b, 0x3a41,
+	0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080,
+	0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4166,
+	0x000e, 0x2009, 0x002a, 0x2061, 0x92e6, 0x6224, 0x6328, 0x642c,
+	0x6530, 0x0804, 0x3685, 0x81ff, 0x1904, 0x2924, 0x080c, 0x3656,
+	0x0904, 0x2927, 0x080c, 0x44d4, 0x0904, 0x2924, 0x080c, 0x4604,
+	0x0804, 0x28ff, 0x0126, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071,
+	0x9200, 0x6044, 0xd0a4, 0x11b0, 0xd084, 0x0118, 0x080c, 0x3bd7,
+	0x0068, 0xd08c, 0x0118, 0x080c, 0x3af8, 0x0040, 0xd094, 0x0118,
+	0x080c, 0x3ad0, 0x0018, 0xd09c, 0x0108, 0x0061, 0x00ee, 0x00ce,
+	0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a,
+	0x001e, 0x0ca0, 0x624c, 0xa286, 0xf0f0, 0x1150, 0x6048, 0xa086,
+	0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0478,
+	0xa294, 0xff00, 0xa296, 0xf700, 0x0160, 0x6240, 0xa295, 0x0100,
+	0x6242, 0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x4186,
+	0x00f0, 0x6040, 0xa084, 0x0010, 0xa085, 0x0040, 0x6042, 0x6043,
+	0x0000, 0x7077, 0x0000, 0x7093, 0x0001, 0x70b3, 0x0000, 0x70cb,
+	0x0000, 0x2009, 0x98c0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b,
+	0x000f, 0x2009, 0x000f, 0x2011, 0x40a8, 0x080c, 0x57b3, 0x0005,
+	0x0156, 0x7078, 0xa005, 0x1510, 0x2011, 0x40a8, 0x080c, 0x5731,
+	0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8,
+	0x6044, 0xd08c, 0x1168, 0x1f04, 0x3ae0, 0x6242, 0x708b, 0x0000,
+	0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030,
+	0x6242, 0x708b, 0x0000, 0x707f, 0x0000, 0x0000, 0x015e, 0x0005,
+	0x707c, 0xa08a, 0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x13fe,
+	0x0005, 0x3b04, 0x3b54, 0x3bd6, 0x00f6, 0x707f, 0x0001, 0x20e1,
+	0xa000, 0xe000, 0x20e1, 0x8700, 0x080c, 0x20ce, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2079, 0x9700, 0x207b, 0x2200, 0x7807, 0x00ef,
+	0x780b, 0x0000, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000,
+	0x781b, 0x0000, 0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff,
+	0x782b, 0x0000, 0x782f, 0x0000, 0x2079, 0x970c, 0x207b, 0x1101,
+	0x7807, 0x0000, 0x2099, 0x9205, 0x20a1, 0x970e, 0x20a9, 0x0004,
+	0x53a3, 0x2079, 0x9712, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099,
+	0x9700, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c,
+	0x600f, 0x0000, 0x080c, 0x40ec, 0x00fe, 0x7083, 0x0000, 0x6043,
+	0x0008, 0x6043, 0x0000, 0x0005, 0x00d6, 0x7080, 0x7083, 0x0000,
+	0xa025, 0x0904, 0x3bbe, 0x6020, 0xd0b4, 0x1904, 0x3bbc, 0x7190,
+	0x81ff, 0x0904, 0x3ba6, 0xa486, 0x000c, 0x1904, 0x3bb1, 0xa480,
+	0x0018, 0x8004, 0x20a8, 0x2011, 0x9780, 0x2019, 0x9700, 0x220c,
+	0x2304, 0xa106, 0x1188, 0x8210, 0x8318, 0x1f04, 0x3b6f, 0x6043,
+	0x0004, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f,
+	0x0002, 0x708b, 0x0002, 0x04c0, 0x2069, 0x9780, 0x6930, 0xa18e,
+	0x1101, 0x1538, 0x6834, 0xa005, 0x1520, 0x6900, 0xa18c, 0x00ff,
+	0x1118, 0x6804, 0xa005, 0x0190, 0x2011, 0x978e, 0x2019, 0x9205,
+	0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0230, 0x1190, 0x8210,
+	0x8318, 0x1f04, 0x3b9a, 0x0068, 0x7093, 0x0000, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x20a9, 0x0014,
+	0x53a6, 0x6043, 0x0008, 0x6043, 0x0000, 0x6020, 0xd0b4, 0x1120,
+	0x60c3, 0x000c, 0x080c, 0x40ec, 0x00de, 0x0005, 0x6040, 0xa085,
+	0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011,
+	0x94ef, 0x2013, 0x0000, 0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3,
+	0x0056, 0x60a7, 0x9575, 0x080c, 0x6f15, 0x0c30, 0x0005, 0x7088,
+	0xa08a, 0x001d, 0x1210, 0x0023, 0x0010, 0x080c, 0x13fe, 0x0005,
+	0x3c0a, 0x3c19, 0x3c43, 0x3c58, 0x3c7e, 0x3ca6, 0x3ccc, 0x3cfd,
+	0x3d23, 0x3d4b, 0x3d86, 0x3dae, 0x3dca, 0x3de0, 0x3e00, 0x3e13,
+	0x3e1b, 0x3e45, 0x3e6b, 0x3e93, 0x3eb9, 0x3eea, 0x3f25, 0x3f54,
+	0x3f70, 0x3faf, 0x3fcf, 0x3fe8, 0x3fe9, 0x00c6, 0x2061, 0x9200,
+	0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006,
+	0x00ce, 0x0005, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002,
+	0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x40af, 0x080c, 0x5725,
+	0x0005, 0x00f6, 0x7080, 0xa086, 0x0014, 0x1518, 0x6043, 0x0000,
+	0x6020, 0xd0b4, 0x11f0, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1102,
+	0x11b0, 0x7834, 0xa005, 0x1198, 0x7a38, 0xd2fc, 0x0138, 0x70b0,
+	0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x2011, 0x40af,
+	0x080c, 0x5731, 0x708b, 0x0010, 0x080c, 0x3e1b, 0x0010, 0x7083,
+	0x0000, 0x00fe, 0x0005, 0x708b, 0x0003, 0x6043, 0x0004, 0x080c,
+	0x416e, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3,
+	0x0000, 0x1f04, 0x3c4f, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005,
+	0x00f6, 0x7080, 0xa005, 0x0500, 0x2011, 0x40af, 0x080c, 0x5731,
+	0xa086, 0x0014, 0x11b8, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1102,
+	0x1188, 0x7834, 0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0,
+	0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x708b, 0x0004,
+	0x0029, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0005,
+	0x080c, 0x416e, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011,
+	0x978e, 0x080c, 0x41bd, 0x1160, 0x7074, 0xa005, 0x1148, 0x714c,
+	0xa186, 0xffff, 0x0128, 0x080c, 0x4074, 0x0110, 0x080c, 0x419d,
+	0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080,
+	0xa005, 0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014,
+	0x11b8, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1103, 0x1188, 0x7834,
+	0xa005, 0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120,
+	0x080c, 0x419d, 0x70b3, 0x0001, 0x708b, 0x0006, 0x0029, 0x0010,
+	0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x0007, 0x080c, 0x416e,
+	0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011, 0x978e, 0x080c,
+	0x41bd, 0x11a8, 0x7074, 0xa005, 0x1190, 0x7154, 0xa186, 0xffff,
+	0x0170, 0xa180, 0x2719, 0x200d, 0xa18c, 0xff00, 0x810f, 0x080c,
+	0x4074, 0x0128, 0x080c, 0x3919, 0x0110, 0x080c, 0x2455, 0x20a9,
+	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005,
+	0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8,
+	0x2079, 0x9780, 0x7a30, 0xa296, 0x1104, 0x1188, 0x7834, 0xa005,
+	0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
+	0x419d, 0x70b3, 0x0001, 0x708b, 0x0008, 0x0029, 0x0010, 0x080c,
+	0x41b6, 0x00fe, 0x0005, 0x708b, 0x0009, 0x080c, 0x416e, 0x20a3,
+	0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x41bd, 0x1150, 0x7074,
+	0xa005, 0x1138, 0x080c, 0x3fea, 0x1170, 0xa085, 0x0001, 0x080c,
+	0x2455, 0x20a9, 0x0008, 0x2099, 0x978e, 0x26a0, 0x53a6, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec, 0x0010,
+	0x080c, 0x3bfd, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011,
+	0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x1560, 0x2079, 0x9780,
+	0x7a30, 0xa296, 0x1105, 0x1530, 0x7834, 0x2011, 0x0100, 0xa21e,
+	0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
+	0x419d, 0x70b3, 0x0001, 0x708b, 0x000a, 0x00c1, 0x00a8, 0xa005,
+	0x1188, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
+	0x419d, 0x70b3, 0x0001, 0x7087, 0x0000, 0x708b, 0x000e, 0x080c,
+	0x3e00, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005, 0x708b, 0x000b,
+	0x2011, 0x970e, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4,
+	0x20a9, 0x0002, 0x2009, 0x0000, 0x41a4, 0x080c, 0x416e, 0x20a3,
+	0x1106, 0x20a3, 0x0000, 0x080c, 0x41bd, 0x0118, 0x2013, 0x0000,
+	0x0020, 0x7050, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042,
+	0x53a6, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080,
+	0xa005, 0x01b0, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0084,
+	0x1168, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834,
+	0xa005, 0x1120, 0x708b, 0x000c, 0x0029, 0x0010, 0x080c, 0x41b6,
+	0x00fe, 0x0005, 0x708b, 0x000d, 0x080c, 0x416e, 0x20a3, 0x1107,
+	0x20a3, 0x0000, 0x2099, 0x978e, 0x20a9, 0x0040, 0x53a6, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005,
+	0x00f6, 0x7080, 0xa005, 0x01d0, 0x2011, 0x40af, 0x080c, 0x5731,
+	0xa086, 0x0084, 0x1188, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1107,
+	0x1158, 0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, 0x4160,
+	0x708b, 0x000e, 0x0029, 0x0010, 0x080c, 0x41b6, 0x00fe, 0x0005,
+	0x708b, 0x000f, 0x7083, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5,
+	0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x40af,
+	0x080c, 0x5725, 0x0005, 0x7080, 0xa005, 0x0120, 0x2011, 0x40af,
+	0x080c, 0x5731, 0x0005, 0x708b, 0x0011, 0x716c, 0x81ff, 0x0170,
+	0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x080c, 0x240b, 0xa186,
+	0x0080, 0x0120, 0x2011, 0x978e, 0x080c, 0x4074, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x7480, 0xa480,
+	0x0018, 0xa080, 0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6,
+	0x60c3, 0x0014, 0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005,
+	0x0500, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8,
+	0x2079, 0x9780, 0x7a30, 0xa296, 0x1103, 0x1188, 0x7834, 0xa005,
+	0x1170, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
+	0x419d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x0029, 0x0010, 0x7083,
+	0x0000, 0x00fe, 0x0005, 0x708b, 0x0013, 0x080c, 0x417a, 0x20a3,
+	0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0x978e, 0x080c, 0x41bd,
+	0x1160, 0x7074, 0xa005, 0x1148, 0x714c, 0xa186, 0xffff, 0x0128,
+	0x080c, 0x4074, 0x0110, 0x080c, 0x419d, 0x20a9, 0x0008, 0x2298,
+	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
+	0x080c, 0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, 0x0500, 0x2011,
+	0x40af, 0x080c, 0x5731, 0xa086, 0x0014, 0x11b8, 0x2079, 0x9780,
+	0x7a30, 0xa296, 0x1104, 0x1188, 0x7834, 0xa005, 0x1170, 0x7a38,
+	0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c, 0x419d, 0x70b3,
+	0x0001, 0x708b, 0x0014, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe,
+	0x0005, 0x708b, 0x0015, 0x080c, 0x417a, 0x20a3, 0x1104, 0x20a3,
+	0x0000, 0x3430, 0x2011, 0x978e, 0x080c, 0x41bd, 0x11a8, 0x7074,
+	0xa005, 0x1190, 0x7154, 0xa186, 0xffff, 0x0170, 0xa180, 0x2719,
+	0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4074, 0x0128, 0x080c,
+	0x3919, 0x0110, 0x080c, 0x2455, 0x20a9, 0x0008, 0x2298, 0x26a0,
+	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
+	0x40ec, 0x0005, 0x00f6, 0x7080, 0xa005, 0x05a8, 0x2011, 0x40af,
+	0x080c, 0x5731, 0xa086, 0x0014, 0x1560, 0x2079, 0x9780, 0x7a30,
+	0xa296, 0x1105, 0x1530, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1178,
+	0x7a38, 0xd2f4, 0x0110, 0x70cb, 0x0008, 0xd2fc, 0x0138, 0x70b0,
+	0xa005, 0x1120, 0x080c, 0x419d, 0x70b3, 0x0001, 0x0070, 0xa005,
+	0x1180, 0x7a38, 0xd2fc, 0x0138, 0x70b0, 0xa005, 0x1120, 0x080c,
+	0x419d, 0x70b3, 0x0001, 0x7087, 0x0000, 0x708b, 0x0016, 0x0029,
+	0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x20e1, 0x9080, 0x20e1,
+	0x4000, 0x2099, 0x9780, 0x20a1, 0x020b, 0x20a9, 0x000e, 0x53a6,
+	0x3430, 0x2011, 0x978e, 0x708b, 0x0017, 0x080c, 0x41bd, 0x1150,
+	0x7074, 0xa005, 0x1138, 0x080c, 0x3fea, 0x1170, 0xa085, 0x0001,
+	0x080c, 0x2455, 0x20a9, 0x0008, 0x2099, 0x978e, 0x26a0, 0x53a6,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x40ec,
+	0x0010, 0x080c, 0x3bfd, 0x0005, 0x00f6, 0x7080, 0xa005, 0x01b0,
+	0x2011, 0x40af, 0x080c, 0x5731, 0xa086, 0x0084, 0x1168, 0x2079,
+	0x9780, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120,
+	0x708b, 0x0018, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005,
+	0x708b, 0x0019, 0x080c, 0x417a, 0x20a3, 0x1106, 0x20a3, 0x0000,
+	0x3430, 0x2099, 0x978e, 0x2039, 0x970e, 0x27a0, 0x20a9, 0x0040,
+	0x53a3, 0x080c, 0x41bd, 0x11e8, 0x2728, 0x2514, 0x8207, 0xa084,
+	0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007, 0xa205, 0x202a,
+	0x7050, 0x2310, 0x8214, 0xa2a0, 0x970e, 0x2414, 0xa38c, 0x0001,
+	0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff, 0x8007, 0xa215,
+	0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005, 0x00f6,
+	0x7080, 0xa005, 0x01d0, 0x2011, 0x40af, 0x080c, 0x5731, 0xa086,
+	0x0084, 0x1188, 0x2079, 0x9780, 0x7a30, 0xa296, 0x1107, 0x1158,
+	0x7834, 0xa005, 0x1140, 0x7087, 0x0001, 0x080c, 0x4160, 0x708b,
+	0x001a, 0x0029, 0x0010, 0x7083, 0x0000, 0x00fe, 0x0005, 0x708b,
+	0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9780, 0x20a1,
+	0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084, 0x03f8,
+	0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c, 0x40ec, 0x0005,
+	0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x9252, 0x252c, 0x20a9,
+	0x0008, 0x2041, 0x970e, 0x28a0, 0x2099, 0x978e, 0x53a3, 0x20a9,
+	0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011, 0x0000, 0x2800,
+	0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210,
+	0x0008, 0x8211, 0x1f04, 0x3fff, 0x0804, 0x406c, 0x82ff, 0x1160,
+	0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020, 0xa1a6, 0x3fff,
+	0x0904, 0x406c, 0xa18d, 0xc000, 0x20a9, 0x0010, 0x2019, 0x0001,
+	0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423,
+	0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318,
+	0x1f04, 0x4025, 0x04c8, 0x23a8, 0x2021, 0x0001, 0x8426, 0x8425,
+	0x1f04, 0x4037, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0158, 0x0006,
+	0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8, 0xa5a8, 0x0010,
+	0x1f04, 0x4046, 0x754e, 0xa5c8, 0x2719, 0x292d, 0xa5ac, 0x00ff,
+	0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2435, 0x001e, 0x60e7,
+	0x0000, 0x65ea, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001,
+	0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0xa085, 0x0001, 0x0028, 0xa006, 0x0018, 0xa006, 0x080c,
+	0x13fe, 0x009e, 0x008e, 0x0005, 0x2118, 0x2021, 0x0000, 0x2001,
+	0x0007, 0xa39a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118,
+	0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001,
+	0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8, 0xa238, 0x2704, 0xa42c,
+	0x11b0, 0xa405, 0x203a, 0x714e, 0xa1a0, 0x2719, 0x242d, 0xa5ac,
+	0x00ff, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x2435, 0x001e,
+	0x60e7, 0x0000, 0x65ea, 0x7077, 0x0001, 0xa084, 0x0000, 0x0005,
+	0x00e6, 0x2071, 0x9200, 0x707b, 0x0000, 0x00ee, 0x0005, 0x00e6,
+	0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x6f1e, 0x7004,
+	0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c,
+	0x4dcd, 0x01b0, 0x080c, 0x4deb, 0x1198, 0x2001, 0x94d7, 0x2003,
+	0xaaaa, 0x2001, 0x0204, 0x2004, 0x0016, 0x2009, 0x94c8, 0x200a,
+	0x001e, 0x2001, 0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0080,
+	0x0126, 0x2091, 0x8000, 0x2071, 0x9222, 0x2073, 0x0000, 0x7840,
+	0x0026, 0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x002e,
+	0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x2011,
+	0x94ef, 0x2013, 0x0000, 0x7083, 0x0000, 0x012e, 0x20e1, 0x9080,
+	0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x6f15, 0x2009, 0x07d0,
+	0x2011, 0x40af, 0x080c, 0x57b3, 0x0005, 0x0016, 0x0026, 0x00c6,
+	0x0126, 0x2091, 0x8000, 0x2009, 0x00f7, 0x080c, 0x4186, 0x2061,
+	0x94f8, 0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0x9200, 0x6003,
+	0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009,
+	0x001e, 0x2011, 0x412a, 0x080c, 0x5725, 0x012e, 0x00ce, 0x002e,
+	0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
+	0x0100, 0x080c, 0x6f1e, 0x2071, 0x0140, 0x7004, 0xa084, 0x4000,
+	0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x080c, 0x4dcd, 0x01b0,
+	0x080c, 0x4deb, 0x1198, 0x2001, 0x94d7, 0x2003, 0xaaaa, 0x2001,
+	0x0204, 0x2004, 0x0016, 0x2009, 0x94c8, 0x200a, 0x001e, 0x2001,
+	0x94d8, 0x2003, 0x0000, 0x080c, 0x4d10, 0x0030, 0x2001, 0x0001,
+	0x080c, 0x23ba, 0x080c, 0x4105, 0x012e, 0x000e, 0x00ee, 0x0005,
+	0x20a9, 0x0040, 0x20a1, 0x98c0, 0x2099, 0x978e, 0x3304, 0x8007,
+	0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4166, 0x0005, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x2099, 0x9700, 0x20a1, 0x020b, 0x20a9, 0x000c,
+	0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0x9780,
+	0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x00c6, 0x0006,
+	0x2061, 0x0100, 0x810f, 0x2001, 0x922f, 0x2004, 0xa005, 0x1138,
+	0x2001, 0x9214, 0x2004, 0xa084, 0x00ff, 0xa105, 0x0010, 0xa185,
+	0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005, 0x0016, 0x0046, 0x2001,
+	0x9252, 0x2004, 0xd0a4, 0x0158, 0xa006, 0x2020, 0x2009, 0x002a,
+	0x080c, 0x90d7, 0x2001, 0x920c, 0x200c, 0xc195, 0x2102, 0x2019,
+	0x002a, 0x080c, 0x264b, 0x004e, 0x001e, 0x0005, 0x080c, 0x4105,
+	0x708b, 0x0000, 0x7083, 0x0000, 0x0005, 0x0006, 0x2001, 0x920c,
+	0x2004, 0xd09c, 0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126,
+	0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102,
+	0x012e, 0x001e, 0x000e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009,
+	0x936e, 0xa006, 0x200a, 0x8108, 0x1f04, 0x41da, 0x015e, 0x0005,
+	0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x9251, 0xa006,
+	0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2719,
+	0x231d, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006,
+	0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4,
+	0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062,
+	0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082,
+	0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x61a2,
+	0x00d6, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1493, 0x60a7, 0x0000,
+	0x60a8, 0xa06d, 0x0110, 0x080c, 0x1493, 0x60ab, 0x0000, 0x00de,
+	0xa006, 0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0xa006, 0x60b2,
+	0x60ae, 0x60b6, 0x60bb, 0x0520, 0x6814, 0xa084, 0x00ff, 0x6042,
+	0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126, 0x2091,
+	0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1a04,
+	0x42cf, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04, 0x42d4,
+	0x2001, 0x920c, 0x2004, 0xa084, 0x0003, 0x1904, 0x42bd, 0xa188,
+	0x936e, 0x2104, 0xa065, 0x0904, 0x42a9, 0x6004, 0xa084, 0x00ff,
+	0xa08e, 0x0006, 0x1904, 0x42ae, 0x60a4, 0xa00d, 0x0118, 0x080c,
+	0x4630, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x467a, 0x1170,
+	0x694c, 0xd1fc, 0x1118, 0x080c, 0x43c4, 0x0448, 0x080c, 0x4386,
+	0x694c, 0xd1ec, 0x1520, 0x080c, 0x452b, 0x0408, 0x694c, 0xa184,
+	0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x453a,
+	0x0028, 0x080c, 0x453a, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4386,
+	0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000,
+	0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c,
+	0x6015, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000,
+	0x0478, 0x2001, 0x0028, 0x2009, 0x0000, 0x0450, 0xa082, 0x0006,
+	0x1260, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1120, 0x60a0, 0xd0bc,
+	0x0904, 0x4264, 0x2001, 0x0028, 0x0078, 0x2009, 0x920c, 0x210c,
+	0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001,
+	0x0004, 0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0048, 0x2001,
+	0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009, 0x0000,
+	0xa005, 0x012e, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000, 0x6844,
+	0x0006, 0x000e, 0x0006, 0x000e, 0xa084, 0xff00, 0xa08e, 0xff00,
+	0x1120, 0x2001, 0x94c6, 0x2064, 0x0098, 0x6844, 0x8007, 0xa084,
+	0x00ff, 0x2008, 0xa182, 0x00ff, 0x16c8, 0xa188, 0x936e, 0x2104,
+	0xa065, 0x01f0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11d8,
+	0x2c70, 0x080c, 0x749c, 0x0580, 0x2e00, 0x601a, 0x2d00, 0x6012,
+	0x601f, 0x0009, 0x600b, 0x0000, 0x6844, 0xa08e, 0xff00, 0x1110,
+	0x600b, 0x8000, 0x2009, 0x0100, 0x080c, 0x7518, 0xa006, 0x00c8,
+	0x2001, 0x0028, 0x00a8, 0xa082, 0x0006, 0x0e10, 0x2009, 0x920c,
+	0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118,
+	0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029,
+	0xa005, 0x012e, 0x00ee, 0x0005, 0x2001, 0x002c, 0x0cc8, 0x6944,
+	0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x1678, 0xa18c, 0xff00,
+	0x810f, 0xa182, 0x00ff, 0x12e0, 0xa188, 0x936e, 0x2104, 0xa065,
+	0x01b8, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11b0, 0x684c,
+	0xd0ec, 0x0120, 0x080c, 0x453a, 0x0489, 0x0030, 0x0479, 0x684c,
+	0xd0fc, 0x0110, 0x080c, 0x452b, 0x080c, 0x4578, 0xa006, 0x0088,
+	0x2001, 0x0028, 0x2009, 0x0000, 0x0060, 0xa082, 0x0006, 0x0e38,
+	0x2001, 0x0029, 0x2009, 0x0000, 0x0020, 0x2001, 0x0029, 0x2009,
+	0x0000, 0xa005, 0x0005, 0x0126, 0x2091, 0x8000, 0x6050, 0xa00d,
+	0x0138, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x012e, 0x0005,
+	0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0, 0x0126, 0x2091,
+	0x8000, 0x604c, 0xa005, 0x0170, 0x00e6, 0x2071, 0x94e5, 0x7004,
+	0xa086, 0x0002, 0x0168, 0x00ee, 0x604c, 0x6802, 0x2d00, 0x604e,
+	0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0cc0,
+	0x701c, 0xac06, 0x1d80, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00,
+	0x7002, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x604c,
+	0xa06d, 0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05,
+	0x012e, 0x0005, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005, 0x1108,
+	0x6052, 0x604e, 0xad05, 0x0005, 0x6803, 0x0000, 0x6084, 0xa00d,
+	0x0120, 0x2d00, 0x200a, 0x6086, 0x0005, 0x2d00, 0x6086, 0x6082,
+	0x0cd8, 0x0126, 0x00c6, 0x0026, 0x2091, 0x8000, 0x6218, 0x2260,
+	0x6200, 0xa005, 0x0110, 0xc285, 0x0008, 0xc284, 0x6202, 0x002e,
+	0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218,
+	0x2260, 0x6204, 0xa294, 0xff00, 0xa215, 0x6206, 0x00ce, 0x012e,
+	0x0005, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204,
+	0xa294, 0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005,
+	0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190,
+	0x936e, 0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x145f,
+	0x2d60, 0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000,
+	0x60ab, 0x0000, 0x080c, 0x41e0, 0xa006, 0x002e, 0x0005, 0x0026,
+	0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0060, 0x00d6, 0xa190,
+	0x936e, 0x2204, 0xa06d, 0x0120, 0x2013, 0x0000, 0x080c, 0x1493,
+	0x00de, 0xa006, 0x002e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218,
+	0xa085, 0x0001, 0x0030, 0xa188, 0x936e, 0x2104, 0xa065, 0x0dc0,
+	0xa006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b,
+	0x0000, 0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x4dc5,
+	0x1520, 0x60a0, 0xa086, 0x007e, 0x2069, 0x9790, 0x0130, 0x2001,
+	0x9232, 0x2004, 0xd0ac, 0x11c8, 0x0098, 0x2d04, 0xd0e4, 0x01a8,
+	0x00d6, 0x2069, 0x978e, 0x00c6, 0x2061, 0x94d9, 0x6810, 0x2062,
+	0x6814, 0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de,
+	0x8d69, 0x2d04, 0x2069, 0x0140, 0x6886, 0x2069, 0x978e, 0x6808,
+	0x605e, 0x6810, 0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814,
+	0x6066, 0x2099, 0x9796, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004,
+	0x53a3, 0x2099, 0x979a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004,
+	0x53a3, 0x2069, 0x97ae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810,
+	0x6072, 0x6818, 0x6076, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008,
+	0x0400, 0xa182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182,
+	0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218,
+	0x2009, 0x0005, 0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004,
+	0x0040, 0xa182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009,
+	0x0002, 0x6192, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x00e6,
+	0x2071, 0x978d, 0x2e04, 0x6896, 0x2071, 0x978e, 0x7004, 0x689a,
+	0x701c, 0x689e, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
+	0x60a4, 0xa06d, 0x01c0, 0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282,
+	0x0010, 0x1648, 0xad88, 0x0004, 0x20a9, 0x0010, 0x2104, 0xa086,
+	0xffff, 0x0128, 0x8108, 0x1f04, 0x44e6, 0x080c, 0x13fe, 0x260a,
+	0x8210, 0x6a06, 0x0098, 0x080c, 0x145f, 0x01a8, 0x2d00, 0x60a6,
+	0x6803, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff,
+	0x8108, 0x1f04, 0x44fe, 0x6807, 0x0001, 0x6e12, 0xa085, 0x0001,
+	0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000,
+	0x00d6, 0x60a4, 0xa00d, 0x01a0, 0x2168, 0x6800, 0xa005, 0x1160,
+	0x080c, 0x4630, 0x1168, 0x200b, 0xffff, 0x6804, 0xa08a, 0x0002,
+	0x0218, 0x8001, 0x6806, 0x0020, 0x080c, 0x1493, 0x60a7, 0x0000,
+	0x00de, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x468d,
+	0x0010, 0x080c, 0x4373, 0x080c, 0x45af, 0x1dd8, 0x080c, 0x4578,
+	0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d,
+	0x01c0, 0x6950, 0x81ff, 0x1540, 0x6a54, 0xa282, 0x0010, 0x1670,
+	0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128,
+	0x8108, 0x1f04, 0x454c, 0x080c, 0x13fe, 0x260a, 0x8210, 0x6a56,
+	0x0098, 0x080c, 0x145f, 0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000,
+	0xad88, 0x0018, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04,
+	0x4564, 0x6857, 0x0001, 0x6e62, 0x0010, 0x080c, 0x43c4, 0x0089,
+	0x1de0, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8,
+	0x0126, 0x2091, 0x8000, 0x080c, 0x6015, 0x012e, 0x0005, 0xa01e,
+	0x0010, 0x2019, 0x0001, 0xa00e, 0x0126, 0x2091, 0x8000, 0x604c,
+	0x2068, 0x6000, 0xd0dc, 0x1170, 0x8dff, 0x01e8, 0x83ff, 0x0120,
+	0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840,
+	0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x604c,
+	0xad06, 0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff,
+	0x1110, 0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019,
+	0x0001, 0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120,
+	0x6848, 0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840,
+	0xa506, 0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080,
+	0xad06, 0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff,
+	0x1110, 0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x462a, 0x1110,
+	0x2011, 0x0001, 0x080c, 0x4674, 0x1110, 0xa295, 0x0002, 0x0005,
+	0x080c, 0x46a5, 0x0118, 0x080c, 0x83ab, 0x0010, 0xa085, 0x0001,
+	0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x8338, 0x0010, 0xa085,
+	0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x837e, 0x0010,
+	0xa085, 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c, 0x8352,
+	0x0010, 0xa085, 0x0001, 0x0005, 0x080c, 0x46a5, 0x0118, 0x080c,
+	0x83d8, 0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6,
+	0x2091, 0x8000, 0x6080, 0xa06d, 0x0168, 0x6800, 0x0006, 0x6837,
+	0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, 0x080c, 0x4809,
+	0x000e, 0x0c88, 0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e,
+	0x012e, 0x0005, 0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005,
+	0x00e6, 0x2170, 0x7000, 0xa005, 0x1160, 0x20a9, 0x0010, 0xae88,
+	0x0004, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x4639, 0xa085,
+	0x0001, 0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
+	0x60a4, 0xa06d, 0x1128, 0x080c, 0x145f, 0x01a0, 0x2d00, 0x60a6,
+	0x6803, 0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010,
+	0x200b, 0xffff, 0x8108, 0x1f04, 0x4658, 0xa085, 0x0001, 0x012e,
+	0x00de, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000,
+	0x60a4, 0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1493, 0xa085,
+	0x0001, 0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085,
+	0x0001, 0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9,
+	0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04,
+	0x4683, 0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000,
+	0x0c19, 0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854,
+	0xa08a, 0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x1493,
+	0x60ab, 0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005,
+	0x00f6, 0x2079, 0x9251, 0x7804, 0xd0a4, 0x0518, 0x0156, 0x00c6,
+	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1168,
+	0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086,
+	0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04,
+	0x46b4, 0x00ce, 0x015e, 0x2009, 0x07d0, 0x2011, 0x46d3, 0x080c,
+	0x57b3, 0x00fe, 0x0005, 0x2011, 0x46d3, 0x080c, 0x5731, 0x0156,
+	0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434,
+	0x1530, 0x6000, 0xd0ec, 0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff,
+	0x8227, 0xa006, 0x2009, 0x0029, 0x080c, 0x90d7, 0x6000, 0xc0e5,
+	0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700, 0x6006,
+	0x2019, 0x0029, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, 0x080c,
+	0x606d, 0x2009, 0x0000, 0x080c, 0x8ee4, 0x008e, 0x004e, 0x001e,
+	0x8108, 0x1f04, 0x46dd, 0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018,
+	0x2060, 0x6000, 0xc0ec, 0x6002, 0x00ce, 0x0005, 0x00c6, 0x00d6,
+	0x080c, 0x145f, 0x2d60, 0x090c, 0x13fe, 0x2009, 0x00ff, 0x080c,
+	0x41e0, 0x6007, 0x0006, 0x6013, 0x00ff, 0x6017, 0xffff, 0x606f,
+	0x0200, 0x606c, 0x6093, 0x0002, 0x60bb, 0x0520, 0x60a3, 0x00ff,
+	0x60b7, 0x0000, 0x60af, 0x0000, 0x2c08, 0x2001, 0x94c6, 0x2102,
+	0x00de, 0x00ce, 0x0005, 0x0156, 0x00e6, 0x00d6, 0x00c6, 0x20a9,
+	0x00ff, 0x2009, 0x0000, 0x0016, 0x080c, 0x4434, 0x1138, 0x2c70,
+	0x70ac, 0xa005, 0x0118, 0x2060, 0x080c, 0x5cf4, 0x001e, 0x8108,
+	0x1f04, 0x4743, 0x00ce, 0x00de, 0x00ee, 0x015e, 0x0005, 0x2071,
+	0x9328, 0x7003, 0x0001, 0x7007, 0x0000, 0x7013, 0x0000, 0x7017,
+	0x0000, 0x701b, 0x0000, 0x701f, 0x0000, 0x704b, 0x0001, 0x704f,
+	0x0000, 0x705b, 0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071,
+	0x94b6, 0x7003, 0x9328, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f,
+	0x9496, 0x7013, 0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005,
+	0x0016, 0x00e6, 0x2071, 0x946e, 0xa00e, 0x7186, 0x718a, 0x7097,
+	0x0001, 0x2001, 0x9252, 0x2004, 0xd0fc, 0x1148, 0x2001, 0x9252,
+	0x2004, 0xa00e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x04f0, 0x2001,
+	0x9271, 0x200c, 0xa184, 0x000f, 0x2009, 0x9272, 0x210c, 0x0002,
+	0x478e, 0x47b0, 0x47b7, 0x47c1, 0x47c6, 0x478e, 0x478e, 0x478e,
+	0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e, 0x478e,
+	0x708f, 0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f,
+	0x0002, 0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001,
+	0x0088, 0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121,
+	0x2001, 0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00,
+	0x8007, 0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005,
+	0x00e6, 0x2071, 0x9328, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085,
+	0x702a, 0xa085, 0x0001, 0x0418, 0x6a60, 0x7236, 0x6b64, 0x733a,
+	0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e,
+	0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x8007, 0x8006, 0x8006,
+	0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x726e,
+	0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006, 0x00ee,
+	0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904, 0x4861,
+	0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0x9200, 0xa016, 0x702c,
+	0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8, 0x702e,
+	0x70ac, 0xa200, 0x70ae, 0x00de, 0x2071, 0x9328, 0x701c, 0xa005,
+	0x1904, 0x4871, 0x20a9, 0x0032, 0x0f04, 0x486f, 0x0e04, 0x482c,
+	0x2071, 0x946e, 0x7200, 0x82ff, 0x05d0, 0x6934, 0xa186, 0x0103,
+	0x1904, 0x487f, 0x6948, 0x6844, 0xa105, 0x1538, 0x2009, 0x8020,
+	0x2200, 0x0002, 0x486f, 0x4846, 0x48e6, 0x48f3, 0x2071, 0x0000,
+	0x20a9, 0x0032, 0x0f04, 0x486f, 0x7018, 0xd084, 0x1dd8, 0x7122,
+	0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080,
+	0x2071, 0x9200, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000,
+	0x70ae, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844, 0xa086, 0x0100,
+	0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020, 0x0888, 0x2071,
+	0x9328, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000, 0x7012, 0x7018,
+	0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e, 0x0c10, 0xa18c,
+	0x00ff, 0xa186, 0x0013, 0x01e0, 0xa186, 0x001b, 0x01c8, 0xa186,
+	0x0023, 0x01e8, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118,
+	0xa18e, 0x001f, 0x19e0, 0x684c, 0xd0cc, 0x09c8, 0x6850, 0xa084,
+	0x00ff, 0xa086, 0x0001, 0x1998, 0x2009, 0x8021, 0x0804, 0x4840,
+	0x6848, 0xa005, 0x1960, 0x2009, 0x8022, 0x0804, 0x4840, 0x2071,
+	0x0000, 0x7018, 0xd084, 0x1918, 0x00e6, 0x2071, 0x9281, 0x7140,
+	0x00ee, 0x6838, 0xa102, 0x0a04, 0x486f, 0x684c, 0xa005, 0x1158,
+	0x00e6, 0x2071, 0x9281, 0x7004, 0x00ee, 0xd08c, 0x1904, 0x486f,
+	0x2001, 0x8024, 0x0040, 0x6848, 0xd084, 0x1118, 0x2001, 0x8023,
+	0x0010, 0x2001, 0x8027, 0x7022, 0x6840, 0x7026, 0x683c, 0x702a,
+	0x6850, 0x702e, 0x0026, 0x0036, 0x6b38, 0x2e10, 0xa290, 0x0072,
+	0x2d00, 0xa080, 0x0015, 0x200c, 0x2112, 0x8000, 0x200c, 0x8210,
+	0x8319, 0x1dd0, 0x003e, 0x002e, 0x0804, 0x4854, 0x7084, 0x8008,
+	0xa092, 0x001e, 0x1a04, 0x486f, 0x7186, 0xae90, 0x0003, 0xa210,
+	0x683c, 0x2012, 0x0080, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04,
+	0x486f, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012,
+	0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x4858, 0x718c,
+	0x7084, 0xa10a, 0x0a04, 0x4858, 0x2071, 0x0000, 0x7018, 0xd084,
+	0x1904, 0x4858, 0x2071, 0x946e, 0x7000, 0xa086, 0x0002, 0x1150,
+	0x080c, 0x4b12, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
+	0x0804, 0x4858, 0x080c, 0x4b3c, 0x2071, 0x0000, 0x701b, 0x0001,
+	0x2091, 0x4080, 0x0804, 0x4858, 0x0006, 0x6837, 0x0103, 0x20a9,
+	0x001c, 0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x000e,
+	0x684a, 0x6952, 0x0005, 0x2071, 0x9328, 0x7004, 0x0002, 0x4948,
+	0x4958, 0x4afd, 0x4afe, 0x4b0b, 0x4b11, 0x4949, 0x4aee, 0x4a9a,
+	0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4956, 0x2009, 0x000d,
+	0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e, 0x0005,
+	0x2069, 0x94f8, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126, 0x2091,
+	0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0x9334, 0x2004, 0xa10a,
+	0x0170, 0x0e04, 0x497c, 0x2069, 0x0000, 0x6818, 0xd084, 0x1158,
+	0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x2069,
+	0x94f8, 0x683f, 0xffff, 0x012e, 0x2069, 0x9200, 0x6844, 0x6964,
+	0xa102, 0x2069, 0x946e, 0x688a, 0x6984, 0x701c, 0xa06d, 0x0120,
+	0x81ff, 0x0904, 0x49d1, 0x00a0, 0x81ff, 0x0904, 0x4a6f, 0x2071,
+	0x946e, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071, 0x94f8,
+	0x7038, 0xa005, 0x0128, 0x1b04, 0x4a6f, 0x713a, 0x0804, 0x4a6f,
+	0x2071, 0x946e, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084, 0xa10a,
+	0x0a04, 0x4a70, 0x0e04, 0x4a2d, 0x2071, 0x0000, 0x7018, 0xd084,
+	0x1904, 0x4a2d, 0x2001, 0xffff, 0x2071, 0x94f8, 0x703a, 0x2071,
+	0x946e, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x4b12, 0x2071,
+	0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x4a2d, 0x080c,
+	0x4b3c, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804,
+	0x4a2d, 0x2071, 0x946e, 0x7000, 0xa005, 0x0904, 0x4a51, 0x6934,
+	0xa186, 0x0103, 0x1904, 0x4a30, 0x6948, 0x6844, 0xa105, 0x1904,
+	0x4a47, 0x2071, 0x946e, 0x7000, 0x0002, 0x4a51, 0x4a11, 0x49e9,
+	0x49fb, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x4a6f, 0xae90,
+	0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0x9328, 0x080c,
+	0x4b95, 0x0804, 0x4a6f, 0x7084, 0x8008, 0xa092, 0x000f, 0x1a04,
+	0x4a6f, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210,
+	0x6840, 0x2012, 0x7186, 0x2071, 0x9328, 0x080c, 0x4b95, 0x0804,
+	0x4a6f, 0x2009, 0x8020, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4a2d,
+	0x2071, 0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026,
+	0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071,
+	0x9328, 0x080c, 0x4b95, 0x0804, 0x4a6f, 0x012e, 0x0804, 0x4a6f,
+	0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118,
+	0xa18e, 0x001f, 0x11b0, 0x684c, 0xd0cc, 0x0198, 0x6850, 0xa084,
+	0x00ff, 0xa086, 0x0001, 0x1168, 0x2009, 0x8021, 0x0860, 0x6844,
+	0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020,
+	0x0810, 0x2071, 0x9328, 0x080c, 0x4ba7, 0x01c8, 0x2071, 0x9328,
+	0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003, 0x1130,
+	0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007, 0x0003,
+	0x080c, 0x4bc0, 0x7050, 0xa086, 0x0100, 0x0904, 0x4afe, 0x0005,
+	0x2071, 0x9328, 0x080c, 0x4ba7, 0x0518, 0x2071, 0x946e, 0x7084,
+	0x700a, 0x20a9, 0x0020, 0x2099, 0x946f, 0x20a1, 0x9496, 0x53a3,
+	0x7087, 0x0000, 0x2071, 0x9328, 0x2069, 0x94b6, 0x706c, 0x6826,
+	0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x080c,
+	0x14c7, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0x94f8, 0x703a,
+	0x012e, 0x08a8, 0x2069, 0x94b6, 0x6808, 0xa08e, 0x0000, 0x0904,
+	0x4aed, 0xa08e, 0x0200, 0x0904, 0x4aeb, 0xa08e, 0x0100, 0x1904,
+	0x4aed, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4ae9, 0x2069, 0x0000,
+	0x6818, 0xd084, 0x15b0, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230,
+	0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080,
+	0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132,
+	0x6936, 0x2001, 0x9493, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069,
+	0x946e, 0x689c, 0x699e, 0x2069, 0x94f8, 0xa102, 0x1118, 0x683c,
+	0xa005, 0x1368, 0x2001, 0x9494, 0x200c, 0x810d, 0x693e, 0x0038,
+	0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007,
+	0x0001, 0x012e, 0x0010, 0x7007, 0x0005, 0x0005, 0x701c, 0xa06d,
+	0x0158, 0x080c, 0x4ba7, 0x0140, 0x7007, 0x0003, 0x080c, 0x4bc0,
+	0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005, 0x7050, 0xa09e,
+	0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086, 0x0200, 0x1110,
+	0x7007, 0x0005, 0x0005, 0x080c, 0x4b61, 0x7006, 0x080c, 0x4b95,
+	0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0x946e, 0x7184, 0x81ff,
+	0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071, 0x0000, 0x21a8,
+	0x2014, 0x7226, 0x8000, 0x0f04, 0x4b36, 0x2014, 0x722a, 0x8000,
+	0x0f04, 0x4b36, 0x2014, 0x722e, 0x8000, 0x0f04, 0x4b36, 0x2014,
+	0x723a, 0x8000, 0x0f04, 0x4b36, 0x2014, 0x723e, 0xa180, 0x8030,
+	0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156, 0x2071, 0x946e,
+	0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071,
+	0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014, 0x722a, 0x8000,
+	0x0f04, 0x4b58, 0x2014, 0x723a, 0x8000, 0x2014, 0x723e, 0x0018,
+	0x2001, 0x8020, 0x0010, 0xa180, 0x8042, 0x7022, 0x015e, 0x00ee,
+	0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
+	0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e,
+	0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001,
+	0x700e, 0x11a0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x4b91, 0x2001,
+	0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x012e, 0x0005,
+	0x2001, 0x000d, 0x2102, 0x2001, 0x0001, 0x0005, 0x2001, 0x0007,
+	0x0005, 0x2001, 0x0006, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170,
+	0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e,
+	0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1493, 0x0005, 0x2019,
+	0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e,
+	0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118,
+	0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005,
+	0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126,
+	0x2091, 0x8000, 0x2009, 0x9508, 0x2104, 0xc08d, 0x200a, 0x012e,
+	0x080c, 0x14df, 0x0005, 0x7088, 0xa08a, 0x0027, 0x1220, 0xa082,
+	0x001d, 0x0033, 0x0010, 0x080c, 0x13fe, 0x6027, 0x1e00, 0x0005,
+	0x4c57, 0x4be9, 0x4bff, 0x4c27, 0x4c4a, 0x4c7c, 0x4c8e, 0x4bff,
+	0x4c68, 0x6803, 0x0010, 0x6124, 0xd1e4, 0x1180, 0x080c, 0x4cd7,
+	0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1cc, 0x0140, 0x708b, 0x0020,
+	0x0028, 0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, 0x6803,
+	0x0008, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198,
+	0xa184, 0x1e00, 0x11d8, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e,
+	0x080c, 0x4df5, 0x6803, 0x0000, 0x708b, 0x0026, 0x2001, 0x9225,
+	0x2003, 0x0000, 0x0058, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d,
+	0x0028, 0x708b, 0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x60e3,
+	0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x4df5, 0x6803, 0x0000,
+	0x6124, 0xd1d4, 0x11a0, 0xd1dc, 0x1178, 0xd1e4, 0x1150, 0xa184,
+	0x1e00, 0x1178, 0x708b, 0x0026, 0x2001, 0x9225, 0x2003, 0x0000,
+	0x0040, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d, 0x0010, 0x708b,
+	0x001f, 0x0005, 0x6803, 0x0020, 0x6124, 0xd1dc, 0x1128, 0xd1e4,
+	0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001d, 0x0005, 0x080c,
+	0x4d03, 0x6124, 0xd1dc, 0x1158, 0x080c, 0x4cd7, 0xd1d4, 0x1128,
+	0xd1e4, 0x0128, 0x708b, 0x001e, 0x0010, 0x708b, 0x001f, 0x0005,
+	0x6803, 0x0020, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc,
+	0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028, 0x708b, 0x001d,
+	0x0010, 0x708b, 0x0021, 0x0005, 0x080c, 0x4d03, 0x6124, 0xd1d4,
+	0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x708b, 0x001e, 0x0028,
+	0x708b, 0x001d, 0x0010, 0x708b, 0x001f, 0x0005, 0x6803, 0x0010,
+	0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4,
+	0x0158, 0x708b, 0x001e, 0x0040, 0x708b, 0x001d, 0x0028, 0x708b,
+	0x0020, 0x0010, 0x708b, 0x001f, 0x0005, 0x00c6, 0x00d6, 0x00e6,
+	0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x9200, 0x2091,
+	0x8000, 0x080c, 0x4de1, 0x0150, 0x080c, 0x4dd7, 0x1138, 0x2001,
+	0x0001, 0x080c, 0x23ba, 0x080c, 0x4d9a, 0x00a0, 0x080c, 0x4d00,
+	0x0178, 0x2001, 0x0001, 0x080c, 0x23ba, 0x7088, 0xa086, 0x001e,
+	0x0120, 0x7088, 0xa086, 0x0022, 0x1118, 0x708b, 0x0025, 0x0010,
+	0x708b, 0x0021, 0x012e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0016,
+	0x0026, 0x2009, 0x0064, 0x2011, 0x4ce2, 0x080c, 0x57b3, 0x002e,
+	0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016, 0x080c, 0x6f1e, 0x2071,
+	0x9200, 0x080c, 0x4ca5, 0x001e, 0x00fe, 0x00ee, 0x0005, 0x0026,
+	0x00e6, 0x2011, 0x4ce2, 0x2071, 0x94f8, 0x701c, 0xa206, 0x1118,
+	0x7018, 0xa005, 0x0110, 0xa085, 0x0001, 0x00ee, 0x002e, 0x0005,
+	0x6020, 0xd09c, 0x0005, 0x6803, 0x0040, 0x0156, 0x20a9, 0x002d,
+	0x1d04, 0x4d08, 0x2091, 0x6000, 0x1f04, 0x4d08, 0x015e, 0x0005,
+	0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071,
+	0x9200, 0x2001, 0x94d8, 0x200c, 0xa186, 0x0000, 0x0158, 0xa186,
+	0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003, 0x0158,
+	0x0804, 0x4d88, 0x708b, 0x0022, 0x0048, 0x708b, 0x0021, 0x0030,
+	0x708b, 0x0023, 0x0038, 0x708b, 0x0024, 0x0020, 0xa085, 0x0001,
+	0x080c, 0x4e05, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001,
+	0x080c, 0x2460, 0x0026, 0x2011, 0x0003, 0x080c, 0x718f, 0x002e,
+	0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028, 0x0010, 0x602b,
+	0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9, 0x0005, 0x6024,
+	0xd0ac, 0x0118, 0x012e, 0x015e, 0x04c8, 0x6803, 0x0080, 0x6803,
+	0x0000, 0x6904, 0xd1d4, 0x1130, 0x6803, 0x0100, 0x1f04, 0x4d57,
+	0x080c, 0x4e12, 0x012e, 0x015e, 0x080c, 0x4dd7, 0x01a8, 0x6044,
+	0xa005, 0x0168, 0x6050, 0x0006, 0xa085, 0x0020, 0x6052, 0x080c,
+	0x4e12, 0xa006, 0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804,
+	0xd0d4, 0x1110, 0x080c, 0x4e12, 0x2001, 0x94d8, 0x2003, 0x0004,
+	0x080c, 0x4bd3, 0x080c, 0x4dd7, 0x0148, 0x6804, 0xd0d4, 0x1130,
+	0xd0dc, 0x1100, 0x2001, 0x94d8, 0x2003, 0x0000, 0x00ee, 0x00de,
+	0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069,
+	0x0140, 0x2071, 0x9200, 0x2001, 0x94d7, 0x2003, 0x0000, 0x2001,
+	0x94c8, 0x2003, 0x0000, 0x708b, 0x0000, 0x60e3, 0x0000, 0x6887,
+	0x0000, 0x2001, 0x0000, 0x080c, 0x2460, 0x6803, 0x0000, 0x6043,
+	0x0090, 0x6027, 0xffff, 0x602b, 0x002f, 0x2001, 0x9225, 0x2003,
+	0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001, 0x94d7,
+	0x2004, 0xa086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x2001, 0x9271,
+	0x2004, 0xa084, 0x0030, 0xa086, 0x0000, 0x000e, 0x0005, 0x0006,
+	0x2001, 0x9271, 0x2004, 0xa084, 0x0030, 0xa086, 0x0030, 0x000e,
+	0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xa084, 0x0030, 0xa086,
+	0x0010, 0x000e, 0x0005, 0x0006, 0x2001, 0x9271, 0x2004, 0xa084,
+	0x0030, 0xa086, 0x0020, 0x000e, 0x0005, 0x2001, 0x920c, 0x2004,
+	0xd0a4, 0x0150, 0x080c, 0x2480, 0x0036, 0x2019, 0x0028, 0x080c,
+	0x264b, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0x920c,
+	0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072,
+	0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006,
+	0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100,
+	0x602f, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x000e, 0x602a,
+	0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2,
+	0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x2460,
+	0x6803, 0x0080, 0x6803, 0x0000, 0x6803, 0x0020, 0x000e, 0x6052,
+	0x6050, 0x0005, 0x2071, 0x92f6, 0x7003, 0x0000, 0x7007, 0x0000,
+	0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053, 0x0001,
+	0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b, 0x0000,
+	0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6, 0x2071, 0x92f6,
+	0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a, 0xa085, 0x0001,
+	0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858, 0x703e, 0x707a,
+	0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840, 0x7032, 0x2009,
+	0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c, 0x003f, 0xa084,
+	0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376, 0x7028, 0xc084,
+	0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee, 0x0005,
+	0x2b78, 0x2071, 0x92f6, 0x7004, 0x0043, 0x700c, 0x0002, 0x4e9c,
+	0x4e93, 0x4e93, 0x4e93, 0x4e93, 0x0005, 0x4ef2, 0x4ef3, 0x4f25,
+	0x4f26, 0x4ef0, 0x4f5a, 0x4f5f, 0x4f90, 0x4f91, 0x4fac, 0x4fad,
+	0x4fae, 0x4faf, 0x4fb0, 0x4fb1, 0x502d, 0x5054, 0x700c, 0x0002,
+	0x4eb5, 0x4ef0, 0x4ef0, 0x4ef1, 0x4ef1, 0x7830, 0x7930, 0xa106,
+	0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030, 0xa10a, 0x01f8,
+	0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0, 0x080c, 0x145f,
+	0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001, 0x0003, 0x7057,
+	0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009, 0x9508, 0x2104,
+	0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c, 0x14df, 0x0005,
+	0x080c, 0x145f, 0x0de0, 0x2d00, 0x705a, 0x080c, 0x145f, 0x1108,
+	0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x08f8,
+	0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x4efa, 0x4efd, 0x4f0b,
+	0x4f24, 0x4f24, 0x080c, 0x4eae, 0x0005, 0x0126, 0x8001, 0x700e,
+	0x7058, 0x0006, 0x080c, 0x5311, 0x0120, 0x2091, 0x8000, 0x080c,
+	0x4eae, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x5311,
+	0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000,
+	0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020, 0x1218, 0x00db, 0x012e,
+	0x0005, 0x012e, 0x080c, 0x4fb2, 0x0005, 0x0005, 0x0005, 0x00e6,
+	0x2071, 0x92f6, 0x700c, 0x0002, 0x4f31, 0x4f31, 0x4f31, 0x4f33,
+	0x4f36, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010, 0x700f, 0x0002,
+	0x00ee, 0x0005, 0x4fb2, 0x4fb2, 0x4fce, 0x4fb2, 0x50e0, 0x4fb2,
+	0x4fb2, 0x4fb2, 0x4fb2, 0x4fb2, 0x4fce, 0x5119, 0x515c, 0x51a5,
+	0x51b9, 0x4fb2, 0x4fb2, 0x4fea, 0x4fce, 0x4ffe, 0x4fb2, 0x5013,
+	0x5243, 0x525e, 0x4fb2, 0x4fea, 0x4fb2, 0x4ffe, 0x4fb2, 0x4fb2,
+	0x5013, 0x525e, 0x7020, 0x2068, 0x080c, 0x1493, 0x0005, 0x700c,
+	0x0002, 0x4f66, 0x4f69, 0x4f77, 0x4f8f, 0x4f8f, 0x080c, 0x4eae,
+	0x0005, 0x0126, 0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x5311,
+	0x0120, 0x2091, 0x8000, 0x080c, 0x4eae, 0x00de, 0x0048, 0x0126,
+	0x8001, 0x700e, 0x080c, 0x5311, 0x7058, 0x2068, 0x7084, 0x705a,
+	0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a,
+	0x001a, 0x1218, 0x003b, 0x012e, 0x0005, 0x012e, 0x0419, 0x0005,
+	0x0005, 0x0005, 0x4fb2, 0x4fce, 0x50cc, 0x4fb2, 0x4fce, 0x4fb2,
+	0x4fce, 0x4fce, 0x4fb2, 0x4fce, 0x50cc, 0x4fce, 0x4fce, 0x4fce,
+	0x4fce, 0x4fce, 0x4fb2, 0x4fce, 0x50cc, 0x4fb2, 0x4fb2, 0x4fce,
+	0x4fb2, 0x4fb2, 0x4fb2, 0x4fce, 0x0005, 0x0005, 0x0005, 0x0005,
+	0x0005, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5,
+	0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005,
+	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0e5, 0x683a, 0x0126,
+	0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, 0x7007, 0x0001,
+	0x6838, 0xa084, 0x00ff, 0xc0ed, 0x683a, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x4809, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084,
+	0x00ff, 0xc0dd, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x4809,
+	0x012e, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0988, 0x8001,
+	0x1120, 0x7007, 0x0001, 0x0804, 0x508d, 0x7007, 0x0006, 0x7012,
+	0x2d00, 0x7016, 0x701a, 0x704b, 0x508d, 0x0005, 0x6834, 0x8007,
+	0xa084, 0x00ff, 0x0904, 0x4fc0, 0x8001, 0x1120, 0x7007, 0x0001,
+	0x0804, 0x50ac, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
+	0x704b, 0x50ac, 0x0005, 0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004,
+	0xa080, 0x0024, 0x2098, 0x20a1, 0x9321, 0x53a3, 0x6858, 0x7012,
+	0xa082, 0x0401, 0x1a04, 0x4fdc, 0x6884, 0xa08a, 0x0003, 0x1a04,
+	0x4fdc, 0xa080, 0x507e, 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904,
+	0x5072, 0x080c, 0x145f, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00,
+	0x7022, 0x70c4, 0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096,
+	0xe008, 0xa20a, 0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003,
+	0x800b, 0xa296, 0x0004, 0x0108, 0xa108, 0x719a, 0x810b, 0x719e,
+	0xae90, 0x0022, 0x080c, 0x14c7, 0x7090, 0xa08e, 0x0100, 0x0170,
+	0xa086, 0x0200, 0x0118, 0x7007, 0x0010, 0x0005, 0x7020, 0x2068,
+	0x080c, 0x1493, 0x7014, 0x2068, 0x0804, 0x4fdc, 0x7020, 0x2068,
+	0x7018, 0x6802, 0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a,
+	0x0804, 0x502d, 0x7014, 0x2068, 0x7007, 0x0001, 0x6834, 0xa084,
+	0x00ff, 0xa086, 0x001e, 0x0904, 0x5276, 0x0078, 0x5081, 0x5085,
+	0x5089, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f, 0x0005,
+	0x0006, 0x0012, 0x000f, 0x0005, 0x0006, 0x2009, 0x922f, 0x210c,
+	0x81ff, 0x11a8, 0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000,
+	0x080c, 0x423e, 0x1108, 0x0005, 0x080c, 0x492c, 0x0126, 0x2091,
+	0x8000, 0x080c, 0x8527, 0x080c, 0x4809, 0x012e, 0x0ca0, 0x2001,
+	0x0028, 0x2009, 0x0000, 0x0c80, 0x2009, 0x922f, 0x210c, 0x81ff,
+	0x11a8, 0x6858, 0xa005, 0x01a8, 0x6838, 0xa084, 0x00ff, 0x683a,
+	0x6853, 0x0000, 0x080c, 0x42db, 0x1108, 0x0005, 0x684a, 0x0126,
+	0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0cb8, 0x2001, 0x0028,
+	0x0ca8, 0x2001, 0x0000, 0x0c90, 0x7018, 0x6802, 0x2d08, 0x2068,
+	0x6906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006,
+	0x0030, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005,
+	0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084,
+	0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000,
+	0x20a9, 0x007e, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f8, 0x6944,
+	0x810f, 0xa18c, 0x00ff, 0x080c, 0x4434, 0x11c0, 0x0066, 0x6e50,
+	0x080c, 0x450d, 0x006e, 0x0090, 0x0046, 0x2011, 0x920c, 0x2224,
+	0xc484, 0xc48c, 0x2412, 0x004e, 0x00c6, 0x080c, 0x4434, 0x1110,
+	0x080c, 0x4664, 0x8108, 0x1f04, 0x510d, 0x00ce, 0x080c, 0x1493,
+	0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0x9252,
+	0x2004, 0xd0a4, 0x0580, 0x2061, 0x9566, 0x6100, 0xd184, 0x0178,
+	0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004,
+	0xa005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011,
+	0x0001, 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016,
+	0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084,
+	0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202,
+	0x012e, 0x0804, 0x5300, 0x012e, 0x0804, 0x52fa, 0x012e, 0x0804,
+	0x52f4, 0x012e, 0x0804, 0x52f7, 0x0126, 0x2091, 0x8000, 0x7007,
+	0x0001, 0x2001, 0x9252, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0x9566,
+	0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48,
+	0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120,
+	0x2100, 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212,
+	0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff,
+	0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082,
+	0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110,
+	0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x5300, 0x012e,
+	0x0804, 0x52fd, 0x012e, 0x0804, 0x52fa, 0x0126, 0x2091, 0x8000,
+	0x7007, 0x0001, 0x2061, 0x9566, 0x6300, 0xd38c, 0x1120, 0x6308,
+	0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x530e, 0x012e, 0x0804,
+	0x52fd, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c,
+	0xd0ac, 0x0148, 0x00c6, 0x2061, 0x9566, 0x6000, 0xa084, 0xfcff,
+	0x6002, 0x00ce, 0x04d8, 0x6858, 0xa005, 0x0904, 0x521a, 0x685c,
+	0xa065, 0x0904, 0x5216, 0x2001, 0x922f, 0x2004, 0xa005, 0x0118,
+	0x080c, 0x849b, 0x0030, 0x6013, 0x0400, 0x2009, 0x0041, 0x080c,
+	0x7518, 0x6958, 0xa18c, 0xf600, 0xa186, 0x2000, 0x01b8, 0xa186,
+	0x0400, 0x01a0, 0xa186, 0x1000, 0x0140, 0xa186, 0x4000, 0x01b0,
+	0x6118, 0x2104, 0xc0fc, 0x200a, 0x0088, 0x00c6, 0x2061, 0x9566,
+	0x6000, 0xa084, 0xfdff, 0x6002, 0x00ce, 0x0040, 0x0026, 0x2009,
+	0x0000, 0x2011, 0xfdff, 0x080c, 0x585b, 0x002e, 0x684c, 0xd0c4,
+	0x0148, 0x2061, 0x9566, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000,
+	0x0208, 0x600a, 0x00ce, 0x012e, 0x0804, 0x5300, 0x00ce, 0x012e,
+	0x0804, 0x52fa, 0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d,
+	0x0d28, 0xa186, 0x002a, 0x1130, 0x2001, 0x920c, 0x200c, 0xc194,
+	0x2102, 0x08e0, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029, 0x1d30,
+	0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4434, 0x1978, 0x6000,
+	0xc0e4, 0x6002, 0x0858, 0x685c, 0xa065, 0x09c0, 0x2001, 0x94dd,
+	0x2004, 0x6016, 0x0818, 0x2061, 0x9566, 0x6000, 0xd084, 0x0190,
+	0xd08c, 0x1904, 0x530e, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210,
+	0x0220, 0x6206, 0x012e, 0x0804, 0x530e, 0x012e, 0x6853, 0x0016,
+	0x0804, 0x5307, 0x6853, 0x0007, 0x0804, 0x5307, 0x6834, 0x8007,
+	0xa084, 0x00ff, 0x1118, 0x080c, 0x4fc0, 0x0078, 0x2030, 0x8001,
+	0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007, 0x0006, 0x7012,
+	0x2d00, 0x7016, 0x701a, 0x704b, 0x5276, 0x0005, 0x00e6, 0x0126,
+	0x2091, 0x8000, 0x2009, 0x922f, 0x210c, 0x81ff, 0x1904, 0x52e9,
+	0x2009, 0x920c, 0x210c, 0xd194, 0x1904, 0x52f1, 0x6848, 0x2070,
+	0xae82, 0x9900, 0x0a04, 0x52dd, 0x2001, 0x9216, 0x2004, 0xae02,
+	0x1a04, 0x52dd, 0x2061, 0x9566, 0x6100, 0xa184, 0x0001, 0x0578,
+	0xa184, 0x0100, 0x1904, 0x52e0, 0xa184, 0x0200, 0x1904, 0x52e3,
+	0x601c, 0xa005, 0x1904, 0x52e6, 0x711c, 0xa186, 0x0006, 0x1520,
+	0x7018, 0xa005, 0x05f0, 0x2004, 0xd0e4, 0x15f0, 0xd0fc, 0x1598,
+	0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1138,
+	0x7112, 0x2e60, 0x080c, 0x57ca, 0x012e, 0x00ee, 0x0005, 0x2068,
+	0x6800, 0xa005, 0x1de0, 0x6902, 0x012e, 0x00ee, 0x0005, 0x012e,
+	0x00ee, 0x6853, 0x0006, 0x04d8, 0x6944, 0xa18c, 0xff00, 0x810f,
+	0x080c, 0x4434, 0x11c8, 0x6000, 0xd0e4, 0x11b0, 0x711c, 0xa186,
+	0x0007, 0x1118, 0x6853, 0x0002, 0x0088, 0x6853, 0x0008, 0x0070,
+	0x6853, 0x000e, 0x0058, 0x6853, 0x0017, 0x0040, 0x6853, 0x0035,
+	0x0028, 0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee,
+	0x00b0, 0x6853, 0x002a, 0x0cd0, 0x2009, 0x003e, 0x0058, 0x2009,
+	0x0004, 0x0040, 0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010,
+	0x2009, 0x0001, 0x6854, 0xa084, 0xff00, 0xa105, 0x6856, 0x0126,
+	0x2091, 0x8000, 0x080c, 0x4809, 0x012e, 0x0005, 0x080c, 0x1493,
+	0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034,
+	0x7072, 0x7038, 0x7076, 0x0058, 0x7070, 0xa080, 0x0040, 0x7072,
+	0x1230, 0x7074, 0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932,
+	0x7132, 0x0005, 0x00d6, 0x080c, 0x57c1, 0x00de, 0x0005, 0x00d6,
+	0x2011, 0x0004, 0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005,
+	0x20e1, 0x0002, 0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000,
+	0x0118, 0xa086, 0x1000, 0x1520, 0x20e1, 0x0004, 0x3d60, 0xd1bc,
+	0x1170, 0x2100, 0xa084, 0xff00, 0xa086, 0x0500, 0x1140, 0x0026,
+	0x2c10, 0x080c, 0x566e, 0x002e, 0x0198, 0x0070, 0x3e60, 0xac84,
+	0x0003, 0x1170, 0xac82, 0x9900, 0x0258, 0x6858, 0xac02, 0x1240,
+	0x2009, 0x0047, 0x080c, 0x7518, 0x7a1c, 0xd284, 0x1988, 0x0005,
+	0xa016, 0x080c, 0x16c6, 0x0cc0, 0x0156, 0x0136, 0x0146, 0x20e1,
+	0x3000, 0x3d20, 0x3e28, 0xa584, 0x0070, 0x1528, 0xa484, 0x7000,
+	0xa086, 0x1000, 0x11a0, 0x04a1, 0x01f0, 0x20e1, 0x3000, 0x7828,
+	0x7828, 0x080c, 0x53cc, 0x014e, 0x013e, 0x015e, 0x2009, 0x94ed,
+	0x2104, 0xa005, 0x1108, 0x0005, 0x080c, 0x6462, 0x0ce0, 0xa484,
+	0x7000, 0x1148, 0x00e9, 0x0190, 0x7000, 0xa084, 0xff00, 0xa086,
+	0x8100, 0x0d18, 0x0058, 0xd5a4, 0x0140, 0x080c, 0x1c26, 0x20e1,
+	0x9010, 0x2001, 0x0138, 0x2202, 0x0038, 0x0051, 0x080c, 0x9157,
+	0x20e1, 0x3000, 0x7828, 0x7828, 0x014e, 0x013e, 0x015e, 0x08d8,
+	0xa484, 0x01ff, 0x6882, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084,
+	0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
+	0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a,
+	0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c,
+	0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x5571, 0x0005,
+	0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c,
+	0x3a6a, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c,
+	0x55f9, 0x0c68, 0x00c6, 0x6a80, 0x82ff, 0x0904, 0x5506, 0x7110,
+	0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023,
+	0x1904, 0x5506, 0xa08e, 0x0023, 0x1558, 0x080c, 0x565c, 0x0904,
+	0x5506, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034,
+	0xa005, 0x1904, 0x5506, 0x2009, 0x0015, 0x080c, 0x7518, 0x0804,
+	0x5506, 0xa08e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0x7518,
+	0x0804, 0x5506, 0xa08e, 0x0100, 0x1904, 0x5506, 0x7034, 0xa005,
+	0x1904, 0x5506, 0x2009, 0x0016, 0x080c, 0x7518, 0x0804, 0x5506,
+	0xa08e, 0x0022, 0x1904, 0x5506, 0x7030, 0xa08e, 0x0300, 0x1568,
+	0x68c8, 0xd0a4, 0x0510, 0xc0b5, 0x68ca, 0x7100, 0xa18c, 0x00ff,
+	0x696e, 0x7004, 0x6872, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea,
+	0x0006, 0xa084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x2435, 0x7932,
+	0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x240b, 0x694e, 0x703c,
+	0x00e6, 0x2071, 0x0140, 0x7086, 0x00ee, 0x7034, 0xa005, 0x1904,
+	0x5506, 0x2009, 0x0017, 0x0804, 0x54d9, 0xa08e, 0x0400, 0x1158,
+	0x7034, 0xa005, 0x1904, 0x5506, 0x68c8, 0xc0a5, 0x68ca, 0x2009,
+	0x0030, 0x0804, 0x54d9, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005,
+	0x1904, 0x5506, 0x2009, 0x0018, 0x0804, 0x54d9, 0xa08e, 0x2010,
+	0x1120, 0x2009, 0x0019, 0x0804, 0x54d9, 0xa08e, 0x2110, 0x1120,
+	0x2009, 0x001a, 0x0804, 0x54d9, 0xa08e, 0x5200, 0x1140, 0x7034,
+	0xa005, 0x1904, 0x5506, 0x2009, 0x001b, 0x0804, 0x54d9, 0xa08e,
+	0x5000, 0x1140, 0x7034, 0xa005, 0x1904, 0x5506, 0x2009, 0x001c,
+	0x0804, 0x54d9, 0xa08e, 0x1200, 0x1138, 0x7034, 0xa005, 0x1904,
+	0x5506, 0x2009, 0x0024, 0x04a8, 0xa08c, 0xff00, 0xa18e, 0x2400,
+	0x1118, 0x2009, 0x002d, 0x0468, 0xa08c, 0xff00, 0xa18e, 0x5300,
+	0x1118, 0x2009, 0x002a, 0x0428, 0xa08e, 0x0f00, 0x1118, 0x2009,
+	0x0020, 0x00f8, 0xa08e, 0x5300, 0x1108, 0x00c8, 0xa08e, 0x6104,
+	0x11b0, 0x2011, 0x978d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8,
+	0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108, 0x2124, 0x080c,
+	0x3698, 0x8108, 0x1f04, 0x54ca, 0x2009, 0x0023, 0x0010, 0x2009,
+	0x001d, 0x0016, 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c,
+	0x240b, 0x1530, 0x080c, 0x4400, 0x1518, 0x6612, 0x6516, 0x86ff,
+	0x0180, 0x001e, 0x0016, 0xa186, 0x0017, 0x1158, 0x686c, 0xa606,
+	0x1140, 0x6870, 0xa506, 0xa084, 0xff00, 0x1118, 0x6000, 0xc0f5,
+	0x6002, 0x00c6, 0x080c, 0x749c, 0x0168, 0x001e, 0x611a, 0x601f,
+	0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x7518, 0x00ce, 0x0005,
+	0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00e6, 0x00d6, 0x2028, 0x2130,
+	0xa696, 0x00ff, 0x1518, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f,
+	0x0804, 0x556d, 0xa596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804,
+	0x556d, 0xa596, 0xfffc, 0x1120, 0x2009, 0x0080, 0x0804, 0x556d,
+	0xa594, 0xff00, 0xa296, 0xfc00, 0x1148, 0x2011, 0x0000, 0x2021,
+	0x0081, 0x20a9, 0x007e, 0x2071, 0x93ef, 0x00a0, 0x2011, 0x0000,
+	0x2019, 0x9232, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9,
+	0x00ff, 0x2071, 0x936e, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e,
+	0x2071, 0x93ef, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410,
+	0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e,
+	0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110,
+	0x83ff, 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x554a, 0x82ff, 0x1118,
+	0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee,
+	0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x557d, 0x557d, 0x557d,
+	0x557d, 0x557d, 0x557e, 0x5593, 0x55e6, 0x0005, 0x7110, 0xd1bc,
+	0x0188, 0x7120, 0x2160, 0xac8c, 0x0003, 0x1160, 0xac8a, 0x9900,
+	0x0248, 0x6858, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009, 0x0046,
+	0x080c, 0x7518, 0x0005, 0x00c6, 0x7110, 0xd1bc, 0x1904, 0x55e4,
+	0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, 0x240b, 0x1904,
+	0x55e4, 0x080c, 0x4434, 0x1904, 0x55e4, 0x6000, 0xd0ec, 0x15e0,
+	0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0160, 0x080c,
+	0x4dc5, 0x11d0, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006, 0x11a0,
+	0xa295, 0x0600, 0x6206, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0520,
+	0x611a, 0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6122, 0x2009,
+	0x0044, 0x080c, 0x7518, 0x00c0, 0x00c6, 0x080c, 0x749c, 0x001e,
+	0x0198, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0xa286, 0x0004,
+	0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001, 0x6003, 0x0001,
+	0x080c, 0x603e, 0x080c, 0x6462, 0x00ce, 0x0005, 0x7110, 0xd1bc,
+	0x0178, 0x7020, 0x2060, 0xac84, 0x0003, 0x1150, 0xac82, 0x9900,
+	0x0238, 0x6858, 0xac02, 0x1220, 0x2009, 0x0045, 0x080c, 0x7518,
+	0x0005, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x1138,
+	0xa084, 0x000f, 0xa08a, 0x0006, 0x1a0c, 0x13fe, 0x000b, 0x0005,
+	0x560e, 0x560f, 0x560e, 0x560e, 0x5644, 0x5650, 0x0005, 0x7110,
+	0xd1bc, 0x1588, 0x700c, 0x7108, 0x080c, 0x240b, 0x1560, 0x080c,
+	0x4400, 0x1548, 0x6612, 0x6516, 0x6204, 0xa294, 0xff00, 0x8217,
+	0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1178, 0x00c6, 0x080c,
+	0x749c, 0x001e, 0x01c0, 0x611a, 0x601f, 0x0005, 0x7120, 0x610a,
+	0x2009, 0x0088, 0x080c, 0x7518, 0x0070, 0x00c6, 0x080c, 0x749c,
+	0x001e, 0x0148, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x2009,
+	0x0001, 0x080c, 0x7518, 0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1,
+	0x0130, 0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0x7518, 0x0005,
+	0x7110, 0xd1bc, 0x0140, 0x0041, 0x0130, 0x7124, 0x610a, 0x2009,
+	0x008a, 0x080c, 0x7518, 0x0005, 0x7020, 0x2060, 0xac84, 0x0003,
+	0x1158, 0xac82, 0x9900, 0x0240, 0x2001, 0x9216, 0x2004, 0xac02,
+	0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x00c6, 0x00d6,
+	0x00e6, 0x20e1, 0x0000, 0x3d08, 0xa18c, 0x00ff, 0xa18e, 0x00ff,
+	0x1150, 0x3e00, 0xa086, 0xffff, 0x1130, 0x2001, 0x94c6, 0x2064,
+	0x2009, 0x00ff, 0x0060, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0x0156,
+	0x080c, 0x240b, 0x015e, 0x1578, 0x080c, 0x4434, 0x1560, 0x2138,
+	0x873f, 0x2c00, 0x2070, 0x20e1, 0x0003, 0x3d18, 0x831f, 0xa39c,
+	0x00ff, 0x0036, 0x0036, 0x003e, 0x003e, 0x20e1, 0x2000, 0x3d00,
+	0xa084, 0x7000, 0xa086, 0x1000, 0x0120, 0x080c, 0x5cc0, 0x1198,
+	0x0040, 0x080c, 0x749c, 0x0178, 0x2e00, 0x601a, 0x620a, 0x601f,
+	0x0009, 0x2009, 0x0101, 0x080c, 0x7518, 0xa085, 0x0001, 0x00ee,
+	0x00de, 0x00ce, 0x0005, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x0005,
+	0x2071, 0x94f8, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a,
+	0x7012, 0x7017, 0x9900, 0x7007, 0x0000, 0x7026, 0x702b, 0x6f2b,
+	0x7032, 0x7037, 0x6f69, 0x703b, 0xffff, 0x703f, 0xffff, 0x0005,
+	0x2071, 0x94f8, 0x1d04, 0x5720, 0x2091, 0x6000, 0x700c, 0x8001,
+	0x700e, 0x1120, 0x700f, 0x0361, 0x7007, 0x0001, 0x0126, 0x2091,
+	0x8000, 0x7024, 0xa00d, 0x0158, 0x7020, 0x8001, 0x7022, 0x1138,
+	0x7023, 0x0009, 0x8109, 0x7126, 0x1110, 0x7028, 0x080f, 0x7030,
+	0xa00d, 0x0158, 0x702c, 0x8001, 0x702e, 0x1138, 0x702f, 0x0009,
+	0x8109, 0x7132, 0x1110, 0x7034, 0x080f, 0x7038, 0xa005, 0x0118,
+	0x0310, 0x8001, 0x703a, 0x703c, 0xa005, 0x0118, 0x0310, 0x8001,
+	0x703e, 0x7018, 0xa00d, 0x0158, 0x7008, 0x8001, 0x700a, 0x1138,
+	0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c, 0x080f, 0x012e,
+	0x7004, 0x0002, 0x5746, 0x5747, 0x575f, 0x00e6, 0x2071, 0x94f8,
+	0x7018, 0xa005, 0x1120, 0x711a, 0x721e, 0x700b, 0x0009, 0x00ee,
+	0x0005, 0x00e6, 0x0006, 0x2071, 0x94f8, 0x701c, 0xa206, 0x1110,
+	0x701a, 0x701e, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x94f8,
+	0x6088, 0xa102, 0x0208, 0x618a, 0x00ee, 0x0005, 0x0005, 0x7110,
+	0x080c, 0x4434, 0x1158, 0x6088, 0x8001, 0x0240, 0x608a, 0x1130,
+	0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x8108, 0xa182,
+	0x00ff, 0x0218, 0xa00e, 0x7007, 0x0002, 0x7112, 0x0005, 0x7014,
+	0x2060, 0x0126, 0x2091, 0x8000, 0x6014, 0xa005, 0x0518, 0x8001,
+	0x6016, 0x1500, 0x611c, 0xa186, 0x0003, 0x0130, 0xa186, 0x0006,
+	0x0118, 0xa186, 0x0009, 0x11a0, 0x6010, 0x2068, 0x6854, 0xa08a,
+	0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0210,
+	0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0010,
+	0x080c, 0x8185, 0x012e, 0xac88, 0x000c, 0x7116, 0x2001, 0x9217,
+	0x2004, 0xa102, 0x0220, 0x7017, 0x9900, 0x7007, 0x0000, 0x0005,
+	0x00e6, 0x2071, 0x94f8, 0x7027, 0x07d0, 0x7023, 0x0009, 0x00ee,
+	0x0005, 0x2001, 0x9501, 0x2003, 0x0000, 0x0005, 0x00e6, 0x2071,
+	0x94f8, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011, 0x9504,
+	0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x94f8, 0x711a, 0x721e,
+	0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x2061, 0x9566, 0x00ce,
+	0x0005, 0xa184, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x9566,
+	0x2060, 0x0005, 0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
+	0xa005, 0x1150, 0x00c6, 0x2061, 0x9566, 0x6014, 0x00ce, 0xa005,
+	0x1138, 0x2001, 0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006,
+	0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0,
+	0xa18e, 0x00c0, 0x0588, 0xd0b4, 0x1138, 0xd0bc, 0x11f0, 0x2009,
+	0x0006, 0x080c, 0x5838, 0x0005, 0xd0fc, 0x0140, 0xa084, 0x0003,
+	0xa08e, 0x0003, 0x05b8, 0xa08e, 0x0000, 0x15a0, 0x2009, 0x9273,
+	0x2104, 0xd084, 0x0128, 0x2009, 0x0042, 0x080c, 0x7518, 0x0005,
+	0x2009, 0x0043, 0x080c, 0x7518, 0x0005, 0xd0fc, 0x0140, 0xa084,
+	0x0003, 0xa08e, 0x0003, 0x01f0, 0xa08e, 0x0000, 0x11d8, 0x2009,
+	0x0042, 0x080c, 0x7518, 0x0005, 0xd0fc, 0x0168, 0xa084, 0x0003,
+	0xa08e, 0x0003, 0x0178, 0xa08e, 0x0002, 0x0138, 0x2009, 0x0041,
+	0x080c, 0x7518, 0x0005, 0x0051, 0x0ce8, 0x2009, 0x0043, 0x080c,
+	0x7518, 0x0cc0, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001,
+	0x6010, 0xa0ec, 0xf000, 0x01f0, 0x2068, 0x6952, 0x6800, 0x6012,
+	0xa186, 0x0001, 0x1188, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100,
+	0x1158, 0x00c6, 0x2061, 0x9566, 0x6200, 0xd28c, 0x1120, 0x6204,
+	0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x4809, 0x6010, 0xa06d,
+	0x190c, 0x57ca, 0x0005, 0x0156, 0x00c6, 0x2061, 0x9566, 0x6000,
+	0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce, 0x015e,
+	0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120, 0x8001,
+	0x680a, 0xa085, 0x0001, 0x0005, 0x2071, 0x9349, 0x7003, 0x0006,
+	0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x702f, 0x0006,
+	0x7033, 0x0001, 0x7063, 0x0000, 0x0005, 0x00e6, 0x2071, 0x9349,
+	0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0x705a, 0x6838,
+	0x702a, 0x705e, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009, 0x0070,
+	0x200a, 0xa005, 0x0150, 0x2009, 0x0000, 0xa188, 0x000c, 0x8001,
+	0x1de0, 0x2100, 0xa210, 0x1208, 0x8318, 0x7252, 0x7356, 0x7010,
+	0xc084, 0x7012, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006, 0x00ee,
+	0x0005, 0x2b78, 0x2071, 0x9349, 0x7004, 0x004b, 0x700c, 0x0002,
+	0x58bb, 0x58b4, 0x58b4, 0x0005, 0x58c5, 0x5913, 0x5914, 0x5915,
+	0x5916, 0x5929, 0x592a, 0x700c, 0x0cba, 0x2f00, 0xa080, 0x0070,
+	0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106, 0x0150, 0x2f00,
+	0xa080, 0x0070, 0x2004, 0x2f08, 0xa188, 0x0070, 0x210c, 0xa106,
+	0x15c8, 0x7018, 0xa10a, 0x05b0, 0x1210, 0x7114, 0xa10a, 0xa192,
+	0x000a, 0x0210, 0x2009, 0x000a, 0x00d6, 0x0016, 0x2001, 0x9281,
+	0xa080, 0x0011, 0x2014, 0x2001, 0x9363, 0xa080, 0x0005, 0x2004,
+	0xa100, 0xa202, 0x001e, 0x00de, 0x02e8, 0x080c, 0x5976, 0x2200,
+	0xa102, 0x0208, 0x2208, 0x713a, 0x080c, 0x5a67, 0x2100, 0x7042,
+	0x2001, 0x0002, 0x7037, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000,
+	0x2009, 0x9508, 0x2104, 0xc095, 0x200a, 0x000e, 0x700e, 0x012e,
+	0x080c, 0x14df, 0x0005, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002,
+	0x591b, 0x591e, 0x5928, 0x080c, 0x58c3, 0x0005, 0x0126, 0x8001,
+	0x700e, 0x7138, 0x0041, 0x2091, 0x8000, 0x080c, 0x58c3, 0x012e,
+	0x0005, 0x0005, 0x0005, 0x7018, 0xa100, 0x7214, 0xa21a, 0x1130,
+	0x701c, 0x7052, 0x7020, 0x7056, 0xa006, 0x0068, 0x0006, 0x080c,
+	0x5a67, 0x2100, 0x7250, 0xa210, 0x7252, 0x1220, 0x7054, 0xa081,
+	0x0000, 0x7056, 0x000e, 0x2f08, 0xa188, 0x0070, 0x200a, 0x701a,
+	0x0005, 0x00e6, 0x2071, 0x9349, 0x700c, 0x0002, 0x5951, 0x5951,
+	0x5953, 0x00ee, 0x0005, 0x700f, 0x0001, 0x00ee, 0x0005, 0x00d6,
+	0x00e6, 0x2071, 0x9363, 0xa006, 0x7006, 0x700e, 0x701a, 0x701e,
+	0x7022, 0x702a, 0x7026, 0x080c, 0x5b1b, 0x0170, 0x080c, 0x5b4d,
+	0x0158, 0x2d00, 0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f,
+	0x0007, 0x00ee, 0x00de, 0x0005, 0xa00e, 0x0cd8, 0x00e6, 0x00d6,
+	0x00c6, 0x2071, 0x9363, 0x721c, 0x2100, 0xa202, 0x1618, 0x080c,
+	0x5b4d, 0x090c, 0x13fe, 0x7018, 0xa005, 0x1160, 0x2d00, 0x7002,
+	0x700a, 0x701a, 0xa006, 0x7006, 0x700e, 0x6806, 0x6802, 0x7012,
+	0x701e, 0x0038, 0x2060, 0x6806, 0x2d00, 0x6002, 0x701a, 0x6803,
+	0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0xa080, 0x0007, 0x701e,
+	0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x0156,
+	0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x9363,
+	0x7300, 0xa398, 0x0003, 0x7104, 0x080c, 0x5a67, 0x810c, 0x2100,
+	0xa318, 0x8003, 0x2228, 0x2021, 0x0054, 0xa402, 0xa532, 0x0208,
+	0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xe000, 0xe000, 0xe000,
+	0x53a5, 0x2508, 0x080c, 0x5a70, 0x2130, 0x7014, 0xa600, 0x7016,
+	0x2600, 0x711c, 0xa102, 0x701e, 0x7004, 0xa600, 0x2008, 0xa082,
+	0x0007, 0x1180, 0x7000, 0x2004, 0xa005, 0x1140, 0x2009, 0x0001,
+	0x0026, 0x080c, 0x5976, 0x002e, 0x7000, 0x2004, 0x7002, 0x7007,
+	0x0000, 0x0008, 0x7106, 0x2500, 0xa212, 0x1910, 0x012e, 0x00ee,
+	0x014e, 0x013e, 0x015e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x00d6,
+	0x04e9, 0x15c8, 0x2170, 0x2805, 0xac68, 0x2900, 0x0002, 0x5a0f,
+	0x5a0f, 0x5a13, 0x5a0f, 0x5a13, 0x5a0f, 0x5a0f, 0x5a0f, 0x5a0f,
+	0x5a0f, 0x5a1c, 0x5a0f, 0x5a1c, 0x5a0f, 0x5a0f, 0x5a0f, 0x080c,
+	0x13fe, 0xa005, 0x00d8, 0x7000, 0x6802, 0x7004, 0x6806, 0x7010,
+	0x680a, 0x680f, 0x0000, 0x0060, 0x7010, 0x6812, 0x6817, 0x0000,
+	0x7000, 0x6802, 0x7004, 0x6806, 0x7008, 0x680a, 0x700c, 0x680e,
+	0x00de, 0x685c, 0x8000, 0x685e, 0x00d6, 0xa006, 0x00de, 0x00ee,
+	0x002e, 0x001e, 0x0005, 0xa085, 0x0001, 0x0cc0, 0x00e6, 0x0036,
+	0x2071, 0x9363, 0x7014, 0xa005, 0x0538, 0x8001, 0x7016, 0x7008,
+	0xa080, 0x0003, 0x710c, 0x2110, 0x0411, 0x810c, 0xa118, 0x8210,
+	0xa282, 0x0007, 0x11b0, 0x7008, 0x2004, 0xa005, 0x0178, 0x00d6,
+	0x0006, 0x7008, 0x2068, 0x080c, 0x5b5c, 0x000e, 0x2068, 0x6807,
+	0x0000, 0x700a, 0x00de, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000,
+	0x0008, 0x720e, 0x2308, 0xa006, 0x003e, 0x00ee, 0x0005, 0x0006,
+	0x810b, 0x810b, 0x2100, 0x810b, 0xa100, 0x2008, 0x000e, 0x0005,
+	0x0006, 0x0026, 0x2100, 0xa005, 0x0160, 0xa092, 0x000c, 0x0248,
+	0x2009, 0x0000, 0x8108, 0xa082, 0x000c, 0x1de0, 0x002e, 0x000e,
+	0x0005, 0x2009, 0x0000, 0x0cd0, 0x2d00, 0xa0b8, 0x0008, 0x690c,
+	0x6810, 0x2019, 0x0001, 0x2031, 0x5ab2, 0xa112, 0x0220, 0x0118,
+	0x8318, 0x2208, 0x0cd0, 0x6808, 0xa005, 0x0108, 0x8318, 0x233a,
+	0x6804, 0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0xa082, 0x0003,
+	0x0967, 0x0a67, 0x8420, 0xa082, 0x0007, 0x0967, 0x0a67, 0x0cd0,
+	0xa082, 0x0002, 0x0967, 0x0a67, 0x8420, 0xa082, 0x0005, 0x0967,
+	0x0a67, 0x0cd0, 0x6c1a, 0x2d00, 0xa0b8, 0x0007, 0x00e6, 0x2071,
+	0x9200, 0x7128, 0x6810, 0x2019, 0x0001, 0xa10a, 0x0118, 0x0210,
+	0x8318, 0x0cd8, 0x2031, 0x5ac5, 0x0870, 0x6c16, 0x00ee, 0x0005,
+	0x00e6, 0x00c6, 0x0126, 0x2091, 0x8000, 0x2e00, 0x2060, 0x2071,
+	0x9363, 0x2009, 0x0001, 0x0026, 0x080c, 0x5976, 0x002e, 0x7300,
+	0xa398, 0x0003, 0x7104, 0x080c, 0x5a67, 0x810c, 0x2100, 0xa318,
+	0x6834, 0xa084, 0x00ff, 0xa086, 0x0024, 0x00d6, 0x2368, 0x1138,
+	0x6000, 0x6802, 0x6004, 0x6806, 0x6008, 0x6812, 0x0050, 0x6000,
+	0x6802, 0x6004, 0x6806, 0x6008, 0x680a, 0x600c, 0x680e, 0x6010,
+	0x6812, 0x00de, 0x7014, 0x8000, 0x7016, 0x711c, 0x8109, 0x711e,
+	0x7004, 0x8000, 0x2008, 0xa082, 0x0007, 0x1180, 0x7000, 0x2004,
+	0xa005, 0x1140, 0x2009, 0x0001, 0x0026, 0x080c, 0x5976, 0x002e,
+	0x7000, 0x2004, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x012e,
+	0x00ce, 0x00ee, 0x0005, 0x00d6, 0x0046, 0x0126, 0x2091, 0x8000,
+	0x2001, 0x9281, 0xa080, 0x0011, 0x2004, 0x8003, 0x2020, 0x080c,
+	0x145f, 0x01d0, 0x2d00, 0x7026, 0x6803, 0x0000, 0x6807, 0x0000,
+	0x080c, 0x145f, 0x0188, 0x7024, 0x6802, 0x6807, 0x0000, 0x2d00,
+	0x7026, 0xa4a2, 0x0007, 0x0110, 0x0208, 0x0c90, 0xa085, 0x0001,
+	0x012e, 0x004e, 0x00de, 0x0005, 0x7024, 0xa005, 0x0dc8, 0x2068,
+	0x2024, 0x080c, 0x1493, 0x2400, 0x0cc0, 0x0126, 0x2091, 0x8000,
+	0x7024, 0x2068, 0xa005, 0x0130, 0x2004, 0x7026, 0x6803, 0x0000,
+	0x6807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x7024,
+	0x6802, 0x2d00, 0x7026, 0x012e, 0x0005, 0x00f6, 0x00e6, 0x00d6,
+	0x00c6, 0x0086, 0x0046, 0x0056, 0x0026, 0x2031, 0x0000, 0x2001,
+	0x934a, 0x2004, 0xa005, 0x0904, 0x5bee, 0x2071, 0x9281, 0x20e1,
+	0x0002, 0x3d08, 0xd19c, 0x0140, 0x2069, 0x9200, 0x6a28, 0x761c,
+	0x7114, 0x2041, 0x0000, 0x0028, 0x7118, 0x720c, 0x7620, 0x7008,
+	0x2040, 0x080c, 0x5d03, 0x0904, 0x5bee, 0x7004, 0xd084, 0x1128,
+	0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029,
+	0x000a, 0x080c, 0x147c, 0x0904, 0x5bee, 0x2d00, 0x2060, 0x6436,
+	0x0016, 0x20e1, 0x0001, 0x3d08, 0x3e00, 0xa18c, 0x00ff, 0x6142,
+	0x603e, 0x001e, 0x6746, 0x2700, 0xa086, 0xff00, 0x1118, 0x6063,
+	0x0000, 0x0010, 0x6063, 0x0003, 0xa006, 0x6002, 0x602a, 0x602e,
+	0x6006, 0x603a, 0x604a, 0x6052, 0x6056, 0x605e, 0x6066, 0x604e,
+	0x2800, 0x606a, 0x604c, 0xc0ad, 0x604e, 0x665a, 0x2c00, 0x2078,
+	0x0479, 0x607f, 0xffff, 0x6083, 0x0000, 0x8109, 0x0180, 0x080c,
+	0x147c, 0x01c0, 0x2d00, 0x7806, 0x2f00, 0x6802, 0x6d36, 0xa006,
+	0x2d00, 0x2520, 0x00e9, 0x2d00, 0x2078, 0x8109, 0x1d80, 0x2c00,
+	0xa005, 0x002e, 0x005e, 0x004e, 0x008e, 0x00ce, 0x00de, 0x00ee,
+	0x00fe, 0x0005, 0x2c00, 0x2068, 0x080c, 0x14a3, 0x2600, 0x2071,
+	0x9363, 0x7120, 0xa102, 0x0a0c, 0x13fe, 0x7022, 0xa006, 0x0c48,
+	0x00d6, 0x00c6, 0x0136, 0x0146, 0x0156, 0x0016, 0x2068, 0x2400,
+	0xa084, 0x000f, 0xa080, 0x1f59, 0x2005, 0x2005, 0xad60, 0x2c00,
+	0x2d08, 0xa188, 0x0030, 0xa102, 0x20a8, 0x2c00, 0x20a0, 0x2001,
+	0xffff, 0x40a4, 0x001e, 0x015e, 0x014e, 0x013e, 0x00ce, 0x00de,
+	0x0005, 0x00c6, 0x00e6, 0x00f6, 0x6858, 0x2071, 0x9363, 0x7120,
+	0xa102, 0x0a0c, 0x13fe, 0x7022, 0x6960, 0x694e, 0x697c, 0x2009,
+	0xffff, 0x7818, 0xa102, 0xe000, 0x0006, 0x0006, 0x0006, 0x0006,
+	0x0006, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x6852, 0x684b,
+	0x0000, 0x6868, 0xa005, 0x0118, 0x6848, 0xc085, 0x684a, 0x2d00,
+	0xa080, 0x0015, 0x2038, 0x2031, 0x0018, 0x6864, 0x2020, 0x683a,
+	0x685c, 0xa08a, 0x00ff, 0x1a0c, 0x13fe, 0x2028, 0x2d00, 0x2060,
+	0x2078, 0x6934, 0xa18c, 0x000f, 0xa188, 0x1f59, 0x2145, 0x685c,
+	0x2050, 0xa005, 0x0530, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff,
+	0xa086, 0x0024, 0x1110, 0x7008, 0x0040, 0x6834, 0xa084, 0x00ff,
+	0xa086, 0x002c, 0x190c, 0x13fe, 0x7010, 0x0006, 0x2400, 0xa005,
+	0x000e, 0x0168, 0x203a, 0x8738, 0x8631, 0x090c, 0x13fe, 0x8421,
+	0x8529, 0x0138, 0x080c, 0x1f1b, 0x090c, 0x13fe, 0x08e0, 0x080c,
+	0x5ac8, 0x6837, 0x0023, 0x00fe, 0x00ee, 0x00ce, 0x0005, 0x00e6,
+	0x00c6, 0x00a6, 0x0086, 0x0056, 0x6858, 0x2071, 0x9363, 0x7120,
+	0xa102, 0x0a0c, 0x13fe, 0x7022, 0x2d00, 0x2060, 0x6934, 0xa18c,
+	0x000f, 0xa188, 0x1f59, 0x2145, 0x685c, 0x2050, 0xa005, 0x01d0,
+	0x2028, 0x2805, 0xac70, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0024,
+	0x1110, 0x7008, 0x0008, 0x7010, 0x0006, 0xa086, 0xffff, 0x000e,
+	0x0110, 0x080c, 0x5ac8, 0x8529, 0x0128, 0x080c, 0x1f1b, 0x090c,
+	0x13fe, 0x0c38, 0x005e, 0x008e, 0x00ae, 0x00ce, 0x00ee, 0x0005,
+	0x70ac, 0xa005, 0x0138, 0x2060, 0x6008, 0xa306, 0x0110, 0x600c,
+	0x0cc0, 0x0005, 0xa085, 0x0001, 0x0ce0, 0x70ac, 0x600e, 0x2c00,
+	0x70ae, 0x0005, 0x00f6, 0x00d6, 0x0036, 0x70ac, 0xa005, 0x090c,
+	0x13fe, 0x2068, 0x2079, 0x0000, 0x2c08, 0xa11e, 0x1118, 0x680c,
+	0x70ae, 0x0060, 0xa106, 0x0140, 0x2d00, 0x2078, 0x680c, 0xa005,
+	0x090c, 0x13fe, 0x2068, 0x0cb0, 0x6b0c, 0x7b0e, 0x600f, 0x0000,
+	0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x080c, 0x5c87, 0x6018,
+	0x2070, 0xa006, 0x70b2, 0x70b6, 0x080c, 0x14a3, 0x0899, 0x080c,
+	0x74f2, 0x00ee, 0x0005, 0x00d6, 0x0026, 0x0016, 0x2061, 0x9363,
+	0x6020, 0x6414, 0xa600, 0xa42a, 0x02c8, 0x6022, 0x2069, 0x9281,
+	0x6828, 0x6114, 0xa102, 0x1260, 0x2011, 0x8025, 0x080c, 0x3698,
+	0xa080, 0x0013, 0x2004, 0xa080, 0x0000, 0x200c, 0x8108, 0x2102,
+	0xa085, 0x0001, 0x001e, 0x002e, 0x00de, 0x0005, 0x2069, 0x9281,
+	0x6804, 0xd09c, 0x0120, 0x2011, 0x8026, 0x080c, 0x3698, 0x2001,
+	0x9281, 0xa080, 0x0013, 0x2004, 0xa080, 0x0001, 0x200c, 0x8108,
+	0x2102, 0xa006, 0x2031, 0x0000, 0x0c28, 0x0066, 0x6000, 0xa0b2,
+	0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x5d56, 0x5d56,
+	0x5d56, 0x5d58, 0x5db1, 0x5d56, 0x5d56, 0x5d56, 0x5de6, 0x5d56,
+	0x5e34, 0x5d56, 0x5d56, 0x5d56, 0x5d56, 0x5d56, 0x080c, 0x13fe,
+	0xa182, 0x0100, 0x0002, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6c, 0x5d85,
+	0x5d9d, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a, 0x5d6a,
+	0x5d6a, 0x5d6a, 0x080c, 0x13fe, 0x00d6, 0x080c, 0x641b, 0x080c,
+	0x651c, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068,
+	0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c,
+	0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x080c, 0x641b, 0x00f6,
+	0x00d6, 0x6110, 0x2178, 0x080c, 0x82ee, 0x0140, 0x784b, 0x0006,
+	0xa006, 0x70b2, 0x70b6, 0x2f68, 0x080c, 0x4809, 0x00de, 0x00fe,
+	0x080c, 0x74f2, 0x080c, 0x651c, 0x0005, 0x080c, 0x641b, 0x080c,
+	0x266c, 0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0120, 0x684b,
+	0x0029, 0x080c, 0x4809, 0x00de, 0x080c, 0x74f2, 0x080c, 0x651c,
+	0x0005, 0xa182, 0x0100, 0x0002, 0x5dc3, 0x5dc5, 0x5dcd, 0x5dc3,
+	0x5dc3, 0x5dc3, 0x5de1, 0x5dc3, 0x5dc3, 0x5dc3, 0x5dc3, 0x5dc3,
+	0x5dc3, 0x5dc3, 0x5dc3, 0x080c, 0x13fe, 0x20e1, 0x0005, 0x3d18,
+	0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00d6, 0x00e6, 0x6110,
+	0x2168, 0x080c, 0x5c19, 0x080c, 0x4809, 0x6018, 0x2070, 0xa006,
+	0x70b2, 0x70b6, 0x080c, 0x5cd2, 0x00ee, 0x00de, 0x080c, 0x74f2,
+	0x0005, 0x080c, 0x5cf4, 0x080c, 0x473b, 0x0005, 0xa182, 0x0100,
+	0x0002, 0x5dfb, 0x5e16, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9,
+	0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9, 0x5df9,
+	0x5df9, 0x080c, 0x13fe, 0x00d6, 0x6003, 0x0003, 0x6106, 0x6010,
+	0x2068, 0x687c, 0x680a, 0x6880, 0x680e, 0x6813, 0x0000, 0x6817,
+	0x0000, 0x00de, 0x2c10, 0x080c, 0x1c88, 0x080c, 0x605b, 0x0126,
+	0x2091, 0x8000, 0x080c, 0x651c, 0x012e, 0x0005, 0x6003, 0x0004,
+	0x630a, 0x080c, 0x5b65, 0x0168, 0x6012, 0x600f, 0x0000, 0x080c,
+	0x5ccd, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6,
+	0x0005, 0x2011, 0x0000, 0x080c, 0x16c6, 0x70b3, 0x0000, 0x70b7,
+	0x0000, 0x080c, 0x74f2, 0x0005, 0x00d6, 0x080c, 0x641b, 0x080c,
+	0x651c, 0x6110, 0x2168, 0x684b, 0x0000, 0x00d6, 0x6018, 0x2068,
+	0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de, 0x080c,
+	0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x6000, 0xa08a, 0x0010,
+	0x1a0c, 0x13fe, 0x000b, 0x0005, 0x5e64, 0x5e64, 0x5e64, 0x5e66,
+	0x5e7f, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x5e64,
+	0x5e64, 0x5e64, 0x5e64, 0x5e64, 0x080c, 0x13fe, 0x080c, 0x7366,
+	0x190c, 0x13fe, 0x6110, 0x2168, 0x684b, 0x0006, 0x00d6, 0x6018,
+	0x2068, 0x6008, 0x68b6, 0x68bb, 0x0500, 0xa006, 0x68b2, 0x00de,
+	0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x0005, 0x0005,
+	0x6000, 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x5e97,
+	0x5e97, 0x5e97, 0x5e99, 0x5e9b, 0x5e97, 0x5e97, 0x5e97, 0x5e97,
+	0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x5e97, 0x080c,
+	0x13fe, 0x080c, 0x13fe, 0x00d6, 0x6010, 0x2068, 0x080c, 0x5cf4,
+	0x00de, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
+	0x1208, 0xa200, 0x1f04, 0x5ea6, 0x8086, 0x818e, 0x0005, 0x0156,
+	0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d,
+	0x0228, 0xa11a, 0x1220, 0x1f04, 0x5eb6, 0x0028, 0xa11a, 0x2308,
+	0x8210, 0x1f04, 0x5eb6, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080,
+	0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8,
+	0x0126, 0x2091, 0x2400, 0x2079, 0x94e5, 0x012e, 0x00d6, 0x2069,
+	0x94e5, 0x6803, 0x0005, 0x2069, 0x0004, 0x2d04, 0xa085, 0x8001,
+	0x206a, 0x00de, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0xa084,
+	0x0007, 0x0002, 0x5ef4, 0x5f15, 0x5f68, 0x5efa, 0x5f15, 0x5ef4,
+	0x5ef2, 0x5ef2, 0x080c, 0x13fe, 0x080c, 0x57a1, 0x080c, 0x6462,
+	0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011,
+	0x40af, 0x080c, 0x5731, 0x7828, 0xa092, 0x0002, 0x1228, 0x8000,
+	0x782a, 0x080c, 0x40fc, 0x0c88, 0x080c, 0x40af, 0x7807, 0x0003,
+	0x7827, 0x0000, 0x782b, 0x0000, 0x0c40, 0x080c, 0x57a1, 0x3c00,
+	0x0006, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x000e, 0x20e0,
+	0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160, 0x782b, 0x0000, 0x7824,
+	0xa065, 0x090c, 0x13fe, 0x2009, 0x0013, 0x080c, 0x7518, 0x00ce,
+	0x0005, 0x3900, 0xa082, 0x9606, 0x1210, 0x080c, 0x7432, 0x00c6,
+	0x7824, 0xa065, 0x090c, 0x13fe, 0x7804, 0xa086, 0x0004, 0x0904,
+	0x5fa8, 0x7828, 0xa092, 0x2710, 0x1230, 0x8000, 0x782a, 0x00ce,
+	0x080c, 0x6f11, 0x0c20, 0x6104, 0xa186, 0x0003, 0x1188, 0x00e6,
+	0x2071, 0x9200, 0x70d4, 0x00ee, 0xd08c, 0x0150, 0x00c6, 0x00e6,
+	0x2061, 0x0100, 0x2071, 0x9200, 0x080c, 0x4105, 0x00ee, 0x00ce,
+	0x080c, 0x91a0, 0x2009, 0x0014, 0x080c, 0x7518, 0x00ce, 0x0838,
+	0x2001, 0x9501, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b,
+	0x0000, 0x7824, 0xa065, 0x090c, 0x13fe, 0x2009, 0x0013, 0x080c,
+	0x7563, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x3900, 0xa082, 0x9606,
+	0x1210, 0x080c, 0x7432, 0x7824, 0xa005, 0x090c, 0x13fe, 0x781c,
+	0xa06d, 0x090c, 0x13fe, 0x6800, 0xc0dc, 0x6802, 0x7924, 0x2160,
+	0x080c, 0x74f2, 0x693c, 0x81ff, 0x090c, 0x13fe, 0x8109, 0x693e,
+	0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010, 0x7918, 0x791e, 0x7807,
+	0x0000, 0x7827, 0x0000, 0x00de, 0x00ce, 0x080c, 0x6462, 0x0888,
+	0x6104, 0xa186, 0x0002, 0x0128, 0xa186, 0x0004, 0x0110, 0x0804,
+	0x5f41, 0x7808, 0xac06, 0x0904, 0x5f41, 0x080c, 0x6389, 0x080c,
+	0x603e, 0x00ce, 0x080c, 0x6462, 0x0804, 0x5f2f, 0x00c6, 0x6027,
+	0x0002, 0x62c8, 0x60c4, 0xa205, 0x11a0, 0x793c, 0xa1e5, 0x0000,
+	0x0150, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009, 0x1110, 0x2009,
+	0x0103, 0x080c, 0x7518, 0x2011, 0x9504, 0x2013, 0x0000, 0x00ce,
+	0x0005, 0x3908, 0xa192, 0x9606, 0x1210, 0x080c, 0x7432, 0x6017,
+	0x0010, 0x793c, 0x81ff, 0x0d78, 0x793c, 0xa188, 0x0007, 0x210c,
+	0xa18e, 0x0006, 0x1118, 0x6017, 0x0012, 0x0c48, 0x793c, 0xa188,
+	0x0007, 0x210c, 0xa18e, 0x0009, 0x0db0, 0x6017, 0x0016, 0x08f8,
+	0x0006, 0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000,
+	0x2c08, 0x2061, 0x94e5, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005,
+	0x0148, 0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e,
+	0x000e, 0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x94e5,
+	0x6000, 0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001,
+	0x1110, 0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x646f,
+	0xc0d5, 0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000,
+	0x0006, 0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0x94e5, 0x0c18,
+	0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016,
+	0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061,
+	0x94e5, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080,
+	0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005,
+	0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061,
+	0x94e5, 0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136,
+	0x00ce, 0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6,
+	0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x0126, 0x2071, 0x94e5,
+	0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x60cb,
+	0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x60c6, 0x88ff,
+	0x0118, 0x6020, 0xa106, 0x15d0, 0x703c, 0xac06, 0x1120, 0x6003,
+	0x000a, 0x630a, 0x0498, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a,
+	0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036,
+	0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
+	0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x82ee, 0x0188,
+	0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c,
+	0x848f, 0x080c, 0x849b, 0x00ce, 0x0804, 0x607d, 0x2c78, 0x600c,
+	0x2060, 0x0804, 0x607d, 0x012e, 0x000e, 0x001e, 0x002e, 0x006e,
+	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006,
+	0x19e8, 0x080c, 0x9097, 0x0c28, 0x0006, 0x0066, 0x00c6, 0x00d6,
+	0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000, 0x2079, 0x94e5,
+	0x7838, 0xa065, 0x0510, 0x600c, 0x0006, 0x600f, 0x0000, 0x783c,
+	0xac06, 0x1128, 0x6003, 0x000a, 0x630a, 0x2c30, 0x00a0, 0x080c,
+	0x82ee, 0x0178, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x11b0,
+	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c,
+	0x848f, 0x080c, 0x849b, 0x000e, 0x08e0, 0x7e3a, 0x7e36, 0x012e,
+	0x00fe, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c, 0xa086,
+	0x0006, 0x0150, 0x601c, 0xa086, 0x0009, 0x1d10, 0x6b4a, 0x080c,
+	0x4809, 0x080c, 0x74f2, 0x0c38, 0x080c, 0x9097, 0x0c10, 0x0016,
+	0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x61d3, 0x008e,
+	0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x94e5, 0x2091,
+	0x8000, 0x080c, 0x625e, 0x080c, 0x62be, 0x012e, 0x00fe, 0x0005,
+	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126,
+	0x2091, 0x8000, 0x2071, 0x94e5, 0x7614, 0x2660, 0x2678, 0x8cff,
+	0x0904, 0x61c3, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904,
+	0x61be, 0x88ff, 0x0120, 0x6020, 0xa106, 0x1904, 0x61be, 0x7024,
+	0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c,
+	0x57a1, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, 0x7027,
+	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
+	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
+	0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a,
+	0x04a8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36,
+	0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013,
+	0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
+	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0178,
+	0x601c, 0xa086, 0x0003, 0x1500, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, 0x848f, 0x080c,
+	0x849b, 0x080c, 0x7238, 0x00ce, 0x0804, 0x614f, 0x2c78, 0x600c,
+	0x2060, 0x0804, 0x614f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce,
+	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e0,
+	0x080c, 0x9097, 0x0c20, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000,
+	0xa280, 0x936e, 0x2004, 0xa065, 0x0904, 0x625a, 0x00f6, 0x00e6,
+	0x00d6, 0x0066, 0x2071, 0x94e5, 0x6654, 0x7018, 0xac06, 0x1108,
+	0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e,
+	0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56, 0xa6ed, 0x0000,
+	0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000,
+	0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x43ba, 0x0904, 0x6256, 0x7624,
+	0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6,
+	0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c, 0x57a1, 0x080c,
+	0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356, 0x7027, 0x0000, 0x0036,
+	0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100,
+	0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827,
+	0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001,
+	0x603e, 0x2660, 0x080c, 0x849b, 0x00ce, 0x0048, 0x00de, 0x00c6,
+	0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x6203, 0x8dff,
+	0x0148, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x8527,
+	0x080c, 0x4809, 0x080c, 0x7238, 0x0804, 0x6203, 0x006e, 0x00de,
+	0x00ee, 0x00fe, 0x012e, 0x000e, 0x00ce, 0x0005, 0x0006, 0x0066,
+	0x00c6, 0x00d6, 0x2031, 0x0000, 0x7814, 0xa065, 0x0904, 0x62b0,
+	0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0xac06, 0x1540, 0x2069,
+	0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c, 0x57a1, 0x080c, 0x6f1e,
+	0x68c3, 0x0000, 0x080c, 0x7356, 0x7827, 0x0000, 0x0036, 0x2069,
+	0x0140, 0x6b04, 0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803,
+	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001,
+	0x003e, 0x0028, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00b0, 0x6010,
+	0x2068, 0x080c, 0x82ee, 0x0168, 0x601c, 0xa086, 0x0003, 0x11b8,
+	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c,
+	0x848f, 0x080c, 0x849b, 0x080c, 0x7238, 0x000e, 0x0804, 0x6265,
+	0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x0005, 0x601c,
+	0xa086, 0x0006, 0x1d28, 0x080c, 0x9097, 0x0c58, 0x0006, 0x0066,
+	0x00c6, 0x00d6, 0x7818, 0xa065, 0x0904, 0x6324, 0x6054, 0x0006,
+	0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002,
+	0x080c, 0x43ba, 0x0904, 0x6321, 0x7e24, 0x86ff, 0x05e8, 0xa680,
+	0x0004, 0x2004, 0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0,
+	0xa005, 0x0548, 0x080c, 0x57a1, 0x080c, 0x6f1e, 0x68c3, 0x0000,
+	0x080c, 0x7356, 0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04,
+	0xa384, 0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069,
+	0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de,
+	0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c,
+	0x849b, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009,
+	0x630a, 0x00ce, 0x0804, 0x62d0, 0x8dff, 0x0138, 0x6837, 0x0103,
+	0x6b4a, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x7238, 0x0804,
+	0x62d0, 0x000e, 0x0804, 0x62c3, 0x781e, 0x781a, 0x00de, 0x00ce,
+	0x006e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc,
+	0x0188, 0x604c, 0xa06d, 0x0170, 0x6848, 0xa606, 0x1158, 0x2071,
+	0x94e5, 0x7024, 0xa035, 0x0130, 0xa080, 0x0004, 0x2004, 0xad06,
+	0x1108, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x2079,
+	0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003, 0x0009,
+	0x630a, 0x00ce, 0x04a0, 0x080c, 0x6f1e, 0x78c3, 0x0000, 0x080c,
+	0x7356, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04, 0xa384,
+	0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079, 0x0100,
+	0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x7356, 0x003e,
+	0x080c, 0x43ba, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001, 0x603e,
+	0x2660, 0x080c, 0x74f2, 0x00ce, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x080c, 0x8527, 0x080c, 0x4809, 0x080c, 0x7238, 0x00fe,
+	0x0005, 0x00e6, 0x00c6, 0x2071, 0x94e5, 0x7004, 0xa084, 0x0007,
+	0x0002, 0x639b, 0x639e, 0x63b4, 0x63cd, 0x6406, 0x639b, 0x6399,
+	0x6399, 0x080c, 0x13fe, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065,
+	0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150, 0x7216,
+	0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee,
+	0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c, 0x43ba,
+	0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120, 0x6054,
+	0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce,
+	0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065, 0x0598,
+	0x700c, 0xac06, 0x1160, 0x080c, 0x7238, 0x600c, 0xa015, 0x0120,
+	0x720e, 0x600f, 0x0000, 0x0428, 0x720e, 0x720a, 0x0410, 0x7014,
+	0xac06, 0x1160, 0x080c, 0x7238, 0x600c, 0xa015, 0x0120, 0x7216,
+	0x600f, 0x0000, 0x00b0, 0x7216, 0x7212, 0x0098, 0x6018, 0x2060,
+	0x080c, 0x43ba, 0x6000, 0xc0dc, 0x6002, 0x080c, 0x7238, 0x701c,
+	0xa065, 0x0138, 0x6054, 0xa015, 0x0110, 0x721e, 0x0010, 0x7218,
+	0x721e, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065,
+	0x0140, 0x080c, 0x7238, 0x600c, 0xa015, 0x0150, 0x720e, 0x600f,
+	0x0000, 0x080c, 0x7356, 0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005,
+	0x720e, 0x720a, 0x0cb0, 0x00d6, 0x2069, 0x94e5, 0x6830, 0xa084,
+	0x0003, 0x0002, 0x6428, 0x642a, 0x644a, 0x6426, 0x080c, 0x13fe,
+	0x00de, 0x0005, 0x00c6, 0x6840, 0xa086, 0x0001, 0x0198, 0x683c,
+	0xa065, 0x0130, 0x600c, 0xa015, 0x0150, 0x6a3a, 0x600f, 0x0000,
+	0x6833, 0x0000, 0x683f, 0x0000, 0x00ce, 0x00de, 0x0005, 0x683a,
+	0x6836, 0x0cb0, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d88, 0x6003,
+	0x0003, 0x0c70, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000, 0x683c,
+	0xa065, 0x0168, 0x600c, 0xa015, 0x0130, 0x6a3a, 0x600f, 0x0000,
+	0x683f, 0x0000, 0x0020, 0x683f, 0x0000, 0x683a, 0x6836, 0x00ce,
+	0x00de, 0x0005, 0x00d6, 0x2001, 0x9295, 0x2004, 0xd084, 0x0110,
+	0x00de, 0x0005, 0x2069, 0x94e5, 0x6804, 0xa084, 0x0007, 0x0002,
+	0x647a, 0x650c, 0x650c, 0x650c, 0x650c, 0x650e, 0x6478, 0x6478,
+	0x080c, 0x13fe, 0x6820, 0xa005, 0x1110, 0x00de, 0x0005, 0x00c6,
+	0x680c, 0xa065, 0x0150, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
+	0x080c, 0x656d, 0x00ce, 0x00de, 0x0005, 0x6814, 0xa065, 0x0150,
+	0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x656d, 0x00ce,
+	0x00de, 0x0005, 0x00e6, 0x0036, 0x6a1c, 0xa2f5, 0x0000, 0x0904,
+	0x6508, 0x704c, 0xa00d, 0x0118, 0x7088, 0xa005, 0x01a0, 0x7054,
+	0xa075, 0x0120, 0xa20e, 0x0904, 0x6508, 0x0028, 0x6818, 0xa20e,
+	0x0904, 0x6508, 0x2070, 0x704c, 0xa00d, 0x0d88, 0x7088, 0xa005,
+	0x1d70, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302, 0x1e40, 0x080c,
+	0x74c9, 0x0904, 0x6508, 0x8318, 0x733e, 0x6112, 0x2e10, 0x621a,
+	0xa180, 0x0015, 0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999,
+	0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78,
+	0x71a0, 0x2001, 0x9232, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150,
+	0x7100, 0xd1f4, 0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009,
+	0x0000, 0x0028, 0xa1e0, 0x2719, 0x2c0d, 0xa18c, 0x00ff, 0x2061,
+	0x0100, 0x619a, 0x080c, 0x6a46, 0x7300, 0xc3dd, 0x7302, 0x6807,
+	0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803,
+	0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005,
+	0x003e, 0x00ee, 0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c,
+	0xa065, 0x0138, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c,
+	0x656d, 0x00ce, 0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x94e5,
+	0x6830, 0xa086, 0x0000, 0x1590, 0x6838, 0xa07d, 0x0578, 0x781c,
+	0xa086, 0x0009, 0x1140, 0x7808, 0xd0fc, 0x0128, 0x2001, 0x94e6,
+	0x2004, 0xa005, 0x1518, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847,
+	0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1d0f,
+	0x11c0, 0x012e, 0xe000, 0xe000, 0xe000, 0x6a3c, 0x2278, 0x781c,
+	0xa086, 0x0009, 0x1148, 0x7808, 0xd0fc, 0x0118, 0x080c, 0x6cf9,
+	0x0028, 0x080c, 0x6d75, 0x0010, 0x080c, 0x6dec, 0x00de, 0x00fe,
+	0x0005, 0x012e, 0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c,
+	0xa015, 0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f,
+	0x0000, 0x0c60, 0x683a, 0x6836, 0x0cc0, 0x601c, 0xa084, 0x000f,
+	0x000b, 0x0005, 0x657b, 0x6580, 0x68f8, 0x6a03, 0x6580, 0x68f8,
+	0x6a03, 0x657b, 0x6580, 0x080c, 0x6389, 0x080c, 0x6462, 0x0005,
+	0x0156, 0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x003e,
+	0x1a0c, 0x13fe, 0x6118, 0x2178, 0x79a0, 0x2011, 0x9232, 0x2214,
+	0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914,
+	0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2719,
+	0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0x0033,
+	0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e, 0x0005, 0x65f5, 0x662d,
+	0x6647, 0x66fa, 0x6725, 0x672d, 0x674e, 0x675f, 0x6770, 0x6778,
+	0x6789, 0x6778, 0x67ce, 0x675f, 0x67ef, 0x67f7, 0x6770, 0x67f7,
+	0x6808, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec,
+	0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x6fda, 0x6fef, 0x7012,
+	0x7036, 0x674e, 0x65ec, 0x674e, 0x6778, 0x65ec, 0x6647, 0x66fa,
+	0x65ec, 0x744f, 0x6778, 0x65ec, 0x746f, 0x6778, 0x65ec, 0x6770,
+	0x65ee, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec, 0x65ec,
+	0x65ec, 0x65ec, 0x65ec, 0x704b, 0x080c, 0x13fe, 0x2001, 0x9214,
+	0x2004, 0x609a, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c,
+	0x681d, 0x20a3, 0x5200, 0x20a3, 0x0000, 0x00d6, 0x2069, 0x9251,
+	0x6804, 0xd084, 0x0150, 0x6828, 0x20a3, 0x0000, 0x0016, 0x080c,
+	0x241f, 0x21a2, 0x001e, 0x00de, 0x0028, 0x00de, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x9205, 0x53a6, 0x20a9,
+	0x0004, 0x2099, 0x9201, 0x53a6, 0x20a3, 0x0000, 0x2001, 0x9214,
+	0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x001c, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c,
+	0x681d, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0x921b, 0x2004,
+	0x20a2, 0x2001, 0x921c, 0x2004, 0x20a2, 0x20a9, 0x0004, 0x2099,
+	0x9205, 0x53a6, 0x60c3, 0x0010, 0x080c, 0x6f0b, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x681d, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086,
+	0x007e, 0x1130, 0x20a3, 0x0400, 0x620c, 0xc2b4, 0x620e, 0x0010,
+	0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004,
+	0xa086, 0x007e, 0x1904, 0x66bc, 0x2001, 0x9232, 0x2004, 0xd0a4,
+	0x01c8, 0x2099, 0x94c7, 0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398,
+	0x3304, 0xa084, 0x2000, 0x20a2, 0x9398, 0x33a6, 0x9398, 0x20a3,
+	0x0000, 0x9398, 0x2001, 0x2710, 0x20a2, 0x9398, 0x33a6, 0x9398,
+	0x33a6, 0x00d0, 0x2099, 0x94c7, 0x33a6, 0x9398, 0x33a6, 0x9398,
+	0x3304, 0x080c, 0x4dc5, 0x1118, 0xa084, 0x37ff, 0x0010, 0xa084,
+	0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099, 0x9205,
+	0x53a6, 0x20a9, 0x0004, 0x2099, 0x9201, 0x53a6, 0x20a9, 0x0008,
+	0x20a3, 0x0000, 0x1f04, 0x66a8, 0x20a9, 0x0008, 0x20a3, 0x0000,
+	0x1f04, 0x66ae, 0x2099, 0x94cf, 0x33a6, 0x20a9, 0x0007, 0x20a3,
+	0x0000, 0x1f04, 0x66b7, 0x0468, 0x2001, 0x9232, 0x2004, 0xd0a4,
+	0x0140, 0x2001, 0x94c8, 0x2004, 0x60e3, 0x0000, 0x080c, 0x2460,
+	0x60e2, 0x2099, 0x94c7, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004,
+	0x2099, 0x9205, 0x53a6, 0x20a9, 0x0004, 0x2099, 0x9201, 0x53a6,
+	0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x66da, 0x20a9, 0x0008,
+	0x20a3, 0x0000, 0x1f04, 0x66e0, 0x2099, 0x94cf, 0x20a9, 0x0008,
+	0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x66eb, 0x20a9,
+	0x000a, 0x20a3, 0x0000, 0x1f04, 0x66f1, 0x60c3, 0x0074, 0x080c,
+	0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c, 0x681d, 0x20a3, 0x2010,
+	0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2,
+	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x00f6, 0x2079, 0x9251, 0x7904,
+	0x00fe, 0xd1ac, 0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085,
+	0x0010, 0xa085, 0x0002, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x080c,
+	0x681d, 0x20a3, 0x5000, 0x0804, 0x665a, 0x20a1, 0x020b, 0x080c,
+	0x681d, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b,
+	0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0004, 0x080c, 0x6f0b, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
+	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005,
+	0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x0804, 0x665a,
+	0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000,
+	0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x6f0b,
+	0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0210,
+	0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068, 0x6894, 0xa086,
+	0x0014, 0x1178, 0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118,
+	0x20a3, 0x2100, 0x0040, 0x20a3, 0x0100, 0x0028, 0x20a3, 0x0400,
+	0x0010, 0x20a3, 0x0700, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
+	0x20a2, 0x00f6, 0x2079, 0x9251, 0x7904, 0x00fe, 0xd1ac, 0x1110,
+	0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009, 0x9273,
+	0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x20a2, 0x20a2, 0x20a2,
+	0x60c3, 0x0014, 0x080c, 0x6f0b, 0x00de, 0x0005, 0x20a1, 0x020b,
+	0x080c, 0x68a0, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000,
+	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x6f0b, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x0804, 0x65fb, 0x20a1,
+	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
+	0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005,
+	0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x68a0,
+	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000,
+	0x60c3, 0x0008, 0x080c, 0x6f0b, 0x0005, 0x0026, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e,
+	0x1198, 0x20a3, 0x22ff, 0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011,
+	0x9214, 0x2214, 0x2001, 0x94d7, 0x2004, 0xa005, 0x0118, 0x2011,
+	0x921c, 0x2214, 0x22a2, 0x0498, 0xa286, 0x007f, 0x1130, 0x00d6,
+	0x20a3, 0x22ff, 0x20a3, 0xfffd, 0x00c8, 0x2001, 0x9232, 0x2004,
+	0xd0ac, 0x1110, 0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1128,
+	0x20a3, 0x22ff, 0x20a3, 0xfffc, 0x0048, 0xa2e8, 0x936e, 0x2d6c,
+	0x6810, 0xa085, 0x2200, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b,
+	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x2200, 0x6298,
+	0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3,
+	0x0129, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
+	0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
+	0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff,
+	0x2011, 0xfffc, 0x22a2, 0x00d6, 0x2069, 0x921b, 0x2da6, 0x8d68,
+	0x2da6, 0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3,
+	0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005,
+	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
+	0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e,
+	0x02e0, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x2300,
+	0x20a2, 0x6814, 0x20a2, 0x6810, 0xa005, 0x1140, 0x6814, 0xa005,
+	0x1128, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0028, 0x2069, 0x921b,
+	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x2300, 0x6298,
+	0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3,
+	0x0198, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
+	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
+	0x0005, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
+	0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
+	0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x13fe, 0xa08a,
+	0x008c, 0x1a0c, 0x13fe, 0x6118, 0x2178, 0x79a0, 0x2011, 0x9232,
+	0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120,
+	0x7914, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8,
+	0x2719, 0x2f0d, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a,
+	0xa082, 0x0085, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x692f, 0x6939,
+	0x6954, 0x692d, 0x692d, 0x692d, 0x692f, 0x080c, 0x13fe, 0x0146,
+	0x20a1, 0x020b, 0x04a1, 0x60c3, 0x0000, 0x080c, 0x6f0b, 0x014e,
+	0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6999, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000,
+	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c,
+	0x080c, 0x6f0b, 0x014e, 0x0005, 0x0146, 0x20a1, 0x020b, 0x080c,
+	0x69d1, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x60c3, 0x0004, 0x080c, 0x6f0b, 0x014e, 0x0005, 0x0026,
+	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
+	0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288,
+	0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
+	0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
+	0x0050, 0x20a3, 0x8100, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011,
+	0x9214, 0x2214, 0x22a2, 0x20a3, 0x0009, 0x20a3, 0x0000, 0x0804,
+	0x6873, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
+	0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092,
+	0x007e, 0x0288, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085,
+	0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68,
+	0x2da6, 0x00de, 0x0050, 0x20a3, 0x8400, 0x6298, 0x22a2, 0x20a3,
+	0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x080c, 0x4dc5, 0x1118,
+	0x20a3, 0x0099, 0x0010, 0x20a3, 0x00d1, 0x20a3, 0x0000, 0x0804,
+	0x68e9, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
+	0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1118, 0xa092,
+	0x007e, 0x0288, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085,
+	0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68,
+	0x2da6, 0x00de, 0x0050, 0x20a3, 0x8500, 0x6298, 0x22a2, 0x20a3,
+	0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0099, 0x20a3,
+	0x0000, 0x0804, 0x68e9, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a,
+	0x0040, 0x0a0c, 0x13fe, 0xa08a, 0x0053, 0x1a0c, 0x13fe, 0x7918,
+	0x2160, 0x61a0, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1110, 0xd1bc,
+	0x0150, 0x6100, 0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040,
+	0x2009, 0x0000, 0x0028, 0xa1e0, 0x2719, 0x2c0d, 0xa18c, 0x00ff,
+	0x2061, 0x0100, 0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce,
+	0x0005, 0x6a46, 0x6b3a, 0x6ade, 0x6c75, 0x6a44, 0x6a44, 0x6a44,
+	0x6a44, 0x6a44, 0x6a44, 0x6a44, 0x71f1, 0x7201, 0x7211, 0x7221,
+	0x6a44, 0x6a44, 0x6a44, 0x71e0, 0x080c, 0x13fe, 0x00d6, 0x0156,
+	0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7910, 0x2168, 0x6948,
+	0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184,
+	0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001,
+	0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x20a2, 0xd1ac, 0x0118,
+	0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020,
+	0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008,
+	0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e,
+	0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080,
+	0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0x9501,
+	0x2003, 0x07d0, 0x2001, 0x9500, 0x2003, 0x0009, 0x080c, 0x165a,
+	0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
+	0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0x9232, 0x231c,
+	0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c,
+	0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b,
+	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0600, 0x6198,
+	0x21a2, 0x20a3, 0x0000, 0x2009, 0x9214, 0x210c, 0x21a2, 0x20a3,
+	0x0829, 0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3,
+	0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156,
+	0x0136, 0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860,
+	0x20a2, 0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006,
+	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x6f0b,
+	0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080,
+	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x9232,
+	0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e,
+	0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069,
+	0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0500,
+	0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2,
+	0x20a3, 0x0889, 0x20a3, 0x0000, 0x080c, 0x6efa, 0x22a2, 0x20a3,
+	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
+	0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x20a1, 0x020b,
+	0x080c, 0x6c38, 0x7810, 0x2068, 0xa016, 0x22a2, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000, 0x1130, 0x7810, 0xa084,
+	0x0700, 0x8007, 0x0043, 0x0010, 0xa006, 0x002b, 0x014e, 0x013e,
+	0x015e, 0x00de, 0x0005, 0x6b65, 0x6bde, 0x6be1, 0x6c04, 0x6c11,
+	0x6c23, 0x6c26, 0x6b63, 0x080c, 0x13fe, 0x0016, 0x0036, 0x694c,
+	0xa18c, 0x0003, 0xa186, 0x0000, 0x1150, 0x6b78, 0x23a2, 0x6868,
+	0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804, 0x6c08, 0xa186,
+	0x0001, 0x1904, 0x6bd9, 0x6b78, 0x23a2, 0x6868, 0x20a2, 0x6864,
+	0x20a2, 0x22a2, 0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009,
+	0x0018, 0xa384, 0x0300, 0x0904, 0x6bd8, 0xd3c4, 0x0110, 0x687c,
+	0xa108, 0xd3cc, 0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d,
+	0xad80, 0x0020, 0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x6b9a,
+	0x015e, 0x22a2, 0x22a2, 0x22a2, 0xa184, 0x0003, 0x0588, 0x20a1,
+	0x020b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080,
+	0x0028, 0x2004, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c,
+	0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b,
+	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0700, 0x6298,
+	0x22a2, 0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x000e,
+	0x20a3, 0x0898, 0x20a2, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
+	0x61c2, 0x003e, 0x001e, 0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0008,
+	0x0428, 0x20a3, 0x0302, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012,
+	0x22a2, 0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3,
+	0x7000, 0x20a3, 0x0500, 0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2,
+	0x20a3, 0x2500, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
+	0x0032, 0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0028, 0x22a2, 0x22a2,
+	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0018, 0x080c, 0x6f0b,
+	0x0005, 0x20a3, 0x0100, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
+	0x20a3, 0x0008, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0020,
+	0x080c, 0x6f0b, 0x0005, 0x20a3, 0x0008, 0x0c00, 0x0036, 0x7b10,
+	0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001, 0x1118, 0x22a2,
+	0x003e, 0x08a0, 0x20a3, 0x0800, 0x22a2, 0x20a2, 0x003e, 0x0880,
+	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
+	0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
+	0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
+	0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6, 0x8d68, 0x2da6, 0x00de,
+	0x0050, 0x20a3, 0x0700, 0x6298, 0x22a2, 0x20a3, 0x0000, 0x2011,
+	0x9214, 0x2214, 0x22a2, 0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c,
+	0x6efa, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00d6, 0x0156, 0x0136,
+	0x0146, 0x0016, 0x0036, 0x7810, 0xa084, 0x0700, 0x8007, 0x003b,
+	0x003e, 0x001e, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x6c8f,
+	0x6c8f, 0x6c91, 0x6c8f, 0x6c8f, 0x6c8f, 0x6cb3, 0x6c8f, 0x080c,
+	0x13fe, 0x7910, 0xa18c, 0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1,
+	0x020b, 0x2009, 0x0003, 0x00f9, 0x00d6, 0x2069, 0x9251, 0x6804,
+	0xd0bc, 0x0130, 0x682c, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010,
+	0x20a3, 0x3f00, 0x00de, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001,
+	0x080c, 0x6f0b, 0x0005, 0x20a1, 0x020b, 0x2009, 0x0003, 0x0019,
+	0x20a3, 0x7f00, 0x0c80, 0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000,
+	0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0x9232, 0x2214, 0xd2ac,
+	0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0x936e, 0x2d6c, 0x6810,
+	0xa085, 0x0100, 0x20a2, 0x6814, 0x20a2, 0x2069, 0x921b, 0x2da6,
+	0x8d68, 0x2da6, 0x00de, 0x0050, 0x20a3, 0x0100, 0x6298, 0x22a2,
+	0x20a3, 0x0000, 0x2011, 0x9214, 0x2214, 0x22a2, 0x20a3, 0x0888,
+	0xa18d, 0x0008, 0x21a2, 0x080c, 0x6efa, 0x22a2, 0x20a3, 0x0000,
+	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e,
+	0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036,
+	0x2061, 0x0100, 0x2071, 0x9200, 0x2009, 0x9214, 0x210c, 0x7818,
+	0x2068, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x0110, 0x736c,
+	0x7470, 0x2500, 0x2031, 0x9232, 0x2634, 0xa6b4, 0x0028, 0x0140,
+	0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050,
+	0x2001, 0x00ff, 0xa085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b,
+	0x0000, 0x616e, 0x68b8, 0x6072, 0x6077, 0x0008, 0x688c, 0x8000,
+	0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020, 0x607a, 0x68b4,
+	0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff, 0x7810, 0x2070,
+	0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca,
+	0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
+	0x2001, 0x9232, 0x2004, 0xd09c, 0x0128, 0x609f, 0x0000, 0x2001,
+	0x0012, 0x0048, 0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027,
+	0xffff, 0x2001, 0x0032, 0x6016, 0x2009, 0x07d0, 0x080c, 0x57a6,
+	0x2001, 0x9295, 0x200c, 0xc185, 0x2102, 0x003e, 0x004e, 0x005e,
+	0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6,
+	0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x9200,
+	0x2009, 0x9214, 0x210c, 0x7818, 0x2068, 0x68a0, 0x2028, 0x2031,
+	0x9232, 0x2634, 0xd6ac, 0x1140, 0xd0bc, 0x1130, 0xa080, 0x2719,
+	0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14, 0x736c, 0x7470,
+	0x2001, 0x9232, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185,
+	0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400,
+	0x6266, 0x606b, 0x0000, 0x616e, 0x68b8, 0x6072, 0x6077, 0x0008,
+	0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0xa085, 0x0020,
+	0x607a, 0x68b4, 0x607f, 0x0000, 0x2d00, 0x6082, 0x6087, 0xffff,
+	0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
+	0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
+	0x60d7, 0x0000, 0xa582, 0x0080, 0x0210, 0x2011, 0x0000, 0x629e,
+	0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x6017, 0x0012,
+	0x2009, 0x07d0, 0x080c, 0x57a6, 0x003e, 0x004e, 0x005e, 0x006e,
+	0x00ce, 0x00de, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0056,
+	0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x9200, 0x7150, 0x7818,
+	0x2068, 0x68a0, 0x2028, 0x76c8, 0xd6ac, 0x1140, 0xd0bc, 0x1130,
+	0xa080, 0x2719, 0x2015, 0xa294, 0x00ff, 0x0020, 0x6910, 0x6a14,
+	0x736c, 0x7470, 0x781c, 0xa086, 0x0006, 0x0904, 0x6e65, 0x70c8,
+	0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266,
+	0x636a, 0x646e, 0x0030, 0x6063, 0x0100, 0x6266, 0x606b, 0x0000,
+	0x616e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
+	0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082,
+	0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e,
+	0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036,
+	0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00,
+	0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000,
+	0x629e, 0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0,
+	0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x57a6, 0x003e, 0x004e,
+	0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7810, 0x2070, 0x704c,
+	0xa084, 0x0003, 0xa086, 0x0002, 0x0904, 0x6eb4, 0x2001, 0x9232,
+	0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062,
+	0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0100, 0x6266, 0x606b,
+	0x0000, 0x616e, 0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000,
+	0xa084, 0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00,
+	0x6086, 0x7808, 0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080,
+	0x60c6, 0x707c, 0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af,
+	0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4,
+	0x0120, 0x6a14, 0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e,
+	0x6017, 0x0012, 0x0804, 0x6e53, 0x2001, 0x9232, 0x2004, 0xd0ac,
+	0x1110, 0xd5bc, 0x0138, 0xa185, 0x0700, 0x6062, 0x6266, 0x636a,
+	0x646e, 0x0030, 0x6063, 0x0700, 0x6266, 0x606b, 0x0000, 0x616e,
+	0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff,
+	0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
+	0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
+	0x60ca, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
+	0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14,
+	0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x6017, 0x0016,
+	0x0804, 0x6e53, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294,
+	0x00ff, 0x2202, 0x8217, 0x0005, 0x00d6, 0x2069, 0x94e5, 0x6843,
+	0x0001, 0x00de, 0x0005, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7,
+	0x9575, 0x0019, 0x080c, 0x5798, 0x0005, 0x0006, 0x6014, 0xa084,
+	0x0004, 0xa085, 0x0009, 0x6016, 0x000e, 0x0005, 0x0006, 0x00c6,
+	0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008, 0x6016,
+	0x00ce, 0x000e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x080c,
+	0x57a1, 0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000,
+	0x0538, 0x0c21, 0x6803, 0x1000, 0x6803, 0x0000, 0x00c6, 0x2061,
+	0x94e5, 0x6128, 0xa192, 0x0002, 0x1250, 0x8108, 0x612a, 0x6124,
+	0x00ce, 0x81ff, 0x0180, 0x080c, 0x5798, 0x0839, 0x0060, 0x6124,
+	0xa1e5, 0x0000, 0x0130, 0x080c, 0x91a0, 0x2009, 0x0014, 0x080c,
+	0x7518, 0x00ce, 0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005,
+	0x080c, 0x4dc5, 0x1118, 0x080c, 0x6f1e, 0x08c0, 0x080c, 0x4105,
+	0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x57ae,
+	0x2071, 0x94e5, 0x713c, 0x81ff, 0x0578, 0x2061, 0x0100, 0x2069,
+	0x0140, 0x6904, 0xa194, 0x4000, 0x0568, 0x6803, 0x1000, 0x6803,
+	0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x7110, 0x003e, 0x713c,
+	0x2160, 0x080c, 0x91a0, 0x2009, 0x004a, 0x621c, 0xa296, 0x0009,
+	0x1110, 0x2009, 0x0104, 0x080c, 0x7518, 0x080c, 0x4dc5, 0x1160,
+	0x0006, 0x2001, 0x94d8, 0x2003, 0x0002, 0x2001, 0x9200, 0x2003,
+	0x0001, 0x080c, 0x4d10, 0x000e, 0x002e, 0x001e, 0x00ee, 0x00de,
+	0x00ce, 0x0005, 0x08b0, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056,
+	0x0046, 0x0006, 0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0,
+	0x2071, 0x94e5, 0x7018, 0x2068, 0x8dff, 0x0198, 0x68a0, 0xa406,
+	0x0118, 0x6854, 0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540,
+	0x6e48, 0x2d60, 0x080c, 0x457f, 0x0120, 0x080c, 0x7238, 0xa085,
+	0x0001, 0x012e, 0x000e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de,
+	0x00ee, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x681d,
+	0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
+	0x60c3, 0x0008, 0x080c, 0x6f0b, 0x014e, 0x015e, 0x0005, 0x0156,
+	0x0146, 0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3,
+	0x0000, 0x20a9, 0x0006, 0x2011, 0x9240, 0x2019, 0x9241, 0x23a6,
+	0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x6fff, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x6f0b, 0x014e,
+	0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b,
+	0x080c, 0x6881, 0x080c, 0x6897, 0x7810, 0x0006, 0xa080, 0x0015,
+	0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080, 0x0004,
+	0x8003, 0x60c2, 0x000e, 0xa080, 0x0001, 0x2004, 0x7812, 0x080c,
+	0x6f0b, 0x002e, 0x001e, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146,
+	0x20a1, 0x020b, 0x080c, 0x681d, 0x20a3, 0x6200, 0x20a3, 0x0000,
+	0x20a3, 0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x6f0b,
+	0x014e, 0x015e, 0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1,
+	0x020b, 0x080c, 0x681d, 0x7810, 0x0006, 0xa080, 0x0017, 0x2098,
+	0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x000e,
+	0xa080, 0x0001, 0x2004, 0x7812, 0x080c, 0x6f0b, 0x002e, 0x001e,
+	0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091,
+	0x8000, 0x2071, 0x94e5, 0x700c, 0x2060, 0x8cff, 0x0168, 0x080c,
+	0x84c8, 0x1110, 0x080c, 0x7776, 0x600c, 0x0006, 0x080c, 0x74f2,
+	0x080c, 0x7238, 0x00ce, 0x0c88, 0x700f, 0x0000, 0x700b, 0x0000,
+	0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6,
+	0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000,
+	0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x94e5, 0x7024, 0x2060,
+	0x8cff, 0x05a0, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x57a1,
+	0x2009, 0x0013, 0x080c, 0x7518, 0x20a9, 0x01f4, 0x6824, 0xd094,
+	0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803,
+	0x1000, 0x7803, 0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001,
+	0x0010, 0x1f04, 0x70ae, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803,
+	0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce,
+	0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x9200,
+	0x2004, 0xa096, 0x0001, 0x0550, 0xa096, 0x0004, 0x0538, 0x6817,
+	0x0008, 0x68c3, 0x0000, 0x2011, 0x40af, 0x080c, 0x5731, 0x20a9,
+	0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084,
+	0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084,
+	0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x70e9, 0x7804, 0xa084,
+	0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x000e, 0x001e,
+	0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005,
+	0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016,
+	0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
+	0x94e5, 0x703c, 0x2060, 0x8cff, 0x0904, 0x7185, 0x6817, 0x0010,
+	0x68c7, 0x0000, 0x68cb, 0x0000, 0x080c, 0x57ae, 0x080c, 0x1ef8,
+	0x0046, 0x0056, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021,
+	0x0169, 0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x11b0, 0x68c7,
+	0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020, 0x2071,
+	0x953b, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803,
+	0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0x250a, 0x005e, 0x004e,
+	0xa39d, 0x0000, 0x1150, 0x2009, 0x0049, 0x601c, 0xa086, 0x0009,
+	0x1110, 0x2009, 0x0103, 0x080c, 0x7518, 0x20a9, 0x03e8, 0x6824,
+	0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x01a0,
+	0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd094, 0x0118, 0x6827,
+	0x0002, 0x0010, 0x1f04, 0x7167, 0x7804, 0xa084, 0x1000, 0x0120,
+	0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e, 0x001e, 0x002e,
+	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6,
+	0x0126, 0x2091, 0x8000, 0x2069, 0x94e5, 0x6a06, 0x012e, 0x00de,
+	0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x94e5, 0x6a32,
+	0x012e, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006,
+	0x0126, 0x2071, 0x94e5, 0x7614, 0x2660, 0x2678, 0x2091, 0x8000,
+	0x8cff, 0x0538, 0x601c, 0xa206, 0x1500, 0x7014, 0xac36, 0x1110,
+	0x660c, 0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
+	0x2f00, 0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00,
+	0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
+	0x849b, 0x080c, 0x7238, 0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060,
+	0x08b8, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
+	0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810, 0x20a2,
+	0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804,
+	0x7230, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
+	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000,
+	0x0478, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
+	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000,
+	0x00f8, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
+	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400,
+	0x0078, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x6a9c, 0x7810,
+	0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200,
+	0x0089, 0x60c3, 0x0020, 0x080c, 0x6f0b, 0x014e, 0x015e, 0x0005,
+	0x00e6, 0x2071, 0x94e5, 0x7020, 0xa005, 0x0110, 0x8001, 0x7022,
+	0x00ee, 0x0005, 0x20a9, 0x0008, 0x20a2, 0x1f04, 0x7244, 0x20a2,
+	0x20a2, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066,
+	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x7614, 0x2660,
+	0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0x72d2, 0x8cff, 0x0904,
+	0x72d2, 0x601c, 0xa086, 0x0006, 0x1904, 0x72cd, 0x88ff, 0x0138,
+	0x2800, 0xac06, 0x1904, 0x72cd, 0x2039, 0x0000, 0x0050, 0x6018,
+	0xa206, 0x1904, 0x72cd, 0x85ff, 0x0120, 0x6020, 0xa106, 0x1904,
+	0x72cd, 0x7024, 0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005,
+	0x01f0, 0x080c, 0x57a1, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c,
+	0x7356, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384,
+	0x1000, 0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
+	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003,
+	0x0009, 0x630a, 0x0450, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616,
+	0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012,
+	0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110,
+	0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c,
+	0x82ee, 0x0110, 0x080c, 0x9097, 0x080c, 0x849b, 0x080c, 0x7238,
+	0x88ff, 0x1190, 0x00ce, 0x0804, 0x725b, 0x2c78, 0x600c, 0x2060,
+	0x0804, 0x725b, 0xa006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce,
+	0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000, 0x00ce, 0xa8c5,
+	0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026,
+	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x7638, 0x2660,
+	0x2678, 0x8cff, 0x0904, 0x7346, 0x601c, 0xa086, 0x0006, 0x1904,
+	0x7341, 0x88ff, 0x0128, 0x2800, 0xac06, 0x1904, 0x7341, 0x0040,
+	0x6018, 0xa206, 0x15f0, 0x85ff, 0x0118, 0x6020, 0xa106, 0x15c8,
+	0x703c, 0xac06, 0x1170, 0x0036, 0x2019, 0x0001, 0x080c, 0x7110,
+	0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000,
+	0x003e, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36,
+	0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037,
+	0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
+	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0110,
+	0x080c, 0x9097, 0x080c, 0x849b, 0x88ff, 0x1190, 0x00ce, 0x0804,
+	0x72f1, 0x2c78, 0x600c, 0x2060, 0x0804, 0x72f1, 0xa006, 0x012e,
+	0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005,
+	0x6017, 0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00e6, 0x2071,
+	0x94e5, 0x2001, 0x9200, 0x2004, 0xa086, 0x0002, 0x1118, 0x7007,
+	0x0005, 0x0010, 0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6,
+	0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
+	0x94e5, 0x2c10, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200,
+	0xac06, 0x11e0, 0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034,
+	0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010,
+	0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
+	0x2678, 0x600f, 0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, 0x600c,
+	0x2060, 0x08d8, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee,
+	0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006,
+	0x0126, 0x2091, 0x8000, 0x2071, 0x94e5, 0x760c, 0x2660, 0x2678,
+	0x8cff, 0x0904, 0x7423, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
+	0x1904, 0x741e, 0x7024, 0xac06, 0x1500, 0x2069, 0x0100, 0x68c0,
+	0xa005, 0x01d8, 0x080c, 0x6f1e, 0x68c3, 0x0000, 0x080c, 0x7356,
+	0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
+	0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
+	0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0xac36, 0x1110,
+	0x660c, 0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
+	0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00,
+	0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
+	0x84b7, 0x1118, 0x080c, 0x2692, 0x00c0, 0x080c, 0x84c8, 0x1118,
+	0x080c, 0x7776, 0x0090, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0168,
+	0x601c, 0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x6003, 0x0000, 0x080c,
+	0x849b, 0x080c, 0x7238, 0x00ce, 0x0804, 0x73b0, 0x2c78, 0x600c,
+	0x2060, 0x0804, 0x73b0, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de,
+	0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x19e8, 0x080c,
+	0x9097, 0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006,
+	0xa190, 0x0020, 0x221c, 0xa39e, 0x251b, 0x1118, 0x8210, 0x8000,
+	0x0cc8, 0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0,
+	0x22c8, 0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6,
+	0x20a1, 0x020b, 0x080c, 0x68a0, 0x20a3, 0x0200, 0x20a3, 0x0014,
+	0x60c3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0x94df,
+	0x20a9, 0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x080c, 0x6f0b, 0x00de, 0x0005, 0x20a1,
+	0x020b, 0x080c, 0x68a0, 0x20a3, 0x0210, 0x20a3, 0x0018, 0x20a3,
+	0x0800, 0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3,
+	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810,
+	0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
+	0x0018, 0x080c, 0x6f0b, 0x0005, 0x2061, 0x9900, 0x2a70, 0x7064,
+	0x7046, 0x704b, 0x9900, 0x0005, 0x00e6, 0x0126, 0x2071, 0x9200,
+	0x2091, 0x8000, 0x7544, 0xa582, 0x0001, 0x0608, 0x7048, 0x2060,
+	0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x000c, 0x7058, 0xac02,
+	0x1208, 0x0cb0, 0x2061, 0x9900, 0x0c98, 0x6003, 0x0008, 0x8529,
+	0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1230, 0x754a, 0xa085,
+	0x0001, 0x012e, 0x00ee, 0x0005, 0x704b, 0x9900, 0x0cc0, 0xa006,
+	0x0cc0, 0x00e6, 0x2071, 0x9200, 0x7544, 0xa582, 0x0001, 0x0600,
+	0x7048, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x000c,
+	0x7058, 0xac02, 0x1208, 0x0cb0, 0x2061, 0x9900, 0x0c98, 0x6003,
+	0x0008, 0x8529, 0x7546, 0xaca8, 0x000c, 0x7058, 0xa502, 0x1228,
+	0x754a, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704b, 0x9900, 0x0cc8,
+	0xa006, 0x0cc8, 0xac82, 0x9900, 0x0a0c, 0x13fe, 0x2001, 0x9216,
+	0x2004, 0xac02, 0x1a0c, 0x13fe, 0xa006, 0x6006, 0x600a, 0x600e,
+	0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003, 0x0000, 0x6022,
+	0x2061, 0x9200, 0x6044, 0x8000, 0x6046, 0xa086, 0x0001, 0x0108,
+	0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0cc0,
+	0x601c, 0xa084, 0x000f, 0x0002, 0x7526, 0x752d, 0x7548, 0x7563,
+	0x8555, 0x8570, 0x858b, 0x7526, 0x752d, 0x5d3d, 0xa18e, 0x0047,
+	0x1118, 0xa016, 0x080c, 0x16c6, 0x0005, 0x0066, 0x6000, 0xa0b2,
+	0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x7546, 0x7654,
+	0x779c, 0x7546, 0x77eb, 0x7546, 0x7546, 0x7546, 0x75f6, 0x7b03,
+	0x7546, 0x7546, 0x7546, 0x7546, 0x7546, 0x7546, 0x080c, 0x13fe,
+	0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e,
+	0x0005, 0x7561, 0x7fa1, 0x7561, 0x7561, 0x7561, 0x7561, 0x7561,
+	0x7561, 0x7f89, 0x8078, 0x7561, 0x7fce, 0x8023, 0x7fce, 0x8023,
+	0x7561, 0x080c, 0x13fe, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
+	0x13fe, 0x0013, 0x006e, 0x0005, 0x757c, 0x7b3f, 0x7bf0, 0x7cb4,
+	0x7df4, 0x757c, 0x757c, 0x757c, 0x7b1b, 0x7f40, 0x7f43, 0x757c,
+	0x757c, 0x757c, 0x757c, 0x7f66, 0x080c, 0x13fe, 0x20a9, 0x000e,
+	0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420,
+	0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002,
+	0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x1f04, 0x758c,
+	0x00e6, 0x080c, 0x82ee, 0x0130, 0x6010, 0x2070, 0x7007, 0x0000,
+	0x7037, 0x0103, 0x00ee, 0x080c, 0x74f2, 0x0005, 0x00d6, 0x0036,
+	0x7330, 0xa386, 0x0200, 0x1130, 0x6018, 0x2068, 0x6813, 0x00ff,
+	0x6817, 0xfffd, 0x6010, 0xa005, 0x0130, 0x2068, 0x6807, 0x0000,
+	0x6837, 0x0103, 0x6b32, 0x080c, 0x74f2, 0x003e, 0x00de, 0x0005,
+	0x0016, 0x20a9, 0x002a, 0xae80, 0x000c, 0x2098, 0x6010, 0xa080,
+	0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a, 0x6010, 0xa080, 0x0001,
+	0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x00e6, 0x6010, 0x2004,
+	0x2070, 0x7037, 0x0103, 0x00ee, 0x080c, 0x74f2, 0x001e, 0x0005,
+	0x00d6, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6,
+	0x0015, 0x1148, 0x6018, 0x2068, 0x7038, 0x680a, 0x703c, 0x680e,
+	0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x7598, 0x2100, 0xa1b2,
+	0x003e, 0x1a0c, 0x13fe, 0x0002, 0x763c, 0x7648, 0x763c, 0x763c,
+	0x763c, 0x763c, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
+	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
+	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
+	0x763a, 0x763a, 0x763a, 0x763c, 0x763a, 0x763c, 0x763c, 0x763a,
+	0x763a, 0x763a, 0x763a, 0x763a, 0x763c, 0x763a, 0x763a, 0x763a,
+	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763c, 0x763a,
+	0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a, 0x763a,
+	0x763a, 0x763c, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c,
+	0x603e, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005,
+	0x6003, 0x0001, 0x6106, 0x080c, 0x603e, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x6462, 0x012e, 0x0005, 0x6004, 0xa0b2, 0x003e, 0x1a0c,
+	0x13fe, 0xa1b6, 0x0013, 0x0904, 0x76f0, 0xa1b6, 0x0027, 0x1904,
+	0x76b6, 0x080c, 0x6389, 0x6004, 0x080c, 0x84b7, 0x0178, 0x080c,
+	0x84c8, 0x0904, 0x76b0, 0xa08e, 0x0021, 0x0904, 0x76b3, 0xa08e,
+	0x0022, 0x05f0, 0xa08e, 0x003d, 0x05f0, 0x04a8, 0x080c, 0x2692,
+	0x2001, 0x0007, 0x080c, 0x43e3, 0x6018, 0xa080, 0x0028, 0x200c,
+	0x080c, 0x7776, 0xa186, 0x007e, 0x1148, 0x2001, 0x9232, 0x2014,
+	0xc285, 0x080c, 0x4dc5, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026,
+	0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x6127, 0x0086, 0x2041,
+	0x0000, 0x080c, 0x606d, 0x00c6, 0x6018, 0xa065, 0x0110, 0x080c,
+	0x460d, 0x00ce, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x003e, 0x002e,
+	0x001e, 0x080c, 0x441f, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005,
+	0x080c, 0x7776, 0x0cc0, 0x080c, 0x7790, 0x0ca8, 0xa186, 0x0014,
+	0x1db0, 0x080c, 0x6389, 0x080c, 0x266c, 0x080c, 0x84b7, 0x1188,
+	0x080c, 0x2692, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x7776,
+	0xa186, 0x007e, 0x1128, 0x2001, 0x9232, 0x200c, 0xc185, 0x2102,
+	0x08d0, 0x080c, 0x84c8, 0x1118, 0x080c, 0x7776, 0x08a0, 0x6004,
+	0xa08e, 0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0x9296, 0x2079,
+	0x0000, 0x080c, 0x2924, 0x00fe, 0x00ee, 0x0828, 0x6004, 0xa08e,
+	0x0021, 0x0d50, 0xa08e, 0x0022, 0x090c, 0x7790, 0x0804, 0x76ab,
+	0x2008, 0x0002, 0x7732, 0x7733, 0x7736, 0x7739, 0x773c, 0x773f,
+	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
+	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
+	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
+	0x7742, 0x7747, 0x7730, 0x7750, 0x7747, 0x7730, 0x7730, 0x7730,
+	0x7730, 0x7730, 0x7747, 0x7747, 0x7730, 0x7730, 0x7730, 0x7730,
+	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730,
+	0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7730, 0x7747,
+	0x080c, 0x13fe, 0x00a0, 0x2001, 0x000b, 0x0418, 0x2001, 0x0003,
+	0x0400, 0x2001, 0x0005, 0x00e8, 0x2001, 0x0001, 0x00d0, 0x2001,
+	0x0009, 0x00b8, 0x080c, 0x13fe, 0x0098, 0x080c, 0x43e3, 0x080c,
+	0x6389, 0x6003, 0x0002, 0x6017, 0x0028, 0x080c, 0x6462, 0x0040,
+	0x080c, 0x6389, 0x6003, 0x0004, 0x6017, 0x0028, 0x080c, 0x6462,
+	0x0005, 0x080c, 0x43e3, 0x080c, 0x6389, 0x6003, 0x0002, 0x0036,
+	0x2019, 0x925c, 0x2304, 0xa084, 0xff00, 0x1118, 0x2019, 0x0028,
+	0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec8, 0x8003, 0x801b, 0x831b,
+	0xa318, 0x6316, 0x003e, 0x080c, 0x6462, 0x0c10, 0x00e6, 0x080c,
+	0x82ee, 0x0188, 0x6010, 0x2070, 0x7007, 0x0000, 0x0016, 0x6004,
+	0xa08e, 0x0021, 0x0150, 0xa08e, 0x003d, 0x0138, 0x001e, 0x7037,
+	0x0103, 0x7033, 0x0100, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cd8,
+	0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103,
+	0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6, 0x6618, 0x2668, 0x6804,
+	0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c, 0x1a0c, 0x13fe, 0x6604,
+	0xa6b6, 0x0028, 0x1118, 0x080c, 0x84f2, 0x0468, 0x6604, 0xa6b6,
+	0x0029, 0x1118, 0x080c, 0x8509, 0x0430, 0x6604, 0xa6b6, 0x001f,
+	0x1118, 0x080c, 0x757e, 0x00f8, 0x6604, 0xa6b6, 0x0000, 0x1118,
+	0x080c, 0x75e0, 0x00c0, 0x6604, 0xa6b6, 0x0022, 0x1118, 0x080c,
+	0x75a6, 0x0088, 0x6604, 0xa6b6, 0x003d, 0x1118, 0x080c, 0x75c0,
+	0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6, 0x0016,
+	0x1118, 0x0804, 0x7983, 0x0005, 0x080c, 0x7526, 0x0ce0, 0x7805,
+	0x7808, 0x7805, 0x7844, 0x7805, 0x7923, 0x7805, 0x7805, 0x7805,
+	0x795b, 0x7805, 0x7971, 0xa1b6, 0x0048, 0x0140, 0x20e1, 0x0005,
+	0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005, 0x00e6, 0xacf0,
+	0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee, 0x080c,
+	0x74f2, 0x0005, 0x080c, 0x74f2, 0x0005, 0xe000, 0xe000, 0x0005,
+	0x00e6, 0x2071, 0x9200, 0x7080, 0xa086, 0x0074, 0x11f0, 0x080c,
+	0x8ebb, 0x1170, 0x00d6, 0x6018, 0x2068, 0x00e9, 0x00de, 0x2001,
+	0x0006, 0x080c, 0x43e3, 0x080c, 0x2692, 0x080c, 0x74f2, 0x0088,
+	0x2001, 0x000a, 0x080c, 0x43e3, 0x080c, 0x2692, 0x6003, 0x0001,
+	0x6007, 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c,
+	0x7910, 0x00ee, 0x0005, 0x6800, 0xd084, 0x0168, 0x2001, 0x0000,
+	0x080c, 0x43d1, 0x2069, 0x9251, 0x6804, 0xd0a4, 0x0120, 0x2001,
+	0x0006, 0x080c, 0x43f1, 0x0005, 0x00d6, 0x2011, 0x9220, 0x2204,
+	0xa086, 0x0074, 0x1904, 0x790b, 0x080c, 0x7a64, 0x6018, 0x2068,
+	0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x0198, 0xa286, 0x0080,
+	0x1904, 0x789c, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
+	0x0588, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833, 0x0200,
+	0x0448, 0x00d6, 0x00e6, 0x00f6, 0x6813, 0x00ff, 0x6817, 0xfffe,
+	0x2071, 0x9232, 0x2e04, 0xa085, 0x0003, 0x2072, 0x2071, 0x9780,
+	0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0x921b, 0x206a,
+	0x78e6, 0x8e70, 0x2e04, 0x2069, 0x921c, 0x206a, 0x78ea, 0x7832,
+	0x7836, 0xa084, 0x00ff, 0x2008, 0x080c, 0x2435, 0x00fe, 0x00ee,
+	0x00de, 0x00f8, 0x2001, 0x0006, 0x080c, 0x43e3, 0x080c, 0x2692,
+	0x080c, 0x74f2, 0x0804, 0x790e, 0x6010, 0xa005, 0x0130, 0x2068,
+	0x6838, 0xd0f4, 0x0110, 0x0804, 0x7862, 0x2001, 0x0004, 0x080c,
+	0x43e3, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x603e, 0x0804,
+	0x790e, 0x685c, 0xd0e4, 0x01c8, 0x080c, 0x8531, 0x080c, 0x4dc5,
+	0x0110, 0xd0dc, 0x19b8, 0x2011, 0x9232, 0x2204, 0xc0ad, 0x2012,
+	0x2001, 0x94c8, 0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000,
+	0x080c, 0x2460, 0x78e2, 0x00fe, 0x0828, 0x080c, 0x854a, 0x2011,
+	0x9232, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0x8fa4, 0x000e,
+	0x1904, 0x7892, 0xc0b5, 0x2012, 0x2001, 0x0000, 0x080c, 0x43d1,
+	0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x7932,
+	0x7936, 0x00fe, 0x080c, 0x2435, 0x2001, 0x9214, 0x2004, 0x2009,
+	0x0000, 0x080c, 0x240b, 0x2001, 0x9213, 0x2102, 0x8108, 0x080c,
+	0x4400, 0x2c00, 0x00ce, 0x1904, 0x7892, 0x601a, 0x2001, 0x0002,
+	0x080c, 0x43e3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002,
+	0x080c, 0x603e, 0x0018, 0x2001, 0x0001, 0x0011, 0x00de, 0x0005,
+	0x0006, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003, 0x000e, 0x0130,
+	0xa005, 0x0120, 0x2001, 0x0007, 0x080c, 0x43e3, 0x080c, 0x2692,
+	0x080c, 0x74f2, 0x0005, 0x00e6, 0x2071, 0x9200, 0x7080, 0xa086,
+	0x0014, 0x1548, 0x7000, 0xa086, 0x0003, 0x1128, 0x6010, 0xa005,
+	0x1110, 0x080c, 0x370a, 0x00d6, 0x6018, 0x2068, 0x080c, 0x44c7,
+	0x080c, 0x7833, 0x00de, 0x080c, 0x7a6e, 0x11a8, 0x2001, 0x0006,
+	0x080c, 0x43e3, 0x00e6, 0x6010, 0xa005, 0x0138, 0x2070, 0x7007,
+	0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c, 0x2692,
+	0x080c, 0x74f2, 0x0030, 0x080c, 0x7776, 0x2001, 0x0000, 0x080c,
+	0x7910, 0x00ee, 0x0005, 0x2011, 0x9220, 0x2204, 0xa086, 0x0014,
+	0x1158, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007,
+	0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, 0x7910,
+	0x0005, 0x2011, 0x9220, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001,
+	0x0007, 0x080c, 0x43e3, 0x080c, 0x74f2, 0x0020, 0x2001, 0x0001,
+	0x080c, 0x7910, 0x0005, 0x000b, 0x0005, 0x7805, 0x7991, 0x7805,
+	0x79b5, 0x7805, 0x7a1a, 0x7805, 0x7802, 0x7805, 0x7a2f, 0x7805,
+	0x7a41, 0x00c6, 0x080c, 0x7a53, 0x1178, 0x2001, 0x0000, 0x080c,
+	0x43d1, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007,
+	0x0002, 0x080c, 0x603e, 0x0078, 0x2009, 0x978f, 0x2104, 0xa084,
+	0xff00, 0xa086, 0x1900, 0x1118, 0x080c, 0x74f2, 0x0020, 0x2001,
+	0x0001, 0x080c, 0x7910, 0x00ce, 0x0005, 0x080c, 0x7a61, 0x00d6,
+	0x2069, 0x94d7, 0x2d04, 0xa005, 0x0168, 0x6018, 0x2068, 0x68a0,
+	0xa086, 0x007e, 0x1138, 0x2069, 0x921c, 0x2d04, 0x8000, 0x206a,
+	0x00de, 0x0010, 0x00de, 0x0078, 0x2001, 0x0000, 0x080c, 0x43d1,
+	0x2001, 0x0002, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007, 0x0002,
+	0x080c, 0x603e, 0x0400, 0x080c, 0x7776, 0x2009, 0x978e, 0x2134,
+	0xa6b4, 0x00ff, 0xa686, 0x0005, 0x01b8, 0x2009, 0x978f, 0x2104,
+	0xa084, 0xff00, 0xa086, 0x1900, 0x1150, 0xa686, 0x0009, 0x0160,
+	0x2001, 0x0004, 0x080c, 0x43e3, 0x080c, 0x74f2, 0x0020, 0x2001,
+	0x0001, 0x080c, 0x7910, 0x0005, 0x00d6, 0x6010, 0x2068, 0x080c,
+	0x82ee, 0x0128, 0x6838, 0xd0fc, 0x0110, 0x00de, 0x0c80, 0x6018,
+	0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0140, 0x8001, 0x6842,
+	0x6017, 0x000a, 0x6007, 0x0016, 0x00de, 0x0c28, 0x080c, 0x266c,
+	0x00de, 0x08e8, 0x080c, 0x7a61, 0x1158, 0x2001, 0x0004, 0x080c,
+	0x43e3, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x603e, 0x0030,
+	0x080c, 0x7776, 0x2001, 0x0000, 0x080c, 0x7910, 0x0005, 0x0489,
+	0x1158, 0x2001, 0x0008, 0x080c, 0x43e3, 0x6003, 0x0001, 0x6007,
+	0x0005, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001, 0x080c, 0x7910,
+	0x0005, 0x00f9, 0x1158, 0x2001, 0x000a, 0x080c, 0x43e3, 0x6003,
+	0x0001, 0x6007, 0x0001, 0x080c, 0x603e, 0x0020, 0x2001, 0x0001,
+	0x080c, 0x7910, 0x0005, 0x2009, 0x978e, 0x2104, 0xa086, 0x0003,
+	0x1138, 0x2009, 0x978f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00,
+	0x0005, 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006,
+	0x2164, 0x080c, 0x4443, 0x001e, 0x00ce, 0x0005, 0x00e6, 0x2071,
+	0x978c, 0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800,
+	0x1188, 0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100,
+	0x1138, 0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010,
+	0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076,
+	0x0056, 0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029,
+	0x94ee, 0x252c, 0x2021, 0x94f4, 0x2424, 0x2061, 0x9900, 0x2071,
+	0x9200, 0x7244, 0x7064, 0xa202, 0x1688, 0x080c, 0x90ee, 0x0540,
+	0x671c, 0xa786, 0x0001, 0x0520, 0xa786, 0x0007, 0x0508, 0x2500,
+	0xac06, 0x01f0, 0x2400, 0xac06, 0x01d8, 0x00c6, 0x6000, 0xa086,
+	0x0004, 0x1110, 0x080c, 0x1788, 0x6010, 0x2068, 0x080c, 0x82ee,
+	0x0160, 0xa786, 0x0003, 0x11e0, 0x6837, 0x0103, 0x6b4a, 0x6847,
+	0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x080c, 0x849b, 0x00ce,
+	0xace0, 0x000c, 0x7058, 0xac02, 0x1208, 0x0858, 0x012e, 0x000e,
+	0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005,
+	0xa786, 0x0006, 0x1118, 0x080c, 0x9097, 0x0c38, 0xa786, 0x0009,
+	0x19d8, 0x2009, 0x0106, 0x080c, 0x7518, 0x0c08, 0x220c, 0x2304,
+	0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x7aee, 0xa006, 0x0005,
+	0x2304, 0xa102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000,
+	0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x003e, 0x1a0c, 0x13fe,
+	0x080c, 0x84b7, 0x0120, 0x080c, 0x84c8, 0x0150, 0x0010, 0x080c,
+	0x2692, 0x080c, 0x6389, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005,
+	0x080c, 0x7776, 0x0cb0, 0xa182, 0x0040, 0x0002, 0x7b31, 0x7b31,
+	0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31, 0x7b31,
+	0x7b31, 0x7b33, 0x7b33, 0x7b33, 0x7b33, 0x7b31, 0x7b31, 0x7b31,
+	0x7b33, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c, 0x5ff8,
+	0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005, 0xa186,
+	0x0013, 0x1128, 0x6004, 0xa082, 0x0040, 0x0804, 0x7bc5, 0xa186,
+	0x0027, 0x11d0, 0x080c, 0x6389, 0x080c, 0x266c, 0x00d6, 0x6110,
+	0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029,
+	0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c,
+	0x74f2, 0x080c, 0x6462, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004,
+	0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045,
+	0x0120, 0xa186, 0x0047, 0x190c, 0x13fe, 0x2001, 0x0109, 0x2004,
+	0xd084, 0x0198, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026,
+	0x080c, 0x5ee3, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000,
+	0xa086, 0x0002, 0x1110, 0x0804, 0x7bf0, 0x080c, 0x7526, 0x0005,
+	0x0002, 0x7ba6, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4,
+	0x7ba4, 0x7ba4, 0x7ba4, 0x7ba4, 0x7bbe, 0x7bbe, 0x7bbe, 0x7bbe,
+	0x7ba4, 0x7ba4, 0x7ba4, 0x7bbe, 0x080c, 0x13fe, 0x080c, 0x6389,
+	0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103,
+	0x684b, 0x0006, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f,
+	0x00de, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389,
+	0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x0002, 0x7bdb, 0x7bd9,
+	0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9, 0x7bd9,
+	0x7bd9, 0x7be9, 0x7be9, 0x7be9, 0x7be9, 0x7bd9, 0x7bd9, 0x7bd9,
+	0x7be9, 0x080c, 0x13fe, 0x080c, 0x6389, 0x6003, 0x0002, 0x080c,
+	0x6462, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a,
+	0x0005, 0x080c, 0x6389, 0x6003, 0x000f, 0x080c, 0x6462, 0x0005,
+	0xa182, 0x0040, 0x0002, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06,
+	0x7c08, 0x7c8a, 0x7ca9, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06,
+	0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x7c06, 0x080c, 0x13fe,
+	0x00e6, 0x00d6, 0x2071, 0x978c, 0x6110, 0x2168, 0x7614, 0xa6b4,
+	0x0fff, 0x86ff, 0x0904, 0x7c70, 0xa68c, 0x0c00, 0x0120, 0x7318,
+	0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0190,
+	0xa186, 0x0028, 0x1128, 0x080c, 0x84a6, 0x684b, 0x001c, 0x0060,
+	0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
+	0x0007, 0x0010, 0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e,
+	0xd6c4, 0x01b0, 0xa686, 0x0100, 0x1138, 0x2001, 0x9799, 0x2004,
+	0xa005, 0x1110, 0xc6c4, 0x0868, 0x7328, 0x732c, 0x6b56, 0x0036,
+	0x2308, 0x2019, 0x9798, 0xad90, 0x0019, 0x080c, 0x80e6, 0x003e,
+	0xd6cc, 0x0560, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071,
+	0x9798, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x80e6,
+	0x00e8, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78,
+	0x00f6, 0x2d78, 0x080c, 0x808b, 0x00fe, 0x080c, 0x80d6, 0x0080,
+	0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0130,
+	0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x7de6, 0x080c, 0x4809,
+	0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e, 0x00de, 0x00ee, 0x080c,
+	0x74f2, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079, 0x978c, 0x7c04,
+	0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0120,
+	0x6003, 0x0002, 0x00fe, 0x0005, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
+	0x00fe, 0x2c10, 0x080c, 0x1c88, 0x080c, 0x605b, 0x080c, 0x651c,
+	0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
+	0x2c10, 0x080c, 0x16c6, 0x0005, 0xa182, 0x0040, 0x0002, 0x7cca,
+	0x7cca, 0x7cca, 0x7cca, 0x7cca, 0x7ccc, 0x7d54, 0x7cca, 0x7cca,
+	0x7d6a, 0x7dc1, 0x7cca, 0x7cca, 0x7cca, 0x7cca, 0x7dcc, 0x7cca,
+	0x7cca, 0x7cca, 0x080c, 0x13fe, 0x0076, 0x00f6, 0x00e6, 0x00d6,
+	0x2071, 0x978c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
+	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
+	0x86ff, 0x0904, 0x7d4f, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120,
+	0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x7d4f,
+	0x080c, 0x147c, 0x090c, 0x13fe, 0x2d00, 0x784a, 0x7f4c, 0xc7cd,
+	0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840,
+	0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c,
+	0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, 0xa186, 0x0028,
+	0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015,
+	0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000,
+	0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0160,
+	0x7328, 0x732c, 0x6b56, 0x0036, 0x2308, 0x2019, 0x9798, 0xad90,
+	0x0019, 0x080c, 0x80e6, 0x003e, 0xd6cc, 0x01c8, 0x7124, 0x695a,
+	0xa192, 0x0021, 0x1250, 0x2071, 0x9798, 0x831c, 0x2300, 0xae18,
+	0xad90, 0x001d, 0x080c, 0x80e6, 0x0050, 0x7838, 0xd0fc, 0x0120,
+	0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x808b, 0x00de,
+	0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6, 0x6003, 0x0003, 0x2079,
+	0x978c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12,
+	0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10, 0x080c, 0x1c88, 0x080c,
+	0x6f04, 0x0005, 0x00d6, 0x6003, 0x0002, 0x080c, 0x641b, 0x080c,
+	0x651c, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904, 0x7dbf, 0xd1cc,
+	0x0540, 0x6948, 0x6838, 0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006,
+	0x6850, 0x0006, 0xad90, 0x000d, 0xa198, 0x000d, 0x2009, 0x0023,
+	0x0156, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210, 0x1f04, 0x7d8a,
+	0x015e, 0x000e, 0x6852, 0x000e, 0x684e, 0x001e, 0x2168, 0x080c,
+	0x14a3, 0x0418, 0x0016, 0x080c, 0x14a3, 0x00de, 0x080c, 0x80d6,
+	0x00e0, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002,
+	0x0180, 0xa086, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd1dc,
+	0x0118, 0x684b, 0x0015, 0x0038, 0xd1d4, 0x0118, 0x684b, 0x0007,
+	0x0010, 0x684b, 0x0000, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de,
+	0x0005, 0x2019, 0x0001, 0x080c, 0x7110, 0x6003, 0x0002, 0x080c,
+	0x641b, 0x080c, 0x651c, 0x0005, 0x080c, 0x641b, 0x080c, 0x266c,
+	0x00d6, 0x6110, 0x2168, 0x080c, 0x82ee, 0x0150, 0x6837, 0x0103,
+	0x684b, 0x0029, 0x6847, 0x0000, 0x080c, 0x4809, 0x080c, 0x848f,
+	0x00de, 0x080c, 0x74f2, 0x080c, 0x651c, 0x0005, 0x684b, 0x0015,
+	0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a, 0xa189,
+	0x0000, 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002, 0x7e0a,
+	0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0c, 0x7e0a, 0x7eac, 0x7eb4,
+	0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a, 0x7e0a,
+	0x7e0a, 0x7e0a, 0x080c, 0x13fe, 0x0076, 0x00f6, 0x00e6, 0x00d6,
+	0x2071, 0x978c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
+	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x8211, 0x6a3e,
+	0x86ff, 0x0904, 0x7e9d, 0xa694, 0xff00, 0xa284, 0x0c00, 0x0120,
+	0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300, 0x0904, 0x7e9b,
+	0xa686, 0x0100, 0x1140, 0x2001, 0x9799, 0x2004, 0xa005, 0x1118,
+	0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x147c, 0x090c, 0x13fe, 0x2d00,
+	0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838,
+	0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
+	0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
+	0x0002, 0x0180, 0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060,
+	0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b,
+	0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
+	0x6856, 0xa01e, 0xd6c4, 0x0160, 0x7328, 0x732c, 0x6b56, 0x0036,
+	0x2308, 0x2019, 0x9798, 0xad90, 0x0019, 0x080c, 0x80e6, 0x003e,
+	0xd6cc, 0x01c8, 0x7124, 0x695a, 0xa192, 0x0021, 0x1250, 0x2071,
+	0x9798, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x80e6,
+	0x0050, 0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78,
+	0x2d78, 0x080c, 0x808b, 0xd6dc, 0x1110, 0xa006, 0x0030, 0x2001,
+	0x0001, 0x2071, 0x978c, 0x7218, 0x731c, 0x080c, 0x1700, 0x00de,
+	0x00ee, 0x00fe, 0x007e, 0x0005, 0x20e1, 0x0005, 0x3d18, 0x3e20,
+	0x2c10, 0x080c, 0x16c6, 0x0005, 0x00d6, 0x6003, 0x0002, 0x6110,
+	0x2168, 0x694c, 0xd1e4, 0x0904, 0x7f3e, 0xd1cc, 0x0904, 0x7f17,
+	0x6948, 0x6838, 0xd0fc, 0x0590, 0x0016, 0x684c, 0x0006, 0x6850,
+	0x0006, 0x684c, 0xd0ac, 0x0180, 0x6810, 0x6914, 0xa115, 0x0160,
+	0x080c, 0x7de6, 0x00f6, 0x6948, 0x2178, 0x6848, 0x784a, 0x6860,
+	0x7862, 0x685c, 0x785e, 0x00fe, 0x6948, 0xad90, 0x000d, 0xa198,
+	0x000d, 0x2009, 0x0023, 0x0156, 0x21a8, 0x2304, 0x2012, 0x8318,
+	0x8210, 0x1f04, 0x7ee5, 0x015e, 0x000e, 0x6852, 0x000e, 0x684e,
+	0x001e, 0x2168, 0x080c, 0x14a3, 0x0804, 0x7f3c, 0x0016, 0x684c,
+	0xd0ac, 0x0190, 0x6810, 0x6914, 0xa115, 0x0170, 0x080c, 0x7de6,
+	0x00f6, 0x6948, 0x2178, 0x6848, 0x784a, 0x6860, 0x7862, 0x685c,
+	0x785e, 0x684c, 0x784e, 0x00fe, 0x6948, 0xa188, 0x0013, 0x684c,
+	0x200a, 0x080c, 0x14a3, 0x00de, 0x080c, 0x80d6, 0x0428, 0x6837,
+	0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086,
+	0x0028, 0x1118, 0x684b, 0x001c, 0x00a8, 0xd1dc, 0x0118, 0x684b,
+	0x0015, 0x0080, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b,
+	0x0000, 0x684c, 0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110,
+	0x080c, 0x7de6, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005,
+	0x080c, 0x6389, 0x0010, 0x080c, 0x641b, 0x080c, 0x82ee, 0x0198,
+	0x00d6, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0x920c, 0x210c,
+	0xd18c, 0x1188, 0xd184, 0x1160, 0x6108, 0x694a, 0x6847, 0x0000,
+	0x080c, 0x4809, 0x00de, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005,
+	0x684b, 0x0004, 0x0c98, 0x684b, 0x0004, 0x0c80, 0xa182, 0x0040,
+	0x0002, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7e, 0x7f7c,
+	0x7f81, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c,
+	0x7f7c, 0x7f7c, 0x7f7c, 0x7f7c, 0x080c, 0x13fe, 0x080c, 0x74f2,
+	0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x16c6, 0x002e, 0x000e,
+	0x0005, 0xa182, 0x0085, 0x0002, 0x7f95, 0x7f93, 0x7f93, 0x7f93,
+	0x7f93, 0x7f93, 0x7f93, 0x080c, 0x13fe, 0x6003, 0x000b, 0x6106,
+	0x080c, 0x5ff8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e,
+	0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c,
+	0x13fe, 0xa08a, 0x008c, 0x1a0c, 0x13fe, 0xa082, 0x0085, 0x0072,
+	0xa186, 0x0027, 0x0120, 0xa186, 0x0014, 0x190c, 0x13fe, 0x080c,
+	0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0x7fc5, 0x7fc7,
+	0x7fc7, 0x7fc5, 0x7fc5, 0x7fc5, 0x7fc5, 0x080c, 0x13fe, 0x080c,
+	0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa186, 0x0013,
+	0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x0492, 0xa186, 0x0027,
+	0x11e8, 0x080c, 0x6389, 0x080c, 0x266c, 0x00d6, 0x6010, 0x2068,
+	0x080c, 0x82ee, 0x0150, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b,
+	0x0029, 0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, 0x74f2,
+	0x080c, 0x6462, 0x0005, 0x080c, 0x7526, 0x0ce0, 0xa186, 0x0014,
+	0x1dd0, 0x080c, 0x6389, 0x00d6, 0x6010, 0x2068, 0x080c, 0x82ee,
+	0x0d60, 0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0006, 0x0c08,
+	0x8011, 0x800f, 0x800f, 0x800f, 0x800f, 0x800f, 0x801a, 0x080c,
+	0x13fe, 0x080c, 0x6389, 0x6017, 0x0014, 0x6003, 0x000c, 0x080c,
+	0x6462, 0x0005, 0x080c, 0x6389, 0x6017, 0x0014, 0x6003, 0x000e,
+	0x080c, 0x6462, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085,
+	0x0208, 0x001a, 0x080c, 0x7526, 0x0005, 0x8034, 0x8034, 0x8034,
+	0x8034, 0x8036, 0x8057, 0x8034, 0x080c, 0x13fe, 0x00d6, 0x080c,
+	0x848f, 0x080c, 0x82ee, 0x01b8, 0x6010, 0x2068, 0x6837, 0x0103,
+	0x6850, 0xd0b4, 0x0118, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118,
+	0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x852d, 0x6847,
+	0x0000, 0x080c, 0x4809, 0x080c, 0x74f2, 0x00de, 0x0005, 0x00d6,
+	0x6010, 0x2068, 0x080c, 0x82ee, 0x01b8, 0x6837, 0x0103, 0x6850,
+	0xd0b4, 0x0118, 0x684b, 0x0006, 0x0048, 0xd0bc, 0x0118, 0x684b,
+	0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x852d, 0x6847, 0x0000,
+	0x080c, 0x4809, 0x080c, 0x848f, 0x00de, 0x080c, 0x74f2, 0x0005,
+	0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186, 0x0027,
+	0x0118, 0x080c, 0x7526, 0x0030, 0x080c, 0x6389, 0x080c, 0x849b,
+	0x080c, 0x6462, 0x0005, 0x0056, 0x0066, 0x00d6, 0x00f6, 0x2029,
+	0x0001, 0xa182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130,
+	0x2069, 0x9798, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020, 0xaf90,
+	0x001d, 0x080c, 0x80e6, 0xa6b2, 0x0020, 0x7804, 0xa06d, 0x0110,
+	0x080c, 0x14a3, 0x080c, 0x147c, 0x0500, 0x8528, 0x6837, 0x0110,
+	0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a, 0x003d, 0x1228, 0x2608,
+	0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2, 0x003c, 0x2009, 0x003c,
+	0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28, 0x00fe, 0x852f, 0xa5ad,
+	0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028, 0x00fe, 0x852f, 0xa5ad,
+	0x0003, 0x7d36, 0x00de, 0x006e, 0x005e, 0x0005, 0x00f6, 0x8dff,
+	0x0158, 0x6804, 0xa07d, 0x0130, 0x6807, 0x0000, 0x080c, 0x4809,
+	0x2f68, 0x0cb8, 0x080c, 0x4809, 0x00fe, 0x0005, 0x0156, 0xa184,
+	0x0001, 0x0108, 0x8108, 0x810c, 0x21a8, 0x2304, 0x8007, 0x2012,
+	0x8318, 0x8210, 0x1f04, 0x80ed, 0x015e, 0x0005, 0x0126, 0x2091,
+	0x8000, 0x601c, 0xa084, 0x000f, 0x0013, 0x012e, 0x0005, 0x8117,
+	0x8109, 0x8112, 0x812e, 0x8109, 0x8112, 0x810b, 0x8112, 0x8109,
+	0x5e80, 0x080c, 0x13fe, 0x0036, 0x2019, 0x0010, 0x080c, 0x8d4e,
+	0x003e, 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0x00d6,
+	0x6010, 0x2068, 0x080c, 0x82ee, 0x0178, 0xa00e, 0x2001, 0x0005,
+	0x080c, 0x492c, 0x080c, 0x852d, 0x080c, 0x4809, 0x080c, 0x74f2,
+	0xa085, 0x0001, 0x00de, 0x0005, 0xa006, 0x0ce0, 0x6000, 0xa08a,
+	0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x8145, 0x8160, 0x8147,
+	0x816f, 0x815d, 0x8145, 0x8112, 0x8117, 0x8117, 0x8112, 0x8112,
+	0x8112, 0x8112, 0x8112, 0x8112, 0x8112, 0x080c, 0x13fe, 0x00d6,
+	0x6010, 0x2068, 0x080c, 0x82ee, 0x0110, 0x080c, 0x852d, 0x00de,
+	0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x5ff8,
+	0x080c, 0x6462, 0xa085, 0x0001, 0x0005, 0x080c, 0x1788, 0x0c38,
+	0x00e6, 0x2071, 0x94e5, 0x7024, 0xac06, 0x1110, 0x080c, 0x708d,
+	0x080c, 0x6fab, 0x00ee, 0x19d8, 0x080c, 0x8112, 0x0005, 0x0036,
+	0x00e6, 0x2071, 0x94e5, 0x703c, 0xac06, 0x1138, 0x2019, 0x0000,
+	0x080c, 0x7110, 0x00ee, 0x003e, 0x0850, 0x080c, 0x7366, 0x00ee,
+	0x003e, 0x1928, 0x080c, 0x8112, 0x0005, 0x00c6, 0x601c, 0xa084,
+	0x000f, 0x0013, 0x00ce, 0x0005, 0x819a, 0x81f7, 0x829a, 0x819e,
+	0x819a, 0x819a, 0x8d44, 0x74f2, 0x81f7, 0x080c, 0x84c8, 0x1110,
+	0x080c, 0x7776, 0x0005, 0x6017, 0x0001, 0x0005, 0x6000, 0xa08a,
+	0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x81b5, 0x81b7, 0x81d5,
+	0x81e7, 0x81f4, 0x81b5, 0x819a, 0x819a, 0x819a, 0x81e7, 0x81e7,
+	0x81b5, 0x81b5, 0x81b5, 0x81b5, 0x81f1, 0x080c, 0x13fe, 0x00e6,
+	0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052, 0x2071, 0x94e5, 0x7024,
+	0xac06, 0x0180, 0x080c, 0x6fab, 0x6007, 0x0085, 0x6003, 0x000b,
+	0x601f, 0x0002, 0x6017, 0x0014, 0x080c, 0x5ff8, 0x080c, 0x6462,
+	0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068,
+	0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b,
+	0x601f, 0x0002, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0005, 0x00d6,
+	0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de,
+	0x0005, 0x080c, 0x74f2, 0x0005, 0x080c, 0x1788, 0x08f0, 0x6000,
+	0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x820e, 0x819b,
+	0x8210, 0x820e, 0x8210, 0x820e, 0x820e, 0x820e, 0x8195, 0x8195,
+	0x820e, 0x820e, 0x820e, 0x820e, 0x820e, 0x820e, 0x080c, 0x13fe,
+	0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a,
+	0x000c, 0x1a0c, 0x13fe, 0x000b, 0x0005, 0x8229, 0x824a, 0x8229,
+	0x824a, 0x8229, 0x824a, 0x822b, 0x8232, 0x8229, 0x824a, 0x8229,
+	0x8243, 0x080c, 0x13fe, 0x6004, 0xa08e, 0x0004, 0x01b0, 0xa08e,
+	0x0002, 0x0198, 0x6004, 0x080c, 0x84c8, 0x0904, 0x8292, 0xa08e,
+	0x0021, 0x0904, 0x8296, 0xa08e, 0x0022, 0x0904, 0x8292, 0xa08e,
+	0x003d, 0x0904, 0x8296, 0x080c, 0x266c, 0x080c, 0x7776, 0x080c,
+	0x74f2, 0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0598,
+	0xa186, 0x0002, 0x11f8, 0x6018, 0x2068, 0x2001, 0x9232, 0x2004,
+	0xd0ac, 0x11c0, 0x68a0, 0xd0bc, 0x11a8, 0x6840, 0xa084, 0x00ff,
+	0xa005, 0x0180, 0x8001, 0x6842, 0x6013, 0x0000, 0x601f, 0x0007,
+	0x6017, 0x0398, 0x080c, 0x749c, 0x0128, 0x2d00, 0x601a, 0x601f,
+	0x0001, 0x0088, 0x00de, 0x00ce, 0x080c, 0x7776, 0x080c, 0x266c,
+	0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x2692, 0x012e, 0x00ee,
+	0x080c, 0x74f2, 0x0005, 0x2001, 0x0002, 0x080c, 0x43e3, 0x6003,
+	0x0001, 0x6007, 0x0002, 0x080c, 0x603e, 0x080c, 0x6462, 0x00de,
+	0x00ce, 0x0c80, 0x080c, 0x7776, 0x0804, 0x8247, 0x080c, 0x7790,
+	0x0804, 0x8247, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x13fe, 0x000b,
+	0x0005, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1, 0x82b1,
+	0x82b1, 0x82b1, 0x819a, 0x82b1, 0x819b, 0x82b3, 0x819b, 0x82bc,
+	0x82b1, 0x080c, 0x13fe, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c,
+	0x5ff8, 0x080c, 0x6462, 0x0005, 0x080c, 0x848f, 0x0479, 0x01d8,
+	0x080c, 0x266c, 0x00d6, 0x0451, 0x0150, 0x6010, 0x2068, 0x6837,
+	0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x080c, 0x4809, 0x00de,
+	0x601f, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x603e,
+	0x080c, 0x6462, 0x0010, 0x080c, 0x74f2, 0x0005, 0xa284, 0x0003,
+	0x1158, 0xa282, 0x9900, 0x0240, 0x2001, 0x9216, 0x2004, 0xa202,
+	0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210,
+	0x82ff, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126,
+	0x2091, 0x8000, 0x2061, 0x9900, 0x2071, 0x9200, 0x7344, 0x7064,
+	0xa302, 0x1290, 0x601c, 0xa206, 0x1148, 0x080c, 0x84c8, 0x1110,
+	0x080c, 0x7776, 0x00c6, 0x080c, 0x74f2, 0x00ce, 0xace0, 0x000c,
+	0x7058, 0xac02, 0x1208, 0x0c50, 0x012e, 0x000e, 0x003e, 0x00ce,
+	0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016, 0xa188, 0x936e, 0x210c,
+	0x81ff, 0x0170, 0x2061, 0x9900, 0x2071, 0x9200, 0x0016, 0x080c,
+	0x749c, 0x001e, 0x0138, 0x611a, 0x080c, 0x266c, 0x080c, 0x74f2,
+	0xa006, 0x0010, 0xa085, 0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005,
+	0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c,
+	0x005e, 0x0170, 0x6612, 0x651a, 0x601f, 0x0003, 0x2009, 0x004b,
+	0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005,
+	0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0,
+	0x00c6, 0x080c, 0x749c, 0x005e, 0x01f8, 0x6013, 0x0000, 0x651a,
+	0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x460d, 0x00ce, 0x080c,
+	0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c,
+	0x8ee4, 0x008e, 0x2009, 0x004c, 0x080c, 0x7518, 0xa085, 0x0001,
+	0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056,
+	0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x749c, 0x005e,
+	0x0500, 0x6612, 0x651a, 0x601f, 0x0003, 0x2019, 0x0005, 0x00c6,
+	0x2560, 0x080c, 0x460d, 0x00ce, 0x080c, 0x6127, 0x0086, 0x2041,
+	0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4, 0x008e, 0x2009,
+	0x004d, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x005e, 0x00ce,
+	0x0005, 0xa006, 0x0cd0, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000,
+	0x62a0, 0x00c6, 0x080c, 0x749c, 0x005e, 0x0500, 0x6612, 0x651a,
+	0x601f, 0x0003, 0x2019, 0x0005, 0x00c6, 0x2560, 0x080c, 0x460d,
+	0x00ce, 0x080c, 0x6127, 0x0086, 0x2041, 0x0000, 0x080c, 0x606d,
+	0x2c08, 0x080c, 0x8ee4, 0x008e, 0x2009, 0x004e, 0x080c, 0x7518,
+	0xa085, 0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0,
+	0x00c6, 0x0096, 0x0086, 0x0056, 0x0126, 0x2091, 0x8000, 0x62a0,
+	0x00c6, 0x080c, 0x749c, 0x005e, 0x0904, 0x8426, 0x6612, 0x651a,
+	0x601f, 0x0003, 0x00c6, 0x2560, 0x080c, 0x45af, 0x0118, 0x2001,
+	0x83ec, 0x0028, 0x080c, 0x4581, 0x0160, 0x2001, 0x83f2, 0x0006,
+	0xa00e, 0x2001, 0x0004, 0x080c, 0x492c, 0x080c, 0x4809, 0x000e,
+	0x0807, 0x2019, 0x0004, 0x080c, 0x632b, 0x0036, 0x003e, 0x00ce,
+	0x2041, 0x0001, 0x2608, 0x080c, 0x6140, 0x080c, 0x606d, 0x2c08,
+	0x2648, 0x080c, 0x8ee4, 0x6018, 0xa080, 0x000f, 0x200c, 0x81ff,
+	0x090c, 0x61d3, 0x2009, 0x0052, 0x080c, 0x7518, 0xa085, 0x0001,
+	0x012e, 0x005e, 0x008e, 0x009e, 0x00ce, 0x0005, 0xa006, 0x0cc0,
+	0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e,
+	0x0178, 0x660a, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009,
+	0x001f, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
+	0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c,
+	0x749c, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f, 0x0008, 0x2d00,
+	0x6012, 0x2009, 0x0021, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e,
+	0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000,
+	0x00c6, 0x080c, 0x749c, 0x001e, 0x0178, 0x660a, 0x611a, 0x601f,
+	0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x7518, 0xa085,
+	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
+	0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0170, 0x611a,
+	0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x080c, 0x7518,
+	0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x0026,
+	0x00d6, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e,
+	0x00de, 0x002e, 0x0005, 0x0006, 0x6013, 0x0000, 0x601f, 0x0007,
+	0x2001, 0x94dd, 0x2004, 0x6016, 0x000e, 0x0005, 0x0066, 0x00c6,
+	0x00d6, 0x2031, 0x9252, 0x2634, 0xd6e4, 0x0128, 0x6618, 0x2660,
+	0x6e48, 0x080c, 0x453a, 0x00de, 0x00ce, 0x006e, 0x0005, 0x0006,
+	0x0016, 0x6004, 0xa08e, 0x0002, 0x0140, 0xa08e, 0x0003, 0x0128,
+	0xa08e, 0x0004, 0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005,
+	0x0006, 0x00d6, 0x6010, 0xa06d, 0x0128, 0x6838, 0xd0fc, 0x0110,
+	0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6,
+	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x749c, 0x001e, 0x0180,
+	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c, 0x266c, 0x2009,
+	0x0028, 0x080c, 0x7518, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
+	0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011, 0x9220, 0x2204,
+	0xa086, 0x0074, 0x1148, 0x080c, 0x7a64, 0x6003, 0x0001, 0x6007,
+	0x0029, 0x080c, 0x603e, 0x0020, 0x080c, 0x7776, 0x080c, 0x74f2,
+	0x0005, 0xa186, 0x0015, 0x11b0, 0x2011, 0x9220, 0x2204, 0xa086,
+	0x0014, 0x1180, 0x00d6, 0x6018, 0x2068, 0x080c, 0x44c7, 0x00de,
+	0x080c, 0x7a6e, 0x1138, 0x2001, 0x0006, 0x080c, 0x43e3, 0x080c,
+	0x7598, 0x0020, 0x080c, 0x7776, 0x080c, 0x74f2, 0x0005, 0x6848,
+	0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad, 0x6852,
+	0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x2001, 0x94d9, 0x200c,
+	0x8000, 0x2014, 0x2001, 0x0064, 0x080c, 0x5eaf, 0x2001, 0x94dd,
+	0x82ff, 0x1110, 0x2011, 0x0002, 0x2202, 0x003e, 0x002e, 0x001e,
+	0x000e, 0x0005, 0x0006, 0x2001, 0x94dd, 0x2003, 0x0028, 0x2001,
+	0x94de, 0x2003, 0x07d0, 0x000e, 0x0005, 0x0066, 0x6000, 0xa0b2,
+	0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e, 0x0005, 0x856e, 0x881c,
+	0x8907, 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x85a6, 0x8973,
+	0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x856e, 0x080c, 0x13fe,
+	0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x13fe, 0x0013, 0x006e,
+	0x0005, 0x8589, 0x8ce9, 0x8589, 0x8589, 0x8589, 0x8589, 0x8589,
+	0x8589, 0x8cad, 0x8d31, 0x8589, 0x9105, 0x9135, 0x9105, 0x9135,
+	0x8589, 0x080c, 0x13fe, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c,
+	0x13fe, 0x0013, 0x006e, 0x0005, 0x85a4, 0x8ab9, 0x8b64, 0x8b88,
+	0x8bd3, 0x85a4, 0x85a4, 0x8c44, 0x897f, 0x8c87, 0x8c9a, 0x85a4,
+	0x85a4, 0x85a4, 0x85a4, 0x85a4, 0x080c, 0x13fe, 0xa1b2, 0x003e,
+	0x1a0c, 0x13fe, 0x2100, 0x0002, 0x85df, 0x86f0, 0x85df, 0x85df,
+	0x85df, 0x86f7, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df,
+	0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df,
+	0x85df, 0x85df, 0x85df, 0x85e1, 0x860b, 0x8616, 0x865a, 0x8674,
+	0x86aa, 0x86dd, 0x85df, 0x85df, 0x86fa, 0x85df, 0x85df, 0x8709,
+	0x8710, 0x85df, 0x85df, 0x85df, 0x85df, 0x85df, 0x87ab, 0x85df,
+	0x85df, 0x87b5, 0x85df, 0x85df, 0x875d, 0x85df, 0x85df, 0x080c,
+	0x13fe, 0x080c, 0x470e, 0x6618, 0x00c6, 0x2660, 0x080c, 0x4443,
+	0x00ce, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006,
+	0x0278, 0x080c, 0x8e28, 0x1904, 0x8654, 0x080c, 0x8dd3, 0x1120,
+	0x6007, 0x0008, 0x0804, 0x86eb, 0x6007, 0x0009, 0x0804, 0x86eb,
+	0x080c, 0x8fa4, 0x0128, 0x080c, 0x8e28, 0x0d78, 0x0804, 0x8654,
+	0x6013, 0x1900, 0x0c88, 0x6106, 0x080c, 0x8d83, 0x6007, 0x0006,
+	0x0804, 0x86eb, 0x6007, 0x0007, 0x0804, 0x86eb, 0x080c, 0x9150,
+	0x1904, 0x87c6, 0x00d6, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00,
+	0x8637, 0xa686, 0x0006, 0x01a0, 0xa686, 0x0004, 0x0188, 0x080c,
+	0x4dc5, 0x1160, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0140,
+	0xa686, 0x0004, 0x0128, 0xa686, 0x0005, 0x0110, 0x00de, 0x00e0,
+	0x080c, 0x8e86, 0x11a0, 0xa686, 0x0006, 0x1150, 0x0026, 0x6218,
+	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x26b1, 0x002e,
+	0x080c, 0x44c7, 0x6007, 0x000a, 0x00de, 0x0804, 0x86eb, 0x6007,
+	0x000b, 0x00de, 0x0804, 0x86eb, 0x080c, 0x266c, 0x6007, 0x0001,
+	0x0804, 0x86eb, 0x080c, 0x9150, 0x1904, 0x87c6, 0x6618, 0x00d6,
+	0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d70, 0x0026, 0x6218,
+	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x26b1, 0x002e,
+	0x6007, 0x000c, 0x0804, 0x86eb, 0x080c, 0x470e, 0x6618, 0xa6b0,
+	0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x02b0, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0004, 0x0118, 0xa686, 0x0006, 0x1960,
+	0x080c, 0x8e93, 0x1120, 0x6007, 0x000e, 0x0804, 0x86eb, 0x080c,
+	0x266c, 0x6007, 0x000f, 0x0804, 0x86eb, 0x080c, 0x8fa4, 0x0160,
+	0xa6b4, 0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0x8654, 0xa682,
+	0x0007, 0x0e30, 0x0804, 0x8654, 0x6013, 0x1900, 0x6007, 0x0009,
+	0x0804, 0x86eb, 0x080c, 0x470e, 0x6618, 0xa6b0, 0x0001, 0x2634,
+	0xa684, 0x00ff, 0xa082, 0x0006, 0x02c0, 0xa6b4, 0xff00, 0x8637,
+	0xa686, 0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0x8654, 0x080c,
+	0x8ebb, 0x1130, 0x080c, 0x8dd3, 0x1118, 0x6007, 0x0010, 0x0418,
+	0x080c, 0x266c, 0x6007, 0x0011, 0x00f0, 0x080c, 0x8fa4, 0x0140,
+	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0d48, 0x0804, 0x8654,
+	0x6013, 0x1900, 0x6007, 0x0009, 0x0070, 0x7030, 0xa086, 0x6000,
+	0x0140, 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, 0x1904,
+	0x8654, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x603e, 0x0005,
+	0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x603e, 0x0cc0, 0x6007,
+	0x0005, 0x0cc0, 0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9,
+	0x1904, 0x8654, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x603e,
+	0x0005, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x603e, 0x0005,
+	0x080c, 0x9150, 0x1904, 0x87c6, 0x080c, 0x87c9, 0x1904, 0x8654,
+	0x0016, 0x0026, 0x2011, 0x9791, 0x2214, 0xa286, 0xffff, 0x0190,
+	0x2c08, 0x080c, 0x82de, 0x01d8, 0x2260, 0x2011, 0x9790, 0x2214,
+	0x6008, 0xa206, 0x11a0, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206,
+	0x01e0, 0x0068, 0x2011, 0x9790, 0x2214, 0x2c08, 0x080c, 0x90ab,
+	0x11a0, 0x2011, 0x9791, 0x2214, 0xa286, 0xffff, 0x01a0, 0x2160,
+	0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0x9789, 0x2214, 0xa296,
+	0xffff, 0x1160, 0x6007, 0x0025, 0x0048, 0x601c, 0xa086, 0x0007,
+	0x1d70, 0x080c, 0x74f2, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001,
+	0x080c, 0x603e, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001, 0x080c,
+	0x43d1, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
+	0x9205, 0x2011, 0x9796, 0x080c, 0x7aee, 0x003e, 0x002e, 0x001e,
+	0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0x86eb, 0x080c, 0x7910,
+	0x080c, 0x4dc5, 0x1578, 0x0006, 0x0026, 0x0036, 0x2011, 0x9223,
+	0x2204, 0x8000, 0x2012, 0xa084, 0x0007, 0x0190, 0x2001, 0x94d7,
+	0x2003, 0xaaaa, 0x2001, 0x94d8, 0x2003, 0x0001, 0x2001, 0x9200,
+	0x2003, 0x0001, 0x080c, 0x4d10, 0x003e, 0x002e, 0x000e, 0x0005,
+	0x2001, 0x0001, 0x080c, 0x23ba, 0x080c, 0x4dd7, 0x1110, 0x080c,
+	0x4d9a, 0x2011, 0x8036, 0x2019, 0x0005, 0x080c, 0x3698, 0x003e,
+	0x002e, 0x000e, 0x0005, 0x6106, 0x0479, 0x6007, 0x002b, 0x0804,
+	0x86eb, 0x6007, 0x002c, 0x0804, 0x86eb, 0x080c, 0x9150, 0x1170,
+	0x0081, 0x1904, 0x8654, 0x6106, 0x0419, 0x1120, 0x6007, 0x002e,
+	0x0804, 0x86eb, 0x6007, 0x002f, 0x0804, 0x86eb, 0x080c, 0x74f2,
+	0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00,
+	0x8637, 0xa686, 0x0006, 0x0128, 0xa686, 0x0004, 0x0110, 0xa085,
+	0x0001, 0x006e, 0x00de, 0x0005, 0x00d6, 0x0439, 0x00de, 0x0005,
+	0x00d6, 0x0481, 0x11e0, 0x680c, 0xa08c, 0xff00, 0x6824, 0xa084,
+	0x00ff, 0xa115, 0x6212, 0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060,
+	0xd1ec, 0x0168, 0x6920, 0xa18c, 0x00ff, 0x6824, 0x080c, 0x240b,
+	0x1130, 0x2110, 0x2009, 0x0000, 0x080c, 0x26b1, 0x0018, 0xa085,
+	0x0001, 0x0008, 0xa006, 0x00de, 0x0005, 0x2069, 0x978d, 0x6800,
+	0xa082, 0x0010, 0x1228, 0x6013, 0x0000, 0xa085, 0x0001, 0x0008,
+	0xa006, 0x0005, 0x6013, 0x0000, 0x2069, 0x978c, 0x6808, 0xa084,
+	0xff00, 0xa086, 0x0800, 0x0005, 0x6004, 0xa0b2, 0x003e, 0x1a0c,
+	0x13fe, 0xa1b6, 0x0013, 0x1110, 0x2008, 0x0092, 0xa1b6, 0x0027,
+	0x0120, 0xa1b6, 0x0014, 0x190c, 0x13fe, 0x2001, 0x0007, 0x080c,
+	0x43f1, 0x080c, 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005,
+	0x8875, 0x8877, 0x8875, 0x8875, 0x8875, 0x8877, 0x8885, 0x88e7,
+	0x88b2, 0x88e7, 0x88c3, 0x88e7, 0x8885, 0x88e7, 0x88df, 0x88e7,
+	0x88df, 0x88e7, 0x88e7, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875,
+	0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875,
+	0x88e7, 0x8875, 0x8875, 0x88e7, 0x8875, 0x88e7, 0x88e7, 0x8875,
+	0x8875, 0x8875, 0x8875, 0x88e7, 0x88e7, 0x8875, 0x88e7, 0x88e7,
+	0x8875, 0x887f, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x8875,
+	0x8875, 0x8875, 0x8875, 0x8875, 0x8875, 0x080c, 0x13fe, 0x080c,
+	0x6389, 0x6003, 0x0002, 0x080c, 0x6462, 0x0804, 0x88ed, 0x2001,
+	0x0000, 0x080c, 0x43d1, 0x0804, 0x88e7, 0x00f6, 0x2079, 0x9251,
+	0x7804, 0x00fe, 0xd0ac, 0x1904, 0x88e7, 0x2001, 0x0000, 0x080c,
+	0x43d1, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0904,
+	0x88e7, 0x2001, 0x0002, 0x080c, 0x43e3, 0x080c, 0x6389, 0x601f,
+	0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x603e, 0x080c,
+	0x6462, 0x00c6, 0x6118, 0x2160, 0x2009, 0x0001, 0x080c, 0x573d,
+	0x00ce, 0x04d8, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4,
+	0xff00, 0x8637, 0xa686, 0x0006, 0x0550, 0xa686, 0x0004, 0x0538,
+	0x2001, 0x0004, 0x0410, 0x2001, 0x9200, 0x2004, 0xa086, 0x0003,
+	0x1110, 0x080c, 0x370a, 0x2001, 0x0006, 0x0401, 0x6618, 0x00d6,
+	0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006,
+	0x0170, 0x2001, 0x0006, 0x0048, 0x2001, 0x0004, 0x0030, 0x2001,
+	0x0006, 0x0061, 0x0020, 0x0018, 0x0010, 0x080c, 0x43f1, 0x080c,
+	0x6389, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x0016, 0x00d6,
+	0x6118, 0x2168, 0x6900, 0xd184, 0x0178, 0x6104, 0xa18e, 0x000a,
+	0x1128, 0x699c, 0xd1a4, 0x1110, 0x2001, 0x0007, 0x2001, 0x0000,
+	0x080c, 0x43d1, 0x080c, 0x2692, 0x00de, 0x001e, 0x0005, 0x00d6,
+	0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de, 0xa0b2,
+	0x000c, 0x1a0c, 0x13fe, 0xa1b6, 0x0015, 0x1110, 0x003b, 0x0028,
+	0xa1b6, 0x0016, 0x190c, 0x13fe, 0x04eb, 0x0005, 0x7805, 0x7805,
+	0x7805, 0x7805, 0x7805, 0x7805, 0x7805, 0x892a, 0x7805, 0x7805,
+	0x7805, 0x7805, 0x00f6, 0x2079, 0x9251, 0x7804, 0x00fe, 0xd0ac,
+	0x1198, 0x2001, 0x0000, 0x080c, 0x43d1, 0x2001, 0x0002, 0x080c,
+	0x43e3, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
+	0x603e, 0x080c, 0x6462, 0x00a8, 0x2011, 0x9783, 0x2204, 0x8211,
+	0x220c, 0x080c, 0x240b, 0x1168, 0x00c6, 0x080c, 0x4434, 0x0120,
+	0x00ce, 0x080c, 0x74f2, 0x0028, 0x080c, 0x41e0, 0x00ce, 0x080c,
+	0x74f2, 0x0005, 0x7805, 0x7805, 0x7805, 0x7805, 0x7805, 0x7805,
+	0x7805, 0x8966, 0x7805, 0x7805, 0x7805, 0x7805, 0x080c, 0x7a61,
+	0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x603e, 0x0010,
+	0x080c, 0x74f2, 0x0005, 0x6004, 0xa08a, 0x003e, 0x1a0c, 0x13fe,
+	0x080c, 0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa182,
+	0x0040, 0x0002, 0x8995, 0x8995, 0x8995, 0x8995, 0x8997, 0x8995,
+	0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x8995,
+	0x8995, 0x8995, 0x8995, 0x8995, 0x8995, 0x080c, 0x13fe, 0x00d6,
+	0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6106, 0x2071, 0x9780,
+	0x7444, 0xa4a4, 0xf600, 0x0904, 0x8a0d, 0xa486, 0x2000, 0x01f0,
+	0xa486, 0x0400, 0x01d8, 0xa486, 0x1000, 0x0178, 0xa486, 0x4000,
+	0x01d8, 0xa486, 0x0200, 0x0120, 0x080c, 0x74f2, 0x0804, 0x8a67,
+	0x6118, 0x2104, 0xc0fd, 0x200a, 0x0078, 0x2069, 0x9566, 0x6a00,
+	0xd284, 0x0904, 0x8a79, 0xc2cd, 0x6a02, 0x0030, 0x2009, 0x0001,
+	0x2011, 0x0200, 0x080c, 0x585b, 0x080c, 0x147c, 0x090c, 0x13fe,
+	0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803, 0x0000, 0x683b,
+	0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2, 0x6018, 0x2078,
+	0x78a0, 0x8007, 0x7130, 0x694a, 0x0016, 0xa084, 0xff00, 0x6846,
+	0x684f, 0x0000, 0x6857, 0x0036, 0x080c, 0x4809, 0x001e, 0xa486,
+	0x2000, 0x1130, 0x2019, 0x0017, 0x080c, 0x9071, 0x0804, 0x8a67,
+	0xa486, 0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0x9033, 0x0804,
+	0x8a67, 0xa486, 0x0200, 0x1110, 0x080c, 0x9020, 0xa486, 0x1000,
+	0x1110, 0x080c, 0x905e, 0x0804, 0x8a67, 0x2069, 0x9566, 0x6a00,
+	0xd284, 0x0904, 0x8ab6, 0xa284, 0x0300, 0x1904, 0x8ab0, 0x6804,
+	0xa005, 0x0904, 0x8aa1, 0x2d78, 0x6003, 0x0007, 0x6018, 0x2004,
+	0xd0fc, 0x1904, 0x8ab0, 0x080c, 0x145f, 0x0904, 0x8a6e, 0x7800,
+	0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013, 0x0000, 0x6803,
+	0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008, 0x68b2, 0x2c00,
+	0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x6986, 0x6846,
+	0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286, 0x0002, 0x1118,
+	0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118, 0x684f, 0x0080,
+	0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001, 0x9790, 0xad90,
+	0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210, 0x1f04, 0x8a59,
+	0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c, 0x4809, 0x002e,
+	0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x6013, 0x0100,
+	0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462,
+	0x0c70, 0x2069, 0x9792, 0x2d04, 0xa084, 0xff00, 0xa086, 0x1200,
+	0x11a8, 0x2069, 0x9780, 0x686c, 0xa084, 0x00ff, 0x0016, 0x6110,
+	0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e, 0x6003, 0x0001, 0x6007,
+	0x0043, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0888, 0x6013, 0x0200,
+	0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462,
+	0x0830, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003, 0x0001,
+	0x6007, 0x0041, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x0804, 0x8a67,
+	0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0818, 0x6013, 0x0200,
+	0x0800, 0xa186, 0x0013, 0x1170, 0x6004, 0xa08a, 0x0040, 0x0a0c,
+	0x13fe, 0xa08a, 0x0053, 0x1a0c, 0x13fe, 0xa082, 0x0040, 0x2008,
+	0x0804, 0x8b24, 0xa186, 0x0047, 0x11b8, 0x2001, 0x0109, 0x2004,
+	0xd084, 0x01f0, 0x0126, 0x2091, 0x2400, 0x0006, 0x0016, 0x0026,
+	0x080c, 0x5ee3, 0x002e, 0x001e, 0x000e, 0x012e, 0x6000, 0xa086,
+	0x0002, 0x1170, 0x0804, 0x8b64, 0xa186, 0x0027, 0x0120, 0xa186,
+	0x0014, 0x190c, 0x13fe, 0x6004, 0xa082, 0x0040, 0x2008, 0x001a,
+	0x080c, 0x7526, 0x0005, 0x8b06, 0x8b08, 0x8b08, 0x8b06, 0x8b06,
+	0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06,
+	0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x8b06, 0x080c, 0x13fe,
+	0x080c, 0x6389, 0x080c, 0x6462, 0x0036, 0x00d6, 0x6010, 0xa06d,
+	0x0180, 0xad84, 0xf000, 0x0168, 0x2019, 0x0004, 0x080c, 0x9097,
+	0x6013, 0x0000, 0x6014, 0xa005, 0x1110, 0x6017, 0x0014, 0x6003,
+	0x0007, 0x00de, 0x003e, 0x0005, 0x0002, 0x8b38, 0x8b55, 0x8b41,
+	0x8b5e, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38,
+	0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38, 0x8b38,
+	0x080c, 0x13fe, 0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400,
+	0x200a, 0x080c, 0x6389, 0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4,
+	0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0x7518, 0x0010,
+	0x6003, 0x0002, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389, 0x080c,
+	0x5836, 0x080c, 0x74f2, 0x080c, 0x6462, 0x0005, 0x080c, 0x6389,
+	0x2009, 0x0041, 0x0804, 0x8c44, 0xa182, 0x0040, 0x0002, 0x8b7a,
+	0x8b7c, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7d, 0x8b7a,
+	0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a, 0x8b7a,
+	0x8b7a, 0x8b7a, 0x080c, 0x13fe, 0x0005, 0x6003, 0x0004, 0x6110,
+	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x0005,
+	0xa182, 0x0040, 0x0002, 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e,
+	0x8b9e, 0x8b9e, 0x8b9e, 0x8b9e, 0x8ba0, 0x8bc0, 0x8b9e, 0x8b9e,
+	0x8b9e, 0x8b9e, 0x8bc0, 0x8b9e, 0x8b9e, 0x8b9e, 0x080c, 0x13fe,
+	0x080c, 0x641b, 0x080c, 0x651c, 0x6010, 0x00d6, 0x2068, 0x684c,
+	0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e, 0x0002, 0x0158, 0x2009,
+	0x0041, 0x00de, 0x0804, 0x8c44, 0x6003, 0x0007, 0x080c, 0x5836,
+	0x00de, 0x0005, 0x080c, 0x5836, 0x080c, 0x74f2, 0x00de, 0x0cc8,
+	0x0036, 0x080c, 0x641b, 0x080c, 0x651c, 0x6010, 0x00d6, 0x2068,
+	0x2019, 0x0004, 0x080c, 0x9097, 0x080c, 0x849b, 0x6017, 0x0028,
+	0x00de, 0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086,
+	0x0042, 0x190c, 0x13fe, 0x080c, 0x6389, 0x080c, 0x6462, 0x0005,
+	0xa186, 0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086,
+	0x0042, 0x190c, 0x13fe, 0x2001, 0x0007, 0x080c, 0x43f1, 0x080c,
+	0x6389, 0x080c, 0x849b, 0x080c, 0x6462, 0x0005, 0xa182, 0x0040,
+	0x0002, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c,
+	0x8c0e, 0x8c1a, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c,
+	0x8c0c, 0x8c0c, 0x8c0c, 0x8c0c, 0x080c, 0x13fe, 0x0036, 0x0046,
+	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x16c6, 0x004e,
+	0x003e, 0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0xa20d,
+	0x1168, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x00e0,
+	0x6003, 0x0007, 0x080c, 0x5836, 0x00de, 0x0005, 0x6003, 0x0007,
+	0x0021, 0x080c, 0x5838, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002,
+	0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009,
+	0x0015, 0x6a6a, 0x6866, 0x0005, 0xa182, 0x0040, 0x0002, 0x8c5a,
+	0x8c5c, 0x8c68, 0x8c74, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c83, 0x8c5a,
+	0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a, 0x8c5a,
+	0x8c5a, 0x8c5a, 0x080c, 0x13fe, 0x6003, 0x0001, 0x6106, 0x080c,
+	0x5ff8, 0x0126, 0x2091, 0x8000, 0x080c, 0x6462, 0x012e, 0x0005,
+	0x6003, 0x0001, 0x6106, 0x080c, 0x5ff8, 0x0126, 0x2091, 0x8000,
+	0x080c, 0x6462, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10,
+	0x080c, 0x1c88, 0x0126, 0x2091, 0x8000, 0x080c, 0x605b, 0x080c,
+	0x651c, 0x012e, 0x0005, 0xa016, 0x080c, 0x16c6, 0x0005, 0x080c,
+	0x6389, 0x6110, 0x81ff, 0x0148, 0x00d6, 0x2168, 0x0036, 0x2019,
+	0x0029, 0x080c, 0x9097, 0x003e, 0x00de, 0x080c, 0x849b, 0x080c,
+	0x6462, 0x0005, 0x080c, 0x641b, 0x6110, 0x81ff, 0x0148, 0x00d6,
+	0x2168, 0x0036, 0x2019, 0x0029, 0x080c, 0x9097, 0x003e, 0x00de,
+	0x080c, 0x849b, 0x080c, 0x651c, 0x0005, 0xa182, 0x0085, 0x0002,
+	0x8cb9, 0x8cb7, 0x8cb7, 0x8cc5, 0x8cb7, 0x8cb7, 0x8cb7, 0x080c,
+	0x13fe, 0x6003, 0x000b, 0x6106, 0x080c, 0x5ff8, 0x0126, 0x2091,
+	0x8000, 0x080c, 0x6462, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c,
+	0x9150, 0x0118, 0x080c, 0x74f2, 0x00c8, 0x2071, 0x9780, 0x7224,
+	0x6212, 0x7220, 0x080c, 0x8f71, 0x0118, 0x6007, 0x0086, 0x0040,
+	0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086,
+	0x6003, 0x0001, 0x080c, 0x5ff8, 0x080c, 0x6462, 0x00ee, 0x002e,
+	0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c,
+	0x13fe, 0xa08a, 0x008c, 0x1a0c, 0x13fe, 0xa082, 0x0085, 0x00a2,
+	0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118, 0x080c, 0x7526,
+	0x0050, 0x2001, 0x0007, 0x080c, 0x43f1, 0x080c, 0x6389, 0x080c,
+	0x849b, 0x080c, 0x6462, 0x0005, 0x8d13, 0x8d15, 0x8d15, 0x8d13,
+	0x8d13, 0x8d13, 0x8d13, 0x080c, 0x13fe, 0x080c, 0x6389, 0x080c,
+	0x74f2, 0x080c, 0x6462, 0x0005, 0xa182, 0x0085, 0x0a0c, 0x13fe,
+	0xa182, 0x008c, 0x1a0c, 0x13fe, 0xa182, 0x0085, 0x0002, 0x8d2e,
+	0x8d2e, 0x8d2e, 0x8d30, 0x8d2e, 0x8d2e, 0x8d2e, 0x080c, 0x13fe,
+	0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014, 0x0130, 0xa186,
+	0x0027, 0x0118, 0x080c, 0x7526, 0x0030, 0x080c, 0x6389, 0x080c,
+	0x849b, 0x080c, 0x6462, 0x0005, 0x0036, 0x2019, 0x000b, 0x0031,
+	0x601f, 0x0006, 0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036,
+	0x0086, 0x2091, 0x8000, 0x2c40, 0x080c, 0x724a, 0x1540, 0x080c,
+	0x72e2, 0x1528, 0x6000, 0xa086, 0x0000, 0x0508, 0x601c, 0xa086,
+	0x0007, 0x01e8, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1140, 0x601f,
+	0x0007, 0x2001, 0x94dd, 0x2004, 0x6016, 0x080c, 0x1788, 0x6010,
+	0x2068, 0x080c, 0x82ee, 0x0110, 0x080c, 0x9097, 0x00de, 0x6013,
+	0x0000, 0x601f, 0x0007, 0x2001, 0x94dd, 0x2004, 0x6016, 0x008e,
+	0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156, 0x2079,
+	0x9780, 0x7938, 0x783c, 0x080c, 0x240b, 0x1904, 0x8dce, 0x0016,
+	0x00c6, 0x080c, 0x4434, 0x15c0, 0x2011, 0x9790, 0xac98, 0x000a,
+	0x20a9, 0x0004, 0x080c, 0x7aee, 0x1578, 0x001e, 0x002e, 0x0026,
+	0x0016, 0x2019, 0x0029, 0x080c, 0x73a2, 0x080c, 0x6127, 0x0086,
+	0x2041, 0x0000, 0x080c, 0x606d, 0x008e, 0x001e, 0x0086, 0x2041,
+	0x0000, 0x080c, 0x8ee4, 0x008e, 0x080c, 0x460d, 0x0026, 0x6204,
+	0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004,
+	0x1118, 0x62a0, 0x080c, 0x2704, 0x002e, 0x001e, 0x080c, 0x41e0,
+	0x6612, 0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e,
+	0x00ce, 0x00fe, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x2009, 0x9220,
+	0x2104, 0xa086, 0x0074, 0x1904, 0x8e1e, 0x2069, 0x978e, 0x690c,
+	0xa182, 0x0100, 0x0678, 0x6908, 0xa184, 0x8000, 0x05a0, 0x2001,
+	0x94d7, 0x2004, 0xa005, 0x1118, 0xa184, 0x0800, 0x0560, 0x6910,
+	0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0x97ae, 0x6904, 0x81ff,
+	0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff, 0x1178,
+	0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001, 0x0298,
+	0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088, 0x6013,
+	0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900, 0x0040,
+	0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013, 0x2d00,
+	0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00de, 0x00ce, 0x0005,
+	0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218, 0x2268, 0x6b04,
+	0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286, 0x0004, 0x0178,
+	0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0xa286, 0x0004,
+	0x0130, 0x00c6, 0x2d60, 0x080c, 0x4443, 0x00ce, 0x04c0, 0x2011,
+	0x9796, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x7aee, 0x1580,
+	0x2011, 0x979a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x7aee,
+	0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006,
+	0x2009, 0x9252, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c,
+	0x90d7, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x080c, 0x6127,
+	0x0086, 0x2041, 0x0000, 0x080c, 0x606d, 0x2c08, 0x080c, 0x8ee4,
+	0x008e, 0x2001, 0x0007, 0x080c, 0x43f1, 0x001e, 0x004e, 0xa006,
+	0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005, 0x00d6, 0x2069,
+	0x978e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013, 0x0000, 0x0008,
+	0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016, 0x0026, 0x0036,
+	0x0156, 0x2079, 0x978c, 0x7930, 0x7834, 0x080c, 0x240b, 0x11a0,
+	0x080c, 0x4434, 0x1188, 0x2011, 0x9790, 0xac98, 0x000a, 0x20a9,
+	0x0004, 0x080c, 0x7aee, 0x1140, 0x2011, 0x9794, 0xac98, 0x0006,
+	0x20a9, 0x0004, 0x080c, 0x7aee, 0x015e, 0x003e, 0x002e, 0x001e,
+	0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016, 0x0026, 0x0036,
+	0x0156, 0x2011, 0x9783, 0x2204, 0x8211, 0x220c, 0x080c, 0x240b,
+	0x11a0, 0x080c, 0x4434, 0x1188, 0x2011, 0x9796, 0xac98, 0x000a,
+	0x20a9, 0x0004, 0x080c, 0x7aee, 0x1140, 0x2011, 0x979a, 0xac98,
+	0x0006, 0x20a9, 0x0004, 0x080c, 0x7aee, 0x015e, 0x003e, 0x002e,
+	0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066,
+	0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2029, 0x94ee,
+	0x252c, 0x2021, 0x94f4, 0x2424, 0x2061, 0x9900, 0x2071, 0x9200,
+	0x7644, 0x7064, 0x8001, 0xa602, 0x1a04, 0x8f44, 0x2100, 0xac06,
+	0x05d0, 0x080c, 0x90ee, 0x05b8, 0x671c, 0xa786, 0x0001, 0x0904,
+	0x8f56, 0xa786, 0x0007, 0x0578, 0x2500, 0xac06, 0x0560, 0x2400,
+	0xac06, 0x0548, 0x080c, 0x90fe, 0x1530, 0x88ff, 0x0118, 0x6020,
+	0xa906, 0x1508, 0x00d6, 0x6000, 0xa086, 0x0004, 0x1120, 0x0016,
+	0x080c, 0x1788, 0x001e, 0x6010, 0x2068, 0x080c, 0x82ee, 0x0180,
+	0xa786, 0x0003, 0x1510, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
+	0x0016, 0x080c, 0x8527, 0x080c, 0x4809, 0x001e, 0x080c, 0x848f,
+	0x00de, 0x080c, 0x849b, 0xace0, 0x000c, 0x2001, 0x9216, 0x2004,
+	0xac02, 0x1210, 0x0804, 0x8ef6, 0x012e, 0x002e, 0x004e, 0x005e,
+	0x006e, 0x007e, 0x00ce, 0x00ee, 0x0005, 0xa786, 0x0006, 0x19d8,
+	0xa386, 0x0005, 0x0d40, 0x080c, 0x9097, 0x0c10, 0x080c, 0x90fe,
+	0x1d10, 0xa180, 0x0001, 0x2004, 0xa086, 0x0018, 0x19e0, 0x6000,
+	0xa086, 0x0002, 0x19c0, 0x080c, 0x84b7, 0x0130, 0x080c, 0x84c8,
+	0x1990, 0x080c, 0x7776, 0x0010, 0x080c, 0x2692, 0x080c, 0x849b,
+	0x0850, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x080c, 0x90ab,
+	0x001e, 0x0120, 0x601c, 0xa084, 0x000f, 0x001b, 0x00ee, 0x00ce,
+	0x0005, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f89, 0x8f8b,
+	0x8f89, 0xa006, 0x0005, 0x0046, 0x0016, 0x7018, 0xa080, 0x0028,
+	0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00, 0x2009, 0x0020, 0x080c,
+	0x90d7, 0x001e, 0x004e, 0x0036, 0x2019, 0x0002, 0x080c, 0x8d4e,
+	0x003e, 0xa085, 0x0001, 0x0005, 0x2001, 0x0001, 0x080c, 0x43d1,
+	0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x9205,
+	0x2011, 0x9796, 0x080c, 0x7aee, 0x003e, 0x002e, 0x001e, 0x015e,
+	0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0026,
+	0x0126, 0x2091, 0x8000, 0x2061, 0x9900, 0x2079, 0x0001, 0x8fff,
+	0x0904, 0x9014, 0x2071, 0x9200, 0x7644, 0x7064, 0x8001, 0xa602,
+	0x1a04, 0x9014, 0x88ff, 0x0128, 0x2800, 0xac06, 0x15a0, 0x2079,
+	0x0000, 0x080c, 0x90ee, 0x0578, 0x2400, 0xac06, 0x0560, 0x671c,
+	0xa786, 0x0006, 0x1540, 0xa786, 0x0007, 0x0528, 0x88ff, 0x1140,
+	0x6018, 0xa206, 0x1500, 0x85ff, 0x0118, 0x6020, 0xa106, 0x11d8,
+	0x00d6, 0x6000, 0xa086, 0x0004, 0x1140, 0x601f, 0x0007, 0x2001,
+	0x94dd, 0x2004, 0x6016, 0x080c, 0x1788, 0x6010, 0x2068, 0x080c,
+	0x82ee, 0x0120, 0x0046, 0x080c, 0x9097, 0x004e, 0x00de, 0x080c,
+	0x849b, 0x88ff, 0x1190, 0xace0, 0x000c, 0x2001, 0x9216, 0x2004,
+	0xac02, 0x1210, 0x0804, 0x8fc7, 0xa006, 0x012e, 0x002e, 0x006e,
+	0x007e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca8,
+	0x0086, 0x0056, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20, 0x2019,
+	0x0002, 0x6218, 0x080c, 0x724a, 0x080c, 0x72e2, 0x080c, 0x8fba,
+	0x005e, 0x008e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0086, 0x00c6,
+	0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016,
+	0x0036, 0x080c, 0x4434, 0x1170, 0x2c10, 0x2041, 0x0000, 0x2508,
+	0x0056, 0x2029, 0x0001, 0x080c, 0x724a, 0x080c, 0x72e2, 0x080c,
+	0x8fba, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0x903f, 0x015e,
+	0x00ce, 0x008e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0086, 0x0056,
+	0x6218, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048, 0x080c,
+	0x724a, 0x080c, 0x72e2, 0x2c20, 0x080c, 0x8fba, 0x005e, 0x008e,
+	0x0005, 0x0026, 0x0046, 0x0056, 0x0086, 0x00c6, 0x0156, 0x2c20,
+	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x4434,
+	0x1150, 0x2c10, 0x2041, 0x0000, 0x2828, 0x080c, 0x724a, 0x080c,
+	0x72e2, 0x080c, 0x8fba, 0x003e, 0x001e, 0x8108, 0x1f04, 0x907c,
+	0x015e, 0x00ce, 0x008e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016,
+	0x00f6, 0x8dff, 0x0168, 0x6800, 0xa07d, 0x0138, 0x6803, 0x0000,
+	0x6b52, 0x080c, 0x4809, 0x2f68, 0x0cb0, 0x6b52, 0x080c, 0x4809,
+	0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046, 0x0036, 0x2061, 0x9900,
+	0x2071, 0x9200, 0x7444, 0x7064, 0x8001, 0xa402, 0x12d8, 0x2100,
+	0xac06, 0x0168, 0x6000, 0xa086, 0x0000, 0x0148, 0x6008, 0xa206,
+	0x1130, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406, 0x0140, 0xace0,
+	0x000c, 0x2001, 0x9216, 0x2004, 0xac02, 0x1220, 0x0c08, 0xa085,
+	0x0001, 0x0008, 0xa006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6,
+	0x0006, 0x080c, 0x147c, 0x000e, 0x090c, 0x13fe, 0x6837, 0x010d,
+	0x685e, 0x6956, 0x6c46, 0x684f, 0x0000, 0xa006, 0x68b2, 0x6802,
+	0x683a, 0x685a, 0x080c, 0x4809, 0x00de, 0x0005, 0x6700, 0xa786,
+	0x0000, 0x0158, 0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128,
+	0xa786, 0x0009, 0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018,
+	0x2070, 0x70a0, 0xa206, 0x00ee, 0x0005, 0xa186, 0x0013, 0x1128,
+	0x6004, 0xa082, 0x0085, 0x2008, 0x00c2, 0xa186, 0x0027, 0x1178,
+	0x080c, 0x6389, 0x0036, 0x00d6, 0x6010, 0x2068, 0x2019, 0x0004,
+	0x080c, 0x9097, 0x00de, 0x003e, 0x080c, 0x6462, 0x0005, 0xa186,
+	0x0014, 0x0d70, 0x080c, 0x7526, 0x0005, 0x912e, 0x912c, 0x912c,
+	0x912c, 0x912c, 0x912c, 0x912e, 0x080c, 0x13fe, 0x080c, 0x6389,
+	0x6003, 0x000c, 0x080c, 0x6462, 0x0005, 0xa182, 0x008c, 0x1220,
+	0xa182, 0x0085, 0x0208, 0x001a, 0x080c, 0x7526, 0x0005, 0x9146,
+	0x9146, 0x9146, 0x9146, 0x9148, 0x914d, 0x9146, 0x080c, 0x13fe,
+	0x00d6, 0x080c, 0x74f2, 0x00de, 0x0005, 0x080c, 0x74f2, 0x0005,
+	0x00e6, 0x6018, 0x2070, 0x7000, 0xd0ec, 0x00ee, 0x0005, 0x0126,
+	0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x9240, 0xd5a4, 0x0118,
+	0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032,
+	0xd5ac, 0x0118, 0x2071, 0x924a, 0x0451, 0x00ee, 0x000e, 0x012e,
+	0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x9240,
+	0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0118, 0x7030,
+	0x8000, 0x7032, 0xd5ac, 0x0118, 0x2071, 0x924a, 0x0081, 0x00ee,
+	0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000,
+	0x2071, 0x9242, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04,
+	0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005,
+	0x00e6, 0x2071, 0x9240, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071,
+	0x9244, 0x0c69, 0x00ee, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008,
+	0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800,
+	0x1000, 0x2000, 0x4000, 0x8000, 0x448c
 };
-unsigned short   risc_code_length01 = 0x65e6;
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/qlogicisp.c linux.pre11.3/drivers/scsi/qlogicisp.c
--- linux.vanilla/drivers/scsi/qlogicisp.c	Wed Apr 28 19:14:28 1999
+++ linux.pre11.3/drivers/scsi/qlogicisp.c	Mon Jul 19 23:28:01 1999
@@ -1065,8 +1065,10 @@
 		ip[0] = 255;
 		ip[1] = 63;
 		ip[2] = size / (ip[0] * ip[1]);
+#if 0
 		if (ip[2] > 1023)
 			ip[2] = 1023;
+#endif			
 	}
 
 	LEAVE("isp1020_biosparam");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/scsi.c linux.pre11.3/drivers/scsi/scsi.c
--- linux.vanilla/drivers/scsi/scsi.c	Tue Jun 15 16:49:51 1999
+++ linux.pre11.3/drivers/scsi/scsi.c	Tue Jul 20 00:03:35 1999
@@ -32,6 +32,8 @@
  *  Converted cli() code to spinlocks, Ingo Molnar
  *
  *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
+ *
+ *  out_of_space + add-single-device work, D. Gilbert (dpg) 990612
  */
 
 #include <linux/config.h>
@@ -180,6 +182,7 @@
                  int * sparse_lun, Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt,
                  struct Scsi_Host *shpnt, char * scsi_result);
 void        scsi_build_commandblocks(Scsi_Device * SDpnt);
+static int scsi_unregister_device(struct Scsi_Device_Template * tpnt);
 
 /*
  * These are the interface to the old error handling code.  It should go away
@@ -451,16 +454,18 @@
   Scsi_Device   * SDtail;
   int             sparse_lun;
 
-  SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), GFP_ATOMIC | GFP_DMA);
-  memset (SCpnt, 0, sizeof (Scsi_Cmnd));
-
-  SDpnt = (Scsi_Device *) scsi_init_malloc (sizeof (Scsi_Device), GFP_ATOMIC);
-  memset (SDpnt, 0, sizeof (Scsi_Device));
-
-
-  /* Make sure we have something that is valid for DMA purposes */
-  scsi_result = ( ( !shpnt->unchecked_isa_dma )
-                 ? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA));
+  scsi_result = NULL;
+  SCpnt = (Scsi_Cmnd *) scsi_init_malloc (sizeof (Scsi_Cmnd), 
+					  GFP_ATOMIC | GFP_DMA);
+    if (SCpnt) {
+	SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof (Scsi_Device), 
+						 GFP_ATOMIC);
+	if (SDpnt) {
+	    /* Make sure we have something that is valid for DMA purposes */
+	    scsi_result = ( ( !shpnt->unchecked_isa_dma )
+			? &scsi_result0[0] : scsi_init_malloc (512, GFP_DMA));
+	}
+    }
 
   if (scsi_result == NULL) 
   {
@@ -512,18 +517,32 @@
     if(lun >= shpnt->max_lun) goto leave;
     scan_scsis_single (channel, dev, lun, &max_dev_lun, &sparse_lun,
 		       &SDpnt, SCpnt, shpnt, scsi_result);
+
+    /* See warning by (DB) in scsi_proc_info() towards end of
+       'add-single-device' section. (dpg) */
+    if (shpnt->select_queue_depths != NULL)
+	(shpnt->select_queue_depths)(shpnt, shpnt->host_queue);
+
     if(SDpnt!=oldSDpnt) {
 
 	/* it could happen the blockdevice hasn't yet been inited */
-    for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-        if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();
+	for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
+	    if(sdtpnt->init && sdtpnt->dev_noticed) (*sdtpnt->init)();
 
-            oldSDpnt->scsi_request_fn = NULL;
-            for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
-                if(sdtpnt->attach) {
-		  (*sdtpnt->attach)(oldSDpnt);
-                  if(oldSDpnt->attached) scsi_build_commandblocks(oldSDpnt);}
-	    resize_dma_pool();
+	oldSDpnt->scsi_request_fn = NULL;
+	for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
+	    if(sdtpnt->attach) {
+		(*sdtpnt->attach)(oldSDpnt);
+		if(oldSDpnt->attached) {
+		    scsi_build_commandblocks(oldSDpnt);
+		    if (0 == oldSDpnt->has_cmdblocks) {
+			printk("scan_scsis: DANGER, no command blocks\n");
+			/* What to do now ?? */
+		    }
+		}
+	    }
+	}
+	resize_dma_pool();
 
         for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
             if(sdtpnt->finish && sdtpnt->nr_dev)
@@ -743,6 +762,17 @@
     scsi_result[1] |= 0x80;     /* removable */
   }
 
+  /*
+   * It would seem the Panasonic DVD-RAM is backwards too
+   * If DVD-RAM or PD media used, it seems to function
+   * as Direct-Access
+   */
+  if (!strncmp (scsi_result + 8, "MATSHITA", 7) &&
+      !strncmp (scsi_result + 16, "PD-2 LF-D100", 12)) {
+    scsi_result[0] = TYPE_DISK;
+    scsi_result[1] |= 0x80;     /* removable */
+  }
+
   memcpy (SDpnt->vendor, scsi_result + 8, 8);
   memcpy (SDpnt->model, scsi_result + 16, 16);
   memcpy (SDpnt->rev, scsi_result + 32, 4);
@@ -884,8 +914,6 @@
       return 0;
   }
 
-  memset (SDpnt, 0, sizeof (Scsi_Device));
-
   /*
    * And hook up our command block to the new device we will be testing
    * for.
@@ -1429,6 +1457,7 @@
 {
     struct Scsi_Host * host = SCpnt->host;
     Scsi_Device      * device = SCpnt->device;
+    int mlqueue = 0;
 
     SCpnt->owner = SCSI_OWNER_MIDLEVEL;
 
@@ -1463,6 +1492,10 @@
     SCpnt->pid = scsi_pid++;
 
     while (SCSI_BLOCK((Scsi_Device *) NULL, host)) {
+	if (in_interrupt()){
+		mlqueue = 1;
+		break;
+	}
     	spin_unlock(&io_request_lock);	/* FIXME!!! */
 	SCSI_SLEEP(&host->host_wait, SCSI_BLOCK((Scsi_Device *) NULL, host));
     	spin_lock_irq(&io_request_lock);	/* FIXME!!! */
@@ -1509,7 +1542,15 @@
     SCpnt->internal_timeout = NORMAL_TIMEOUT;
     SCpnt->abort_reason = 0;
     SCpnt->result = 0;
-    internal_cmnd (SCpnt);
+
+    if (mlqueue == 1 && host->hostt->use_new_eh_code){
+	/* Assign a unique nonzero serial_number. */
+	if (++serial_number == 0) serial_number = 1;
+	SCpnt->serial_number = serial_number;
+	scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
+    }
+    else
+	internal_cmnd (SCpnt);
 
     SCSI_LOG_MLQUEUE(3,printk ("Leaving scsi_do_cmd()\n"));
 }
@@ -1899,9 +1940,9 @@
 	for (order = 0, a_size = PAGE_SIZE;
              a_size < size; order++, a_size <<= 1)
             ;
-        retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order);
+	retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order);
     } else
-        retval = kmalloc(size, gfp_mask);
+	retval = kmalloc(size, gfp_mask);
 
     if (retval)
 	memset(retval, 0, size);
@@ -1970,9 +2011,10 @@
 	printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n",
 	       SDpnt->queue_depth, j);
 	SDpnt->queue_depth = j;
-	/* Still problem if 0==j , continue anyway ... */
+	SDpnt->has_cmdblocks = (0 != j);
     }
-    SDpnt->has_cmdblocks = 1;
+    else
+	SDpnt->has_cmdblocks = 1;
 }
 
 #ifndef MODULE /* { */
@@ -2036,7 +2078,13 @@
             /* SDpnt->scsi_request_fn = NULL; */
             for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
                 if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt);
-            if(SDpnt->attached) scsi_build_commandblocks(SDpnt);
+            if(SDpnt->attached) {
+		scsi_build_commandblocks(SDpnt);
+		if (0 == SDpnt->has_cmdblocks) {
+		    printk("scsi_dev_init: DANGER, no command blocks\n");
+		    /* What to do now ?? */
+		}
+	    }
         }
     }
     
@@ -2332,8 +2380,9 @@
         /* FIXME (DB) This assumes that the queue_depth routines can be used
            in this context as well, while they were all designed to be
            called only once after the detect routine. (DB) */
-	if (HBA_ptr->select_queue_depths != NULL)
-		(HBA_ptr->select_queue_depths)(HBA_ptr, HBA_ptr->host_queue);
+	/* ... but scan_scsis(,1,,,) needs the correct queue_length. So
+	   select_queue_depths() has been moved inside scan_scsis() and
+	   is only used in this context (ie scan_scsis(,1,,,) ). (dpg) */
 
 	return(length);
 
@@ -2396,7 +2445,7 @@
              * Nobody is using this device any more.
              * Free all of the command structures.
              */
-            for(SCpnt=scd->device_queue; SCpnt; SCpnt = SCpnt->next)
+            for(SCpnt=scd->device_queue; SCpnt; SCpnt = scd->device_queue)
             {
                 scd->device_queue = SCpnt->next;
                 scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
@@ -2429,7 +2478,7 @@
  */
 static void resize_dma_pool(void)
 {
-    int i;
+    int i, k;
     unsigned long size;
     struct Scsi_Host * shpnt;
     struct Scsi_Host * host = NULL;
@@ -2438,6 +2487,7 @@
     unsigned int new_dma_sectors = 0;
     unsigned int new_need_isa_buffer = 0;
     unsigned char ** new_dma_malloc_pages = NULL;
+    int out_of_space = 0;
 
     if( !scsi_hostlist )
     {
@@ -2529,27 +2579,67 @@
      * race conditions that I would rather not even think
      * about right now.
      */
-    if( new_dma_sectors < dma_sectors )
+#if 0  /* Why do this? No gain and risks out_of_space */
+     if( new_dma_sectors < dma_sectors ) 
 	new_dma_sectors = dma_sectors;
+#endif
+    if( new_dma_sectors <= dma_sectors ) 
+	return;	/* best to quit while we are in front */
 
-    if (new_dma_sectors)
-    {
-        size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
-	new_dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC);
-	memset(new_dma_malloc_freelist, 0, size);
-
-        size = (new_dma_sectors / SECTORS_PER_PAGE)*sizeof(*new_dma_malloc_pages);
-	new_dma_malloc_pages = (unsigned char **) scsi_init_malloc(size, GFP_ATOMIC);
-	memset(new_dma_malloc_pages, 0, size);
-    }
+    for (k = 0; k < 20; ++k) { /* just in case */
+	out_of_space = 0;
+	size = (new_dma_sectors / SECTORS_PER_PAGE) *
+				    sizeof(FreeSectorBitmap);
+	new_dma_malloc_freelist = (FreeSectorBitmap *) 
+			    scsi_init_malloc(size, GFP_ATOMIC);
+	if (new_dma_malloc_freelist) {
+	    size = (new_dma_sectors / SECTORS_PER_PAGE) *
+			    sizeof(*new_dma_malloc_pages);
+	    new_dma_malloc_pages = (unsigned char **) 
+			    scsi_init_malloc(size, GFP_ATOMIC);
+	    if (! new_dma_malloc_pages) {
+		size = (new_dma_sectors / SECTORS_PER_PAGE) *
+				    sizeof(FreeSectorBitmap);
+		scsi_init_free((char *)new_dma_malloc_freelist, size);
+		out_of_space = 1;
+	    }
+	}
+	else
+	    out_of_space = 1;
+	
+	if ((! out_of_space) && (new_dma_sectors > dma_sectors)) { 
+	    for(i = dma_sectors / SECTORS_PER_PAGE; 
+		i < new_dma_sectors / SECTORS_PER_PAGE; i++) {
+		new_dma_malloc_pages[i] = (unsigned char *)
+		    scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
+		if (! new_dma_malloc_pages[i])
+		    break;
+	    }
+	    if (i != new_dma_sectors / SECTORS_PER_PAGE) { /* clean up */
+		int k = i;
 
-    /*
-     * If we need more buffers, expand the list.
-     */
-    if( new_dma_sectors > dma_sectors ) { 
-	for(i=dma_sectors / SECTORS_PER_PAGE; i< new_dma_sectors / SECTORS_PER_PAGE; i++)
-	    new_dma_malloc_pages[i] = (unsigned char *)
-	        scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
+		out_of_space = 1;
+		for (i = 0; i < k; ++i)
+		    scsi_init_free(new_dma_malloc_pages[i], PAGE_SIZE);
+	    }
+	}
+	if (out_of_space) { /* try scaling down new_dma_sectors request (dpg) */
+	    printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, "
+		   "wanted=%u, scaling\n", dma_sectors, new_dma_sectors);
+	    if (new_dma_sectors < (8 * SECTORS_PER_PAGE))
+		break; /* pretty well hopeless ... */
+	    new_dma_sectors = (new_dma_sectors * 3) / 4;
+	    new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
+	    if (new_dma_sectors <= dma_sectors)
+		break; /* stick with what we have got */
+	}
+	else
+	    break; /* found space ... */
+    } /* end of for loop */
+    if (out_of_space) {
+	scsi_need_isa_buffer = new_need_isa_buffer; /* some useful info */
+	printk("      WARNING, not enough memory, pool not expanded\n");
+	return;
     }
 
     /* When we dick with the actual DMA list, we need to
@@ -2596,6 +2686,7 @@
     struct Scsi_Device_Template * sdtpnt;
     const char * name;
     unsigned long flags;
+    int out_of_space = 0;
 
     if (tpnt->next || !tpnt->detect) return 1;/* Must be already loaded, or
 					       * no detect routine available
@@ -2695,11 +2786,11 @@
         {
 	    if(shpnt->hostt == tpnt) 
             {
-                scan_scsis(shpnt,0,0,0,0);
-                if (shpnt->select_queue_depths != NULL)
-                {
-                    (shpnt->select_queue_depths)(shpnt, shpnt->host_queue);
-                }
+		scan_scsis(shpnt,0,0,0,0);
+		if (shpnt->select_queue_depths != NULL)
+		{
+		    (shpnt->select_queue_depths)(shpnt, shpnt->host_queue);
+		}
 	    }
         }
 
@@ -2718,14 +2809,19 @@
                 {
                     for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
                         if(sdtpnt->attach) (*sdtpnt->attach)(SDpnt);
-                    if(SDpnt->attached) scsi_build_commandblocks(SDpnt);
+                    if(SDpnt->attached) {
+			scsi_build_commandblocks(SDpnt);
+			if (0 == SDpnt->has_cmdblocks)
+			    out_of_space = 1;
+		    }
                 }
         }
 
 	/*
 	 * Now that we have all of the devices, resize the DMA pool,
 	 * as required.  */
-	resize_dma_pool();
+	if (! out_of_space)
+	    resize_dma_pool();
 
 
 	/* This does any final handling that is required. */
@@ -2746,7 +2842,13 @@
 #endif
 
     MOD_INC_USE_COUNT;
-    return 0;
+
+    if (out_of_space) {
+	scsi_unregister_host(tpnt); /* easiest way to clean up?? */
+	return 1;
+    }
+    else
+	return 0;
 }
 
 /*
@@ -3007,6 +3109,7 @@
 {
     Scsi_Device      * SDpnt;
     struct Scsi_Host * shpnt;
+    int out_of_space = 0;
 
     if (tpnt->next) return 1;
 
@@ -3048,6 +3151,8 @@
             {
                 SDpnt->online = TRUE;
                 scsi_build_commandblocks(SDpnt);
+		if (0 == SDpnt->has_cmdblocks)
+		    out_of_space = 1;
             }
         }
     }
@@ -3056,15 +3161,22 @@
      * This does any final handling that is required.
      */
     if(tpnt->finish && tpnt->nr_dev)  (*tpnt->finish)();
-    resize_dma_pool();
+    if (! out_of_space)
+	resize_dma_pool();
     MOD_INC_USE_COUNT;
-    return 0;
+
+    if (out_of_space) {
+	scsi_unregister_device(tpnt); /* easiest way to clean up?? */
+	return 1;
+    }
+    else
+	return 0;
 }
 
 static int scsi_unregister_device(struct Scsi_Device_Template * tpnt)
 {
     Scsi_Device * SDpnt;
-    Scsi_Cmnd * SCpnt;
+    Scsi_Cmnd * SCpnt, *SCnext;
     struct Scsi_Host * shpnt;
     struct Scsi_Device_Template * spnt;
     struct Scsi_Device_Template * prev_spnt;
@@ -3092,11 +3204,14 @@
 	         * Nobody is using this device any more.  Free all of the
 	         * command structures.
 	         */
-	        for(SCpnt = SDpnt->device_queue; SCpnt; 
-                    SCpnt = SCpnt->next)
+
+		SCpnt = SDpnt->device_queue;
+		if (SCpnt) SCnext = SCpnt->next;
+		for(; SCpnt; SCpnt = SCnext)
 	        {
 		    if(SCpnt == SDpnt->device_queue)
 			SDpnt->device_queue = SCpnt->next;
+		    SCnext = SCpnt->next;
 		    scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
 	        }
 	        SDpnt->has_cmdblocks = 0;
@@ -3229,7 +3344,7 @@
                 printk("(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n",
                        i++, 
 
-                       SCpnt->host->host_no,
+                       SCpnt->host ? SCpnt->host->host_no : -1,
                        SCpnt->channel,
                        SCpnt->target,
                        SCpnt->lun,
@@ -3294,6 +3409,7 @@
 int init_module(void) 
 {
     unsigned long size;
+    int has_space = 0;
 
     /*
      * This makes /proc/scsi visible.
@@ -3309,7 +3425,6 @@
     proc_scsi_register(0, &proc_scsi_scsi);
 #endif
 
-
     dma_sectors = PAGE_SIZE / SECTOR_SIZE;
     scsi_dma_free_sectors= dma_sectors;
     /*
@@ -3318,15 +3433,31 @@
      */
 
     /* One bit per sector to indicate free/busy */
-    size = (dma_sectors / SECTORS_PER_PAGE)*sizeof(FreeSectorBitmap);
-    dma_malloc_freelist = (FreeSectorBitmap *) scsi_init_malloc(size, GFP_ATOMIC);
-    memset(dma_malloc_freelist, 0, size);
-
-    /* One pointer per page for the page list */
-    dma_malloc_pages = (unsigned char **)
-	scsi_init_malloc((dma_sectors / SECTORS_PER_PAGE)*sizeof(*dma_malloc_pages), GFP_ATOMIC);
-    dma_malloc_pages[0] = (unsigned char *)
-	scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
+    size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
+    dma_malloc_freelist = (FreeSectorBitmap *) 
+				scsi_init_malloc(size, GFP_ATOMIC);
+    if (dma_malloc_freelist) {
+	/* One pointer per page for the page list */
+	dma_malloc_pages = (unsigned char **)scsi_init_malloc(
+		(dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages),
+							      GFP_ATOMIC);
+	if (dma_malloc_pages) {
+	    dma_malloc_pages[0] = (unsigned char *)
+			scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
+	    if (dma_malloc_pages[0])
+		has_space = 1;
+	}
+    }
+    if (! has_space) {
+	if (dma_malloc_freelist) {
+	    scsi_init_free((char *)dma_malloc_freelist, size);
+	    if (dma_malloc_pages)
+		scsi_init_free((char *)dma_malloc_pages,
+		(dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages));
+	}
+	printk("scsi::init_module: failed, out of memory\n");
+	return 1;
+    }
 
     /*
      * This is where the processing takes place for most everything
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/scsi.h linux.pre11.3/drivers/scsi/scsi.h
--- linux.vanilla/drivers/scsi/scsi.h	Tue Jun 15 16:49:51 1999
+++ linux.pre11.3/drivers/scsi/scsi.h	Tue Jul 20 01:42:53 1999
@@ -377,6 +377,9 @@
 extern int  scsi_decide_disposition (Scsi_Cmnd * SCpnt);
 extern int  scsi_block_when_processing_errors(Scsi_Device *);
 extern void scsi_sleep(int);
+extern int  scsi_partsize(struct buffer_head *bh, unsigned long capacity,
+                    unsigned int *cyls, unsigned int *hds,
+                    unsigned int *secs);
 
 /*
  *  scsi_abort aborts the current command that is executing on host host.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/scsi_error.c linux.pre11.3/drivers/scsi/scsi_error.c
--- linux.vanilla/drivers/scsi/scsi_error.c	Wed Mar 10 21:13:06 1999
+++ linux.pre11.3/drivers/scsi/scsi_error.c	Mon Jul 19 23:28:02 1999
@@ -1926,6 +1926,7 @@
 	int	               rtn;
 	struct semaphore sem = MUTEX_LOCKED;
         unsigned long flags;
+        struct fs_struct *fs;
 
 	lock_kernel();
 
@@ -1936,16 +1937,18 @@
 	 */
 	exit_mm(current);
 
-
 	current->session = 1;
 	current->pgrp = 1;
-        /*
-         * FIXME(eric) this is still a child process of the one that did the insmod.
-         * This needs to be attached to task[0] instead.
-         */
+	
+	/* Become as one with the init task */
+	
+	exit_fs(current);	/* current->fs->count--; */
+	fs = init_task.fs;
+	current->fs = fs;
+	atomic_inc(&fs->count);
 
 	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
-        current->fs->umask = 0;
+
 
 	/*
 	 * Set the name of this process.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sd.c linux.pre11.3/drivers/scsi/sd.c
--- linux.vanilla/drivers/scsi/sd.c	Tue Jun 15 16:49:51 1999
+++ linux.pre11.3/drivers/scsi/sd.c	Mon Jul 19 23:27:56 1999
@@ -1050,6 +1050,7 @@
 
     SCpnt->transfersize = rscsi_disks[dev].sector_size;
     SCpnt->underflow = this_count << 9;
+    SCpnt->cmd_len = 0;
     scsi_do_cmd (SCpnt, (void *) cmd, buff,
 		 this_count * rscsi_disks[dev].sector_size,
 		 rw_intr,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sgiwd93.c linux.pre11.3/drivers/scsi/sgiwd93.c
--- linux.vanilla/drivers/scsi/sgiwd93.c	Sun Nov  8 15:07:57 1998
+++ linux.pre11.3/drivers/scsi/sgiwd93.c	Mon Jul 19 23:28:03 1999
@@ -5,13 +5,14 @@
  *
  * (In all truth, Jed Schimmel wrote all this code.)
  *
- * $Id: sgiwd93.c,v 1.1 1998/05/01 01:35:42 ralf Exp $
+ * $Id: sgiwd93.c,v 1.13 1999/03/28 23:06:06 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blk.h>
 #include <linux/version.h>
+#include <linux/delay.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -21,6 +22,7 @@
 #include <asm/sgihpc.h>
 #include <asm/sgint23.h>
 #include <asm/irq.h>
+#include <asm/spinlock.h>
 #include <asm/io.h>
 
 #include "scsi.h"
@@ -65,14 +67,40 @@
 /* XXX woof! */
 static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
 	wd33c93_intr(sgiwd93_host);
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
 #undef DEBUG_DMA
 
+static inline
+void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len)
+{
+	unsigned long physaddr;
+	unsigned long count;
+	
+	dma_cache_wback_inv((unsigned long)addr,len);
+	physaddr = PHYSADDR(addr);
+	while (len) {
+		/*
+		 * even cntinfo could be up to 16383, without
+		 * magic only 8192 works correctly
+		 */
+		count = len > 8192 ? 8192 : len;
+		(*hcp)->desc.pbuf = physaddr;
+		(*hcp)->desc.cntinfo = count;
+		(*hcp)++;
+		len -= count;
+		physaddr += count;
+	}
+}
+
 static int dma_setup(Scsi_Cmnd *cmd, int datainp)
 {
-	struct WD33C93_hostdata *hdata = CMDHOSTDATA(cmd);
+	struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
 	wd33c93_regs *regp = hdata->regp;
 	struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base;
 	struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer;
@@ -84,21 +112,18 @@
 
 	hdata->dma_dir = datainp;
 
-	if(cmd->use_sg) {
+	if(cmd->SCp.buffers_residual) {
 		struct scatterlist *slp = cmd->SCp.buffer;
 		int i, totlen = 0;
 
 #ifdef DEBUG_DMA
 		printk("SCLIST<");
 #endif
-		for(i = 0; i <= (cmd->use_sg - 1); i++, hcp++) {
+		for(i = 0; i <= cmd->SCp.buffers_residual; i++) {
 #ifdef DEBUG_DMA
 			printk("[%p,%d]", slp[i].address, slp[i].length);
 #endif
-			dma_cache_wback_inv((unsigned long)slp[i].address,
-			                    PAGE_SIZE);
-			hcp->desc.pbuf = PHYSADDR(slp[i].address);
-			hcp->desc.cntinfo = (slp[i].length & HPCDMA_BCNT);
+			fill_hpc_entries (&hcp, slp[i].address, slp[i].length);
 			totlen += slp[i].length;
 		}
 #ifdef DEBUG_DMA
@@ -111,10 +136,16 @@
 #ifdef DEBUG_DMA
 		printk("ONEBUF<%p,%d>", cmd->SCp.ptr, cmd->SCp.this_residual);
 #endif
-		dma_cache_wback_inv((unsigned long)cmd->SCp.ptr, PAGE_SIZE);
-		hcp->desc.pbuf = PHYSADDR(cmd->SCp.ptr);
-		hcp->desc.cntinfo = (cmd->SCp.this_residual & HPCDMA_BCNT);
-		hcp++;
+		/*
+		 * wd33c93 shouldn't pass us bogus dma_setups, but
+		 * it does:-( The other wd33c93 drivers deal with
+		 * it the same way (which isn't that obvious).
+		 * IMHO a better fix would be, not to do these
+		 * dma setups in the first place
+		 */
+		if (cmd->SCp.ptr == NULL)
+			return 1;
+		fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual);
 		write_wd33c93_count(regp, cmd->SCp.this_residual);
 	}
 
@@ -141,9 +172,14 @@
 static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
 		     int status)
 {
-	struct WD33C93_hostdata *hdata = INSTHOSTDATA(instance);
+	struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)instance->hostdata;
 	wd33c93_regs *regp = hdata->regp;
-	struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) SCpnt->host->base;
+	struct hpc3_scsiregs *hregs;
+
+	if (!SCpnt)
+		return;
+
+	hregs = (struct hpc3_scsiregs *) SCpnt->host->base;
 
 #ifdef DEBUG_DMA
 	printk("dma_stop: status<%d> ", status);
@@ -158,7 +194,7 @@
 	hregs->ctrl = 0;
 
 	/* See how far we got and update scatterlist state if necessary. */
-	if(SCpnt->use_sg) {
+	if(SCpnt->SCp.buffers_residual) {
 		struct scatterlist *slp = SCpnt->SCp.buffer;
 		int totlen, wd93_residual, transferred, i;
 
@@ -178,7 +214,7 @@
 #ifdef DEBUG_DMA
 			printk("Jed was here...");
 #endif
-			for(i = 0; i <= (SCpnt->use_sg - 1); i++) {
+			for(i = 0; i <= SCpnt->SCp.buffers_residual; i++) {
 				if(slp[i].length >= transferred)
 					break;
 				transferred -= slp[i].length;
@@ -188,10 +224,10 @@
 #ifdef DEBUG_DMA
 			printk("did it all...");
 #endif
-			i = (SCpnt->use_sg - 1);
+			i = SCpnt->SCp.buffers_residual;
 		}
 		SCpnt->SCp.buffer = &slp[i];
-		SCpnt->SCp.buffers_residual = (SCpnt->use_sg - 1 - i);
+		SCpnt->SCp.buffers_residual = SCpnt->SCp.buffers_residual - i;
 		SCpnt->SCp.ptr = (char *) slp[i].address;
 		SCpnt->SCp.this_residual = slp[i].length;
 	}
@@ -200,6 +236,15 @@
 #endif
 }
 
+void sgiwd93_reset(void)
+{
+	struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0;
+
+	hregs->ctrl = HPC3_SCTRL_CRESET;
+	udelay (50);
+	hregs->ctrl = 0;
+}
+
 static inline void init_hpc_chain(uchar *buf)
 {
 	struct hpc_chunk *hcp = (struct hpc_chunk *) buf;
@@ -231,6 +276,7 @@
 
 	sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata));
 	sgiwd93_host->base = (unsigned char *) hregs;
+	sgiwd93_host->irq = 1;
 
 	buf = (uchar *) get_free_page(GFP_KERNEL);
 	init_hpc_chain(buf);
@@ -239,7 +285,7 @@
 	wd33c93_init(sgiwd93_host, (wd33c93_regs *) 0xbfbc0003,
 		     dma_setup, dma_stop, WD33C93_FS_16_20);
 
-	hdata = INSTHOSTDATA(sgiwd93_host);
+	hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata;
 	hdata->no_sync = 0;
 	hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
 	dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sgiwd93.h linux.pre11.3/drivers/scsi/sgiwd93.h
--- linux.vanilla/drivers/scsi/sgiwd93.h	Sun Nov  8 15:07:57 1998
+++ linux.pre11.3/drivers/scsi/sgiwd93.h	Mon Jul 19 23:28:03 1999
@@ -1,4 +1,4 @@
-/* $Id: sgiwd93.h,v 1.2 1998/05/04 09:18:49 ralf Exp $
+/* $Id: sgiwd93.h,v 1.5 1998/08/25 09:18:50 ralf Exp $
  * sgiwd93.h: SGI WD93 scsi definitions.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/sym53c416.c linux.pre11.3/drivers/scsi/sym53c416.c
--- linux.vanilla/drivers/scsi/sym53c416.c	Wed Mar 10 21:13:06 1999
+++ linux.pre11.3/drivers/scsi/sym53c416.c	Mon Jul 19 23:28:06 1999
@@ -3,6 +3,10 @@
  *  Low-level SCSI driver for sym53c416 chip.
  *  Copyright (C) 1998 Lieven Willems (lw_linux@hotmail.com)
  * 
+ *  Changes : 
+ * 
+ *  Marcelo Tosatti <marcelo@conectiva.com.br> : Added io_request_lock locking
+ * 
  *  LILO command line usage: sym53c416=<PORTBASE>[,<IRQ>]
  *
  *  This program is free software; you can redistribute it and/or modify it
@@ -30,6 +34,7 @@
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/spinlock.h>
 #include <linux/blk.h>
 #include <linux/version.h>
 #include "scsi.h"
@@ -371,7 +376,9 @@
     printk("sym53c416: Warning: Reset received\n");
     current_command->SCp.phase = idle;
     current_command->result = DID_RESET << 16;
+    spin_lock_irqsave(&io_request_lock, flags);
     current_command->scsi_done(current_command);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return;
     }
   if(int_reg & ILCMD)       /* Illegal Command */
@@ -379,7 +386,9 @@
     printk("sym53c416: Warning: Illegal Command: 0x%02x\n", inb(base + COMMAND_REG));
     current_command->SCp.phase = idle;
     current_command->result = DID_ERROR << 16;
+    spin_lock_irqsave(&io_request_lock, flags);
     current_command->scsi_done(current_command);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return;
     }
   if(status_reg & GE)         /* Gross Error */
@@ -387,7 +396,9 @@
     printk("sym53c416: Warning: Gross Error\n");
     current_command->SCp.phase = idle;
     current_command->result = DID_ERROR << 16;
+    spin_lock_irqsave(&io_request_lock, flags);
     current_command->scsi_done(current_command);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return;
     }
   if(status_reg & PE)         /* Parity Error */
@@ -395,7 +406,9 @@
     printk("sym53c416: Warning: Parity Error\n");
     current_command->SCp.phase = idle;
     current_command->result = DID_PARITY << 16;
+    spin_lock_irqsave(&io_request_lock, flags);
     current_command->scsi_done(current_command);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return;
     }
   if(pio_int_reg & (CE | OUE))
@@ -403,7 +416,9 @@
     printk("sym53c416: Warning: PIO Interrupt Error\n");
     current_command->SCp.phase = idle;
     current_command->result = DID_ERROR << 16;
+    spin_lock_irqsave(&io_request_lock, flags);
     current_command->scsi_done(current_command);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return;
     }
   if(int_reg & DIS)           /* Disconnect */
@@ -413,7 +428,10 @@
     else
       current_command->result = (current_command->SCp.Status & 0xFF) | ((current_command->SCp.Message & 0xFF) << 8) | (DID_OK << 16);
     current_command->SCp.phase = idle;
+
+    spin_lock_irqsave(&io_request_lock, flags);
     current_command->scsi_done(current_command);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return;
     }
   /* Now we handle SCSI phases         */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/wd33c93.h linux.pre11.3/drivers/scsi/wd33c93.h
--- linux.vanilla/drivers/scsi/wd33c93.h	Sun Nov  8 15:07:54 1998
+++ linux.pre11.3/drivers/scsi/wd33c93.h	Mon Jul 19 23:28:01 1999
@@ -190,6 +190,9 @@
 typedef struct {
    volatile unsigned char   SASR;
    char                     pad;
+#ifdef CONFIG_SGI
+   char                     pad2,pad3;
+#endif
    volatile unsigned char   SCMD;
 } wd33c93_regs;
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/scsi/wd7000.c linux.pre11.3/drivers/scsi/wd7000.c
--- linux.vanilla/drivers/scsi/wd7000.c	Sat Jan  9 21:50:44 1999
+++ linux.pre11.3/drivers/scsi/wd7000.c	Tue Jul 20 00:03:54 1999
@@ -1561,19 +1561,16 @@
 			break;
 
 		if (i == pass) {
-#if (LINUX_VERSION_CODE < 0x020100)
-#else
 		    void *biosaddr = ioremap (wd7000_biosaddr[biosaddr_ptr] +
 			                      signatures[sig_ptr].ofs,
 					      signatures[sig_ptr].len);
-#endif
-		    short bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig,
+		    short bios_match=0;
+		    
+		    if(biosaddr)
+		    	bios_match = memcmp ((char *) biosaddr, signatures[sig_ptr].sig,
 			                       signatures[sig_ptr].len);
 
-#if (LINUX_VERSION_CODE < 0x020100)
-#else
 		    iounmap (biosaddr);
-#endif
 
 		    if (! bios_match)
 		        goto bios_matched;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/Config.in linux.pre11.3/drivers/sgi/Config.in
--- linux.vanilla/drivers/sgi/Config.in	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/sgi/Config.in	Mon Jul 19 23:28:25 1999
@@ -0,0 +1,18 @@
+#
+# Character device configuration
+#
+mainmenu_option next_comment
+comment 'SGI devices'
+
+bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL
+if [ "$CONFIG_SGI_SERIAL" != "n" ]; then
+  define_bool CONFIG_SERIAL y
+fi
+
+bool 'SGI DS1286  RTC support' CONFIG_SGI_DS1286
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then  
+  tristate 'SGI Newport Graphics support' CONFIG_SGI_NEWPORT_GFX
+fi
+
+endmenu
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/Makefile linux.pre11.3/drivers/sgi/Makefile
--- linux.vanilla/drivers/sgi/Makefile	Sun Nov  8 15:08:16 1998
+++ linux.pre11.3/drivers/sgi/Makefile	Mon Jul 19 23:28:23 1999
@@ -8,13 +8,15 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 SUB_DIRS     :=
-MOD_SUB_DIRS := $(SUB_DIRS)
+MOD_SUB_DIRS := $(SUB_DIRS) char
 ALL_SUB_DIRS := $(SUB_DIRS) char
 
+
 L_OBJS   := 
 L_TARGET := sgi.a
+MOD_LIST_NAME := SGI_MODULES
 
-# Character devices for SGI machines.
+# Character and Audio devices for SGI machines.
 #
 SUB_DIRS += char
 L_OBJS += char/sgichar.o
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/Makefile linux.pre11.3/drivers/sgi/char/Makefile
--- linux.vanilla/drivers/sgi/char/Makefile	Sun Nov  8 15:08:16 1998
+++ linux.pre11.3/drivers/sgi/char/Makefile	Mon Jul 19 23:28:23 1999
@@ -8,11 +8,25 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := sgichar.o
-O_OBJS   := graphics.o streamable.o newport.o cons_newport.o sgicons.o \
-	vga_font.o rrm.o shmiq.o usema.o
+OX_OBJS := newport.o
+O_OBJS   := sgicons.o \
+	usema.o shmiq.o streamable.o
 
 ifeq ($(CONFIG_SGI_SERIAL),y)
   O_OBJS += sgiserial.o
+endif
+
+ifeq ($(CONFIG_SGI_DS1286),y)
+  O_OBJS += ds1286.o
+endif
+
+ifeq ($(CONFIG_SGI_NEWPORT_GFX),y)
+  O_OBJS +=  graphics.o rrm.o
+else 
+ifeq ($(CONFIG_SGI_NEWPORT_GFX),m)
+  OX_OBJS  +=  graphics_syms.o
+  MX_OBJS +=  graphics.o rrm.o
+endif
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/cons_newport.c linux.pre11.3/drivers/sgi/char/cons_newport.c
--- linux.vanilla/drivers/sgi/char/cons_newport.c	Sun Nov  8 15:08:16 1998
+++ linux.pre11.3/drivers/sgi/char/cons_newport.c	Thu Jan  1 01:00:00 1970
@@ -1,611 +0,0 @@
-/*
- * cons_newport.c: Newport graphics console code for the SGI.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: cons_newport.c,v 1.1 1998/01/10 19:05:47 ecd Exp $
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/kd.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/version.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/sgialib.h>
-#include <asm/ptrace.h>
-
-#include <linux/kbd_kern.h>
-#include <linux/vt_kern.h>
-#include <linux/consolemap.h>
-#include <linux/selection.h>
-#include <linux/console_struct.h>
-
-#include "gconsole.h"
-#include "newport.h"
-#include "graphics.h" /* Just for now */
-#include <asm/gfx.h>
-#include <asm/ng1.h>
-
-#if 0
-#include "linux_logo.h"
-#endif
-
-#define BMASK(c) (c << 24)
-
-#define RENDER(regs, cp) do { \
-(regs)->go.zpattern = BMASK((cp)[0x0]); (regs)->go.zpattern = BMASK((cp)[0x1]); \
-(regs)->go.zpattern = BMASK((cp)[0x2]); (regs)->go.zpattern = BMASK((cp)[0x3]); \
-(regs)->go.zpattern = BMASK((cp)[0x4]); (regs)->go.zpattern = BMASK((cp)[0x5]); \
-(regs)->go.zpattern = BMASK((cp)[0x6]); (regs)->go.zpattern = BMASK((cp)[0x7]); \
-(regs)->go.zpattern = BMASK((cp)[0x8]); (regs)->go.zpattern = BMASK((cp)[0x9]); \
-(regs)->go.zpattern = BMASK((cp)[0xa]); (regs)->go.zpattern = BMASK((cp)[0xb]); \
-(regs)->go.zpattern = BMASK((cp)[0xc]); (regs)->go.zpattern = BMASK((cp)[0xd]); \
-(regs)->go.zpattern = BMASK((cp)[0xe]); (regs)->go.zpattern = BMASK((cp)[0xf]); \
-} while(0)        
-
-#define REVERSE_RENDER(regs, cp) do { \
-(regs)->go.zpattern = BMASK((~(cp)[0x0])); (regs)->go.zpattern = BMASK((~(cp)[0x1])); \
-(regs)->go.zpattern = BMASK((~(cp)[0x2])); (regs)->go.zpattern = BMASK((~(cp)[0x3])); \
-(regs)->go.zpattern = BMASK((~(cp)[0x4])); (regs)->go.zpattern = BMASK((~(cp)[0x5])); \
-(regs)->go.zpattern = BMASK((~(cp)[0x6])); (regs)->go.zpattern = BMASK((~(cp)[0x7])); \
-(regs)->go.zpattern = BMASK((~(cp)[0x8])); (regs)->go.zpattern = BMASK((~(cp)[0x9])); \
-(regs)->go.zpattern = BMASK((~(cp)[0xa])); (regs)->go.zpattern = BMASK((~(cp)[0xb])); \
-(regs)->go.zpattern = BMASK((~(cp)[0xc])); (regs)->go.zpattern = BMASK((~(cp)[0xd])); \
-(regs)->go.zpattern = BMASK((~(cp)[0xe])); (regs)->go.zpattern = BMASK((~(cp)[0xf])); \
-} while(0)        
-
-extern int default_red[16], default_grn[16], default_blu[16];
-extern unsigned char video_type;
-
-static int cursor_pos = -1;
-struct newport_regs *npregs;
-
-#define TESTVAL 0xdeadbeef
-#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11)
-
-static inline void
-newport_disable_video(void)
-{
-	unsigned short treg;
-
-	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EVIDEO)));
-}
-
-static inline void
-newport_enable_video(void)
-{
-	unsigned short treg;
-
-	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO));
-}
-
-static inline void
-newport_disable_cursor(void)
-{
-	unsigned short treg;
-
-	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP)));
-}
-
-#if 0
-static inline void
-newport_enable_cursor(void)
-{
-	unsigned short treg;
-
-	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
-	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
-}
-#endif
-
-static inline void
-newport_init_cmap(void)
-{
-	unsigned short i;
-
-	for(i = 0; i < 16; i++) {
-		newport_bfwait();
-		newport_cmap_setaddr(npregs, color_table[i]);
-		newport_cmap_setrgb(npregs,
-				    default_red[i],
-				    default_grn[i],
-				    default_blu[i]);
-	}
-}
-
-#if 0
-static inline void
-newport_init_cursor(void)
-{
-	unsigned char cursor[256];
-	unsigned short *cookie;
-	int i;
-
-	for(i = 0; i < 256; i++)
-		cursor[i] = 0x0;
-	for(i = 211; i < 256; i+=4) {
-		cursor[i] = 0xff;
-#if 0
-		cursor[(i + 128) << 2] = 0xff;
-		cursor[((i + 128) << 2) + 1] = 0xff;
-#endif
-	}
-
-	/* Load the SRAM on the VC2 for this new GLYPH. */
-	cookie = (unsigned short *) cursor;
-	newport_vc2_set(npregs, VC2_IREG_RADDR, VC2_CGLYPH_ADDR);
-	npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
-			       NPORT_DMODE_W2 | VC2_PROTOCOL);
-	for(i = 0; i < 128; i++) {
-		newport_bfwait();
-		npregs->set.dcbdata0.hwords.s1 = *cookie++;
-	}
-
-	/* Place the cursor at origin. */
-	newport_vc2_set(npregs, VC2_IREG_CURSX, 0);
-	newport_vc2_set(npregs, VC2_IREG_CURSY, 0);
-	newport_enable_cursor();
-}
-#endif
-
-static inline void
-newport_clear_screen(void)
-{
-	newport_wait();
-	npregs->set.wrmask = 0xffffffff;
-	npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
-			      NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
-			      NPORT_DMODE0_STOPY);
-	npregs->set.colori = 0;
-	npregs->set.xystarti = 0;
-	npregs->go.xyendi = (((1280 + 63) << 16)|(1024));
-	newport_bfwait();
-}
-
-static inline void
-newport_render_version(void)
-{
-#if 0
-	unsigned short *ush;
-	int currcons = 0;
-	char *p;
-
-	ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20;
-	for (p = "SGI/Linux version " UTS_RELEASE; *p; p++, ush++) {
-		*ush = (attr << 8) + *p;
-		newport_blitc (*ush, (unsigned long) ush);
-	}
-#endif
-}
-
-#if 0
-static inline void
-newport_render_logo(void)
-{
-	int i, xpos, ypos;
-	unsigned char *bmap;
-
-	xpos = 8;
-	ypos = 18;
-
-	newport_wait();
-	npregs->set.colori = 9;
-	npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
-			      NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
-			      NPORT_DMODE0_L32);
-
-	for(i = 0; i < 80; i+=8) {
-		/* Set coordinates for bitmap operation. */
-		npregs->set.xystarti = ((xpos + i) << 16) | ypos;
-		npregs->set.xyendi = (((xpos + i) + 7) << 16);
-		newport_wait();
-
-		bmap = linux_logo + (i * 80);
-		RENDER(npregs, bmap); bmap += 0x10;
-		RENDER(npregs, bmap); bmap += 0x10;
-		RENDER(npregs, bmap); bmap += 0x10;
-		RENDER(npregs, bmap); bmap += 0x10;
-		RENDER(npregs, bmap);
-	}
-	prom_getchar();
-	prom_imode();
-}
-#endif
-
-static inline void
-newport_render_background(int xpos, int ypos, int ci)
-{
-	newport_wait();
-	npregs->set.wrmask = 0xffffffff;
-	npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
-			      NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
-			      NPORT_DMODE0_STOPY);
-	npregs->set.colori = ci;
-	npregs->set.xystarti = (xpos << 16) | ypos;
-	npregs->go.xyendi = ((xpos + 7) << 16) | (ypos + 15);
-}
-
-void
-newport_set_origin(unsigned short offset)
-{
-	/* maybe this works... */
-	__origin = offset;
-}
-
-void
-newport_hide_cursor(void)
-{
-	int xpos, ypos, idx;
-	unsigned long flags;
-
-	if(vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
-		return;
-	save_and_cli(flags);
-
-	idx = cursor_pos;
-	if(idx == -1) {
-		restore_flags(flags);
-		return;
-	}
-	xpos = 8 + ((idx % video_num_columns) << 3);
-	ypos = 18 + ((idx / video_num_columns) << 4);
-	newport_render_background(xpos, ypos, 0);
-	restore_flags(flags);
-}
-
-void
-newport_set_cursor(int currcons)
-{
-	int xpos, ypos, idx, oldpos;
-	unsigned short *sp, *osp, cattr;
-	unsigned long flags;
-	unsigned char *p;
-
-	if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
-		return;
-
-	if (__real_origin != __origin)
-		__set_origin(__real_origin);
-
-	save_and_cli(flags);
-
-	idx = (pos - video_mem_base) >> 1;
-	sp = (unsigned short *) pos;
-	oldpos = cursor_pos;
-	cursor_pos = idx;
-	if(!deccm) {
-		hide_cursor();
-		restore_flags(flags);
-		return;
-	}
-	xpos = 8 + ((idx % video_num_columns) << 3);
-	ypos = 18 + ((idx / video_num_columns) << 4);
-	if(oldpos != -1) {
-		int oxpos, oypos;
-
-		/* Restore old location. */
-		osp = (unsigned short *) ((oldpos << 1) + video_mem_base);
-		oxpos = 8 + ((oldpos % video_num_columns) << 3);
-		oypos = 18 + ((oldpos / video_num_columns) << 4);
-		cattr = *osp;
-		newport_render_background(oxpos, oypos, (cattr & 0xf000) >> 12);
-		p = &vga_font[(cattr & 0xff) << 4];
-		newport_wait();
-		npregs->set.colori = (cattr & 0x0f00) >> 8;
-		npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
-				      NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
-				      NPORT_DMODE0_L32);
-		npregs->set.xystarti = (oxpos << 16) | oypos;
-		npregs->set.xyendi = ((oxpos + 7) << 16);
-		newport_wait();
-		RENDER(npregs, p);
-	}
-	cattr = *sp;
-	newport_render_background(xpos, ypos, (cattr & 0xf000) >> 12);
-	p = &vga_font[(cattr & 0xff) << 4];
-	newport_wait();
-	npregs->set.colori = (cattr & 0x0f00) >> 8;
-	npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
-			      NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
-			      NPORT_DMODE0_L32);
-	npregs->set.xystarti = (xpos << 16) | ypos;
-	npregs->set.xyendi = ((xpos + 7) << 16);
-	newport_wait();
-	REVERSE_RENDER(npregs, p);
-	restore_flags (flags);
-	return;
-}
-
-void
-newport_get_scrmem(int currcons)
-{
-	memcpyw((unsigned short *)vc_scrbuf[currcons],
-		(unsigned short *)origin, video_screen_size);
-	origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
-	scr_end = video_mem_end = video_mem_start + video_screen_size;
-	pos = origin + y*video_size_row + (x<<1);
-}
-
-void
-newport_set_scrmem(int currcons, long offset)
-{
-	if (video_mem_term - video_mem_base < offset + video_screen_size)
-		offset = 0;
-	memcpyw((unsigned short *)(video_mem_base + offset),
-		(unsigned short *) origin, video_screen_size);
-	video_mem_start = video_mem_base;
-	video_mem_end = video_mem_term;
-	origin = video_mem_base + offset;
-	scr_end = origin + video_screen_size;
-	pos = origin + y*video_size_row + (x<<1);
-	has_wrapped = 0;
-}
-
-int
-newport_set_get_cmap(unsigned char * arg, int set)
-{
-	unsigned short ent;
-	int i;
-
-	i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, 16*3);
-	if (i)
-		return i;
-
-	for (i=0; i<16; i++) {
-		if (set) {
-			__get_user(default_red[i], arg++);
-			__get_user(default_grn[i], arg++);
-			__get_user(default_blu[i], arg++);
-		} else {
-			__put_user (default_red[i], arg++);
-			__put_user (default_grn[i], arg++);
-			__put_user (default_blu[i], arg++);
-		}
-	}
-	if (set) {
-		for (i=0; i<MAX_NR_CONSOLES; i++) {
-			if (vc_cons_allocated(i)) {
-				int j, k;
-				for (j = k = 0; j<16; j++) {
-					vc_cons[i].d->vc_palette[k++] =
-						default_red[j];
-					vc_cons[i].d->vc_palette[k++] =
-						default_grn[j];
-					vc_cons[i].d->vc_palette[k++] =
-						default_blu[j];
-				}
-			}
-		}
-		if(console_blanked || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
-			return 0;
-		for(ent = 0; ent < 16; ent++) {
-			newport_bfwait();
-			newport_cmap_setaddr(npregs, ent);
-			newport_cmap_setrgb(npregs,
-					    default_red[ent],
-					    default_grn[ent],
-					    default_blu[ent]);
-		}
-	}
-
-	return 0;
-}
-
-void
-newport_blitc(unsigned short charattr, unsigned long addr)
-{
-	int idx, xpos, ypos;
-	unsigned char *p;
-
-	idx = (addr - (video_mem_base + (__origin<<1))) >> 1;
-	xpos = 8 + ((idx % video_num_columns) << 3);
-	ypos = 18 + ((idx / video_num_columns) << 4);
-
-	p = &vga_font[(charattr & 0xff) << 4];
-	charattr = (charattr >> 8) & 0xff;
-
-	newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4);
-
-	/* Set the color and drawing mode. */
-	newport_wait();
-	npregs->set.colori = charattr & 0xf;
-	npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
-			      NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
-			      NPORT_DMODE0_L32);
-
-	/* Set coordinates for bitmap operation. */
-	npregs->set.xystarti = (xpos << 16) | ypos;
-	npregs->set.xyendi = ((xpos + 7) << 16);
-	newport_wait();
-
-	/* Go, baby, go... */
-	RENDER(npregs, p);
-}
-
-void
-newport_memsetw(void * s, unsigned short c, unsigned int count)
-{
-	unsigned short * addr = (unsigned short *) s;
-
-	count /= 2;
-	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) {
-		while (count) {
-			count--;
-			*addr++ = c;
-		}
-		return;
-	}
-	if ((unsigned long) addr + count > video_mem_term ||
-	    (unsigned long) addr < video_mem_base) {
-	    	if ((unsigned long) addr + count <= video_mem_term ||
-	    	    (unsigned long) addr > video_mem_base) {
-			while (count) {
-				count--;
-				*addr++ = c;
-			}
-			return;
-	    	} else {
-			while (count) {
-				count--;
-				scr_writew(c, addr++);
-			}
-		}
-	} else {
-		while (count) {
-			count--;
-			if (*addr != c) {
-				newport_blitc(c, (unsigned long)addr);
-				*addr++ = c;
-			} else
-				addr++;
-		}
-	}
-}
-
-void
-newport_memcpyw(unsigned short *to, unsigned short *from, unsigned int count)
-{
-	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) {
-		memcpy(to, from, count);
-		return;
-	}
-	if ((unsigned long) to + count > video_mem_term ||
-	    (unsigned long) to < video_mem_base) {
-	    	if ((unsigned long) to + count <= video_mem_term ||
-	    	    (unsigned long) to > video_mem_base)
-	    	    	memcpy(to, from, count);
-	    	else {
-	    		count /= 2;
-			while (count) {
-				count--;
-				scr_writew(scr_readw(from++), to++);
-			}
-		}
-	} else {
-		count /= 2;
-		while (count) {
-			count--;
-			if (*to != *from) {
-				newport_blitc(*from, (unsigned long)to);
-				*to++ = *from++;
-			} else {
-				from++;
-				to++;
-			}
-		}
-	}
-}
-
-struct console_ops newport_console = {
-	newport_set_origin,
-	newport_hide_cursor,
-	newport_set_cursor,
-	newport_get_scrmem,
-	newport_set_scrmem,
-	newport_set_get_cmap,
-	newport_blitc,
-	newport_memsetw,
-	newport_memcpyw
-};
-
-/* Currently hard-coded values that are the same as those found on my system */
-struct ng1_info newport_board_info = {
-	{ "NG1", "" /* what is the label? */, 1280, 1024, sizeof (struct ng1_info) },
-	6,			/* boardrev */
-	1,			/* rex3rev */
-	0,			/* vc2rev */
-	2,			/* monitor type */
-        0,			/* videoinstalled */
-	3,			/* mcrev */
-	24,			/* bitplanes */
-	0,			/* xmap9rev */
-	2,			/* cmaprev */
-	{ 256, 1280, 1024, 76},	/* ng1_vof_info */
-	13,			/* paneltype */
-	0
-};
-
-void
-newport_reset (void)
-{
-	newport_wait();
-	newport_enable_video();
-
-	/* Init the cursor disappear. */
-	newport_wait();
-#if 0
-	newport_init_cursor();
-#else
-	newport_disable_cursor();
-#endif
-
-	newport_init_cmap();
-
-	/* Clear the screen. */
-	newport_clear_screen();
-}
-
-/* right now the newport does not do anything at all */
-struct graphics_ops newport_graphic_ops = {
-	0,			      /* owner */
-	0,			      /* current user */
-	(void *) &newport_board_info, /* board info */
-	sizeof (struct ng1_info),     /* size of our data structure */
-	0, 0,			      /* g_regs, g_regs_size */
-	newport_save, newport_restore, /* g_save_context, g_restore_context */
-	newport_reset, newport_ioctl /* g_reset_console, g_ioctl */
-};
-
-struct graphics_ops *
-newport_probe (int slot, const char **name)
-{
-	struct newport_regs *p;
-
-	npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000);
-	
-	p = npregs;
-	p->cset.config = NPORT_CFG_GD0;
-
-	if(newport_wait()) {
-		prom_printf("whoops, timeout, no NEWPORT there?");
-		return 0;
-	}
-
-	p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) {
-		prom_printf("newport_probe: read back wrong value ;-(\n");
-		return 0;
-	}
-
-	if (slot == 0){
-		register_gconsole (&newport_console);
-		video_type = VIDEO_TYPE_SGI;
-		can_do_color = 1;
-		*name = "NEWPORT";
-	}
-
-	newport_reset ();
-	newport_render_version();
-#if 0
-	newport_render_logo();
-#endif
-	newport_graphic_ops.g_regs = 0x1f0f0000;
-	newport_graphic_ops.g_regs_size = sizeof (struct newport_regs);
-	return &newport_graphic_ops;
-}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/ds1286.c linux.pre11.3/drivers/sgi/char/ds1286.c
--- linux.vanilla/drivers/sgi/char/ds1286.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/sgi/char/ds1286.c	Mon Jul 19 23:28:23 1999
@@ -0,0 +1,570 @@
+/* $Id: ds1286.c,v 1.3.2.3 1999/06/17 12:08:44 ralf Exp $
+ *
+ *	Real Time Clock interface for Linux	
+ *
+ *	Copyright (C) 1998, 1999 Ralf Baechle
+ *	
+ *	Based on code written by Paul Gortmaker.
+ *
+ *	This driver allows use of the real time clock (built into
+ *	nearly all computers) from user space. It exports the /dev/rtc
+ *	interface supporting various ioctl() and also the /proc/rtc
+ *	pseudo-file for status information.
+ *
+ *	The ioctls can be used to set the interrupt behaviour and
+ *	generation rate from the RTC via IRQ 8. Then the /dev/rtc
+ *	interface can be used to make use of these timer interrupts,
+ *	be they interval or alarm based.
+ *
+ *	The /dev/rtc interface will block on reads until an interrupt
+ *	has been received. If a RTC interrupt has already happened,
+ *	it will output an unsigned long and then block. The output value
+ *	contains the interrupt status in the low byte and the number of
+ *	interrupts since the last read in the remaining high bytes. The 
+ *	/dev/rtc interface can also be used with the select(2) call.
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/rtc.h>
+
+#include <asm/ds1286.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/spinlock.h>
+#include <asm/system.h>
+
+#define DS1286_VERSION		"1.0"
+
+/*
+ *	We sponge a minor off of the misc major. No need slurping
+ *	up another valuable major dev number for this. If you add
+ *	an ioctl, make sure you don't conflict with SPARC's RTC
+ *	ioctls.
+ */
+
+static struct wait_queue *ds1286_wait;
+
+static long long ds1286_llseek(struct file *file, loff_t offset, int origin);
+
+static ssize_t ds1286_read(struct file *file, char *buf,
+			size_t count, loff_t *ppos);
+
+static int ds1286_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg);
+
+static unsigned int ds1286_poll(struct file *file, poll_table *wait);
+
+void get_rtc_time (struct rtc_time *rtc_tm);
+void get_rtc_alm_time (struct rtc_time *alm_tm);
+
+void set_rtc_irq_bit(unsigned char bit);
+void clear_rtc_irq_bit(unsigned char bit);
+
+static inline unsigned char ds1286_is_updating(void);
+
+#ifdef __SMP__
+static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
+/*
+ *	Bits in rtc_status. (7 bits of room for future expansion)
+ */
+
+#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
+#define RTC_TIMER_ON		0x02	/* missed irq timer active	*/
+
+unsigned char ds1286_status = 0;	/* bitmapped status byte.	*/
+unsigned long ds1286_freq = 0;		/* Current periodic IRQ rate	*/
+unsigned long ds1286_irq_data = 0;	/* our output to the world	*/
+
+unsigned char days_in_mo[] = 
+{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/*
+ *	A very tiny interrupt handler. It runs with SA_INTERRUPT set,
+ *	so that there is no possibility of conflicting with the
+ *	set_rtc_mmss() call that happens during some timer interrupts.
+ *	(See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
+ */
+
+/*
+ *	Now all the various file operations that we export.
+ */
+
+static long long ds1286_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+static ssize_t ds1286_read(struct file *file, char *buf,
+                           size_t count, loff_t *ppos)
+{
+	struct wait_queue wait = { current, NULL };
+	unsigned long data;
+	ssize_t retval;
+	
+	if (count < sizeof(unsigned long))
+		return -EINVAL;
+
+	add_wait_queue(&ds1286_wait, &wait);
+
+	current->state = TASK_INTERRUPTIBLE;
+		
+	while ((data = xchg(&ds1286_irq_data, 0)) == 0) {
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+		schedule();
+	}
+
+	retval = put_user(data, (unsigned long *)buf); 
+	if (!retval)
+		retval = sizeof(unsigned long); 
+ out:
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&ds1286_wait, &wait);
+
+	return retval;
+}
+
+static int ds1286_ioctl(struct inode *inode, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+
+	struct rtc_time wtime; 
+
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* Mask alarm int. enab. bit	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = CMOS_READ(RTC_CMD);
+		val |=  RTC_TDM;
+		CMOS_WRITE(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_AIE_ON:	/* Allow alarm interrupts.	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = CMOS_READ(RTC_CMD);
+		val &=  ~RTC_TDM;
+		CMOS_WRITE(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_WIE_OFF:	/* Mask watchdog int. enab. bit	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = CMOS_READ(RTC_CMD);
+		val |= RTC_WAM;
+		CMOS_WRITE(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_WIE_ON:	/* Allow watchdog interrupts.	*/
+	{
+		unsigned int flags;
+		unsigned char val;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		val = CMOS_READ(RTC_CMD);
+		val &= ~RTC_WAM;
+		CMOS_WRITE(val, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	case RTC_ALM_READ:	/* Read the present alarm time */
+	{
+		/*
+		 * This returns a struct rtc_time. Reading >= 0xc0
+		 * means "don't care" or "match all". Only the tm_hour,
+		 * tm_min, and tm_sec values are filled in.
+		 */
+
+		get_rtc_alm_time(&wtime);
+		break; 
+	}
+	case RTC_ALM_SET:	/* Store a time into the alarm */
+	{
+		/*
+		 * This expects a struct rtc_time. Writing 0xff means
+		 * "don't care" or "match all". Only the tm_hour,
+		 * tm_min and tm_sec are used.
+		 */
+		unsigned char hrs, min, sec;
+		struct rtc_time alm_tm;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		if (copy_from_user(&alm_tm, (struct rtc_time*)arg,
+				   sizeof(struct rtc_time)))
+			return -EFAULT;
+
+		hrs = alm_tm.tm_hour;
+		min = alm_tm.tm_min;
+
+		if (hrs >= 24)
+			hrs = 0xff;
+
+		if (min >= 60)
+			min = 0xff;
+
+		BIN_TO_BCD(sec);
+		BIN_TO_BCD(min);
+		BIN_TO_BCD(hrs);
+
+		spin_lock(&ds1286_lock);
+		CMOS_WRITE(hrs, RTC_HOURS_ALARM);
+		CMOS_WRITE(min, RTC_MINUTES_ALARM);
+		spin_unlock(&ds1286_lock);
+
+		return 0;
+	}
+	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
+	{
+		get_rtc_time(&wtime);
+		break;
+	}
+	case RTC_SET_TIME:	/* Set the RTC */
+	{
+		struct rtc_time rtc_tm;
+		unsigned char mon, day, hrs, min, sec, leap_yr;
+		unsigned char save_control;
+		unsigned int yrs, flags;
+
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+
+		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
+				   sizeof(struct rtc_time)))
+			return -EFAULT;
+
+		yrs = rtc_tm.tm_year + 1900;
+		mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
+		day = rtc_tm.tm_mday;
+		hrs = rtc_tm.tm_hour;
+		min = rtc_tm.tm_min;
+		sec = rtc_tm.tm_sec;
+
+		if (yrs < 1970)
+			return -EINVAL;
+
+		leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+		if ((mon > 12) || (day == 0))
+			return -EINVAL;
+
+		if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
+			return -EINVAL;
+
+		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+			return -EINVAL;
+
+		if ((yrs -= 1940) > 255)    /* They are unsigned */
+			return -EINVAL;
+
+		if (yrs >= 100)
+			yrs -= 100;
+
+		BIN_TO_BCD(sec);
+		BIN_TO_BCD(min);
+		BIN_TO_BCD(hrs);
+		BIN_TO_BCD(day);
+		BIN_TO_BCD(mon);
+		BIN_TO_BCD(yrs);
+
+		spin_lock_irqsave(&ds1286_lock, flags);
+		save_control = CMOS_READ(RTC_CMD);
+		CMOS_WRITE((save_control|RTC_TE), RTC_CMD);
+
+		CMOS_WRITE(yrs, RTC_YEAR);
+		CMOS_WRITE(mon, RTC_MONTH);
+		CMOS_WRITE(day, RTC_DATE);
+		CMOS_WRITE(hrs, RTC_HOURS);
+		CMOS_WRITE(min, RTC_MINUTES);
+		CMOS_WRITE(sec, RTC_SECONDS);
+		CMOS_WRITE(0, RTC_HUNDREDTH_SECOND);
+
+		CMOS_WRITE(save_control, RTC_CMD);
+		spin_unlock_irqrestore(&ds1286_lock, flags);
+
+		return 0;
+	}
+	default:
+		return -EINVAL;
+	}
+	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+}
+
+/*
+ *	We enforce only one user at a time here with the open/close.
+ *	Also clear the previous interrupt data on an open, and clean
+ *	up things on a close.
+ */
+
+static int ds1286_open(struct inode *inode, struct file *file)
+{
+	if(ds1286_status & RTC_IS_OPEN)
+		return -EBUSY;
+
+	ds1286_status |= RTC_IS_OPEN;
+	ds1286_irq_data = 0;
+	return 0;
+}
+
+static int ds1286_release(struct inode *inode, struct file *file)
+{
+	ds1286_status &= ~RTC_IS_OPEN;
+	return 0;
+}
+
+static unsigned int ds1286_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &ds1286_wait, wait);
+	if (ds1286_irq_data != 0)
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+/*
+ *	The various file operations we support.
+ */
+
+static struct file_operations ds1286_fops = {
+	ds1286_llseek,
+	ds1286_read,
+	NULL,		/* No write */
+	NULL,		/* No readdir */
+	ds1286_poll,
+	ds1286_ioctl,
+	NULL,		/* No mmap */
+	ds1286_open,
+	NULL,		/* No flush */
+	ds1286_release
+};
+
+static struct miscdevice ds1286_dev=
+{
+	RTC_MINOR,
+	"rtc",
+	&ds1286_fops
+};
+
+__initfunc(int ds1286_init(void))
+{
+	printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION);
+	misc_register(&ds1286_dev);
+
+	ds1286_wait = NULL;
+
+	return 0;
+}
+
+static char *days[] = {
+	"***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+/*
+ *	Info exported via "/proc/rtc".
+ */
+int get_ds1286_status(char *buf)
+{
+	char *p, *s;
+	struct rtc_time tm;
+	unsigned char hundredth, month, cmd, amode;
+
+	p = buf;
+
+	get_rtc_time(&tm);
+	hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND);
+	hundredth = BCD_TO_BIN(hundredth);
+
+	p += sprintf(p,
+	             "rtc_time\t: %02d:%02d:%02d.%02d\n"
+	             "rtc_date\t: %04d-%02d-%02d\n",
+		     tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth,
+		     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+
+	/*
+	 * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will
+	 * match any value for that particular field. Values that are
+	 * greater than a valid time, but less than 0xc0 shouldn't appear.
+	 */
+	get_rtc_alm_time(&tm);
+	p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]);
+	if (tm.tm_hour <= 24)
+		p += sprintf(p, "%02d:", tm.tm_hour);
+	else
+		p += sprintf(p, "**:");
+
+	if (tm.tm_min <= 59)
+		p += sprintf(p, "%02d\n", tm.tm_min);
+	else
+		p += sprintf(p, "**\n");
+
+	month = CMOS_READ(RTC_MONTH);
+	p += sprintf(p,
+	             "oscillator\t: %s\n"
+	             "square_wave\t: %s\n",
+	             (month & RTC_EOSC) ? "disabled" : "enabled",
+	             (month & RTC_ESQW) ? "disabled" : "enabled");
+
+	amode = ((CMOS_READ(RTC_MINUTES_ALARM) & 0x80) >> 5) |
+	        ((CMOS_READ(RTC_HOURS_ALARM) & 0x80) >> 6) |
+	        ((CMOS_READ(RTC_DAY_ALARM) & 0x80) >> 7);
+	if (amode == 7)      s = "each minute";
+	else if (amode == 3) s = "minutes match";
+	else if (amode == 1) s = "hours and minutes match";
+	else if (amode == 0) s = "days, hours and minutes match";
+	else                 s = "invalid";
+	p += sprintf(p, "alarm_mode\t: %s\n", s);
+
+	cmd = CMOS_READ(RTC_CMD);
+	p += sprintf(p,
+	             "alarm_enable\t: %s\n"
+	             "wdog_alarm\t: %s\n"
+	             "alarm_mask\t: %s\n"
+	             "wdog_alarm_mask\t: %s\n"
+	             "interrupt_mode\t: %s\n"
+	             "INTB_mode\t: %s_active\n"
+	             "interrupt_pins\t: %s\n",
+		     (cmd & RTC_TDF) ? "yes" : "no",
+		     (cmd & RTC_WAF) ? "yes" : "no",
+		     (cmd & RTC_TDM) ? "disabled" : "enabled",
+		     (cmd & RTC_WAM) ? "disabled" : "enabled",
+		     (cmd & RTC_PU_LVL) ? "pulse" : "level",
+		     (cmd & RTC_IBH_LO) ? "low" : "high",
+	             (cmd & RTC_IPSW) ? "unswapped" : "swapped");
+
+	return  p - buf;
+}
+
+/*
+ * Returns true if a clock update is in progress
+ */
+static inline unsigned char ds1286_is_updating(void)
+{
+	return CMOS_READ(RTC_CMD) & RTC_TE;
+}
+
+void get_rtc_time(struct rtc_time *rtc_tm)
+{
+	unsigned long uip_watchdog = jiffies;
+	unsigned char save_control;
+	unsigned int flags;
+
+	/*
+	 * read RTC once any update in progress is done. The update
+	 * can take just over 2ms. We wait 10 to 20ms. There is no need to
+	 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+	 * If you need to know *exactly* when a second has started, enable
+	 * periodic update complete interrupts, (via ioctl) and then 
+	 * immediately read /dev/rtc which will block until you get the IRQ.
+	 * Once the read clears, read the RTC time (again via ioctl). Easy.
+	 */
+
+	if (ds1286_is_updating() != 0)
+		while (jiffies - uip_watchdog < 2*HZ/100)
+			barrier();
+
+	/*
+	 * Only the values that we read from the RTC are set. We leave
+	 * tm_wday, tm_yday and tm_isdst untouched. Even though the
+	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+	 * by the RTC when initially set to a non-zero value.
+	 */
+	spin_lock_irqsave(&ds1286_lock, flags);
+	save_control = CMOS_READ(RTC_CMD);
+	CMOS_WRITE((save_control|RTC_TE), RTC_CMD);
+
+	rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
+	rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
+	rtc_tm->tm_hour = CMOS_READ(RTC_HOURS) & 0x1f;
+	rtc_tm->tm_mday = CMOS_READ(RTC_DATE);
+	rtc_tm->tm_mon = CMOS_READ(RTC_MONTH) & 0x1f;
+	rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
+
+	CMOS_WRITE(save_control, RTC_CMD);
+	spin_unlock_irqrestore(&ds1286_lock, flags);
+
+	BCD_TO_BIN(rtc_tm->tm_sec);
+	BCD_TO_BIN(rtc_tm->tm_min);
+	BCD_TO_BIN(rtc_tm->tm_hour);
+	BCD_TO_BIN(rtc_tm->tm_mday);
+	BCD_TO_BIN(rtc_tm->tm_mon);
+	BCD_TO_BIN(rtc_tm->tm_year);
+
+	/*
+	 * Account for differences between how the RTC uses the values
+	 * and how they are defined in a struct rtc_time;
+	 */
+	if (rtc_tm->tm_year < 45)
+		rtc_tm->tm_year += 30;
+	if ((rtc_tm->tm_year += 40) < 70)
+		rtc_tm->tm_year += 100;
+
+	rtc_tm->tm_mon--;
+}
+
+void get_rtc_alm_time(struct rtc_time *alm_tm)
+{
+	unsigned char cmd;
+	unsigned int flags;
+
+	/*
+	 * Only the values that we read from the RTC are set. That
+	 * means only tm_wday, tm_hour, tm_min.
+	 */
+	spin_lock_irqsave(&ds1286_lock, flags);
+	alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM) & 0x7f;
+	alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM)  & 0x1f;
+	alm_tm->tm_wday = CMOS_READ(RTC_DAY_ALARM)    & 0x07;
+	cmd = CMOS_READ(RTC_CMD);
+	spin_unlock_irqrestore(&ds1286_lock, flags);
+
+	BCD_TO_BIN(alm_tm->tm_min);
+	BCD_TO_BIN(alm_tm->tm_hour);
+	alm_tm->tm_sec = 0;
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/graphics.c linux.pre11.3/drivers/sgi/char/graphics.c
--- linux.vanilla/drivers/sgi/char/graphics.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/graphics.c	Mon Jul 19 23:28:23 1999
@@ -1,7 +1,10 @@
-/*
+/* $Id: graphics.c,v 1.16 1999/04/01 23:45:00 ulfc Exp $
+ *
  * gfx.c: support for SGI's /dev/graphics, /dev/opengl
  *
  * Author: Miguel de Icaza (miguel@nuclecu.unam.mx)
+ *         Ralf Baechle (ralf@gnu.org)
+ *         Ulf Carlsson (ulfc@bun.falkenberg.se)
  *
  * On IRIX, /dev/graphics is [10, 146]
  *          /dev/opengl   is [10, 147]
@@ -21,35 +24,56 @@
  * We implement those misterious things, and tried not to think about
  * the reasons behind them.
  */
+#include <linux/kernel.h>
 #include <linux/fs.h>
+#include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/malloc.h>
+#include <linux/module.h>
 #include <asm/uaccess.h>
 #include "gconsole.h"
 #include "graphics.h"
+#include "usema.h"
 #include <asm/gfx.h>
 #include <asm/rrm.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/newport.h>
 
-/* The boards */
-#include "newport.h"
+#define DEBUG
 
-#ifdef PRODUCTION_DRIVER
-#define enable_gconsole()
-#define disable_gconsole()
-#endif
+/* The boards */
+extern struct graphics_ops *newport_probe (int, const char **);
 
 static struct graphics_ops cards [MAXCARDS];
 static int boards;
 
 #define GRAPHICS_CARD(inode) 0
 
+/*
+void enable_gconsole(void) {};
+void disable_gconsole(void) {};
+*/
+
+
 int
 sgi_graphics_open (struct inode *inode, struct file *file)
 {
+	struct newport_regs *nregs =
+		(struct newport_regs *) KSEG1ADDR(cards[0].g_regs);
+
+	newport_wait();
+	nregs->set.wrmask = 0xffffffff;
+	nregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+			     NPORT_DMODE0_STOPY);
+	nregs->set.colori = 1;
+	nregs->set.xystarti = (0 << 16) | 0;
+	nregs->go.xyendi = (1280 << 16) | 1024;
+
 	return 0;
 }
 
@@ -59,10 +83,10 @@
 	unsigned int board;
 	unsigned int devnum = GRAPHICS_CARD (inode->i_rdev);
 	int i;
-	
+
 	if ((cmd >= RRM_BASE) && (cmd <= RRM_CMD_LIMIT))
 		return rrm_command (cmd-RRM_BASE, (void *) arg);
-	
+
 	switch (cmd){
 	case GFX_GETNUM_BOARDS:
 		return boards;
@@ -113,7 +137,7 @@
 			printk ("Parameter board does not match the current board\n");
 			return -EINVAL;
 		}
-		
+
 		if (board >= boards)
 			return -EINVAL;
 
@@ -126,11 +150,11 @@
 		 * sgi_graphics_mmap
 		 */
 		disable_gconsole ();
-		r = do_mmap (file, (unsigned long)vaddr, cards [board].g_regs_size,
-			 PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE, 0);
+		r = do_mmap (file, (unsigned long)vaddr,
+			     cards[board].g_regs_size, PROT_READ|PROT_WRITE,
+			     MAP_FIXED|MAP_PRIVATE, 0);
 		if (r)
 			return r;
-
 	}
 
 	/* Strange, the real mapping seems to be done at GFX_ATTACH_BOARD,
@@ -141,13 +165,13 @@
 
 	case GFX_LABEL:
 		return 0;
-			
+
 		/* Version check
 		 * for my IRIX 6.2 X server, this is what the kernel returns
 		 */
 	case 1:
 		return 3;
-		
+
 	/* Xsgi does not use this one, I assume minor is the board being queried */
 	case GFX_IS_MANAGED:
 		if (devnum > boards)
@@ -166,14 +190,15 @@
 sgi_graphics_close (struct inode *inode, struct file *file)
 {
 	int board = GRAPHICS_CARD (inode->i_rdev);
-	
+
 	/* Tell the rendering manager that one client is going away */
 	rrm_close (inode, file);
 
 	/* Was this file handle from the board owner?, clear it */
 	if (current == cards [board].g_owner){
 		cards [board].g_owner = 0;
-		(*cards [board].g_reset_console)();
+		if (cards [board].g_reset_console)
+			(*cards [board].g_reset_console)();
 		enable_gconsole ();
 	}
 	return 0;
@@ -184,37 +209,42 @@
  */
 
 unsigned long
-sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int write_access)
+sgi_graphics_nopage (struct vm_area_struct *vma, unsigned long address, int
+		     no_share)
 {
-	unsigned long page;
+	pgd_t *pgd; pmd_t *pmd; pte_t *pte; 
 	int board = GRAPHICS_CARD (vma->vm_dentry->d_inode->i_rdev);
 
-#ifdef DEBUG_GRAPHICS
-	printk ("Got a page fault for board %d address=%lx guser=%lx\n", board, address,
-		cards [board].g_user);
+	unsigned long virt_add, phys_add;
+
+#ifdef DEBUG
+	printk ("Got a page fault for board %d address=%lx guser=%lx\n", board,
+		address, (unsigned long) cards[board].g_user);
 #endif
 	
-	/* 1. figure out if another process has this mapped,
-	 * and revoke the mapping in that case.
-	 */
-	if (cards [board].g_user && cards [board].g_user != current){
-		/* FIXME: save graphics context here, dump it to rendering node? */
-		remove_mapping (cards [board].g_user, vma->vm_start, vma->vm_end);
+	/* Figure out if another process has this mapped, and revoke the mapping
+	 * in that case. */
+	if (cards[board].g_user && cards[board].g_user != current) {
+		/* FIXME: save graphics context here, dump it to rendering
+		 * node? */
+
+		remove_mapping(cards[board].g_user, vma->vm_start, vma->vm_end);
 	}
+
 	cards [board].g_user = current;
-#if DEBUG_GRAPHICS
-	printk ("Registers: 0x%lx\n", cards [board].g_regs);
-	printk ("vm_start:  0x%lx\n", vma->vm_start);
-	printk ("address:   0x%lx\n", address);
-	printk ("diff:      0x%lx\n", (address - vma->vm_start));
 
-	printk ("page/pfn:  0x%lx\n", page);
-	printk ("TLB entry: %lx\n", pte_val (mk_pte (page + PAGE_OFFSET, PAGE_USERIO)));
-#endif
-	
-	/* 2. Map this into the current process address space */
-	page = ((cards [board].g_regs) + (address - vma->vm_start));
-	return page + PAGE_OFFSET;
+	/* Map the physical address of the newport registers into the address
+	 * space of this process */
+
+	virt_add = address & PAGE_MASK;
+	phys_add = cards[board].g_regs + virt_add - vma->vm_start;
+	remap_page_range(virt_add, phys_add, PAGE_SIZE, vma->vm_page_prot);
+
+	pgd = pgd_offset(current->mm, address);
+	pmd = pmd_offset(pgd, address);
+	pte = pte_offset(pmd, address);
+	printk("page: %08lx\n", pte_page(*pte));
+	return pte_page(*pte);
 }
 
 /*
@@ -237,7 +267,7 @@
 };
 	
 int
-sgi_graphics_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma)
+sgi_graphics_mmap (struct file *file, struct vm_area_struct *vma)
 {
 	uint size;
 
@@ -250,12 +280,13 @@
 
 	/* 2. Set the special tlb permission bits */
 	vma->vm_page_prot = PAGE_USERIO;
-		
+
 	/* final setup */
-	vma->vm_dentry = dget (file->f_dentry);
+	vma->vm_file = file;
 	return 0;
 }
-	
+
+#if 0
 /* Do any post card-detection setup on graphics_ops */
 static void
 graphics_ops_post_init (int slot)
@@ -264,6 +295,7 @@
 	cards [slot].g_owner = (struct task_struct *) 0;
 	cards [slot].g_user  = (struct task_struct *) 0;
 }
+#endif
 
 struct file_operations sgi_graphics_fops = {
 	NULL,			/* llseek */
@@ -284,33 +316,36 @@
 
 /* /dev/graphics */
 static struct miscdevice dev_graphics = {
-        SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops
+	SGI_GRAPHICS_MINOR, "sgi-graphics", &sgi_graphics_fops
 };
 
 /* /dev/opengl */
 static struct miscdevice dev_opengl = {
-        SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops
+	SGI_OPENGL_MINOR, "sgi-opengl", &sgi_graphics_fops
 };
 
 /* This is called later from the misc-init routine */
-void
-gfx_register (void)
+__initfunc(void gfx_register (void))
 {
 	misc_register (&dev_graphics);
 	misc_register (&dev_opengl);
 }
 
-void 
-gfx_init (const char **name)
+__initfunc(void gfx_init (const char **name))
 {
+#if 0
 	struct console_ops *console;
 	struct graphics_ops *g;
+#endif
 
 	printk ("GFX INIT: ");
 	shmiq_init ();
 	usema_init ();
-	
-	if ((g = newport_probe (boards, name)) != 0){
+
+	boards++;
+
+#if 0
+	if ((g = newport_probe (boards, name)) != 0) {
 		cards [boards] = *g;
 		graphics_ops_post_init (boards);
 		boards++;
@@ -318,11 +353,39 @@
 	}
 	/* Add more graphic drivers here */
 	/* Keep passing console around */
-	
-	if (boards > MAXCARDS){
-		printk ("Too many cards found on the system\n");
-		prom_halt ();
+#endif
+
+	if (boards > MAXCARDS)
+		printk (KERN_WARNING "Too many cards found on the system\n");
+}
+
+#ifdef MODULE
+int init_module(void) {
+	static int initiated = 0;
+
+	printk("SGI Newport Graphics version %i.%i.%i\n",42,54,69);
+
+	if (!initiated++) {
+		shmiq_init();
+		usema_init();
+		printk("Adding first board\n");
+		boards++;
+		cards[0].g_regs = 0x1f0f0000;
+		cards[0].g_regs_size = sizeof (struct newport_regs);
 	}
+
+	printk("Boards: %d\n", boards);
+
+	misc_register (&dev_graphics);
+	misc_register (&dev_opengl);
+
+	return 0;
 }
 
+void cleanup_module(void) {
+	printk("Shutting down SGI Newport Graphics\n");
 
+	misc_deregister (&dev_graphics);
+	misc_deregister (&dev_opengl);
+}
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/graphics.h linux.pre11.3/drivers/sgi/char/graphics.h
--- linux.vanilla/drivers/sgi/char/graphics.h	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/graphics.h	Mon Jul 19 23:28:23 1999
@@ -25,4 +25,3 @@
 
 void shmiq_init (void);
 void streamable_init (void);
-void usema_init (void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/graphics_syms.c linux.pre11.3/drivers/sgi/char/graphics_syms.c
--- linux.vanilla/drivers/sgi/char/graphics_syms.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/sgi/char/graphics_syms.c	Mon Jul 19 23:28:25 1999
@@ -0,0 +1,37 @@
+/*
+ * graphics_syms.c: interfaces for SGI Indy newport graphics
+ *
+ * Copyright (C) 1999 Alex deVries <puffin@redhat.com>
+ *
+ * We should not even be trying to compile this if we are not doing
+ * a module.
+ */
+
+#define __NO_VERSION__
+#include <linux/config.h>
+#include <linux/module.h>
+
+/* extern int rrm_command (unsigned int cmd, void *arg);
+extern int rrm_close (struct inode *inode, struct file *file);
+EXPORT_SYMBOL(rrm_command);
+EXPORT_SYMBOL(rrm_close);
+
+
+*/
+extern void shmiq_init (void);
+extern void usema_init(void);
+
+EXPORT_SYMBOL(shmiq_init);
+EXPORT_SYMBOL(usema_init);
+
+extern void disable_gconsole(void);
+extern void enable_gconsole(void);
+extern void remove_mapping (struct task_struct *task, unsigned long start,
+      unsigned long end);
+
+EXPORT_SYMBOL(disable_gconsole);
+EXPORT_SYMBOL(enable_gconsole);
+EXPORT_SYMBOL(remove_mapping);
+
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/newport.c linux.pre11.3/drivers/sgi/char/newport.c
--- linux.vanilla/drivers/sgi/char/newport.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/newport.c	Mon Jul 19 23:28:23 1999
@@ -4,13 +4,20 @@
  *
  * Author: Miguel de Icaza
  */
+
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <asm/types.h>
 #include <asm/gfx.h>
 #include <asm/ng1.h>
 #include <asm/uaccess.h>
-#include "newport.h"
+#include <asm/newport.h>
+#include <linux/config.h>
+#include <linux/module.h>
+
+struct newport_regs *npregs;
+
+EXPORT_SYMBOL(npregs);
 
 /* Kernel routines for supporting graphics context switching */
 
@@ -167,7 +174,6 @@
 {
 	switch (cmd){
 	case NG1_SETDISPLAYMODE: {
-		int i;
 		struct ng1_setdisplaymode_args request;
 		
 		if (copy_from_user (&request, (void *) arg, sizeof (request)))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/newport.h linux.pre11.3/drivers/sgi/char/newport.h
--- linux.vanilla/drivers/sgi/char/newport.h	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/newport.h	Thu Jan  1 01:00:00 1970
@@ -1,585 +0,0 @@
-/* $Id: newport.h,v 1.1 1998/01/10 19:05:58 ecd Exp $
- * newport.h: Defines and register layout for NEWPORT graphics
- *            hardware.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-
-#ifndef _SGI_NEWPORT_H
-#define _SGI_NEWPORT_H
-
-
-typedef volatile unsigned long npireg_t;
-
-union npfloat {
-	volatile float f;
-	npireg_t       i;
-};
-
-typedef union npfloat npfreg_t;
-
-union np_dcb {
-	npireg_t all;
-	struct { volatile unsigned short s0, s1; } hwords;
-	struct { volatile unsigned char b0, b1, b2, b3; } bytes;
-};
-
-struct newport_rexregs {
-	npireg_t drawmode1;      /* GL extra mode bits */
-	
-#define DM1_PLANES         0x00000007
-#define    DM1_NOPLANES    0x00000000
-#define    DM1_RGBPLANES   0x00000001
-#define    DM1_RGBAPLANES  0x00000002
-#define    DM1_OLAYPLANES  0x00000004
-#define    DM1_PUPPLANES   0x00000005
-#define    DM1_CIDPLANES   0x00000006
-	
-#define NPORT_DMODE1_DDMASK      0x00000018
-#define NPORT_DMODE1_DD4         0x00000000
-#define NPORT_DMODE1_DD8         0x00000008
-#define NPORT_DMODE1_DD12        0x00000010
-#define NPORT_DMODE1_DD24        0x00000018
-#define NPORT_DMODE1_DSRC        0x00000020
-#define NPORT_DMODE1_YFLIP       0x00000040
-#define NPORT_DMODE1_RWPCKD      0x00000080
-#define NPORT_DMODE1_HDMASK      0x00000300
-#define NPORT_DMODE1_HD4         0x00000000
-#define NPORT_DMODE1_HD8         0x00000100
-#define NPORT_DMODE1_HD12        0x00000200
-#define NPORT_DMODE1_HD32        0x00000300
-#define NPORT_DMODE1_RWDBL       0x00000400
-#define NPORT_DMODE1_ESWAP       0x00000800 /* Endian swap */
-#define NPORT_DMODE1_CCMASK      0x00007000
-#define NPORT_DMODE1_CCLT        0x00001000
-#define NPORT_DMODE1_CCEQ        0x00002000
-#define NPORT_DMODE1_CCGT        0x00004000
-#define NPORT_DMODE1_RGBMD       0x00008000
-#define NPORT_DMODE1_DENAB       0x00010000 /* Dither enable */
-#define NPORT_DMODE1_FCLR        0x00020000 /* Fast clear */
-#define NPORT_DMODE1_BENAB       0x00040000 /* Blend enable */
-#define NPORT_DMODE1_SFMASK      0x00380000
-#define NPORT_DMODE1_SF0         0x00000000
-#define NPORT_DMODE1_SF1         0x00080000
-#define NPORT_DMODE1_SFDC        0x00100000
-#define NPORT_DMODE1_SFMDC       0x00180000
-#define NPORT_DMODE1_SFSA        0x00200000
-#define NPORT_DMODE1_SFMSA       0x00280000
-#define NPORT_DMODE1_DFMASK      0x01c00000
-#define NPORT_DMODE1_DF0         0x00000000
-#define NPORT_DMODE1_DF1         0x00400000
-#define NPORT_DMODE1_DFSC        0x00800000
-#define NPORT_DMODE1_DFMSC       0x00c00000
-#define NPORT_DMODE1_DFSA        0x01000000
-#define NPORT_DMODE1_DFMSA       0x01400000
-#define NPORT_DMODE1_BBENAB      0x02000000 /* Back blend enable */
-#define NPORT_DMODE1_PFENAB      0x04000000 /* Pre-fetch enable */
-#define NPORT_DMODE1_ABLEND      0x08000000 /* Alpha blend */
-#define NPORT_DMODE1_LOMASK      0xf0000000
-#define NPORT_DMODE1_LOZERO      0x00000000
-#define NPORT_DMODE1_LOAND       0x10000000
-#define NPORT_DMODE1_LOANDR      0x20000000
-#define NPORT_DMODE1_LOSRC       0x30000000
-#define NPORT_DMODE1_LOANDI      0x40000000
-#define NPORT_DMODE1_LODST       0x50000000
-#define NPORT_DMODE1_LOXOR       0x60000000
-#define NPORT_DMODE1_LOOR        0x70000000
-#define NPORT_DMODE1_LONOR       0x80000000
-#define NPORT_DMODE1_LOXNOR      0x90000000
-#define NPORT_DMODE1_LONDST      0xa0000000
-#define NPORT_DMODE1_LOORR       0xb0000000
-#define NPORT_DMODE1_LONSRC      0xc0000000
-#define NPORT_DMODE1_LOORI       0xd0000000
-#define NPORT_DMODE1_LONAND      0xe0000000
-#define NPORT_DMODE1_LOONE       0xf0000000
-
-	npireg_t drawmode0;      /* REX command register */
-
-	/* These bits define the graphics opcode being performed. */
-#define NPORT_DMODE0_OPMASK   0x00000003 /* Opcode mask */
-#define NPORT_DMODE0_NOP      0x00000000 /* No operation */
-#define NPORT_DMODE0_RD       0x00000001 /* Read operation */
-#define NPORT_DMODE0_DRAW     0x00000002 /* Draw operation */
-#define NPORT_DMODE0_S2S      0x00000003 /* Screen to screen operation */
-
-	/* The following decide what addressing mode(s) are to be used */
-#define NPORT_DMODE0_AMMASK   0x0000001c /* Address mode mask */
-#define NPORT_DMODE0_SPAN     0x00000000 /* Spanning address mode */
-#define NPORT_DMODE0_BLOCK    0x00000004 /* Block address mode */
-#define NPORT_DMODE0_ILINE    0x00000008 /* Iline address mode */
-#define NPORT_DMODE0_FLINE    0x0000000c /* Fline address mode */
-#define NPORT_DMODE0_ALINE    0x00000010 /* Aline address mode */
-#define NPORT_DMODE0_TLINE    0x00000014 /* Tline address mode */
-#define NPORT_DMODE0_BLINE    0x00000018 /* Bline address mode */
-
-	/* And now some misc. operation control bits. */
-#define NPORT_DMODE0_DOSETUP  0x00000020
-#define NPORT_DMODE0_CHOST    0x00000040
-#define NPORT_DMODE0_AHOST    0x00000080
-#define NPORT_DMODE0_STOPX    0x00000100
-#define NPORT_DMODE0_STOPY    0x00000200
-#define NPORT_DMODE0_SK1ST    0x00000400
-#define NPORT_DMODE0_SKLST    0x00000800
-#define NPORT_DMODE0_ZPENAB   0x00001000
-#define NPORT_DMODE0_LISPENAB 0x00002000
-#define NPORT_DMODE0_LISLST   0x00004000
-#define NPORT_DMODE0_L32      0x00008000
-#define NPORT_DMODE0_ZOPQ     0x00010000
-#define NPORT_DMODE0_LISOPQ   0x00020000
-#define NPORT_DMODE0_SHADE    0x00040000
-#define NPORT_DMODE0_LRONLY   0x00080000
-#define NPORT_DMODE0_XYOFF    0x00100000
-#define NPORT_DMODE0_CLAMP    0x00200000
-#define NPORT_DMODE0_ENDPF    0x00400000
-#define NPORT_DMODE0_YSTR     0x00800000
-
-	npireg_t lsmode;      /* Mode for line stipple ops */
-	npireg_t lspattern;   /* Pattern for line stipple ops */
-	npireg_t lspatsave;   /* Backup save pattern */
-	npireg_t zpattern;    /* Pixel zpattern */
-	npireg_t colorback;   /* Background color */
-	npireg_t colorvram;   /* Clear color for fast vram */
-	npireg_t alpharef;    /* Reference value for afunctions */
-	unsigned long pad0;
-	npireg_t smask0x;     /* Window GL relative screen mask 0 */
-	npireg_t smask0y;     /* Window GL relative screen mask 0 */
-	npireg_t _setup;
-	npireg_t _stepz;
-	npireg_t _lsrestore;
-	npireg_t _lssave;
-
-	unsigned long _pad1[0x30];
-
-	/* Iterators, full state for context switch */
-	npfreg_t _xstart;	/* X-start point (current) */
-	npfreg_t _ystart;	/* Y-start point (current) */
-	npfreg_t _xend;		/* x-end point */
-	npfreg_t _yend;		/* y-end point */
-	npireg_t xsave;		/* copy of xstart integer value for BLOCk addressing MODE */
-	npireg_t xymove;	/* x.y offset from xstart, ystart for relative operations */
-	npfreg_t bresd;
-	npfreg_t bress1;;
-	npireg_t bresoctinc1;
-	volatile int bresrndinc2;
-	npireg_t brese1;
-	npireg_t bress2;
-	npireg_t aweight0;
-	npireg_t aweight1;
-	npfreg_t xstartf;
-	npfreg_t ystartf;
-	npfreg_t xendf;
-	npfreg_t yendf;
-	npireg_t xstarti;
-	npfreg_t xendf1;
-	npireg_t xystarti;
-	npireg_t xyendi;
-	npireg_t xstartendi;
-
-	unsigned long _unused2[0x29];
-
-	npfreg_t colorred;
-	npfreg_t coloralpha;
-	npfreg_t colorgrn;
-	npfreg_t colorblue;
-	npfreg_t slopered;
-	npfreg_t slopealpha;
-	npfreg_t slopegrn;
-	npfreg_t slopeblue;
-	npireg_t wrmask;
-	npireg_t colori;
-	npfreg_t colorx;
-	npfreg_t slopered1;
-	npireg_t hostrw0;
-	npireg_t hostrw1;
-	npireg_t dcbmode;
-#define NPORT_DMODE_WMASK   0x00000003
-#define NPORT_DMODE_W4      0x00000000
-#define NPORT_DMODE_W1      0x00000001
-#define NPORT_DMODE_W2      0x00000002
-#define NPORT_DMODE_W3      0x00000003
-#define NPORT_DMODE_EDPACK  0x00000004
-#define NPORT_DMODE_ECINC   0x00000008
-#define NPORT_DMODE_CMASK   0x00000070
-#define NPORT_DMODE_AMASK   0x00000780
-#define NPORT_DMODE_AVC2    0x00000000
-#define NPORT_DMODE_ACMALL  0x00000080
-#define NPORT_DMODE_ACM0    0x00000100
-#define NPORT_DMODE_ACM1    0x00000180
-#define NPORT_DMODE_AXMALL  0x00000200
-#define NPORT_DMODE_AXM0    0x00000280
-#define NPORT_DMODE_AXM1    0x00000300
-#define NPORT_DMODE_ABT     0x00000380
-#define NPORT_DMODE_AVCC1   0x00000400
-#define NPORT_DMODE_AVAB1   0x00000480
-#define NPORT_DMODE_ALG3V0  0x00000500
-#define NPORT_DMODE_A1562   0x00000580
-#define NPORT_DMODE_ESACK   0x00000800
-#define NPORT_DMODE_EASACK  0x00001000
-#define NPORT_DMODE_CWMASK  0x0003e000
-#define NPORT_DMODE_CHMASK  0x007c0000
-#define NPORT_DMODE_CSMASK  0x0f800000
-#define NPORT_DMODE_SENDIAN 0x10000000
-
-	unsigned long _unused3;
-
-	union np_dcb dcbdata0;
-	npireg_t dcbdata1;
-};
-
-struct newport_cregs {
-	npireg_t smask1x;
-	npireg_t smask1y;
-	npireg_t smask2x;
-	npireg_t smask2y;
-	npireg_t smask3x;
-	npireg_t smask3y;
-	npireg_t smask4x;
-	npireg_t smask4y;
-	npireg_t topscan;
-	npireg_t xywin;
-	npireg_t clipmode;
-#define NPORT_CMODE_SM0   0x00000001
-#define NPORT_CMODE_SM1   0x00000002
-#define NPORT_CMODE_SM2   0x00000004
-#define NPORT_CMODE_SM3   0x00000008
-#define NPORT_CMODE_SM4   0x00000010
-#define NPORT_CMODE_CMSK  0x00001e00
-
-	unsigned long _unused0;
-	unsigned long config;
-#define NPORT_CFG_G32MD   0x00000001
-#define NPORT_CFG_BWIDTH  0x00000002
-#define NPORT_CFG_ERCVR   0x00000004
-#define NPORT_CFG_BDMSK   0x00000078
-#define NPORT_CFG_GDMSK   0x00000f80
-#define NPORT_CFG_GD0     0x00000080
-#define NPORT_CFG_GD1     0x00000100
-#define NPORT_CFG_GD2     0x00000200
-#define NPORT_CFG_GD3     0x00000400
-#define NPORT_CFG_GD4     0x00000800
-#define NPORT_CFG_GFAINT  0x00001000
-#define NPORT_CFG_TOMSK   0x0000e000
-#define NPORT_CFG_VRMSK   0x00070000
-#define NPORT_CFG_FBTYP   0x00080000
-
-	npireg_t _unused1;
-	npireg_t stat;
-#define NPORT_STAT_VERS   0x00000007
-#define NPORT_STAT_GBUSY  0x00000008
-#define NPORT_STAT_BBUSY  0x00000010
-#define NPORT_STAT_VRINT  0x00000020
-#define NPORT_STAT_VIDINT 0x00000040
-#define NPORT_STAT_GLMSK  0x00001f80
-#define NPORT_STAT_BLMSK  0x0007e000
-#define NPORT_STAT_BFIRQ  0x00080000
-#define NPORT_STAT_GFIRQ  0x00100000
-
-	npireg_t ustat;
-	npireg_t dreset;
-};
-
-struct newport_regs {
-	struct newport_rexregs set;
-	unsigned long _unused0[0x16e];
-	struct newport_rexregs go;
-	unsigned long _unused1[0x22e];
-	struct newport_cregs cset;
-	unsigned long _unused2[0x1ef];
-	struct newport_cregs cgo;
-};
-extern struct newport_regs *npregs;
-
-
-typedef struct {
-	unsigned int drawmode1;
-	unsigned int drawmode0;
-	unsigned int lsmode;   
-	unsigned int lspattern;
-	unsigned int lspatsave;
-	unsigned int zpattern; 
-	unsigned int colorback;
-	unsigned int colorvram;
-	unsigned int alpharef; 
-	unsigned int smask0x;  
-	unsigned int smask0y;  
-	unsigned int _xstart;  
-	unsigned int _ystart;  
-	unsigned int _xend;    
-	unsigned int _yend;    
-	unsigned int xsave;    
-	unsigned int xymove;   
-	unsigned int bresd;    
-	unsigned int bress1;   
-	unsigned int bresoctinc1;
-	unsigned int bresrndinc2;
-	unsigned int brese1;     
-	unsigned int bress2;     
-	
-	unsigned int aweight0;    
-	unsigned int aweight1;    
-	unsigned int colorred;    
-	unsigned int coloralpha;  
-	unsigned int colorgrn;    
-	unsigned int colorblue;   
-	unsigned int slopered;    
-	unsigned int slopealpha;  
-	unsigned int slopegrn;    
-	unsigned int slopeblue;   
-	unsigned int wrmask;      
-	unsigned int hostrw0;     
-	unsigned int hostrw1;     
-	
-        /* configregs */
-	
-	unsigned int smask1x;    
-	unsigned int smask1y;    
-	unsigned int smask2x;    
-	unsigned int smask2y;    
-	unsigned int smask3x;    
-	unsigned int smask3y;    
-	unsigned int smask4x;    
-	unsigned int smask4y;    
-	unsigned int topscan;    
-	unsigned int xywin;      
-	unsigned int clipmode;   
-	unsigned int config;     
-	
-        /* dcb registers */
-	unsigned int dcbmode;   
-	unsigned int dcbdata0;  
-	unsigned int dcbdata1;
-} newport_ctx;
-
-/* Reading/writing VC2 registers. */
-#define VC2_REGADDR_INDEX      0x00000000
-#define VC2_REGADDR_IREG       0x00000010
-#define VC2_REGADDR_RAM        0x00000030
-#define VC2_PROTOCOL           (NPORT_DMODE_EASACK | 0x00800000 | 0x00040000)
-
-#define VC2_VLINET_ADDR        0x000
-#define VC2_VFRAMET_ADDR       0x400
-#define VC2_CGLYPH_ADDR        0x500
-
-/* Now the Indexed registers of the VC2. */
-#define VC2_IREG_VENTRY        0x00
-#define VC2_IREG_CENTRY        0x01
-#define VC2_IREG_CURSX         0x02
-#define VC2_IREG_CURSY         0x03
-#define VC2_IREG_CCURSX        0x04
-#define VC2_IREG_DENTRY        0x05
-#define VC2_IREG_SLEN          0x06
-#define VC2_IREG_RADDR         0x07
-#define VC2_IREG_VFPTR         0x08
-#define VC2_IREG_VLSPTR        0x09
-#define VC2_IREG_VLIR          0x0a
-#define VC2_IREG_VLCTR         0x0b
-#define VC2_IREG_CTPTR         0x0c
-#define VC2_IREG_WCURSY        0x0d
-#define VC2_IREG_DFPTR         0x0e
-#define VC2_IREG_DLTPTR        0x0f
-#define VC2_IREG_CONTROL       0x10
-#define VC2_IREG_CONFIG        0x20
-
-extern inline void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg,
-				   unsigned short val)
-{
-	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 |
-			   NPORT_DMODE_ECINC | VC2_PROTOCOL);
-	regs->set.dcbdata0.all = (vc2ireg << 24) | (val << 8);
-}
-
-extern inline unsigned short newport_vc2_get(struct newport_regs *regs,
-					     unsigned char vc2ireg)
-{
-	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 |
-			   NPORT_DMODE_ECINC | VC2_PROTOCOL);
-	regs->set.dcbdata0.bytes.b3 = vc2ireg;
-	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_IREG | NPORT_DMODE_W2 |
-			   NPORT_DMODE_ECINC | VC2_PROTOCOL);
-	return regs->set.dcbdata0.hwords.s1;
-}
-
-/* VC2 Control register bits */
-#define VC2_CTRL_EVIRQ     0x0001
-#define VC2_CTRL_EDISP     0x0002
-#define VC2_CTRL_EVIDEO    0x0004
-#define VC2_CTRL_EDIDS     0x0008
-#define VC2_CTRL_ECURS     0x0010
-#define VC2_CTRL_EGSYNC    0x0020
-#define VC2_CTRL_EILACE    0x0040
-#define VC2_CTRL_ECDISP    0x0080
-#define VC2_CTRL_ECCURS    0x0100
-#define VC2_CTRL_ECG64     0x0200
-#define VC2_CTRL_GLSEL     0x0400
-
-/* Controlling the color map on NEWPORT. */
-#define NCMAP_REGADDR_AREG   0x00000000
-#define NCMAP_REGADDR_ALO    0x00000000
-#define NCMAP_REGADDR_AHI    0x00000010
-#define NCMAP_REGADDR_PBUF   0x00000020
-#define NCMAP_REGADDR_CREG   0x00000030
-#define NCMAP_REGADDR_SREG   0x00000040
-#define NCMAP_REGADDR_RREG   0x00000060
-#define NCMAP_PROTOCOL       (0x00008000 | 0x00040000 | 0x00800000)
-
-static inline void newport_cmap_setaddr(struct newport_regs *regs,
-					unsigned short addr)
-{
-	regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL |
-			   NPORT_DMODE_SENDIAN | NPORT_DMODE_ECINC |
-			   NCMAP_REGADDR_AREG | NPORT_DMODE_W2);
-	regs->set.dcbdata0.hwords.s1 = addr;
-	regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL |
-			   NCMAP_REGADDR_PBUF | NPORT_DMODE_W3);
-}
-
-static inline void newport_cmap_setrgb(struct newport_regs *regs,
-				       unsigned char red,
-				       unsigned char green,
-				       unsigned char blue)
-{
-	regs->set.dcbdata0.all =
-		(red << 24) |
-		(green << 16) |
-		(blue << 8);
-}
-
-/* Miscellaneous NEWPORT routines. */
-#define BUSY_TIMEOUT 100000
-static inline int newport_wait(void)
-{
-	int i = 0;
-
-	while(i < BUSY_TIMEOUT)
-		if(!(npregs->cset.stat & NPORT_STAT_GBUSY))
-			break;
-	if(i == BUSY_TIMEOUT)
-		return 1;
-	return 0;
-}
-
-static inline int newport_bfwait(void)
-{
-	int i = 0;
-
-	while(i < BUSY_TIMEOUT)
-		if(!(npregs->cset.stat & NPORT_STAT_BBUSY))
-			break;
-	if(i == BUSY_TIMEOUT)
-		return 1;
-	return 0;
-}
-
-/* newport.c and cons_newport.c routines */
-extern struct graphics_ops *newport_probe (int, const char **);
-
-void newport_save    (void *);
-void newport_restore (void *);
-void newport_reset   (void);
-int  newport_ioctl   (int card, int cmd, unsigned long arg);
-
-/*
- * DCBMODE register defines:
- */
-
-/* Widht of the data being transfered for each DCBDATA[01] word */
-#define DCB_DATAWIDTH_4 0x0
-#define DCB_DATAWIDTH_1 0x1
-#define DCB_DATAWIDTH_2 0x2
-#define DCB_DATAWIDTH_3 0x3
-
-/* If set, all of DCBDATA will be moved, otherwise only DATAWIDTH bytes */
-#define DCB_ENDATAPACK   (1 << 2)
-
-/* Enables DCBCRS auto increment after each DCB transfer */
-#define DCB_ENCRSINC     (1 << 3)
-
-/* shift for accessing the control register select address (DBCCRS, 3 bits) */
-#define DCB_CRS_SHIFT    4
-
-/* DCBADDR (4 bits): display bus slave address */
-#define DCB_ADDR_SHIFT   7
-#define DCB_VC2          (0 <<  DCB_ADDR_SHIFT)
-#define DCB_CMAP_ALL     (1 <<  DCB_ADDR_SHIFT)
-#define DCB_CMAP0        (2 <<  DCB_ADDR_SHIFT)
-#define DCB_CMAP1        (3 <<  DCB_ADDR_SHIFT)
-#define DCB_XMAP_ALL     (4 <<  DCB_ADDR_SHIFT)
-#define DCB_XMAP0        (5 <<  DCB_ADDR_SHIFT)
-#define DCB_XMAP1        (6 <<  DCB_ADDR_SHIFT)
-#define DCB_BT445        (7 <<  DCB_ADDR_SHIFT)
-#define DCB_VCC1         (8 <<  DCB_ADDR_SHIFT)
-#define DCB_VAB1         (9 <<  DCB_ADDR_SHIFT)
-#define DCB_LG3_BDVERS0  (10 << DCB_ADDR_SHIFT)
-#define DCB_LG3_ICS1562  (11 << DCB_ADDR_SHIFT)
-#define DCB_RESERVED     (15 << DCB_ADDR_SHIFT)
-
-/* DCB protocol ack types */
-#define DCB_ENSYNCACK    (1 << 11)
-#define DCB_ENASYNCACK   (1 << 12)
-
-#define DCB_CSWIDTH_SHIFT 13
-#define DCB_CSHOLD_SHIFT  18
-#define DCB_CSSETUP_SHIFT 23
-
-/* XMAP9 specific defines */
-/*   XMAP9 -- registers as seen on the DCBMODE register*/
-#   define XM9_CRS_CONFIG            (0 << DCB_CRS_SHIFT)
-#       define XM9_PUPMODE           (1 << 0)
-#       define XM9_ODD_PIXEL         (1 << 1)
-#       define XM9_8_BITPLANES       (1 << 2)
-#       define XM9_SLOW_DCB          (1 << 3)
-#       define XM9_VIDEO_RGBMAP_MASK (3 << 4)
-#       define XM9_EXPRESS_VIDEO     (1 << 6)
-#       define XM9_VIDEO_OPTION      (1 << 7)
-#   define XM9_CRS_REVISION          (1 << DCB_CRS_SHIFT)
-#   define XM9_CRS_FIFO_AVAIL        (2 << DCB_CRS_SHIFT)
-#       define XM9_FIFO_0_AVAIL      0
-#       define XM9_FIFO_1_AVAIL      1
-#       define XM9_FIFO_2_AVAIL      3
-#       define XM9_FIFO_3_AVAIL      2
-#       define XM9_FIFO_FULL         XM9_FIFO_0_AVAIL
-#       define XM9_FIFO_EMPTY        XM9_FIFO_3_AVAIL
-#   define XM9_CRS_CURS_CMAP_MSB     (3 << DCB_CRS_SHIFT)
-#   define XM9_CRS_PUP_CMAP_MSB      (4 << DCB_CRS_SHIFT)
-#   define XM9_CRS_MODE_REG_DATA     (5 << DCB_CRS_SHIFT)
-#   define XM9_CRS_MODE_REG_INDEX    (7 << DCB_CRS_SHIFT)
-
-
-#define DCB_CYCLES(setup,hold,width)                \
-                  ((hold << DCB_CSHOLD_SHIFT)  |    \
-		   (setup << DCB_CSSETUP_SHIFT)|    \
-		   (width << DCB_CSWIDTH_SHIFT))
-
-#define W_DCB_XMAP9_PROTOCOL       DCB_CYCLES (2, 1, 0)
-#define WSLOW_DCB_XMAP9_PROTOCOL   DCB_CYCLES (5, 5, 0)
-#define WAYSLOW_DCB_XMAP9_PROTOCOL DCB_CYCLES (12, 12, 0)
-#define R_DCB_XMAP9_PROTOCOL       DCB_CYCLES (2, 1, 3)
-
-static inline void
-xmap9FIFOWait (struct newport_regs *rex)
-{
-        rex->set.dcbmode = DCB_XMAP0 | XM9_CRS_FIFO_AVAIL |
-		DCB_DATAWIDTH_1 | R_DCB_XMAP9_PROTOCOL;
-        newport_bfwait ();
-	
-        while ((rex->set.dcbdata0.bytes.b3 & 3) != XM9_FIFO_EMPTY)
-		;
-}
-
-static inline void
-xmap9SetModeReg (struct newport_regs *rex, unsigned int modereg, unsigned int data24, int cfreq)
-{
-        if (cfreq > 119)
-            rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA |
-                        DCB_DATAWIDTH_4 | W_DCB_XMAP9_PROTOCOL;
-        else if (cfreq > 59)
-            rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA |
-		    DCB_DATAWIDTH_4 | WSLOW_DCB_XMAP9_PROTOCOL;    
-        else
-            rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA |
-                        DCB_DATAWIDTH_4 | WAYSLOW_DCB_XMAP9_PROTOCOL; 
-        rex->set.dcbdata0.all = ((modereg) << 24) | (data24 & 0xffffff);
-}
-
-#endif /* !(_SGI_NEWPORT_H) */
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/rrm.c linux.pre11.3/drivers/sgi/char/rrm.c
--- linux.vanilla/drivers/sgi/char/rrm.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/rrm.c	Mon Jul 19 23:28:23 1999
@@ -12,6 +12,10 @@
 #include <asm/uaccess.h>
 #include <asm/rrm.h>
 
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
 int
 rrm_open_rn (int rnid, void *arg)
 {
@@ -66,4 +70,3 @@
 	/* This routine is invoked when the device is closed */
 	return 0;
 }
-
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/sgicons.c linux.pre11.3/drivers/sgi/char/sgicons.c
--- linux.vanilla/drivers/sgi/char/sgicons.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/sgicons.c	Mon Jul 19 23:28:23 1999
@@ -1,14 +1,11 @@
-/*
+/* $Id: sgicons.c,v 1.11 1999/01/04 16:07:19 ralf Exp $
+ *
  * sgicons.c: Setting up and registering console I/O on the SGI.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *
  * This implement a virtual console interface.
- *
- * This should be replaced with Gert's all-singing all-dancing
- * graphics console code in the future
- *
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -17,7 +14,7 @@
 #include "gconsole.h"
 
 /* To make psaux code cleaner */
-int aux_device_present = 0xaa;
+unsigned char aux_device_present = 0xaa;
 
 /* This is the system graphics console (the first adapter found) */
 struct console_ops *gconsole = 0;
@@ -45,139 +42,4 @@
 	if (gconsole)
 		return;
 	gconsole = gc;
-}
-
-void
-__set_origin (unsigned short offset)
-{
-	if (gconsole)
-		(*gconsole->set_origin)(offset);
-}
-
-void
-hide_cursor (void)
-{
-
-	if (gconsole)
-		(*gconsole->hide_cursor)();
-}
-
-void
-set_cursor (int currcons)
-{
-	if (gconsole)
-		(*gconsole->set_cursor)(currcons);
-}
-
-void
-get_scrmem (int currcons)
-{
-	if (gconsole)
-		(*gconsole->get_scrmem)(currcons);
-}
-
-void
-set_scrmem (int currcons, long offset)
-{
-	if (gconsole)
-		(*gconsole->set_scrmem)(currcons, offset);
-}
-
-int
-set_get_cmap (unsigned char *arg, int set)
-{
-	if (gconsole)
-		return (*gconsole->set_get_cmap)(arg, set);
-	return 0;
-}
-
-void
-blitc (unsigned short charattr, unsigned long addr)
-{
-	if (gconsole)
-		(*gconsole->blitc)(charattr, addr);
-}
-
-void
-memsetw (void *s, unsigned short c, unsigned int count)
-{
-	if (gconsole)
-		(*gconsole->memsetw)(s, c, count);
-}
-
-void
-memcpyw (unsigned short *to, unsigned short *from, unsigned int count)
-{
-	if (gconsole)
-		(*gconsole->memcpyw)(to, from, count);
-}
-
-int
-con_adjust_height (unsigned long fontheight)
-{
-	return -EINVAL;
-}
-
-int
-set_get_font (char *arg, int set, int ch512)
-{
-	int error, i, line;
-
-	if (!arg)
-		return -EINVAL;
-	error = verify_area (set ? VERIFY_READ : VERIFY_WRITE, (void *) arg,
-			     ch512 ? 2* cmapsz : cmapsz);
-	if (error)
-		return error;
-
-	/* download the current font */
-	if (!set) {
-		memset (arg, 0, cmapsz);
-		for (i = 0; i < 256; i++) {
-			for (line = 0; line < CHAR_HEIGHT; line++)
-				__put_user (vga_font [i], arg+(i*32+line));
-		}
-		return 0;
-	}
-	
-        /* set the font */
-	for (i = 0; i < 256; i++) {
-		for (line = 0; line < CHAR_HEIGHT; line++) {
-			__get_user(vga_font [i*CHAR_HEIGHT + line],
-			           arg + (i * 32 + line));
-		}
-	}
-	return 0;
-}
-
-/*
- * dummy routines for the VESA blanking code, which is VGA only,
- * so we don't have to carry that stuff around for the Sparc...  */
-void vesa_blank(void) { }
-void vesa_unblank(void) { }
-void set_vesa_blanking(const unsigned long arg) { }
-void vesa_powerdown(void) { }
-void set_palette (void) { }
-
-extern unsigned long video_mem_base, video_screen_size, video_mem_term;
-
-__initfunc(unsigned long con_type_init(unsigned long start_mem, const char **name))
-{
-	extern int serial_console;
-
-	if (serial_console)
-		*name = "NONE";
-	else {
-		gfx_init (name);
-		printk("Video screen size is %08lx at %08lx\n",
-		       video_screen_size, start_mem);
-		video_mem_base = start_mem;
-		start_mem += (video_screen_size * 2);
-		video_mem_term = start_mem;
-	}
-	return start_mem;
-}
-
-__initfunc(void con_type_init_finish(void))
-{
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/sgiserial.c linux.pre11.3/drivers/sgi/char/sgiserial.c
--- linux.vanilla/drivers/sgi/char/sgiserial.c	Sun Nov  8 15:10:21 1998
+++ linux.pre11.3/drivers/sgi/char/sgiserial.c	Mon Jul 19 23:28:23 1999
@@ -1,6 +1,7 @@
 /* sgiserial.c: Serial port driver for SGI machines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
  */
 
 #include <linux/config.h> /* for CONFIG_REMOTE_DEBUG */
@@ -18,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/console.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -39,33 +41,16 @@
 struct sgi_zschannel *zs_channels[NUM_CHANNELS] = { 0, 0, };
 struct sgi_zschannel *zs_conschan;
 struct sgi_zschannel *zs_kgdbchan;
-int zs_nodes[NUM_SERIAL] = { 0, };
 
 struct sgi_serial zs_soft[NUM_CHANNELS];
 struct sgi_serial *zs_chain;  /* IRQ servicing chain */
 static int zilog_irq = 21;
 
-struct tty_struct zs_ttys[NUM_CHANNELS];
-/** struct tty_struct *zs_constty; **/
-
 /* Console hooks... */
 static int zs_cons_chanout = 0;
 static int zs_cons_chanin = 0;
 struct sgi_serial *zs_consinfo = 0;
 
-static struct console sgi_console_driver = {
-        "debug",
-        NULL,                   /* write */
-        NULL,                   /* read */
-        NULL,                   /* device */
-        NULL,                   /* wait_key */
-        NULL,                   /* unblank */
-        NULL,                   /* setup */
-        CON_PRINTBUFFER,
-        -1,
-        0,
-        NULL
-};
 static unsigned char kgdb_regs[16] = {
 	0, 0, 0,                     /* write 0, 1, 2 */
 	(Rx8 | RxENABLE),            /* write 3 */
@@ -80,6 +65,22 @@
 	(DCDIE)                      /* write 15 */
 };
 
+static unsigned char zscons_regs[16] = {
+	0,                           /* write 0 */
+	(EXT_INT_ENAB | INT_ALL_Rx), /* write 1 */
+	0,                           /* write 2 */
+	(Rx8 | RxENABLE),            /* write 3 */
+	(X16CLK),                    /* write 4 */
+	(DTR | Tx8 | TxENAB),        /* write 5 */
+	0, 0, 0,                     /* write 6, 7, 8 */
+	(NV | MIE),                  /* write 9 */
+	(NRZ),                       /* write 10 */
+	(TCBR | RCBR),               /* write 11 */
+	0, 0,                        /* BRG time constant, write 12 + 13 */
+	(BRENABL),                   /* write 14 */
+	(DCDIE | CTSIE | TxUIE | BRKIE) /* write 15 */
+};
+
 #define ZS_CLOCK         3672000   /* Zilog input clock rate */
 
 DECLARE_TASK_QUEUE(tq_serial);
@@ -161,6 +162,10 @@
  * driver work on the Sun4 which needs a settling delay after each chip
  * register access, other machines handle this in hardware via auxiliary
  * flip-flops which implement the settle time we do in software.
+ *
+ * read_zsreg() and write_zsreg() may get called from rs_kgdb_hook() before
+ * interrupts are enabled. Therefore we have to check ioc_iocontrol before we
+ * access it.
  */
 static inline unsigned char read_zsreg(struct sgi_zschannel *channel, unsigned char reg)
 {
@@ -169,7 +174,8 @@
 
 	udelay(2);
 	channel->control = reg;
-	junk = ioc_icontrol->istat0;
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 	udelay(1);
 	retval = channel->control;
 	return retval;
@@ -181,10 +187,12 @@
 
 	udelay(2);
 	channel->control = reg;
-	junk = ioc_icontrol->istat0;
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 	udelay(1);
 	channel->control = value;
-	junk = ioc_icontrol->istat0;
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 	return;
 }
 
@@ -235,7 +243,7 @@
 		kgdb_regs[R1] = 0;
 		kgdb_regs[R9] &= ~MIE;
 	}
-	brg = BPS_TO_BRG(bps, ZS_CLOCK/16);
+	brg = BPS_TO_BRG(bps, ZS_CLOCK/ss->clk_divisor);
 	kgdb_regs[R12] = (brg & 255);
 	kgdb_regs[R13] = ((brg >> 8) & 255);
 	load_zsregs(ss->zs_channel, kgdb_regs);
@@ -552,7 +560,7 @@
 	struct sgi_serial * info = (struct sgi_serial *) dev_id;
 	unsigned char zs_intreg;
 
-	zs_intreg = read_zsreg(info->zs_channel, 3);
+	zs_intreg = read_zsreg(info->zs_next->zs_channel, 3);
 
 	/* NOTE: The read register 3, which holds the irq status,
 	 *       does so for both channels on each chip.  Although
@@ -564,25 +572,25 @@
 #define CHAN_B_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
 
 	/* *** Chip 1 *** */
-	/* Channel A -- /dev/ttya, could be the console */
-	if(zs_intreg & CHAN_A_IRQMASK) {
-		if (zs_intreg & CHARxIP)
+	/* Channel B -- /dev/ttyb, could be the console */
+	if(zs_intreg & CHAN_B_IRQMASK) {
+		if (zs_intreg & CHBRxIP)
 			receive_chars(info, regs);
-		if (zs_intreg & CHATxIP)
+		if (zs_intreg & CHBTxIP)
 			transmit_chars(info);
-		if (zs_intreg & CHAEXT)
+		if (zs_intreg & CHBEXT)
 			status_handle(info);
 	}
 
 	info=info->zs_next;
 
-	/* Channel B -- /dev/ttyb, could be the console */
-	if(zs_intreg & CHAN_B_IRQMASK) {
-		if (zs_intreg & CHBRxIP)
+	/* Channel A -- /dev/ttya, could be the console */
+	if(zs_intreg & CHAN_A_IRQMASK) {
+		if (zs_intreg & CHARxIP)
 			receive_chars(info, regs);
-		if (zs_intreg & CHBTxIP)
+		if (zs_intreg & CHATxIP)
 			transmit_chars(info);
-		if (zs_intreg & CHBEXT)
+		if (zs_intreg & CHAEXT)
 			status_handle(info);
 	}
 }
@@ -904,7 +912,7 @@
 /* These are for receiving and sending characters under the kgdb
  * source level kernel debugger.
  */
-void putDebugChar(char kgdb_char)
+int putDebugChar(char kgdb_char)
 {
 	struct sgi_zschannel *chan = zs_kgdbchan;
 	volatile unsigned char junk;
@@ -919,6 +927,8 @@
 	chan->data = kgdb_char;
 	junk = ioc_icontrol->istat0;
 	restore_flags(flags);
+
+	return 1;
 }
 
 char getDebugChar(void)
@@ -971,63 +981,6 @@
 	return;
 }
 
-/*
- * zs_console_print is registered for printk.
- */
-
-static void zs_console_print(struct console *co, const char *str, unsigned int count)
-{
-
-	while(count--) {
-		if(*str == '\n')
-			rs_put_char('\r');
-		rs_put_char(*str++);
-	}
-
-	/* Comment this if you want to have a strict interrupt-driven output */
-	rs_fair_output();
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
-	struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !info->xmit_buf)
-		return;
-
-	/* Enable transmitter */
-	save_flags(flags); cli();
-	info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
-	info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
-	write_zsreg(info->zs_channel, 1, info->curregs[1]);
-	info->curregs[5] |= TxENAB;
-	info->pendregs[5] |= TxENAB;
-	write_zsreg(info->zs_channel, 5, info->curregs[5]);
-
-	/*
-	 * Send a first (bootstrapping) character. A best solution is
-	 * to call transmit_chars() here which handles output in a
-	 * generic way. Current transmit_chars() not only transmits,
-	 * but resets interrupts also what we do not desire here.
-	 * XXX Discuss with David.
-	 */
-	if (info->zs_channel->control & Tx_BUF_EMP) {
-		volatile unsigned char junk;
-
-		/* Send char */
-		udelay(2);
-		info->zs_channel->data = info->xmit_buf[info->xmit_tail++];
-		junk = ioc_icontrol->istat0;
-		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		info->xmit_cnt--;
-	}
-	restore_flags(flags);
-}
 
 static int rs_write(struct tty_struct * tty, int from_user,
 		    const unsigned char *buf, int count)
@@ -1117,6 +1070,47 @@
 		(tty->ldisc.write_wakeup)(tty);
 }
 
+static void rs_flush_chars(struct tty_struct *tty)
+{
+	struct sgi_serial *info = (struct sgi_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !info->xmit_buf)
+		return;
+
+	/* Enable transmitter */
+	save_flags(flags); cli();
+	info->curregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
+	info->pendregs[1] |= TxINT_ENAB|EXT_INT_ENAB;
+	write_zsreg(info->zs_channel, 1, info->curregs[1]);
+	info->curregs[5] |= TxENAB;
+	info->pendregs[5] |= TxENAB;
+	write_zsreg(info->zs_channel, 5, info->curregs[5]);
+
+	/*
+	 * Send a first (bootstrapping) character. A best solution is
+	 * to call transmit_chars() here which handles output in a
+	 * generic way. Current transmit_chars() not only transmits,
+	 * but resets interrupts also what we do not desire here.
+	 * XXX Discuss with David.
+	 */
+	if (info->zs_channel->control & Tx_BUF_EMP) {
+		volatile unsigned char junk;
+
+		/* Send char */
+		udelay(2);
+		info->zs_channel->data = info->xmit_buf[info->xmit_tail++];
+		junk = ioc_icontrol->istat0;
+		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+		info->xmit_cnt--;
+	}
+	restore_flags(flags);
+}
+
 /*
  * ------------------------------------------------------------
  * rs_throttle()
@@ -1614,7 +1608,7 @@
 		if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
 		    !(info->flags & ZILOG_CLOSING) && do_clocal)
 			break;
-		if (current->signal & ~current->blocked) {
+		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
 			break;
 		}
@@ -1725,17 +1719,14 @@
 }
 
 
-
 static inline void
 rs_cons_check(struct sgi_serial *ss, int channel)
 {
 	int i, o, io;
-	static consout_registered = 0;
-	static msg_printed = 0;
+	static int msg_printed = 0;
 
 	i = o = io = 0;
 
-
 	/* Is this one of the serial console lines? */
 	if((zs_cons_chanout != channel) &&
 	   (zs_cons_chanin != channel))
@@ -1744,18 +1735,6 @@
 	zs_consinfo = ss;
 
 
-	/* Register the console output putchar, if necessary */
-	if((zs_cons_chanout == channel)) {
-		o = 1;
-		/* double whee.. */
-
-		if(!consout_registered) {
-		  sgi_console_driver.write = zs_console_print;
-			register_console(&sgi_console_driver);
-			consout_registered = 1;
-		}
-	}
-
 
 	/* If this is console input, we handle the break received
 	 * status interrupt on this line to mean prom_halt().
@@ -1873,8 +1852,8 @@
 		if(!zs_chips[chip]) {
 			zs_chips[chip] = get_zs(chip);
 			/* Two channels per chip */
-			zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
-			zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
+			zs_channels[(chip*2)] = &zs_chips[chip]->channelB;
+			zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA;
 			zs_soft[(chip*2)].kgdb_channel = 0;
 			zs_soft[(chip*2)+1].kgdb_channel = 0;
 		}
@@ -1990,14 +1969,14 @@
 	
 	if(chip)
 		panic("rs_cons_hook called with chip not zero");
-	if(line != 1 && line != 2)
+	if(line != 0 && line != 1)
 		panic("rs_cons_hook called with line not ttya or ttyb");
-	channel = line - 1;
+	channel = line;
 	if(!zs_chips[chip]) {
 		zs_chips[chip] = get_zs(chip);
 		/* Two channels per chip */
-		zs_channels[(chip*2)] = &zs_chips[chip]->channelA;
-		zs_channels[(chip*2)+1] = &zs_chips[chip]->channelB;
+		zs_channels[(chip*2)] = &zs_chips[chip]->channelB;
+		zs_channels[(chip*2)+1] = &zs_chips[chip]->channelA;
 	}
 	zs_soft[channel].zs_channel = zs_channels[channel];
 	zs_soft[channel].change_needed = 0;
@@ -2041,3 +2020,176 @@
 	udelay(5);
 	ZS_CLEARFIFO(zs_kgdbchan);
 }
+
+static void zs_console_write(struct console *co, const char *str, unsigned int count)
+{
+
+	while(count--) {
+		if(*str == '\n')
+			rs_put_char('\r');
+		rs_put_char(*str++);
+	}
+
+	/* Comment this if you want to have a strict interrupt-driven output */
+	rs_fair_output();
+}
+
+static int zs_console_wait_key(struct console *con)
+{
+	sleep_on(&keypress_wait);
+	return 0;
+}
+
+static kdev_t zs_console_device(struct console *con)
+{
+	return MKDEV(TTY_MAJOR, 64 + con->index);
+}
+
+
+__initfunc(static int zs_console_setup(struct console *con, char *options))
+{
+	struct sgi_serial *info;
+	int	baud = 9600;
+	int	bits = 8;
+	int	parity = 'n';
+	int	cflag = CREAD | HUPCL | CLOCAL;
+	char	*s;
+	int     i, brg;
+    
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while(*s >= '0' && *s <= '9')
+			s++;
+		if (*s) parity = *s++;
+		if (*s) bits   = *s - '0';
+	}
+
+	/*
+	 *	Now construct a cflag setting.
+	 */
+	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;
+	}
+	switch(bits) {
+		case 7:
+			cflag |= CS7;
+			break;
+		default:
+		case 8:
+			cflag |= CS8;
+			break;
+	}
+	switch(parity) {
+		case 'o': case 'O':
+			cflag |= PARODD;
+			break;
+		case 'e': case 'E':
+			cflag |= PARENB;
+			break;
+	}
+	con->cflag = cflag;
+
+        rs_cons_hook(0, 0, con->index);
+	info = zs_soft + con->index;
+	info->is_cons = 1;
+    
+	printk("Console: ttyS%d (Zilog8530)\n", info->line);
+
+	i = con->cflag & CBAUD;
+	if (con->cflag & CBAUDEX) {
+		i &= ~CBAUDEX;
+		con->cflag &= ~CBAUDEX;
+	}
+	info->zs_baud = baud;
+
+	switch (con->cflag & CSIZE) {
+		case CS5:
+			zscons_regs[3] = Rx5 | RxENABLE;
+			zscons_regs[5] = Tx5 | TxENAB;
+			break;
+		case CS6:
+			zscons_regs[3] = Rx6 | RxENABLE;
+			zscons_regs[5] = Tx6 | TxENAB;
+			break;
+		case CS7:
+			zscons_regs[3] = Rx7 | RxENABLE;
+			zscons_regs[5] = Tx7 | TxENAB;
+			break;
+		default:
+		case CS8:
+			zscons_regs[3] = Rx8 | RxENABLE;
+			zscons_regs[5] = Tx8 | TxENAB;
+			break;
+	}
+	zscons_regs[5] |= DTR;
+
+	if (con->cflag & PARENB)
+		zscons_regs[4] |= PAR_ENA;
+	if (!(con->cflag & PARODD))
+		zscons_regs[4] |= PAR_EVEN;
+
+	if (con->cflag & CSTOPB)
+		zscons_regs[4] |= SB2;
+	else
+		zscons_regs[4] |= SB1;
+
+	brg = BPS_TO_BRG(baud, ZS_CLOCK / info->clk_divisor);
+	zscons_regs[12] = brg & 0xff;
+	zscons_regs[13] = (brg >> 8) & 0xff;
+	memcpy(info->curregs, zscons_regs, sizeof(zscons_regs));
+	memcpy(info->pendregs, zscons_regs, sizeof(zscons_regs));    
+	load_zsregs(info->zs_channel, zscons_regs);
+	ZS_CLEARERR(info->zs_channel);
+	ZS_CLEARFIFO(info->zs_channel);
+	return 0;
+}
+
+static struct console sgi_console_driver = {
+        "ttyS",
+        zs_console_write,       /* write */
+        NULL,                   /* read */
+        zs_console_device,      /* device */
+        zs_console_wait_key,    /* wait_key */
+        NULL,                   /* unblank */
+        zs_console_setup,       /* setup */
+        CON_PRINTBUFFER,
+        -1,
+        0,
+        NULL
+};
+
+/*
+ *	Register console.
+ */
+__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+{
+	register_console(&sgi_console_driver);
+	return kmem_start;
+}
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/sgiserial.h linux.pre11.3/drivers/sgi/char/sgiserial.h
--- linux.vanilla/drivers/sgi/char/sgiserial.h	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/sgiserial.h	Mon Jul 19 23:28:23 1999
@@ -412,7 +412,8 @@
 
 	udelay(2);
 	channel->control = ERR_RES;
-	junk = ioc_icontrol->istat0;
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 }
 
 extern inline void ZS_CLEARFIFO(struct sgi_zschannel *channel)
@@ -421,11 +422,17 @@
 
 	udelay(2);
 	junk = channel->data;
-	udelay(2); junk = ioc_icontrol->istat0;
+	udelay(2);
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 	junk = channel->data;
-	udelay(2); junk = ioc_icontrol->istat0;
+	udelay(2);
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 	junk = channel->data;
-	udelay(2); junk = ioc_icontrol->istat0;
+	udelay(2);
+	if (ioc_icontrol)
+		junk = ioc_icontrol->istat0;
 }
 
 #if 0
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/shmiq.c linux.pre11.3/drivers/sgi/char/shmiq.c
--- linux.vanilla/drivers/sgi/char/shmiq.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/shmiq.c	Mon Jul 19 23:28:23 1999
@@ -1,4 +1,5 @@
-/*
+/* $Id: shmiq.c,v 1.11.2.2 1999/06/17 12:08:45 ralf Exp $
+ *
  * shmiq.c: shared memory input queue driver
  * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *
@@ -47,6 +48,7 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/interrupt.h>
+#include <linux/poll.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
 #include <linux/major.h>
@@ -237,7 +239,7 @@
 	return -EBADF;
 }
 
-extern sys_munmap(unsigned long addr, size_t len);
+extern int sys_munmap(unsigned long addr, size_t len);
 
 static int
 qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg, int minor)
@@ -394,12 +396,12 @@
 }
 
 static int
-shmiq_qcntl_fasync (struct file *file, int on)
+shmiq_qcntl_fasync (int fd, struct file *file, int on)
 {
 	int retval;
 	int minor = MINOR (file->f_dentry->d_inode->i_rdev);
 
-	retval = fasync_helper (file, on, &shmiqs [minor].fasync);
+	retval = fasync_helper (fd, file, on, &shmiqs [minor].fasync);
 	if (retval < 0)
 		return retval;
 	return 0;
@@ -422,7 +424,7 @@
 		return -EINVAL;
 
 	lock_kernel ();
-	shmiq_qcntl_fasync (filp, 0);
+	shmiq_qcntl_fasync (-1, filp, 0);
 	shmiqs [minor].opened      = 0;
 	shmiqs [minor].mapped      = 0;
 	shmiqs [minor].events      = 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/streamable.c linux.pre11.3/drivers/sgi/char/streamable.c
--- linux.vanilla/drivers/sgi/char/streamable.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/streamable.c	Mon Jul 19 23:28:23 1999
@@ -1,4 +1,5 @@
-/*
+/* $Id: streamable.c,v 1.9 1998/09/19 19:17:50 ralf Exp $
+ *
  * streamable.c: streamable devices. /dev/gfx
  * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *
@@ -51,14 +52,14 @@
 static int
 sgi_gfx_open (struct inode *inode, struct file *file)
 {
-	printk ("GFX: Opened by %d\n", current->pid);
+	printk ("GFX: Opened by %ld\n", current->pid);
 	return 0;
 }
 
 static int
 sgi_gfx_close (struct inode *inode, struct file *file)
 {
-	printk ("GFX: Closed by %d\n", current->pid);
+	printk ("GFX: Closed by %ld\n", current->pid);
 	return 0;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/usema.c linux.pre11.3/drivers/sgi/char/usema.c
--- linux.vanilla/drivers/sgi/char/usema.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/usema.c	Mon Jul 19 23:28:23 1999
@@ -27,11 +27,13 @@
 #include <linux/sched.h>
 #include <linux/file.h>
 #include <linux/major.h>
+#include <linux/poll.h>
 #include <linux/string.h>
 #include <linux/dcache.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
+#include "usema.h"
 
 #include <asm/usioctl.h>
 #include <asm/mman.h>
@@ -42,6 +44,7 @@
 	struct wait_queue *proc_list;
 };
 
+
 static int
 sgi_usema_attach (usattach_t * attach, struct irix_usema *usema)
 {
@@ -64,7 +67,7 @@
 	struct irix_usema *usema = file->private_data;
 	int retval;
 	
-	printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
+	printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)",
 	       current->comm, current->pid, cmd, arg);
 
 	switch(cmd) {
@@ -76,7 +79,7 @@
 		usattach_t *attach = (usattach_t *)arg;
 		retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
 		if (retval) {
-			printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
+			printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): "
 			       "verify_area failure",
 			       current->comm, current->pid);
 			return retval;
@@ -84,7 +87,8 @@
 		if (usema == 0)
 			return -EINVAL;
 
-		printk("UIOCATTACHSEMA: attaching usema %p to process %d\n", usema, current->pid);
+		printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n",
+		       usema, current->pid);
 		/* XXX what is attach->us_handle for? */
 		return sgi_usema_attach(attach, usema);
 		break;
@@ -97,12 +101,12 @@
 
 		retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
 		if (retval) {
-			printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
+			printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
 			       "verify_area failure",
 			       current->comm, current->pid);
 			return retval;
 		}
-		printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
+		printk("UIOC*BLOCK: putting process %ld to sleep on usema %p",
 		       current->pid, usema);
 		if (cmd == UIOCNOIBLOCK)
 			interruptible_sleep_on(&usema->proc_list);
@@ -117,13 +121,13 @@
 
 		retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
 		if (retval) {
-			printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
+			printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
 			       "verify_area failure",
 			       current->comm, current->pid);
 			return retval;
 		}
 
-		printk("[%s:%d] releasing usema %p",
+		printk("[%s:%ld] releasing usema %p",
 		       current->comm, current->pid, usema);
 		wake_up(&usema->proc_list);
 		return 0;
@@ -137,7 +141,8 @@
 {
 	struct irix_usema *usema = filp->private_data;
 	
-	printk("[%s:%d] wants to poll usema %p", current->comm, current->pid, usema);
+	printk("[%s:%ld] wants to poll usema %p",
+	       current->comm, current->pid, usema);
 	
 	return 0;
 }
@@ -187,6 +192,7 @@
 void
 usema_init(void)
 {
-	printk("usemaclone misc device registered (minor: %d)\n", SGI_USEMACLONE);
+	printk("usemaclone misc device registered (minor: %d)\n",
+	       SGI_USEMACLONE);
 	misc_register(&dev_usemaclone);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/usema.h linux.pre11.3/drivers/sgi/char/usema.h
--- linux.vanilla/drivers/sgi/char/usema.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/sgi/char/usema.h	Mon Jul 19 23:28:23 1999
@@ -0,0 +1,10 @@
+/* usema.h
+ *
+ * Copyright (C) 1996 Alex deVries <puffin@redhat.com>
+ */
+#ifndef _SGI_USEMA_H
+#define _SGI_USEMA_H
+
+void usema_init (void); 
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sgi/char/vga_font.c linux.pre11.3/drivers/sgi/char/vga_font.c
--- linux.vanilla/drivers/sgi/char/vga_font.c	Sun Nov  8 15:08:17 1998
+++ linux.pre11.3/drivers/sgi/char/vga_font.c	Thu Jan  1 01:00:00 1970
@@ -1,346 +0,0 @@
-#include "gconsole.h"
-
-unsigned char vga_font[cmapsz] = {
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 
-0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 
-0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 
-0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 
-0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 
-0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 
-0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 
-0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, 
-0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 
-0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, 
-0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 
-0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, 
-0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 
-0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, 
-0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 
-0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 
-0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 
-0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 
-0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 
-0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 
-0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 
-0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 
-0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 
-0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 
-0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 
-0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 
-0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 
-0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 
-0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 
-0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 
-0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 
-0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 
-0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 
-0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 
-0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, 
-0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 
-0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 
-0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, 
-0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 
-0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
-0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 
-0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 
-0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, 
-0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 
-0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 
-0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 
-0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 
-0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 
-0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 
-0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 
-0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 
-0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 
-0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 
-0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 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, 0xff, 0x00, 0x00, 
-0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, 
-0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 
-0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, 
-0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 
-0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, 
-0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 
-0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 
-0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 
-0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 
-0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 
-0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 
-0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 
-0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 
-0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
-0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, 
-0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 
-0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 
-0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 
-0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 
-0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 
-0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 
-0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 
-0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 
-0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 
-0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 
-0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 
-0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, 
-0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 
-0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 
-0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, 
-0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
-0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 
-0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 
-0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 
-0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 
-0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 
-0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 
-0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 
-0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 
-0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 
-0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 
-0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 
-0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 
-0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 
-0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, 
-0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 
-0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 
-0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 
-0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 
-0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
-0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 
-0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 
-0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 
-0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 
-0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 
-0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 
-0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 
-0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 
-0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 
-0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 
-0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 
-0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 
-0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
-0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 
-0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 
-0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 
-0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 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, 
-};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/dev_table.h linux.pre11.3/drivers/sound/dev_table.h
--- linux.vanilla/drivers/sound/dev_table.h	Fri Apr 16 22:10:56 1999
+++ linux.pre11.3/drivers/sound/dev_table.h	Mon Jul 19 23:28:08 1999
@@ -25,30 +25,18 @@
 #define SNDCARD_DESKPROXL		27	/* Compaq Deskpro XL */
 #define SNDCARD_VIDC			28	/* ARMs VIDC */
 #define SNDCARD_SBPNP			29
-#define SNDCARD_OPL3SA1			38
-#define SNDCARD_OPL3SA1_SB		39
-#define SNDCARD_OPL3SA1_MPU		40
 #define SNDCARD_SOFTOSS			36
 #define SNDCARD_VMIDI			37
+#define SNDCARD_OPL3SA1			38	/* Note: clash in msnd.h */
+#define SNDCARD_OPL3SA1_SB		39
+#define SNDCARD_OPL3SA1_MPU		40
 #define SNDCARD_WAVEFRONT               41
 #define SNDCARD_OPL3SA2                 42
 #define SNDCARD_OPL3SA2_MPU             43
 #define SNDCARD_WAVEARTIST		44
+#define SNDCARD_OPL3SA2_MSS             45	/* Originally missed */
 #define SNDCARD_AD1816                  88
 
-void attach_opl3sa_wss (struct address_info *hw_config);
-int probe_opl3sa_wss (struct address_info *hw_config);
-void attach_opl3sa_sb (struct address_info *hw_config);
-int probe_opl3sa_sb (struct address_info *hw_config);
-void attach_opl3sa_mpu (struct address_info *hw_config);
-int probe_opl3sa_mpu (struct address_info *hw_config);
-void unload_opl3sa_wss(struct address_info *hw_info);
-void unload_opl3sa_sb(struct address_info *hw_info);
-void unload_opl3sa_mpu(struct address_info *hw_info);
-void attach_softsyn_card (struct address_info *hw_config);
-int probe_softsyn (struct address_info *hw_config);
-void unload_softsyn (struct address_info *hw_config);
-
 /*
  *	NOTE! 	NOTE!	NOTE!	NOTE!
  *
@@ -424,6 +412,7 @@
 
 #ifdef CONFIG_SOUND_OPL3SA2
 	{"OPL3SA2", 0, SNDCARD_OPL3SA2,	"OPL3SA2",		attach_opl3sa2, probe_opl3sa2, unload_opl3sa2},
+	{"OPL3SA2MSS", 1, SNDCARD_OPL3SA2_MSS,	"OPL3SA2 MSS",		attach_opl3sa2_mss, probe_opl3sa2_mss, unload_opl3sa2_mss},
 	{"OPL3SA2MPU", 0, SNDCARD_OPL3SA2_MPU,	"OPL3SA2 MIDI",		attach_opl3sa2_mpu, probe_opl3sa2_mpu, unload_opl3sa2_mpu},
 #endif
 
@@ -587,10 +576,11 @@
 #ifndef CONFIG_OPL3SA2_DMA2
 #define CONFIG_OPL3SA2_DMA2 CONFIG_OPL3SA2_DMA
 #endif
+	{SNDCARD_OPL3SA2, {CONFIG_OPL3SA2_CTRL_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE},
+	{SNDCARD_OPL3SA2_MSS, {CONFIG_OPL3SA2_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE},
 #ifdef CONFIG_OPL3SA2_MPU_BASE
-	{SNDCARD_OPL3SA2_MPU, {CONFIG_OPL3SA2_MPU_BASE, CONFIG_OPL3SA2_MPU_IRQ, 0, -1}, SND_DEFAULT_ENABLE},
+	{SNDCARD_OPL3SA2_MPU, {CONFIG_OPL3SA2_MPU_BASE, CONFIG_OPL3SA2_MPU_IRQ, CONFIG_OPL3SA2_DMA, -1}, SND_DEFAULT_ENABLE},
 #endif
-	{SNDCARD_OPL3SA2, {CONFIG_OPL3SA2_BASE, CONFIG_OPL3SA2_IRQ, CONFIG_OPL3SA2_DMA, CONFIG_OPL3SA2_DMA2}, SND_DEFAULT_ENABLE},
 #endif
 
 #ifdef CONFIG_SGALAXY
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/dmasound.c linux.pre11.3/drivers/sound/dmasound.c
--- linux.vanilla/drivers/sound/dmasound.c	Wed Mar 24 10:55:22 1999
+++ linux.pre11.3/drivers/sound/dmasound.c	Tue Jul 20 00:04:07 1999
@@ -4579,7 +4579,7 @@
 		if (nbufs < 2 || nbufs > numBufs)
 			nbufs = numBufs;
 		size &= 0xffff;
-		if (size >= 8 && size <= 30) {
+		if (size >= 8 && size <= 29) {
 			size = 1 << size;
 			size *= sound.hard.size * (sound.hard.stereo + 1);
 			size /= sound.soft.size * (sound.soft.stereo + 1);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/es1370.c linux.pre11.3/drivers/sound/es1370.c
--- linux.vanilla/drivers/sound/es1370.c	Tue Jun 15 16:49:52 1999
+++ linux.pre11.3/drivers/sound/es1370.c	Tue Jul 20 00:04:07 1999
@@ -98,6 +98,9 @@
  *                     (micz). From Kim.Berts@fisub.mail.abb.com
  *    11.05.99   0.22  Implemented the IMIX call to mute recording monitor.
  *                     Guenter Geiger <geiger@epy.co.at>
+ *    15.06.99   0.23  Fix bad allocation bug.
+ *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.99   0.24  Add pci_set_master
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -531,8 +534,9 @@
 	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
-		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--)
-			db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order);
+		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
+				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
 		db->buforder = order;
@@ -2317,7 +2321,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.22 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.24 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 || 
@@ -2381,6 +2385,7 @@
 		/* initialize the chips */
 		outl(s->ctrl, s->io+ES1370_REG_CONTROL);
 		outl(s->sctrl, s->io+ES1370_REG_SERIAL_CONTROL);
+		pci_set_master(pcidev);  /* enable bus mastering */
 		wrcodec(s, 0x16, 3); /* no RST, PD */
 		wrcodec(s, 0x17, 0); /* CODEC ADC and CODEC DAC use {LR,B}CLK2 and run off the LRCLK2 PLL; program DAC_SYNC=0!!  */
 		wrcodec(s, 0x18, 0); /* recording source is mixer */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/es1371.c linux.pre11.3/drivers/sound/es1371.c
--- linux.vanilla/drivers/sound/es1371.c	Fri Apr 16 22:10:56 1999
+++ linux.pre11.3/drivers/sound/es1371.c	Tue Jul 20 00:04:07 1999
@@ -65,6 +65,9 @@
  *                     reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
  *                     Note: joystick address handling might still be wrong on archs
  *                     other than i386
+ *    15.06.99   0.12  Fix bad allocation bug.
+ *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.99   0.13  Add pci_set_master
  *
  */
 
@@ -759,8 +762,9 @@
 	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
-		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--)
-			db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order);
+		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
+				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
 		db->buforder = order;
@@ -2732,7 +2736,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.11 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.13 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 || 
@@ -2789,6 +2793,7 @@
 		outl(s->ctrl, s->io+ES1371_REG_CONTROL);
 		outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
 		outl(0, s->io+ES1371_REG_LEGACY);
+		pci_set_master(pcidev);  /* enable bus mastering */
 		/* AC97 warm reset to start the bitclk */
 		outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
 		udelay(2);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/mad16.c linux.pre11.3/drivers/sound/mad16.c
--- linux.vanilla/drivers/sound/mad16.c	Wed Mar 10 21:13:07 1999
+++ linux.pre11.3/drivers/sound/mad16.c	Tue Jul 20 00:04:24 1999
@@ -668,7 +668,7 @@
 	 * Set the IRQ and DMA addresses.
 	 */
 	
-	if (board_type == C930)
+	if (board_type == C930 || c924pnp)
 		interrupt_bits[5] = 0x28;	/* Also IRQ5 is possible on C930 */
 
 	bits = interrupt_bits[hw_config->irq];
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/maui.c linux.pre11.3/drivers/sound/maui.c
--- linux.vanilla/drivers/sound/maui.c	Sun Nov  8 15:10:21 1998
+++ linux.pre11.3/drivers/sound/maui.c	Mon Jul 19 23:28:08 1999
@@ -15,9 +15,12 @@
  *					system
  *
  *	Status:
- *		Untested
+ *		Andrew J. Kroll		Tested 06/01/1999 with:
+ *					* OSWF.MOT File Version: 1.15
+ *					* OSWF.MOT File Dated: 09/12/94
+ *					* Older versions will cause problems.
  */
- 
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/init.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/mpu401.c linux.pre11.3/drivers/sound/mpu401.c
--- linux.vanilla/drivers/sound/mpu401.c	Sun Nov  8 15:08:01 1998
+++ linux.pre11.3/drivers/sound/mpu401.c	Mon Jul 19 23:28:08 1999
@@ -437,6 +437,15 @@
 	devc->m_busy = 0;
 }
 
+int intchk_mpu401(void *dev_id)
+{
+	struct mpu_config *devc;
+	int dev = (int) dev_id;
+
+	devc = &dev_conf[dev];
+	return input_avail(devc);
+}
+
 void mpuintr(int irq, void *dev_id, struct pt_regs *dummy)
 {
 	struct mpu_config *devc;
@@ -1715,6 +1724,7 @@
 EXPORT_SYMBOL(probe_mpu401);
 EXPORT_SYMBOL(attach_mpu401);
 EXPORT_SYMBOL(unload_mpu401);
+EXPORT_SYMBOL(intchk_mpu401);
 EXPORT_SYMBOL(mpuintr);
 
 #ifdef MODULE
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/opl3sa2.c linux.pre11.3/drivers/sound/opl3sa2.c
--- linux.vanilla/drivers/sound/opl3sa2.c	Sat Jan  9 21:50:45 1999
+++ linux.pre11.3/drivers/sound/opl3sa2.c	Mon Jul 19 23:28:10 1999
@@ -467,13 +467,13 @@
 }
 
 
-static int probe_opl3sa2_mss(struct address_info *hw_config)
+int probe_opl3sa2_mss(struct address_info *hw_config)
 {
 	return probe_ms_sound(hw_config);
 }
 
 
-static void attach_opl3sa2_mss(struct address_info *hw_config)
+void attach_opl3sa2_mss(struct address_info *hw_config)
 {
 	char mixer_name[64];
 
@@ -516,7 +516,7 @@
 }
 
 
-static void unload_opl3sa2_mss(struct address_info *hw_config)
+void unload_opl3sa2_mss(struct address_info *hw_config)
 {
 	unload_ms_sound(hw_config);
 }
@@ -592,6 +592,9 @@
 	{
 		/* Generate a pretty name */
 		sprintf(chipset_name, "OPL3-SA%c", tag);
+#if defined(CONFIG_OPL3SA2_MPU_BASE) && !defined(MODULE)
+		sound_getconf(SNDCARD_OPL3SA2_MPU)->always_detect = 1;
+#endif
 		return 1;
 	}
 	return 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_ess.c linux.pre11.3/drivers/sound/sb_ess.c
--- linux.vanilla/drivers/sound/sb_ess.c	Thu May 27 22:11:56 1999
+++ linux.pre11.3/drivers/sound/sb_ess.c	Tue Jul 20 00:04:49 1999
@@ -40,6 +40,10 @@
  *								recording problems for high samplerates. I
  *								fixed this by removing ess_calc_best_speed ()
  *								and just doing what the documentation says. 
+ * Andy Sloane  (June 4 1999):  Stole some code from ALSA to fix the playback
+ * andy@guildsoftware.com		speed on ES1869, ES1879, ES1887, and ES1888.
+ * 								1879's were previously ignored by this driver;
+ * 								added (untested) support for those.
  *
  * This files contains ESS chip specifics. It's based on the existing ESS
  * handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
@@ -190,15 +194,23 @@
 #define ESSTYPE_LIKE20	-1		/* Mimic 2.0 behaviour					*/
 #define ESSTYPE_DETECT	0		/* Mimic 2.0 behaviour					*/
 
-int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */
+int esstype = ESSTYPE_DETECT; /* module parameter in sb_card.c */
 
 #define SUBMDL_ES1788	0x10	/* Subtype ES1788 for specific handling */
 #define SUBMDL_ES1868	0x11	/* Subtype ES1868 for specific handling */
 #define SUBMDL_ES1869	0x12	/* Subtype ES1869 for specific handling */
 #define SUBMDL_ES1878	0x13	/* Subtype ES1878 for specific handling */
+#define SUBMDL_ES1879	0x16    /* ES1879 was initially forgotten */
 #define SUBMDL_ES1887	0x14	/* Subtype ES1887 for specific handling */
 #define SUBMDL_ES1888	0x15	/* Subtype ES1888 for specific handling */
 
+#define SB_CAP_ES18XX_RATE 0x100
+
+#define ES1688_CLOCK1 795444 /* 128 - div */
+#define ES1688_CLOCK2 397722 /* 256 - div */
+#define ES18XX_CLOCK1 793800 /* 128 - div */
+#define ES18XX_CLOCK2 768000 /* 256 - div */
+
 #ifdef FKS_LOGGING
 static void ess_show_mixerregs (sb_devc *devc);
 #endif
@@ -323,7 +335,6 @@
 	return retval;
 }
 
-#ifdef OBSOLETE
 static int ess_calc_best_speed
 	(int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
 {
@@ -347,7 +358,6 @@
 
 	return retval;
 }
-#endif
 
 /*
  * Depending on the audiochannel ESS devices can
@@ -366,11 +376,14 @@
 		 * The 0x80 is important for the first audio channel
 		 */
 		div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
+	} else if(devc->caps & SB_CAP_ES18XX_RATE) {
+		ess_calc_best_speed(ES18XX_CLOCK1, 128, ES18XX_CLOCK2, 256, 
+						&div, speedp);
 	} else {
 		if (*speedp > 22000) {
-			div = 0x80 | ess_calc_div (795500, 256, speedp, &diff);
+			div = 0x80 | ess_calc_div (ES1688_CLOCK1, 256, speedp, &diff);
 		} else {
-			div = 0x00 | ess_calc_div (397700, 128, speedp, &diff);
+			div = 0x00 | ess_calc_div (ES1688_CLOCK2, 128, speedp, &diff);
 		}
 	}
 	*divp = div;
@@ -1070,6 +1083,12 @@
 		case 1788:
 			submodel = SUBMDL_ES1788;
 			break;
+		case 1878:
+			submodel = SUBMDL_ES1878;
+			break;
+		case 1879:
+			submodel = SUBMDL_ES1879;
+			break;
 		case 1887:
 			submodel = SUBMDL_ES1887;
 			break;
@@ -1117,6 +1136,10 @@
 				chip = "ES1878";
 				devc->submodel = SUBMDL_ES1878;
 				break;
+			case 0x1879:
+				chip = "ES1879";
+				devc->submodel = SUBMDL_ES1879;
+				break;
 			default:
 				if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) {
 					printk ("ess_init: Unrecognized %04x\n", type);
@@ -1173,6 +1196,17 @@
 		sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f);
 	} else {
 		strcpy(name, "Jazz16");
+	}
+
+	/* AAS: info stolen from ALSA: these boards have different clocks */
+	switch(devc->submodel) {
+/* APPARENTLY NOT 1869 
+		case SUBMDL_ES1869:
+*/		
+		case SUBMDL_ES1887:
+		case SUBMDL_ES1888:
+			devc->caps |= SB_CAP_ES18XX_RATE;
+			break;
 	}
 
 	hw_config->name = name;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_mixer.c linux.pre11.3/drivers/sound/sb_mixer.c
--- linux.vanilla/drivers/sound/sb_mixer.c	Fri Apr 16 22:10:57 1999
+++ linux.pre11.3/drivers/sound/sb_mixer.c	Mon Jul 19 23:28:08 1999
@@ -13,6 +13,7 @@
  *
  * Thomas Sailer				: ioctl code reworked (vmalloc/vfree removed)
  * Rolf Fokkens (Dec 20 1998)	: Moved ESS stuff into sb_ess.[ch]
+ * Stanislav Voronyi <stas@esc.kharkov.com>	: Support for AWE 3DSE device (Jun 7 1999)
  */
 
 #include <linux/config.h>
@@ -550,14 +551,37 @@
 	int val, ret;
 
 	/*
-	 * Use ioctl(fd, SOUND_MIXER_PRIVATE1, &mode) to turn AGC off (0) or on (1).
+	 * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1).
+	 * Use ioctl(fd, SOUND_MIXER_3DSE, &mode) to turn 3DSE off (0) or on (1)
+	 *					      or mode==2 put 3DSE state to mode.
 	 */
-	if (cmd == SOUND_MIXER_PRIVATE1 && devc->model == MDL_SB16) 
-	{
-		if (get_user(val, (int *)arg))
-			return -EFAULT;
-		sb_setmixer(devc, 0x43, (~val) & 0x01);
-		return 0;
+	if (devc->model == MDL_SB16) {
+		if (cmd == SOUND_MIXER_AGC) 
+		{
+			if (get_user(val, (int *)arg))
+				return -EFAULT;
+			sb_setmixer(devc, 0x43, (~val) & 0x01);
+			return 0;
+		}
+		if (cmd == SOUND_MIXER_3DSE) 
+		{
+			/* I put here 15, but I don't know the exact version.
+			   At least my 4.13 havn't 3DSE, 4.16 has it. */
+			if (devc->minor < 15)
+				return -EINVAL;
+			if (get_user(val, (int *)arg))
+				return -EFAULT;
+			if (val == 0 || val == 1)
+				sb_chgmixer(devc, AWE_3DSE, 0x01, val);
+			else if (val == 2)
+			{
+				ret = sb_getmixer(devc, AWE_3DSE)&0x01;
+				return put_user(ret, (int *)arg);
+			}
+			else
+				return -EINVAL;
+			return 0;
+		}
 	}
 	if (((cmd >> 8) & 0xff) == 'M') 
 	{
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sb_mixer.h linux.pre11.3/drivers/sound/sb_mixer.h
--- linux.vanilla/drivers/sound/sb_mixer.h	Sat Jan  9 21:50:45 1999
+++ linux.pre11.3/drivers/sound/sb_mixer.h	Mon Jul 19 23:28:08 1999
@@ -78,6 +78,11 @@
 #define RIGHT_CHN	1
 
 /*
+ * 3DSE register of AWE32/64
+ */
+#define AWE_3DSE	0x90
+
+/*
  * Mixer registers of ALS007
  */
 #define ALS007_RECORD_SRC	0x6c
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sgalaxy.c linux.pre11.3/drivers/sound/sgalaxy.c
--- linux.vanilla/drivers/sound/sgalaxy.c	Fri Nov 13 01:37:15 1998
+++ linux.pre11.3/drivers/sound/sgalaxy.c	Mon Jul 19 23:28:09 1999
@@ -2,7 +2,7 @@
  * sound/sgalaxy.c
  *
  * Low level driver for Aztech Sound Galaxy cards.
- * Copyright 1998 Artur Skawina
+ * Copyright 1998 Artur Skawina <skawina@geocities.com>
  *
  * Supported cards:
  *    Aztech Sound Galaxy Waverider Pro 32 - 3D
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sonicvibes.c linux.pre11.3/drivers/sound/sonicvibes.c
--- linux.vanilla/drivers/sound/sonicvibes.c	Fri Apr 16 22:10:57 1999
+++ linux.pre11.3/drivers/sound/sonicvibes.c	Tue Jul 20 00:04:49 1999
@@ -68,6 +68,9 @@
  *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
  *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
  *                     Note: dmaio hack might still be wrong on archs other than i386
+ *    15.06.99   0.15  Fix bad allocation bug.
+ *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.99   0.16  Add pci_set_master
  *
  */
 
@@ -699,8 +702,9 @@
 	db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
 	if (!db->rawbuf) {
 		db->ready = db->mapped = 0;
-		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER && !db->rawbuf; order--)
-			db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
+		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
+			if ((db->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order)))
+				break;
 		if (!db->rawbuf)
 			return -ENOMEM;
 		db->buforder = order;
@@ -2321,7 +2325,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.14 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.16 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");
@@ -2447,6 +2451,7 @@
 			goto err_dev3;
 		if ((s->dev_dmfm = register_sound_special(&sv_dmfm_fops, 15 /* ?? */)) < 0)
 			goto err_dev4;
+		pci_set_master(pcidev);  /* enable bus mastering */
 		/* initialize the chips */
 		fs = get_fs();
 		set_fs(KERNEL_DS);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sound_calls.h linux.pre11.3/drivers/sound/sound_calls.h
--- linux.vanilla/drivers/sound/sound_calls.h	Wed Jan  6 23:02:26 1999
+++ linux.pre11.3/drivers/sound/sound_calls.h	Mon Jul 19 23:28:08 1999
@@ -157,6 +157,7 @@
 /*	From mpu401.c */
 void attach_mpu401(struct address_info * hw_config);
 int probe_mpu401(struct address_info *hw_config);
+int intchk_mpu401(void *dev_id);
 void mpuintr(int irq, void *dev_id, struct pt_regs * dummy);
 
 /*	From uart6850.c */
@@ -256,21 +257,39 @@
 void unload_trix_mpu(struct address_info *hw_info);
 void unload_cs4232(struct address_info *hw_info);
 void unload_cs4232_mpu(struct address_info *hw_info);
+void unload_opl3sa_wss(struct address_info *hw_info);
+void unload_opl3sa_sb(struct address_info *hw_info);
+void unload_opl3sa_mpu(struct address_info *hw_info);
 void unload_opl3sa2(struct address_info *hw_info);
 void unload_opl3sa2_mpu(struct address_info *hw_info);
+void unload_opl3sa2_mss(struct address_info *hw_info);
+void unload_softsyn (struct address_info *hw_config);
 
-/* From cs4232.c */
-
+/*	From cs4232.c */
 int probe_cs4232 (struct address_info *hw_config);
 void attach_cs4232 (struct address_info *hw_config);
 int probe_cs4232_mpu (struct address_info *hw_config);
 void attach_cs4232_mpu (struct address_info *hw_config);
 
-/* From opl3sa2.c */
+/*	From opl3sa.c */
+void attach_opl3sa_wss (struct address_info *hw_config);
+int probe_opl3sa_wss (struct address_info *hw_config);
+void attach_opl3sa_sb (struct address_info *hw_config);
+int probe_opl3sa_sb (struct address_info *hw_config);
+void attach_opl3sa_mpu (struct address_info *hw_config);
+int probe_opl3sa_mpu (struct address_info *hw_config);
+
+/*	From opl3sa2.c */
 int probe_opl3sa2 (struct address_info *hw_config);
 void attach_opl3sa2 (struct address_info *hw_config);
 int probe_opl3sa2_mpu (struct address_info *hw_config);
 void attach_opl3sa2_mpu (struct address_info *hw_config);
+int probe_opl3sa2_mss (struct address_info *hw_config);
+void attach_opl3sa2_mss (struct address_info *hw_config);
+
+/*	From softoss.c */
+void attach_softsyn_card (struct address_info *hw_config);
+int probe_softsyn (struct address_info *hw_config);
 
 /*	From maui.c */
 void attach_maui(struct address_info * hw_config);
@@ -291,12 +310,12 @@
 int probe_waveartist(struct address_info *hw_config);
 void unload_waveartist(struct address_info *hw_config);
 
-/*      From wavefront.c */
+/*	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 */
+/*	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);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/sound_syms.c linux.pre11.3/drivers/sound/sound_syms.c
--- linux.vanilla/drivers/sound/sound_syms.c	Wed Jan  6 23:02:26 1999
+++ linux.pre11.3/drivers/sound/sound_syms.c	Mon Jul 19 23:28:08 1999
@@ -3,6 +3,9 @@
  *	modulespace.
  *
  *      (C) Copyright 1997      Alan Cox, Licensed under the GNU GPL
+ *
+ *	Thu May 27 1999 Andrew J. Kroll <ag784@freenet..buffalo..edu>
+ *	left out exported symbol... fixed
  */
 
 #include <linux/module.h>
@@ -43,6 +46,7 @@
 
 EXPORT_SYMBOL(load_mixer_volumes);
 
+EXPORT_SYMBOL(trace_init); /* oops! this is needed for maui.c -- AJK */
 
 EXPORT_SYMBOL(conf_printf);
 EXPORT_SYMBOL(conf_printf2);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/sound/trix.c linux.pre11.3/drivers/sound/trix.c
--- linux.vanilla/drivers/sound/trix.c	Wed Mar 10 21:13:08 1999
+++ linux.pre11.3/drivers/sound/trix.c	Mon Jul 19 23:28:08 1999
@@ -42,6 +42,12 @@
 
 static int mpu = 0;
 
+#ifdef TRIX_JOYSTICK
+static int joystick=1;
+#else
+static int joystick=0;
+#endif
+
 static unsigned char trix_read(int addr)
 {
 	outb(((unsigned char) addr), 0x390);	/* MT-0002-PC ASIC address */
@@ -196,9 +202,8 @@
 
 	if (ret)
 	{
-#ifdef TRIX_ENABLE_JOYSTICK
-		trix_write(0x15, 0x80);
-#endif
+		if(joystick==1)
+			trix_write(0x15, 0x80);
 		request_region(0x390, 2, "AudioTrix");
 	}
 	return ret;
@@ -477,7 +482,7 @@
 MODULE_PARM(sb_irq,"i");
 MODULE_PARM(mpu_io,"i");
 MODULE_PARM(mpu_irq,"i");
-
+MODULE_PARM(joystick, "i");
 struct address_info config;
 struct address_info sb_config;
 struct address_info mpu_config;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/Makefile linux.pre11.3/drivers/tc/Makefile
--- linux.vanilla/drivers/tc/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/tc/Makefile	Mon Jul 19 23:28:26 1999
@@ -0,0 +1,33 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+SUB_DIRS     :=
+MOD_SUB_DIRS := 
+ALL_SUB_DIRS := 
+
+L_TARGET := tc.a
+L_OBJS   := tc.o
+
+# Nasty trick as nobody references tcsyms.o, but we still want it linked.
+# Stolen from pci Makefile
+ifeq ($(CONFIG_MODULES),y)
+O_TARGET = tc_syms.o
+OX_OBJS  = tcsyms.o
+O_OBJS   = tc.o
+L_OBJS   := tc_syms.o
+else
+L_OBJS   := tc.o
+endif
+
+ifdef CONFIG_ZS
+L_OBJS   += zs.o
+endif
+
+include $(TOPDIR)/Rules.make
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/tc.c linux.pre11.3/drivers/tc/tc.c
--- linux.vanilla/drivers/tc/tc.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/tc/tc.c	Mon Jul 19 23:28:26 1999
@@ -0,0 +1,236 @@
+/* $Id: $
+ * tc-init: We assume the TURBOchannel to be up and running so
+ * just probe for Modules and fill in the global data structure
+ * tc_bus.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) Harald Koerfgen, 1998
+ *
+ */
+
+#include <linux/string.h>
+#include <asm/init.h>
+#include <asm/addrspace.h>
+#include <asm/errno.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/tcinfo.h>
+#include <asm/dec/tcmodule.h>
+#include <asm/dec/interrupts.h>
+
+#include <asm/ptrace.h>
+#include <linux/kernel.h>
+
+#define TC_DEBUG
+
+slot_info tc_bus[MAX_SLOT];
+static int max_tcslot = 0;
+static tcinfo *info = (tcinfo *)0;
+
+unsigned long system_base = 0;
+
+extern void (*dbe_board_handler)(struct pt_regs *regs);
+extern unsigned long *(*rex_slot_address)(int);
+extern void *(*rex_gettcinfo)(void);
+
+/*
+ * Interface to the world. Read comment in include/asm-mips/tc.h.
+ */
+
+int search_tc_card(char *name)
+{
+	int slot;
+	slot_info *sip;
+
+	for (slot = 0; slot <= max_tcslot; slot++) {
+		sip = &tc_bus[slot];
+		if ((sip->flags & FREE) && (strncmp(sip->name, name, strlen(name)) == 0)) {
+			return slot;
+		}
+	}
+
+	return -ENODEV;
+}
+
+void claim_tc_card(int slot)
+{
+	if (tc_bus[slot].flags & IN_USE) {
+		printk("claim_tc_card: attempting to claim a card already in use\n");
+		return;
+	}
+	tc_bus[slot].flags &= ~FREE;
+	tc_bus[slot].flags |= IN_USE;
+}
+
+void release_tc_card(int slot)
+{
+	if (tc_bus[slot].flags & FREE) {
+		printk("release_tc_card: attempting to release a card already free\n");
+		return;
+	}
+	tc_bus[slot].flags &= ~IN_USE;
+	tc_bus[slot].flags |= FREE;
+}
+
+unsigned long get_tc_base_addr(int slot)
+{
+	return tc_bus[slot].base_addr;
+}
+
+unsigned long get_tc_irq_nr(int slot)
+{
+	return tc_bus[slot].interrupt;
+}
+
+unsigned long get_tc_speed(void)
+{
+	return 100000 * (10000 / (unsigned long)info->clk_period);
+}
+
+/*
+ * Probing for TURBOchannel modules
+ */
+__initfunc(static void my_dbe_handler(struct pt_regs *regs))
+{
+	regs->cp0_epc += 4;
+}
+
+__initfunc(static void tc_probe(unsigned long startaddr, unsigned long size, int max_slot))
+{
+	int i, slot;
+	long offset;
+	unsigned char *module;
+	void (*old_be_handler)(struct pt_regs *regs);
+
+	/* Install our exception handler temporarily */
+
+	old_be_handler = dbe_board_handler;
+	dbe_board_handler = my_dbe_handler;
+	for (slot = 0; slot <= max_slot; slot++) {
+		module = (char *)(startaddr + slot * size);
+		offset = -1;
+		if (module[OLDCARD + PATTERN0] == 0x55 && module[OLDCARD + PATTERN1] == 0x00
+		  && module[OLDCARD + PATTERN2] == 0xaa && module[OLDCARD + PATTERN3] == 0xff)
+			offset = OLDCARD;
+		if (module[PATTERN0] == 0x55 && module[PATTERN1] == 0x00
+		  && module[PATTERN2] == 0xaa && module[PATTERN3] == 0xff)
+			offset = 0;
+
+		if (offset != -1) {
+			tc_bus[slot].base_addr = (unsigned long)module;
+			for(i = 0; i < 8; i++) {
+				tc_bus[slot].firmware[i] = module[FIRM_VER + offset + 4 * i];
+				tc_bus[slot].vendor[i] = module[VENDOR + offset + 4 * i];
+				tc_bus[slot].name[i] = module[MODULE + offset + 4 * i];
+			}
+			tc_bus[slot].firmware[8] = 0;
+			tc_bus[slot].vendor[8] = 0;
+			tc_bus[slot].name[8] = 0;
+			/*
+			 * Looks unneccesary, but we may change
+			 * TC? in the future
+			 */
+			switch (slot) {
+			case 0:
+				tc_bus[slot].interrupt = TC0;
+				break;
+			case 1:
+				tc_bus[slot].interrupt = TC1;
+				break;
+			case 2:
+				tc_bus[slot].interrupt = TC2;
+				break;
+			/*
+			 * Yuck! DS5000/200 onboard devices
+			 */
+			case 5:
+				tc_bus[slot].interrupt = SCSI_INT;
+				break;
+			case 6:
+				tc_bus[slot].interrupt = ETHER;
+				break;
+			default:
+				tc_bus[slot].interrupt = -1;
+				break;
+			}	
+		}
+	}
+
+	dbe_board_handler = old_be_handler;
+}
+
+/*
+ * the main entry
+ */
+__initfunc(void tc_init(void))
+{
+	int tc_clock;
+	int i;
+	unsigned long slot0addr;
+	unsigned long slot_size;
+
+	if (!TURBOCHANNEL)
+		return;
+
+	for (i = 0; i < MAX_SLOT; i++) {
+		tc_bus[i].base_addr = 0;
+		tc_bus[i].name[0] = 0;
+		tc_bus[i].vendor[0] = 0;
+		tc_bus[i].firmware[0] = 0;
+		tc_bus[i].interrupt = -1;
+		tc_bus[i].flags = FREE;
+	}
+
+	info = (tcinfo *) rex_gettcinfo();
+	slot0addr = (unsigned long)KSEG1ADDR(rex_slot_address(0));
+
+	switch (mips_machtype) {
+	case MACH_DS5000_200:
+		max_tcslot = 6;
+		break;
+	case MACH_DS5000_1XX:
+	case MACH_DS5000_2X0:
+		max_tcslot = 2;
+		break;
+	case MACH_DS5000_XX:
+	default:
+		max_tcslot = 1;
+		break;
+	}
+
+	tc_clock = 10000 / info->clk_period;
+
+	if (TURBOCHANNEL && info->slot_size && slot0addr) {
+		printk("TURBOchannel rev. %1d at %2d.%1d MHz ", info->revision,
+			tc_clock / 10, tc_clock % 10);
+		printk("(%sparity)\n", info->parity ? "" : "no ");
+
+		slot_size = info->slot_size << 20;
+
+		tc_probe(slot0addr, slot_size, max_tcslot);
+
+  		/*
+  		 * All TURBOchannel DECstations have the onboard devices
+ 		 * where the (max_tcslot + 1 or 2 on DS5k/xx) Option Module
+ 		 * would be.
+ 		 */
+ 		if(mips_machtype == MACH_DS5000_XX)
+ 			i = 2;
+		else
+ 			i = 1;
+ 		
+ 	        system_base = slot0addr + slot_size * (max_tcslot + i);
+
+#ifdef TC_DEBUG
+		for (i = 0; i <= max_tcslot; i++)
+			if (tc_bus[i].base_addr) {
+				printk("    slot %d: ", i);
+				printk("%s %s %s\n", tc_bus[i].vendor,
+					tc_bus[i].name, tc_bus[i].firmware);
+			}
+#endif
+	}
+
+}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/tcsyms.c linux.pre11.3/drivers/tc/tcsyms.c
--- linux.vanilla/drivers/tc/tcsyms.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/tc/tcsyms.c	Mon Jul 19 23:28:26 1999
@@ -0,0 +1,14 @@
+/*
+ *	Turbo Channel Services -- Exported Symbols
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/dec/tc.h>
+
+EXPORT_SYMBOL(get_tc_irq_nr);
+EXPORT_SYMBOL(claim_tc_card);
+EXPORT_SYMBOL(search_tc_card);
+EXPORT_SYMBOL(get_tc_speed);
+EXPORT_SYMBOL(get_tc_base_addr);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/zs.c linux.pre11.3/drivers/tc/zs.c
--- linux.vanilla/drivers/tc/zs.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/tc/zs.c	Mon Jul 19 23:28:26 1999
@@ -0,0 +1,2107 @@
+/*
+ * decserial.c: Serial port driver for IOASIC DECsatations.
+ *
+ * Derived from drivers/macintosh/macserial.c by Harald Koerfgen.
+ * Derived from drivers/sbus/char/sunserial.c by Paul Mackerras.
+ *
+ * DECstation changes
+ * Copyright (C) 1998 Harald Koerfgen (Harald.Koerfgen@home.ivm.de)
+ *
+ * For the rest of the code the original Copyright applies:
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Keyboard and mouse are not supported right now. If you want to change this,
+ * you might want to have a look at drivers/sbus/char/sunserial.c to see
+ * how this might be done. HK
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/dec/interrupts.h>
+#include <asm/dec/machtype.h>
+#include <asm/dec/tc.h>
+#include <asm/dec/ioasic_addrs.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
+
+#include "zs.h"
+
+
+/*
+ * It would be nice to dynamically allocate everything that
+ * depends on NUM_SERIAL, so we could support any number of
+ * Z8530s, but for now...
+ */
+#define NUM_SERIAL	2		/* Max number of ZS chips supported */
+#define NUM_CHANNELS	(NUM_SERIAL * 2)	/* 2 channels per chip */
+
+#define RECOVERY_DELAY  udelay(2)
+
+struct dec_zschannel zs_channels[NUM_CHANNELS];
+
+struct dec_serial zs_soft[NUM_CHANNELS];
+int zs_channels_found;
+struct dec_serial *zs_chain;	/* list of all channels */
+
+struct tty_struct zs_ttys[NUM_CHANNELS];
+
+#ifdef CONFIG_SERIAL_CONSOLE
+static struct console sercons;
+#endif
+
+#ifdef CONFIG_KGDB
+struct dec_zschannel *zs_kgdbchan;
+static unsigned char scc_inittab[] = {
+	9,  0x80,	/* reset A side (CHRA) */
+	13, 0,		/* set baud rate divisor */
+	12, 1,
+	14, 1,		/* baud rate gen enable, src=rtxc (BRENABL) */
+	11, 0x50,	/* clocks = br gen (RCBR | TCBR) */
+	5,  0x6a,	/* tx 8 bits, assert RTS (Tx8 | TxENAB | RTS) */
+	4,  0x44,	/* x16 clock, 1 stop (SB1 | X16CLK)*/
+	3,  0xc1,	/* rx enable, 8 bits (RxENABLE | Rx8)*/
+};
+#endif
+
+static unsigned char zs_init_regs[16] __initdata = {
+	0,                           /* write 0 */
+	0,			     /* write 1 */
+	0xf0,                        /* write 2 */
+	(Rx8),                       /* write 3 */
+	(X16CLK | SB1),              /* write 4 */
+	(Tx8),                       /* write 5 */
+	0, 0, 0,                     /* write 6, 7, 8 */
+	(VIS),                       /* write 9 */
+	(NRZ),                       /* write 10 */
+	(TCBR | RCBR),               /* write 11 */
+	0, 0,                        /* BRG time constant, write 12 + 13 */
+	(BRSRC | BRENABL),           /* write 14 */
+	0 			     /* write 15 */
+};
+
+#define ZS_CLOCK         7372800 	/* Z8530 RTxC input clock rate */
+
+DECLARE_TASK_QUEUE(tq_zs_serial);
+
+struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* serial subtype definitions */
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/*
+ * Debugging.
+ */
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_THROTTLE
+#undef SERIAL_PARANOIA_CHECK
+
+#define RS_STROBE_TIME 10
+#define RS_ISR_PASS_LIMIT 256
+
+#define _INLINE_ inline
+
+static void probe_sccs(void);
+static void change_speed(struct dec_serial *info);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+
+static struct tty_struct *serial_table[NUM_CHANNELS];
+static struct termios *serial_termios[NUM_CHANNELS];
+static struct termios *serial_termios_locked[NUM_CHANNELS];
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write.  We need to
+ * lock it in case the copy_from_user 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;
+
+static inline int serial_paranoia_check(struct dec_serial *info,
+					dev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%d, %d) in %s\n";
+	static const char *badinfo =
+		"Warning: null mac_serial for (%d, %d) in %s\n";
+
+	if (!info) {
+		printk(badinfo, MAJOR(device), MINOR(device), routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, MAJOR(device), MINOR(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts
+ */
+static int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	9600, 19200, 38400, 57600, 0, 0 };
+
+/* 
+ * Reading and writing Z8530 registers.
+ */
+static inline unsigned char read_zsreg(struct dec_zschannel *channel,
+				       unsigned char reg)
+{
+	unsigned char retval;
+
+	if (reg != 0) {
+		*channel->control = reg & 0xf;
+		RECOVERY_DELAY;
+	}
+	retval = *channel->control;
+	RECOVERY_DELAY;
+	return retval;
+}
+
+static inline void write_zsreg(struct dec_zschannel *channel,
+			       unsigned char reg, unsigned char value)
+{
+	if (reg != 0) {
+		*channel->control = reg & 0xf;
+		RECOVERY_DELAY;
+	}
+	*channel->control = value;
+	RECOVERY_DELAY;
+	return;
+}
+
+static inline unsigned char read_zsdata(struct dec_zschannel *channel)
+{
+	unsigned char retval;
+
+	retval = *channel->data;
+	RECOVERY_DELAY;
+	return retval;
+}
+
+static inline void write_zsdata(struct dec_zschannel *channel,
+				unsigned char value)
+{
+	*channel->data = value;
+	RECOVERY_DELAY;
+	return;
+}
+
+static inline void load_zsregs(struct dec_zschannel *channel,
+			       unsigned char *regs)
+{
+/*	ZS_CLEARERR(channel);
+	ZS_CLEARFIFO(channel); */
+	/* Load 'em up */
+	write_zsreg(channel, R4, regs[R4]);
+	write_zsreg(channel, R3, regs[R3] & ~RxENABLE);
+	write_zsreg(channel, R5, regs[R5] & ~TxENAB);
+	write_zsreg(channel, R9, regs[R9]);
+	write_zsreg(channel, R1, regs[R1]);
+	write_zsreg(channel, R2, regs[R2]);
+	write_zsreg(channel, R10, regs[R10]);
+	write_zsreg(channel, R11, regs[R11]);
+	write_zsreg(channel, R12, regs[R12]);
+	write_zsreg(channel, R13, regs[R13]);
+	write_zsreg(channel, R14, regs[R14]);
+	write_zsreg(channel, R15, regs[R15]);
+	write_zsreg(channel, R3, regs[R3]);
+	write_zsreg(channel, R5, regs[R5]);
+	return;
+}
+
+/* Sets or clears DTR/RTS on the requested line */
+static inline void zs_rtsdtr(struct dec_serial *ss, int set)
+{
+	if (ss->zs_channel != ss->zs_chan_a) {
+		if (set)
+			ss->zs_chan_a->curregs[5] |= (RTS | DTR);
+		else
+			ss->zs_chan_a->curregs[5] &= ~(RTS | DTR);
+		write_zsreg(ss->zs_chan_a, 5, ss->zs_chan_a->curregs[5]);
+	}
+	return;
+}
+
+/* Utility routines for the Zilog */
+static inline int get_zsbaud(struct dec_serial *ss)
+{
+	struct dec_zschannel *channel = ss->zs_channel;
+	int brg;
+
+	/* The baud rate is split up between two 8-bit registers in
+	 * what is termed 'BRG time constant' format in my docs for
+	 * the chip, it is a function of the clk rate the chip is
+	 * receiving which happens to be constant.
+	 */
+	brg = (read_zsreg(channel, 13) << 8);
+	brg |= read_zsreg(channel, 12);
+	return BRG_TO_BPS(brg, (ZS_CLOCK/(ss->clk_divisor)));
+}
+
+/* On receive, this clears errors and the receiver interrupts */
+static inline void rs_recv_clear(struct dec_zschannel *zsc)
+{
+	write_zsreg(zsc, 0, ERR_RES);
+	write_zsreg(zsc, 0, RES_H_IUS); /* XXX this is unnecessary */
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void rs_sched_event(struct dec_serial *info,
+				  int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_zs_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(struct dec_serial *info,
+				   struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned char ch, stat, flag;
+
+	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) != 0) {
+
+		stat = read_zsreg(info->zs_channel, R1);
+		ch = read_zsdata(info->zs_channel);
+
+#ifdef CONFIG_KGDB
+		if (info->kgdb_channel) {
+			if (ch == 0x03 || ch == '$')
+				breakpoint();
+			if (stat & (Rx_OVR|FRM_ERR|PAR_ERR))
+				write_zsreg(info->zs_channel, 0, ERR_RES);
+			return;
+		}
+#endif
+		if (!tty)
+			continue;
+
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+			static int flip_buf_ovf;
+			++flip_buf_ovf;
+			continue;
+		}
+		tty->flip.count++;
+		{
+			static int flip_max_cnt;
+			if (flip_max_cnt < tty->flip.count)
+				flip_max_cnt = tty->flip.count;
+		}
+		if (stat & Rx_OVR) {
+			flag = TTY_OVERRUN;
+		} else if (stat & FRM_ERR) {
+			flag = TTY_FRAME;
+		} else if (stat & PAR_ERR) {
+			flag = TTY_PARITY;
+		} else
+			flag = 0;
+		if (flag)
+			/* reset the error indication */
+			write_zsreg(info->zs_channel, 0, ERR_RES);
+		*tty->flip.flag_buf_ptr++ = flag;
+		*tty->flip.char_buf_ptr++ = ch;
+	}
+	tty_flip_buffer_push(tty);
+}
+
+static void transmit_chars(struct dec_serial *info)
+{
+	if ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0)
+		return;
+	info->tx_active = 0;
+
+	if (info->x_char) {
+		/* Send next char */
+		write_zsdata(info->zs_channel, info->x_char);
+		info->x_char = 0;
+		info->tx_active = 1;
+		return;
+	}
+
+	if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tx_stopped) {
+		write_zsreg(info->zs_channel, 0, RES_Tx_P);
+		return;
+	}
+	/* Send char */
+	write_zsdata(info->zs_channel, info->xmit_buf[info->xmit_tail++]);
+	info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+	info->xmit_cnt--;
+	info->tx_active = 1;
+
+	if (info->xmit_cnt < WAKEUP_CHARS)
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+}
+
+static _INLINE_ void status_handle(struct dec_serial *info)
+{
+	unsigned char status;
+
+	/* Get status from Read Register 0 */
+	status = read_zsreg(info->zs_channel, 0);
+
+	/* FIXEM: Check for DCD transitions */
+	if (((status ^ info->read_reg_zero) & DCD) != 0
+	    && info->tty && !C_CLOCAL(info->tty)) {
+		if (status & DCD) {
+			wake_up_interruptible(&info->open_wait);
+		} else if (!(info->flags & ZILOG_CALLOUT_ACTIVE)) {
+			if (info->tty)
+				tty_hangup(info->tty);
+		}
+	}
+
+	/* Check for CTS transitions */
+	if (info->tty && C_CRTSCTS(info->tty)) {
+		/*
+		 * For some reason, on the Power Macintosh,
+		 * it seems that the CTS bit is 1 when CTS is
+		 * *negated* and 0 when it is asserted.
+		 * The DCD bit doesn't seem to be inverted
+		 * like this.
+		 */
+		if ((status & CTS) != 0) {
+			if (info->tx_stopped) {
+				info->tx_stopped = 0;
+				if (!info->tx_active)
+					transmit_chars(info);
+			}
+		} else {
+			info->tx_stopped = 1;
+		}
+	}
+
+	/* Clear status condition... */
+	write_zsreg(info->zs_channel, 0, RES_EXT_INT);
+	info->read_reg_zero = status;
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct dec_serial *info = (struct dec_serial *) dev_id;
+	unsigned char zs_intreg;
+	int shift;
+
+	/* NOTE: The read register 3, which holds the irq status,
+	 *       does so for both channels on each chip.  Although
+	 *       the status value itself must be read from the A
+	 *       channel and is only valid when read from channel A.
+	 *       Yes... broken hardware...
+	 */
+#define CHAN_IRQMASK (CHBRxIP | CHBTxIP | CHBEXT)
+
+	if (info->zs_chan_a == info->zs_channel)
+		shift = 3;	/* Channel A */
+	else
+		shift = 0;	/* Channel B */
+
+	for (;;) {
+		zs_intreg = read_zsreg(info->zs_chan_a, 3) >> shift; 
+		if ((zs_intreg & CHAN_IRQMASK) == 0)
+			break;
+
+		if (zs_intreg & CHBRxIP) {
+			receive_chars(info, regs);
+		}
+		if (zs_intreg & CHBTxIP) {
+			transmit_chars(info);
+		}
+		if (zs_intreg & CHBEXT) {
+			status_handle(info);
+		}
+	}
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_stop"))
+		return;
+	
+#if 1
+	save_flags(flags); cli();
+	if (info->zs_channel->curregs[5] & TxENAB) {
+		info->zs_channel->curregs[5] &= ~TxENAB;
+		write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+	}
+	restore_flags(flags);
+#endif
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "rs_start"))
+		return;
+	
+	save_flags(flags); cli();
+#if 1
+	if (info->xmit_cnt && info->xmit_buf && !(info->zs_channel->curregs[5] & TxENAB)) {
+		info->zs_channel->curregs[5] |= TxENAB;
+		write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+	}
+#else
+	if (info->xmit_cnt && info->xmit_buf && !info->tx_active) {
+		transmit_chars(info);
+	}
+#endif
+	restore_flags(flags);
+}
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+	run_task_queue(&tq_zs_serial);
+}
+
+static void do_softint(void *private_)
+{
+	struct dec_serial	*info = (struct dec_serial *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+}
+
+static void rs_timer(void)
+{
+}
+
+static int startup(struct dec_serial * info)
+{
+	unsigned long flags;
+
+	if (info->flags & ZILOG_INITIALIZED)
+		return 0;
+
+	if (!info->xmit_buf) {
+		info->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);
+		if (!info->xmit_buf)
+			return -ENOMEM;
+	}
+
+	save_flags(flags); cli();
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("starting up ttyS%d (irq %d)...", info->line, info->irq);
+#endif
+
+	/*
+	 * Clear the receive FIFO.
+	 */
+	ZS_CLEARFIFO(info->zs_channel);
+	info->xmit_fifo_size = 1;
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	write_zsreg(info->zs_channel, 0, ERR_RES);
+	write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+	/*
+	 * Turn on RTS and DTR.
+	 */
+	zs_rtsdtr(info, 1);
+
+	/*
+	 * Finally, enable sequencing and interrupts
+	 */
+	info->zs_channel->curregs[1] = (info->zs_channel->curregs[1] & ~0x18) | (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB);
+	info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
+	info->zs_channel->curregs[5] |= (TxENAB | Tx8);
+	info->zs_channel->curregs[15] |= (DCDIE | CTSIE | TxUIE | BRKIE);
+	info->zs_channel->curregs[9] |= (VIS | MIE);
+	write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);
+	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+	write_zsreg(info->zs_channel, 15, info->zs_channel->curregs[15]);
+	write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	write_zsreg(info->zs_channel, 0, ERR_RES);
+	write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	/*
+	 * Set the speed of the serial port
+	 */
+	change_speed(info);
+
+	/* Save the current value of RR0 */
+	info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+
+	info->flags |= ZILOG_INITIALIZED;
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct dec_serial * info)
+{
+	unsigned long	flags;
+
+	if (!(info->flags & ZILOG_INITIALIZED))
+		return;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("Shutting down serial port %d (irq %d)....", info->line,
+	       info->irq);
+#endif
+	
+	save_flags(flags); cli(); /* Disable interrupts */
+	
+	if (info->xmit_buf) {
+		free_page((unsigned long) info->xmit_buf);
+		info->xmit_buf = 0;
+	}
+
+	info->zs_channel->curregs[1] = 0;
+	write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);	/* no interrupts */
+
+	info->zs_channel->curregs[3] &= ~RxENABLE;
+	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+
+	info->zs_channel->curregs[5] &= ~TxENAB;
+	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+	if (!info->tty || C_HUPCL(info->tty)) {
+		info->zs_chan_a->curregs[5] &= ~(DTR | RTS);
+		write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+	}
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ZILOG_INITIALIZED;
+	restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct dec_serial *info)
+{
+	unsigned short port;
+	unsigned cflag;
+	int	i;
+	int	brg;
+	unsigned long flags;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+	if (!(port = info->port))
+		return;
+	i = cflag & CBAUD;
+
+	save_flags(flags); cli();
+	info->zs_baud = baud_table[i];
+	info->clk_divisor = 16;
+
+	switch (info->zs_baud) {
+	default:
+		info->zs_channel->curregs[4] = X16CLK;
+		brg = BPS_TO_BRG(info->zs_baud, ZS_CLOCK/info->clk_divisor);
+		info->zs_channel->curregs[12] = (brg & 255);
+		info->zs_channel->curregs[13] = ((brg >> 8) & 255);
+	}
+
+	/* byte size and parity */
+	info->zs_channel->curregs[3] &= ~RxNBITS_MASK;
+	info->zs_channel->curregs[5] &= ~TxNBITS_MASK;
+	switch (cflag & CSIZE) {
+	case CS5:
+		info->zs_channel->curregs[3] |= Rx5;
+		info->zs_channel->curregs[5] |= Tx5;
+		break;
+	case CS6:
+		info->zs_channel->curregs[3] |= Rx6;
+		info->zs_channel->curregs[5] |= Tx6;
+		break;
+	case CS7:
+		info->zs_channel->curregs[3] |= Rx7;
+		info->zs_channel->curregs[5] |= Tx7;
+		break;
+	case CS8:
+	default: /* defaults to 8 bits */
+		info->zs_channel->curregs[3] |= Rx8;
+		info->zs_channel->curregs[5] |= Tx8;
+		break;
+	}
+
+	info->zs_channel->curregs[4] &= ~(SB_MASK | PAR_ENA | PAR_EVEN);
+	if (cflag & CSTOPB) {
+		info->zs_channel->curregs[4] |= SB2;
+	} else {
+		info->zs_channel->curregs[4] |= SB1;
+	}
+	if (cflag & PARENB) {
+		info->zs_channel->curregs[4] |= PAR_ENA;
+	}
+	if (!(cflag & PARODD)) {
+		info->zs_channel->curregs[4] |= PAR_EVEN;
+	}
+
+	if (!(cflag & CLOCAL)) {
+		if (!(info->zs_channel->curregs[15] & DCDIE))
+			info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+		info->zs_channel->curregs[15] |= DCDIE;
+	} else
+		info->zs_channel->curregs[15] &= ~DCDIE;
+	if (cflag & CRTSCTS) {
+		info->zs_channel->curregs[15] |= CTSIE;
+		if ((read_zsreg(info->zs_channel, 0) & CTS) != 0)
+			info->tx_stopped = 1;
+	} else {
+		info->zs_channel->curregs[15] &= ~CTSIE;
+		info->tx_stopped = 0;
+	}
+
+	/* Load up the new values */
+	load_zsregs(info->zs_channel, info->zs_channel->curregs);
+
+	restore_flags(flags);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || info->tx_stopped ||
+	    !info->xmit_buf)
+		return;
+
+	/* Enable transmitter */
+	save_flags(flags); cli();
+	transmit_chars(info);
+	restore_flags(flags);
+}
+
+static int rs_write(struct tty_struct * tty, int from_user,
+		    const unsigned char *buf, int count)
+{
+	int	c, total = 0;
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_write"))
+		return 0;
+
+	if (!tty || !info->xmit_buf)
+		return 0;
+
+	save_flags(flags);
+	while (1) {
+		cli();		
+		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				   SERIAL_XMIT_SIZE - info->xmit_head));
+		if (c <= 0)
+			break;
+
+		if (from_user) {
+			down(&tmp_buf_sem);
+			copy_from_user(tmp_buf, buf, c);
+			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+			up(&tmp_buf_sem);
+		} else
+			memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		info->xmit_cnt += c;
+		restore_flags(flags);
+		buf += c;
+		count -= c;
+		total += c;
+	}
+
+	if (info->xmit_cnt && !tty->stopped && !info->tx_stopped
+	    && !info->tx_active)
+		transmit_chars(info);
+	restore_flags(flags);
+	return total;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	int	ret;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
+		return 0;
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+			
+	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
+		return 0;
+	return info->xmit_cnt;
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+				
+	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
+		return;
+	cli();
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	sti();
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("throttle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
+		return;
+	
+	if (I_IXOFF(tty)) {
+		save_flags(flags); cli();
+		info->x_char = STOP_CHAR(tty);
+		if (!info->tx_active)
+			transmit_chars(info);
+		restore_flags(flags);
+	}
+
+	if (C_CRTSCTS(tty)) {
+		/*
+		 * Here we want to turn off the RTS line.  On Macintoshes,
+		 * we only get the DTR line, which goes to both DTR and
+		 * RTS on the modem.  RTS doesn't go out to the serial
+		 * port socket.  So you should make sure your modem is
+		 * set to ignore DTR if you're using CRTSCTS.
+		 */
+		save_flags(flags); cli();
+		info->zs_chan_a->curregs[5] &= ~(DTR | RTS);
+		write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+		restore_flags(flags);
+	}
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
+		return;
+	
+	if (I_IXOFF(tty)) {
+		save_flags(flags); cli();
+		if (info->x_char)
+			info->x_char = 0;
+		else {
+			info->x_char = START_CHAR(tty);
+			if (!info->tx_active)
+				transmit_chars(info);
+		}
+		restore_flags(flags);
+	}
+
+	if (C_CRTSCTS(tty)) {
+		/* Assert RTS and DTR lines */
+		save_flags(flags); cli();
+		info->zs_chan_a->curregs[5] |= DTR | RTS;
+		write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+		restore_flags(flags);
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct dec_serial * info,
+			   struct serial_struct * retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->line;
+	tmp.port = info->port;
+	tmp.irq = info->irq;
+	tmp.flags = info->flags;
+	tmp.baud_base = info->baud_base;
+	tmp.close_delay = info->close_delay;
+	tmp.closing_wait = info->closing_wait;
+	tmp.custom_divisor = info->custom_divisor;
+	return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
+}
+
+static int set_serial_info(struct dec_serial * info,
+			   struct serial_struct * new_info)
+{
+	struct serial_struct new_serial;
+	struct dec_serial old_info;
+	int 			retval = 0;
+
+	if (!new_info)
+		return -EFAULT;
+	copy_from_user(&new_serial,new_info,sizeof(new_serial));
+	old_info = *info;
+
+	if (!suser()) {
+		if ((new_serial.baud_base != info->baud_base) ||
+		    (new_serial.type != info->type) ||
+		    (new_serial.close_delay != info->close_delay) ||
+		    ((new_serial.flags & ~ZILOG_USR_MASK) !=
+		     (info->flags & ~ZILOG_USR_MASK)))
+			return -EPERM;
+		info->flags = ((info->flags & ~ZILOG_USR_MASK) |
+			       (new_serial.flags & ZILOG_USR_MASK));
+		info->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	if (info->count > 1)
+		return -EBUSY;
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	info->baud_base = new_serial.baud_base;
+	info->flags = ((info->flags & ~ZILOG_FLAGS) |
+			(new_serial.flags & ZILOG_FLAGS));
+	info->type = new_serial.type;
+	info->close_delay = new_serial.close_delay;
+	info->closing_wait = new_serial.closing_wait;
+
+check_and_exit:
+	retval = startup(info);
+	return retval;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space. 
+ */
+static int get_lsr_info(struct dec_serial * info, unsigned int *value)
+{
+	unsigned char status;
+
+	cli();
+	status = read_zsreg(info->zs_channel, 0);
+	sti();
+	put_user(status,value);
+	return 0;
+}
+
+static int get_modem_info(struct dec_serial *info, unsigned int *value)
+{
+	unsigned char control, status;
+	unsigned int result;
+
+	cli();
+	control = info->zs_chan_a->curregs[5];
+	status = read_zsreg(info->zs_channel, 0);
+	sti();
+	result =  ((control & RTS) ? TIOCM_RTS: 0)
+		| ((control & DTR) ? TIOCM_DTR: 0)
+		| ((status  & DCD) ? TIOCM_CAR: 0)
+		| ((status  & CTS) ? 0: TIOCM_CTS);
+	put_user(result,value);
+	return 0;
+}
+
+static int set_modem_info(struct dec_serial *info, unsigned int cmd,
+			  unsigned int *value)
+{
+	int error;
+	unsigned int arg, bits;
+
+	error = verify_area(VERIFY_READ, value, sizeof(int));
+	if (error)
+		return error;
+	get_user(arg, value);
+	bits = (arg & TIOCM_RTS? RTS: 0) + (arg & TIOCM_DTR? DTR: 0);
+	cli();
+	switch (cmd) {
+	case TIOCMBIS:
+		info->zs_chan_a->curregs[5] |= bits;
+		break;
+	case TIOCMBIC:
+		info->zs_chan_a->curregs[5] &= ~bits;
+		break;
+	case TIOCMSET:
+		info->zs_chan_a->curregs[5] = (info->zs_chan_a->curregs[5] & ~(DTR | RTS)) | bits;
+		break;
+	default:
+		sti();
+		return -EINVAL;
+	}
+	write_zsreg(info->zs_chan_a, 5, info->zs_chan_a->curregs[5]);
+	sti();
+	return 0;
+}
+
+/*
+ * rs_break - turn transmit break condition on/off
+ */
+static void rs_break(struct tty_struct *tty, int break_state)
+{
+	struct dec_serial *info = (struct dec_serial *) tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "rs_break"))
+		return;
+	if (!info->port)
+		return;
+
+	save_flags(flags); cli();
+	if (break_state == -1)
+		info->zs_channel->curregs[5] |= SND_BRK;
+	else
+		info->zs_channel->curregs[5] &= ~SND_BRK;
+	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+	restore_flags(flags);
+}
+
+static int rs_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int error;
+	struct dec_serial * info = (struct dec_serial *)tty->driver_data;
+
+#ifdef CONFIG_KGDB
+	if (info->kgdb_channel)
+		return -ENODEV;
+#endif
+	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
+	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+	
+	switch (cmd) {
+		case TIOCMGET:
+			error = verify_area(VERIFY_WRITE, (void *) arg,
+				sizeof(unsigned int));
+			if (error)
+				return error;
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+		case TIOCGSERIAL:
+			error = verify_area(VERIFY_WRITE, (void *) arg,
+						sizeof(struct serial_struct));
+			if (error)
+				return error;
+			return get_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSSERIAL:
+			return set_serial_info(info,
+					       (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(info, (unsigned int *) arg);
+
+		case TIOCSERGSTRUCT:
+			error = verify_area(VERIFY_WRITE, (void *) arg,
+						sizeof(struct dec_serial));
+			if (error)
+				return error;
+			copy_from_user((struct dec_serial *) arg,
+				       info, sizeof(struct dec_serial));
+			return 0;
+			
+		default:
+			return -ENOIOCTLCMD;
+		}
+	return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	struct dec_serial *info = (struct dec_serial *)tty->driver_data;
+	int was_stopped;
+
+	if (tty->termios->c_cflag == old_termios->c_cflag)
+		return;
+	was_stopped = info->tx_stopped;
+
+	change_speed(info);
+
+	if (was_stopped && !info->tx_stopped)
+		rs_start(tty);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ * 
+ * This routine is called when the serial port gets closed.
+ * Wait for the last remaining data to be sent.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+	struct dec_serial * info = (struct dec_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
+		return;
+	
+	save_flags(flags); cli();
+	
+	if (tty_hung_up_p(filp)) {
+		restore_flags(flags);
+		return;
+	}
+	
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_close ttys%d, count = %d\n", info->line, info->count);
+#endif
+	if ((tty->count == 1) && (info->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  Info->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("rs_close: bad serial port count; tty->count is 1, "
+		       "info->count is %d\n", info->count);
+		info->count = 1;
+	}
+	if (--info->count < 0) {
+		printk("rs_close: bad serial port count for ttys%d: %d\n",
+		       info->line, info->count);
+		info->count = 0;
+	}
+	if (info->count) {
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ZILOG_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ZILOG_NORMAL_ACTIVE)
+		info->normal_termios = *tty->termios;
+	if (info->flags & ZILOG_CALLOUT_ACTIVE)
+		info->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receiver and receive interrupts.
+	 */
+	info->zs_channel->curregs[3] &= ~RxENABLE;
+	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+	info->zs_channel->curregs[1] = 0;	/* disable any rx ints */
+	write_zsreg(info->zs_channel, 1, info->zs_channel->curregs[1]);
+	ZS_CLEARFIFO(info->zs_channel);
+	if (info->flags & ZILOG_INITIALIZED) {
+		/*
+		 * Before we drop DTR, make sure the SCC transmitter
+		 * has completely drained.
+		 */
+		rs_wait_until_sent(tty, info->timeout);
+	}
+
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE|
+			 ZILOG_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	restore_flags(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct dec_serial *info = (struct dec_serial *) tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+
+	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
+		return;
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 */
+	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout)
+		char_time = MIN(char_time, timeout);
+	while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+		current->state = TASK_INTERRUPTIBLE;
+		current->counter = 0;	/* make us low-priority */
+		schedule_timeout(char_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && ((orig_jiffies + timeout) < jiffies))
+			break;
+	}
+	current->state = TASK_RUNNING;
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+void rs_hangup(struct tty_struct *tty)
+{
+	struct dec_serial * info = (struct dec_serial *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "rs_hangup"))
+		return;
+
+	rs_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	info->count = 0;
+	info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   struct dec_serial *info)
+{
+	struct wait_queue wait = { current, NULL };
+	int		retval;
+	int		do_clocal = 0;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (info->flags & ZILOG_CLOSING) {
+		interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ZILOG_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ZILOG_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ZILOG_CALLOUT_ACTIVE) &&
+		    (info->flags & ZILOG_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+		    return -EBUSY;
+		if ((info->flags & ZILOG_CALLOUT_ACTIVE) &&
+		    (info->flags & ZILOG_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+		    return -EBUSY;
+		info->flags |= ZILOG_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ZILOG_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ZILOG_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (info->flags & ZILOG_CALLOUT_ACTIVE) {
+		if (info->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+	
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       info->line, info->count);
+#endif
+	cli();
+	if (!tty_hung_up_p(filp)) 
+		info->count--;
+	sti();
+	info->blocked_open++;
+	while (1) {
+		cli();
+		if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
+		    (tty->termios->c_cflag & CBAUD))
+			zs_rtsdtr(info, 1);
+		sti();
+		current->state = TASK_INTERRUPTIBLE;
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ZILOG_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ZILOG_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
+		    !(info->flags & ZILOG_CLOSING) &&
+		    (do_clocal || (read_zsreg(info->zs_channel, 0) & DCD)))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, info->count);
+#endif
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		info->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, info->count);
+#endif
+	if (retval)
+		return retval;
+	info->flags |= ZILOG_NORMAL_ACTIVE;
+	return 0;
+}	
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its ZILOG structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+int rs_open(struct tty_struct *tty, struct file * filp)
+{
+	struct dec_serial	*info;
+	int 			retval, line;
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= zs_channels_found))
+		return -ENODEV;
+	info = zs_soft + line;
+
+#ifdef CONFIG_KGDB
+	if (info->kgdb_channel)
+		return -ENODEV;
+#endif
+	if (serial_paranoia_check(info, tty->device, "rs_open"))
+		return -ENODEV;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
+	       info->count);
+#endif
+
+	info->count++;
+	tty->driver_data = info;
+	info->tty = tty;
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ZILOG_CLOSING)) {
+		if (info->flags & ZILOG_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ZILOG_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval)
+		return retval;
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("rs_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+
+	if ((info->count == 1) && (info->flags & ZILOG_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->normal_termios;
+		else 
+			*tty->termios = info->callout_termios;
+		change_speed(info);
+	}
+#ifdef CONFIG_SERIAL_CONSOLE
+	if (sercons.cflag && sercons.index == line) {
+		tty->termios->c_cflag = sercons.cflag;
+		sercons.cflag = 0;
+		change_speed(info);
+	}
+#endif
+
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open ttys%d successful...", info->line);
+#endif
+/* tty->low_latency = 1; */
+	return 0;
+}
+
+/* Finally, routines used to initialize the serial driver. */
+
+__initfunc(static void show_serial_version(void))
+{
+	printk("DECstation Z8530 serial driver version 0.03\n");
+}
+
+/*  Initialize Z8530s zs_channels
+ */
+
+__initfunc(static void probe_sccs(void))
+{
+	struct dec_serial **pp;
+	int i, n, n_chips = 0, n_channels, chip, channel;
+	unsigned long flags;
+
+	/*
+	 * did we get here by accident?
+	 */
+	if(!IOASIC) {
+		printk("Not on JUNKIO machine, skipping probe_sccs\n");
+		return;
+	}
+	
+	/*
+	 * When serial console is activated, tc_init has not been called yet
+	 * and system_base is undefined. Unfortunately we have to hardcode
+	 * system_base for this case :-(. HK
+	 */
+	switch(mips_machtype) {
+	case MACH_DS5000_2X0:
+		system_base = 0xbf800000;
+		n_chips = 2;
+		break;
+	case MACH_DS5000_1XX:
+		system_base = 0xbc000000;
+		n_chips = 2;
+		break;
+	case MACH_DS5000_XX:
+		system_base = 0xbc000000;
+		n_chips = 1;
+		break;
+	}
+
+	pp = &zs_chain;
+
+	n_channels = 0;
+
+	for (chip = 0; chip < n_chips; chip++) {
+		for (channel = 0; channel <= 1; channel++) {
+			/*
+			 * The sccs reside on the high byte of the 16 bit IOBUS
+			 */
+			zs_channels[n_channels].control = (volatile unsigned char *)
+				system_base + (0 == chip ? SCC0 : SCC1) + (0 == channel ? 1 : 9);
+			zs_channels[n_channels].data = zs_channels[n_channels].control + 4;
+			zs_soft[n_channels].zs_channel = &zs_channels[n_channels];
+			zs_soft[n_channels].irq = SERIAL;
+
+			if (0 == channel)
+				zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels+1];
+			else
+				zs_soft[n_channels].zs_chan_a = &zs_channels[n_channels];
+
+			*pp = &zs_soft[n_channels];
+			pp = &zs_soft[n_channels].zs_next;
+			n_channels++;
+		}
+	}
+
+	*pp = 0;
+	zs_channels_found = n_channels;
+
+	for (n = 0; n < zs_channels_found; n++) {
+		for (i = 0; i < 16; i++) {
+			zs_soft[n].zs_channel->curregs[i] = zs_init_regs[i];
+		}
+	}
+
+/*	save_and_cli(flags);
+	for (n = 0; n < zs_channels_found; n++) {
+		if (((int)zs_channels[n].control & 0xf) == 1) {
+			write_zsreg(zs_soft[channel].zs_chan_a, R9, FHWRES);
+			udelay(10000);
+			write_zsreg(zs_soft[channel].zs_chan_a, R9, 0);
+		}
+		load_zsregs(zs_soft[n].zs_channel, zs_soft[n].zs_channel->curregs);
+	} 
+	restore_flags(flags); */
+}
+
+/* zs_init inits the driver */
+__initfunc(int zs_init(void))
+{
+	int channel, i;
+	unsigned long flags;
+	struct dec_serial *info;
+
+	if(!IOASIC)
+		return -ENODEV;
+
+	/* Setup base handler, and timer table. */
+	init_bh(SERIAL_BH, do_serial_bh);
+	timer_table[RS_TIMER].fn = rs_timer;
+	timer_table[RS_TIMER].expires = 0;
+
+	/* Find out how many Z8530 SCCs we have */
+	if (zs_chain == 0)
+		probe_sccs();
+
+	show_serial_version();
+
+	/* Initialize the tty_driver structure */
+	/* Not all of this is exactly right for us. */
+
+	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.name = "ttyS";
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64;
+	serial_driver.num = zs_channels_found;
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+
+	serial_driver.init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver.flags = TTY_DRIVER_REAL_RAW;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+
+	serial_driver.open = rs_open;
+	serial_driver.close = rs_close;
+	serial_driver.write = rs_write;
+	serial_driver.flush_chars = rs_flush_chars;
+	serial_driver.write_room = rs_write_room;
+	serial_driver.chars_in_buffer = rs_chars_in_buffer;
+	serial_driver.flush_buffer = rs_flush_buffer;
+	serial_driver.ioctl = rs_ioctl;
+	serial_driver.throttle = rs_throttle;
+	serial_driver.unthrottle = rs_unthrottle;
+	serial_driver.set_termios = rs_set_termios;
+	serial_driver.stop = rs_stop;
+	serial_driver.start = rs_start;
+	serial_driver.hangup = rs_hangup;
+	serial_driver.break_ctl = rs_break;
+	serial_driver.wait_until_sent = rs_wait_until_sent;
+
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+	callout_driver.name = "cua";
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout driver\n");
+
+	save_flags(flags); cli();
+
+	for (channel = 0; channel < zs_channels_found; ++channel) {
+#ifdef CONFIG_KGDB
+		if (zs_soft[channel].kgdb_channel) {
+			continue;
+		}
+#endif
+		zs_soft[channel].clk_divisor = 16;
+		zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
+
+		if (request_irq(SERIAL, rs_interrupt, SA_SHIRQ,
+				"SCC", &zs_soft[channel]))
+			printk(KERN_ERR "decserial: can't get irq %d\n",
+			       SERIAL);
+
+		/* If console serial line, then enable interrupts. */
+/*		if (zs_soft[channel].is_cons) {
+			write_zsreg(zs_soft[channel].zs_channel, R1,
+				    (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
+			write_zsreg(zs_soft[channel].zs_channel, R9,
+				    (VIS | MIE));
+		}
+*/
+	}
+
+	for (info = zs_chain, i = 0; info; info = info->zs_next, i++)
+	{
+#ifdef CONFIG_KGDB
+		if (info->kgdb_channel) {
+			continue;
+		}
+#endif
+		info->magic = SERIAL_MAGIC;
+		info->port = (int) info->zs_channel->control;
+		info->line = i;
+		info->tty = 0;
+		info->custom_divisor = 16;
+		info->close_delay = 50;
+		info->closing_wait = 3000;
+		info->x_char = 0;
+		info->event = 0;
+		info->count = 0;
+		info->blocked_open = 0;
+		info->tqueue.routine = do_softint;
+		info->tqueue.data = info;
+		info->callout_termios =callout_driver.init_termios;
+		info->normal_termios = serial_driver.init_termios;
+		info->open_wait = 0;
+		info->close_wait = 0;
+		printk("tty%02d at 0x%08x (irq = %d)", info->line, 
+		       info->port, info->irq);
+		printk(" is a Z85C30 SCC\n");
+	}
+
+	restore_flags(flags);
+
+	return 0;
+}
+
+/*
+ * register_serial and unregister_serial allows for serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+/* PowerMac: Unused at this time, just here to make things link. */
+int register_serial(struct serial_struct *req)
+{
+	return -1;
+}
+
+void unregister_serial(int line)
+{
+	return;
+}
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ */
+
+/* This is for console output */
+static void
+zs_console_putchar(struct dec_serial *info, char ch)
+{
+	int loops = 10000;
+	unsigned long flags;
+
+	if(!info->zs_channel)
+		return;
+
+	save_flags(flags); cli();
+
+	while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops)
+		RECOVERY_DELAY;
+	*(info->zs_channel->data) = ch;
+	RECOVERY_DELAY;
+
+	restore_flags(flags);
+}
+
+static void serial_console_write(struct console *co, const char *s,
+				 unsigned count)
+{
+	struct dec_serial *info;
+	int i;
+	unsigned char nine;
+
+	info = zs_soft + co->index;
+
+#if 0
+	/*
+	 * disable master interrupt if necessary
+	 */
+	nine = info->zs_channel->curregs[9];
+	if(nine & MIE)
+		write_zsreg(info->zs_channel, R9, nine & ~MIE);
+#endif
+	/*
+	 * do it
+	 */
+	for (i = 0; i < count; i++, s++) {
+		if(*s == '\n')
+			zs_console_putchar(info, '\r');
+		zs_console_putchar(info, *s);
+	}
+	/*
+	 * restore master interrupt enable
+	 */
+#if 0
+	write_zsreg(info->zs_channel, R9, nine);
+#endif
+}
+
+/*
+ *	Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+	return 0;
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ *	Setup initial baud/bits/parity. We do two things here:
+ *	- construct a cflag setting for the first rs_open()
+ *	- initialize the serial port
+ *	Return non-zero if we didn't find a serial port.
+ */
+__initfunc(static int serial_console_setup(struct console *co, char *options))
+{
+	struct dec_serial *info;
+	int	baud = 9600;
+	int	bits = 8;
+	int	parity = 'n';
+	int	cflag = CREAD | HUPCL | CLOCAL;
+	char	*s;
+	unsigned long flags;
+
+	if(!IOASIC)
+		return -ENODEV;
+
+	info = zs_soft + co->index;
+
+	if (zs_chain == 0)
+		probe_sccs();
+
+	info->is_cons = 1;
+
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while(*s >= '0' && *s <= '9')
+			s++;
+		if (*s)
+			parity = *s++;
+		if (*s)
+			bits   = *s - '0';
+	}
+
+	/*
+	 *	Now construct a cflag setting.
+	 */
+	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;
+	}
+	switch(bits) {
+	case 7:
+		cflag |= CS7;
+		break;
+	default:
+	case 8:
+		cflag |= CS8;
+		break;
+	}
+	switch(parity) {
+	case 'o': case 'O':
+		cflag |= PARODD;
+		break;
+	case 'e': case 'E':
+		cflag |= PARENB;
+		break;
+	}
+	co->cflag = cflag;
+#if 1 
+	save_and_cli(flags);
+
+	/*
+	 * Turn on RTS and DTR.
+	 */
+	zs_rtsdtr(info, 1);
+
+	/*
+	 * Finally, enable sequencing
+	 */
+	info->zs_channel->curregs[3] |= (RxENABLE | Rx8);
+	info->zs_channel->curregs[5] |= (TxENAB | Tx8);
+	info->zs_channel->curregs[9] |= (VIS);
+	write_zsreg(info->zs_channel, 3, info->zs_channel->curregs[3]);
+	write_zsreg(info->zs_channel, 5, info->zs_channel->curregs[5]);
+	write_zsreg(info->zs_channel, 9, info->zs_channel->curregs[9]);
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	write_zsreg(info->zs_channel, 0, ERR_RES);
+	write_zsreg(info->zs_channel, 0, RES_H_IUS);
+
+	/*
+	 * Set the speed of the serial port
+	 */
+	change_speed(info);
+
+	/* Save the current value of RR0 */
+	info->read_reg_zero = read_zsreg(info->zs_channel, 0);
+
+	zs_soft[co->index].clk_divisor = 16;
+	zs_soft[co->index].zs_baud = get_zsbaud(&zs_soft[co->index]);
+
+	restore_flags(flags);
+#endif
+	return 0;
+}
+
+static struct console sercons = {
+	"ttyS",
+	serial_console_write,
+	NULL,
+	serial_console_device,
+	serial_console_wait_key,
+	NULL,
+	serial_console_setup,
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+/*
+ *	Register console.
+ */
+__initfunc (long zs_serial_console_init(long kmem_start, long kmem_end))
+{
+	register_console(&sercons);
+	return kmem_start;
+}
+#endif /* ifdef CONFIG_SERIAL_CONSOLE */
+
+#ifdef CONFIG_KGDB
+/* These are for receiving and sending characters under the kgdb
+ * source level kernel debugger.
+ */
+void putDebugChar(char kgdb_char)
+{
+	struct dec_zschannel *chan = zs_kgdbchan;
+	while ((read_zsreg(chan, 0) & Tx_BUF_EMP) == 0)
+		RECOVERY_DELAY;
+	write_zsdata(chan, kgdb_char);
+}
+char getDebugChar(void)
+{
+	struct dec_zschannel *chan = zs_kgdbchan;
+	while((read_zsreg(chan, 0) & Rx_CH_AV) == 0)
+		eieio(); /*barrier();*/
+	return read_zsdata(chan);
+}
+void kgdb_interruptible(int yes)
+{
+	struct dec_zschannel *chan = zs_kgdbchan;
+	int one, nine;
+	nine = read_zsreg(chan, 9);
+	if (yes == 1) {
+		one = EXT_INT_ENAB|INT_ALL_Rx;
+		nine |= MIE;
+		printk("turning serial ints on\n");
+	} else {
+		one = RxINT_DISAB;
+		nine &= ~MIE;
+		printk("turning serial ints off\n");
+	}
+	write_zsreg(chan, 1, one);
+	write_zsreg(chan, 9, nine);
+}
+/* This sets up the serial port we're using, and turns on
+ * interrupts for that channel, so kgdb is usable once we're done.
+ */
+static inline void kgdb_chaninit(struct dec_zschannel *ms, int intson, int bps)
+{
+	int brg;
+	int i, x;
+	volatile char *sccc = ms->control;
+	brg = BPS_TO_BRG(bps, ZS_CLOCK/16);
+	printk("setting bps on kgdb line to %d [brg=%x]\n", bps, brg);
+	for (i = 20000; i != 0; --i) {
+		x = *sccc; eieio();
+	}
+	for (i = 0; i < sizeof(scc_inittab); ++i) {
+		write_zsreg(ms, scc_inittab[i], scc_inittab[i+1]);
+		i++;
+	}
+}
+/* This is called at boot time to prime the kgdb serial debugging
+ * serial line.  The 'tty_num' argument is 0 for /dev/ttya and 1
+ * for /dev/ttyb which is determined in setup_arch() from the
+ * boot command line flags.
+ */
+__initfunc(void zs_kgdb_hook(int tty_num))
+{
+	/* Find out how many Z8530 SCCs we have */
+	if (zs_chain == 0)
+		probe_sccs();
+	zs_soft[tty_num].zs_channel = &zs_channels[tty_num];
+	zs_kgdbchan = zs_soft[tty_num].zs_channel;
+	zs_soft[tty_num].change_needed = 0;
+	zs_soft[tty_num].clk_divisor = 16;
+	zs_soft[tty_num].zs_baud = 38400;
+	zs_soft[tty_num].kgdb_channel = 1;     /* This runs kgdb */
+	zs_soft[tty_num ^ 1].kgdb_channel = 0; /* This does not */
+	/* Turn on transmitter/receiver at 8-bits/char */
+        kgdb_chaninit(zs_soft[tty_num].zs_channel, 1, 38400);
+	printk("KGDB: on channel %d initialized\n", tty_num);
+	set_debug_traps(); /* init stub */
+}
+#endif /* ifdef CONFIG_KGDB */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/tc/zs.h linux.pre11.3/drivers/tc/zs.h
--- linux.vanilla/drivers/tc/zs.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/tc/zs.h	Mon Jul 19 23:28:26 1999
@@ -0,0 +1,405 @@
+/*
+ * macserial.h: Definitions for the Macintosh Z8530 serial driver.
+ *
+ * Adapted from drivers/sbus/char/sunserial.h by Paul Mackerras.
+ *
+ * Copyright (C) 1996 Paul Mackerras (Paul.Mackerras@cs.anu.edu.au)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _DECSERIAL_H
+#define _DECSERIAL_H
+
+#define NUM_ZSREGS    16
+
+struct serial_struct {
+	int	type;
+	int	line;
+	int	port;
+	int	irq;
+	int	flags;
+	int	xmit_fifo_size;
+	int	custom_divisor;
+	int	baud_base;
+	unsigned short	close_delay;
+	char	reserved_char[2];
+	int	hub6;
+	unsigned short	closing_wait; /* time to wait before closing */
+	unsigned short	closing_wait2; /* no longer used... */
+	int	reserved[4];
+};
+
+/*
+ * For the close wait times, 0 means wait forever for serial port to
+ * flush its output.  65535 means don't wait at all.
+ */
+#define ZILOG_CLOSING_WAIT_INF	0
+#define ZILOG_CLOSING_WAIT_NONE	65535
+
+/*
+ * Definitions for ZILOG_struct (and serial_struct) flags field
+ */
+#define ZILOG_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes 
+				   on the callout port */
+#define ZILOG_FOURPORT  0x0002	/* Set OU1, OUT2 per AST Fourport settings */
+#define ZILOG_SAK	0x0004	/* Secure Attention Key (Orange book) */
+#define ZILOG_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define ZILOG_SPD_MASK	0x0030
+#define ZILOG_SPD_HI	0x0010	/* Use 56000 instead of 38400 bps */
+
+#define ZILOG_SPD_VHI	0x0020  /* Use 115200 instead of 38400 bps */
+#define ZILOG_SPD_CUST	0x0030  /* Use user-specified divisor */
+
+#define ZILOG_SKIP_TEST	0x0040 /* Skip UART test during autoconfiguration */
+#define ZILOG_AUTO_IRQ  0x0080 /* Do automatic IRQ during autoconfiguration */
+#define ZILOG_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define ZILOG_PGRP_LOCKOUT    0x0200 /* Lock out cua opens based on pgrp */
+#define ZILOG_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
+
+#define ZILOG_FLAGS	0x0FFF	/* Possible legal ZILOG flags */
+#define ZILOG_USR_MASK 0x0430	/* Legal flags that non-privileged
+				 * users can set or reset */
+
+/* Internal flags used only by kernel/chr_drv/serial.c */
+#define ZILOG_INITIALIZED	0x80000000 /* Serial port was initialized */
+#define ZILOG_CALLOUT_ACTIVE	0x40000000 /* Call out device is active */
+#define ZILOG_NORMAL_ACTIVE	0x20000000 /* Normal device is active */
+#define ZILOG_BOOT_AUTOCONF	0x10000000 /* Autoconfigure port on bootup */
+#define ZILOG_CLOSING		0x08000000 /* Serial port is closing */
+#define ZILOG_CTS_FLOW		0x04000000 /* Do CTS flow control */
+#define ZILOG_CHECK_CD		0x02000000 /* i.e., CLOCAL */
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ * 
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct dec_zschannel {
+	volatile unsigned char *control;
+	volatile unsigned char *data;
+
+	/* Current write register values */
+	unsigned char curregs[NUM_ZSREGS];
+};
+
+struct dec_serial {
+	struct dec_serial *zs_next;	/* For IRQ servicing chain */
+	struct dec_zschannel *zs_channel; /* Channel registers */
+	struct dec_zschannel *zs_chan_a;	/* A side registers */
+	unsigned char read_reg_zero;
+
+	char soft_carrier;  /* Use soft carrier on this channel */
+	char break_abort;   /* Is serial console in, so process brk/abrt */
+	char kgdb_channel;  /* Kgdb is running on this channel */
+	char is_cons;       /* Is this our console. */
+	unsigned char tx_active; /* character is being xmitted */
+	unsigned char tx_stopped; /* output is suspended */
+
+	/* We need to know the current clock divisor
+	 * to read the bps rate the chip has currently
+	 * loaded.
+	 */
+	unsigned char clk_divisor;  /* May be 1, 16, 32, or 64 */
+	int zs_baud;
+
+	char change_needed;
+
+	int			magic;
+	int			baud_base;
+	int			port;
+	int			irq;
+	int			flags; 		/* defined in tty.h */
+	int			type; 		/* UART type */
+	struct tty_struct 	*tty;
+	int			read_status_mask;
+	int			ignore_status_mask;
+	int			timeout;
+	int			xmit_fifo_size;
+	int			custom_divisor;
+	int			x_char;	/* xon/xoff character */
+	int			close_delay;
+	unsigned short		closing_wait;
+	unsigned short		closing_wait2;
+	unsigned long		event;
+	unsigned long		last_active;
+	int			line;
+	int			count;	    /* # of fd on device */
+	int			blocked_open; /* # of blocked opens */
+	long			session; /* Session of opening process */
+	long			pgrp; /* pgrp of opening process */
+	unsigned char 		*xmit_buf;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	struct tq_struct	tqueue;
+	struct tq_struct	tqueue_hangup;
+	struct termios		normal_termios;
+	struct termios		callout_termios;
+	struct wait_queue	*open_wait;
+	struct wait_queue	*close_wait;
+};
+
+
+#define SERIAL_MAGIC 0x5301
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP	0
+
+#endif /* __KERNEL__ */
+
+/* Conversion routines to/from brg time constants from/to bits
+ * per second.
+ */
+#define BRG_TO_BPS(brg, freq) ((freq) / 2 / ((brg) + 2))
+#define BPS_TO_BRG(bps, freq) ((((freq) + (bps)) / (2 * (bps))) - 2)
+
+/* The Zilog register set */
+
+#define	FLAG	0x7e
+
+/* Write Register 0 */
+#define	R0	0		/* Register selects */
+#define	R1	1
+#define	R2	2
+#define	R3	3
+#define	R4	4
+#define	R5	5
+#define	R6	6
+#define	R7	7
+#define	R8	8
+#define	R9	9
+#define	R10	10
+#define	R11	11
+#define	R12	12
+#define	R13	13
+#define	R14	14
+#define	R15	15
+
+#define	NULLCODE	0	/* Null Code */
+#define	POINT_HIGH	0x8	/* Select upper half of registers */
+#define	RES_EXT_INT	0x10	/* Reset Ext. Status Interrupts */
+#define	SEND_ABORT	0x18	/* HDLC Abort */
+#define	RES_RxINT_FC	0x20	/* Reset RxINT on First Character */
+#define	RES_Tx_P	0x28	/* Reset TxINT Pending */
+#define	ERR_RES		0x30	/* Error Reset */
+#define	RES_H_IUS	0x38	/* Reset highest IUS */
+
+#define	RES_Rx_CRC	0x40	/* Reset Rx CRC Checker */
+#define	RES_Tx_CRC	0x80	/* Reset Tx CRC Checker */
+#define	RES_EOM_L	0xC0	/* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define	EXT_INT_ENAB	0x1	/* Ext Int Enable */
+#define	TxINT_ENAB	0x2	/* Tx Int Enable */
+#define	PAR_SPEC	0x4	/* Parity is special condition */
+
+#define	RxINT_DISAB	0	/* Rx Int Disable */
+#define	RxINT_FCERR	0x8	/* Rx Int on First Character Only or Error */
+#define	INT_ALL_Rx	0x10	/* Int on all Rx Characters or error */
+#define	INT_ERR_Rx	0x18	/* Int on error only */
+
+#define	WT_RDY_RT	0x20	/* Wait/Ready on R/T */
+#define	WT_FN_RDYFN	0x40	/* Wait/FN/Ready FN */
+#define	WT_RDY_ENAB	0x80	/* Wait/Ready Enable */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define	RxENABLE	0x1	/* Rx Enable */
+#define	SYNC_L_INH	0x2	/* Sync Character Load Inhibit */
+#define	ADD_SM		0x4	/* Address Search Mode (SDLC) */
+#define	RxCRC_ENAB	0x8	/* Rx CRC Enable */
+#define	ENT_HM		0x10	/* Enter Hunt Mode */
+#define	AUTO_ENAB	0x20	/* Auto Enables */
+#define	Rx5		0x0	/* Rx 5 Bits/Character */
+#define	Rx7		0x40	/* Rx 7 Bits/Character */
+#define	Rx6		0x80	/* Rx 6 Bits/Character */
+#define	Rx8		0xc0	/* Rx 8 Bits/Character */
+#define RxNBITS_MASK	0xc0
+
+/* Write Register 4 */
+
+#define	PAR_ENA		0x1	/* Parity Enable */
+#define	PAR_EVEN	0x2	/* Parity Even/Odd* */
+
+#define	SYNC_ENAB	0	/* Sync Modes Enable */
+#define	SB1		0x4	/* 1 stop bit/char */
+#define	SB15		0x8	/* 1.5 stop bits/char */
+#define	SB2		0xc	/* 2 stop bits/char */
+#define SB_MASK		0xc
+
+#define	MONSYNC		0	/* 8 Bit Sync character */
+#define	BISYNC		0x10	/* 16 bit sync character */
+#define	SDLC		0x20	/* SDLC Mode (01111110 Sync Flag) */
+#define	EXTSYNC		0x30	/* External Sync Mode */
+
+#define	X1CLK		0x0	/* x1 clock mode */
+#define	X16CLK		0x40	/* x16 clock mode */
+#define	X32CLK		0x80	/* x32 clock mode */
+#define	X64CLK		0xC0	/* x64 clock mode */
+#define XCLK_MASK	0xC0
+
+/* Write Register 5 */
+
+#define	TxCRC_ENAB	0x1	/* Tx CRC Enable */
+#define	RTS		0x2	/* RTS */
+#define	SDLC_CRC	0x4	/* SDLC/CRC-16 */
+#define	TxENAB		0x8	/* Tx Enable */
+#define	SND_BRK		0x10	/* Send Break */
+#define	Tx5		0x0	/* Tx 5 bits (or less)/character */
+#define	Tx7		0x20	/* Tx 7 bits/character */
+#define	Tx6		0x40	/* Tx 6 bits/character */
+#define	Tx8		0x60	/* Tx 8 bits/character */
+#define TxNBITS_MASK	0x60
+#define	DTR		0x80	/* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define	VIS	1	/* Vector Includes Status */
+#define	NV	2	/* No Vector */
+#define	DLC	4	/* Disable Lower Chain */
+#define	MIE	8	/* Master Interrupt Enable */
+#define	STATHI	0x10	/* Status high */
+#define SOFTACK 0x20    /* Software Interrupt Acknowledge */
+#define	NORESET	0	/* No reset on write to R9 */
+#define	CHRB	0x40	/* Reset channel B */
+#define	CHRA	0x80	/* Reset channel A */
+#define	FHWRES	0xc0	/* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define	BIT6	1	/* 6 bit/8bit sync */
+#define	LOOPMODE 2	/* SDLC Loop mode */
+#define	ABUNDER	4	/* Abort/flag on SDLC xmit underrun */
+#define	MARKIDLE 8	/* Mark/flag on idle */
+#define	GAOP	0x10	/* Go active on poll */
+#define	NRZ	0	/* NRZ mode */
+#define	NRZI	0x20	/* NRZI mode */
+#define	FM1	0x40	/* FM1 (transition = 1) */
+#define	FM0	0x60	/* FM0 (transition = 0) */
+#define	CRCPS	0x80	/* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define	TRxCXT	0	/* TRxC = Xtal output */
+#define	TRxCTC	1	/* TRxC = Transmit clock */
+#define	TRxCBR	2	/* TRxC = BR Generator Output */
+#define	TRxCDP	3	/* TRxC = DPLL output */
+#define	TRxCOI	4	/* TRxC O/I */
+#define	TCRTxCP	0	/* Transmit clock = RTxC pin */
+#define	TCTRxCP	8	/* Transmit clock = TRxC pin */
+#define	TCBR	0x10	/* Transmit clock = BR Generator output */
+#define	TCDPLL	0x18	/* Transmit clock = DPLL output */
+#define	RCRTxCP	0	/* Receive clock = RTxC pin */
+#define	RCTRxCP	0x20	/* Receive clock = TRxC pin */
+#define	RCBR	0x40	/* Receive clock = BR Generator output */
+#define	RCDPLL	0x60	/* Receive clock = DPLL output */
+#define	RTxCX	0x80	/* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define	BRENABL	1	/* Baud rate generator enable */
+#define	BRSRC	2	/* Baud rate generator source */
+#define	DTRREQ	4	/* DTR/Request function */
+#define	AUTOECHO 8	/* Auto Echo */
+#define	LOOPBAK	0x10	/* Local loopback */
+#define	SEARCH	0x20	/* Enter search mode */
+#define	RMC	0x40	/* Reset missing clock */
+#define	DISDPLL	0x60	/* Disable DPLL */
+#define	SSBR	0x80	/* Set DPLL source = BR generator */
+#define	SSRTxC	0xa0	/* Set DPLL source = RTxC */
+#define	SFMM	0xc0	/* Set FM mode */
+#define	SNRZI	0xe0	/* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define	ZCIE	2	/* Zero count IE */
+#define	DCDIE	8	/* DCD IE */
+#define	SYNCIE	0x10	/* Sync/hunt IE */
+#define	CTSIE	0x20	/* CTS IE */
+#define	TxUIE	0x40	/* Tx Underrun/EOM IE */
+#define	BRKIE	0x80	/* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define	Rx_CH_AV	0x1	/* Rx Character Available */
+#define	ZCOUNT		0x2	/* Zero count */
+#define	Tx_BUF_EMP	0x4	/* Tx Buffer empty */
+#define	DCD		0x8	/* DCD */
+#define	SYNC_HUNT	0x10	/* Sync/hunt */
+#define	CTS		0x20	/* CTS */
+#define	TxEOM		0x40	/* Tx underrun */
+#define	BRK_ABRT	0x80	/* Break/Abort */
+
+/* Read Register 1 */
+#define	ALL_SNT		0x1	/* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define	RES3		0x8	/* 0/3 */
+#define	RES4		0x4	/* 0/4 */
+#define	RES5		0xc	/* 0/5 */
+#define	RES6		0x2	/* 0/6 */
+#define	RES7		0xa	/* 0/7 */
+#define	RES8		0x6	/* 0/8 */
+#define	RES18		0xe	/* 1/8 */
+#define	RES28		0x0	/* 2/8 */
+/* Special Rx Condition Interrupts */
+#define	PAR_ERR		0x10	/* Parity error */
+#define	Rx_OVR		0x20	/* Rx Overrun Error */
+#define	FRM_ERR		0x40	/* CRC/Framing Error */
+#define	END_FR		0x80	/* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define	CHBEXT	0x1		/* Channel B Ext/Stat IP */
+#define	CHBTxIP	0x2		/* Channel B Tx IP */
+#define	CHBRxIP	0x4		/* Channel B Rx IP */
+#define	CHAEXT	0x8		/* Channel A Ext/Stat IP */
+#define	CHATxIP	0x10		/* Channel A Tx IP */
+#define	CHARxIP	0x20		/* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10  (misc status bits) */
+#define	ONLOOP	2		/* On loop */
+#define	LOOPSEND 0x10		/* Loop sending */
+#define	CLK2MIS	0x40		/* Two clocks missing */
+#define	CLK1MIS	0x80		/* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
+
+/* Misc macros */
+#define ZS_CLEARERR(channel)    (write_zsreg(channel, 0, ERR_RES))
+#define ZS_CLEARFIFO(channel)   do { volatile unsigned char garbage; \
+				     garbage = read_zsdata(channel); \
+				     garbage = read_zsdata(channel); \
+				     garbage = read_zsdata(channel); \
+				} while(0)
+
+#endif /* !(_DECSERIAL_H) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/Config.in linux.pre11.3/drivers/video/Config.in
--- linux.vanilla/drivers/video/Config.in	Fri May 28 00:32:59 1999
+++ linux.pre11.3/drivers/video/Config.in	Mon Jul 19 23:28:19 1999
@@ -74,6 +74,7 @@
   fi
   if [ "$ARCH" = "i386" ]; then
     bool 'VESA VGA graphics console' CONFIG_FB_VESA
+    bool 'VGA 16-color graphics console' CONFIG_FB_VGA16
     define_bool CONFIG_VIDEO_SELECT y
   fi
   if [ "$CONFIG_VISWS" = "y" ]; then
@@ -141,6 +142,7 @@
     tristate 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8
 #   tristate 'Atari interleaved bitplanes (16 planes) support' CONFIG_FBCON_IPLAN2P16
     tristate 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC
+    bool 'VGA 16-color planar support' CONFIG_FBCON_VGA_PLANES
     tristate 'VGA characters/attributes support' CONFIG_FBCON_VGA
   else
     # Guess what we need
@@ -282,6 +284,9 @@
       if [ "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then
 	define_bool CONFIG_FBCON_MAC  m
       fi
+    fi
+    if [ "$CONFIG_FB_VGA16" = "y" ]; then
+      define_bool CONFIG_FBCON_VGA_PLANES y
     fi
     if [ "$CONFIG_FB_MDA" = "y" -o "$CONFIG_FB_VGA" = "y" ]; then
       define_bool CONFIG_FBCON_VGA y
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/Makefile linux.pre11.3/drivers/video/Makefile
--- linux.vanilla/drivers/video/Makefile	Fri May 28 00:32:59 1999
+++ linux.pre11.3/drivers/video/Makefile	Tue Jul 20 00:05:06 1999
@@ -192,9 +192,11 @@
 
 ifeq ($(CONFIG_FB_TGA),y)
 L_OBJS += tgafb.o
+CONFIG_FBGEN_BUILTIN = y
 else
   ifeq ($(CONFIG_FB_TGA),m)
   M_OBJS += tgafb.o
+  CONFIG_FBGEN_MODULE = y
   endif
 endif
 
@@ -202,6 +204,10 @@
 L_OBJS += vesafb.o
 endif
 
+ifeq ($(CONFIG_FB_VGA16),y)
+L_OBJS += vga16fb.o
+endif
+
 ifeq ($(CONFIG_FB_VIRGE),y)
 L_OBJS += virgefb.o
 else
@@ -462,6 +468,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_FBCON_VGA_PLANES),y)
+OX_OBJS += fbcon-vga-planes.o
+else
+  ifeq ($(CONFIG_FBCON_VGA_PLANES),m)
+  MX_OBJS += fbcon-vga-planes.o
+  endif
+endif
+
 ifeq ($(CONFIG_FBCON_VGA),y)
 OX_OBJS += fbcon-vga.o
 else
@@ -483,6 +497,16 @@
 else
   ifeq ($(CONFIG_MDA_CONSOLE),m)
   M_OBJS += mdacon.o
+  endif
+endif
+
+# Newport Text Console
+
+ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),y)
+L_OBJS += newport_con.o vga_font.o
+else
+  ifeq ($(CONFIG_SGI_NEWPORT_CONSOLE),m)
+  M_OBJS += newport_con.o vga_font.o
   endif
 endif
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/fbcon-vga-planes.c linux.pre11.3/drivers/video/fbcon-vga-planes.c
--- linux.vanilla/drivers/video/fbcon-vga-planes.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/video/fbcon-vga-planes.c	Mon Jul 19 23:28:22 1999
@@ -0,0 +1,364 @@
+/*
+ *  linux/drivers/video/fbcon-vga-planes.c -- Low level frame buffer operations
+ *				  for VGA 4-plane modes
+ *
+ * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Based on code by Michael Schmitz
+ * Based on the old macfb.c 4bpp code by Alan Cox
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.  */
+
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/fb.h>
+#include <linux/vt_buffer.h>
+
+#include <asm/io.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-vga-planes.h>
+
+#define GRAPHICS_ADDR_REG 0x3ce		/* Graphics address register. */
+#define GRAPHICS_DATA_REG 0x3cf		/* Graphics data register. */
+
+#define SET_RESET_INDEX 0		/* Set/Reset Register index. */
+#define ENABLE_SET_RESET_INDEX 1	/* Enable Set/Reset Register index. */
+#define DATA_ROTATE_INDEX 3		/* Data Rotate Register index. */
+#define GRAPHICS_MODE_INDEX 5		/* Graphics Mode Register index. */
+#define BIT_MASK_INDEX 8		/* Bit Mask Register index. */
+
+/* The VGA's weird architecture often requires that we read a byte and
+   write a byte to the same location.  It doesn't matter *what* byte
+   we write, however.  This is because all the action goes on behind
+   the scenes in the VGA's 32-bit latch register, and reading and writing
+   video memory just invokes latch behavior.
+
+   To avoid race conditions (is this necessary?), reading and writing
+   the memory byte should be done with a single instruction.  One
+   suitable instruction is the x86 bitwise OR.  The following
+   read-modify-write routine should optimize to one such bitwise
+   OR. */
+static inline void rmw(volatile char *p)
+{
+	*p |= 1;
+}
+
+/* Set the Graphics Mode Register.  Bits 0-1 are write mode, bit 3 is
+   read mode. */
+static inline void setmode(int mode)
+{
+	outb(GRAPHICS_MODE_INDEX, GRAPHICS_ADDR_REG);
+	outb(mode, GRAPHICS_DATA_REG);
+}
+
+/* Select the Bit Mask Register. */
+static inline void selectmask(void)
+{
+	outb(BIT_MASK_INDEX, GRAPHICS_ADDR_REG);
+}
+
+/* Set the value of the Bit Mask Register.  It must already have been
+   selected with selectmask(). */
+static inline void setmask(int mask)
+{
+	outb(mask, GRAPHICS_DATA_REG);
+}
+
+/* Set the Data Rotate Register.  Bits 0-2 are rotate count, bits 3-4
+   are logical operation (0=NOP, 1=AND, 2=OR, 3=XOR). */
+static inline void setop(int op)
+{
+	outb(DATA_ROTATE_INDEX, GRAPHICS_ADDR_REG);
+	outb(op, GRAPHICS_DATA_REG);
+}
+
+/* Set the Enable Set/Reset Register.  The code here always uses value
+   0xf for this register.  */
+static inline void setsr(int sr)
+{
+	outb(ENABLE_SET_RESET_INDEX, GRAPHICS_ADDR_REG);
+	outb(sr, GRAPHICS_DATA_REG);
+}
+
+/* Set the Set/Reset Register. */
+static inline void setcolor(int color)
+{
+	outb(SET_RESET_INDEX, GRAPHICS_ADDR_REG);
+	outb(color, GRAPHICS_DATA_REG);
+}
+
+/* Set the value in the Graphics Address Register. */
+static inline void setindex(int index)
+{
+	outb(index, GRAPHICS_ADDR_REG);
+}
+
+void fbcon_vga_planes_setup(struct display *p)
+{
+}
+
+void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx,
+		   int height, int width)
+{
+	char *src;
+	char *dest;
+	int line_ofs;
+	int x;
+
+	setmode(1);
+	setop(0);
+	setsr(0xf);
+
+	sy *= fontheight(p);
+	dy *= fontheight(p);
+	height *= fontheight(p);
+
+	if (dy < sy || (dy == sy && dx < sx)) {
+		line_ofs = p->line_length - width;
+		dest = p->screen_base + dx + dy * p->line_length;
+		src = p->screen_base + sx + sy * p->line_length;
+		while (height--) {
+			for (x = 0; x < width; x++) 
+				*dest++ = *src++;
+			src += line_ofs;
+			dest += line_ofs;
+		}
+	} else {
+		line_ofs = p->line_length - width;
+		dest = p->screen_base + dx + width + (dy + height - 1) * p->line_length;
+		src = p->screen_base + sx + width + (sy + height - 1) * p->line_length;
+		while (height--) {
+			for (x = 0; x < width; x++)
+				*--dest = *--src;
+			src -= line_ofs;
+			dest -= line_ofs;
+		}
+	}
+}
+
+void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+		   int height, int width)
+{
+	int line_ofs = p->line_length - width;
+	char *where;
+	int x;
+	
+	setmode(0);
+	setop(0);
+	setsr(0xf);
+	setcolor(attr_bgcol_ec(p, conp));
+	selectmask();
+
+	setmask(0xff);
+
+	sy *= fontheight(p);
+	height *= fontheight(p);
+
+	where = p->screen_base + sx + sy * p->line_length;
+	while (height--) {
+		for (x = 0; x < width; x++)
+			*where++ = 0;
+		where += line_ofs;
+	}
+}
+
+void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+	int fg = attr_fgcol(p,c);
+	int bg = attr_bgcol(p,c);
+
+	int y;
+	u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+
+	setmode(0);
+	setop(0);
+	setsr(0xf);
+	setcolor(bg);
+	selectmask();
+
+	setmask(0xff);
+	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
+		rmw(where);
+
+	where -= p->line_length * y;
+	setcolor(fg);
+	selectmask();
+	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
+		if (cdat[y]) {
+			setmask(cdat[y]);
+			rmw(where);
+		}
+}
+
+void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+	int fg = attr_fgcol(p,c);
+	int bg = attr_bgcol(p,c);
+
+	int y;
+	u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+
+	setmode(2);
+	setop(0);
+	setsr(0xf);
+	setcolor(fg);
+	selectmask();
+
+	setmask(0xff);
+	*where = bg;
+	rmb();
+	*(volatile char*)where; /* fill latches */
+	setmode(3);
+	wmb();
+	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
+		*where = cdat[y];
+	wmb();
+}
+
+/* 28.50 in my test */
+void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
+		   int count, int yy, int xx)
+{
+	int fg = attr_fgcol(p,scr_readw(s));
+	int bg = attr_bgcol(p,scr_readw(s));
+
+	char *where;
+	int n;
+
+	setmode(2);
+	setop(0);
+	selectmask();
+
+	setmask(0xff);
+	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+	*where = bg;
+	rmb();
+	*(volatile char*)where;
+	wmb();
+	selectmask();
+	for (n = 0; n < count; n++) {
+		int c = scr_readw(s++) & p->charmask;
+		u8 *cdat = p->fontdata + c * fontheight(p);
+		u8 *end = cdat + fontheight(p);
+
+		while (cdat < end) {
+			outb(*cdat++, GRAPHICS_DATA_REG);	
+			wmb();
+			*where = fg;
+			where += p->line_length;
+		}
+		where += 1 - p->line_length * fontheight(p);
+	}
+	
+	wmb();
+}
+
+/* 6.96 in my test */
+void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
+		   int count, int yy, int xx)
+{
+	int fg = attr_fgcol(p,*s);
+	int bg = attr_bgcol(p,*s);
+
+	char *where;
+	int n;
+
+	setmode(2);
+	setop(0);
+	setsr(0xf);
+	setcolor(fg);
+	selectmask();
+
+	setmask(0xff);
+	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+	*where = bg;
+	rmb();
+	*(volatile char*)where; /* fill latches with background */
+	setmode(3);	
+	wmb();
+	for (n = 0; n < count; n++) {
+		int y;
+		int c = *s++ & p->charmask;
+		u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+
+		for (y = 0; y < fontheight(p); y++, cdat++) {
+			*where = *cdat;
+			where += p->line_length;
+		}
+		where += 1 - p->line_length * fontheight(p);
+	}
+	
+	wmb();
+}
+
+void fbcon_vga_planes_revc(struct display *p, int xx, int yy)
+{
+	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);
+	int y;
+	
+	setmode(0);
+	setop(0x18);
+	setsr(0xf);
+	setcolor(0xf);
+	selectmask();
+
+	setmask(0xff);
+	for (y = 0; y < fontheight(p); y++) {
+		rmw(where);
+		where += p->line_length;
+	}
+}
+
+struct display_switch fbcon_vga_planes = {
+    fbcon_vga_planes_setup, fbcon_vga_planes_bmove, fbcon_vga_planes_clear,
+    fbcon_vga_planes_putc, fbcon_vga_planes_putcs, fbcon_vga_planes_revc,
+    NULL, NULL, NULL, FONTWIDTH(8)
+};
+
+struct display_switch fbcon_ega_planes = {
+    fbcon_vga_planes_setup, fbcon_vga_planes_bmove, fbcon_vga_planes_clear,
+    fbcon_ega_planes_putc, fbcon_ega_planes_putcs, fbcon_vga_planes_revc,
+    NULL, NULL, NULL, FONTWIDTH(8)
+};
+
+#ifdef MODULE
+int init_module(void)
+{
+    return 0;
+}
+
+void cleanup_module(void)
+{}
+#endif /* MODULE */
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(fbcon_vga_planes);
+EXPORT_SYMBOL(fbcon_vga_planes_setup);
+EXPORT_SYMBOL(fbcon_vga_planes_bmove);
+EXPORT_SYMBOL(fbcon_vga_planes_clear);
+EXPORT_SYMBOL(fbcon_vga_planes_putc);
+EXPORT_SYMBOL(fbcon_vga_planes_putcs);
+EXPORT_SYMBOL(fbcon_vga_planes_revc);
+
+EXPORT_SYMBOL(fbcon_ega_planes);
+EXPORT_SYMBOL(fbcon_ega_planes_putc);
+EXPORT_SYMBOL(fbcon_ega_planes_putcs);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/fbcon.c linux.pre11.3/drivers/video/fbcon.c
--- linux.vanilla/drivers/video/fbcon.c	Tue Jun 15 16:49:52 1999
+++ linux.pre11.3/drivers/video/fbcon.c	Mon Jul 19 23:28:19 1999
@@ -91,6 +91,9 @@
 #include <asm/machdep.h>
 #include <asm/setup.h>
 #endif
+#ifdef CONFIG_FBCON_VGA_PLANES
+#include <asm/io.h>
+#endif
 #define INCLUDE_LINUX_LOGO_DATA
 #include <asm/linux_logo.h>
 
@@ -2237,6 +2240,35 @@
 	    done = 1;
 	}
 #endif
+#if defined(CONFIG_FBCON_VGA_PLANES)
+	if (depth == 4 && p->type == FB_TYPE_VGA_PLANES) {
+		outb_p(1,0x3ce); outb_p(0xf,0x3cf);
+		outb_p(3,0x3ce); outb_p(0,0x3cf);
+		outb_p(5,0x3ce); outb_p(0,0x3cf);
+
+		src = logo;
+		for (y1 = 0; y1 < LOGO_H; y1++) {
+			for (x1 = 0; x1 < LOGO_W / 2; x1++) {
+				dst = fb + y1*line + x1/4 + x/8;
+
+				outb_p(0,0x3ce);
+				outb_p(*src >> 4,0x3cf);
+				outb_p(8,0x3ce);
+				outb_p(1 << (7 - x1 % 4 * 2),0x3cf);
+				*(volatile char *) dst |= 1;
+
+				outb_p(0,0x3ce);
+				outb_p(*src & 0xf,0x3cf);
+				outb_p(8,0x3ce);
+				outb_p(1 << (7 - (1 + x1 % 4 * 2)),0x3cf);
+				*(volatile char *) dst |= 1;
+
+				src++;
+			}
+		}
+		done = 1;
+	}
+#endif			
     }
     
     if (p->fb_info->fbops->fb_rasterimg)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/fbmem.c linux.pre11.3/drivers/video/fbmem.c
--- linux.vanilla/drivers/video/fbmem.c	Fri May 28 00:32:59 1999
+++ linux.pre11.3/drivers/video/fbmem.c	Tue Jul 20 00:05:18 1999
@@ -74,6 +74,7 @@
 extern void imsttfb_setup(char *options, int *ints);
 extern void dnfb_init(void);
 extern void tgafb_init(void);
+extern void tgafb_setup(char *options, int *ints);
 extern void virgefb_init(void);
 extern void virgefb_setup(char *options, int *ints);
 extern void resolver_video_setup(char *options, int *ints);
@@ -81,6 +82,8 @@
 extern void s3triofb_setup(char *options, int *ints);
 extern void vesafb_init(void);
 extern void vesafb_setup(char *options, int *ints);
+extern void vga16fb_init(void);
+extern void vga16fb_setup(char *options, int *ints);
 extern void matroxfb_init(void);
 extern void matroxfb_setup(char* options, int *ints);
 extern void hpfb_init(void);
@@ -156,13 +159,16 @@
 	{ "s3trio", s3triofb_init, s3triofb_setup },
 #endif 
 #ifdef CONFIG_FB_TGA
-	{ "tga", tgafb_init, NULL },
+	{ "tga", tgafb_init, tgafb_setup },
 #endif
 #ifdef CONFIG_FB_VIRGE
 	{ "virge", virgefb_init, virgefb_setup },
 #endif
 #ifdef CONFIG_FB_VESA
 	{ "vesa", vesafb_init, vesafb_setup },
+#endif 
+#ifdef CONFIG_FB_VGA16
+	{ "vga16", vga16fb_init, vga16fb_setup },
 #endif 
 #ifdef CONFIG_FB_MATROX
 	{ "matrox", matroxfb_init, matroxfb_setup },
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/g364fb.c linux.pre11.3/drivers/video/g364fb.c
--- linux.vanilla/drivers/video/g364fb.c	Sun Nov  8 15:08:13 1998
+++ linux.pre11.3/drivers/video/g364fb.c	Mon Jul 19 23:28:20 1999
@@ -1,4 +1,4 @@
-/* $Id: g364fb.c,v 1.3 1998/08/28 22:43:00 tsbogend Exp $
+/* $Id: g364fb.c,v 1.4 1999/02/25 20:39:56 tsbogend Exp $
  *
  * linux/drivers/video/g364fb.c -- Mips Magnum frame buffer device
  *
@@ -144,7 +144,7 @@
      case CM_MOVE:
      case CM_DRAW:
 	*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
-	*(unsigned int *) CURS_POS_REG = ((x * p->fontwidth) << 12) | ((y * p->fontheight)-p->var.yoffset);
+	*(unsigned int *) CURS_POS_REG = ((x * fontwidth(p)) << 12) | ((y * fontheight(p))-p->var.yoffset);
 	break;
     }
 }
@@ -485,7 +485,7 @@
     if (regno > 255)
 	return 1;
 
-    red >> = 8;
+    red >>= 8;
     green >>= 8;
     blue >>=8;
     palette[regno].red = red;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/newport_con.c linux.pre11.3/drivers/video/newport_con.c
--- linux.vanilla/drivers/video/newport_con.c	Wed Mar 10 21:13:08 1999
+++ linux.pre11.3/drivers/video/newport_con.c	Mon Jul 19 23:28:21 1999
@@ -1,8 +1,9 @@
-/* $Id: newport_con.c,v 1.3 1998/09/01 21:43:18 tsbogend Exp $
+/* $Id: newport_con.c,v 1.13 1999/04/11 10:37:08 ulfc Exp $
  *
  * newport_con.c: Abscon for newport hardware
  * 
  * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
  * 
  * This driver is based on sgicons.c and cons_newport.
  * 
@@ -19,19 +20,27 @@
 #include <linux/console_struct.h>
 #include <linux/vt_kern.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/newport.h>
+#define INCLUDE_LINUX_LOGO_DATA
+#include <asm/linux_logo.h>
 
-struct newport_regs *npregs;
-int newport_num_lines;
-int newport_num_columns;
-int topscan;
+#define LOGO_W		80
+#define LOGO_H		80
 
 extern unsigned char vga_font[];
+extern struct newport_regs *npregs;
+
+static int logo_active;
+static int topscan;
+static int xcurs_correction = 29;
+static int newport_xsize;
+static int newport_ysize;
 
 #define BMASK(c) (c << 24)
 
@@ -49,7 +58,8 @@
 #define TESTVAL 0xdeadbeef
 #define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11)
 
-static inline void newport_render_background(int xpos, int ypos, int ci)
+static inline void newport_render_background(int xstart, int ystart,
+					     int xend, int yend, int ci)
 {
     newport_wait();
     npregs->set.wrmask = 0xffffffff;
@@ -57,8 +67,8 @@
 			     NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
 			     NPORT_DMODE0_STOPY);
     npregs->set.colori = ci;
-    npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff);
-    npregs->go.xyendi = ((xpos + 7) << 16) | ((ypos + topscan + 15) & 0x3ff);
+    npregs->set.xystarti = (xstart << 16) | ((ystart + topscan) & 0x3ff);
+    npregs->go.xyendi = ((xend + 7) << 16) | ((yend + topscan + 15) & 0x3ff);
 }
 
 static inline void newport_init_cmap(void)
@@ -75,23 +85,51 @@
     }
 }
 
-static inline void newport_clear_screen(int xstart, int ystart, int xend, int yend)
+static inline void newport_show_logo(void)
 {
+    unsigned long i;
+
+    for(i = 0; i < LINUX_LOGO_COLORS; i++) {
+	newport_bfwait();
+	newport_cmap_setaddr(npregs, i + 0x20);
+	newport_cmap_setrgb(npregs,
+			    linux_logo_red[i],
+			    linux_logo_green[i],
+			    linux_logo_blue[i]);
+    }
+
+    newport_wait();
+    npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_CHOST);
+    
+    npregs->set.xystarti = ((newport_xsize - LOGO_W) << 16) | (0);
+    npregs->set.xyendi = ((newport_xsize - 1) << 16);
+    newport_wait();
+
+    for (i = 0; i < LOGO_W * LOGO_H; i++)
+	npregs->go.hostrw0 = linux_logo[i] << 24;
+}
+
+static inline void newport_clear_screen(int xstart, int ystart, int xend,
+					int yend, int ci) {
+    if (logo_active)
+	return;
+
     newport_wait();
     npregs->set.wrmask = 0xffffffff;
     npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
 			     NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
 			     NPORT_DMODE0_STOPY);
-    npregs->set.colori = 0;
+    npregs->set.colori = ci;
     npregs->set.xystarti = (xstart << 16) | ystart;
     npregs->go.xyendi = (xend << 16) | yend;
 }
 
-static inline void newport_clear_lines(int ystart, int yend)
+static inline void newport_clear_lines(int ystart, int yend, int ci)
 {
     ystart = ((ystart << 4) + topscan) & 0x3ff;
     yend = ((yend << 4) + topscan + 15) & 0x3ff;    
-    newport_clear_screen (0, ystart, 1279, yend);
+    newport_clear_screen (0, ystart, 1280+63, yend, ci);
 }
 
 void newport_reset (void)
@@ -116,13 +154,121 @@
     }
 
     newport_init_cmap();
-    npregs->cset.topscan = topscan = 0;
+
+    /* turn off popup plane */
+    npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
+                           XM9_CRS_CONFIG | NPORT_DMODE_W1);
+    npregs->set.dcbdata0.bytes.b3 &= ~XM9_PUPMODE;
+    npregs->set.dcbmode = (DCB_XMAP1 | R_DCB_XMAP9_PROTOCOL |
+                           XM9_CRS_CONFIG | NPORT_DMODE_W1);
+    npregs->set.dcbdata0.bytes.b3 &= ~XM9_PUPMODE;
+    
+    topscan = 0;
+    npregs->cset.topscan = 0x3ff;
     npregs->cset.xywin = (4096 << 16) | 4096;
+
     /* Clear the screen. */
-    newport_clear_screen(0,0,1280+63,1024);
+    newport_clear_screen(0,0,1280+63,1024,0);
 }
 
+/*
+ * calculate the actual screen size by reading
+ * the video timing out of the VC2
+ */
+void newport_get_screensize(void)
+{
+    int i,cols;
+    unsigned short ventry,treg;
+    unsigned short linetable[128]; /* should be enough */
+
+    ventry = newport_vc2_get (npregs, VC2_IREG_VENTRY);
+    newport_vc2_set(npregs, VC2_IREG_RADDR, ventry);
+    npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+			   NPORT_DMODE_W2 | VC2_PROTOCOL);
+    for(i = 0; i < 128; i++) {
+	newport_bfwait();
+	linetable[i] = npregs->set.dcbdata0.hwords.s1;
+    }
+
+    newport_xsize = newport_ysize = 0;
+    for (i = 0; linetable[i+1] && (i < sizeof(linetable)); i+=2) {
+	cols = 0;
+        newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]);
+        npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+			       NPORT_DMODE_W2 | VC2_PROTOCOL);
+	do {
+	    newport_bfwait();
+	    treg = npregs->set.dcbdata0.hwords.s1;
+	    if ((treg & 1) == 0)
+		cols += (treg >> 7) & 0xfe;
+	    if ((treg & 0x80) == 0) {
+		newport_bfwait();
+		treg = npregs->set.dcbdata0.hwords.s1;
+	    } 
+	} while ((treg & 0x8000) == 0);
+	if (cols) {
+	    if (cols > newport_xsize)
+		newport_xsize = cols;
+	    newport_ysize += linetable[i+1];
+	}
+    }
+    printk ("NG1: Screensize %dx%d\n",newport_xsize,newport_ysize);
+}
+
+static void newport_get_revisions(void)
+{
+    unsigned int tmp;
+    unsigned int board_rev;
+    unsigned int rex3_rev;
+    unsigned int vc2_rev;
+    unsigned int cmap_rev;
+    unsigned int xmap9_rev;
+    unsigned int bt445_rev;
+    unsigned int bitplanes;
+
+    rex3_rev = npregs->cset.stat & NPORT_STAT_VERS;
+
+    npregs->set.dcbmode = (DCB_CMAP0 | NCMAP_PROTOCOL |
+                           NCMAP_REGADDR_RREG | NPORT_DMODE_W1);
+    tmp = npregs->set.dcbdata0.bytes.b3;
+    cmap_rev = tmp & 7;
+    board_rev = (tmp >> 4) & 7;
+    bitplanes = ((board_rev > 1) && (tmp & 0x80)) ? 8 : 24; 
+
+    npregs->set.dcbmode = (DCB_CMAP1 | NCMAP_PROTOCOL |
+                           NCMAP_REGADDR_RREG | NPORT_DMODE_W1);
+    tmp = npregs->set.dcbdata0.bytes.b3;
+    if ((tmp & 7) < cmap_rev)
+	cmap_rev = (tmp & 7);
+
+    vc2_rev = (newport_vc2_get(npregs, VC2_IREG_CONFIG) >> 5) & 7;
+
+    npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
+                           XM9_CRS_REVISION | NPORT_DMODE_W1);
+    xmap9_rev = npregs->set.dcbdata0.bytes.b3 & 7;
+
+    npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL |
+                           BT445_CSR_ADDR_REG | NPORT_DMODE_W1);
+    npregs->set.dcbdata0.bytes.b3 = BT445_REVISION_REG;
+    npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL |
+                           BT445_CSR_REVISION | NPORT_DMODE_W1);
+    bt445_rev = (npregs->set.dcbdata0.bytes.b3 >> 4) - 0x0a;
+
+#define L(a)     (char)('A'+(a))
+    printk ("NG1: Revision %d, %d bitplanes, REX3 revision %c, VC2 revision %c, xmap9 revision %c, cmap revision %c, bt445 revision %c\n",
+	    board_rev,bitplanes,L(rex3_rev),L(vc2_rev), L(xmap9_rev),
+	    L(cmap_rev ? (cmap_rev+1):0),L(bt445_rev));
+#undef L
+
+    if (board_rev == 3) /* I don't know all affected revisions */
+	xcurs_correction = 21;
+}
+
+#ifdef MODULE
+static const char *newport_startup(void)
+#else
 __initfunc(static const char *newport_startup(void))
+#endif
 {
     struct newport_regs *p;
 
@@ -140,18 +286,18 @@
     }
 
     newport_reset ();
+    newport_get_revisions();
+    newport_get_screensize();
 
     // gfx_init (display_desc);
-    newport_num_lines = ORIG_VIDEO_LINES;
-    newport_num_columns = ORIG_VIDEO_COLS;
     
     return "SGI Newport";
 }
 
 static void newport_init(struct vc_data *vc, int init)
 {
-    vc->vc_cols = newport_num_columns;
-    vc->vc_rows = newport_num_lines;
+    vc->vc_cols = newport_xsize / 8;
+    vc->vc_rows = newport_ysize / 16;
     vc->vc_can_do_color = 1;
 }
 
@@ -160,12 +306,18 @@
     int xend = ((sx + width) << 3) - 1;
     int ystart = ((sy << 4) + topscan) & 0x3ff;
     int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff;
+
+    if (logo_active)
+	return;
     
     if (ystart < yend) {
-	newport_clear_screen(sx << 3, ystart, xend, yend);
+	newport_clear_screen(sx << 3, ystart, xend, yend,
+			     (vc->vc_color & 0xf0) >> 4);
     } else {
-	newport_clear_screen(sx << 3, ystart, xend, 1023);
-	newport_clear_screen(sx << 3, 0, xend, yend);
+	newport_clear_screen(sx << 3, ystart, xend, 1023,
+			     (vc->vc_color & 0xf0) >> 4);
+	newport_clear_screen(sx << 3, 0, xend, yend,
+			     (vc->vc_color & 0xf0) >> 4);
     }
 }
 
@@ -178,7 +330,7 @@
     xpos <<= 3;
     ypos <<= 4;
 
-    newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4);
+    newport_render_background(xpos, ypos, xpos, ypos, (charattr & 0xf0) >> 4);
     
     /* Set the color and drawing mode. */
     newport_wait();
@@ -196,11 +348,43 @@
     RENDER(npregs, p);
 }
 
-static void newport_putcs(struct vc_data *vc, const unsigned short *s, int count,
-			  int ypos, int xpos)
+static void newport_putcs(struct vc_data *vc, const unsigned short *s,
+			  int count, int ypos, int xpos)
 {
-    while (count--)
-	newport_putc (vc, scr_readw(s++), ypos, xpos++);
+    int i;
+    int charattr;
+    unsigned char *p; 
+
+    charattr = (*s >> 8) & 0xff;
+
+    xpos <<= 3;
+    ypos <<= 4;
+
+    if (!logo_active)
+	/* Clear the area behing the string */
+	newport_render_background(xpos, ypos, xpos + ((count-1) << 3), ypos,
+				  (charattr & 0xf0) >> 4);
+
+    newport_wait();
+
+    /* Set the color and drawing mode. */
+    npregs->set.colori = charattr & 0xf;
+    npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+			     NPORT_DMODE0_L32);
+    
+    for (i = 0; i < count; i++, xpos += 8) {
+	p = &vga_font[(s[i] & 0xff) << 4];
+
+	newport_wait();
+
+	/* Set coordinates for bitmap operation. */
+	npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff);
+	npregs->set.xyendi = ((xpos + 7) << 16);
+
+	/* Go, baby, go... */
+	RENDER(npregs, p);
+    }
 }
 
 static void newport_cursor(struct vc_data *vc, int mode)
@@ -220,7 +404,7 @@
 	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
 	xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2;
 	ycurs = ((xcurs / vc->vc_cols) << 4) + 31;
-	xcurs = ((xcurs % vc->vc_cols) << 3) + 21;
+	xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction;
 	newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs);
 	newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs);
     }
@@ -228,7 +412,17 @@
 
 static int newport_switch(struct vc_data *vc)
 {
-    npregs->cset.topscan = topscan = 0;
+    static int logo_drawn = 0;
+
+    topscan = 0;
+    npregs->cset.topscan = 0x3ff;
+
+    if (!logo_drawn) {
+	newport_show_logo();
+	logo_drawn = 1;
+	logo_active = 1;
+    }
+
     return 1;
 }
 
@@ -270,14 +464,18 @@
     unsigned short *s, *d;
     unsigned short chattr;
 
+    logo_active = 0;	/* it's time to disable the logo now.. */
+
     if (t == 0 && b == vc->vc_rows) {
 	if (dir == SM_UP) {
-	    npregs->cset.topscan = topscan = (topscan + (lines << 4)) & 0x3ff;
-	    newport_clear_lines (vc->vc_rows-lines,vc->vc_rows-1);		
+	    topscan = (topscan + (lines << 4)) & 0x3ff;
+	    newport_clear_lines (vc->vc_rows-lines,vc->vc_rows-1,
+				 (vc->vc_color & 0xf0) >> 4);
 	} else {
-	    npregs->cset.topscan = topscan = (topscan + (-lines << 4)) & 0x3ff;
-	    newport_clear_lines (0,lines-1);
+	    topscan = (topscan + (-lines << 4)) & 0x3ff;
+	    newport_clear_lines (0,lines-1, (vc->vc_color & 0xf0) >> 4);
 	}
+	npregs->cset.topscan = (topscan - 1) & 0x3ff;
 	return 0;
     }
     
@@ -392,3 +590,23 @@
     NULL, /* newport_build_attr */
     NULL  /* newport_invert_region */
 };
+
+#ifdef MODULE
+
+int init_module(void) {
+    if (!newport_startup()) 
+       printk("Error loading SGI Newport Console driver\n");
+    else 
+       printk("Loading SGI Newport Console Driver\n");
+
+    take_over_console(&newport_con,0,MAX_NR_CONSOLES-1,1);
+
+    return 0;
+}
+
+int cleanup_module(void) {
+    printk("Unloading SGI Newport Console Driver\n");
+    return 0;
+}
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/sbusfb.c linux.pre11.3/drivers/video/sbusfb.c
--- linux.vanilla/drivers/video/sbusfb.c	Wed Apr 28 19:14:30 1999
+++ linux.pre11.3/drivers/video/sbusfb.c	Mon Jul 19 23:28:20 1999
@@ -364,9 +364,29 @@
      */
 
 static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
+			  struct fb_info *info)
 {
-	return -EINVAL;
+       struct display *display;
+       int activate = var->activate;
+
+       if(con >= 0)
+               display = &fb_display[con];
+       else
+               display = info->disp;
+
+       /* simple check for equality until fully implemented -E */
+       if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+               if (display->var.xres != var->xres ||
+                       display->var.yres != var->yres ||
+                       display->var.xres_virtual != var->xres_virtual ||
+                       display->var.yres_virtual != var->yres_virtual ||
+                       display->var.bits_per_pixel != var->bits_per_pixel ||
+                       display->var.accel_flags != var->accel_flags) {
+                       return -EINVAL;
+               }
+       }
+       return 0;
+
 }
 
     /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/tgafb.c linux.pre11.3/drivers/video/tgafb.c
--- linux.vanilla/drivers/video/tgafb.c	Tue Dec 22 23:19:59 1998
+++ linux.pre11.3/drivers/video/tgafb.c	Tue Jul 20 00:05:18 1999
@@ -1,27 +1,29 @@
 /*
  *  linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
  *
- *	Copyright (C) 1997 Geert Uytterhoeven
+ *	Copyright (C) 1999 Martin Lucina, Tom Zerucha
+ *  
+ *  $Id: tgafb.c,v 1.12 1999/07/01 13:39:23 mato Exp $
  *
- *  This driver is partly based on the original TGA console driver
+ *  This driver is partly based on the original TGA framebuffer device, which 
+ *  was partly based on the original TGA console driver, which are
  *
- *	Copyright (C) 1995  Jay Estabrook
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *	Copyright (C) 1995 Jay Estabrook
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive for
  *  more details.
  */
 
-
 /* KNOWN PROBLEMS/TO DO ===================================================== *
  *
  *	- How to set a single color register on 24-plane cards?
  *
- *	- Hardware cursor (useful for other graphics boards too)
- *
- *	- Support for more resolutions
+ *	- Hardware cursor/other text acceleration methods
  *
  *	- Some redraws can stall kernel for several seconds
+ *	  [This should now be solved by the fast memmove() patch in 2.3.6]
  *
  * KNOWN PROBLEMS/TO DO ==================================================== */
 
@@ -45,477 +47,459 @@
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb32.h>
+#include "tgafb.h"
 
 
-/* TGA hardware description (minimal) */
-/*
- * Offsets within Memory Space
- */
-#define	TGA_ROM_OFFSET			0x0000000
-#define	TGA_REGS_OFFSET			0x0100000
-#define	TGA_8PLANE_FB_OFFSET		0x0200000
-#define	TGA_24PLANE_FB_OFFSET		0x0804000
-#define	TGA_24PLUSZ_FB_OFFSET		0x1004000
-
-#define	TGA_PLANEMASK_REG		0x0028
-#define	TGA_MODE_REG			0x0030
-#define	TGA_RASTEROP_REG		0x0034
-#define	TGA_DEEP_REG			0x0050
-#define	TGA_PIXELMASK_REG		0x005c
-#define	TGA_CURSOR_BASE_REG		0x0060
-#define	TGA_HORIZ_REG			0x0064
-#define	TGA_VERT_REG			0x0068
-#define	TGA_BASE_ADDR_REG		0x006c
-#define	TGA_VALID_REG			0x0070
-#define	TGA_CURSOR_XY_REG		0x0074
-#define	TGA_INTR_STAT_REG		0x007c
-#define	TGA_RAMDAC_SETUP_REG		0x00c0
-#define	TGA_BLOCK_COLOR0_REG		0x0140
-#define	TGA_BLOCK_COLOR1_REG		0x0144
-#define	TGA_CLOCK_REG			0x01e8
-#define	TGA_RAMDAC_REG			0x01f0
-#define	TGA_CMD_STAT_REG		0x01f8
-
-/*
- * useful defines for managing the BT485 on the 8-plane TGA
- */
-#define	BT485_READ_BIT			0x01
-#define	BT485_WRITE_BIT			0x00
-
-#define	BT485_ADDR_PAL_WRITE		0x00
-#define	BT485_DATA_PAL			0x02
-#define	BT485_PIXEL_MASK		0x04
-#define	BT485_ADDR_PAL_READ		0x06
-#define	BT485_ADDR_CUR_WRITE		0x08
-#define	BT485_DATA_CUR			0x0a
-#define	BT485_CMD_0			0x0c
-#define	BT485_ADDR_CUR_READ		0x0e
-#define	BT485_CMD_1			0x10
-#define	BT485_CMD_2			0x12
-#define	BT485_STATUS			0x14
-#define	BT485_CMD_3			0x14
-#define	BT485_CUR_RAM			0x16
-#define	BT485_CUR_LOW_X			0x18
-#define	BT485_CUR_HIGH_X		0x1a
-#define	BT485_CUR_LOW_Y			0x1c
-#define	BT485_CUR_HIGH_Y		0x1e
-
-/*
- * useful defines for managing the BT463 on the 24-plane TGAs
- */
-#define	BT463_ADDR_LO		0x0
-#define	BT463_ADDR_HI		0x1
-#define	BT463_REG_ACC		0x2
-#define	BT463_PALETTE		0x3
+    /*
+     *  Global declarations
+     */
 
-#define	BT463_CUR_CLR_0		0x0100
-#define	BT463_CUR_CLR_1		0x0101
+static struct tgafb_info fb_info;
+static struct tgafb_par current_par;
+static int current_par_valid = 0;
+static struct display disp;
 
-#define	BT463_CMD_REG_0		0x0201
-#define	BT463_CMD_REG_1		0x0202
-#define	BT463_CMD_REG_2		0x0203
+static char __initdata default_fontname[40] = { 0 };
+static struct fb_var_screeninfo default_var;
+static int default_var_valid = 0;
 
-#define	BT463_READ_MASK_0	0x0205
-#define	BT463_READ_MASK_1	0x0206
-#define	BT463_READ_MASK_2	0x0207
-#define	BT463_READ_MASK_3	0x0208
+static int currcon = 0;
 
-#define	BT463_BLINK_MASK_0	0x0209
-#define	BT463_BLINK_MASK_1	0x020a
-#define	BT463_BLINK_MASK_2	0x020b
-#define	BT463_BLINK_MASK_3	0x020c
+#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
 
-#define	BT463_WINDOW_TYPE_BASE	0x0300
+static struct { u_char red, green, blue, pad; } palette[256];
+#ifdef FBCON_HAS_CFB32
+static u32 fbcon_cfb32_cmap[16];
+#endif
 
 
-int tga_type;
-unsigned int tga_mem_base;
-unsigned long tga_fb_base;
-unsigned long tga_regs_base;
+    /*
+     *  Hardware presets
+     */
 
-static unsigned int fb_offset_presets[4] __initdata = {
+static unsigned int fb_offset_presets[4] = {
 	TGA_8PLANE_FB_OFFSET,
 	TGA_24PLANE_FB_OFFSET,
 	0xffffffff,
 	TGA_24PLUSZ_FB_OFFSET
 };
 
-static unsigned int deep_presets[4] __initdata = {
+static unsigned int deep_presets[4] = {
   0x00014000,
   0x0001440d,
   0xffffffff,
   0x0001441d
 };
 
-static unsigned int rasterop_presets[4] __initdata = {
+static unsigned int rasterop_presets[4] = {
   0x00000003,
   0x00000303,
   0xffffffff,
   0x00000303
 };
 
-static unsigned int mode_presets[4] __initdata = {
+static unsigned int mode_presets[4] = {
   0x00002000,
   0x00002300,
   0xffffffff,
   0x00002300
 };
 
-static unsigned int base_addr_presets[4] __initdata = {
+static unsigned int base_addr_presets[4] = {
   0x00000000,
   0x00000001,
   0xffffffff,
   0x00000001
 };
 
-#define TGA_WRITE_REG(v,r) \
-	{ writel((v), tga_regs_base+(r)); mb(); }
-
-#define TGA_READ_REG(r) readl(tga_regs_base+(r))
-
-#define BT485_WRITE(v,r) \
-	  TGA_WRITE_REG((r),TGA_RAMDAC_SETUP_REG);		\
-	  TGA_WRITE_REG(((v)&0xff)|((r)<<8),TGA_RAMDAC_REG);
-
-#define BT463_LOAD_ADDR(a) \
-	TGA_WRITE_REG(BT463_ADDR_LO<<2, TGA_RAMDAC_SETUP_REG); \
-	TGA_WRITE_REG((BT463_ADDR_LO<<10)|((a)&0xff), TGA_RAMDAC_REG); \
-	TGA_WRITE_REG(BT463_ADDR_HI<<2, TGA_RAMDAC_SETUP_REG); \
-	TGA_WRITE_REG((BT463_ADDR_HI<<10)|(((a)>>8)&0xff), TGA_RAMDAC_REG);
+const unsigned int bt463_cursor_source[4] = {
+  0xffff0000, 0x00000000, 0x00000000, 0x00000000
+};
 
-#define BT463_WRITE(m,a,v) \
-	BT463_LOAD_ADDR((a)); \
-	TGA_WRITE_REG(((m)<<2),TGA_RAMDAC_SETUP_REG); \
-	TGA_WRITE_REG(((m)<<10)|((v)&0xff),TGA_RAMDAC_REG);
 
+    /*
+     *  Predefined video modes
+     *  This is a subset of the standard VESA modes, recalculated from XFree86.
+     *
+     *  XXX Should we store these in terms of the encoded par structs? Even better,
+     *      fbcon should provide a general mechanism for doing something like this.
+     */
 
-unsigned char PLLbits[7] __initdata = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 };
+static struct fb_videomode tgafb_predefined[] __initdata = {
+    { "640x480-60", {
+	640, 480, 640, 480, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "800x600-56", {
+	800, 600, 800, 600, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 27777, 128, 24, 22, 1, 72, 2,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "640x480-72", {
+	640, 480, 640, 480, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 31746, 144, 40, 30, 8, 40, 3,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "800x600-60", {
+	800, 600, 800, 600, 0, 0, 0, 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_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "800x600-72", {
+	800, 600, 800, 600, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 20000, 64, 56, 23, 37, 120, 6,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1024x768-60", {
+	1024, 768, 1024, 768, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 15384, 168, 8, 29, 3, 144, 6,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1152x864-60", {
+	1152, 864, 1152, 864, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 11123, 208, 64, 16, 4, 256, 8,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1024x768-70", {
+	1024, 768, 1024, 768, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 13333, 144, 24, 29, 3, 136, 6,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1024x768-76", {
+	1024, 768, 1024, 768, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 11764, 208, 8, 36, 16, 120, 3,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1152x864-70", {
+	1152, 864, 1152, 864, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 10869, 106, 56, 20, 1, 160, 10,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1280x1024-61", {
+	1280, 1024, 1280, 1024, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 9090, 200, 48, 26, 1, 184, 3,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1024x768-85", {
+	1024, 768, 1024, 768, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 10111, 192, 32, 34, 14, 160, 6,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1280x1024-70", {
+	1280, 1024, 1280, 1024, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 7905, 224, 32, 28, 8, 160, 8,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1152x864-84", {
+	1152, 864, 1152, 864, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 184, 312, 32, 0, 128, 12,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1280x1024-76", {
+	1280, 1024, 1280, 1024, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 248, 32, 34, 3, 104, 3,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "1280x1024-85", {
+	1280, 1024, 1280, 1024, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 6349, 224, 64, 44, 1, 160, 3,
+	0,
+	FB_VMODE_NONINTERLACED
+    }},
 
-const unsigned long bt485_cursor_source[64] __initdata = {
-#if 1
-  0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
-  0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
-  0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
-  0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000,
-#else
-  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
-  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
-  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
-  0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,
-#endif
-  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,
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-};
+    /* These are modes used by the two fixed-frequency monitors I have at home. 
+     * You may or may not find these useful.
+     */
 
-const unsigned int bt463_cursor_source[256] __initdata = {
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  0xffff0000, 0x00000000, 0x00000000, 0x00000000,
-  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,
-  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,
-  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,
-  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,
-  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,
-  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
+    { "WYSE1", {			/* 1280x1024 @ 72 Hz, 130 Mhz clock */
+	1280, 1024, 1280, 1024, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 7692, 192, 32, 47, 0, 192, 5,
+	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
+	FB_VMODE_NONINTERLACED
+    }},
+    { "IBM3", {				/* 1280x1024 @ 70 Hz, 120 Mhz clock */
+	1280, 1024, 1280, 1024, 0, 0, 0, 0,
+	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	0, 0, -1, -1, FB_ACCELF_TEXT, 8333, 192, 32, 47, 0, 192, 5,
+	0,
+	FB_VMODE_NONINTERLACED
+    }}
 };
 
-
-#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
-
-static int currcon = 0;
-static struct display disp;
-static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[256];
-#ifdef FBCON_HAS_CFB32
-static u32 fbcon_cfb32_cmap[16];
-#endif
-
-static struct fb_fix_screeninfo fb_fix = { { "DEC TGA ", } };
-static struct fb_var_screeninfo fb_var = { 0, };
+#define NUM_TOTAL_MODES    arraysize(tgafb_predefined)
 
 
     /*
      *  Interface used by the world
      */
 
+static void tgafb_detect(void);
+static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
+		        struct fb_info_gen *info);
+static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
+		        struct fb_info_gen *info);
+static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
+		        struct fb_info_gen *info);
+static void tgafb_get_par(void *fb_par, struct fb_info_gen *info);
+static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info);
+static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, 
+		u_int *transp, struct fb_info *info);
+static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 
+		u_int transp, struct fb_info *info);
+static int tgafb_pan_display(const struct fb_var_screeninfo *var,
+		struct fb_info_gen *info);
+static int tgafb_blank(int blank, struct fb_info_gen *info);
+static void tgafb_set_disp(const void *fb_par, struct display *disp, 
+		struct fb_info_gen *info);
+
 static int tgafb_open(struct fb_info *info, int user);
 static int tgafb_release(struct fb_info *info, int user);
-static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info);
-static int tgafb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
-static int tgafb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
-static int tgafb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info);
-static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
-static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
-static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info);
-
-
-    /*
-     *  Interface to the low level console driver
-     */
-
+void tgafb_setup(char *options, int *ints);
 void tgafb_init(void);
-static int tgafbcon_switch(int con, struct fb_info *info);
-static int tgafbcon_updatevar(int con, struct fb_info *info);
-static void tgafbcon_blank(int blank, struct fb_info *info);
+void tgafb_cleanup(struct fb_info *info);
 
-
-    /*
-     *  Internal routines
-     */
-
-static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info);
-static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info);
+static void tgafb_set_pll(int f);
 #if 1
-static void tga_update_palette(void);
+static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static void tgafb_update_palette(void);
 #endif
-static void do_install_cmap(int con, struct fb_info *info);
-
-
-static struct fb_ops tgafb_ops = {
-    tgafb_open, tgafb_release, tgafb_get_fix, tgafb_get_var, tgafb_set_var,
-    tgafb_get_cmap, tgafb_set_cmap, tgafb_pan_display, tgafb_ioctl
-};
 
 
     /*
-     *  Open/Release the frame buffer device
+     *  Chipset specific functions
      */
 
-static int tgafb_open(struct fb_info *info, int user)
-{
-    /*                                                                     
-     *  Nothing, only a usage count for the moment                          
-     */                                                                    
 
-    MOD_INC_USE_COUNT;
-    return(0);                              
-}
-        
-static int tgafb_release(struct fb_info *info, int user)
+static void tgafb_detect(void)
 {
-    MOD_DEC_USE_COUNT;
-    return(0);                                                    
+    return;
 }
 
 
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
+static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
+	struct fb_info_gen *info)
 {
-    memcpy(fix, &fb_fix, sizeof(fb_fix));
-    return 0;
-}
+    struct tgafb_par *par = (struct tgafb_par *)fb_par;
 
+    strcpy(fix->id, fb_info.gen.info.modename);
 
-    /*
-     *  Get the User Defined Part of the Display
-     */
+    fix->type = FB_TYPE_PACKED_PIXELS;
+    fix->type_aux = 0;
+    if (fb_info.tga_type == 0) /* 8-plane */
+	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+    else /* 24-plane or 24plusZ */
+	fix->visual = FB_VISUAL_TRUECOLOR;
+
+    fix->line_length = par->xres * (par->bits_per_pixel >> 3);
+    fix->smem_start = (char *)__pa(fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base));
+    fix->smem_len = fix->line_length * par->yres;
+    fix->mmio_start = (char *)__pa(fb_info.tga_regs_base);
+    fix->mmio_len = 0x1000;		/* Is this sufficient? */
+    fix->xpanstep = fix->ypanstep = fix->ywrapstep = 0;
+    fix->accel = FB_ACCEL_DEC_TGA;
 
-static int tgafb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-    memcpy(var, &fb_var, sizeof(fb_var));
     return 0;
 }
 
 
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int tgafb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
+	struct fb_info_gen *info)
 {
-    struct display *display;
-    int oldbpp = -1, err;
-
-    if (con >= 0)
-	display = &fb_display[con];
-    else
-	display = &disp;	/* used during initialization */
+    struct tgafb_par *par = (struct tgafb_par *)fb_par;
 
-    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
-	var->xres_virtual > fb_var.xres_virtual ||
-	var->yres_virtual > fb_var.yres_virtual ||
-	var->bits_per_pixel > fb_var.bits_per_pixel ||
-	var->nonstd ||
-	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-	return -EINVAL;
-    memcpy(var, &fb_var, sizeof(fb_var));
-
-    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-	oldbpp = display->var.bits_per_pixel;
-	display->var = *var;
-    }
-    if (oldbpp != var->bits_per_pixel) {
-	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-	    return err;
-	do_install_cmap(con, info);
+    /* round up some */
+    if (fb_info.tga_type == 0) {
+	if (var->bits_per_pixel > 8) {
+	    return -EINVAL;
+	}
+	par->bits_per_pixel = 8;
+    } else {
+	if (var->bits_per_pixel > 32) {
+	    return -EINVAL;
+	}
+	par->bits_per_pixel = 32;
     }
-    return 0;
-}
 
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int tgafb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info)
-{
-    if (var->xoffset || var->yoffset)
+    /* check the values for sanity */
+    if (var->xres_virtual != var->xres ||
+	var->yres_virtual != var->yres ||
+	var->nonstd || (1000000000/var->pixclock) > TGA_PLL_MAX_FREQ ||
+	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED
+#if 0	
+	|| !fbmon_valid_timings(var->pixclock, var->htotal, var->vtotal, info))
+#else
+	)
+#endif
 	return -EINVAL;
-    else
-	return 0;
-}
 
-    /*
-     *  Get the Colormap
-     */
+    /* encode video timings */
+    par->htimings = ((var->xres/4) & TGA_HORIZ_ACT_LSB) | 
+	(((var->xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB);
+    par->vtimings = (var->yres & TGA_VERT_ACTIVE);
+    par->htimings |= ((var->right_margin/4) << 9) & TGA_HORIZ_FP;
+    par->vtimings |= (var->lower_margin << 11) & TGA_VERT_FP;
+    par->htimings |= ((var->hsync_len/4) << 14) & TGA_HORIZ_SYNC;
+    par->vtimings |= (var->vsync_len << 16) & TGA_VERT_SYNC;
+    par->htimings |= ((var->left_margin/4) << 21) & TGA_HORIZ_BP;
+    par->vtimings |= (var->upper_margin << 22) & TGA_VERT_BP;
+
+    if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+	par->htimings |= TGA_HORIZ_POLARITY;
+    if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+	par->vtimings |= TGA_VERT_POLARITY;
+    /* what about sync on green? */
+
+    /* store other useful values in par */
+    par->xres = var->xres; 
+    par->yres = var->yres;
+    par->pll_freq = 1000000000/var->pixclock;
+    par->bits_per_pixel = var->bits_per_pixel;
 
-static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
-{
-    if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, kspc, tgafb_getcolreg, info);
-    else if (fb_display[con].cmap.len) /* non default colormap? */
-	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-    else
-	fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2);
     return 0;
 }
 
-    /*
-     *  Set the Colormap
-     */
 
-static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
+	struct fb_info_gen *info)
 {
-    int err;
+    struct tgafb_par *par = (struct tgafb_par *)fb_par;
 
-    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
-	if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
-	    return err;
+    /* decode video timings */
+    var->xres = ((par->htimings & TGA_HORIZ_ACT_LSB) | ((par->htimings & TGA_HORIZ_ACT_MSB) >> 19)) * 4;
+    var->yres = (par->vtimings & TGA_VERT_ACTIVE);
+    var->right_margin = ((par->htimings & TGA_HORIZ_FP) >> 9) * 4;
+    var->lower_margin = ((par->vtimings & TGA_VERT_FP) >> 11);
+    var->hsync_len = ((par->htimings & TGA_HORIZ_SYNC) >> 14) * 4;
+    var->vsync_len = ((par->vtimings & TGA_VERT_SYNC) >> 16);
+    var->left_margin = ((par->htimings & TGA_HORIZ_BP) >> 21) * 4;
+    var->upper_margin = ((par->vtimings & TGA_VERT_BP) >> 22);
+
+    if (par->htimings & TGA_HORIZ_POLARITY) 
+    	var->sync |= FB_SYNC_HOR_HIGH_ACT;
+    if (par->vtimings & TGA_VERT_POLARITY)
+    	var->sync |= FB_SYNC_VERT_HIGH_ACT;
+
+    var->xres_virtual = var->xres;
+    var->yres_virtual = var->yres;
+    var->xoffset = var->yoffset = 0;
+
+    /* depth-related */
+    if (fb_info.tga_type == 0) {
+	var->red.offset = 0;
+	var->green.offset = 0;
+	var->blue.offset = 0;
+    } else {
+	/* XXX: is this correct? */
+	var->red.offset = 16;
+	var->green.offset = 8;
+	var->blue.offset = 0;
     }
-    if (con == currcon) {		/* current console? */
-	err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
-#if 1
-	if (tga_type != 0)
-		tga_update_palette();
-#endif
-	return err;
-    } else
-	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+    var->bits_per_pixel = par->bits_per_pixel;
+    var->grayscale = 0;
+    var->red.length = var->green.length = var->blue.length = 8;
+    var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+    var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+
+    /* others */
+    var->xoffset = var->yoffset = 0;
+    var->pixclock = 1000000000/par->pll_freq;
+    var->nonstd = 0;
+    var->activate = 0;
+    var->height = var->width = -1;
+    var->accel_flags = 0;
+
     return 0;
 }
 
 
-static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info)
+static void tgafb_get_par(void *fb_par, struct fb_info_gen *info)
 {
-    return -EINVAL;
-}
+    struct tgafb_par *par = (struct tgafb_par *)fb_par;
 
+    if (current_par_valid)
+	*par = current_par;
+    else {
+	if (fb_info.tga_type == 0)
+	    default_var.bits_per_pixel = 8;
+	else
+	    default_var.bits_per_pixel = 32;
 
-    /*
-     *  Initialisation
-     */
+	tgafb_decode_var(&default_var, par, info);
+    }
+}
 
-__initfunc(void tgafb_init(void))
+
+static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info)
 {
     int i, j, temp;
-    unsigned char *cbp;
-    struct pci_dev *pdev;
-
-    pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
-    if (!pdev)
-	return;
-    tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
-#ifdef DEBUG
-    printk("tgafb_init: mem_base 0x%x\n", tga_mem_base);
-#endif /* DEBUG */
+    struct tgafb_par *par = (struct tgafb_par *)fb_par;
 
-    tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f;
-    switch (tga_type) {
-	case 0:
-	    strcat(fb_fix.id, "8plane");
-	    break;
-	case 1:
-	    strcat(fb_fix.id, "24plane");
-	    break;
-	case 3:
-	    strcat(fb_fix.id, "24plusZ");
-	    break;
-	default:
-	    printk("TGA type (0x%x) unrecognized!\n", tga_type);
+#if 0
+    /* XXX this will break console switching with X11, maybe I need to test KD_GRAPHICS? */
+    /* if current_par is valid, check to see if we need to change anything */
+    if (current_par_valid) {
+	if (!memcmp(par, &current_par, sizeof current_par)) {
 	    return;
+	}
     }
-
-    tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET);
-    tga_fb_base = ((unsigned long)tga_mem_base + fb_offset_presets[tga_type]);
+#endif
+    current_par = *par;
+    current_par_valid = 1;
 
     /* first, disable video timing */
     TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
-
+    
     /* write the DEEP register */
     while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
       continue;
 
     mb();
-    TGA_WRITE_REG(deep_presets[tga_type], TGA_DEEP_REG);
+    TGA_WRITE_REG(deep_presets[fb_info.tga_type], TGA_DEEP_REG);
     while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
 	continue;
     mb();
 
     /* write some more registers */
-    TGA_WRITE_REG(rasterop_presets[tga_type], TGA_RASTEROP_REG);
-    TGA_WRITE_REG(mode_presets[tga_type], TGA_MODE_REG);
-    TGA_WRITE_REG(base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
-
-    /* write the PLL for 640x480 @ 60Hz */
-    for (i = 0; i <= 6; i++) {
-	for (j = 0; j <= 7; j++) {
-	    temp = (PLLbits[i] >> (7-j)) & 1;
-	    if (i == 6 && j == 7)
-		temp |= 2;
-	    TGA_WRITE_REG(temp, TGA_CLOCK_REG);
-	}
-    }
+    TGA_WRITE_REG(rasterop_presets[fb_info.tga_type], TGA_RASTEROP_REG);
+    TGA_WRITE_REG(mode_presets[fb_info.tga_type], TGA_MODE_REG);
+    TGA_WRITE_REG(base_addr_presets[fb_info.tga_type], TGA_BASE_ADDR_REG);
+
+    /* calculate & write the PLL */
+    tgafb_set_pll(par->pll_freq);
 
     /* write some more registers */
     TGA_WRITE_REG(0xffffffff, TGA_PLANEMASK_REG);
@@ -523,21 +507,19 @@
     TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR0_REG);
     TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR1_REG);
 
-    /* init video timing regs for 640x480 @ 60 Hz */
-    TGA_WRITE_REG(0x018608a0, TGA_HORIZ_REG);
-    TGA_WRITE_REG(0x084251e0, TGA_VERT_REG);
-
-    if (tga_type == 0) { /* 8-plane */
+    /* init video timing regs */
+    TGA_WRITE_REG(par->htimings, TGA_HORIZ_REG);
+    TGA_WRITE_REG(par->vtimings, TGA_VERT_REG);
 
-	fb_var.bits_per_pixel = 8;
-	fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
+    /* initalise RAMDAC */
+    if (fb_info.tga_type == 0) { /* 8-plane */
 
 	/* init BT485 RAMDAC registers */
 	BT485_WRITE(0xa2, BT485_CMD_0);
 	BT485_WRITE(0x01, BT485_ADDR_PAL_WRITE);
 	BT485_WRITE(0x14, BT485_CMD_3); /* cursor 64x64 */
 	BT485_WRITE(0x40, BT485_CMD_1);
-	BT485_WRITE(0x22, BT485_CMD_2); /* WIN cursor type */
+	BT485_WRITE(0x20, BT485_CMD_2); /* cursor off, for now */
 	BT485_WRITE(0xff, BT485_PIXEL_MASK);
 
 	/* fill palette registers */
@@ -560,6 +542,7 @@
 	    TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
 	}	  
 
+#if 0
 	/* initialize RAMDAC cursor colors */
 	BT485_WRITE(0, BT485_ADDR_CUR_WRITE);
 
@@ -581,19 +564,39 @@
 
 	/* initialize RAMDAC cursor RAM */
 	BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
-	cbp = (unsigned char *)bt485_cursor_source;
-	for (i = 0; i < 512; i++) {
-	    BT485_WRITE(*cbp++, BT485_CUR_RAM);
-	}
+
+	for (i = 0; i < tga_font_height_padded; i++)
+	    for (j = 7; j >= 0; j--) {
+#if 0
+		/* note that this is for a top-right alignment
+		 * - top left is commented out */
+		if( j > /*<*/ ((tga_font_width - 1) >> 3) ) {
+		    BT485_WRITE(0, BT485_CUR_RAM);
+		}
+		else if( j == ((tga_font_width - 1) >> 3) ) {
+		    BT485_WRITE((0xff >> /*<<*/
+				(7 - ((tga_font_width - 1)&7))) , BT485_CUR_RAM);
+		}
+		else {
+		    BT485_WRITE(0xff, BT485_CUR_RAM);
+		}
+#else
+		BT485_WRITE(0, BT485_CUR_RAM);
+#endif
+	    }
+	for (i = tga_font_height_padded; i < 64; i++)
+	    for (j = 0; j < 8; j++) {
+		BT485_WRITE(0, BT485_CUR_RAM);
+	    }
+	/* mask? */
+
 	for (i = 0; i < 512; i++) {
 	    BT485_WRITE(0xff, BT485_CUR_RAM);
 	}
+#endif
 
     } else { /* 24-plane or 24plusZ */
 
-	fb_var.bits_per_pixel = 32;
-	fb_fix.visual = FB_VISUAL_TRUECOLOR;
-
 	TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
 
 	/*
@@ -652,6 +655,7 @@
 	    TGA_WRITE_REG(0x80|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
 	}
 
+#if 0
 	/*
 	 * init cursor colors
 	 */
@@ -679,135 +683,204 @@
 	temp = tga_fb_base - 1024; /* this assumes video starts at base
 				     and base is beyond memory start*/
 
-	for (i = 0; i < 256; i++) {
-	    writel(bt463_cursor_source[i], temp + i*4);
-	}
+	for (i = 0; i < tga_font_height_padded*4; i++)
+	    writel(bt463_cursor_source[i&3], temp + i*4);
+	for (i = tga_font_height_padded*4; i < 256; i++)
+	    writel(0, temp + i*4);
 	TGA_WRITE_REG(temp & 0x000fffff, TGA_CURSOR_BASE_REG);
+#endif
     }
 
     /* finally, enable video scan
-       (and pray for the monitor... :-) */
+	(and pray for the monitor... :-) */
     TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+}
 
-    fb_var.xres = fb_var.xres_virtual = 640;
-    fb_var.yres = fb_var.yres_virtual = 480;
-    fb_fix.line_length = 80*fb_var.bits_per_pixel;
-    fb_fix.smem_start = (char *)__pa(tga_fb_base + dense_mem(tga_fb_base));
-    fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
-    fb_fix.type = FB_TYPE_PACKED_PIXELS;
-    fb_fix.type_aux = 0;
-    fb_fix.mmio_start = (char *)__pa(tga_regs_base);
-    fb_fix.mmio_len = 0x1000;		/* Is this sufficient? */
-    fb_fix.accel = FB_ACCEL_DEC_TGA;
-
-    fb_var.xoffset = fb_var.yoffset = 0;
-    fb_var.grayscale = 0;
-    if (tga_type == 0) { /* 8-plane */
-	fb_var.red.offset = 0;
-	fb_var.green.offset = 0;
-	fb_var.blue.offset = 0;
-    } else { /* 24-plane or 24plusZ */
-	/* XXX: is this correct?? */
-	fb_var.red.offset = 16;
-	fb_var.green.offset = 8;
-	fb_var.blue.offset = 0;
-    }
-    fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
-    fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
-    fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
-    fb_var.nonstd = 0;
-    fb_var.activate = 0;
-    fb_var.height = fb_var.width = -1;
-    fb_var.accel_flags = 0;
-    fb_var.pixclock = 39722;
-    fb_var.left_margin = 40;
-    fb_var.right_margin = 24;
-    fb_var.upper_margin = 32;
-    fb_var.lower_margin = 11;
-    fb_var.hsync_len = 96;
-    fb_var.vsync_len = 2;
-    fb_var.sync = 0;
-    fb_var.vmode = FB_VMODE_NONINTERLACED;
-
-    disp.var = fb_var;
-    disp.cmap.start = 0;
-    disp.cmap.len = 0;
-    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
-    disp.screen_base = (char *)tga_fb_base + dense_mem(tga_fb_base);
-    disp.visual = fb_fix.visual;
-    disp.type = fb_fix.type;
-    disp.type_aux = fb_fix.type_aux;
-    disp.ypanstep = 0;
-    disp.ywrapstep = 0;
-    disp.line_length = fb_fix.line_length;
-    disp.can_soft_blank = 1;
-    disp.inverse = 0;
-    switch (tga_type) {
-#ifdef FBCON_HAS_CFB8
-	case 0: /* 8-plane */
-	    disp.dispsw = &fbcon_cfb8;
-	    break;
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 1: /* 24-plane */
-	case 3: /* 24plusZ */
-	    disp.dispsw = &fbcon_cfb32;
-	    disp.dispsw_data = &fbcon_cfb32_cmap;
-	    break;
-#endif
-	default:
-	    disp.dispsw = &fbcon_dummy;
+
+#define DIFFCHECK(x) { if( m <= 0x3f ) { \
+      int delta = f - (TGA_PLL_BASE_FREQ * (x)) / (r << shift); \
+      if (delta < 0) delta = -delta; \
+      if (delta < min_diff) min_diff = delta, vm = m, va = a, vr = r; } }
+
+static void tgafb_set_pll(int f)
+{
+    int                 n, shift, base, min_diff, target;
+    int                 r,a,m,vm = 34, va = 1, vr = 30;
+
+    for( r = 0 ; r < 12 ; r++ )
+	TGA_WRITE_REG(!r, TGA_CLOCK_REG);
+
+    if (f > TGA_PLL_MAX_FREQ)
+	f = TGA_PLL_MAX_FREQ;
+
+    if (f >= TGA_PLL_MAX_FREQ / 2)
+	shift = 0;
+    else if (f >= TGA_PLL_MAX_FREQ / 4)
+	shift = 1;
+    else
+	shift = 2;
+
+    TGA_WRITE_REG(shift & 1, TGA_CLOCK_REG);
+    TGA_WRITE_REG(shift >> 1, TGA_CLOCK_REG);
+
+    for( r = 0 ; r < 10 ; r++ ) {
+	TGA_WRITE_REG(0, TGA_CLOCK_REG);
     }
-    disp.scrollmode = SCROLL_YREDRAW;
 
-    strcpy(fb_info.modename, fb_fix.id);
-    fb_info.node = -1;
-    fb_info.fbops = &tgafb_ops;
-    fb_info.disp = &disp;
-    fb_info.fontname[0] = '\0';
-    fb_info.changevar = NULL;
-    fb_info.switch_con = &tgafbcon_switch;
-    fb_info.updatevar = &tgafbcon_updatevar;
-    fb_info.blank = &tgafbcon_blank;
-    fb_info.flags = FBINFO_FLAG_DEFAULT;
+    if (f <= 120000) {
+	TGA_WRITE_REG(0, TGA_CLOCK_REG);
+	TGA_WRITE_REG(0, TGA_CLOCK_REG);
+    }
+    else if (f <= 200000) {
+	TGA_WRITE_REG(1, TGA_CLOCK_REG);
+	TGA_WRITE_REG(0, TGA_CLOCK_REG);
+    }
+    else {
+	TGA_WRITE_REG(0, TGA_CLOCK_REG);
+	TGA_WRITE_REG(1, TGA_CLOCK_REG);
+    }
 
-    tgafb_set_var(&fb_var, -1, &fb_info);
+    TGA_WRITE_REG(1, TGA_CLOCK_REG);
+    TGA_WRITE_REG(0, TGA_CLOCK_REG);
+    TGA_WRITE_REG(0, TGA_CLOCK_REG);
+    TGA_WRITE_REG(1, TGA_CLOCK_REG);
+    TGA_WRITE_REG(0, TGA_CLOCK_REG);
+    TGA_WRITE_REG(1, TGA_CLOCK_REG);
+
+    target = (f << shift) / TGA_PLL_BASE_FREQ;
+    min_diff = TGA_PLL_MAX_FREQ;
+
+    r = 7 / target;
+    if (!r)
+	r = 1;
+
+    base = target * r;
+    while (base < 449) {
+	for (n = base < 7 ? 7 : base ; n < base + target && n < 449; n++) {
+	m = ((n + 3) / 7) - 1;
+	a = 0;
+	DIFFCHECK((m + 1) * 7);
+	m++;
+	DIFFCHECK((m + 1) * 7);
+	m = (n / 6) - 1;
+	if( (a = n % 6))
+	    DIFFCHECK( n );
+	}
+	r++;
+	base += target;
+    }
 
-    if (register_framebuffer(&fb_info) < 0)
-	return;
+    vr--;
 
-    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
-	   fb_fix.id);
+    for( r=0; r<8 ; r++) {
+	TGA_WRITE_REG((vm >> r) & 1, TGA_CLOCK_REG);
+    }
+    for( r=0; r<8 ; r++) {
+	TGA_WRITE_REG((va >> r) & 1, TGA_CLOCK_REG);
+    }
+    for( r=0; r<7 ; r++) {
+	TGA_WRITE_REG((vr >> r) & 1, TGA_CLOCK_REG);
+    }
+    TGA_WRITE_REG(((vr >> 7) & 1)|2, TGA_CLOCK_REG);
 }
 
 
-static int tgafbcon_switch(int con, struct fb_info *info)
+static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp, struct fb_info *info)
 {
-    /* Do we have to save the colormap? */
-    if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, 1, tgafb_getcolreg, info);
+    if (regno > 255)
+	return 1;
+    *red = (palette[regno].red<<8) | palette[regno].red;
+    *green = (palette[regno].green<<8) | palette[regno].green;
+    *blue = (palette[regno].blue<<8) | palette[regno].blue;
+    *transp = 0;
+    return 0;
+}
+
+
+static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp, struct fb_info *info)
+{
+    if (regno > 255)
+	return 1;
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+
+#ifdef FBCON_HAS_CFB32
+    if (regno < 16 && fb_info.tga_type != 0)
+	fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
+#endif
+
+    if (fb_info.tga_type == 0) { /* 8-plane */
+        BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
+        TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+        TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+        TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+        TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+    }                                                    
+    /* How to set a single color register on 24-plane cards?? */
 
-    currcon = con;
-    /* Install new colormap */
-    do_install_cmap(con, info);
     return 0;
 }
 
+#if 1
     /*
-     *  Update the `var' structure (called by fbcon.c)
+     *	FIXME: since I don't know how to set a single arbitrary color register
+     *  on 24-plane cards, all color palette registers have to be updated
      */
 
-static int tgafbcon_updatevar(int con, struct fb_info *info)
+static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info)
 {
-    /* Nothing */
+    int err;
+
+    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+	if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
+	    return err;
+    }
+    if (con == currcon) {		/* current console? */
+	err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
+#if 1
+	if (fb_info.tga_type != 0)
+		tgafb_update_palette();
+#endif
+	return err;
+    } else
+	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
     return 0;
 }
 
-    /*
-     *  Blank and unblank the display.
-     */
+static void tgafb_update_palette(void)
+{
+    int i;
+
+    BT463_LOAD_ADDR(0x0000);
+    TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+
+    for (i = 0; i < 256; i++) {
+	 TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	 TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	 TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+    }
+}
+#endif
+
+
+static int tgafb_pan_display(const struct fb_var_screeninfo *var, 
+	                             struct fb_info_gen *info)
+{
+    if (var->xoffset || var->yoffset)
+	return -EINVAL;
+    else
+	return 0;
+}
 
-static void tgafbcon_blank(int blank, struct fb_info *info)
+
+static int tgafb_blank(int blank, struct fb_info_gen *info)
 {
     static int tga_vesa_blanked = 0;
     u32 vhcr, vvcr;
@@ -854,158 +927,187 @@
     }
 
     restore_flags(flags);
-}
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-                         u_int *transp, struct fb_info *info)
-{
-    if (regno > 255)
-	return 1;
-    *red = (palette[regno].red<<8) | palette[regno].red;
-    *green = (palette[regno].green<<8) | palette[regno].green;
-    *blue = (palette[regno].blue<<8) | palette[regno].blue;
-    *transp = 0;
     return 0;
 }
 
 
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-                         u_int transp, struct fb_info *info)
+static void tgafb_set_disp(const void *fb_par, struct display *disp,
+	struct fb_info_gen *info)
 {
-    if (regno > 255)
-	return 1;
-    red >>= 8;
-    green >>= 8;
-    blue >>= 8;
-    palette[regno].red = red;
-    palette[regno].green = green;
-    palette[regno].blue = blue;
-
+    disp->screen_base = (char *)fb_info.tga_fb_base + dense_mem(fb_info.tga_fb_base);
+    switch (fb_info.tga_type) {
+#ifdef FBCON_HAS_CFB8
+	case 0: /* 8-plane */
+	    disp->dispsw = &fbcon_cfb8;
+            break;
+#endif
 #ifdef FBCON_HAS_CFB32
-    if (regno < 16 && tga_type != 0)
-	fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
+        case 1: /* 24-plane */
+        case 3: /* 24plusZ */
+            disp->dispsw = &fbcon_cfb32;
+            disp->dispsw_data = &fbcon_cfb32_cmap;
+            break;
 #endif
+        default:
+            disp->dispsw = &fbcon_dummy;
+    }
 
-    if (tga_type == 0) { /* 8-plane */
-        BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
-        TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
-        TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-        TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-        TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-    }                                                    
-    /* How to set a single color register on 24-plane cards?? */
-
-    return 0;
+    disp->scrollmode = SCROLL_YREDRAW;
 }
 
 
-#if 1
+struct fbgen_hwswitch tgafb_hwswitch = {
+    tgafb_detect, tgafb_encode_fix, tgafb_decode_var, tgafb_encode_var, tgafb_get_par,
+    tgafb_set_par, tgafb_getcolreg, tgafb_setcolreg, tgafb_pan_display, tgafb_blank, 
+    tgafb_set_disp
+};
+
+
     /*
-     *	FIXME: since I don't know how to set a single arbitrary color register
-     *  on 24-plane cards, all color palette registers have to be updated
+     *  Hardware Independent functions
      */
 
-static void tga_update_palette(void)
-{
-    int i;
 
-    BT463_LOAD_ADDR(0x0000);
-    TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+    /* 
+     *  Frame buffer operations
+     */
 
-    for (i = 0; i < 256; i++) {
-	 TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
-	 TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
-	 TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
-    }
+static int tgafb_open(struct fb_info *info, int user)
+{
+    MOD_INC_USE_COUNT;
+    return(0);                              
 }
-#endif
+      
 
-static void do_install_cmap(int con, struct fb_info *info)
+static int tgafb_release(struct fb_info *info, int user)
 {
-    if (con != currcon)
-	return;
-    if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, 1, tgafb_setcolreg, info);
-    else
-	fb_set_cmap(fb_default_cmap(256), 1, tgafb_setcolreg, info);
-#if 1
-    if (tga_type != 0)
-        tga_update_palette();
-#endif
+    MOD_DEC_USE_COUNT;
+    return(0);                                                    
 }
 
-#if 0	/* No cursor stuff yet */
 
-/*
- * Hide the cursor from view, during blanking, usually...
- */
-void
-hide_cursor(void)
-{
-	unsigned long flags;
-	save_flags(flags); cli();
+static struct fb_ops tgafb_ops = {
+    tgafb_open, tgafb_release, fbgen_get_fix, fbgen_get_var, fbgen_set_var,
+    fbgen_get_cmap, tgafb_set_cmap, fbgen_pan_display, fbgen_ioctl
+};
 
-	if (tga_type == 0) {
-	  BT485_WRITE(0x20, BT485_CMD_2);
-	} else {
-	  TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
-	}
 
-	restore_flags(flags);
+    /*
+     *  Setup
+     */
+
+__initfunc(void tgafb_setup(char *options, int *ints)) {
+    char *this_opt;
+    int i;
+    
+    if (options && *options)
+    	for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
+       	    if (!*this_opt) continue;
+        
+	    if (!strncmp(this_opt, "font:", 5))
+	     	strncpy(default_fontname, this_opt+5, sizeof default_fontname);
+	    else if (!strncmp(this_opt, "mode:", 5)) {
+    		for (i = 0; i < NUM_TOTAL_MODES; i++) {
+    		    if (!strcmp(this_opt+5, tgafb_predefined[i].name))
+    			default_var = tgafb_predefined[i].var;
+		    	default_var_valid = 1;
+    		}
+    	    } else {
+      		printk(KERN_ERR "tgafb: unknown parameter %s\n", this_opt);
+    	    }
+      	}
 }
 
-void
-set_cursor(int currcons)
+
+    /*
+     *  Initialisation
+     */
+
+__initfunc(void tgafb_init(void))
 {
-  unsigned int idx, xt, yt, row, col;
-  unsigned long flags;
+    struct pci_dev *pdev;
 
-  if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
-    return;
+    pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
+    if (!pdev)
+	return;
+    fb_info.tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+#ifdef DEBUG
+    printk("tgafb_init: mem_base 0x%x\n", fb_info.tga_mem_base);
+#endif /* DEBUG */
+
+    fb_info.tga_type = (readl((unsigned long)fb_info.tga_mem_base) >> 12) & 0x0f;
+    fb_info.tga_regs_base = ((unsigned long)fb_info.tga_mem_base + TGA_REGS_OFFSET);
+    fb_info.tga_fb_base = ((unsigned long)fb_info.tga_mem_base + fb_offset_presets[fb_info.tga_type]);
+
+    /* XXX Why the fuck is it called modename if it identifies the board? */
+    strcpy (fb_info.gen.info.modename,"DEC 21030 TGA "); 
+    switch (fb_info.tga_type) 
+    { 
+	case 0: /* 8-plane */
+	    strcat (fb_info.gen.info.modename, "8-plane");
+	    break;
 
-  save_flags(flags); cli();
+	case 1:
+	    strcat (fb_info.gen.info.modename, "24-plane");
+	    break;
 
-  if (deccm) {
-    idx = (pos - video_mem_base) >> 1;
-    col = idx % 80;
-    row = (idx - col) / 80;
+	case 3:
+	    strcat (fb_info.gen.info.modename, "24plusZ");
+	    break;
+    }
 
-    if (tga_type == 0) { /* 8-plane */
+    fb_info.gen.info.node = -1;
+    fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+    fb_info.gen.info.fbops = &tgafb_ops;
+    fb_info.gen.info.disp = &disp;
+    fb_info.gen.info.changevar = NULL;
+    fb_info.gen.info.switch_con = &fbgen_switch;
+    fb_info.gen.info.updatevar = &fbgen_update_var;
+    fb_info.gen.info.blank = &fbgen_blank;
+    strcpy(fb_info.gen.info.fontname, default_fontname);
+    fb_info.gen.parsize = sizeof (struct tgafb_par);
+    fb_info.gen.fbhw = &tgafb_hwswitch;
+    fb_info.gen.fbhw->detect();
+
+    /* This should give a reasonable default video mode */
+    if (!default_var_valid)
+	default_var = tgafb_predefined[0].var;
+    fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+    disp.var.activate = FB_ACTIVATE_NOW;
+    fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+    fbgen_set_disp(-1, &fb_info.gen);
+    fbgen_install_cmap(0, &fb_info.gen);
+    if (register_framebuffer(&fb_info.gen.info) < 0)
+	return;
+    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+	fb_info.gen.info.modename);
+}
 
-      xt = col * TGA_F_WIDTH + 64;
-      yt = row * TGA_F_HEIGHT_PADDED + 64;
 
-      /* make sure it's enabled */
-      BT485_WRITE(0x22, BT485_CMD_2); /* WIN cursor type */
+    /*
+     *  Cleanup
+     */
 
-      BT485_WRITE(xt, BT485_CUR_LOW_X);
-      BT485_WRITE((xt >> 8), BT485_CUR_HIGH_X);
-      BT485_WRITE(yt, BT485_CUR_LOW_Y);
-      BT485_WRITE((yt >> 8), BT485_CUR_HIGH_Y);
+void tgafb_cleanup(struct fb_info *info)
+{
+    unregister_framebuffer(info);
+}
 
-    } else {
 
-      xt = col * TGA_F_WIDTH + 144;
-      yt = row * TGA_F_HEIGHT_PADDED + 35;
+    /*
+     *  Modularisation
+     */
 
-      TGA_WRITE_REG(0x05, TGA_VALID_REG); /* SCANNING and CURSOR */
-      TGA_WRITE_REG(xt | (yt << 12), TGA_CURSOR_XY_REG);
-    }
+#ifdef MODULE
+int init_module(void)
+{
+    tgafb_init();
+    return 0;
+}
 
-  } else
-    hide_cursor();
-  restore_flags(flags);
+void cleanup_module(void)
+{
+    tgafb_cleanup(void);
 }
+#endif /* MODULE */
 
-#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/tgafb.h linux.pre11.3/drivers/video/tgafb.h
--- linux.vanilla/drivers/video/tgafb.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/video/tgafb.h	Tue Jul 20 00:05:18 1999
@@ -0,0 +1,190 @@
+/*
+ *  linux/drivers/video/tgafb.h -- DEC 21030 TGA frame buffer device
+ *
+ *  	Copyright (C) 1999 Martin Lucina, Tom Zerucha
+ *  
+ *  $Id: tgafb.h,v 1.4 1999/05/15 08:44:31 mato Exp $
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef TGAFB_H
+#define TGAFB_H
+
+    /*
+     * TGA hardware description (minimal)
+     */
+
+
+    /*
+     * Offsets within Memory Space
+     */
+
+#define	TGA_ROM_OFFSET			0x0000000
+#define	TGA_REGS_OFFSET			0x0100000
+#define	TGA_8PLANE_FB_OFFSET		0x0200000
+#define	TGA_24PLANE_FB_OFFSET		0x0804000
+#define	TGA_24PLUSZ_FB_OFFSET		0x1004000
+
+#define	TGA_PLANEMASK_REG		0x0028
+#define	TGA_MODE_REG			0x0030
+#define	TGA_RASTEROP_REG		0x0034
+#define	TGA_PIXELSHIFT_REG		0x0038
+#define	TGA_DEEP_REG			0x0050
+#define	TGA_PIXELMASK_REG		0x005c
+#define	TGA_CURSOR_BASE_REG		0x0060
+#define	TGA_HORIZ_REG			0x0064
+#define	TGA_VERT_REG			0x0068
+#define	TGA_BASE_ADDR_REG		0x006c
+#define	TGA_VALID_REG			0x0070
+#define	TGA_CURSOR_XY_REG		0x0074
+#define	TGA_INTR_STAT_REG		0x007c
+#define	TGA_RAMDAC_SETUP_REG		0x00c0
+#define	TGA_BLOCK_COLOR0_REG		0x0140
+#define	TGA_BLOCK_COLOR1_REG		0x0144
+#define	TGA_CLOCK_REG			0x01e8
+#define	TGA_RAMDAC_REG			0x01f0
+#define	TGA_CMD_STAT_REG		0x01f8
+
+
+    /* 
+     * useful defines for managing the video timing registers
+     */
+
+#define TGA_HORIZ_ODD			0x80000000
+#define TGA_HORIZ_POLARITY		0x40000000
+#define TGA_HORIZ_ACT_MSB		0x30000000
+#define TGA_HORIZ_BP			0x0fe00000
+#define TGA_HORIZ_SYNC			0x001fc000
+#define TGA_HORIZ_FP			0x00007c00
+#define TGA_HORIZ_ACT_LSB		0x000001ff
+
+#define TGA_VERT_SE			0x80000000
+#define TGA_VERT_POLARITY		0x40000000
+#define TGA_VERT_RESERVED		0x30000000
+#define TGA_VERT_BP			0x0fc00000
+#define TGA_VERT_SYNC			0x003f0000
+#define TGA_VERT_FP			0x0000f800
+#define TGA_VERT_ACTIVE			0x000007ff
+
+
+    /*
+     * useful defines for managing the ICS1562 PLL clock
+     */
+
+#define TGA_PLL_BASE_FREQ 		14318		/* .18 */
+#define TGA_PLL_MAX_FREQ 		230000
+
+
+    /*
+     * useful defines for managing the BT485 on the 8-plane TGA
+     */
+
+#define	BT485_READ_BIT			0x01
+#define	BT485_WRITE_BIT			0x00
+
+#define	BT485_ADDR_PAL_WRITE		0x00
+#define	BT485_DATA_PAL			0x02
+#define	BT485_PIXEL_MASK		0x04
+#define	BT485_ADDR_PAL_READ		0x06
+#define	BT485_ADDR_CUR_WRITE		0x08
+#define	BT485_DATA_CUR			0x0a
+#define	BT485_CMD_0			0x0c
+#define	BT485_ADDR_CUR_READ		0x0e
+#define	BT485_CMD_1			0x10
+#define	BT485_CMD_2			0x12
+#define	BT485_STATUS			0x14
+#define	BT485_CMD_3			0x14
+#define	BT485_CUR_RAM			0x16
+#define	BT485_CUR_LOW_X			0x18
+#define	BT485_CUR_HIGH_X		0x1a
+#define	BT485_CUR_LOW_Y			0x1c
+#define	BT485_CUR_HIGH_Y		0x1e
+
+
+    /*
+     * useful defines for managing the BT463 on the 24-plane TGAs
+     */
+
+#define	BT463_ADDR_LO		0x0
+#define	BT463_ADDR_HI		0x1
+#define	BT463_REG_ACC		0x2
+#define	BT463_PALETTE		0x3
+
+#define	BT463_CUR_CLR_0		0x0100
+#define	BT463_CUR_CLR_1		0x0101
+
+#define	BT463_CMD_REG_0		0x0201
+#define	BT463_CMD_REG_1		0x0202
+#define	BT463_CMD_REG_2		0x0203
+
+#define	BT463_READ_MASK_0	0x0205
+#define	BT463_READ_MASK_1	0x0206
+#define	BT463_READ_MASK_2	0x0207
+#define	BT463_READ_MASK_3	0x0208
+
+#define	BT463_BLINK_MASK_0	0x0209
+#define	BT463_BLINK_MASK_1	0x020a
+#define	BT463_BLINK_MASK_2	0x020b
+#define	BT463_BLINK_MASK_3	0x020c
+
+#define	BT463_WINDOW_TYPE_BASE	0x0300
+
+
+    /*
+     * Macros for reading/writing TGA and RAMDAC registers
+     */
+
+#define TGA_WRITE_REG(v,r) \
+	{ writel((v), fb_info.tga_regs_base+(r)); mb(); }
+
+#define TGA_READ_REG(r) readl(fb_info.tga_regs_base+(r))
+
+#define BT485_WRITE(v,r) \
+	  TGA_WRITE_REG((r),TGA_RAMDAC_SETUP_REG);		\
+	  TGA_WRITE_REG(((v)&0xff)|((r)<<8),TGA_RAMDAC_REG);
+
+#define BT463_LOAD_ADDR(a) \
+	TGA_WRITE_REG(BT463_ADDR_LO<<2, TGA_RAMDAC_SETUP_REG); \
+	TGA_WRITE_REG((BT463_ADDR_LO<<10)|((a)&0xff), TGA_RAMDAC_REG); \
+	TGA_WRITE_REG(BT463_ADDR_HI<<2, TGA_RAMDAC_SETUP_REG); \
+	TGA_WRITE_REG((BT463_ADDR_HI<<10)|(((a)>>8)&0xff), TGA_RAMDAC_REG);
+
+#define BT463_WRITE(m,a,v) \
+	BT463_LOAD_ADDR((a)); \
+	TGA_WRITE_REG(((m)<<2),TGA_RAMDAC_SETUP_REG); \
+	TGA_WRITE_REG(((m)<<10)|((v)&0xff),TGA_RAMDAC_REG);
+
+
+    /*
+     *  This structure describes the board.
+     */
+
+struct tgafb_info {
+    /* Use the generic framebuffer ops */
+    struct fb_info_gen gen;
+
+    /* Device dependent information */
+    int tga_type;					/* TGA type: {8plane, 24plane, 24plusZ} */
+    unsigned int tga_mem_base;
+    unsigned long tga_fb_base;
+    unsigned long tga_regs_base;
+    struct fb_var_screeninfo default_var;		/* default video mode */
+};
+
+
+    /*
+     *  This structure uniquely defines a video mode.
+     */
+
+struct tgafb_par {
+    int xres, yres;					/* resolution in pixels */
+    unsigned int htimings;				/* horizontal timing register */
+    unsigned int vtimings;				/* vertical timing register */
+    unsigned int pll_freq;				/* pixclock in mhz */
+    unsigned int bits_per_pixel;			/* bits per pixel */
+};
+
+#endif /* TGAFB_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/vga16fb.c linux.pre11.3/drivers/video/vga16fb.c
--- linux.vanilla/drivers/video/vga16fb.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/video/vga16fb.c	Mon Jul 19 23:28:22 1999
@@ -0,0 +1,1065 @@
+/*
+ * linux/drivers/video/vga16.c -- VGA 16-color framebuffer driver
+ * 
+ * Copyright 1999 Ben Pfaff <pfaffben@debian.org> and Petr Vandrovec <VANDROVE@vc.cvut.cz>
+ * Based on VGA info at http://www.goodnet.com/~tinara/FreeVGA/home.htm
+ * Based on VESA framebuffer (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file COPYING in the main directory of this
+ * archive for more details.  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/console.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/config.h>
+
+#include <asm/io.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-vga-planes.h>
+
+#define dac_reg	(0x3c8)
+#define dac_val	(0x3c9)
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * card parameters
+ */
+
+static struct vga16fb_info {
+	struct fb_info  fb_info;
+	char *video_vbase;			/* 0xa0000 map address */
+	int isVGA;
+	
+	/* structure holding original VGA register settings when the
+           screen is blanked */
+	struct {
+		unsigned char	SeqCtrlIndex;		/* Sequencer Index reg.   */
+		unsigned char	CrtCtrlIndex;		/* CRT-Contr. Index reg.  */
+		unsigned char	CrtMiscIO;		/* Miscellaneous register */
+		unsigned char	HorizontalTotal;	/* CRT-Controller:00h */
+		unsigned char	HorizDisplayEnd;	/* CRT-Controller:01h */
+		unsigned char	StartHorizRetrace;	/* CRT-Controller:04h */
+		unsigned char	EndHorizRetrace;	/* CRT-Controller:05h */
+		unsigned char	Overflow;		/* CRT-Controller:07h */
+		unsigned char	StartVertRetrace;	/* CRT-Controller:10h */
+		unsigned char	EndVertRetrace;		/* CRT-Controller:11h */
+		unsigned char	ModeControl;		/* CRT-Controller:17h */
+		unsigned char	ClockingMode;		/* Seq-Controller:01h */
+	} vga_state;
+
+	int palette_blanked;
+	int vesa_blanked;
+} vga16fb;
+
+/* Some of the code below is taken from SVGAlib.  The original,
+   unmodified copyright notice for that code is below. */
+/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
+/*                                                                 */
+/* This library is free software; you can redistribute it and/or   */
+/* modify it without any restrictions. This library is distributed */
+/* in the hope that it will be useful, but without any warranty.   */
+
+/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
+/* partially copyrighted (C) 1993 by Hartmut Schirmer */
+
+/* VGA data register ports */
+#define CRT_DC  0x3D5		/* CRT Controller Data Register - color emulation */
+#define CRT_DM  0x3B5		/* CRT Controller Data Register - mono emulation */
+#define ATT_R   0x3C1		/* Attribute Controller Data Read Register */
+#define GRA_D   0x3CF		/* Graphics Controller Data Register */
+#define SEQ_D   0x3C5		/* Sequencer Data Register */
+#define MIS_R   0x3CC		/* Misc Output Read Register */
+#define MIS_W   0x3C2		/* Misc Output Write Register */
+#define IS1_RC  0x3DA		/* Input Status Register 1 - color emulation */
+#define IS1_RM  0x3BA		/* Input Status Register 1 - mono emulation */
+#define PEL_D   0x3C9		/* PEL Data Register */
+#define PEL_MSK 0x3C6		/* PEL mask register */
+
+/* EGA-specific registers */
+#define GRA_E0	0x3CC		/* Graphics enable processor 0 */
+#define GRA_E1	0x3CA		/* Graphics enable processor 1 */
+
+
+/* VGA index register ports */
+#define CRT_IC  0x3D4		/* CRT Controller Index - color emulation */
+#define CRT_IM  0x3B4		/* CRT Controller Index - mono emulation */
+#define ATT_IW  0x3C0		/* Attribute Controller Index & Data Write Register */
+#define GRA_I   0x3CE		/* Graphics Controller Index */
+#define SEQ_I   0x3C4		/* Sequencer Index */
+#define PEL_IW  0x3C8		/* PEL Write Index */
+#define PEL_IR  0x3C7		/* PEL Read Index */
+
+/* standard VGA indexes max counts */
+#define CRT_C   24		/* 24 CRT Controller Registers */
+#define ATT_C   21		/* 21 Attribute Controller Registers */
+#define GRA_C   9		/* 9  Graphics Controller Registers */
+#define SEQ_C   5		/* 5  Sequencer Registers */
+#define MIS_C   1		/* 1  Misc Output Register */
+
+#define CRTC_H_TOTAL		0
+#define CRTC_H_DISP		1
+#define CRTC_H_BLANK_START	2
+#define CRTC_H_BLANK_END	3
+#define CRTC_H_SYNC_START	4
+#define CRTC_H_SYNC_END		5
+#define CRTC_V_TOTAL		6
+#define CRTC_OVERFLOW		7
+#define CRTC_PRESET_ROW		8
+#define CRTC_MAX_SCAN		9
+#define CRTC_CURSOR_START	0x0A
+#define CRTC_CURSOR_END		0x0B
+#define CRTC_START_HI		0x0C
+#define CRTC_START_LO		0x0D
+#define CRTC_CURSOR_HI		0x0E
+#define CRTC_CURSOR_LO		0x0F
+#define CRTC_V_SYNC_START	0x10
+#define CRTC_V_SYNC_END		0x11
+#define CRTC_V_DISP_END		0x12
+#define CRTC_OFFSET		0x13
+#define CRTC_UNDERLINE		0x14
+#define CRTC_V_BLANK_START	0x15
+#define CRTC_V_BLANK_END	0x16
+#define CRTC_MODE		0x17
+#define CRTC_LINE_COMPARE	0x18
+#define CRTC_REGS		0x19
+
+#define ATC_MODE		0x10
+#define ATC_OVERSCAN		0x11
+#define ATC_PLANE_ENABLE	0x12
+#define ATC_PEL			0x13
+#define ATC_COLOR_PAGE		0x14
+
+#define SEQ_CLOCK_MODE		0x01
+#define SEQ_PLANE_WRITE		0x02
+#define SEQ_CHARACTER_MAP	0x03
+#define SEQ_MEMORY_MODE		0x04
+
+#define GDC_SR_VALUE		0x00
+#define GDC_SR_ENABLE		0x01
+#define GDC_COMPARE_VALUE	0x02
+#define GDC_DATA_ROTATE		0x03
+#define GDC_PLANE_READ		0x04
+#define GDC_MODE		0x05
+#define GDC_MISC		0x06
+#define GDC_COMPARE_MASK	0x07
+#define GDC_BIT_MASK		0x08
+
+struct vga16fb_par {
+	u8 crtc[CRTC_REGS];
+	u8 atc[ATT_C];
+	u8 gdc[GRA_C];
+	u8 seq[SEQ_C];
+	u8 misc;
+	u8 vss;
+	struct fb_var_screeninfo var;
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo vga16fb_defined = {
+	640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
+	0,0,		/* virtual -> visible no offset */
+	4,		/* depth -> load bits_per_pixel */
+	0,		/* greyscale ? */
+	{0,0,0},	/* R */
+	{0,0,0},	/* G */
+	{0,0,0},	/* B */
+	{0,0,0},	/* transparency */
+	0,		/* standard pixel format */
+	FB_ACTIVATE_NOW,
+	-1,-1,
+	0,
+	39721, 48, 16, 39, 8,
+	96, 2, 0,	/* No sync info */
+	FB_VMODE_NONINTERLACED,
+	{0,0,0,0,0,0}
+};
+
+static struct display disp;
+static struct { u_short blue, green, red, pad; } palette[256];
+
+static int             currcon   = 0;
+
+/* --------------------------------------------------------------------- */
+
+	/*
+	 * Open/Release the frame buffer device
+	 */
+
+static int vga16fb_open(struct fb_info *info, int user)
+{
+	/*
+	 * Nothing, only a usage count for the moment
+	 */
+	MOD_INC_USE_COUNT;
+	return(0);
+}
+
+static int vga16fb_release(struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return(0);
+}
+
+static void vga16fb_pan_var(struct fb_info *info, struct fb_var_screeninfo *var)
+{
+	u32 pos = (var->xres_virtual * var->yoffset + var->xoffset) >> 3;
+	outb(CRTC_START_HI, CRT_IC);
+	outb(pos >> 8, CRT_DC);
+	outb(CRTC_START_LO, CRT_IC);
+	outb(pos & 0xFF, CRT_DC);
+#if 0
+	/* if someone supports xoffset in bit resolution */
+	inb(IS1_RC);		/* reset flip-flop */
+	outb(ATC_PEL, ATT_IW);
+	outb(xoffset & 7, ATT_IW);
+	inb(IS1_RC);
+	outb(0x20, ATT_IW);
+#endif
+}
+
+static int vga16fb_update_var(int con, struct fb_info *info)
+{
+	vga16fb_pan_var(info, &fb_display[con].var);
+	return 0;
+}
+
+static int vga16fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			   struct fb_info *info)
+{
+	struct display *p;
+
+	if (con < 0)
+		p = &disp;
+	else
+		p = fb_display + con;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id,"VGA16 VGA");
+
+	fix->smem_start = (char *) 0xa0000;
+	fix->smem_len = 65536;
+	fix->type = FB_TYPE_VGA_PLANES;
+	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	fix->xpanstep  = 8;
+	fix->ypanstep  = 1;
+	fix->ywrapstep = 0;
+	fix->line_length = p->var.xres_virtual / 8;
+	return 0;
+}
+
+static int vga16fb_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	if(con==-1)
+		memcpy(var, &vga16fb_defined, sizeof(struct fb_var_screeninfo));
+	else
+		*var=fb_display[con].var;
+	return 0;
+}
+
+static void vga16fb_set_disp(int con, struct vga16fb_info *info)
+{
+	struct fb_fix_screeninfo fix;
+	struct display *display;
+
+	if (con < 0)
+		display = &disp;
+	else
+		display = fb_display + con;
+
+	
+	vga16fb_get_fix(&fix, con, &info->fb_info);
+
+	display->screen_base = info->video_vbase;
+	display->visual = fix.visual;
+	display->type = fix.type;
+	display->type_aux = fix.type_aux;
+	display->ypanstep = fix.ypanstep;
+	display->ywrapstep = fix.ywrapstep;
+	display->line_length = fix.line_length;
+	display->next_line = fix.line_length;
+	display->can_soft_blank = 1;
+	display->inverse = 0;
+
+	if (info->isVGA)
+		display->dispsw = &fbcon_vga_planes;
+	else
+		display->dispsw = &fbcon_ega_planes;
+	display->scrollmode = SCROLL_YREDRAW;
+}
+
+static void vga16fb_encode_var(struct fb_var_screeninfo *var,
+			       const struct vga16fb_par *par,
+			       const struct vga16fb_info *info)
+{
+	*var = par->var;
+}
+
+static void vga16fb_clock_chip(struct vga16fb_par *par,
+			       unsigned int pixclock,
+			       const struct vga16fb_info *info)
+{
+	static struct {
+		u32 pixclock;
+		u8  misc;
+		u8  seq_clock_mode;
+	} *ptr, *best, vgaclocks[] = {
+		{ 79442 /* 12.587 */, 0x00, 0x08},
+		{ 70616 /* 14.161 */, 0x04, 0x08},
+		{ 39721 /* 25.175 */, 0x00, 0x00},
+		{ 35308 /* 28.322 */, 0x04, 0x00},
+		{     0 /* bad */,    0x00, 0x00}};
+	int err;
+
+	best = vgaclocks;
+	err = pixclock - best->pixclock;
+	if (err < 0) err = -err;
+	for (ptr = vgaclocks + 1; ptr->pixclock; ptr++) {
+		int tmp;
+
+		tmp = pixclock - ptr->pixclock;
+		if (tmp < 0) tmp = -tmp;
+		if (tmp < err) {
+			err = tmp;
+			best = ptr;
+		}
+	}
+	par->misc |= best->misc;
+	par->seq[SEQ_CLOCK_MODE] |= best->seq_clock_mode;
+	par->var.pixclock = best->pixclock;		
+}
+			       
+#define FAIL(X) return -EINVAL
+
+static int vga16fb_decode_var(const struct fb_var_screeninfo *var,
+			      struct vga16fb_par *par,
+			      const struct vga16fb_info *info)
+{
+	u32 xres, right, hslen, left, xtotal;
+	u32 yres, lower, vslen, upper, ytotal;
+	u32 vxres, xoffset, vyres, yoffset;
+	u32 pos;
+	u8 r7, rMode;
+	int i;
+
+	if (var->bits_per_pixel != 4)
+		return -EINVAL;
+	xres = (var->xres + 7) & ~7;
+	vxres = (var->xres_virtual + 0xF) & ~0xF;
+	xoffset = (var->xoffset + 7) & ~7;
+	left = (var->left_margin + 7) & ~7;
+	right = (var->right_margin + 7) & ~7;
+	hslen = (var->hsync_len + 7) & ~7;
+
+	if (vxres < xres)
+		vxres = xres;
+	if (xres + xoffset > vxres)
+		xoffset = vxres - xres;
+
+	par->var.xres = xres;
+	par->var.right_margin = right;
+	par->var.hsync_len = hslen;
+	par->var.left_margin = left;
+	par->var.xres_virtual = vxres;
+	par->var.xoffset = xoffset;
+
+	xres >>= 3;
+	right >>= 3;
+	hslen >>= 3;
+	left >>= 3;
+	vxres >>= 3;
+	xtotal = xres + right + hslen + left;
+	if (xtotal >= 256)
+		FAIL("xtotal too big");
+	if (hslen > 32)
+		FAIL("hslen too big");
+	if (right + hslen + left > 64)
+		FAIL("hblank too big");
+	par->crtc[CRTC_H_TOTAL] = xtotal - 5;
+	par->crtc[CRTC_H_BLANK_START] = xres - 1;
+	par->crtc[CRTC_H_DISP] = xres - 1;
+	pos = xres + right;
+	par->crtc[CRTC_H_SYNC_START] = pos;
+	pos += hslen;
+	par->crtc[CRTC_H_SYNC_END] = pos & 0x1F;
+	pos += left - 2; /* blank_end + 2 <= total + 5 */
+	par->crtc[CRTC_H_BLANK_END] = (pos & 0x1F) | 0x80;
+	if (pos & 0x20)
+		par->crtc[CRTC_H_SYNC_END] |= 0x80;
+
+	yres = var->yres;
+	lower = var->lower_margin;
+	vslen = var->vsync_len;
+	upper = var->upper_margin;
+	vyres = var->yres_virtual;
+	yoffset = var->yoffset;
+
+	if (yres > vyres)
+		vyres = yres;
+	if (vxres * vyres > 65536) {
+		vyres = 65536 / vxres;
+		if (vyres < yres)
+			return -ENOMEM;
+	}
+	if (yoffset + yres > vyres)
+		yoffset = vyres - yres;
+	par->var.yres = yres;
+	par->var.lower_margin = lower;
+	par->var.vsync_len = vslen;
+	par->var.upper_margin = upper;
+	par->var.yres_virtual = vyres;
+	par->var.yoffset = yoffset;
+
+	if (var->vmode & FB_VMODE_DOUBLE) {
+		yres <<= 1;
+		lower <<= 1;
+		vslen <<= 1;
+		upper <<= 1;
+	}
+	ytotal = yres + lower + vslen + upper;
+	if (ytotal > 1024) {
+		ytotal >>= 1;
+		yres >>= 1;
+		lower >>= 1;
+		vslen >>= 1;
+		upper >>= 1;
+		rMode = 0x04;
+	} else
+		rMode = 0x00;
+	if (ytotal > 1024)
+		FAIL("ytotal too big");
+	if (vslen > 16)
+		FAIL("vslen too big");
+	par->crtc[CRTC_V_TOTAL] = ytotal - 2;
+	r7 = 0x10;	/* disable linecompare */
+	if (ytotal & 0x100) r7 |= 0x01;
+	if (ytotal & 0x200) r7 |= 0x20;
+	par->crtc[CRTC_PRESET_ROW] = 0;
+	par->crtc[CRTC_MAX_SCAN] = 0x40;	/* 1 scanline, no linecmp */
+	par->var.vmode = var->vmode;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		par->crtc[CRTC_MAX_SCAN] |= 0x80;
+	par->crtc[CRTC_CURSOR_START] = 0x20;
+	par->crtc[CRTC_CURSOR_END]   = 0x00;
+	pos = yoffset * vxres + (xoffset >> 3);
+	par->crtc[CRTC_START_HI]     = pos >> 8;
+	par->crtc[CRTC_START_LO]     = pos & 0xFF;
+	par->crtc[CRTC_CURSOR_HI]    = 0x00;
+	par->crtc[CRTC_CURSOR_LO]    = 0x00;
+	pos = yres - 1;
+	par->crtc[CRTC_V_DISP_END] = pos & 0xFF;
+	par->crtc[CRTC_V_BLANK_START] = pos & 0xFF;
+	if (pos & 0x100)
+		r7 |= 0x0A;	/* 0x02 -> DISP_END, 0x08 -> BLANK_START */
+	if (pos & 0x200) {
+		r7 |= 0x40;	/* 0x40 -> DISP_END */
+		par->crtc[CRTC_MAX_SCAN] |= 0x20; /* BLANK_START */
+	}
+	pos += lower;
+	par->crtc[CRTC_V_SYNC_START] = pos & 0xFF;
+	if (pos & 0x100)
+		r7 |= 0x04;
+	if (pos & 0x200)
+		r7 |= 0x80;
+	pos += vslen;
+	par->crtc[CRTC_V_SYNC_END] = (pos & 0x0F) | 0x10; /* disabled IRQ */
+	pos += upper - 1; /* blank_end + 1 <= ytotal + 2 */
+	par->crtc[CRTC_V_BLANK_END] = pos & 0xFF; /* 0x7F for original VGA,
+                     but some SVGA chips requires all 8 bits to set */
+	if (vxres >= 512)
+		FAIL("vxres too long");
+	par->crtc[CRTC_OFFSET] = vxres >> 1;
+	par->crtc[CRTC_UNDERLINE] = 0x1F;
+	par->crtc[CRTC_MODE] = rMode | 0xE3;
+	par->crtc[CRTC_LINE_COMPARE] = 0xFF;
+	par->crtc[CRTC_OVERFLOW] = r7;
+
+	par->vss = 0x00;	/* 3DA */
+
+	for (i = 0x00; i < 0x10; i++)
+		par->atc[i] = i;
+	par->atc[ATC_MODE] = 0x81;
+	par->atc[ATC_OVERSCAN] = 0x00;	/* 0 for EGA, 0xFF for VGA */
+	par->atc[ATC_PLANE_ENABLE] = 0x0F;
+	par->atc[ATC_PEL] = xoffset & 7;
+	par->atc[ATC_COLOR_PAGE] = 0x00;
+	
+	par->misc = 0xC3;	/* enable CPU, ports 0x3Dx, positive sync */
+	par->var.sync = var->sync;
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		par->misc &= ~0x40;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		par->misc &= ~0x80;
+	
+	par->seq[SEQ_CLOCK_MODE] = 0x01;
+	par->seq[SEQ_PLANE_WRITE] = 0x0F;
+	par->seq[SEQ_CHARACTER_MAP] = 0x00;
+	par->seq[SEQ_MEMORY_MODE] = 0x06;
+	
+	par->gdc[GDC_SR_VALUE] = 0x00;
+	par->gdc[GDC_SR_ENABLE] = 0x0F;
+	par->gdc[GDC_COMPARE_VALUE] = 0x00;
+	par->gdc[GDC_DATA_ROTATE] = 0x20;
+	par->gdc[GDC_PLANE_READ] = 0;
+	par->gdc[GDC_MODE] = 0x00;
+	par->gdc[GDC_MISC] = 0x05;
+	par->gdc[GDC_COMPARE_MASK] = 0x0F;
+	par->gdc[GDC_BIT_MASK] = 0xFF;
+
+	vga16fb_clock_chip(par, var->pixclock, info);
+
+	par->var.bits_per_pixel = 4;
+	par->var.grayscale = var->grayscale;
+	par->var.red.offset = par->var.green.offset = par->var.blue.offset = 
+	par->var.transp.offset = 0;
+	par->var.red.length = par->var.green.length = par->var.blue.length =
+		(info->isVGA) ? 6 : 2;
+	par->var.transp.length = 0;
+	par->var.nonstd = 0;
+	par->var.activate = FB_ACTIVATE_NOW;
+	par->var.height = -1;
+	par->var.width = -1;
+	par->var.accel_flags = 0;
+	
+	return 0;
+}
+#undef FAIL
+
+static int vga16fb_set_par(const struct vga16fb_par *par,
+			   struct vga16fb_info *info)
+{
+	int i;
+
+	outb(inb(MIS_R) | 0x01, MIS_W);
+
+	/* Enable graphics register modification */
+	if (!info->isVGA) {
+		outb(0x00, GRA_E0);
+		outb(0x01, GRA_E1);
+	}
+	
+	/* update misc output register */
+	outb(par->misc, MIS_W);
+	
+	/* synchronous reset on */
+	outb(0x00, SEQ_I);
+	outb(0x01, SEQ_D);
+	
+	/* write sequencer registers */
+	outb(1, SEQ_I);
+	outb(par->seq[1] | 0x20, SEQ_D);
+	for (i = 2; i < SEQ_C; i++) {
+		outb(i, SEQ_I);
+		outb(par->seq[i], SEQ_D);
+	}
+	
+	/* synchronous reset off */
+	outb(0x00, SEQ_I);
+	outb(0x03, SEQ_D);
+	
+	/* deprotect CRT registers 0-7 */
+	outb(0x11, CRT_IC);
+	outb(par->crtc[0x11], CRT_DC);
+
+	/* write CRT registers */
+	for (i = 0; i < CRTC_REGS; i++) {
+		outb(i, CRT_IC);
+		outb(par->crtc[i], CRT_DC);
+	}
+	
+	/* write graphics controller registers */
+	for (i = 0; i < GRA_C; i++) {
+		outb(i, GRA_I);
+		outb(par->gdc[i], GRA_D);
+	}
+	
+	/* write attribute controller registers */
+	for (i = 0; i < ATT_C; i++) {
+		inb_p(IS1_RC);		/* reset flip-flop */
+		outb_p(i, ATT_IW);
+		outb_p(par->atc[i], ATT_IW);
+	}
+
+	/* Wait for screen to stabilize. */
+	mdelay(50);
+
+	outb(0x01, SEQ_I);
+	outb(par->seq[1], SEQ_D);
+
+	inb(IS1_RC);
+	outb(0x20, ATT_IW);
+	
+	return 0;
+}
+
+static int vga16fb_set_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *fb)
+{
+	struct vga16fb_info *info = (struct vga16fb_info*)fb;
+	struct vga16fb_par par;
+	struct display *display;
+	int err;
+
+	if (con < 0)
+		display = fb->disp;
+	else
+		display = fb_display + con;
+	if ((err = vga16fb_decode_var(var, &par, info)) != 0)
+		return err;
+	vga16fb_encode_var(var, &par, info);
+	
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
+		return 0;
+
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+		u32 oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+		oldxres = display->var.xres;
+		oldyres = display->var.yres;
+		oldvxres = display->var.xres_virtual;
+		oldvyres = display->var.yres_virtual;
+		oldbpp = display->var.bits_per_pixel;
+
+		display->var = *var;
+
+		if (oldxres != var->xres || oldyres != var->yres ||
+		    oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+		    oldbpp != var->bits_per_pixel) {
+			vga16fb_set_disp(con, info);
+			if (info->fb_info.changevar)
+				info->fb_info.changevar(con);
+		}
+		if (con == currcon)
+			vga16fb_set_par(&par, info);
+	}
+
+	return 0;
+}
+
+static void ega16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+{
+	static unsigned char map[] = { 000, 001, 010, 011 };
+	int val;
+	
+	val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
+	inb_p(0x3DA);   /* ! 0x3BA */
+	outb_p(regno, 0x3C0);
+	outb_p(val, 0x3C0);
+	inb_p(0x3DA);   /* some clones need it */
+	outb_p(0x20, 0x3C0); /* unblank screen */
+}
+
+static int vga16_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+			  unsigned *blue, unsigned *transp,
+			  struct fb_info *fb_info)
+{
+	/*
+	 *  Read a single color register and split it into colors/transparent.
+	 *  Return != 0 for invalid regno.
+	 */
+
+	if (regno >= 16)
+		return 1;
+
+	*red   = palette[regno].red;
+	*green = palette[regno].green;
+	*blue  = palette[regno].blue;
+	*transp = 0;
+	return 0;
+}
+
+static void vga16_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+{
+	outb(regno,       dac_reg);
+	outb(red   >> 10, dac_val);
+	outb(green >> 10, dac_val);
+	outb(blue  >> 10, dac_val);
+}
+
+static int vga16_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp,
+			  struct fb_info *fb_info)
+{
+	int gray;
+
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+	
+	if (regno >= 16)
+		return 1;
+
+	palette[regno].red   = red;
+	palette[regno].green = green;
+	palette[regno].blue  = blue;
+	
+	if (currcon < 0)
+		gray = disp.var.grayscale;
+	else
+		gray = fb_display[currcon].var.grayscale;
+	if (gray) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+	if (((struct vga16fb_info *) fb_info)->isVGA) 
+		vga16_setpalette(regno,red,green,blue);
+	else
+		ega16_setpalette(regno,red,green,blue);
+	
+	return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+	if (con != currcon)
+		return;
+	if (fb_display[con].cmap.len)
+		fb_set_cmap(&fb_display[con].cmap, 1, vga16_setcolreg, info);
+	else
+		fb_set_cmap(fb_default_cmap(16), 1, vga16_setcolreg,
+			    info);
+}
+
+static int vga16fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
+{
+	if (con == currcon) /* current console? */
+		return fb_get_cmap(cmap, kspc, vga16_getcolreg, info);
+	else if (fb_display[con].cmap.len) /* non default colormap? */
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+	else
+		fb_copy_cmap(fb_default_cmap(16),
+		     cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+static int vga16fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
+{
+	int err;
+
+	if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+		err = fb_alloc_cmap(&fb_display[con].cmap,16,0);
+		if (err)
+			return err;
+	}
+	if (con == currcon)			/* current console? */
+		return fb_set_cmap(cmap, kspc, vga16_setcolreg, info);
+	else
+		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+	return 0;
+}
+
+static int vga16fb_pan_display(struct fb_var_screeninfo *var, int con,
+			       struct fb_info *info) 
+{
+	if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual ||
+	    var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+		return -EINVAL;
+	if (con == currcon)
+		vga16fb_pan_var(info, var);
+	fb_display[con].var.xoffset = var->xoffset;
+	fb_display[con].var.yoffset = var->yoffset;
+	fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+static int vga16fb_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg, int con,
+		       struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static struct fb_ops vga16fb_ops = {
+	vga16fb_open,
+	vga16fb_release,
+	vga16fb_get_fix,
+	vga16fb_get_var,
+	vga16fb_set_var,
+	vga16fb_get_cmap,
+	vga16fb_set_cmap,
+	vga16fb_pan_display,
+	vga16fb_ioctl
+};
+
+void vga16fb_setup(char *options, int *ints)
+{
+	char *this_opt;
+	
+	vga16fb.fb_info.fontname[0] = '\0';
+	
+	if (!options || !*options)
+		return;
+	
+	for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
+		if (!*this_opt) continue;
+		
+		if (!strncmp(this_opt, "font:", 5))
+			strcpy(vga16fb.fb_info.fontname, this_opt+5);
+	}
+}
+
+static int vga16fb_switch(int con, struct fb_info *fb)
+{
+	struct vga16fb_par par;
+	struct vga16fb_info *info = (struct vga16fb_info*)fb;
+
+	/* Do we have to save the colormap? */
+	if (fb_display[currcon].cmap.len)
+		fb_get_cmap(&fb_display[currcon].cmap, 1, vga16_getcolreg,
+			    fb);
+	
+	currcon = con;
+	vga16fb_decode_var(&fb_display[con].var, &par, info);
+	vga16fb_set_par(&par, info);
+	vga16fb_set_disp(con, info);
+
+	/* Install new colormap */
+	do_install_cmap(con, fb);
+/*	vga16fb_update_var(con, fb); */
+	return 1;
+}
+
+/* The following VESA blanking code is taken from vgacon.c.  The VGA
+   blanking code was originally by Huang shi chao, and modified by
+   Christoph Rimek (chrimek@toppoint.de) and todd j. derr
+   (tjd@barefoot.org) for Linux. */
+#define attrib_port	0x3c0
+#define seq_port_reg	0x3c4
+#define seq_port_val	0x3c5
+#define gr_port_reg	0x3ce
+#define gr_port_val	0x3cf
+#define video_misc_rd	0x3cc
+#define video_misc_wr	0x3c2
+#define vga_video_port_reg	0x3d4
+#define vga_video_port_val	0x3d5
+
+static void vga_vesa_blank(struct vga16fb_info *info, int mode)
+{
+	unsigned char SeqCtrlIndex;
+	unsigned char CrtCtrlIndex;
+	
+	cli();
+	SeqCtrlIndex = inb_p(seq_port_reg);
+	CrtCtrlIndex = inb_p(vga_video_port_reg);
+
+	/* save original values of VGA controller registers */
+	if(!info->vesa_blanked) {
+		info->vga_state.CrtMiscIO = inb_p(video_misc_rd);
+		sti();
+
+		outb_p(0x00,vga_video_port_reg);	/* HorizontalTotal */
+		info->vga_state.HorizontalTotal = inb_p(vga_video_port_val);
+		outb_p(0x01,vga_video_port_reg);	/* HorizDisplayEnd */
+		info->vga_state.HorizDisplayEnd = inb_p(vga_video_port_val);
+		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
+		info->vga_state.StartHorizRetrace = inb_p(vga_video_port_val);
+		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
+		info->vga_state.EndHorizRetrace = inb_p(vga_video_port_val);
+		outb_p(0x07,vga_video_port_reg);	/* Overflow */
+		info->vga_state.Overflow = inb_p(vga_video_port_val);
+		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
+		info->vga_state.StartVertRetrace = inb_p(vga_video_port_val);
+		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
+		info->vga_state.EndVertRetrace = inb_p(vga_video_port_val);
+		outb_p(0x17,vga_video_port_reg);	/* ModeControl */
+		info->vga_state.ModeControl = inb_p(vga_video_port_val);
+		outb_p(0x01,seq_port_reg);		/* ClockingMode */
+		info->vga_state.ClockingMode = inb_p(seq_port_val);
+	}
+
+	/* assure that video is enabled */
+	/* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */
+	cli();
+	outb_p(0x01,seq_port_reg);
+	outb_p(info->vga_state.ClockingMode | 0x20,seq_port_val);
+
+	/* test for vertical retrace in process.... */
+	if ((info->vga_state.CrtMiscIO & 0x80) == 0x80)
+		outb_p(info->vga_state.CrtMiscIO & 0xef,video_misc_wr);
+
+	/*
+	 * Set <End of vertical retrace> to minimum (0) and
+	 * <Start of vertical Retrace> to maximum (incl. overflow)
+	 * Result: turn off vertical sync (VSync) pulse.
+	 */
+	if (mode & VESA_VSYNC_SUSPEND) {
+		outb_p(0x10,vga_video_port_reg);	/* StartVertRetrace */
+		outb_p(0xff,vga_video_port_val); 	/* maximum value */
+		outb_p(0x11,vga_video_port_reg);	/* EndVertRetrace */
+		outb_p(0x40,vga_video_port_val);	/* minimum (bits 0..3)  */
+		outb_p(0x07,vga_video_port_reg);	/* Overflow */
+		outb_p(info->vga_state.Overflow | 0x84,vga_video_port_val); /* bits 9,10 of vert. retrace */
+	}
+
+	if (mode & VESA_HSYNC_SUSPEND) {
+		/*
+		 * Set <End of horizontal retrace> to minimum (0) and
+		 *  <Start of horizontal Retrace> to maximum
+		 * Result: turn off horizontal sync (HSync) pulse.
+		 */
+		outb_p(0x04,vga_video_port_reg);	/* StartHorizRetrace */
+		outb_p(0xff,vga_video_port_val);	/* maximum */
+		outb_p(0x05,vga_video_port_reg);	/* EndHorizRetrace */
+		outb_p(0x00,vga_video_port_val);	/* minimum (0) */
+	}
+
+	/* restore both index registers */
+	outb_p(SeqCtrlIndex,seq_port_reg);
+	outb_p(CrtCtrlIndex,vga_video_port_reg);
+	sti();
+}
+
+static void vga_vesa_unblank(struct vga16fb_info *info)
+{
+	unsigned char SeqCtrlIndex;
+	unsigned char CrtCtrlIndex;
+	
+	cli();
+	SeqCtrlIndex = inb_p(seq_port_reg);
+	CrtCtrlIndex = inb_p(vga_video_port_reg);
+
+	/* restore original values of VGA controller registers */
+	outb_p(info->vga_state.CrtMiscIO,video_misc_wr);
+
+	outb_p(0x00,vga_video_port_reg);		/* HorizontalTotal */
+	outb_p(info->vga_state.HorizontalTotal,vga_video_port_val);
+	outb_p(0x01,vga_video_port_reg);		/* HorizDisplayEnd */
+	outb_p(info->vga_state.HorizDisplayEnd,vga_video_port_val);
+	outb_p(0x04,vga_video_port_reg);		/* StartHorizRetrace */
+	outb_p(info->vga_state.StartHorizRetrace,vga_video_port_val);
+	outb_p(0x05,vga_video_port_reg);		/* EndHorizRetrace */
+	outb_p(info->vga_state.EndHorizRetrace,vga_video_port_val);
+	outb_p(0x07,vga_video_port_reg);		/* Overflow */
+	outb_p(info->vga_state.Overflow,vga_video_port_val);
+	outb_p(0x10,vga_video_port_reg);		/* StartVertRetrace */
+	outb_p(info->vga_state.StartVertRetrace,vga_video_port_val);
+	outb_p(0x11,vga_video_port_reg);		/* EndVertRetrace */
+	outb_p(info->vga_state.EndVertRetrace,vga_video_port_val);
+	outb_p(0x17,vga_video_port_reg);		/* ModeControl */
+	outb_p(info->vga_state.ModeControl,vga_video_port_val);
+	outb_p(0x01,seq_port_reg);		/* ClockingMode */
+	outb_p(info->vga_state.ClockingMode,seq_port_val);
+
+	/* restore index/control registers */
+	outb_p(SeqCtrlIndex,seq_port_reg);
+	outb_p(CrtCtrlIndex,vga_video_port_reg);
+	sti();
+}
+
+static void vga_pal_blank(void)
+{
+	int i;
+
+	for (i=0; i<16; i++) {
+		outb_p (i, dac_reg) ;
+		outb_p (0, dac_val) ;
+		outb_p (0, dac_val) ;
+		outb_p (0, dac_val) ;
+	}
+}
+
+/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
+static void vga16fb_blank(int blank, struct fb_info *fb_info)
+{
+	struct vga16fb_info *info = (struct vga16fb_info*)fb_info;
+
+	switch (blank) {
+	case 0:				/* Unblank */
+		if (info->vesa_blanked) {
+			vga_vesa_unblank(info);
+			info->vesa_blanked = 0;
+		}
+		if (info->palette_blanked) {
+			do_install_cmap(currcon, fb_info);
+			info->palette_blanked = 0;
+		}
+		break;
+	case 1:				/* blank */
+		vga_pal_blank();
+		info->palette_blanked = 1;
+		break;
+	default:			/* VESA blanking */
+		vga_vesa_blank(info, blank-1);
+		info->vesa_blanked = 1;
+		break;
+	}
+}
+
+__initfunc(void vga16fb_init(void))
+{
+	int i,j;
+
+	printk("vga16fb: initializing\n");
+
+        vga16fb.video_vbase = ioremap((unsigned long)0xa0000, 65536);
+	printk("vga16fb: mapped to 0x%p\n", vga16fb.video_vbase);
+
+	vga16fb.isVGA = ORIG_VIDEO_ISVGA;
+	vga16fb.palette_blanked = 0;
+	vga16fb.vesa_blanked = 0;
+
+	i = vga16fb.isVGA? 6 : 2;
+	
+	vga16fb_defined.red.length   = i;
+	vga16fb_defined.green.length = i;
+	vga16fb_defined.blue.length  = i;	
+	for(i = 0; i < 16; i++) {
+		j = color_table[i];
+		palette[i].red   = default_red[j];
+		palette[i].green = default_grn[j];
+		palette[i].blue  = default_blu[j];
+	}
+	if (vga16fb.isVGA)
+		request_region(0x3c0, 32, "vga+");
+	else
+		request_region(0x3C0, 32, "ega");
+
+	disp.var = vga16fb_defined;
+
+	/* name should not depend on EGA/VGA */
+	strcpy(vga16fb.fb_info.modename, "VGA16 VGA");
+	vga16fb.fb_info.changevar = NULL;
+	vga16fb.fb_info.node = -1;
+	vga16fb.fb_info.fbops = &vga16fb_ops;
+	vga16fb.fb_info.disp=&disp;
+	vga16fb.fb_info.switch_con=&vga16fb_switch;
+	vga16fb.fb_info.updatevar=&vga16fb_update_var;
+	vga16fb.fb_info.blank=&vga16fb_blank;
+	vga16fb.fb_info.flags=FBINFO_FLAG_DEFAULT;
+	vga16fb_set_disp(-1, &vga16fb);
+
+	if (register_framebuffer(&vga16fb.fb_info)<0)
+		return;
+
+	printk("fb%d: %s frame buffer device\n",
+	       GET_FB_IDX(vga16fb.fb_info.node), vga16fb.fb_info.modename);
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/drivers/video/vga_font.c linux.pre11.3/drivers/video/vga_font.c
--- linux.vanilla/drivers/video/vga_font.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/drivers/video/vga_font.c	Mon Jul 19 23:28:22 1999
@@ -0,0 +1,352 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/modversions.h>
+
+
+#define cmapsz 8192
+
+unsigned char vga_font[cmapsz] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 
+0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, 
+0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 
+0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 
+0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 
+0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 
+0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, 
+0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 
+0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, 
+0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 
+0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, 
+0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 
+0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, 
+0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 
+0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 
+0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 
+0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 
+0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 
+0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 
+0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 
+0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 
+0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 
+0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 
+0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 
+0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 
+0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 
+0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 
+0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, 
+0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 
+0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, 
+0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 
+0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
+0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 
+0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, 
+0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 
+0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 
+0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 
+0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 
+0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 
+0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 
+0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 
+0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 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, 0xff, 0x00, 0x00, 
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, 
+0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 
+0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, 
+0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, 
+0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 
+0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 
+0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 
+0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 
+0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 
+0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 
+0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 
+0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 
+0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 
+0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, 
+0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 
+0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, 
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 
+0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 
+0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 
+0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 
+0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, 
+0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 
+0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 
+0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, 
+0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 
+0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 
+0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 
+0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 
+0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 
+0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 
+0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 
+0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 
+0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 
+0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, 
+0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 
+0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 
+0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 
+0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 
+0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 
+0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 
+0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 
+0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 
+0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 
+0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 
+0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 
+0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, 
+0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 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, 
+};
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/Config.in linux.pre11.3/fs/Config.in
--- linux.vanilla/fs/Config.in	Tue Jun 15 16:49:52 1999
+++ linux.pre11.3/fs/Config.in	Mon Jul 19 23:26:27 1999
@@ -54,7 +54,12 @@
 if [ "$CONFIG_UFS_FS" != "n" ]; then
   bool '   UFS filesystem write support (experimental)' CONFIG_UFS_FS_WRITE
 fi
-
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'SGI EFS filesystem support (read only) (experimental)' CONFIG_EFS_FS
+  if [ "$CONFIG_EFS_FS" != "n" ]; then
+    define_bool CONFIG_SGI_PARTITION y
+  fi
+fi
 
 if [ "$CONFIG_NET" = "y" ]; then
 
@@ -69,9 +74,9 @@
   fi
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
     tristate 'NFS server support' CONFIG_NFSD
-    if [ "$CONFIG_NFSD" != "n" ]; then
-      bool '   Emulate SUN NFS server' CONFIG_NFSD_SUN
-    fi
+  fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFSD" != "n" ]; then
+    bool '   Emulate SUN NFS server' CONFIG_NFSD_SUN
   fi
   if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
     define_bool CONFIG_SUNRPC y
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/Makefile linux.pre11.3/fs/Makefile
--- linux.vanilla/fs/Makefile	Sun Nov  8 15:06:31 1998
+++ linux.pre11.3/fs/Makefile	Mon Jul 19 23:26:24 1999
@@ -17,8 +17,8 @@
 
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
-		hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd nfsd \
-		nls devpts adfs qnx4
+		hpfs sysv smbfs ncpfs ufs affs romfs autofs hfs lockd \
+		nfsd nls devpts adfs qnx4 efs
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
@@ -212,6 +212,14 @@
 else
   ifeq ($(CONFIG_QNX4FS_FS),m)
   MOD_SUB_DIRS += qnx4
+  endif
+endif
+
+ifeq ($(CONFIG_EFS_FS),y)
+SUB_DIRS += efs
+else
+  ifeq ($(CONFIG_EFS_FS),m)
+  MOD_SUB_DIRS += efs
   endif
 endif
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/buffer.c linux.pre11.3/fs/buffer.c
--- linux.vanilla/fs/buffer.c	Fri May 28 00:32:59 1999
+++ linux.pre11.3/fs/buffer.c	Tue Jul 20 00:30:55 1999
@@ -100,7 +100,7 @@
 				each time we call refill */
 		int nref_dirt; /* Dirty buffer threshold for activating bdflush
 				  when trying to refill buffers. */
-		int dummy1;    /* unused */
+		int interval; /* jiffies delay between kupdate flushes */
 		int age_buffer;  /* Time for normal buffer to age before 
 				    we flush it */
 		int age_super;  /* Time for superblock to age before we 
@@ -109,11 +109,11 @@
 		int dummy3;    /* unused */
 	} b_un;
 	unsigned int data[N_PARAM];
-} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
+} bdf_prm = {{40, 500, 64, 256, 5*HZ, 30*HZ, 5*HZ, 1884, 2}};
 
 /* These are the min and max parameter values that we will allow to be assigned */
 int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   1*HZ,   1*HZ, 1, 1};
-int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 600*HZ, 600*HZ, 2047, 5};
+int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,60*HZ, 600*HZ, 600*HZ, 2047, 5};
 
 void wakeup_bdflush(int);
 
@@ -1663,8 +1663,9 @@
 		goto out;
 
 	if (func == 1) {
-		 error = sync_old_buffers();
-		 goto out;
+		unlock_kernel();
+		/* do_exit directly and let kupdate to do its work alone. */
+		do_exit(0);
 	}
 
 	/* Basically func 1 means read param 1, 2 means write param 1, etc */
@@ -1823,5 +1824,44 @@
 
 			interruptible_sleep_on(&bdflush_wait);
 		}
+	}
+}
+
+/*
+ * This is the kernel update daemon. It was used to live in userspace
+ * but since it's need to run safely we want it unkillable by mistake.
+ * You don't need to change your userspace configuration since
+ * the userspace `update` will do_exit(0) at the first sys_bdflush().
+ */
+int kupdate(void * unused) 
+{
+	struct task_struct * tsk = current;
+	int interval;
+
+	tsk->session = 1;
+	tsk->pgrp = 1;
+	strcpy(tsk->comm, "kupdate");
+	sigfillset(&tsk->blocked);
+	/* sigcont will wakeup kupdate after setting interval to 0 */
+	sigdelset(&tsk->blocked, SIGCONT);
+
+	lock_kernel();
+
+	for (;;) {
+		interval = bdf_prm.b_un.interval;
+		if (interval)
+		{
+			tsk->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(interval);
+		}
+		else
+		{
+			tsk->state = TASK_STOPPED;
+			schedule(); /* wait for SIGCONT */
+		}
+#ifdef DEBUG
+		printk("kupdate() activated...\n");
+#endif
+		sync_old_buffers();
 	}
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/cache.c linux.pre11.3/fs/coda/cache.c
--- linux.vanilla/fs/coda/cache.c	Tue Dec 22 23:20:00 1998
+++ linux.pre11.3/fs/coda/cache.c	Mon Jul 19 23:26:35 1999
@@ -326,8 +326,8 @@
 	while ( alias != &inode->i_dentry ) {
 		alias_de = list_entry(alias, struct dentry, d_alias);
 		coda_flag_children(alias_de, flag);
-		shrink_dcache_parent(alias_de);
 		alias = alias->next;
+		shrink_dcache_parent(alias_de);
 	}
 
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/cnode.c linux.pre11.3/fs/coda/cnode.c
--- linux.vanilla/fs/coda/cnode.c	Tue Jan 26 09:44:22 1999
+++ linux.pre11.3/fs/coda/cnode.c	Mon Jul 19 23:26:35 1999
@@ -13,6 +13,17 @@
 extern int coda_debug;
 extern int coda_print_entry;
 
+inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
+{
+	if (fid1->Vnode != fid2->Vnode)
+		return 0;
+	if (fid1->Volume != fid2->Volume)
+		return 0;
+	if (fid1->Unique != fid2->Unique)
+		return 0;
+	return 1;
+}
+
 /* cnode.c */
 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
 {
@@ -83,8 +94,14 @@
         }
 
 	cnp = ITOC(*inode);
-       if  ( cnp->c_magic != 0 ) {
-               printk("coda_cnode make on initialized inode %ld, old %s new
+	/* see if we've got it already */
+	if  ( cnp->c_magic != 0 && coda_fideq(fid, &cnp->c_fid)) {
+		return 0;
+	}
+
+	/* not fresh: collision */
+	if  ( cnp->c_magic != 0 ) {
+               printk("coda_cnode_make on initialized inode %ld, old %s new
 %s!\n",
                       (*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid));
                iput(*inode);
@@ -118,14 +135,6 @@
         return 0;
 }
 
-inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
-{
-	int eq;
-	eq =   ( (fid1->Vnode == fid2->Vnode) &&
-		 (fid1->Volume == fid2->Volume) &&
-		 (fid1->Unique == fid2->Unique) );
-	return eq;
-}
 
 void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, 
 		      struct ViceFid *newfid)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/coda_linux.c linux.pre11.3/fs/coda/coda_linux.c
--- linux.vanilla/fs/coda/coda_linux.c	Tue Jan 26 09:44:22 1999
+++ linux.pre11.3/fs/coda/coda_linux.c	Mon Jul 19 23:26:35 1999
@@ -215,6 +215,8 @@
         if (attr->va_ctime.tv_sec != -1)
 	        inode->i_ctime = attr->va_ctime.tv_sec;
 }
+
+
 /* 
  * BSD sets attributes that need not be modified to -1. 
  * Linux uses the valid field to indicate what should be
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/dir.c linux.pre11.3/fs/coda/dir.c
--- linux.vanilla/fs/coda/dir.c	Thu May 27 22:11:57 1999
+++ linux.pre11.3/fs/coda/dir.c	Mon Jul 19 23:26:35 1999
@@ -799,16 +799,16 @@
 
 	shrink_dcache_parent(de);
 
+	/* propagate for a flush */
+	if (cii->c_flags & C_FLUSH) 
+		coda_flag_inode_children(inode, C_FLUSH);
+
 	if (de->d_count > 1) {
 		/* pretend it's valid, but don't change the flags */
 		CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n",
 		       de->d_inode->i_ino, coda_f2s(&cii->c_fid));
 		return 1;
 	}
-
-	/* propagate for a flush */
-	if (cii->c_flags & C_FLUSH) 
-		coda_flag_inode_children(inode, C_FLUSH);
 
 	/* clear the flags. */
 	cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/inode.c linux.pre11.3/fs/coda/inode.c
--- linux.vanilla/fs/coda/inode.c	Tue Jun 15 16:49:52 1999
+++ linux.pre11.3/fs/coda/inode.c	Mon Jul 19 23:26:35 1999
@@ -75,6 +75,9 @@
 
         if ( sbi->sbi_sb ) {
 		printk("Already mounted\n");
+		unlock_super(sb);
+		EXIT;  
+		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 
@@ -98,7 +101,6 @@
 	        printk("coda_read_super: coda_get_rootfid failed with %d\n",
 		       error);
 		sb->s_dev = 0;
-	        unlock_super(sb);
 		goto error;
 	}	  
 	printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
@@ -108,7 +110,6 @@
         if ( error || !root ) {
 	    printk("Failure of coda_cnode_make for root: error %d\n", error);
 	    sb->s_dev = 0;
-	    unlock_super(sb);
 	    goto error;
 	} 
 
@@ -121,6 +122,7 @@
         return sb;
 
  error:
+	unlock_super(sb);
 	EXIT;  
 	MOD_DEC_USE_COUNT;
 	if (sbi) {
@@ -145,7 +147,6 @@
         sb->s_dev = 0;
 	coda_cache_clear_all(sb);
 	sb_info = coda_sbp(sb);
-/*	sb_info->sbi_vcomm->vc_inuse = 0; You can not do this: psdev_release would see usagecount == 0 and would refuse to decrease MOD_USE_COUNT --pavel */ 
 	coda_super_info.sbi_sb = NULL;
 	printk("Coda: Bye bye.\n");
 	memset(sb_info, 0, sizeof(* sb_info));
@@ -209,7 +210,7 @@
 	EXIT;
 }
 
-static int  coda_notify_change(struct dentry *de, struct iattr *iattr)
+static int coda_notify_change(struct dentry *de, struct iattr *iattr)
 {
 	struct inode *inode = de->d_inode;
         struct coda_inode_info *cii;
@@ -238,21 +239,32 @@
         return error;
 }
 
-/*  we need _something_ for this routine. Let's mimic AFS */
 static int coda_statfs(struct super_block *sb, struct statfs *buf, 
 		       int bufsiz)
 {
 	struct statfs tmp;
+	int error;
+
+	memset(&tmp, 0, sizeof(struct statfs));
 
+	error = venus_statfs(sb, &tmp);
+
+	if (error) {
+		/* fake something like AFS does */
+		tmp.f_blocks = 9000000;
+		tmp.f_bfree  = 9000000;
+		tmp.f_bavail = 9000000;
+		tmp.f_files  = 9000000;
+		tmp.f_ffree  = 9000000;
+	}
+
+	/* and fill in the rest */
 	tmp.f_type = CODA_SUPER_MAGIC;
 	tmp.f_bsize = 1024;
-	tmp.f_blocks = 9000000;
-	tmp.f_bfree = 9000000;
-	tmp.f_bavail = 9000000 ;
-	tmp.f_files = 9000000;
-	tmp.f_ffree = 9000000;
-	tmp.f_namelen = 0;
+	tmp.f_namelen = CODA_MAXNAMLEN;
+
 	copy_to_user(buf, &tmp, bufsiz);
+
 	return 0; 
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/sysctl.c linux.pre11.3/fs/coda/sysctl.c
--- linux.vanilla/fs/coda/sysctl.c	Tue Feb 23 14:21:34 1999
+++ linux.pre11.3/fs/coda/sysctl.c	Mon Jul 19 23:26:35 1999
@@ -71,6 +71,7 @@
 struct coda_cache_inv_stats	coda_cache_inv_stat;
 struct coda_upcall_stats_entry  coda_upcall_stat[CODA_NCALLS];
 struct coda_upcallstats         coda_callstats;
+int                             coda_upcall_timestamping = 0;
 
 /* keep this in sync with coda.h! */
 char *coda_upcall_names[] = {
@@ -103,9 +104,12 @@
 	"purgeuser   ",   /* 26 */
 	"zapfile     ",   /* 27 */
 	"zapdir      ",   /* 28 */
-	"zapvnode    ",   /* 28 */
+	"noop2       ",   /* 29 */
 	"purgefid    ",   /* 30 */
-	"open_by_path"    /* 31 */
+	"open_by_path",   /* 31 */
+	"resolve     ",   /* 32 */
+	"reintegrate ",   /* 33 */
+	"statfs      "    /* 34 */
 };
 
 
@@ -133,8 +137,7 @@
 void do_time_stats( struct coda_upcall_stats_entry * pentry, 
 		    unsigned long runtime )
 {
-	
-	unsigned long time = runtime * 1000 /HZ;	/* time in ms */
+	unsigned long time = runtime;	/* time in us */
 	CDEBUG(D_SPECIAL, "time: %ld\n", time);
 
 	if ( pentry->count == 0 ) {
@@ -221,9 +224,12 @@
 {
 	if ( write ) {
 		reset_coda_vfs_stats();
+
+		filp->f_pos += *lenp;
+	} else {
+		*lenp = 0;
 	}
-  
-	*lenp = 0;
+
 	return 0;
 }
 
@@ -232,10 +238,19 @@
 				size_t * lenp )
 {
 	if ( write ) {
+        	if (*lenp > 0) {
+			char c;
+                	if (get_user(c, (char *)buffer))
+			       	return -EFAULT;
+                        coda_upcall_timestamping = (c == '1');
+                }
 		reset_coda_upcall_stats();
+
+		filp->f_pos += *lenp;
+	} else {
+		*lenp = 0;
 	}
-  
-	*lenp = 0;
+
 	return 0;
 }
 
@@ -245,9 +260,12 @@
 {
 	if ( write ) {
 		reset_coda_permission_stats();
+
+		filp->f_pos += *lenp;
+	} else {
+		*lenp = 0;
 	}
-  
-	*lenp = 0;
+
 	return 0;
 }
 
@@ -257,9 +275,12 @@
 {
 	if ( write ) {
 		reset_coda_cache_inv_stats();
+
+		filp->f_pos += *lenp;
+	} else {
+		*lenp = 0;
 	}
   
-	*lenp = 0;
 	return 0;
 }
 
@@ -347,12 +368,12 @@
 	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)");
+		len += sprintf( buffer + len,"%-79s\n",	"upcall              count       avg time(us)    std deviation(us)");
 	if ( offset < 320) 
-		len += sprintf( buffer + len,"%-79s\n",	"------\t\t    -----\t------------\t-----------------");
+		len += sprintf( buffer + len,"%-79s\n",	"------              -----       ------------    -----------------");
 	pos = 320; 
 	for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
-		tmplen += sprintf(tmpbuf,"%s\t%9d\t%10ld\t%10ld", 
+		tmplen += sprintf(tmpbuf,"%s    %9d       %10ld      %10ld", 
 				  coda_upcall_names[i],
 				  coda_upcall_stat[i].count, 
 				  get_time_average(&coda_upcall_stat[i]),
@@ -499,6 +520,7 @@
 		MOD_INC_USE_COUNT;
 	else
 		MOD_DEC_USE_COUNT;
+			
 }
 
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/coda/upcall.c linux.pre11.3/fs/coda/upcall.c
--- linux.vanilla/fs/coda/upcall.c	Wed Mar 24 10:55:24 1999
+++ linux.pre11.3/fs/coda/upcall.c	Mon Jul 19 23:26:35 1999
@@ -580,6 +580,33 @@
 	return error;
 }
 
+int venus_statfs(struct super_block *sb, struct statfs *sfs) 
+{ 
+        union inputArgs *inp;
+        union outputArgs *outp;
+        int insize, outsize, error;
+        
+	insize = max(INSIZE(statfs), OUTSIZE(statfs));
+	UPARG(CODA_STATFS);
+
+        error =  coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+	
+        if (!error) {
+		sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
+		sfs->f_bfree  = outp->coda_statfs.stat.f_bfree;
+		sfs->f_bavail = outp->coda_statfs.stat.f_bavail;
+		sfs->f_files  = outp->coda_statfs.stat.f_files;
+		sfs->f_ffree  = outp->coda_statfs.stat.f_ffree;
+	} else {
+		printk("coda_statfs: Venus returns: %d\n", error);
+	}
+
+        if (inp) CODA_FREE(inp, insize);
+        CDEBUG(D_INODE, " result %d\n",error);
+        EXIT;
+        return error;
+}
+
 /*
  * coda_upcall and coda_downcall routines.
  * 
@@ -588,10 +615,12 @@
 static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
 {
 	struct wait_queue	wait = { current, NULL };
-	unsigned long posttime;
+	struct timeval begin = { 0, 0 }, end = { 0, 0 };
 
 	vmp->uc_posttime = jiffies;
-	posttime = jiffies;
+
+	if (coda_upcall_timestamping)
+		do_gettimeofday(&begin);
 
 	add_wait_queue(&vmp->uc_sleep, &wait);
 	for (;;) {
@@ -620,9 +649,20 @@
 	remove_wait_queue(&vmp->uc_sleep, &wait);
 	current->state = TASK_RUNNING;
 
-	CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n", posttime, jiffies-posttime);
-	return 	(jiffies - posttime);
+	if (coda_upcall_timestamping && begin.tv_sec != 0) {
+		do_gettimeofday(&end);
+
+		if (end.tv_usec < begin.tv_usec) {
+			end.tv_usec += 1000000; end.tv_sec--;
+		}
+		end.tv_sec  -= begin.tv_sec;
+		end.tv_usec -= begin.tv_usec;
+	}
+
+	CDEBUG(D_SPECIAL, "begin: %ld.%06ld, elapsed: %ld.%06ld\n",
+		begin.tv_sec, begin.tv_usec, end.tv_sec, end.tv_usec);
 
+	return 	((end.tv_sec * 1000000) + end.tv_usec);
 }
 
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/dquot.c linux.pre11.3/fs/dquot.c
--- linux.vanilla/fs/dquot.c	Thu May 27 22:11:57 1999
+++ linux.pre11.3/fs/dquot.c	Mon Jul 19 23:26:26 1999
@@ -21,6 +21,17 @@
  *		Revised list management to avoid races
  *		-- Bill Hawes, <whawes@star.net>, 9/98
  *
+ *		Fixed races in dquot_transfer(), dqget() and dquot_alloc_...().
+ *		As the consequence the locking was moved from dquot_decr_...(),
+ *		dquot_incr_...() to calling functions.
+ *		invalidate_dquots() now writes modified dquots.
+ *		Serialized quota_off() and quota_on() for mount point.
+ *		Fixed a few bugs in grow_dquots. Fixed deadlock in write_dquot().
+ *		reset_dquot_ptrs() now traverse through inodes not filps.
+ *		add_dquot_ref() restarts after blocking
+ *		Added check for bogus uid and fixed check for group in quotactl.
+ *		Jan Kara, <jack@atrey.karlin.mff.cuni.cz>, 4-6/99
+ *
  * (C) Copyright 1994 - 1997 Marco van Wieringen 
  */
 
@@ -48,6 +59,10 @@
 int nr_dquots = 0, nr_free_dquots = 0;
 int max_dquots = NR_DQUOTS;
 
+/* We need this list for invalidating dquots... */
+extern struct list_head inode_in_use;
+extern spinlock_t inode_lock;
+
 static char quotamessage[MAX_QUOTA_MESSAGE];
 static char *quotatypes[] = INITQFNAMES;
 
@@ -166,7 +181,8 @@
 {
 	/* sanity check */
 	if (list_empty(&dquot->dq_free)) {
-		printk("remove_free_dquot: dquot not on free list??\n");
+		printk("remove_free_dquot: dquot not on the free list??\n");
+		return;		/* J.K. Just don't do anything */
 	}
 	list_del(&dquot->dq_free);
 	INIT_LIST_HEAD(&dquot->dq_free);
@@ -229,13 +245,25 @@
 static void write_dquot(struct dquot *dquot)
 {
 	short type = dquot->dq_type;
-	struct file *filp = dquot->dq_mnt->mnt_dquot.files[type];
+	struct file *filp;
 	mm_segment_t fs;
 	loff_t offset;
 	ssize_t ret;
+	struct dqblk data;
+	struct semaphore *sem = &dquot->dq_mnt->mnt_dquot.dqio_sem;
 
-	lock_dquot(dquot);
-	down(&dquot->dq_mnt->mnt_dquot.semaphore);
+	/*
+	 * We copy our data to preserve consistency when dquot is not locked.
+	 * We can't lock it because it can cause deadlocks - think about
+	 * growing the quota file...
+	 */
+	memcpy(&data, &dquot->dq_dqb, sizeof(struct dqblk));
+	down(sem);
+	if (!dquot->dq_mnt) {	/* Invalidated quota? */
+		up(sem);
+		return;
+	}
+	filp = dquot->dq_mnt->mnt_dquot.files[type];
 	offset = dqoff(dquot->dq_id);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
@@ -247,46 +275,51 @@
 	dquot->dq_flags &= ~DQ_MOD;
 	ret = 0;
 	if (filp)
-		ret = filp->f_op->write(filp, (char *)&dquot->dq_dqb, 
+		ret = filp->f_op->write(filp, (char *)&data, 
 					sizeof(struct dqblk), &offset);
 	if (ret != sizeof(struct dqblk))
 		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
 			kdevname(dquot->dq_dev));
 
-	up(&dquot->dq_mnt->mnt_dquot.semaphore);
+	/*
+	 * Be sure that anybody didn't invalidated the dquot in the mean time...
+	 * Nasty but I don't see other choice when we don't want to lock dquot.
+	 */
+	up(sem);
 	set_fs(fs);
 
-	unlock_dquot(dquot);
 	dqstats.writes++;
 }
 
 static void read_dquot(struct dquot *dquot)
 {
-	short type;
+	short type = dquot->dq_type;
 	struct file *filp;
 	mm_segment_t fs;
 	loff_t offset;
 
-	type = dquot->dq_type;
 	filp = dquot->dq_mnt->mnt_dquot.files[type];
-
 	if (filp == (struct file *)NULL)
 		return;
 
 	lock_dquot(dquot);
-	down(&dquot->dq_mnt->mnt_dquot.semaphore);
+	if (!dquot->dq_mnt)	/* Invalidated quota? */
+		goto out_lock;
+	/* Now we are sure filp is valid - the dquot isn't invalidated */
+	down(&dquot->dq_mnt->mnt_dquot.dqio_sem);
 	offset = dqoff(dquot->dq_id);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
 	filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset);
-	up(&dquot->dq_mnt->mnt_dquot.semaphore);
+	up(&dquot->dq_mnt->mnt_dquot.dqio_sem);
 	set_fs(fs);
 
 	if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
 	    dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
 		dquot->dq_flags |= DQ_FAKE;
-	unlock_dquot(dquot);
 	dqstats.reads++;
+out_lock:
+	unlock_dquot(dquot);
 }
 
 /*
@@ -306,10 +339,11 @@
 
 void invalidate_dquots(kdev_t dev, short type)
 {
-	struct dquot *dquot, *next = inuse_list;
+	struct dquot *dquot, *next;
 	int need_restart;
 
 restart:
+	next = inuse_list;	/* Here it is better. Otherwise the restart doesn't have any sense ;-) */
 	need_restart = 0;
 	while ((dquot = next) != NULL) {
 		next = dquot->dq_next;
@@ -317,6 +351,8 @@
 			continue;
 		if (dquot->dq_type != type)
 			continue;
+		if (!dquot->dq_mnt)	/* Already invalidated entry? */
+			continue;
 		if (dquot->dq_flags & DQ_LOCKED) {
 			__wait_on_dquot(dquot);
 
@@ -329,6 +365,18 @@
 				continue;
 			if (dquot->dq_type != type)
 				continue;
+			if (!dquot->dq_mnt)
+				continue;
+		}
+		/*
+		 *  Because inodes needn't to be the only holders of dquot
+		 *  the quota needn't to be written to disk. So we write it
+		 *  ourselves before discarding the data just for sure...
+		 */
+		if (dquot->dq_flags & DQ_MOD && dquot->dq_mnt)
+		{
+			write_dquot(dquot);
+			need_restart = 1;	/* We slept on IO */
 		}
 		clear_dquot(dquot);
 	}
@@ -342,10 +390,11 @@
 
 int sync_dquots(kdev_t dev, short type)
 {
-	struct dquot *dquot, *next = inuse_list;
+	struct dquot *dquot, *next;
 	int need_restart;
 
 restart:
+	next = inuse_list;
 	need_restart = 0;
 	while ((dquot = next) != NULL) {
 		next = dquot->dq_next;
@@ -353,6 +402,8 @@
 			continue;
                 if (type != -1 && dquot->dq_type != type)
 			continue;
+		if (!dquot->dq_mnt)	/* Invalidated? */
+			continue;
 		if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD)))
 			continue;
 
@@ -390,10 +441,11 @@
 	 * checking and doesn't need to be written. It's just an empty
 	 * dquot that is put back on to the freelist.
 	 */
-	if (dquot->dq_mnt != (struct vfsmount *)NULL) {
+	if (dquot->dq_mnt)
 		dqstats.drops++;
 we_slept:
-		wait_on_dquot(dquot);
+	wait_on_dquot(dquot);
+	if (dquot->dq_mnt) {
 		if (dquot->dq_count > 1) {
 			dquot->dq_count--;
 			return;
@@ -407,8 +459,16 @@
 	/* sanity check */
 	if (!list_empty(&dquot->dq_free)) {
 		printk("dqput: dquot already on free list??\n");
+		dquot->dq_count--;	/* J.K. Just decrementing use count seems safer... */
+		return;
 	}
 	if (--dquot->dq_count == 0) {
+		/* Sanity check. Locked quota without owner isn't good idea... */
+		if (dquot->dq_flags & DQ_LOCKED) {
+			printk(KERN_ERR "VFS: Locked quota to be put on the free list.\n");
+			dquot->dq_flags &= ~DQ_LOCKED;
+		}
+		dquot->dq_flags &= ~DQ_MOD;	/* Modified flag has no sense on free list */
  		/* Place at end of LRU free queue */
 		put_dquot_last(dquot);
 		wake_up(&dquot_wait);
@@ -417,23 +477,25 @@
 	return;
 }
 
-static void grow_dquots(void)
+static int grow_dquots(void)
 {
 	struct dquot *dquot;
-	int cnt = 32;
+	int cnt = 0;
 
-	while (cnt > 0) {
+	while (cnt < 32) {
 		dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
 		if(!dquot)
-			return;
+			return cnt;
 
 		nr_dquots++;
 		memset((caddr_t)dquot, 0, sizeof(struct dquot));
+		init_waitqueue(&dquot->dq_wait);
 		/* all dquots go on the inuse_list */
 		put_inuse(dquot);
 		put_dquot_head(dquot);
-		cnt--;
+		cnt++;
 	}
+	return cnt;
 }
 
 static struct dquot *find_best_candidate_weighted(void)
@@ -445,6 +507,7 @@
 
 	while ((tmp = tmp->next) != &free_dquots && --limit) {
 		dquot = list_entry(tmp, struct dquot, dq_free);
+		/* This should never happen... */
 		if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD))
 			continue;
 		myscore = dquot->dq_referenced;
@@ -480,20 +543,9 @@
 	if (!dquot)
 		goto pressure;
 got_it:
-	if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) {
-		wait_on_dquot(dquot);
-		if (dquot->dq_flags & DQ_MOD)
-		{
-			if(dquot->dq_mnt != (struct vfsmount *)NULL)
-				write_dquot(dquot);
-		}
-		/*
-		 * The dquot may be back in use now, so we
-		 * must recheck the free list.
-		 */
-		goto repeat;
-	}
-	/* sanity check ... */
+	/* Sanity checks */
+	if (dquot->dq_flags & DQ_LOCKED)
+		printk(KERN_ERR "VFS: Locked dquot on the free list\n");
 	if (dquot->dq_count != 0)
 		printk(KERN_ERR "VFS: free dquot count=%d\n", dquot->dq_count);
 
@@ -504,10 +556,9 @@
 	return dquot;
 
 pressure:
-	if (nr_dquots < max_dquots) {
-		grow_dquots();
-		goto repeat;
-	}
+	if (nr_dquots < max_dquots)
+		if (grow_dquots())
+			goto repeat;
 
 	dquot = find_best_candidate_weighted();
 	if (dquot)
@@ -534,7 +585,7 @@
 	struct dquot *dquot, *empty = NULL;
 	struct vfsmount *vfsmnt;
 
-        if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || is_enabled(vfsmnt, type) == 0)
+        if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || !is_enabled(vfsmnt, type))
                 return(NODQUOT);
 
 we_slept:
@@ -567,12 +618,46 @@
 	while (dquot_updating[hashent])
 		sleep_on(&update_wait);
 
+	if (!dquot->dq_mnt) {	/* Has somebody invalidated entry under us? */
+		/*
+		 *  Do it as if the quota was invalidated before we started
+		 */
+		dqput(dquot);
+		return NODQUOT;
+	}
 	dquot->dq_referenced++;
 	dqstats.lookups++;
 
 	return dquot;
 }
 
+static struct dquot *dqduplicate(struct dquot *dquot)
+{
+	if (dquot == NODQUOT || !dquot->dq_mnt)
+		return NODQUOT;
+	dquot->dq_count++;
+	wait_on_dquot(dquot);
+	if (!dquot->dq_mnt) {
+		dquot->dq_count--;
+		return NODQUOT;
+	}
+	return dquot;
+}
+
+static int dqinit_needed(struct inode *inode, short type)
+{
+	int cnt;
+
+        if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
+                return 0;
+	if (type != -1)
+		return inode->i_dquot[type] == NODQUOT;
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (inode->i_dquot[cnt] == NODQUOT)
+			return 1;
+	return 0;
+}
+
 static void add_dquot_ref(kdev_t dev, short type)
 {
 	struct super_block *sb = get_super(dev);
@@ -582,6 +667,7 @@
 	if (!sb || !sb->dq_op)
 		return;	/* nothing to do */
 
+restart:
 	for (filp = inuse_filps; filp; filp = filp->f_next) {
 		if (!filp->f_dentry)
 			continue;
@@ -590,79 +676,97 @@
 		inode = filp->f_dentry->d_inode;
 		if (!inode)
 			continue;
-		/* N.B. race problem -- filp could become unused */
-		if (filp->f_mode & FMODE_WRITE) {
+		/* Didn't we already initialized this inode? */
+		if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
 			sb->dq_op->initialize(inode, type);
 			inode->i_flags |= S_QUOTA;
+			/* as we may have blocked we had better restart */
+			goto restart;
 		}
 	}
 }
 
+static int reset_inode_dquot_ptrs(struct inode *inode, short type)
+{
+	struct dquot *dquot = inode->i_dquot[type];
+	int cnt;
+
+	inode->i_dquot[type] = NODQUOT;
+	/* any other quota in use? */
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+		if (inode->i_dquot[cnt] != NODQUOT)
+			goto put_it;
+	}
+	inode->i_flags &= ~S_QUOTA;
+put_it:
+	if (dquot != NODQUOT) {
+		spin_unlock(&inode_lock);	/* We may block so drop the lock... */
+		dqput(dquot);
+		spin_lock(&inode_lock);		/* And capture lock again */
+		/* we may have blocked ... */
+		return 1;
+	}
+	return 0;
+}
+
 static void reset_dquot_ptrs(kdev_t dev, short type)
 {
 	struct super_block *sb = get_super(dev);
-	struct file *filp;
 	struct inode *inode;
-	struct dquot *dquot;
-	int cnt;
+	struct list_head *act_head;
+	int need_list = 3;
 
 	if (!sb || !sb->dq_op)
 		return;	/* nothing to do */
 
-restart:
-	/* free any quota for unused dentries */
-	shrink_dcache_sb(sb);
+	/* We have to be protected against other CPUs */
+	spin_lock(&inode_lock);
 
-	for (filp = inuse_filps; filp; filp = filp->f_next) {
-		if (!filp->f_dentry)
-			continue;
-		if (filp->f_dentry->d_sb != sb)
-			continue;
-		inode = filp->f_dentry->d_inode;
-		if (!inode)
-			continue;
-		/*
-		 * Note: we restart after each blocking operation,
-		 * as the inuse_filps list may have changed.
-		 */
-		if (IS_QUOTAINIT(inode)) {
-			dquot = inode->i_dquot[type];
-			inode->i_dquot[type] = NODQUOT;
-			/* any other quota in use? */
-			for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-				if (inode->i_dquot[cnt] != NODQUOT)
-					goto put_it;
+	do {
+		if (need_list & 1) {
+			need_list &= ~1;
+	restart_in_use:
+			for (act_head = inode_in_use.next; act_head != &inode_in_use; act_head = act_head->next) {
+				inode = list_entry(act_head, struct inode, i_list);
+				if (inode->i_sb != sb || !IS_QUOTAINIT(inode))
+					continue;
+				if (reset_inode_dquot_ptrs(inode, type)) {
+					need_list |= 2;
+					goto restart_in_use;
+				}
 			}
-			inode->i_flags &= ~S_QUOTA;
-		put_it:
-			if (dquot != NODQUOT) {
-				dqput(dquot);
-				/* we may have blocked ... */
-				goto restart;
+		}
+		if (need_list & 2) {
+			need_list &= ~2;
+	restart_dirty:
+			for (act_head = sb->s_dirty.next; act_head != &sb->s_dirty; act_head = act_head->next) {
+				inode = list_entry(act_head, struct inode, i_list);
+				if (IS_QUOTAINIT(inode) && reset_inode_dquot_ptrs(inode, type)) {
+					need_list |= 1;
+					goto restart_dirty;
+				}
 			}
 		}
 	}
+	while (need_list);
+
+	spin_unlock(&inode_lock);
 }
 
 static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
 {
-	lock_dquot(dquot);
 	dquot->dq_curinodes += number;
 	dquot->dq_flags |= DQ_MOD;
-	unlock_dquot(dquot);
 }
 
 static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
 {
-	lock_dquot(dquot);
 	dquot->dq_curblocks += number;
 	dquot->dq_flags |= DQ_MOD;
-	unlock_dquot(dquot);
 }
 
 static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
 {
-	lock_dquot(dquot);
 	if (dquot->dq_curinodes > number)
 		dquot->dq_curinodes -= number;
 	else
@@ -671,12 +775,10 @@
 		dquot->dq_itime = (time_t) 0;
 	dquot->dq_flags &= ~DQ_INODES;
 	dquot->dq_flags |= DQ_MOD;
-	unlock_dquot(dquot);
 }
 
 static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
 {
-	lock_dquot(dquot);
 	if (dquot->dq_curblocks > number)
 		dquot->dq_curblocks -= number;
 	else
@@ -685,7 +787,6 @@
 		dquot->dq_btime = (time_t) 0;
 	dquot->dq_flags &= ~DQ_BLKS;
 	dquot->dq_flags |= DQ_MOD;
-	unlock_dquot(dquot);
 }
 
 static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot)
@@ -704,7 +805,7 @@
 	return(initiator == 0 && dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type] == 0);
 }
 
-static int check_idq(struct dquot *dquot, short type, u_long short inodes, uid_t initiator, 
+static int check_idq(struct dquot *dquot, short type, u_long inodes, uid_t initiator, 
 			struct tty_struct *tty)
 {
 	if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
@@ -869,9 +970,11 @@
 	if (dquot == NODQUOT)
 		goto out;
 
+	lock_dquot(dquot);	/* We must protect against invalidating the quota */
 	error = -EFAULT;
 	if (dqblk && !copy_to_user(dqblk, &dquot->dq_dqb, sizeof(struct dqblk)))
 		error = 0;
+	unlock_dquot(dquot);
 	dqput(dquot);
 out:
 	return error;
@@ -963,6 +1066,8 @@
 						break;
 				}
 				dquot = dqget(inode->i_dev, id, cnt);
+				if (dquot == NODQUOT)
+					continue;
 				if (inode->i_dquot[cnt] != NODQUOT) {
 					dqput(dquot);
 					continue;
@@ -1000,23 +1105,36 @@
 int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator, 
 			char warn)
 {
-	unsigned short cnt;
+	int cnt;
 	struct tty_struct *tty = current->tty;
+	struct dquot *dquot[MAXQUOTAS];
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] == NODQUOT)
+		dquot[cnt] = dqduplicate(inode->i_dquot[cnt]);
+		if (dquot[cnt] == NODQUOT)
 			continue;
-		if (check_bdq(inode->i_dquot[cnt], cnt, number, initiator, tty, warn))
-			return(NO_QUOTA);
+		lock_dquot(dquot[cnt]);
+		if (check_bdq(dquot[cnt], cnt, number, initiator, tty, warn))
+			goto put_all;
 	}
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] == NODQUOT)
+		if (dquot[cnt] == NODQUOT)
 			continue;
-		dquot_incr_blocks(inode->i_dquot[cnt], number);
+		dquot_incr_blocks(dquot[cnt], number);
+		unlock_dquot(dquot[cnt]);
+		dqput(dquot[cnt]);
 	}
 
-	return(QUOTA_OK);
+	return QUOTA_OK;
+put_all:
+	for (; cnt >= 0; cnt--) {
+		if (dquot[cnt] == NODQUOT)
+			continue;
+		unlock_dquot(dquot[cnt]);
+		dqput(dquot[cnt]);
+	}
+	return NO_QUOTA;
 }
 
 /*
@@ -1024,23 +1142,36 @@
  */
 int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator)
 {
-	unsigned short cnt;
+	int cnt;
 	struct tty_struct *tty = current->tty;
+	struct dquot *dquot[MAXQUOTAS];
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] == NODQUOT)
+		dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]);
+		if (dquot[cnt] == NODQUOT)
 			continue;
-		if (check_idq(inode->i_dquot[cnt], cnt, number, initiator, tty))
-			return(NO_QUOTA);
+		lock_dquot(dquot[cnt]);
+		if (check_idq(dquot[cnt], cnt, number, initiator, tty))
+			goto put_all;
 	}
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] == NODQUOT)
+		if (dquot[cnt] == NODQUOT)
 			continue;
-		dquot_incr_inodes(inode->i_dquot[cnt], number);
+		dquot_incr_inodes(dquot[cnt], number);
+		unlock_dquot(dquot[cnt]);
+		dqput(dquot[cnt]);
 	}
 
-	return(QUOTA_OK);
+	return QUOTA_OK;
+put_all:
+	for (; cnt >= 0; cnt--) {
+		if (dquot[cnt] == NODQUOT)
+			continue;
+		unlock_dquot(dquot[cnt]);
+		dqput(dquot[cnt]);
+	}
+	return NO_QUOTA;
 }
 
 /*
@@ -1049,11 +1180,14 @@
 void dquot_free_block(const struct inode *inode, unsigned long number)
 {
 	unsigned short cnt;
+	struct dquot *dquot;
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] == NODQUOT)
+		dquot = inode->i_dquot[cnt];
+		if (dquot == NODQUOT)
 			continue;
-		dquot_decr_blocks(inode->i_dquot[cnt], number);
+		wait_on_dquot(dquot);
+		dquot_decr_blocks(dquot, number);
 	}
 }
 
@@ -1063,11 +1197,14 @@
 void dquot_free_inode(const struct inode *inode, unsigned long number)
 {
 	unsigned short cnt;
+	struct dquot *dquot;
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-		if (inode->i_dquot[cnt] == NODQUOT)
+		dquot = inode->i_dquot[cnt];
+		if (dquot == NODQUOT)
 			continue;
-		dquot_decr_inodes(inode->i_dquot[cnt], number);
+		wait_on_dquot(dquot);
+		dquot_decr_inodes(dquot, number);
 	}
 }
 
@@ -1076,14 +1213,18 @@
  *
  * Note: this is a blocking operation.
  */
-int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid_t initiator)
+int dquot_transfer(struct dentry *dentry, struct iattr *iattr, uid_t initiator)
 {
+	struct inode *inode = dentry -> d_inode;
 	unsigned long blocks;
 	struct dquot *transfer_from[MAXQUOTAS];
 	struct dquot *transfer_to[MAXQUOTAS];
 	struct tty_struct *tty = current->tty;
 	short cnt, disc;
+	int error = -EDQUOT;
 
+	if (!inode)
+		return -ENOENT;
 	/*
 	 * Find out if this filesystem uses i_blocks.
 	 */
@@ -1107,27 +1248,60 @@
 			case USRQUOTA:
 				if (inode->i_uid == iattr->ia_uid)
 					continue;
-				transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_uid : inode->i_uid, cnt);
-				transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_uid : iattr->ia_uid, cnt);
+				/* We can get transfer_from from inode, can't we? */
+				transfer_from[cnt] = dqget(inode->i_dev, inode->i_uid, cnt);
+				transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_uid, cnt);
 				break;
 			case GRPQUOTA:
 				if (inode->i_gid == iattr->ia_gid)
 					continue;
-				transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_gid : inode->i_gid, cnt);
-				transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_gid : iattr->ia_gid, cnt);
+				transfer_from[cnt] = dqget(inode->i_dev, inode->i_gid, cnt);
+				transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_gid, cnt);
 				break;
 		}
 
-		if (check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
-		    check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) {
-			for (disc = 0; disc <= cnt; disc++) {
-				dqput(transfer_from[disc]);
-				dqput(transfer_to[disc]);
+		/* Something bad (eg. quotaoff) happened while we were sleeping? */
+		if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT)
+		{
+			if (transfer_from[cnt] != NODQUOT) {
+				dqput(transfer_from[cnt]);
+				transfer_from[cnt] = NODQUOT;
+			}
+			if (transfer_to[cnt] != NODQUOT) {
+				dqput(transfer_to[cnt]);
+				transfer_to[cnt] = NODQUOT;
 			}
-			return(NO_QUOTA);
+			continue;
+		}
+		/*
+		 *  We have to lock the quotas to prevent races...
+		 */
+		if (transfer_from[cnt] < transfer_to[cnt])
+		{
+                	lock_dquot(transfer_from[cnt]);
+			lock_dquot(transfer_to[cnt]);
+		}
+		else
+		{
+			lock_dquot(transfer_to[cnt]);
+			lock_dquot(transfer_from[cnt]);
+		}
+
+		/*
+		 * The entries might got invalidated while locking. The second
+		 * dqget() could block and so the first structure might got
+		 * invalidated or locked...
+		 */
+		if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt ||
+		    check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
+		    check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) {
+			cnt++;
+			goto put_all;
 		}
 	}
 
+	if ((error = notify_change(dentry, iattr)))
+		goto put_all; 
 	/*
 	 * Finally perform the needed transfer from transfer_from to transfer_to,
 	 * and release any pointers to dquots not needed anymore.
@@ -1139,28 +1313,39 @@
 		if (transfer_from[cnt] == NODQUOT && transfer_to[cnt] == NODQUOT)
 			continue;
 
-		if (transfer_from[cnt] != NODQUOT) {
-			dquot_decr_inodes(transfer_from[cnt], 1);
-			dquot_decr_blocks(transfer_from[cnt], blocks);
-		}
+		dquot_decr_inodes(transfer_from[cnt], 1);
+		dquot_decr_blocks(transfer_from[cnt], blocks);
 
-		if (transfer_to[cnt] != NODQUOT) {
-			dquot_incr_inodes(transfer_to[cnt], 1);
-			dquot_incr_blocks(transfer_to[cnt], blocks);
-		}
+		dquot_incr_inodes(transfer_to[cnt], 1);
+		dquot_incr_blocks(transfer_to[cnt], blocks);
 
+		unlock_dquot(transfer_from[cnt]);
+		dqput(transfer_from[cnt]);
 		if (inode->i_dquot[cnt] != NODQUOT) {
 			struct dquot *temp = inode->i_dquot[cnt];
 			inode->i_dquot[cnt] = transfer_to[cnt];
+			unlock_dquot(transfer_to[cnt]);
 			dqput(temp);
-			dqput(transfer_from[cnt]);
 		} else {
-			dqput(transfer_from[cnt]);
+			unlock_dquot(transfer_to[cnt]);
 			dqput(transfer_to[cnt]);
 		}
 	}
 
-	return(QUOTA_OK);
+	return 0;
+put_all:
+	for (disc = 0; disc < cnt; disc++) {
+		/* There should be none or both pointers set but... */
+		if (transfer_to[disc] != NODQUOT) {
+			unlock_dquot(transfer_to[disc]);
+			dqput(transfer_to[disc]);
+		}
+		if (transfer_from[disc] != NODQUOT) {
+			unlock_dquot(transfer_from[disc]);
+			dqput(transfer_from[disc]);
+		}
+	}
+	return error;
 }
 
 
@@ -1224,16 +1409,18 @@
 	struct vfsmount *vfsmnt;
 	struct file *filp;
 	short cnt;
+	int enabled = 0;
 
+	/* We don't need to search for vfsmnt each time - umount has to wait for us */
+	vfsmnt = lookup_vfsmnt(dev);
+	if (!vfsmnt || !vfsmnt->mnt_sb)
+		goto out;
+
+	/* We need to serialize quota_off() for device */
+	down(&vfsmnt->mnt_dquot.dqoff_sem);
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (type != -1 && cnt != type)
 			continue;
-
-		vfsmnt = lookup_vfsmnt(dev);
-		if (!vfsmnt)
-			goto out;
-                if (!vfsmnt->mnt_sb)
-			goto out;
 		if (!is_enabled(vfsmnt, cnt))
 			continue;
 		reset_enable_flags(vfsmnt, cnt);
@@ -1242,26 +1429,25 @@
 		reset_dquot_ptrs(dev, cnt);
 		invalidate_dquots(dev, cnt);
 
+		/* Wait for any pending IO - remove me as soon as invalidate is more polite */
+		down(&vfsmnt->mnt_dquot.dqio_sem);
 		filp = vfsmnt->mnt_dquot.files[cnt];
 		vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL;
 		vfsmnt->mnt_dquot.inode_expire[cnt] = 0;
 		vfsmnt->mnt_dquot.block_expire[cnt] = 0;
+		up(&vfsmnt->mnt_dquot.dqio_sem);
 		fput(filp);
-	}
+	}	
 
 	/*
 	 * Check whether any quota is still enabled,
 	 * and if not clear the dq_op pointer.
 	 */
-	vfsmnt = lookup_vfsmnt(dev);
-	if (vfsmnt && vfsmnt->mnt_sb) {
-		int enabled = 0;
-		for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-			enabled |= is_enabled(vfsmnt, cnt);
-		if (!enabled)
-			vfsmnt->mnt_sb->dq_op = NULL;
-	}
-
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		enabled |= is_enabled(vfsmnt, cnt);
+	if (!enabled)
+		vfsmnt->mnt_sb->dq_op = NULL;
+	up(&vfsmnt->mnt_dquot.dqoff_sem);
 out:
 	return(0);
 }
@@ -1282,47 +1468,51 @@
 
 	if (is_enabled(vfsmnt, type))
 		return -EBUSY;
-	mnt_dquot = &vfsmnt->mnt_dquot;
 
+	mnt_dquot = &vfsmnt->mnt_dquot;
+	down(&mnt_dquot->dqoff_sem);
 	tmp = getname(path);
 	error = PTR_ERR(tmp);
 	if (IS_ERR(tmp))
-		return error;
+		goto out_lock;
 
 	f = filp_open(tmp, O_RDWR, 0600);
 	putname(tmp);
-	if (IS_ERR(f))
-		return PTR_ERR(f);
 
-	/* sanity checks */
+	error = PTR_ERR(f);
+	if (IS_ERR(f))
+		goto out_lock;
 	error = -EIO;
 	if (!f->f_op->read && !f->f_op->write)
-		goto cleanup;
+		goto out_f;
 	inode = f->f_dentry->d_inode;
 	error = -EACCES;
 	if (!S_ISREG(inode->i_mode))
-		goto cleanup;
+		goto out_f;
 	error = -EINVAL;
 	if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0)
-		goto cleanup;
+		goto out_f;
 
-	/* OK, there we go */
 	set_enable_flags(vfsmnt, type);
 	mnt_dquot->files[type] = f;
 
 	dquot = dqget(dev, 0, type);
-	mnt_dquot->inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
-	mnt_dquot->block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
+	mnt_dquot->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;
+	mnt_dquot->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;
 	dqput(dquot);
 
 	vfsmnt->mnt_sb->dq_op = &dquot_operations;
 	add_dquot_ref(dev, type);
 
-	return(0);
+	up(&mnt_dquot->dqoff_sem);
+	return 0;
 
-cleanup:
-	fput(f);
-	return error;
+out_f:
+	filp_close(f, NULL);
+out_lock:
+	up(&mnt_dquot->dqoff_sem);
+
+	return error; 
 }
 
 /*
@@ -1343,6 +1533,9 @@
 
 	if ((u_int) type >= MAXQUOTAS)
 		goto out;
+	if (id & ~0xFFFF)
+		goto out;
+
 	ret = -EPERM;
 	switch (cmds) {
 		case Q_SYNC:
@@ -1350,7 +1543,7 @@
 			break;
 		case Q_GETQUOTA:
 			if (((type == USRQUOTA && current->euid != id) ||
-			     (type == GRPQUOTA && current->egid != id)) &&
+			     (type == GRPQUOTA && in_group_p(id))) &&
 			    !capable(CAP_SYS_RESOURCE))
 				goto out;
 			break;
@@ -1360,7 +1553,7 @@
 	}
 
 	ret = -EINVAL;
-	dev = 0;
+	dev = NODEV;
 	if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
 		mode_t mode;
 		struct dentry * dentry;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/Makefile linux.pre11.3/fs/efs/Makefile
--- linux.vanilla/fs/efs/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/Makefile	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux efs-filesystem routines.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+O_TARGET := efs.o
+O_OBJS   := super.o inode.o namei.o dir.o file.o symlink.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/dir.c linux.pre11.3/fs/efs/dir.c
--- linux.vanilla/fs/efs/dir.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/dir.c	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,139 @@
+/*
+ * dir.c
+ *
+ * Copyright (c) 1999 Al Smith
+ */
+
+#include <linux/efs_fs.h>
+
+static int efs_readdir(struct file *, void *, filldir_t);
+
+static struct file_operations efs_dir_operations = {
+	NULL,			/* lseek */
+	NULL,			/* read */
+	NULL,			/* write */
+	efs_readdir,		/* readdir */
+	NULL,			/* poll */
+	NULL,			/* ioctl */
+	NULL,			/* mmap */
+	NULL,			/* open */
+	NULL,			/* flush */
+	NULL,			/* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL			/* revalidate */
+};
+
+struct inode_operations efs_dir_inode_operations = {
+	&efs_dir_operations,	/* default directory file-ops */
+	NULL,			/* create */
+	efs_lookup,		/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	efs_bmap,		/* bmap */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* smap */
+};
+
+static int efs_readdir(struct file *filp, void *dirent, filldir_t filldir) {
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct buffer_head *bh;
+
+	struct efs_dir		*dirblock;
+	struct efs_dentry	*dirslot;
+	efs_ino_t		inodenum;
+	efs_block_t		block;
+	int			slot, namelen;
+	char			*nameptr;
+
+	if (!inode || !S_ISDIR(inode->i_mode))
+		return -EBADF;
+
+	if (inode->i_size & (EFS_DIRBSIZE-1))
+		printk(KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n");
+
+	/* work out where this entry can be found */
+	block = filp->f_pos >> EFS_DIRBSIZE_BITS;
+
+	/* each block contains at most 256 slots */
+	slot  = filp->f_pos & 0xff;
+
+	/* look at all blocks */
+	while (block < inode->i_blocks) {
+		/* read the dir block */
+		bh = bread(inode->i_dev, efs_bmap(inode, block), EFS_DIRBSIZE);
+
+		if (!bh) {
+			printk(KERN_ERR "EFS: readdir(): failed to read dir block %d\n", block);
+			break;
+		}
+
+		dirblock = (struct efs_dir *) bh->b_data; 
+
+		if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
+			printk(KERN_ERR "EFS: readdir(): invalid directory block\n");
+			brelse(bh);
+			break;
+		}
+
+		while (slot < dirblock->slots) {
+			if (dirblock->space[slot] == 0) {
+				slot++;
+				continue;
+			}
+
+			dirslot  = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
+
+			inodenum = be32_to_cpu(dirslot->inode);
+			namelen  = dirslot->namelen;
+			nameptr  = dirslot->name;
+
+#ifdef DEBUG
+			printk(KERN_DEBUG "EFS: readdir(): block %d slot %d/%d: inode %u, name \"%s\", namelen %u\n", block, slot, dirblock->slots-1, inodenum, nameptr, namelen);
+#endif
+			if (namelen > 0) {
+				/* found the next entry */
+				filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
+
+				/* copy filename and data in dirslot */
+				filldir(dirent, nameptr, namelen, filp->f_pos, inodenum);
+
+				/* sanity check */
+				if (nameptr - (char *) dirblock + namelen > EFS_DIRBSIZE) {
+					printk(KERN_WARNING "EFS: directory entry %d exceeds directory block\n", slot);
+					slot++;
+					continue;
+				}
+
+				/* store position of next slot */
+				if (++slot == dirblock->slots) {
+					slot = 0;
+					block++;
+				}
+				brelse(bh);
+				filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
+				return 0;
+			}
+			slot++;
+		}
+		brelse(bh);
+
+		slot = 0;
+		block++;
+	}
+
+	filp->f_pos = (block << EFS_DIRBSIZE_BITS) | slot;
+	return 0;
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/file.c linux.pre11.3/fs/efs/file.c
--- linux.vanilla/fs/efs/file.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/file.c	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,72 @@
+/*
+ * file.c
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
+ */
+
+#include <linux/efs_fs.h>
+
+static struct file_operations efs_file_operations = {
+	NULL,			/* lseek */
+	generic_file_read,	/* read */
+	NULL,			/* write */
+	NULL,			/* readdir */
+	NULL,			/* poll */
+	NULL,			/* ioctl */
+	generic_file_mmap,	/* mmap */
+	NULL,			/* open */
+	NULL,			/* flush */
+	NULL,			/* release */
+	NULL,			/* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL			/* revalidate */
+};
+
+struct inode_operations efs_file_inode_operations = {
+	&efs_file_operations,	/* default file operations */
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	NULL,			/* readlink */
+	NULL,			/* follow_link */
+	generic_readpage,	/* readpage */
+	NULL,			/* writepage */
+	efs_bmap,		/* bmap */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* smap */
+};
+ 
+int efs_bmap(struct inode *inode, efs_block_t block) {
+
+	if (block < 0) {
+		printk(KERN_WARNING "EFS: bmap(): block < 0\n");
+		return 0;
+	}
+
+	/* are we about to read past the end of a file ? */
+	if (!(block < inode->i_blocks)) {
+#ifdef DEBUG
+		/*
+		 * i have no idea why this happens as often as it does
+		 */
+		printk(KERN_WARNING "EFS: bmap(): block %d >= %ld (filesize %ld)\n",
+			block,
+			inode->i_blocks,
+			inode->i_size);
+#endif
+		return 0;
+	}
+
+	return efs_map_block(inode, block);
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/inode.c linux.pre11.3/fs/efs/inode.c
--- linux.vanilla/fs/efs/inode.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/inode.c	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,301 @@
+/*
+ * inode.c
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang,
+ *              and from work (c) 1998 Mike Shaver.
+ */
+
+#include <linux/efs_fs.h>
+#include <linux/efs_fs_sb.h>
+
+static inline void extent_copy(efs_extent *src, efs_extent *dst) {
+	/*
+	 * this is slightly evil. it doesn't just copy
+	 * efs_extent from src to dst, it also mangles
+	 * the bits so that dst ends up in cpu byte-order.
+	 */
+
+	dst->cooked.ex_magic  =  (unsigned int) src->raw[0];
+	dst->cooked.ex_bn     = ((unsigned int) src->raw[1] << 16) |
+				((unsigned int) src->raw[2] <<  8) |
+				((unsigned int) src->raw[3] <<  0);
+	dst->cooked.ex_length =  (unsigned int) src->raw[4];
+	dst->cooked.ex_offset = ((unsigned int) src->raw[5] << 16) |
+				((unsigned int) src->raw[6] <<  8) |
+				((unsigned int) src->raw[7] <<  0);
+	return;
+}
+
+void efs_read_inode(struct inode *inode) {
+	int i, inode_index;
+	dev_t device;
+	struct buffer_head *bh;
+	struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
+	struct efs_inode_info *in = INODE_INFO(inode);
+	efs_block_t block, offset;
+	struct efs_dinode *efs_inode;
+  
+	/*
+	** EFS layout:
+	**
+	** |   cylinder group    |   cylinder group    |   cylinder group ..etc
+	** |inodes|data          |inodes|data          |inodes|data       ..etc
+	**
+	** work out the inode block index, (considering initially that the
+	** inodes are stored as consecutive blocks). then work out the block
+	** number of that inode given the above layout, and finally the
+	** offset of the inode within that block.
+	*/
+
+	inode_index = inode->i_ino /
+		(EFS_BLOCKSIZE / sizeof(struct efs_dinode));
+
+	block = sb->fs_start + sb->first_block + 
+		(sb->group_size * (inode_index / sb->inode_blocks)) +
+		(inode_index % sb->inode_blocks);
+
+	offset = (inode->i_ino %
+			(EFS_BLOCKSIZE / sizeof(struct efs_dinode))) *
+		sizeof(struct efs_dinode);
+
+	bh = bread(inode->i_dev, block, EFS_BLOCKSIZE);
+	if (!bh) {
+		printk(KERN_WARNING "EFS: bread() failed at block %d\n", block);
+		goto read_inode_error;
+	}
+
+	efs_inode = (struct efs_dinode *) (bh->b_data + offset);
+    
+	inode->i_mode  = be16_to_cpu(efs_inode->di_mode);
+	inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
+	inode->i_uid   = be16_to_cpu(efs_inode->di_uid);
+	inode->i_gid   = be16_to_cpu(efs_inode->di_gid);
+	inode->i_size  = be32_to_cpu(efs_inode->di_size);
+	inode->i_atime = be32_to_cpu(efs_inode->di_atime);
+	inode->i_mtime = be32_to_cpu(efs_inode->di_mtime);
+	inode->i_ctime = be32_to_cpu(efs_inode->di_ctime);
+
+	/* this is the number of blocks in the file */
+	if (inode->i_size == 0) {
+		inode->i_blocks = 0;
+	} else {
+		inode->i_blocks = ((inode->i_size - 1) >> EFS_BLOCKSIZE_BITS) + 1;
+	}
+
+	/*
+	 * BUG: irix dev_t is 32-bits. linux dev_t is only 16-bits.
+	 *
+	 * apparently linux will change to 32-bit dev_t sometime during
+	 * linux 2.3.
+	 *
+	 * as is, this code maps devices that can't be represented in
+	 * 16-bits (ie major > 255 or minor > 255) to major = minor = 255.
+	 *
+	 * during 2.3 when 32-bit dev_t become available, we should test
+	 * to see whether odev contains 65535. if this is the case then we
+	 * should then do device = be32_to_cpu(efs_inode->di_u.di_dev.ndev).
+	 */
+    	device = be16_to_cpu(efs_inode->di_u.di_dev.odev);
+
+	/* get the number of extents for this object */
+	in->numextents = be16_to_cpu(efs_inode->di_numextents);
+	in->lastextent = 0;
+
+	/* copy the extents contained within the inode to memory */
+	for(i = 0; i < EFS_DIRECTEXTENTS; i++) {
+		extent_copy(&(efs_inode->di_u.di_extents[i]), &(in->extents[i]));
+		if (i < in->numextents && in->extents[i].cooked.ex_magic != 0) {
+			printk(KERN_WARNING "EFS: extent %d has bad magic number in inode %lu\n", i, inode->i_ino);
+			brelse(bh);
+			goto read_inode_error;
+		}
+	}
+
+	brelse(bh);
+   
+#ifdef DEBUG
+	printk(KERN_DEBUG "EFS: read_inode(): inode %lu, extents %d, mode %o\n",
+		inode->i_ino, in->numextents, inode->i_mode);
+#endif
+
+	switch (inode->i_mode & S_IFMT) {
+		case S_IFDIR: 
+			inode->i_op = &efs_dir_inode_operations; 
+			break;
+		case S_IFREG:
+			inode->i_op = &efs_file_inode_operations;
+			break;
+		case S_IFLNK:
+			inode->i_op = &efs_symlink_inode_operations;
+			break;
+		case S_IFCHR:
+			inode->i_rdev = device;
+			inode->i_op = &chrdev_inode_operations; 
+			break;
+		case S_IFBLK:
+			inode->i_rdev = device;
+			inode->i_op = &blkdev_inode_operations; 
+			break;
+		case S_IFIFO:
+			init_fifo(inode);
+			break;    
+		default:
+			printk(KERN_WARNING "EFS: unsupported inode mode %o\n", inode->i_mode);
+			goto read_inode_error;
+			break;
+	}
+
+	return;
+        
+read_inode_error:
+	printk(KERN_WARNING "EFS: failed to read inode %lu\n", inode->i_ino);
+	inode->i_mode = S_IFREG;
+	inode->i_atime = 0;
+	inode->i_ctime = 0;
+	inode->i_mtime = 0;
+	inode->i_nlink = 1;
+	inode->i_size = 0;
+	inode->i_blocks = 0;
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	inode->i_op = NULL;
+
+	return;
+}
+
+static inline efs_block_t
+efs_extent_check(efs_extent *ptr, efs_block_t block, struct efs_sb_info *sb) {
+	efs_block_t start;
+	efs_block_t length;
+	efs_block_t offset;
+
+	/*
+	 * given an extent and a logical block within a file,
+	 * can this block be found within this extent ?
+	 */
+	start  = ptr->cooked.ex_bn;
+	length = ptr->cooked.ex_length;
+	offset = ptr->cooked.ex_offset;
+
+	if ((block >= offset) && (block < offset+length)) {
+		return(sb->fs_start + start + block - offset);
+	} else {
+		return 0;
+	}
+}
+
+efs_block_t efs_map_block(struct inode *inode, efs_block_t block) {
+	struct efs_sb_info    *sb = SUPER_INFO(inode->i_sb);
+	struct efs_inode_info *in = INODE_INFO(inode);
+	struct buffer_head    *bh = NULL;
+
+	int cur, last, first = 1;
+	int ibase, ioffset, dirext, direxts, indext, indexts;
+	efs_block_t iblock, result = 0, lastblock = 0;
+	efs_extent ext, *exts;
+
+	last = in->lastextent;
+
+	if (in->numextents <= EFS_DIRECTEXTENTS) {
+		/* first check the last extent we returned */
+		if ((result = efs_extent_check(&in->extents[last], block, sb)))
+			return result;
+    
+		/* if we only have one extent then nothing can be found */
+		if (in->numextents == 1) {
+			printk(KERN_ERR "EFS: map_block() failed to map (1 extent)\n");
+			return 0;
+		}
+
+		direxts = in->numextents;
+
+		/*
+		 * check the stored extents in the inode
+		 * start with next extent and check forwards
+		 */
+		for(dirext = 1; dirext < direxts; dirext++) {
+			cur = (last + dirext) % in->numextents;
+			if ((result = efs_extent_check(&in->extents[cur], block, sb))) {
+				in->lastextent = cur;
+				return result;
+			}
+		}
+
+		printk(KERN_ERR "EFS: map_block() failed to map block %u (dir)\n", block);
+		return 0;
+	}
+
+#ifdef DEBUG
+	printk(KERN_DEBUG "EFS: map_block(): indirect search for logical block %u\n", block);
+#endif
+	direxts = in->extents[0].cooked.ex_offset;
+	indexts = in->numextents;
+
+	for(indext = 0; indext < indexts; indext++) {
+		cur = (last + indext) % indexts;
+
+		/*
+		 * work out which direct extent contains `cur'.
+		 *
+		 * also compute ibase: i.e. the number of the first
+		 * indirect extent contained within direct extent `cur'.
+		 *
+		 */
+		ibase = 0;
+		for(dirext = 0; cur < ibase && dirext < direxts; dirext++) {
+			ibase += in->extents[dirext].cooked.ex_length *
+				(EFS_BLOCKSIZE / sizeof(efs_extent));
+		}
+
+		if (dirext == direxts) {
+			/* should never happen */
+			printk(KERN_ERR "EFS: couldn't find direct extent for indirect extent %d (block %u)\n", cur, block);
+			if (bh) brelse(bh);
+			return 0;
+		}
+		
+		/* work out block number and offset of this indirect extent */
+		iblock = sb->fs_start + in->extents[dirext].cooked.ex_bn +
+			(cur - ibase) /
+			(EFS_BLOCKSIZE / sizeof(efs_extent));
+		ioffset = (cur - ibase) %
+			(EFS_BLOCKSIZE / sizeof(efs_extent));
+
+		if (first || lastblock != iblock) {
+			if (bh) brelse(bh);
+
+			bh = bread(inode->i_dev, iblock, EFS_BLOCKSIZE);
+			if (!bh) {
+				printk(KERN_ERR "EFS: bread() failed at block %d\n", iblock);
+				return 0;
+			}
+#ifdef DEBUG
+			printk(KERN_DEBUG "EFS: map_block(): read indirect extent block %d\n", iblock);
+#endif
+			first = 0;
+			lastblock = iblock;
+		}
+
+		exts = (efs_extent *) bh->b_data;
+
+		extent_copy(&(exts[ioffset]), &ext);
+
+		if (ext.cooked.ex_magic != 0) {
+			printk(KERN_ERR "EFS: extent %d has bad magic number in block %d\n", cur, iblock);
+			if (bh) brelse(bh);
+			return 0;
+		}
+
+		if ((result = efs_extent_check(&ext, block, sb))) {
+			if (bh) brelse(bh);
+			in->lastextent = cur;
+			return result;
+		}
+	}
+	if (bh) brelse(bh);
+	printk(KERN_ERR "EFS: map_block() failed to map block %u (indir)\n", block);
+	return 0;
+}  
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/namei.c linux.pre11.3/fs/efs/namei.c
--- linux.vanilla/fs/efs/namei.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/namei.c	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,75 @@
+/*
+ * namei.c
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
+ */
+
+#include <linux/efs_fs.h>
+
+static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) {
+	struct buffer_head *bh;
+
+	int			slot, namelen;
+	char			*nameptr;
+	struct efs_dir		*dirblock;
+	struct efs_dentry	*dirslot;
+	efs_ino_t		inodenum;
+	efs_block_t		block;
+ 
+	if (inode->i_size & (EFS_DIRBSIZE-1))
+		printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n");
+
+	for(block = 0; block < inode->i_blocks; block++) {
+
+		bh = bread(inode->i_dev, efs_bmap(inode, block), EFS_DIRBSIZE);
+		if (!bh) {
+			printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block);
+			return 0;
+		}
+    
+		dirblock = (struct efs_dir *) bh->b_data;
+
+		if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
+			printk(KERN_ERR "EFS: find_entry(): invalid directory block\n");
+			brelse(bh);
+			return(0);
+		}
+
+		for(slot = 0; slot < dirblock->slots; slot++) {
+			dirslot  = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
+
+			namelen  = dirslot->namelen;
+			nameptr  = dirslot->name;
+
+			if ((namelen == len) && (!memcmp(name, nameptr, len))) {
+				inodenum = be32_to_cpu(dirslot->inode);
+				brelse(bh);
+				return(inodenum);
+			}
+		}
+		brelse(bh);
+	}
+	return(0);
+}
+
+struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry) {
+	efs_ino_t inodenum;
+	struct inode * inode;
+
+	if (!dir || !S_ISDIR(dir->i_mode))
+		return ERR_PTR(-ENOENT);
+
+	inode = NULL;
+
+	inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
+	if (inodenum) {
+		if (!(inode = iget(dir->i_sb, inodenum)))
+			return ERR_PTR(-EACCES);
+	}
+
+	d_add(dentry, inode);
+	return NULL;
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/super.c linux.pre11.3/fs/efs/super.c
--- linux.vanilla/fs/efs/super.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/super.c	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,255 @@
+/*
+ * super.c
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/locks.h>
+#include <linux/efs_fs.h>
+#include <linux/efs_vh.h>
+#include <linux/efs_fs_sb.h>
+
+static struct file_system_type efs_fs_type = {
+	"efs",			/* filesystem name */
+	FS_REQUIRES_DEV,	/* fs_flags */
+	efs_read_super,		/* entry function pointer */
+	NULL 			/* next */
+};
+
+static struct super_operations efs_superblock_operations = {
+	efs_read_inode,	/* read_inode */
+	NULL,		/* write_inode */
+	NULL,		/* put_inode */
+	NULL,		/* delete_inode */
+	NULL,		/* notify_change */
+	efs_put_super,	/* put_super */
+	NULL,		/* write_super */
+	efs_statfs,	/* statfs */
+	NULL		/* remount */
+};
+
+__initfunc(int init_efs_fs(void)) {
+	return register_filesystem(&efs_fs_type);
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void) {
+	printk("EFS: "EFS_VERSION" - http://aeschi.ch.eu.org/efs/\n");
+	return init_efs_fs();
+}
+
+void cleanup_module(void) {
+	unregister_filesystem(&efs_fs_type);
+}
+#endif
+
+static efs_block_t efs_validate_vh(struct volume_header *vh) {
+	int		i;
+	unsigned int	cs, csum, *ui;
+	efs_block_t	sblock = 0; /* shuts up gcc */
+	struct pt_types	*pt_entry;
+	int		pt_type, slice = -1;
+
+	if (be32_to_cpu(vh->vh_magic) != VHMAGIC) {
+		/*
+		 * assume that we're dealing with a partition and allow
+		 * read_super() to try and detect a valid superblock
+		 * on the next block.
+		 */
+		return 0;
+	}
+
+	ui = ((unsigned int *) (vh + 1)) - 1;
+	for(csum = 0; ui >= ((unsigned int *) vh);) {
+		cs = *ui--;
+		csum += be32_to_cpu(cs);
+	}
+	if (csum) {
+		printk(KERN_INFO "EFS: SGI disklabel: checksum bad, label corrupted\n");
+		return 0;
+	}
+
+#ifdef DEBUG
+	printk(KERN_DEBUG "EFS: bf: \"%16s\"\n", vh->vh_bootfile);
+
+	for(i = 0; i < NVDIR; i++) {
+		int	j;
+		char	name[VDNAMESIZE+1];
+
+		for(j = 0; j < VDNAMESIZE; j++) {
+			name[j] = vh->vh_vd[i].vd_name[j];
+		}
+		name[j] = (char) 0;
+
+		if (name[0]) {
+			printk(KERN_DEBUG "EFS: vh: %8s block: 0x%08x size: 0x%08x\n",
+				name,
+				(int) be32_to_cpu(vh->vh_vd[i].vd_lbn),
+				(int) be32_to_cpu(vh->vh_vd[i].vd_nbytes));
+		}
+	}
+#endif
+
+	for(i = 0; i < NPARTAB; i++) {
+		pt_type = (int) be32_to_cpu(vh->vh_pt[i].pt_type);
+		for(pt_entry = sgi_pt_types; pt_entry->pt_name; pt_entry++) {
+			if (pt_type == pt_entry->pt_type) break;
+		}
+#ifdef DEBUG
+		if (be32_to_cpu(vh->vh_pt[i].pt_nblks)) {
+			printk(KERN_DEBUG "EFS: pt %2d: start: %08d size: %08d type: 0x%02x (%s)\n",
+				i,
+				(int) be32_to_cpu(vh->vh_pt[i].pt_firstlbn),
+				(int) be32_to_cpu(vh->vh_pt[i].pt_nblks),
+				pt_type,
+				(pt_entry->pt_name) ? pt_entry->pt_name : "unknown");
+		}
+#endif
+		if (IS_EFS(pt_type)) {
+			sblock = be32_to_cpu(vh->vh_pt[i].pt_firstlbn);
+			slice = i;
+		}
+	}
+
+	if (slice == -1) {
+		printk(KERN_NOTICE "EFS: partition table contained no EFS partitions\n");
+#ifdef DEBUG
+	} else {
+		printk(KERN_INFO "EFS: using slice %d (type %s, offset 0x%x)\n",
+			slice,
+			(pt_entry->pt_name) ? pt_entry->pt_name : "unknown",
+			sblock);
+#endif
+	}
+	return(sblock);
+}
+
+static int efs_validate_super(struct efs_sb_info *sb, struct efs_super *super) {
+
+	if (!IS_EFS_MAGIC(be32_to_cpu(super->fs_magic))) return -1;
+	if (!(super->fs_cgisize)) return -1;
+
+	sb->fs_magic     = be32_to_cpu(super->fs_magic);
+	sb->total_blocks = be32_to_cpu(super->fs_size);
+	sb->first_block  = be32_to_cpu(super->fs_firstcg);
+	sb->group_size   = be32_to_cpu(super->fs_cgfsize);
+	sb->data_free    = be32_to_cpu(super->fs_tfree);
+	sb->inode_free   = be32_to_cpu(super->fs_tinode);
+	sb->inode_blocks = be16_to_cpu(super->fs_cgisize);
+	sb->total_groups = be16_to_cpu(super->fs_ncg);
+    
+	return 0;    
+}
+
+struct super_block *efs_read_super(struct super_block *s, void *d, int silent) {
+	kdev_t dev = s->s_dev;
+	struct efs_sb_info *sb;
+	struct buffer_head *bh;
+
+	MOD_INC_USE_COUNT;
+	lock_super(s);
+  
+ 	sb = SUPER_INFO(s);
+
+	set_blocksize(dev, EFS_BLOCKSIZE);
+  
+	/* read the vh (volume header) block */
+	bh = bread(dev, 0, EFS_BLOCKSIZE);
+
+	if (!bh) {
+		printk(KERN_ERR "EFS: cannot read volume header\n");
+		goto out_no_fs_ul;
+	}
+
+	/*
+	 * if this returns zero then we didn't find any partition table.
+	 * this isn't (yet) an error - just assume for the moment that
+	 * the device is valid and go on to search for a superblock.
+	 */
+	sb->fs_start = efs_validate_vh((struct volume_header *) bh->b_data);
+	brelse(bh);
+
+	if (sb->fs_start == -1) {
+		goto out_no_fs_ul;
+	}
+
+	bh = bread(dev, sb->fs_start + EFS_SUPER, EFS_BLOCKSIZE);
+	if (!bh) {
+		printk(KERN_ERR "EFS: cannot read superblock\n");
+		goto out_no_fs_ul;
+	}
+		
+	if (efs_validate_super(sb, (struct efs_super *) bh->b_data)) {
+#ifdef DEBUG
+		printk(KERN_WARNING "EFS: invalid superblock at block %u\n", sb->fs_start + EFS_SUPER);
+#endif
+		brelse(bh);
+		goto out_no_fs_ul;
+	}
+	brelse(bh);
+ 
+	s->s_magic		= EFS_SUPER_MAGIC;
+	s->s_blocksize		= EFS_BLOCKSIZE;
+	s->s_blocksize_bits	= EFS_BLOCKSIZE_BITS;
+	if (!(s->s_flags & MS_RDONLY)) {
+#ifdef DEBUG
+		printk(KERN_INFO "EFS: forcing read-only mode\n");
+#endif
+		s->s_flags |= MS_RDONLY;
+	}
+	s->s_op   = &efs_superblock_operations;
+	s->s_dev  = dev;
+	s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE), NULL);
+	unlock_super(s);
+ 
+	if (!(s->s_root)) {
+		printk(KERN_ERR "EFS: get root inode failed\n");
+		goto out_no_fs;
+	}
+
+	if (check_disk_change(s->s_dev)) {
+		printk(KERN_ERR "EFS: device changed\n");
+		goto out_no_fs;
+	}
+
+	return(s);
+
+out_no_fs_ul:
+	unlock_super(s);
+out_no_fs:
+	s->s_dev = 0;
+	MOD_DEC_USE_COUNT;
+	return(NULL);
+}
+
+void efs_put_super(struct super_block *s) {
+	MOD_DEC_USE_COUNT;
+}
+
+int efs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) {
+	struct statfs ret;
+	struct efs_sb_info *sb = SUPER_INFO(s);
+
+	ret.f_type    = EFS_SUPER_MAGIC;	/* efs magic number */
+	ret.f_bsize   = EFS_BLOCKSIZE;		/* blocksize */
+	ret.f_blocks  = sb->total_groups *	/* total data blocks */
+			(sb->group_size - sb->inode_blocks);
+	ret.f_bfree   = sb->data_free;		/* free data blocks */
+	ret.f_bavail  = sb->data_free;		/* free blocks for non-root */
+	ret.f_files   = sb->total_groups *	/* total inodes */
+			sb->inode_blocks *
+			(EFS_BLOCKSIZE / sizeof(struct efs_dinode));
+	ret.f_ffree   = sb->inode_free;	/* free inodes */
+	ret.f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
+	ret.f_fsid.val[1] =  sb->fs_magic        & 0xffff; /* fs ID */
+	ret.f_namelen = EFS_MAXNAMELEN;		/* max filename length */
+
+	return copy_to_user(buf, &ret, bufsiz) ? -EFAULT : 0;
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/efs/symlink.c linux.pre11.3/fs/efs/symlink.c
--- linux.vanilla/fs/efs/symlink.c	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/fs/efs/symlink.c	Mon Jul 19 23:26:39 1999
@@ -0,0 +1,102 @@
+/*
+ * symlink.c
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
+ */
+
+#include <linux/malloc.h>
+#include <linux/efs_fs.h>
+
+static int efs_readlink(struct dentry *, char *, int);
+static struct dentry * efs_follow_link(struct dentry *, struct dentry *, unsigned int);
+
+struct inode_operations efs_symlink_inode_operations = {
+	NULL,			/* no symlink file-operations */
+	NULL,			/* create */
+	NULL,			/* lookup */
+	NULL,			/* link */
+	NULL,			/* unlink */
+	NULL,			/* symlink */
+	NULL,			/* mkdir */
+	NULL,			/* rmdir */
+	NULL,			/* mknod */
+	NULL,			/* rename */
+	efs_readlink,		/* readlink */
+	efs_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
+	NULL,			/* bmap */
+	NULL,			/* truncate */
+	NULL,			/* permission */
+	NULL			/* smap */
+};
+
+static char *efs_linktarget(struct inode *in, int *len) {
+	char *name;
+	struct buffer_head * bh;
+	efs_block_t size = in->i_size;
+  
+	if (size > 2 * EFS_BLOCKSIZE) {
+		printk(KERN_ERR "EFS: linktarget(): name too long: %lu\n", in->i_size);
+		return NULL;
+	}
+  
+	if (!(name = kmalloc(size + 1, GFP_KERNEL)))
+		return NULL;
+  
+	/* read first 512 bytes of link target */
+	bh = bread(in->i_dev, efs_bmap(in, 0), EFS_BLOCKSIZE);
+	if (!bh) {
+		kfree(name);
+		printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 0));
+		return NULL;
+	}
+
+	memcpy(name, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
+	brelse(bh);
+
+	if (size > EFS_BLOCKSIZE) {
+		bh = bread(in->i_dev, efs_bmap(in, 1), EFS_BLOCKSIZE);
+		if (!bh) {
+			kfree(name);
+			printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 1));
+			return NULL;
+		}
+		memcpy(name + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
+		brelse(bh);
+	}
+  
+	name[size] = (char) 0;
+	if (len) *len = size;
+
+	return name;
+}
+
+static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) {
+	char *name;
+	struct inode *inode = dentry->d_inode;
+
+	if (!(name = efs_linktarget(inode, NULL))) {
+		dput(base);
+		return ERR_PTR(-ELOOP);
+	}
+	base = lookup_dentry(name, base, follow);
+	kfree(name);
+  
+	return base;
+}
+
+static int efs_readlink(struct dentry * dir, char * buf, int bufsiz) {
+	int rc;
+	char *name;
+	struct inode *inode = dir->d_inode;
+  
+	if (!(name = efs_linktarget(inode, &bufsiz))) return 0;
+	rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : bufsiz;
+	kfree(name);
+
+	return rc;
+}
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ext2/balloc.c linux.pre11.3/fs/ext2/balloc.c
--- linux.vanilla/fs/ext2/balloc.c	Sun Nov  8 15:10:22 1998
+++ linux.pre11.3/fs/ext2/balloc.c	Tue Jul 20 00:06:26 1999
@@ -368,11 +368,10 @@
 	struct super_block * sb;
 	struct ext2_group_desc * gdp;
 	struct ext2_super_block * es;
-
-	*err = -ENOSPC;
 #ifdef EXT2FS_DEBUG
 	static int goal_hits = 0, goal_attempts = 0;
 #endif
+	*err = -ENOSPC;
 	sb = inode->i_sb;
 	if (!sb) {
 		printk ("ext2_new_block: nonexistent device");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ext2/file.c linux.pre11.3/fs/ext2/file.c
--- linux.vanilla/fs/ext2/file.c	Tue Jun 15 16:49:52 1999
+++ linux.pre11.3/fs/ext2/file.c	Tue Jul 20 00:06:33 1999
@@ -50,7 +50,7 @@
 	   (1LL << (bits - 2)) * (1LL << (bits - 2)) * (1LL << (bits - 2))) * 	\
 	  (1LL << bits)) - 1)
 
-static long long ext2_max_sizes[] = {
+long long ext2_max_sizes[] = {
 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 EXT2_MAX_SIZE(10), EXT2_MAX_SIZE(11), EXT2_MAX_SIZE(12), EXT2_MAX_SIZE(13)
 };
@@ -163,10 +163,16 @@
 	struct super_block * sb;
 	int err;
 	int i,buffercount,write_error, new_buffer;
-
+	unsigned long limit;
+	
 	/* POSIX: mtime/ctime may not change for 0 count */
 	if (!count)
 		return 0;
+	/* This makes the bounds-checking arithmetic later on much more
+	 * sane. */
+	if (((signed) count) < 0)
+		return -EINVAL;
+	
 	write_error = buffercount = 0;
 	if (!inode) {
 		printk("ext2_file_write: inode = NULL\n");
@@ -192,29 +198,38 @@
 		pos = *ppos;
 		if (pos != *ppos)
 			return -EINVAL;
-#if BITS_PER_LONG >= 64
-		if (pos > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)])
-			return -EINVAL;
-#endif
 	}
 
 	/* Check for overflow.. */
+
 #if BITS_PER_LONG < 64
-	if (pos > (__u32) (pos + count)) {
-		count = ~pos; /* == 0xFFFFFFFF - pos */
-		if (!count)
+	/* If the fd's pos is already greater than or equal to the file
+	 * descriptor's offset maximum, then we need to return EFBIG for
+	 * any non-zero count (and we already tested for zero above). */
+	if (((unsigned) pos) >= 0x7FFFFFFFUL)
+		return -EFBIG;
+	
+	/* If we are about to overflow the maximum file size, we also
+	 * need to return the error, but only if no bytes can be written
+	 * successfully. */
+	if (((unsigned) pos + count) > 0x7FFFFFFFUL) {
+		count = 0x7FFFFFFFL - pos;
+		if (((signed) count) < 0)
 			return -EFBIG;
 	}
 #else
 	{
 		off_t max = ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(sb)];
 
+		if (pos >= max)
+			return -EFBIG;
+		
 		if (pos + count > max) {
 			count = max - pos;
 			if (!count)
 				return -EFBIG;
 		}
-		if (((pos + count) >> 32) && 
+		if (((pos + count) >> 33) && 
 		    !(sb->u.ext2_sb.s_es->s_feature_ro_compat &
 		      cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) {
 			/* If this is the first large file created, add a flag
@@ -225,6 +240,20 @@
 		}
 	}
 #endif
+
+	/* From SUS: We must generate a SIGXFSZ for file size overflow
+	 * only if no bytes were actually written to the file. --sct */
+
+	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+	if (limit < RLIM_INFINITY) {
+		if (((unsigned) pos+count) >= limit) {
+			count = limit - pos;
+			if (((signed) count) <= 0) {
+				send_sig(SIGXFSZ, current, 0);
+				return -EFBIG;
+			}
+		}
+	}
 
 	/*
 	 * If a file has been opened in synchronous mode, we have to ensure
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ext2/inode.c linux.pre11.3/fs/ext2/inode.c
--- linux.vanilla/fs/ext2/inode.c	Thu May 27 22:11:57 1999
+++ linux.pre11.3/fs/ext2/inode.c	Tue Jul 20 00:08:27 1999
@@ -220,21 +220,7 @@
 	}
 	*err = -EFBIG;
 	if (!create)
-		goto dont_create;
-
-	/* Check file limits.. */
-	{
-		unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
-		if (limit < RLIM_INFINITY) {
-			limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb);
-			if (new_block >= limit) {
-				send_sig(SIGXFSZ, current, 0);
-dont_create:
-				*err = -EFBIG;
-				return NULL;
-			}
-		}
-	}
+		return NULL;
 
 	if (inode->u.ext2_i.i_next_alloc_block == new_block)
 		goal = inode->u.ext2_i.i_next_alloc_goal;
@@ -286,7 +272,6 @@
 	u32 * p;
 	struct buffer_head * result;
 	int blocks = inode->i_sb->s_blocksize / 512;
-	unsigned long limit;
 	
 	if (!bh)
 		return NULL;
@@ -316,16 +301,6 @@
 		return NULL;
 	}
 
-	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
-	if (limit < RLIM_INFINITY) {
-		limit >>= EXT2_BLOCK_SIZE_BITS(inode->i_sb);
-		if (new_block >= limit) {
-			brelse (bh);
-			send_sig(SIGXFSZ, current, 0);
-			return NULL;
-		}
-	}
-
 	if (inode->u.ext2_i.i_next_alloc_block == new_block)
 		goal = inode->u.ext2_i.i_next_alloc_goal;
 	if (!goal) {
@@ -732,49 +707,83 @@
 	unsigned int	flags;
 	
 	retval = -EPERM;
-	if ((iattr->ia_attr_flags &
-	     (ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^
-	    (inode->u.ext2_i.i_flags &
-	     (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
+	if (iattr->ia_valid & ATTR_ATTR_FLAG &&
+	    ((!(iattr->ia_attr_flags & ATTR_FLAG_APPEND) !=
+	      !(inode->u.ext2_i.i_flags & EXT2_APPEND_FL)) ||
+	     (!(iattr->ia_attr_flags & ATTR_FLAG_IMMUTABLE) !=
+	      !(inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL)))) {
 		if (!capable(CAP_LINUX_IMMUTABLE))
 			goto out;
 	} else if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
 		goto out;
 
+	if (iattr->ia_valid & ATTR_SIZE) {
+		off_t size = iattr->ia_size;
+		unsigned long limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+
+		if (size < 0)
+			return -EINVAL;
+#if BITS_PER_LONG == 64	
+		if (size > ext2_max_sizes[EXT2_BLOCK_SIZE_BITS(inode->i_sb)])
+			return -EFBIG;
+#endif
+		if (limit < RLIM_INFINITY && size > limit) {
+			send_sig(SIGXFSZ, current, 0);
+			return -EFBIG;
+		}
+
+#if BITS_PER_LONG == 64	
+		if (size >> 33) {
+			struct super_block *sb = inode->i_sb;
+			struct ext2_super_block *es = sb->u.ext2_sb.s_es;
+			if (!(es->s_feature_ro_compat &
+			      cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE))){
+				/* If this is the first large file
+				 * created, add a flag to the superblock */
+				es->s_feature_ro_compat |=
+				cpu_to_le32(EXT2_FEATURE_RO_COMPAT_LARGE_FILE);
+				mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
+			}
+		}
+#endif
+	}
+	
 	retval = inode_change_ok(inode, iattr);
 	if (retval != 0)
 		goto out;
 
 	inode_setattr(inode, iattr);
 	
-	flags = iattr->ia_attr_flags;
-	if (flags & ATTR_FLAG_SYNCRONOUS) {
-		inode->i_flags |= MS_SYNCHRONOUS;
-		inode->u.ext2_i.i_flags = EXT2_SYNC_FL;
-	} else {
-		inode->i_flags &= ~MS_SYNCHRONOUS;
-		inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL;
-	}
-	if (flags & ATTR_FLAG_NOATIME) {
-		inode->i_flags |= MS_NOATIME;
-		inode->u.ext2_i.i_flags = EXT2_NOATIME_FL;
-	} else {
-		inode->i_flags &= ~MS_NOATIME;
-		inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL;
-	}
-	if (flags & ATTR_FLAG_APPEND) {
-		inode->i_flags |= S_APPEND;
-		inode->u.ext2_i.i_flags = EXT2_APPEND_FL;
-	} else {
-		inode->i_flags &= ~S_APPEND;
-		inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL;
-	}
-	if (flags & ATTR_FLAG_IMMUTABLE) {
-		inode->i_flags |= S_IMMUTABLE;
-		inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL;
-	} else {
-		inode->i_flags &= ~S_IMMUTABLE;
-		inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
+	if (iattr->ia_valid & ATTR_ATTR_FLAG) {
+		flags = iattr->ia_attr_flags;
+		if (flags & ATTR_FLAG_SYNCRONOUS) {
+			inode->i_flags |= MS_SYNCHRONOUS;
+			inode->u.ext2_i.i_flags = EXT2_SYNC_FL;
+		} else {
+			inode->i_flags &= ~MS_SYNCHRONOUS;
+			inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL;
+		}
+		if (flags & ATTR_FLAG_NOATIME) {
+			inode->i_flags |= MS_NOATIME;
+			inode->u.ext2_i.i_flags = EXT2_NOATIME_FL;
+		} else {
+			inode->i_flags &= ~MS_NOATIME;
+			inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL;
+		}
+		if (flags & ATTR_FLAG_APPEND) {
+			inode->i_flags |= S_APPEND;
+			inode->u.ext2_i.i_flags = EXT2_APPEND_FL;
+		} else {
+			inode->i_flags &= ~S_APPEND;
+			inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL;
+		}
+		if (flags & ATTR_FLAG_IMMUTABLE) {
+			inode->i_flags |= S_IMMUTABLE;
+			inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL;
+		} else {
+			inode->i_flags &= ~S_IMMUTABLE;
+			inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
+		}
 	}
 	mark_inode_dirty(inode);
 out:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ext2/ioctl.c linux.pre11.3/fs/ext2/ioctl.c
--- linux.vanilla/fs/ext2/ioctl.c	Sun Nov  8 15:06:33 1998
+++ linux.pre11.3/fs/ext2/ioctl.c	Mon Jul 19 23:26:26 1999
@@ -33,18 +33,17 @@
 		flags = flags & EXT2_FL_USER_MODIFIABLE;
 		/*
 		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
-		 * the super user when the security level is zero.
+		 * a process with the relevent capability.
 		 */
 		if ((flags & (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)) ^
 		    (inode->u.ext2_i.i_flags &
-		     (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
+		     (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL)))
 			/* This test looks nicer. Thanks to Pauline Middelink */
 			if (!capable(CAP_LINUX_IMMUTABLE))
 				return -EPERM;
-		} else
-			if ((current->fsuid != inode->i_uid) && 
-			    !capable(CAP_FOWNER))
-				return -EPERM;
+
+		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+			return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
 		inode->u.ext2_i.i_flags = (inode->u.ext2_i.i_flags &
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ext2/super.c linux.pre11.3/fs/ext2/super.c
--- linux.vanilla/fs/ext2/super.c	Fri Apr 16 22:10:57 1999
+++ linux.pre11.3/fs/ext2/super.c	Tue Jul 20 00:08:38 1999
@@ -134,7 +134,7 @@
 	ext2_write_inode,
 	ext2_put_inode,
 	ext2_delete_inode,
-	NULL,
+	ext2_notify_change,
 	ext2_put_super,
 	ext2_write_super,
 	ext2_statfs,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/fat/cache.c linux.pre11.3/fs/fat/cache.c
--- linux.vanilla/fs/fat/cache.c	Sun Nov  8 15:06:35 1998
+++ linux.pre11.3/fs/fat/cache.c	Mon Jul 19 23:26:27 1999
@@ -2,6 +2,10 @@
  *  linux/fs/fat/cache.c
  *
  *  Written 1992,1993 by Werner Almesberger
+ *
+ *  Mar 1999. AV. Changed cache, so that it uses the starting cluster instead
+ *	of inode number.
+ *  May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
  */
 
 #include <linux/msdos_fs.h>
@@ -62,6 +66,8 @@
 		p_first = p_last = NULL; /* GCC needs that stuff */
 		next = CF_LE_L(((unsigned long *) bh->b_data)[(first &
 		    (SECTOR_SIZE-1)) >> 2]);
+		/* Fscking Microsoft marketing department. Their "32" is 28. */
+		next &= 0xfffffff;
 		if (next >= 0xffffff7) next = -1;
 		PRINTK(("fat_bread: 0x%x, nr=0x%x, first=0x%x, next=0x%d\n", b, nr, first, next));
 
@@ -141,14 +147,13 @@
 void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
 {
 	struct fat_cache *walk;
+	int first = MSDOS_I(inode)->i_start;
 
-#ifdef DEBUG
-printk("cache lookup: <%s,%d> %d (%d,%d) -> ", kdevname(inode->i_dev),
-       inode->i_ino, cluster, *f_clu, *d_clu);
-#endif
+	if (!first)
+		return;
 	for (walk = fat_cache; walk; walk = walk->next)
 		if (inode->i_dev == walk->device
-		    && walk->ino == inode->i_ino
+		    && walk->start_cluster == first
 		    && walk->file_cluster <= cluster
 		    && walk->file_cluster > *f_clu) {
 			*d_clu = walk->disk_cluster;
@@ -171,7 +176,8 @@
 	for (walk = fat_cache; walk; walk = walk->next) {
 		if (walk->device)
 			printk("<%s,%d>(%d,%d) ", kdevname(walk->device),
-			       walk->ino, walk->file_cluster, walk->disk_cluster);
+			       walk->start_cluster, walk->file_cluster,
+			       walk->disk_cluster);
 		else printk("-- ");
 	}
 	printk("\n");
@@ -182,15 +188,12 @@
 void fat_cache_add(struct inode *inode,int f_clu,int d_clu)
 {
 	struct fat_cache *walk,*last;
+	int first = MSDOS_I(inode)->i_start;
 
-#ifdef DEBUG
-printk("cache add: <%s,%d> %d (%d)\n", kdevname(inode->i_dev),
-       inode->i_ino, f_clu, d_clu);
-#endif
 	last = NULL;
 	for (walk = fat_cache; walk->next; walk = (last = walk)->next)
 		if (inode->i_dev == walk->device
-		    && walk->ino == inode->i_ino
+		    && walk->start_cluster == first
 		    && walk->file_cluster == f_clu) {
 			if (walk->disk_cluster != d_clu) {
 				printk("FAT cache corruption inode=%ld\n",
@@ -209,7 +212,7 @@
 			return;
 		}
 	walk->device = inode->i_dev;
-	walk->ino = inode->i_ino;
+	walk->start_cluster = first;
 	walk->file_cluster = f_clu;
 	walk->disk_cluster = d_clu;
 	last->next = NULL;
@@ -227,10 +230,11 @@
 void fat_cache_inval_inode(struct inode *inode)
 {
 	struct fat_cache *walk;
+	int first = MSDOS_I(inode)->i_start;
 
 	for (walk = fat_cache; walk; walk = walk->next)
 		if (walk->device == inode->i_dev
-		    && walk->ino == inode->i_ino)
+		    && walk->start_cluster == first)
 			walk->device = 0;
 }
 
@@ -300,9 +304,11 @@
 			return -EIO;
 		}
 	}
-	if (last)
+	if (last) {
 		fat_access(inode->i_sb,last,EOF_FAT(inode->i_sb));
-	else {
+		fat_cache_inval_inode(inode);
+	} else {
+		fat_cache_inval_inode(inode);
 		MSDOS_I(inode)->i_start = 0;
 		MSDOS_I(inode)->i_logstart = 0;
 		mark_inode_dirty(inode);
@@ -322,6 +328,5 @@
 		inode->i_blocks -= MSDOS_SB(inode->i_sb)->cluster_size;
 	}
 	unlock_fat(inode->i_sb);
-	fat_cache_inval_inode(inode);
 	return 0;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/fat/dir.c linux.pre11.3/fs/fat/dir.c
--- linux.vanilla/fs/fat/dir.c	Wed Apr 28 19:14:30 1999
+++ linux.pre11.3/fs/fat/dir.c	Tue Jul 20 00:31:27 1999
@@ -9,7 +9,7 @@
  *
  *  VFAT extensions by Gordon Chaffee <chaffee@plateau.cs.berkeley.edu>
  *  Merged with msdos fs by Henrik Storner <storner@osiris.ping.dk>
- *  Plugged buffer overrun in readdir(). AV
+ *  Rewritten for constant inumbers. Plugged buffer overrun in readdir(). AV
  */
 
 #define ASC_LINUX_VERSION(V, P, S)	(((V) * 65536) + ((P) * 256) + (S))
@@ -25,6 +25,7 @@
 #include <linux/ioctl.h>
 #include <linux/dirent.h>
 #include <linux/mm.h>
+#include <linux/ctype.h>
 
 #include <asm/uaccess.h>
 
@@ -118,224 +119,369 @@
 	printk("]\n");
 }
 #endif
-int fat_readdirx(
-	struct inode *inode,
-	struct file *filp,
-	void *dirent,
-	fat_filldir_t fat_filldir,
-	filldir_t filldir,
-	int shortnames,
-	int longnames,
-	int both)
+static int memicmp(const char *s1, const char *s2, int len) {
+	while(len--) if (tolower(*s1++)!=tolower(*s2++)) return 1;
+	return 0;
+}
+
+/*
+ * Return values: negative -> error, 0 -> not found, positive -> found,
+ * value is the total amount of slots, including the shortname entry.
+ */
+int fat_search_long(
+	struct inode *inode, const char *name, int name_len, int anycase,
+	loff_t *spos, loff_t *lpos)
 {
 	struct super_block *sb = inode->i_sb;
 	int ino,i,i2,last;
 	char c;
-	struct buffer_head *bh;
+	struct buffer_head *bh = NULL;
 	struct msdos_dir_entry *de;
-	unsigned long oldpos = filp->f_pos;
-	unsigned long spos;
-	int is_long;
-	char longname[275];
-	unsigned char long_len = 0; /* Make compiler warning go away */
-	unsigned char alias_checksum = 0; /* Make compiler warning go away */
-	unsigned char long_slots = 0;
+	loff_t cpos = MSDOS_I(inode)->i_last_pos;
+	loff_t barrier = 0;
+	char bufname[14];
+	unsigned char long_slots;
 	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
 	int utf8 = MSDOS_SB(sb)->options.utf8;
 	unsigned char *unicode = NULL;
 	struct nls_table *nls = MSDOS_SB(sb)->nls_io;
+	int res = 0;
 
-/* Fake . and .. for the root directory. */
-	if (inode->i_ino == MSDOS_ROOT_INO) {
-		while (oldpos < 2) {
-			if (fat_filldir(filldir, dirent, "..", oldpos+1, 0, oldpos, oldpos, 0, MSDOS_ROOT_INO) < 0)
-				return 0;
-			oldpos++;
-			filp->f_pos++;
-		}
-		if (oldpos == 2)
-			filp->f_pos = 0;
-	}
-	if (filp->f_pos & (sizeof(struct msdos_dir_entry)-1))
-		return -ENOENT;
-
- 	bh = NULL;
-	longname[0] = longname[1] = 0;
-	is_long = 0;
-	ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);
-	while (ino > -1) {
-#if 0
-		dump_de(de);
-#endif
-		/* Check for long filename entry */
-		if (MSDOS_SB(sb)->options.isvfat && (de->name[0] == (__s8) DELETED_FLAG)) {
-			is_long = 0;
-			oldpos = filp->f_pos;
-		} else if (MSDOS_SB(sb)->options.isvfat && de->attr ==  ATTR_EXT) {
-			int get_new_entry;
+	while(1) {
+		if (barrier && cpos>=barrier)
+			goto EODir;
+rescan:
+		if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
+			goto EODir;
+parse_record:
+		long_slots = 0;
+		if (de->name[0] == (__s8) DELETED_FLAG)
+			continue;
+		if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
+			continue;
+		if (de->attr != ATTR_EXT && IS_FREE(de->name))
+			continue;
+		if (de->attr ==  ATTR_EXT) {
 			struct msdos_dir_slot *ds;
 			int offset;
 			unsigned char id;
 			unsigned char slot;
-			unsigned char slots = 0;
+			unsigned char slots;
+			unsigned char sum;
+			unsigned char alias_checksum;
 
 			if (!unicode) {
 				unicode = (unsigned char *)
 					__get_free_page(GFP_KERNEL);
-				if (!unicode)
+				if (!unicode) {
+					fat_brelse(sb, bh);
 					return -ENOMEM;
+				}
 			}
-
+parse_long:
+			slots = 0;
 			offset = 0;
 			ds = (struct msdos_dir_slot *) de;
 			id = ds->id;
-			if (id & 0x40) {
-				slots = id & ~0x40;
-				/*
-				 * Dirty, but not dirtier than the original,
-				 * and plugs the hole.
-				 */
-				if (slots > 20)
-					slots = 0;
-				else {
-					long_slots = slots;
-					is_long = 1;
-					alias_checksum = ds->alias_checksum;
-				}
-			}
+			if (!(id & 0x40))
+				continue;
+			slots = id & ~0x40;
+			if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */
+				continue;
+			long_slots = slots;
+			alias_checksum = ds->alias_checksum;
 
-			get_new_entry = 1;
 			slot = slots;
-			while (slot > 0) {
-				PRINTK(("1. get_new_entry: %d\n", get_new_entry));
-				if (ds->attr !=  ATTR_EXT) {
-					is_long = 0;
-					get_new_entry = 0;
-					break;
-				}
-				if ((ds->id & ~0x40) != slot) {
-					is_long = 0;
-					break;
-				}
-				if (ds->alias_checksum != alias_checksum) {
-					is_long = 0;
-					break;
-				}
+			while (1) {
 				slot--;
 				offset = slot * 26;
-				PRINTK(("2. get_new_entry: %d\n", get_new_entry));
 				memcpy(&unicode[offset], ds->name0_4, 10);
-				offset += 10;
-				memcpy(&unicode[offset], ds->name5_10, 12);
-				offset += 12;
-				memcpy(&unicode[offset], ds->name11_12, 4);
-				offset += 4;
+				memcpy(&unicode[offset+10], ds->name5_10, 12);
+				memcpy(&unicode[offset+22], ds->name11_12, 4);
+				offset += 26;
 
 				if (ds->id & 0x40) {
 					unicode[offset] = 0;
 					unicode[offset+1] = 0;
 				}
-				if (slot > 0) {
-					ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);
-					PRINTK(("4. get_new_entry: %d\n", get_new_entry));
-					if (ino == -1) {
-						is_long = 0;
-						get_new_entry = 0;
-						break;
-					}
-					ds = (struct msdos_dir_slot *) de;
-				}
-				PRINTK(("5. get_new_entry: %d\n", get_new_entry));
+				if (fat_get_entry(inode,&cpos,&bh,&de,&ino)<0)
+					goto EODir;
+				if (slot == 0)
+					break;
+				ds = (struct msdos_dir_slot *) de;
+				if (ds->attr !=  ATTR_EXT)
+					goto parse_record;
+				if ((ds->id & ~0x40) != slot)
+					goto parse_long;
+				if (ds->alias_checksum != alias_checksum)
+					goto parse_long;
 			}
-		} else if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) {
-			char bufname[14];
-			char *ptname = bufname;
-			int dotoffset = 0;
-			int was_long = is_long;
-
-			if (is_long) {
-				unsigned char sum;
-				for (sum = 0, i = 0; i < 11; i++) {
-					sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
-				}
+			if (de->name[0] == (__s8) DELETED_FLAG)
+				continue;
+			if (de->attr ==  ATTR_EXT)
+				goto parse_long;
+			if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))
+				continue;
+			for (sum = 0, i = 0; i < 11; i++)
+				sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
+			if (sum != alias_checksum)
+				long_slots = 0;
+		}
 
-				if (sum != alias_checksum) {
-					PRINTK(("Checksums don't match %d != %d\n", sum, alias_checksum));
-					is_long = 0;
-					long_slots = 0;
-				}
-				if (utf8) {
-					long_len = utf8_wcstombs(longname, (__u16 *) unicode, sizeof(longname));
-				} else {
-					long_len = uni16_to_x8(longname, unicode, uni_xlate, nls);
-				}
-			}
+		for (i = 0, last = 0; i < 8;) {
+			if (!(c = de->name[i])) break;
+			if (c >= 'A' && c <= 'Z') c += 32;
+			if (c == 0x05) c = 0xE5;
+			if ((bufname[i++] = c) != ' ')
+				last = i;
+		}
+		i = last;
+		bufname[i++] = '.';
+		for (i2 = 0; i2 < 3; i2++) {
+			if (!(c = de->ext[i2])) break;
+			if (c >= 'A' && c <= 'Z') c += 32;
+			if ((bufname[i++] = c) != ' ')
+				last = i;
+		}
+		if (!last)
+			continue;
 
-			if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
-				bufname[0] = '.';
-				dotoffset = 1;
-				ptname = bufname+1;
-			}
-			for (i = 0, last = 0; i < 8; i++) {
-				if (!(c = de->name[i])) break;
-				if (c >= 'A' && c <= 'Z') c += 32;
-				/* see namei.c, msdos_format_name */
-				if (c == 0x05) c = 0xE5;
-				if (c != ' ')
-					last = i+1;
-				ptname[i] = c;
-			}
-			i = last;
-			ptname[i] = '.';
-			i++;
-			for (i2 = 0; i2 < 3; i2++) {
-				if (!(c = de->ext[i2])) break;
-				if (c >= 'A' && c <= 'Z') c += 32;
-				if (c != ' ')
-					last = i+1;
-				ptname[i] = c;
-				i++;
+		if (last==name_len)
+			if ((!anycase && !memcmp(name, bufname, last)) ||
+			    (anycase && !memicmp(name, bufname, last)))
+			goto Found;
+		if (long_slots) {
+			char longname[260];	/* 256 + 4 */
+			unsigned char long_len;
+			long_len = utf8
+				?utf8_wcstombs(longname, (__u16 *) unicode, 260)
+				:uni16_to_x8(longname, unicode, uni_xlate, nls);
+			if (long_len != name_len)
+				continue;
+			if ((!anycase && !memcmp(name, longname, long_len)) ||
+			    (anycase && !memicmp(name, longname, long_len)))
+				goto Found;
+		}
+	}
+
+Found:
+	fat_brelse(sb, bh);
+	res = long_slots + 1;
+	*spos = cpos - sizeof(struct msdos_dir_entry);
+	*lpos = cpos - res*sizeof(struct msdos_dir_entry);
+	MSDOS_I(inode)->i_last_pos = cpos;
+exit:
+	if (unicode) {
+		free_page((unsigned long) unicode);
+	}
+	return res;
+EODir:
+	if (!MSDOS_I(inode)->i_last_pos)
+		goto exit;
+	if (barrier) {
+		MSDOS_I(inode)->i_last_pos = 0;
+		goto exit;
+	}
+	barrier = MSDOS_I(inode)->i_last_pos;
+	cpos = 0;
+	goto rescan;
+}
+
+static int fat_readdirx(
+	struct inode *inode,
+	struct file *filp,
+	void *dirent,
+	filldir_t filldir,
+	int shortnames,
+	int both)
+{
+	struct super_block *sb = inode->i_sb;
+	int ino,inum,i,i2,last;
+	char c;
+	struct buffer_head *bh;
+	struct msdos_dir_entry *de;
+	unsigned long lpos;
+	loff_t cpos;
+	unsigned char long_slots;
+	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
+	int utf8 = MSDOS_SB(sb)->options.utf8;
+	unsigned char *unicode = NULL;
+	struct nls_table *nls = MSDOS_SB(sb)->nls_io;
+	char bufname[14];
+	char *ptname = bufname;
+	int dotoffset = 0;
+	unsigned long *furrfu = &lpos;
+	unsigned long dummy;
+
+	cpos = filp->f_pos;
+/* Fake . and .. for the root directory. */
+	if (inode->i_ino == MSDOS_ROOT_INO) {
+		while (cpos < 2) {
+			if (filldir(dirent, "..", cpos+1, cpos, MSDOS_ROOT_INO) < 0)
+				return 0;
+			cpos++;
+			filp->f_pos++;
+		}
+		if (cpos == 2) {
+			dummy = 2;
+			furrfu = &dummy;
+			cpos = 0;
+		}
+	}
+	if (cpos & (sizeof(struct msdos_dir_entry)-1))
+		return -ENOENT;
+
+ 	bh = NULL;
+GetNew:
+	long_slots = 0;
+	if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
+		goto EODir;
+	/* Check for long filename entry */
+	if (MSDOS_SB(sb)->options.isvfat) {
+		if (de->name[0] == (__s8) DELETED_FLAG)
+			goto RecEnd;
+		if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
+			goto RecEnd;
+		if (de->attr != ATTR_EXT && IS_FREE(de->name))
+			goto RecEnd;
+	} else {
+		if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))
+			goto RecEnd;
+	}
+
+	if (MSDOS_SB(sb)->options.isvfat && de->attr ==  ATTR_EXT) {
+		struct msdos_dir_slot *ds;
+		int offset;
+		unsigned char id;
+		unsigned char slot;
+		unsigned char slots;
+		unsigned char sum;
+		unsigned char alias_checksum;
+
+		if (!unicode) {
+			unicode = (unsigned char *)
+				__get_free_page(GFP_KERNEL);
+			if (!unicode) {
+				filp->f_pos = cpos;
+				fat_brelse(sb, bh);
+				return -ENOMEM;
 			}
-			if ((i = last) != 0) {
-				if (!strcmp(de->name,MSDOS_DOT))
-					ino = inode->i_ino;
-				else if (!strcmp(de->name,MSDOS_DOTDOT))
-					ino = fat_parent_ino(inode,0);
-
-				if (shortnames || !is_long) {
-					if (both)
-						bufname[i+dotoffset] = '\0';
-					spos = oldpos;
-					if (was_long) {
-						spos = filp->f_pos - sizeof(struct msdos_dir_entry);
-					} else {
-						long_slots = 0;
-					}
-					if (fat_filldir(filldir, dirent, bufname, i+dotoffset, 0, oldpos, spos, long_slots, ino) < 0) {
-						filp->f_pos = oldpos;
-						break;
-					}
-				}
-				if (is_long && longnames) {
-					if (both) {
-						memcpy(&longname[long_len+1], bufname, i+dotoffset);
-						long_len += i+dotoffset;
-					}
-					spos = filp->f_pos - sizeof(struct msdos_dir_entry);
-					if (fat_filldir(filldir, dirent, longname, long_len, 1, oldpos, spos, long_slots, ino) < 0) {
-						filp->f_pos = oldpos;
-						break;
-					}
-				}
-				oldpos = filp->f_pos;
+		}
+ParseLong:
+		slots = 0;
+		offset = 0;
+		ds = (struct msdos_dir_slot *) de;
+		id = ds->id;
+		if (!(id & 0x40))
+			goto RecEnd;
+		slots = id & ~0x40;
+		if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */
+			goto RecEnd;
+		long_slots = slots;
+		alias_checksum = ds->alias_checksum;
+
+		slot = slots;
+		while (1) {
+			slot--;
+			offset = slot * 26;
+			memcpy(&unicode[offset], ds->name0_4, 10);
+			memcpy(&unicode[offset+10], ds->name5_10, 12);
+			memcpy(&unicode[offset+22], ds->name11_12, 4);
+			offset += 26;
+
+			if (ds->id & 0x40) {
+				unicode[offset] = 0;
+				unicode[offset+1] = 0;
 			}
-			is_long = 0;
-		} else {
-			is_long = 0;
-			oldpos = filp->f_pos;
+			if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)
+				goto EODir;
+			if (slot == 0)
+				break;
+			ds = (struct msdos_dir_slot *) de;
+			if (ds->attr !=  ATTR_EXT)
+				goto RecEnd;	/* XXX */
+			if ((ds->id & ~0x40) != slot)
+				goto ParseLong;
+			if (ds->alias_checksum != alias_checksum)
+				goto ParseLong;
 		}
-		ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);	
+		if (de->name[0] == (__s8) DELETED_FLAG)
+			goto RecEnd;
+		if (de->attr ==  ATTR_EXT)
+			goto ParseLong;
+		if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))
+			goto RecEnd;
+		for (sum = 0, i = 0; i < 11; i++)
+			sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
+		if (sum != alias_checksum)
+			long_slots = 0;
+	}
+
+	if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
+		*ptname++ = '.';
+		dotoffset = 1;
+	}
+	for (i = 0, last = 0; i < 8;) {
+		if (!(c = de->name[i])) break;
+		if (c >= 'A' && c <= 'Z') c += 32;
+		/* see namei.c, msdos_format_name */
+		if (c == 0x05) c = 0xE5;
+		if ((ptname[i++] = c) != ' ')
+			last = i;
+	}
+	i = last;
+	ptname[i++] = '.';
+	for (i2 = 0; i2 < 3; i2++) {
+		if (!(c = de->ext[i2])) break;
+		if (c >= 'A' && c <= 'Z') c += 32;
+		if ((ptname[i++] = c) != ' ')
+			last = i;
+	}
+	if (!last)
+		goto RecEnd;
+
+	i = last + dotoffset;
+
+	lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);
+	if (!memcmp(de->name,MSDOS_DOT,11))
+		inum = inode->i_ino;
+	else if (!memcmp(de->name,MSDOS_DOTDOT,11)) {
+/*		inum = fat_parent_ino(inode,0); */
+		inum = filp->f_dentry->d_parent->d_inode->i_ino;
+	} else {
+		struct inode *tmp = fat_iget(sb, ino);
+		if (tmp) {
+			inum = tmp->i_ino;
+			iput(tmp);
+		} else
+			inum = iunique(sb, MSDOS_ROOT_INO);
 	}
+
+	if (!long_slots||shortnames) {
+		if (both)
+			bufname[i] = '\0';
+		if (filldir(dirent, bufname, i, *furrfu, inum) < 0)
+			goto FillFailed;
+	} else {
+		char longname[275];
+		unsigned char long_len = utf8
+			? utf8_wcstombs(longname, (__u16 *) unicode, 275)
+			: uni16_to_x8(longname, unicode, uni_xlate, nls);
+		if (both) {
+			memcpy(&longname[long_len+1], bufname, i);
+			long_len += i;
+		}
+		if (filldir(dirent, longname, long_len, *furrfu, inum) < 0)
+			goto FillFailed;
+	}
+
+RecEnd:
+	furrfu = &lpos;
+	filp->f_pos = cpos;
+	goto GetNew;
+EODir:
+	filp->f_pos = cpos;
+FillFailed:
 	if (bh)
 		fat_brelse(sb, bh);
 	if (unicode) {
@@ -344,39 +490,17 @@
 	return 0;
 }
 
-static int fat_filldir(
-	filldir_t filldir,
-	void * buf,
-	const char * name,
-	int name_len,
-	int is_long,
-	off_t offset,
-	off_t short_offset,
-	int long_slots,
-	ino_t ino)
-{
-	return filldir(buf, name, name_len, offset, ino);
-}
-
-int fat_readdir(
-	struct file *filp,
-	void *dirent,
-	filldir_t filldir)
+int fat_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
-	return fat_readdirx(inode, filp, dirent, fat_filldir, filldir,
-			    0, 1, 0);
+	return fat_readdirx(inode, filp, dirent, filldir, 0, 0);
 }
 
 static int vfat_ioctl_fill(
-	filldir_t filldir,
 	void * buf,
 	const char * name,
 	int name_len,
-	int is_long,
 	off_t offset,
-	off_t short_offset,
-	int long_slots,
 	ino_t ino)
 {
 	struct dirent *d1 = (struct dirent *)buf;
@@ -438,7 +562,7 @@
 			return err;
 		put_user(0, &d1->d_reclen);
 		return fat_readdirx(inode,filp,(void *)arg,
-				    vfat_ioctl_fill, NULL, 0, 1, 1);
+				    vfat_ioctl_fill, 0, 1);
 	}
 	case VFAT_IOCTL_READDIR_SHORT: {
 		struct dirent *d1 = (struct dirent *)arg;
@@ -447,7 +571,7 @@
 		if (err)
 			return err;
 		return fat_readdirx(inode,filp,(void *)arg,
-				    vfat_ioctl_fill, NULL, 1, 0, 1);
+				    vfat_ioctl_fill, 1, 1);
 	}
 	default:
 		/* forward ioctl to CVF extension */
@@ -459,6 +583,62 @@
 	}
 
 	return 0;
+}
+
+/***** See if directory is empty */
+int fat_dir_empty(struct inode *dir)
+{
+	loff_t pos;
+	struct buffer_head *bh;
+	struct msdos_dir_entry *de;
+	int ino,result = 0;
+
+	pos = 0;
+	bh = NULL;
+	while (fat_get_entry(dir,&pos,&bh,&de,&ino) > -1) {
+		/* Ignore vfat longname entries */
+		if (de->attr == ATTR_EXT)
+			continue;
+		if (!IS_FREE(de->name) && 
+		    strncmp(de->name,MSDOS_DOT   , MSDOS_NAME) &&
+		    strncmp(de->name,MSDOS_DOTDOT, MSDOS_NAME)) {
+			result = -ENOTEMPTY;
+			break;
+		}
+	}
+	if (bh)
+		fat_brelse(dir->i_sb, bh);
+
+	return result;
+}
+
+/* This assumes that size of cluster is above the 32*slots */
+
+int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
+		  struct msdos_dir_entry **de, int *ino)
+{
+	struct super_block *sb = dir->i_sb;
+	loff_t offset, curr;
+	int row;
+	int res;
+
+	offset = curr = 0;
+	*bh = NULL;
+	row = 0;
+	while (fat_get_entry(dir,&curr,bh,de,ino) > -1) {
+		if (IS_FREE((*de)->name)) {
+			if (++row == slots)
+				return offset;
+		} else {
+			row = 0;
+			offset = curr;
+		}
+	}
+	if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32)) 
+		return -ENOSPC;
+	if ((res = fat_add_cluster(dir)) < 0) return res;
+	do fat_get_entry(dir,&curr,bh,de,ino); while (++row<slots);
+	return offset;
 }
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/fat/fatfs_syms.c linux.pre11.3/fs/fat/fatfs_syms.c
--- linux.vanilla/fs/fat/fatfs_syms.c	Wed Apr 28 19:14:30 1999
+++ linux.pre11.3/fs/fat/fatfs_syms.c	Mon Jul 19 23:26:27 1999
@@ -18,9 +18,11 @@
 extern struct file_operations fat_dir_operations;
 
 EXPORT_SYMBOL(fat_add_cluster);
+EXPORT_SYMBOL(fat_add_cluster1);
 EXPORT_SYMBOL(fat_bmap);
 EXPORT_SYMBOL(fat_brelse);
 EXPORT_SYMBOL(fat_cache_inval_inode);
+EXPORT_SYMBOL(fat_clear_inode);
 EXPORT_SYMBOL(fat_date_unix2dos);
 EXPORT_SYMBOL(fat_delete_inode);
 EXPORT_SYMBOL(fat_dir_operations);
@@ -28,17 +30,18 @@
 EXPORT_SYMBOL(fat_file_read);
 EXPORT_SYMBOL(fat_file_write);
 EXPORT_SYMBOL(fat_fs_panic);
-EXPORT_SYMBOL(fat_get_entry);
+EXPORT_SYMBOL(fat__get_entry);
 EXPORT_SYMBOL(fat_lock_creation);
 EXPORT_SYMBOL(fat_mark_buffer_dirty);
 EXPORT_SYMBOL(fat_mmap);
 EXPORT_SYMBOL(fat_notify_change);
 EXPORT_SYMBOL(fat_parent_ino);
-EXPORT_SYMBOL(fat_put_inode);
 EXPORT_SYMBOL(fat_put_super);
-EXPORT_SYMBOL(fat_read_inode);
+EXPORT_SYMBOL(fat_attach);
+EXPORT_SYMBOL(fat_detach);
+EXPORT_SYMBOL(fat_build_inode);
 EXPORT_SYMBOL(fat_read_super);
-EXPORT_SYMBOL(fat_readdirx);
+EXPORT_SYMBOL(fat_search_long);
 EXPORT_SYMBOL(fat_readdir);
 EXPORT_SYMBOL(fat_scan);
 EXPORT_SYMBOL(fat_smap);
@@ -54,9 +57,11 @@
 EXPORT_SYMBOL(unlock_fat);
 EXPORT_SYMBOL(fat_dir_ioctl);
 EXPORT_SYMBOL(fat_readpage);
-EXPORT_SYMBOL(fat_is_binary);
+EXPORT_SYMBOL(fat_add_entries);
+EXPORT_SYMBOL(fat_dir_empty);
 
 int init_fat_fs(void)
 {
+	fat_hash_init();
 	return 0;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/fat/inode.c linux.pre11.3/fs/fat/inode.c
--- linux.vanilla/fs/fat/inode.c	Wed Apr 28 19:14:30 1999
+++ linux.pre11.3/fs/fat/inode.c	Mon Jul 19 23:26:27 1999
@@ -3,6 +3,7 @@
  *
  *  Written 1992,1993 by Werner Almesberger
  *  VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
+ *  Rewritten for the constant inumbers support by Al Viro
  *
  *  Fixes:
  *
@@ -45,34 +46,123 @@
 #  define PRINTK1(x)
 #endif
 
-void fat_put_inode(struct inode *inode)
+/*
+ * New FAT inode stuff. We do the following:
+ *	a) i_ino is constant and has nothing with on-disk location.
+ *	b) FAT manages its own cache of directory entries.
+ *	c) *This* cache is indexed by on-disk location.
+ *	d) inode has an associated directory entry, all right, but
+ *		it may be unhashed.
+ *	e) currently entries are stored within struct inode. That should
+ *		change.
+ *	f) we deal with races in the following way:
+ *		1. readdir() and lookup() do FAT-dir-cache lookup.
+ *		2. rename() unhashes the F-d-c entry and rehashes it in
+ *			a new place.
+ *		3. unlink() and rmdir() unhash F-d-c entry.
+ *		4. fat_write_inode() checks whether the thing is unhashed.
+ *			If it is we silently return. If it isn't we do bread(),
+ *			check if the location is still valid and retry if it
+ *			isn't. Otherwise we do changes.
+ *		5. Spinlock is used to protect hash/unhash/location check/lookup
+ *		6. fat_clear_inode() unhashes the F-d-c entry.
+ *		7. lookup() and readdir() do igrab() if they find a F-d-c entry
+ *			and consider negative result as cache miss.
+ */
+
+#define FAT_HASH_BITS	8
+#define FAT_HASH_SIZE	(1UL << FAT_HASH_BITS)
+#define FAT_HASH_MASK	(FAT_HASH_SIZE-1)
+static struct list_head fat_inode_hashtable[FAT_HASH_SIZE];
+spinlock_t fat_inode_lock = SPIN_LOCK_UNLOCKED;
+
+void fat_hash_init(void) {
+	int i;
+	for(i=0;i<FAT_HASH_SIZE;i++) {
+		INIT_LIST_HEAD(&fat_inode_hashtable[i]);
+	}
+}
+
+static inline unsigned long fat_hash(struct super_block *sb, int i_pos)
 {
-	/*
-	 * Check whether we're a dependent of other inodes ...
-	 */ 
-	if (inode->i_count <= 1) {
-#ifdef FAT_PARANOIA
-printk("fat_put_inode: last use for (%p,%ld), i_count=%d\n",
-inode, inode->i_ino, inode->i_count); 
-#endif
-		if (inode->i_nlink) {
-			if (MSDOS_I(inode)->i_busy)
-				fat_cache_inval_inode(inode);
-		}
+	unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb;
+	tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS*2);
+	return tmp & FAT_HASH_MASK;
+}
+
+void fat_attach(struct inode *inode, int i_pos) {
+	spin_lock(&fat_inode_lock);
+	MSDOS_I(inode)->i_location = i_pos;
+	list_add(&MSDOS_I(inode)->i_fat_hash,
+		fat_inode_hashtable+fat_hash(inode->i_sb, i_pos));
+	spin_unlock(&fat_inode_lock);
+}
+
+void fat_detach(struct inode *inode) {
+	spin_lock(&fat_inode_lock);
+	MSDOS_I(inode)->i_location = 0;
+	list_del(&MSDOS_I(inode)->i_fat_hash);
+	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
+	spin_unlock(&fat_inode_lock);
+}
+
+struct inode *fat_iget(struct super_block *sb, int i_pos) {
+	struct list_head *p = fat_inode_hashtable + fat_hash(sb, i_pos);
+	struct list_head *walk;
+	struct msdos_inode_info *i;
+	struct inode *inode = NULL;
+	spin_lock(&fat_inode_lock);
+	for(walk=p->next;walk!=p;walk=walk->next) {
+		i = list_entry(walk, struct msdos_inode_info, i_fat_hash);
+		if (i->i_fat_inode->i_sb != sb)
+			continue;
+		if (i->i_location != i_pos)
+			continue;
+		inode = igrab(i->i_fat_inode);
 	}
+	spin_unlock(&fat_inode_lock);
+	return inode;
+}
+
+static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
+
+struct inode *fat_build_inode(struct super_block *sb,
+				struct msdos_dir_entry *de, int ino, int *res)
+{
+	struct inode *inode;
+	*res = 0;
+	inode = fat_iget(sb, ino);
+	if (inode)
+		goto out;
+	inode = get_empty_inode();
+	*res = -ENOMEM;
+	if (!inode)
+		goto out;
+	*res = 0;
+	inode->i_sb = sb;
+	inode->i_dev = sb->s_dev;
+	inode->i_ino = iunique(sb, MSDOS_ROOT_INO);
+	fat_fill_inode(inode, de);
+	fat_attach(inode, ino);
+	insert_inode_hash(inode);
+out:
+	return inode;
 }
 
 void fat_delete_inode(struct inode *inode)
 {
-	/*
-	 * Make sure there are no active dependencies ...
-	 */
-	fat_cache_inval_inode(inode);
 	inode->i_size = 0;
 	fat_truncate(inode);
 	clear_inode(inode);
 }
 
+void fat_clear_inode(struct inode *inode)
+{
+	spin_lock(&fat_inode_lock);
+	fat_cache_inval_inode(inode);
+	list_del(&MSDOS_I(inode)->i_fat_hash);
+	spin_unlock(&fat_inode_lock);
+}
 
 void fat_put_super(struct super_block *sb)
 {
@@ -103,6 +193,8 @@
 		MSDOS_SB(sb)->options.iocharset = NULL;
 	}
 
+	if (MSDOS_SB(sb)->put_super_callback)
+		MSDOS_SB(sb)->put_super_callback(sb);
 	MOD_DEC_USE_COUNT;
 	return;
 }
@@ -267,6 +359,62 @@
 	return ret;
 }
 
+static void fat_read_root(struct inode *inode)
+{
+	struct super_block *sb = inode->i_sb;
+	int nr;
+
+	MSDOS_I(inode)->i_binary = 1;
+	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
+	MSDOS_I(inode)->i_location = 0;
+	MSDOS_I(inode)->i_fat_inode = inode;
+	inode->i_uid = MSDOS_SB(sb)->options.fs_uid;
+	inode->i_gid = MSDOS_SB(sb)->options.fs_gid;
+	inode->i_version = ++event;
+	MSDOS_I(inode)->i_last_pos = 0;
+	inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR;
+	inode->i_op = MSDOS_SB(sb)->dir_ops;
+	if (MSDOS_SB(sb)->fat_bits == 32) {
+		MSDOS_I(inode)->i_start = MSDOS_SB(sb)->root_cluster;
+		if ((nr = MSDOS_I(inode)->i_start) != 0) {
+			while (nr != -1) {
+				inode->i_size += SECTOR_SIZE*MSDOS_SB(sb)->cluster_size;
+				if (!(nr = fat_access(sb,nr,-1))) {
+					printk("Directory %ld: bad FAT\n",
+					       inode->i_ino);
+					break;
+				}
+			}
+		}
+	} else {
+		MSDOS_I(inode)->i_start = 0;
+		inode->i_size = MSDOS_SB(sb)->dir_entries*
+			sizeof(struct msdos_dir_entry);
+	}
+	inode->i_blksize = MSDOS_SB(sb)->cluster_size* SECTOR_SIZE;
+	inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
+		    inode->i_blksize*MSDOS_SB(sb)->cluster_size;
+	MSDOS_I(inode)->i_logstart = 0;
+
+	MSDOS_I(inode)->i_attrs = 0;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
+	MSDOS_I(inode)->i_ctime_ms = 0;
+	inode->i_nlink = fat_subdirs(inode)+2;
+}
+
+static struct super_operations fat_sops = { 
+	NULL,
+	fat_write_inode,
+	NULL,
+	fat_delete_inode,
+	fat_notify_change,
+	fat_put_super,
+	NULL,		/* write_super */
+	fat_statfs,
+	NULL,		/* remount */
+	fat_clear_inode
+};
+
 /*
  * Read the super block of an MS-DOS FS.
  *
@@ -274,7 +422,8 @@
  * with some fields already initialized.
  */
 struct super_block *
-fat_read_super(struct super_block *sb, void *data, int silent)
+fat_read_super(struct super_block *sb, void *data, int silent,
+		struct inode_operations *fs_dir_inode_ops)
 {
 	struct inode *root_inode;
 	struct buffer_head *bh;
@@ -296,6 +445,9 @@
 	MSDOS_SB(sb)->private_data = NULL;
 
 	MOD_INC_USE_COUNT;
+	MSDOS_SB(sb)->dir_ops = fs_dir_inode_ops;
+	MSDOS_SB(sb)->put_super_callback = NULL;
+	sb->s_op = &fat_sops;
 	if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
 		blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
 		if (blksize != 512){
@@ -491,9 +643,14 @@
 		}
 	}
 
-	root_inode = iget(sb, MSDOS_ROOT_INO);
+	root_inode=get_empty_inode();
 	if (!root_inode)
-		goto out_no_root;
+		goto out_unload_nls;
+	root_inode->i_sb = sb;
+	root_inode->i_dev = sb->s_dev;
+	root_inode->i_ino = MSDOS_ROOT_INO;
+	fat_read_root(root_inode);
+	insert_inode_hash(root_inode);
 	sb->s_root = d_alloc_root(root_inode, NULL);
 	if (!sb->s_root)
 		goto out_no_root;
@@ -590,71 +747,29 @@
 	return 0;
 }
 
-void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_ops)
+/* doesn't deal with root inode */
+static void fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 {
 	struct super_block *sb = inode->i_sb;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *raw_entry;
 	int nr;
 
-	PRINTK1(("fat_read_inode: inode=%p, ino=%ld, sb->dir_start=0x%x\n",
-		 inode, inode->i_ino, MSDOS_SB(sb)->dir_start));
-	MSDOS_I(inode)->i_busy = 0;
 	MSDOS_I(inode)->i_binary = 1;
+	INIT_LIST_HEAD(&MSDOS_I(inode)->i_fat_hash);
+	MSDOS_I(inode)->i_location = 0;
+	MSDOS_I(inode)->i_fat_inode = inode;
 	inode->i_uid = MSDOS_SB(sb)->options.fs_uid;
 	inode->i_gid = MSDOS_SB(sb)->options.fs_gid;
 	inode->i_version = ++event;
-	if (inode->i_ino == MSDOS_ROOT_INO) {
-		inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(sb)->options.fs_umask) |
-		    S_IFDIR;
-		inode->i_op = fs_dir_inode_ops;
-		if (MSDOS_SB(sb)->fat_bits == 32) {
-			MSDOS_I(inode)->i_start = MSDOS_SB(sb)->root_cluster;
-			if ((nr = MSDOS_I(inode)->i_start) != 0) {
-				while (nr != -1) {
-					inode->i_size += SECTOR_SIZE*MSDOS_SB(sb)->cluster_size;
-					if (!(nr = fat_access(sb,nr,-1))) {
-						printk("Directory %ld: bad FAT\n",
-						       inode->i_ino);
-						break;
-					}
-				}
-			}
-		} else {
-			MSDOS_I(inode)->i_start = 0;
-			inode->i_size = MSDOS_SB(sb)->dir_entries*
-				sizeof(struct msdos_dir_entry);
-		}
-		inode->i_blksize = MSDOS_SB(sb)->cluster_size*
-		    SECTOR_SIZE;
-		inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
-		    inode->i_blksize*MSDOS_SB(sb)->cluster_size;
-		MSDOS_I(inode)->i_logstart = 0;
-
-		MSDOS_I(inode)->i_attrs = 0;
-		inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
-		MSDOS_I(inode)->i_ctime_ms = 0;
-		inode->i_nlink = fat_subdirs(inode)+2;
-		    /* subdirs (neither . nor ..) plus . and "self" */
-		return;
-	}
-	if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
-		printk("dev = %s, ino = %ld\n",
-		       kdevname(inode->i_dev), inode->i_ino);
-		fat_fs_panic(sb, "fat_read_inode: unable to read i-node block");
-		return;
-	}
-	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
-	    [inode->i_ino & (MSDOS_DPB-1)];
-	if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
-		inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO &
+	if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) {
+		MSDOS_I(inode)->i_last_pos = 0;
+		inode->i_mode = MSDOS_MKMODE(de->attr,S_IRWXUGO &
 		    ~MSDOS_SB(sb)->options.fs_umask) | S_IFDIR;
-		inode->i_op = fs_dir_inode_ops;
+		inode->i_op = MSDOS_SB(inode->i_sb)->dir_ops;
 
-		MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
+		MSDOS_I(inode)->i_start = CF_LE_W(de->start);
 		if (MSDOS_SB(sb)->fat_bits == 32) {
 			MSDOS_I(inode)->i_start |=
-				(CF_LE_W(raw_entry->starthi) << 16);
+				(CF_LE_W(de->starthi) << 16);
 		}
 		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
 		inode->i_nlink = fat_subdirs(inode);
@@ -677,10 +792,10 @@
 				}
 			}
 	} else { /* not a directory */
-		inode->i_mode = MSDOS_MKMODE(raw_entry->attr,
+		inode->i_mode = MSDOS_MKMODE(de->attr,
 		    ((IS_NOEXEC(inode) || 
 		      (MSDOS_SB(sb)->options.showexec &&
-		       !is_exec(raw_entry->ext)))
+		       !is_exec(de->ext)))
 		    	? S_IRUGO|S_IWUGO : S_IRWXUGO)
 		    & ~MSDOS_SB(sb)->options.fs_umask) | S_IFREG;
 		if (MSDOS_SB(sb)->cvf_format)
@@ -691,51 +806,58 @@
 		  inode->i_op = (sb->s_blocksize == 1024 || sb->s_blocksize == 2048)
 			? &fat_file_inode_operations_1024
 			: &fat_file_inode_operations;
-		MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
+		MSDOS_I(inode)->i_start = CF_LE_W(de->start);
 		if (MSDOS_SB(sb)->fat_bits == 32) {
 			MSDOS_I(inode)->i_start |=
-				(CF_LE_W(raw_entry->starthi) << 16);
+				(CF_LE_W(de->starthi) << 16);
 		}
 		MSDOS_I(inode)->i_logstart = MSDOS_I(inode)->i_start;
 		inode->i_nlink = 1;
-		inode->i_size = CF_LE_L(raw_entry->size);
+		inode->i_size = CF_LE_L(de->size);
 	}
-	if(raw_entry->attr & ATTR_SYS)
+	if(de->attr & ATTR_SYS)
 		if (MSDOS_SB(sb)->options.sys_immutable)
 			inode->i_flags |= S_IMMUTABLE;
 	MSDOS_I(inode)->i_binary =
-	    fat_is_binary(MSDOS_SB(sb)->options.conversion, raw_entry->ext);
-	MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
+	    fat_is_binary(MSDOS_SB(sb)->options.conversion, de->ext);
+	MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
 	/* this is as close to the truth as we can get ... */
 	inode->i_blksize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
 	inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
 	    inode->i_blksize*MSDOS_SB(sb)->cluster_size;
 	inode->i_mtime = inode->i_atime =
-	    date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
+	    date_dos2unix(CF_LE_W(de->time),CF_LE_W(de->date));
 	inode->i_ctime =
 		MSDOS_SB(sb)->options.isvfat
-		? date_dos2unix(CF_LE_W(raw_entry->ctime),CF_LE_W(raw_entry->cdate))
+		? date_dos2unix(CF_LE_W(de->ctime),CF_LE_W(de->cdate))
 		: inode->i_mtime;
-	MSDOS_I(inode)->i_ctime_ms = raw_entry->ctime_ms;
-	fat_brelse(sb, bh);
+	MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
 }
 
-
 void fat_write_inode(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *raw_entry;
+	int i_pos;
 
-	if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
-	if (!(bh = fat_bread(sb, inode->i_ino >> MSDOS_DPB_BITS))) {
-		printk("dev = %s, ino = %ld\n",
-		       kdevname(inode->i_dev), inode->i_ino);
+retry:
+	i_pos = MSDOS_I(inode)->i_location;
+	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) return;
+	if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) {
+		printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
 		fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
 		return;
 	}
+	spin_lock(&fat_inode_lock);
+	if (i_pos != MSDOS_I(inode)->i_location) {
+		spin_unlock(&fat_inode_lock);
+		fat_brelse(sb, bh);
+		goto retry;
+	}
+
 	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
-	    [inode->i_ino & (MSDOS_DPB-1)];
+	    [i_pos & (MSDOS_DPB-1)];
 	if (S_ISDIR(inode->i_mode)) {
 		raw_entry->attr = ATTR_DIR;
 		raw_entry->size = 0;
@@ -757,6 +879,7 @@
 		raw_entry->ctime = CT_LE_W(raw_entry->ctime);
 		raw_entry->cdate = CT_LE_W(raw_entry->cdate);
 	}
+	spin_unlock(&fat_inode_lock);
 	fat_mark_buffer_dirty(sb, bh, 1);
 	fat_brelse(sb, bh);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/fat/misc.c linux.pre11.3/fs/fat/misc.c
--- linux.vanilla/fs/fat/misc.c	Wed Apr 28 19:14:30 1999
+++ linux.pre11.3/fs/fat/misc.c	Mon Jul 19 23:26:27 1999
@@ -144,17 +144,17 @@
  * represented by inode. The cluster is zero-initialized.
  */
 
-int fat_add_cluster(struct inode *inode)
+struct buffer_head *fat_add_cluster1(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
 	int count,nr,limit,last,curr,sector,last_sector,file_cluster;
-	struct buffer_head *bh;
+	struct buffer_head *bh, *res=NULL;
 	int cluster_size = MSDOS_SB(sb)->cluster_size;
 
 	if (MSDOS_SB(sb)->fat_bits != 32) {
-		if (inode->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
+		if (inode->i_ino == MSDOS_ROOT_INO) return res;
 	}
-	if (!MSDOS_SB(sb)->free_clusters) return -ENOSPC;
+	if (!MSDOS_SB(sb)->free_clusters) return res;
 	lock_fat(sb);
 	limit = MSDOS_SB(sb)->clusters;
 	nr = limit; /* to keep GCC happy */
@@ -170,7 +170,7 @@
 	if (count >= limit) {
 		MSDOS_SB(sb)->free_clusters = 0;
 		unlock_fat(sb);
-		return -ENOSPC;
+		return res;
 	}
 	fat_access(sb,nr,EOF_FAT(sb));
 	if (MSDOS_SB(sb)->free_clusters != -1)
@@ -202,7 +202,7 @@
 			if (!(curr = fat_access(sb,
 			    last = curr,-1))) {
 				fat_fs_panic(sb,"File without EOF");
-				return -ENOSPC;
+				return res;
 			}
 		}
 		PRINTK ((" --  "));
@@ -235,7 +235,10 @@
 			memset(bh->b_data,0,SECTOR_SIZE);
 			fat_set_uptodate(sb, bh, 1);
 			fat_mark_buffer_dirty(sb, bh, 1);
-			fat_brelse(sb, bh);
+			if (!res)
+				res=bh;
+			else
+				fat_brelse(sb, bh);
 		}
 	}
 	if (file_cluster != inode->i_blocks/cluster_size){
@@ -257,9 +260,17 @@
 #endif
 		mark_inode_dirty(inode);
 	}
-	return 0;
+	return res;
 }
 
+int fat_add_cluster(struct inode *inode)
+{
+	struct buffer_head *bh = fat_add_cluster1(inode);
+	if (!bh)
+		return -ENOSPC;
+	fat_brelse(inode->i_sb, bh);
+	return 0;
+}
 
 /* Linear day numbers of the respective 1sts in non-leap years. */
 
@@ -319,10 +330,17 @@
 
 /* Returns the inode number of the directory entry at offset pos. If bh is
    non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
-   returned in bh. */
+   returned in bh.
+   AV. Most often we do it item-by-item. Makes sense to optimize.
+   AV. OK, there we go: if both bh and de are non-NULL we assume that we just
+   AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
+   AV. It's done in fat_get_entry() (inlined), here the slow case lives.
+   AV. Additionally, when we return -1 (i.e. reached the end of directory)
+   AV. we make bh NULL. 
+ */
 
-int fat_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
-    struct msdos_dir_entry **de)
+int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
+    struct msdos_dir_entry **de, int *ino)
 {
 	struct super_block *sb = dir->i_sb;
 	int sector, offset;
@@ -330,25 +348,24 @@
 	while (1) {
 		offset = *pos;
 		PRINTK (("get_entry offset %d\n",offset));
+		if (*bh)
+			fat_brelse(sb, *bh);
+		*bh = NULL;
 		if ((sector = fat_smap(dir,offset >> SECTOR_BITS)) == -1)
 			return -1;
-		PRINTK (("get_entry sector %d %p\n",sector,*bh));
 		if (!sector)
 			return -1; /* beyond EOF */
 		*pos += sizeof(struct msdos_dir_entry);
-		if (*bh)
-			fat_brelse(sb, *bh);
-		PRINTK (("get_entry sector apres brelse\n"));
 		if (!(*bh = fat_bread(sb, sector))) {
 			printk("Directory sread (sector 0x%x) failed\n",sector);
 			continue;
 		}
-		PRINTK (("get_entry apres sread\n"));
-		*de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset &
-		    (SECTOR_SIZE-1)));
-		return (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
-		    MSDOS_DIR_BITS);
+		break;
 	}
+	*de = (struct msdos_dir_entry*)((*bh)->b_data+(offset&(SECTOR_SIZE-1)));
+	*ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >>
+		    MSDOS_DIR_BITS);
+	return 0;
 }
 
 
@@ -393,14 +410,6 @@
 #define RSS_FREE /* search for free entry */ \
     { \
 	done = IS_FREE(data[entry].name); \
-	if (done) { \
-	    inode = iget(sb,sector*MSDOS_DPS+entry); \
-	    if (inode) { \
-	    /* Directory slots of busy deleted files aren't available yet. */ \
-		done = !MSDOS_I(inode)->i_busy; \
-		iput(inode); \
-	    } \
-	} \
     }
 
 #define RSS_COUNT /* count subdirectories */ \
@@ -412,11 +421,10 @@
 
 static int raw_scan_sector(struct super_block *sb,int sector,const char *name,
     int *number,int *ino,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de,char scantype)
+    struct msdos_dir_entry **res_de)
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *data;
-	struct inode *inode;
 	int entry,start,done;
 
 	if (!(bh = fat_bread(sb,sector)))
@@ -426,11 +434,6 @@
 /* RSS_COUNT:  if (data[entry].name == name) done=true else done=false. */
 		if (name) {
 			RSS_NAME
-			if (done && scantype) {   /* scantype != SCAN_ANY */
-				done = (data[entry].attr & ATTR_HIDDEN)
-					? (scantype==SCAN_HID)
-					: (scantype==SCAN_NOTHID);
-			}
 		} else {
 			if (!ino) RSS_COUNT
 			else {
@@ -464,13 +467,13 @@
  */
 
 static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino,
-    struct buffer_head **res_bh,struct msdos_dir_entry **res_de,char scantype)
+    struct buffer_head **res_bh,struct msdos_dir_entry **res_de)
 {
 	int count,cluster;
 
 	for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) {
 		if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count,
-		    name,number,ino,res_bh,res_de,scantype)) >= 0) return cluster;
+		    name,number,ino,res_bh,res_de)) >= 0) return cluster;
 	}
 	return -ENOENT;
 }
@@ -483,7 +486,7 @@
 
 static int raw_scan_nonroot(struct super_block *sb,int start,const char *name,
     int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry
-    **res_de,char scantype)
+    **res_de)
 {
 	int count,cluster;
 
@@ -494,7 +497,7 @@
 		for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) {
 			if ((cluster = raw_scan_sector(sb,(start-2)*
 			    MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+
-			    count,name,number,ino,res_bh,res_de,scantype)) >= 0)
+			    count,name,number,ino,res_bh,res_de)) >= 0)
 				return cluster;
 		}
 		if (!(start = fat_access(sb,start,-1))) {
@@ -519,12 +522,12 @@
 
 static int raw_scan(struct super_block *sb, int start, const char *name,
     int *number, int *ino, struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de, char scantype)
+    struct msdos_dir_entry **res_de)
 {
 	if (start) return raw_scan_nonroot
-		(sb,start,name,number,ino,res_bh,res_de,scantype);
+		(sb,start,name,number,ino,res_bh,res_de);
 	else return raw_scan_root
-		(sb,name,number,ino,res_bh,res_de,scantype);
+		(sb,name,number,ino,res_bh,res_de);
 }
 
 
@@ -532,6 +535,11 @@
  * fat_parent_ino returns the inode number of the parent directory of dir.
  * File creation has to be deferred while fat_parent_ino is running to
  * prevent renames.
+ *
+ * AV. Bad, bad, bad... We need a mapping that would give us inode by
+ * first cluster. Sheeeeit... OK, we can do it on fat_fill_inode() and
+ * update on fat_add_cluster(). When will we remove it? fat_clear_inode()
+ * and fat_truncate() to zero?
  */
 
 int fat_parent_ino(struct inode *dir,int locked)
@@ -544,7 +552,7 @@
 	if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino;
 	if (!locked) fat_lock_creation(); /* prevent renames */
 	if ((curr = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT,
-	    &zero,NULL,NULL,NULL,SCAN_ANY)) < 0) {
+	    &zero,NULL,NULL,NULL)) < 0) {
 		if (!locked) fat_unlock_creation();
 		return curr;
 	}
@@ -553,7 +561,7 @@
 	else {
 		PRINTK(("fat_parent_ino: Debug 2\n"));
 		if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL,
-		    NULL,NULL,SCAN_ANY)) < 0) {
+		    NULL,NULL)) < 0) {
 			PRINTK(("fat_parent_ino: Debug 3 prev=%d\n", prev));
 			if (!locked) fat_unlock_creation();
 			return prev;
@@ -563,7 +571,7 @@
 			prev = MSDOS_SB(dir->i_sb)->root_cluster;
 		}
 		if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL,
-		    NULL,SCAN_ANY)) < 0) {
+		    NULL)) < 0) {
 			PRINTK(("fat_parent_ino: Debug 5 error=%d\n", error));
 			if (!locked) fat_unlock_creation();
 			return error;
@@ -587,12 +595,12 @@
 	count = 0;
 	if ((dir->i_ino == MSDOS_ROOT_INO) &&
 	    (MSDOS_SB(dir->i_sb)->fat_bits != 32)) {
-		(void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL,SCAN_ANY);
+		(void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL);
 	} else {
 		if ((dir->i_ino != MSDOS_ROOT_INO) &&
 		    !MSDOS_I(dir)->i_start) return 0; /* in mkdir */
 		else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start,
-		    NULL,&count,NULL,NULL,NULL,SCAN_ANY);
+		    NULL,&count,NULL,NULL,NULL);
 	}
 	return count;
 }
@@ -604,11 +612,11 @@
  */
 
 int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
-    struct msdos_dir_entry **res_de,int *ino, char scantype)
+    struct msdos_dir_entry **res_de,int *ino)
 {
 	int res;
 
 	res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,
-		       name, NULL, ino, res_bh, res_de, scantype);
+		       name, NULL, ino, res_bh, res_de);
 	return res<0 ? res : 0;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/filesystems.c linux.pre11.3/fs/filesystems.c
--- linux.vanilla/fs/filesystems.c	Sun Nov  8 15:06:33 1998
+++ linux.pre11.3/fs/filesystems.c	Mon Jul 19 23:26:26 1999
@@ -22,6 +22,7 @@
 #include <linux/ncp_fs.h>
 #include <linux/affs_fs.h>
 #include <linux/ufs_fs.h>
+#include <linux/efs_fs.h>
 #include <linux/romfs_fs.h>
 #include <linux/auto_fs.h>
 #include <linux/qnx4_fs.h>
@@ -127,6 +128,10 @@
 
 #ifdef CONFIG_UFS_FS
 	init_ufs_fs();
+#endif
+
+#ifdef CONFIG_EFS_FS
+	init_efs_fs();
 #endif
 
 #ifdef CONFIG_AUTOFS_FS
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/inode.c linux.pre11.3/fs/inode.c
--- linux.vanilla/fs/inode.c	Thu May 27 22:11:57 1999
+++ linux.pre11.3/fs/inode.c	Mon Jul 19 23:26:25 1999
@@ -44,7 +44,7 @@
  * allowing for low-overhead inode sync() operations.
  */
 
-static LIST_HEAD(inode_in_use);
+LIST_HEAD(inode_in_use);
 static LIST_HEAD(inode_unused);
 static struct list_head inode_hashtable[HASH_SIZE];
 
@@ -296,6 +296,7 @@
 			INIT_LIST_HEAD(&inode->i_hash);
 			list_del(&inode->i_list);
 			list_add(&inode->i_list, dispose);
+			inode->i_state |= I_FREEING;
 			continue;
 		}
 		busy = 1;
@@ -356,6 +357,7 @@
 		list_del(&INODE(tmp)->i_hash);
 		INIT_LIST_HEAD(&INODE(tmp)->i_hash);
 		list_add(tmp, freeable);
+		list_entry(tmp, struct inode, i_list)->i_state = I_FREEING;
 		found = 1;
 	}
 
@@ -639,6 +641,43 @@
 	return tmp & HASH_MASK;
 }
 
+/* Yeah, I know about quadratic hash. Maybe, later. */
+ino_t iunique(struct super_block *sb, ino_t max_reserved)
+{
+	static ino_t counter = 0;
+	struct inode *inode;
+	struct list_head * head;
+	ino_t res;
+	spin_lock(&inode_lock);
+retry:
+	if (counter > max_reserved) {
+		head = inode_hashtable + hash(sb,counter);
+		inode = find_inode(sb, res = counter++, head);
+		if (!inode) {
+			spin_unlock(&inode_lock);
+			return res;
+		}
+		inode->i_count--; /* compensate find_inode() */
+	} else {
+		counter = max_reserved + 1;
+	}
+	goto retry;
+	
+}
+
+struct inode *igrab(struct inode *inode)
+{
+	spin_lock(&inode_lock);
+	if (inode->i_state & I_FREEING)
+		inode = NULL;
+	else
+		inode->i_count++;
+	spin_unlock(&inode_lock);
+	if (inode)
+		wait_on_inode(inode);
+	return inode;
+}
+
 struct inode *iget(struct super_block *sb, unsigned long ino)
 {
 	struct list_head * head = inode_hashtable + hash(sb,ino);
@@ -692,6 +731,7 @@
 				INIT_LIST_HEAD(&inode->i_hash);
 				list_del(&inode->i_list);
 				INIT_LIST_HEAD(&inode->i_list);
+				inode->i_state|=I_FREEING;
 				if (op && op->delete_inode) {
 					void (*delete)(struct inode *) = op->delete_inode;
 					spin_unlock(&inode_lock);
@@ -702,6 +742,7 @@
 			if (list_empty(&inode->i_hash)) {
 				list_del(&inode->i_list);
 				INIT_LIST_HEAD(&inode->i_list);
+				inode->i_state|=I_FREEING;
 				spin_unlock(&inode_lock);
 				clear_inode(inode);
 				spin_lock(&inode_lock);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ioctl.c linux.pre11.3/fs/ioctl.c
--- linux.vanilla/fs/ioctl.c	Mon Mar 29 10:25:56 1999
+++ linux.pre11.3/fs/ioctl.c	Mon Jul 19 23:26:25 1999
@@ -18,6 +18,8 @@
 
 	switch (cmd) {
 		case FIBMAP:
+			if (!capable(CAP_SYS_RAWIO))
+				return -EPERM;
 			if (inode->i_op == NULL)
 				return -EBADF;
 		    	if (inode->i_op->bmap == NULL)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/isofs/namei.c linux.pre11.3/fs/isofs/namei.c
--- linux.vanilla/fs/isofs/namei.c	Thu May 27 22:11:57 1999
+++ linux.pre11.3/fs/isofs/namei.c	Tue Jul 20 00:09:02 1999
@@ -147,6 +147,8 @@
 			
 			de = (struct iso_directory_record *)
 				kmalloc(offset - old_offset, GFP_KERNEL);
+			if(de==NULL)
+				break;
 			memcpy((char *)de, bh->b_data + old_offset, 
 			       bufsize - old_offset);
 			memcpy((char *)de + bufsize - old_offset,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/locks.c linux.pre11.3/fs/locks.c
--- linux.vanilla/fs/locks.c	Thu May 27 22:11:58 1999
+++ linux.pre11.3/fs/locks.c	Mon Jul 19 23:26:25 1999
@@ -341,7 +341,11 @@
 		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
 		if (error < 0)
 			goto out_putf;
-		fl = &file_lock;
+		else if (error == LOCK_USE_CLNT)
+		  /* Bypass for NFS with no locking - 2.0.36 compat */
+		  fl = posix_test_lock(filp, &file_lock);
+		else
+		  fl = (file_lock.fl_type == F_UNLCK ? NULL : &file_lock);
 	} else {
 		fl = posix_test_lock(filp, &file_lock);
 	}
@@ -512,7 +516,9 @@
 	while ((fl = *before) != NULL) {
 		if ((fl->fl_flags & FL_FLOCK) && fl->fl_file == filp) {
 			int (*lock)(struct file *, int, struct file_lock *);
-			lock = filp->f_op->lock;
+			lock = NULL;
+			if (filp->f_op)
+				lock = filp->f_op->lock;
 			if (lock) {
 				file_lock = *fl;
 				file_lock.fl_type = F_UNLCK;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/minix/file.c linux.pre11.3/fs/minix/file.c
--- linux.vanilla/fs/minix/file.c	Sun Nov  8 15:06:33 1998
+++ linux.pre11.3/fs/minix/file.c	Mon Jul 19 23:26:25 1999
@@ -25,7 +25,6 @@
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
 #include <linux/fs.h>
-#include <linux/minix_fs.h>
 
 static ssize_t minix_file_write(struct file *, const char *, size_t, loff_t *);
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/msdos/msdosfs_syms.c linux.pre11.3/fs/msdos/msdosfs_syms.c
--- linux.vanilla/fs/msdos/msdosfs_syms.c	Sun Nov  8 15:06:32 1998
+++ linux.pre11.3/fs/msdos/msdosfs_syms.c	Mon Jul 19 23:26:25 1999
@@ -20,11 +20,9 @@
 EXPORT_SYMBOL(msdos_create);
 EXPORT_SYMBOL(msdos_lookup);
 EXPORT_SYMBOL(msdos_mkdir);
-EXPORT_SYMBOL(msdos_read_inode);
 EXPORT_SYMBOL(msdos_rename);
 EXPORT_SYMBOL(msdos_rmdir);
 EXPORT_SYMBOL(msdos_unlink);
-EXPORT_SYMBOL(msdos_unlink_umsdos);
 EXPORT_SYMBOL(msdos_read_super);
 EXPORT_SYMBOL(msdos_put_super);
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/msdos/namei.c linux.pre11.3/fs/msdos/namei.c
--- linux.vanilla/fs/msdos/namei.c	Wed Apr 28 19:14:31 1999
+++ linux.pre11.3/fs/msdos/namei.c	Mon Jul 19 23:26:25 1999
@@ -3,6 +3,7 @@
  *
  *  Written 1992,1993 by Werner Almesberger
  *  Hidden files 1995 by Albert Cahalan <albert@ccs.neu.edu> <adc@coe.neu.edu>
+ *  Rewritten for constant inumbers 1999 by Al Viro
  */
 
 
@@ -43,43 +44,24 @@
 static char bad_if_strict[] = "+=,; ";
 #endif
 
+/* Must die */
 void msdos_put_super(struct super_block *sb)
 {
 	fat_put_super(sb);
-	MOD_DEC_USE_COUNT;
 }
 
-struct super_operations msdos_sops = { 
-	msdos_read_inode,
-	fat_write_inode,
-	fat_put_inode,
-	fat_delete_inode,
-	fat_notify_change,
-	msdos_put_super,
-	NULL, /* added in 0.96c */
-	fat_statfs,
-	NULL
-};
-
 /***** Formats an MS-DOS file name. Rejects invalid names. */
 static int msdos_format_name(char conv,const char *name,int len,
-	char *res,int dot_dirs,char dotsOK)
+	char *res,char dotsOK)
 	/* conv is relaxed/normal/strict, name is proposed name,
 	 * len is the length of the proposed name, res is the result name,
-	 * dot_dirs is . and .. are OK, dotsOK is if hidden files get dots.
+	 * dotsOK is if hidden files get dots.
 	 */
 {
 	char *walk;
 	const char **reserved;
 	unsigned char c;
 	int space;
-
-	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
-		if (!dot_dirs) return -EEXIST;
-		memset(res+1,' ',10);
-		while (len--) *res++ = '.';
-		return 0;
-	}
 	if (name[0] == '.') {  /* dotfile because . and .. already done */
 		if (!dotsOK) return -EINVAL;
 		/* Get rid of dot - test for it elsewhere */
@@ -142,32 +124,31 @@
 	return 0;
 }
 
-
 /***** Locates a directory entry.  Uses unformatted name. */
 static int msdos_find(struct inode *dir,const char *name,int len,
     struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
 {
 	int res;
 	char dotsOK;
-	char scantype;
 	char msdos_name[MSDOS_NAME];
 
 	dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK;
 	res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,
-				name,len, msdos_name,1,dotsOK);
+				name,len, msdos_name,dotsOK);
 	if (res < 0)
 		return -ENOENT;
-	if((name[0]=='.') && dotsOK){
-	    switch(len){
-		case  0: panic("Empty name in msdos_find!");
-		case  1: scantype = SCAN_ANY;				break;
-		case  2: scantype = ((name[1]=='.')?SCAN_ANY:SCAN_HID); break;
-		default: scantype = SCAN_HID;
-	    }
-	} else {
-	    scantype = (dotsOK ? SCAN_NOTHID : SCAN_ANY);
+	res = fat_scan(dir,msdos_name,bh,de,ino);
+	if (!res && dotsOK) {
+		if (name[0]=='.') {
+			if (!((*de)->attr & ATTR_HIDDEN))
+				res = -ENOENT;
+		} else {
+			if ((*de)->attr & ATTR_HIDDEN)
+				res = -ENOENT;
+		}
 	}
-	return fat_scan(dir,msdos_name,bh,de,ino,scantype);
+	return res;
+
 }
 
 /*
@@ -183,7 +164,7 @@
 	char msdos_name[MSDOS_NAME];
 	
 	error = msdos_format_name(options->name_check, qstr->name, qstr->len,
-					msdos_name, 1, options->dotsOK);
+					msdos_name, options->dotsOK);
 	if (!error)
 		qstr->hash = full_name_hash(msdos_name, MSDOS_NAME);
 	return 0;
@@ -200,11 +181,11 @@
 	char a_msdos_name[MSDOS_NAME], b_msdos_name[MSDOS_NAME];
 
 	error = msdos_format_name(options->name_check, a->name, a->len,
-					a_msdos_name, 1, options->dotsOK);
+					a_msdos_name, options->dotsOK);
 	if (error)
 		goto old_compare;
 	error = msdos_format_name(options->name_check, b->name, b->len,
-					b_msdos_name, 1, options->dotsOK);
+					b_msdos_name, options->dotsOK);
 	if (error)
 		goto old_compare;
 	error = memcmp(a_msdos_name, b_msdos_name, MSDOS_NAME);
@@ -228,26 +209,9 @@
 	NULL
 };
 
-struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
-{
-	struct super_block *res;
-
-	MOD_INC_USE_COUNT;
-
-	MSDOS_SB(sb)->options.isvfat = 0;
-	sb->s_op = &msdos_sops;
-	res = fat_read_super(sb, data, silent);
-	if (res == NULL)
-		goto out_fail;
-	sb->s_root->d_op = &msdos_dentry_operations;
-	return res;
-
-out_fail:
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
-	return NULL;
-}
-
+/*
+ * AV. Wrappers for FAT sb operations. Is it wise?
+ */
 
 /***** Get inode using directory and name */
 struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry)
@@ -255,7 +219,7 @@
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode = NULL;
 	struct msdos_dir_entry *de;
-	struct buffer_head *bh;
+	struct buffer_head *bh = NULL;
 	int ino,res;
 	
 	PRINTK (("msdos_lookup\n"));
@@ -269,76 +233,52 @@
 		goto add;
 	if (res < 0)
 		goto out;
-	if (bh)
-		fat_brelse(sb, bh);
-
-	/* try to get the inode */
-	res = -EACCES;
-	inode = iget(sb, ino);
-	if (!inode)
-		goto out;
-	if (!inode->i_sb ||
-	   (inode->i_sb->s_magic != MSDOS_SUPER_MAGIC)) {
-		printk(KERN_WARNING "msdos_lookup: foreign inode??\n");
-	}
-	/* mkdir in progress? */
-	if (MSDOS_I(inode)->i_busy) {
-		printk(KERN_WARNING "msdos_lookup: %s/%s busy\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name);
-		iput(inode);
+	inode = fat_build_inode(sb, de, ino, &res);
+	if (res)
 		goto out;
-	}
 add:
 	d_add(dentry, inode);
 	res = 0;
 out:
+	if (bh)
+		fat_brelse(sb, bh);
 	return ERR_PTR(res);
 }
 
-
 /***** Creates a directory entry (name is already formatted). */
-static int msdos_create_entry(struct inode *dir, const char *name,
-    int is_dir, int is_hid, struct inode **result)
+static int msdos_add_entry(struct inode *dir, const char *name,
+			   struct buffer_head **bh,
+			   struct msdos_dir_entry **de,
+			   int *ino,
+			   int is_dir, int is_hid)
 {
 	struct super_block *sb = dir->i_sb;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
-	int res,ino;
+	int res;
 
-	*result = NULL;
-	if ((res = fat_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) {
-		if (res != -ENOENT) return res;
-		if ((dir->i_ino == MSDOS_ROOT_INO) &&
-		    (MSDOS_SB(sb)->fat_bits != 32))
-			return -ENOSPC;
-		if ((res = fat_add_cluster(dir)) < 0) return res;
-		if ((res = fat_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) return res;
-	}
+	if ((res = fat_add_entries(dir, 1, bh, de, ino))<0)
+		return res;
 	/*
 	 * XXX all times should be set by caller upon successful completion.
 	 */
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(dir);
-	memcpy(de->name,name,MSDOS_NAME);
-	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
-	de->attr = is_hid ? (de->attr|ATTR_HIDDEN) : (de->attr&~ATTR_HIDDEN);
-	de->start = 0;
-	de->starthi = 0;
-	fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
-	de->size = 0;
-	fat_mark_buffer_dirty(sb, bh, 1);
-
-	if ((*result = iget(dir->i_sb,ino)) != NULL)
-		msdos_read_inode(*result);
-	fat_brelse(sb, bh);
-	if (!*result) return -EIO;
-	(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
-	    CURRENT_TIME;
-	mark_inode_dirty(*result);
+	memcpy((*de)->name,name,MSDOS_NAME);
+	(*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
+	if (is_hid)
+		(*de)->attr |= ATTR_HIDDEN;
+	(*de)->start = 0;
+	(*de)->starthi = 0;
+	fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
+	(*de)->size = 0;
+	fat_mark_buffer_dirty(sb, *bh, 1);
 	return 0;
 }
 
-/***** Create a file or directory */
+/*
+ * AV. Huh??? It's exported. Oughtta check usage.
+ */
+
+/***** Create a file */
 int msdos_create(struct inode *dir,struct dentry *dentry,int mode)
 {
 	struct super_block *sb = dir->i_sb;
@@ -350,79 +290,27 @@
 
 	res = msdos_format_name(MSDOS_SB(sb)->options.name_check,
 				dentry->d_name.name,dentry->d_name.len,
-				msdos_name,0,
-				MSDOS_SB(sb)->options.dotsOK);
+				msdos_name, MSDOS_SB(sb)->options.dotsOK);
 	if (res < 0)
 		return res;
 	is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.');
-	fat_lock_creation();
-	/* Scan for existing file twice, so that creating a file fails
-	 * with -EINVAL if the other (dotfile/nondotfile) exists.
-	 * Else SCAN_ANY would do. Maybe use EACCES, EBUSY, ENOSPC, ENFILE?
-	 */
-	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_HID) >= 0) {
-		fat_unlock_creation();
-		fat_brelse(sb, bh);
-		return is_hid ? -EEXIST : -EINVAL;
- 	}
-	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_NOTHID) >= 0) {
-		fat_unlock_creation();
+	/* Have to do it due to foo vs. .foo conflicts */
+	if (fat_scan(dir,msdos_name,&bh,&de,&ino) >= 0) {
 		fat_brelse(sb, bh);
-		return is_hid ? -EINVAL : -EEXIST;
+		return -EINVAL;
  	}
-	res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),is_hid,
-				 &inode);
-	fat_unlock_creation();
-	if (!res)
-		d_instantiate(dentry, inode);
-	return res;
-}
-
-
-#ifdef DEBUG
-
-static void dump_fat(struct super_block *sb,int start)
-{
-	printk("[");
-	while (start) {
-		printk("%d ",start);
-        	start = fat_access(sb,start,-1);
-		if (!start) {
-			printk("ERROR");
-			break;
-		}
-		if (start == -1) break;
-	}
-	printk("]\n");
-}
-
-#endif
-
-/***** See if directory is empty */
-static int msdos_empty(struct inode *dir)
-{
-	loff_t pos;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
-	int result = 0;
-
-	pos = 0;
-	bh = NULL;
-	while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
-		/* Ignore vfat longname entries */
-		if (de->attr == ATTR_EXT)
-			continue;
-		if (!IS_FREE(de->name) && 
-		    strncmp(de->name,MSDOS_DOT   , MSDOS_NAME) &&
-		    strncmp(de->name,MSDOS_DOTDOT, MSDOS_NAME)) {
-			result = -ENOTEMPTY;
-			break;
-		}
-	}
-	if (bh)
-		fat_brelse(dir->i_sb, bh);
-
-	return result;
+	inode = NULL;
+	res = msdos_add_entry(dir, msdos_name, &bh, &de, &ino, 0, is_hid);
+	if (res)
+		return res;
+	inode = fat_build_inode(dir->i_sb, de, ino, &res);
+	fat_brelse(sb, bh);
+	if (!inode)
+		return res;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	d_instantiate(dentry, inode);
+	return 0;
 }
 
 /***** Remove a directory */
@@ -446,23 +334,19 @@
 	res = -EBUSY;
 	if (!list_empty(&dentry->d_hash))
 		goto rmdir_done;
-	res = msdos_empty(inode);
+	res = fat_dir_empty(inode);
 	if (res)
 		goto rmdir_done;
 
+	de->name[0] = DELETED_FLAG;
+	fat_mark_buffer_dirty(sb, bh, 1);
+	fat_detach(inode);
 	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);
-	/*
-	 * Do the d_delete before any blocking operations.
-	 * We must make a negative dentry, as the FAT code
-	 * apparently relies on the inode being iput().
-	 */
 	d_delete(dentry);
-	de->name[0] = DELETED_FLAG;
-	fat_mark_buffer_dirty(sb, bh, 1);
 	res = 0;
 
 rmdir_done:
@@ -476,77 +360,94 @@
 	struct super_block *sb = dir->i_sb;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	struct inode *inode,*dot;
-	int ino,res,is_hid;
+	struct inode *inode;
+	int res,is_hid;
 	char msdos_name[MSDOS_NAME];
+	struct buffer_head *bh1;
+	struct msdos_dir_entry *de1;
+	int ino;
 
 	res = msdos_format_name(MSDOS_SB(sb)->options.name_check,
 				dentry->d_name.name,dentry->d_name.len,
-				msdos_name,0,
-				MSDOS_SB(sb)->options.dotsOK);
+				msdos_name,MSDOS_SB(sb)->options.dotsOK);
 	if (res < 0)
 		return res;
 	is_hid = (dentry->d_name.name[0]=='.') && (msdos_name[0]!='.');
-	fat_lock_creation();
-	if (fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0)
+	/* foo vs .foo situation */
+	if (fat_scan(dir,msdos_name,&bh,&de,&ino) >= 0)
 		goto out_exist;
 
-	res = msdos_create_entry(dir,msdos_name,1,is_hid, &inode);
-	if (res < 0)
+	res = msdos_add_entry(dir, msdos_name, &bh, &de, &ino, 1, is_hid);
+	if (res)
 		goto out_unlock;
+	inode = fat_build_inode(dir->i_sb, de, ino, &res);
+	if (!inode) {
+		fat_brelse(sb, bh);
+		goto out_unlock;
+	}
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	res = 0;
 
 	dir->i_nlink++;
 	inode->i_nlink = 2; /* no need to mark them dirty */
 
-	if ((res = fat_add_cluster(inode)) < 0)
+	if (!(bh1 = fat_add_cluster1(inode))) {
+		res = -ENOSPC;
 		goto mkdir_error;
-	if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0)
-		goto mkdir_error;
-	dot->i_size = inode->i_size; /* doesn't grow in the 2nd create_entry */
-	MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
-	MSDOS_I(dot)->i_logstart = MSDOS_I(inode)->i_logstart;
-	dot->i_nlink = inode->i_nlink;
-	mark_inode_dirty(dot);
-	iput(dot);
+	}
+	fat_brelse(sb, bh);
+	de1 = (struct msdos_dir_entry *)bh1->b_data;
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(inode);
 
-	if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,0,&dot)) < 0)
-		goto mkdir_error;
-	dot->i_size = dir->i_size;
-	MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
-	MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
-	dot->i_nlink = dir->i_nlink;
-	mark_inode_dirty(dot);
-	iput(dot);
+	memcpy(de1->name,MSDOS_DOT,MSDOS_NAME);
+	de1->attr = ATTR_DIR;
+	de1->start = CT_LE_W(MSDOS_I(inode)->i_logstart);
+	de1->starthi = CT_LE_W(MSDOS_I(inode)->i_logstart >> 16);
+	fat_date_unix2dos(inode->i_mtime,&de1->time,&de1->date);
+	de1->size = 0;
+	de1->time = CT_LE_W(de1->time);
+	de1->date = CT_LE_W(de1->date);
+	de1++;
+	memcpy(de1->name,MSDOS_DOTDOT,MSDOS_NAME);
+	de1->attr = ATTR_DIR;
+	de1->start = CT_LE_W(MSDOS_I(dir)->i_logstart);
+	de1->starthi = CT_LE_W(MSDOS_I(dir)->i_logstart >> 16);
+	fat_date_unix2dos(dir->i_mtime,&de1->time,&de1->date);
+	de1->size = 0;
+	de1->time = CT_LE_W(de1->time);
+	de1->date = CT_LE_W(de1->date);
+	fat_mark_buffer_dirty(sb, bh1, 1);
+	fat_brelse(sb, bh1);
 	d_instantiate(dentry, inode);
 	res = 0;
 
 out_unlock:
-	fat_unlock_creation();
 	return res;
 
 mkdir_error:
 	printk("msdos_mkdir: error=%d, attempting cleanup\n", res);
-	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);
+	fat_detach(inode);
+	iput(inode);
 	goto out_unlock;
 
 out_exist:
 	fat_brelse(sb, bh);
-	res = -EEXIST;
+	res = -EINVAL;
 	goto out_unlock;
 }
 
 /***** Unlink a file */
-static int msdos_unlinkx( struct inode *dir, struct dentry *dentry, int nospc)
+int msdos_unlink( struct inode *dir, struct dentry *dentry)
 {
 	struct super_block *sb = dir->i_sb;
 	struct inode *inode = dentry->d_inode;
@@ -559,39 +460,21 @@
 			&bh, &de, &ino);
 	if (res < 0)
 		goto unlink_done;
-	res = -EPERM;
-	if (!S_ISREG(inode->i_mode) && nospc)
-		goto unlink_done;
-	/* N.B. check for busy files? */
 
+	de->name[0] = DELETED_FLAG;
+	fat_mark_buffer_dirty(sb, bh, 1);
+	fat_detach(inode);
+	fat_brelse(sb, bh);
 	inode->i_nlink = 0;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	MSDOS_I(inode)->i_busy = 1;
 	mark_inode_dirty(inode);
 	mark_inode_dirty(dir);
 	d_delete(dentry);	/* This also frees the inode */
-	de->name[0] = DELETED_FLAG;
-	fat_mark_buffer_dirty(sb, bh, 1);
 	res = 0;
 unlink_done:
-	fat_brelse(sb, bh);
 	return res;
 }
 
-/***** Unlink, as called for msdosfs */
-int msdos_unlink(struct inode *dir,struct dentry *dentry)
-{
-	return msdos_unlinkx (dir,dentry,1);
-}
-
-/***** Unlink, as called for umsdosfs */
-int msdos_unlink_umsdos(struct inode *dir,struct dentry *dentry)
-{
-	return msdos_unlinkx (dir,dentry,0);
-}
-
-/* Now we could merge it with msdos_rename_same. Later */
-/***** Rename across directories - a nonphysical move */
 static int do_msdos_rename(struct inode *old_dir, char *old_name,
     struct dentry *old_dentry,
     struct inode *new_dir,char *new_name, struct dentry *new_dentry,
@@ -599,157 +482,97 @@
     struct msdos_dir_entry *old_de, int old_ino, int is_hid)
 {
 	struct super_block *sb = old_dir->i_sb;
-	struct buffer_head *new_bh,*free_bh,*dotdot_bh;
-	struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
-	struct inode *old_inode,*new_inode,*dotdot_inode;
-	int new_ino,free_ino,dotdot_ino;
-	int error, exists;
+	struct buffer_head *new_bh=NULL,*dotdot_bh=NULL;
+	struct msdos_dir_entry *new_de,*dotdot_de;
+	struct inode *old_inode,*new_inode;
+	int new_ino,dotdot_ino;
+	int error;
+	int is_dir;
 
 	old_inode = old_dentry->d_inode;
-	if (old_dir==new_dir && !strncmp(old_name, new_name, MSDOS_NAME))
-		goto set_hid;
-	error = -ENOENT;
-	if (*(unsigned char *) old_de->name == DELETED_FLAG)
-		goto out;
+	new_inode = new_dentry->d_inode;
+	is_dir = S_ISDIR(old_inode->i_mode);
 
-	/* find free spot */
-	if (new_dir!=old_dir)
-		while ((error = fat_scan(new_dir, NULL, &free_bh, &free_de,
-					&free_ino, SCAN_ANY)) < 0) {
-			if (error != -ENOENT)
-				goto out;
-			error = fat_add_cluster(new_dir);
+	if (fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino)>=0 &&!new_inode)
+		goto degenerate_case;
+	if (is_dir) {
+		if (new_inode) {
+			error = fat_dir_empty(new_inode);
 			if (error)
 				goto out;
 		}
-
-	exists = fat_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
-	if (exists) {  /* Trash the old file! */
-		error = -EIO;
-		new_inode = new_dentry->d_inode;
-		/* Make sure it really exists ... */
-		if (!new_inode) {
-			printk(KERN_ERR
-				"msdos_rename: %s/%s inode NULL, ino=%d\n",
-				new_dentry->d_parent->d_name.name,
-				new_dentry->d_name.name, new_ino);
-			d_drop(new_dentry);
-			goto out_new;
-		}
- 		error = -EPERM;
-		if ((old_de->attr & ATTR_SYS))
-			goto out_new;
-
-		if (S_ISDIR(new_inode->i_mode)) {
-			error = msdos_empty(new_inode);
-			if (error)
-				goto out_new;
-			new_dir->i_nlink--;
-			mark_inode_dirty(new_dir);
-		}
-		new_inode->i_nlink = 0;
-		MSDOS_I(new_inode)->i_busy = 1;
-		mark_inode_dirty(new_inode);
-
-		new_de->name[0] = DELETED_FLAG;
-		fat_mark_buffer_dirty(sb, new_bh, 1);
-		fat_brelse(sb, new_bh);
-	}
-
-	if (old_dir==new_dir) {
-		memcpy(old_de->name, new_name, MSDOS_NAME);
-set_hid:
-		old_de->attr = is_hid
-			? (old_de->attr | ATTR_HIDDEN)
-			: (old_de->attr &~ ATTR_HIDDEN);
-		fat_mark_buffer_dirty(sb, old_bh, 1);
-		MSDOS_I(old_inode)->i_attrs = is_hid
-			? (MSDOS_I(old_inode)->i_attrs |  ATTR_HIDDEN)
-			: (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
-		error = 0;
-		goto out;
-	}
-
-	/* Get the dotdot inode if we'll need it ... */
-	dotdot_bh = NULL;
-	dotdot_inode = NULL;
-	if (S_ISDIR(old_inode->i_mode)) {
 		error = fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
-				&dotdot_de, &dotdot_ino, SCAN_ANY);
+				&dotdot_de, &dotdot_ino);
 		if (error < 0) {
 			printk(KERN_WARNING
 				"MSDOS: %s/%s, get dotdot failed, ret=%d\n",
 				old_dentry->d_parent->d_name.name,
 				old_dentry->d_name.name, error);
-			goto rename_done;
+			goto out;
 		}
-		error = -EIO;
-		dotdot_inode = iget(sb, dotdot_ino);
-		if (!dotdot_inode)
-			goto out_dotdot;
 	}
+	if (!new_bh) {
+		error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de,
+					&new_ino, is_dir, is_hid);
+		if (error)
+			goto out;
+	}
+	new_dir->i_version = ++event;
 
-	/*
-	 * Potential race here. It will go away when we'll switch to
-	 * sane inumbers (along with a frigging lot of other races).
-	 */
-
-	/* set new entry */
-	memcpy(free_de, old_de, sizeof(struct msdos_dir_entry));
-	memcpy(free_de->name, new_name, MSDOS_NAME);
-	free_de->attr = is_hid
-		? (free_de->attr|ATTR_HIDDEN)
-		: (free_de->attr&~ATTR_HIDDEN);
-
-	/*
-	 * Now the tricky part. We need to change i_ino. icache ignores
-	 * i_ino for unhashed inodes, so we'll remove inode from hash,
-	 * change what we want to change and reinsert it back. NB: we
-	 * don't have to invalidate FAT cache here - all we need is to
-	 * flip i_ino in relevant cache entries. Later.
-	 */
-	remove_inode_hash(old_inode);
+	/* There we go */
 
-	fat_cache_inval_inode(old_inode);
-	old_inode->i_version = ++event;
-	MSDOS_I(old_inode)->i_binary =
-		fat_is_binary(MSDOS_SB(sb)->options.conversion, free_de->ext);
-	old_inode->i_ino = free_ino;
-	fat_mark_buffer_dirty(sb, free_bh, 1);
+	if (new_inode)
+		fat_detach(new_inode);
 	old_de->name[0] = DELETED_FLAG;
 	fat_mark_buffer_dirty(sb, old_bh, 1);
-
-	insert_inode_hash(old_inode);
-
-	/* a directory? */
+	fat_detach(old_inode);
+	fat_attach(old_inode, new_ino);
+	if (is_hid)
+		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
+	else
+		MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
+	mark_inode_dirty(old_inode);
+	old_dir->i_version = ++event;
+	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(old_dir);
+	if (new_inode) {
+		new_inode->i_nlink--;
+		new_inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(new_inode);
+	}
 	if (dotdot_bh) {
-		MSDOS_I(dotdot_inode)->i_start = MSDOS_I(new_dir)->i_start;
-		MSDOS_I(dotdot_inode)->i_logstart = MSDOS_I(new_dir)->i_logstart;
 		dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart);
 		dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16);
-		old_dir->i_nlink--;
-		new_dir->i_nlink++;
-		/* no need to mark them dirty */
-		dotdot_inode->i_nlink = new_dir->i_nlink;
-		mark_inode_dirty(dotdot_inode);
-		iput(dotdot_inode);
 		fat_mark_buffer_dirty(sb, dotdot_bh, 1);
-		fat_brelse(sb, dotdot_bh);
+		old_dir->i_nlink--;
+		mark_inode_dirty(old_dir);
+		if (new_inode) {
+			new_inode->i_nlink--;
+			mark_inode_dirty(new_inode);
+		} else {
+			new_dir->i_nlink++;
+			mark_inode_dirty(new_dir);
+		}
 	}
-
 	error = 0;
-
-rename_done:
-	fat_brelse(sb, free_bh);
 out:
+	fat_brelse(sb, new_bh);
+	fat_brelse(sb, dotdot_bh);
 	return error;
 
-out_dotdot:
-	fat_brelse(sb, dotdot_bh);
-	goto rename_done;
-out_new:
-	fat_brelse(sb, new_bh);
-	goto rename_done;
+degenerate_case:
+	error = -EINVAL;
+	if (new_de!=old_de)
+		goto out;
+	if (is_hid)
+		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
+	else
+		MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
+	mark_inode_dirty(old_inode);
+	old_dir->i_version = ++event;
+	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(old_dir);
+	return 0;
 }
 
 /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
@@ -765,27 +588,24 @@
 
 	error = msdos_format_name(MSDOS_SB(sb)->options.name_check,
 				old_dentry->d_name.name, old_dentry->d_name.len,
-				old_msdos_name, 1,MSDOS_SB(sb)->options.dotsOK);
+				old_msdos_name,MSDOS_SB(sb)->options.dotsOK);
 	if (error < 0)
 		goto rename_done;
 	error = msdos_format_name(MSDOS_SB(sb)->options.name_check,
 				new_dentry->d_name.name, new_dentry->d_name.len,
-				new_msdos_name, 0,MSDOS_SB(sb)->options.dotsOK);
+				new_msdos_name,MSDOS_SB(sb)->options.dotsOK);
 	if (error < 0)
 		goto rename_done;
 
 	is_hid  = (new_dentry->d_name.name[0]=='.') && (new_msdos_name[0]!='.');
 	old_hid = (old_dentry->d_name.name[0]=='.') && (old_msdos_name[0]!='.');
-	error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de,
-			&old_ino, old_hid?SCAN_HID:SCAN_NOTHID);
+	error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_ino);
 	if (error < 0)
 		goto rename_done;
 
-	fat_lock_creation();
 	error = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
 				new_dir, new_msdos_name, new_dentry,
 				old_bh, old_de, (ino_t)old_ino, is_hid);
-	fat_unlock_creation();
 	fat_brelse(sb, old_bh);
 
 rename_done:
@@ -817,10 +637,29 @@
 	NULL,                   /* revalidate */
 };
 
+static void msdos_put_super_callback(struct super_block *sb)
+{
+	MOD_DEC_USE_COUNT;
+}
 
-void msdos_read_inode(struct inode *inode)
+struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
 {
-	fat_read_inode(inode, &msdos_dir_inode_operations);
+	struct super_block *res;
+
+	MOD_INC_USE_COUNT;
+
+	MSDOS_SB(sb)->options.isvfat = 0;
+	res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
+	if (res == NULL)
+		goto out_fail;
+	MSDOS_SB(sb)->put_super_callback=msdos_put_super_callback;
+	sb->s_root->d_op = &msdos_dentry_operations;
+	return res;
+
+out_fail:
+	sb->s_dev = 0;
+	MOD_DEC_USE_COUNT;
+	return NULL;
 }
 
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ncpfs/dir.c linux.pre11.3/fs/ncpfs/dir.c
--- linux.vanilla/fs/ncpfs/dir.c	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/fs/ncpfs/dir.c	Tue Jul 20 00:09:20 1999
@@ -19,7 +19,6 @@
 #include <linux/mm.h>
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
-#include <linux/errno.h>
 #include <linux/locks.h>
 
 #include <linux/ncp_fs.h>
@@ -351,6 +350,10 @@
 	struct ncpfs_inode_info finfo;
 	__u8 __name[dentry->d_name.len + 1];
         
+	if (!dir) {
+		return 0;
+	}
+	
 	server = NCP_SERVER(dir);
 
 	if (!ncp_conn_valid(server))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/pipe.c linux.pre11.3/fs/pipe.c
--- linux.vanilla/fs/pipe.c	Thu Nov 19 18:38:47 1998
+++ linux.pre11.3/fs/pipe.c	Mon Jul 19 23:26:25 1999
@@ -25,7 +25,7 @@
 /* Florian Coosmann (FGC)                                ^ current = 1       */
 /* Additionally, we now use locking technique. This prevents race condition  */
 /* in case of paging and multiple read/write on the same pipe. (FGC)         */
-
+/* Reads with count = 0 should always return 0. Julian Bradfield 1999-06-07. */
 
 static ssize_t pipe_read(struct file * filp, char * buf,
 			 size_t count, loff_t *ppos)
@@ -34,8 +34,11 @@
 	ssize_t chars = 0, size = 0, read = 0;
         char *pipebuf;
 
+
 	if (ppos != &filp->f_pos)
 		return -ESPIPE;
+
+	if ( !count ) return 0;
 
 	if (filp->f_flags & O_NONBLOCK) {
 		if (PIPE_LOCK(*inode))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/proc/array.c linux.pre11.3/fs/proc/array.c
--- linux.vanilla/fs/proc/array.c	Fri May 28 00:33:00 1999
+++ linux.pre11.3/fs/proc/array.c	Tue Jul 20 00:10:08 1999
@@ -93,6 +93,9 @@
 	memset(&dump, 0, sizeof(struct user));
 	dump.magic = CMAGIC;
 	dump.u_dsize = max_mapnr;
+#if defined (__i386__)
+	dump.start_code = PAGE_OFFSET;
+#endif
 #ifdef __alpha__
 	dump.start_data = PAGE_OFFSET;
 #endif
@@ -529,7 +532,22 @@
 		return ((unsigned long *)schedule_frame)[12];
 	    }
 	    return pc;
-	}	
+	}
+#elif defined(__mips__)
+	/*
+	 * The same comment as on the Alpha applies here, too ...
+	 */
+	{
+		unsigned long schedule_frame;
+		unsigned long pc;
+
+		pc = thread_saved_pc(&p->tss);
+		if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
+			schedule_frame = ((unsigned long *)(long)p->tss.reg30)[16];
+			return (unsigned long)((unsigned long *)schedule_frame)[11];
+		}
+		return pc;
+	}
 #elif defined(__mc68000__)
 	{
 	    unsigned long fp, pc;
@@ -608,6 +626,7 @@
 		} while (++count < 16);
 	}
 #endif
+
 	return 0;
 }
 
@@ -644,6 +663,12 @@
 #elif defined(__sparc__)
 # define KSTK_EIP(tsk)  ((tsk)->tss.kregs->pc)
 # define KSTK_ESP(tsk)  ((tsk)->tss.kregs->u_regs[UREG_FP])
+#elif defined(__mips__)
+# define PT_REG(reg)		((long)&((struct pt_regs *)0)->reg \
+				 - sizeof(struct pt_regs))
+#define KSTK_TOS(tsk) ((unsigned long)(tsk) + KERNEL_STACK_SIZE - 32)
+# define KSTK_EIP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(cp0_epc)))
+# define KSTK_ESP(tsk)	(*(unsigned long *)(KSTK_TOS(tsk) + PT_REG(regs[29])))
 #endif
 
 /* Gcc optimizes away "strlen(x)" for constant x */
@@ -1341,6 +1366,10 @@
 #ifdef CONFIG_RTC
 		case PROC_RTC:
 			return get_rtc_status(page);
+#endif
+#ifdef CONFIG_SGI_DS1286
+		case PROC_RTC:
+			return get_ds1286_status(page);
 #endif
 		case PROC_LOCKS:
 			return get_locks_status(page, start, offset, length);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/proc/link.c linux.pre11.3/fs/proc/link.c
--- linux.vanilla/fs/proc/link.c	Fri Apr 16 22:10:59 1999
+++ linux.pre11.3/fs/proc/link.c	Tue Jul 20 00:10:16 1999
@@ -143,6 +143,9 @@
 	char * tmp = (char*)__get_free_page(GFP_KERNEL), *path, *pattern;
 	int len;
 
+	if(tmp==NULL)
+		return -ENOMEM;
+		
 	/* Check for special dentries.. */
 	pattern = NULL;
 	inode = dentry->d_inode;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/proc/root.c linux.pre11.3/fs/proc/root.c
--- linux.vanilla/fs/proc/root.c	Wed Apr 28 19:14:31 1999
+++ linux.pre11.3/fs/proc/root.c	Mon Jul 19 23:26:25 1999
@@ -633,6 +633,13 @@
 	0, &proc_array_inode_operations
 };
 #endif
+#ifdef CONFIG_SGI_DS1286
+static struct proc_dir_entry proc_root_ds1286 = {
+	PROC_RTC, 3, "rtc",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations
+};
+#endif
 static struct proc_dir_entry proc_root_locks = {
 	PROC_LOCKS, 5, "locks",
 	S_IFREG | S_IRUGO, 1, 0, 0,
@@ -709,6 +716,9 @@
 	proc_register(&proc_root, &proc_root_cmdline);
 #ifdef CONFIG_RTC
 	proc_register(&proc_root, &proc_root_rtc);
+#endif
+#ifdef CONFIG_SGI_DS1286
+	proc_register(&proc_root, &proc_root_ds1286);
 #endif
 	proc_register(&proc_root, &proc_root_locks);
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/qnx4/dir.c linux.pre11.3/fs/qnx4/dir.c
--- linux.vanilla/fs/qnx4/dir.c	Wed Apr 28 19:14:32 1999
+++ linux.pre11.3/fs/qnx4/dir.c	Tue Jul 20 00:10:29 1999
@@ -41,6 +41,11 @@
 
 	while (filp->f_pos < inode->i_size) {
 		bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
+		if(bh==NULL)
+		{
+			printk(KERN_ERR "qnx4_readdir: bread failed (%d)\n", blknum);
+			break;
+		}
 		i = (filp->f_pos - (((filp->f_pos >> 6) >> 3) << 9)) & 0x3f;
 		while (i < QNX4_INODES_PER_BLOCK) {
 			offset = i * QNX4_DIR_ENTRY_SIZE;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/qnx4/symlinks.c linux.pre11.3/fs/qnx4/symlinks.c
--- linux.vanilla/fs/qnx4/symlinks.c	Wed Jan  6 23:02:28 1999
+++ linux.pre11.3/fs/qnx4/symlinks.c	Tue Jul 20 00:10:29 1999
@@ -94,12 +94,12 @@
 	}
 	bh = bread(inode->i_dev, qnx4_ino->i_first_xtnt.xtnt_blk,
 		   QNX4_BLOCK_SIZE);
-	QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n",
-		   bh->b_data));
 	if (bh == NULL) {
 		QNX4DEBUG(("qnx4: NULL symlink bh\n"));
 		return 0;
 	}
+	QNX4DEBUG(("qnx4: qnx4_bread sym called -> [%s]\n",
+		   bh->b_data));
 	if (bh->b_data[0] != 0) {
 		i = 0;
 		while (i < buflen && (c = bh->b_data[i])) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/super.c linux.pre11.3/fs/super.c
--- linux.vanilla/fs/super.c	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/fs/super.c	Tue Jul 20 00:10:54 1999
@@ -48,6 +48,7 @@
 extern struct file_operations * get_blkfops(unsigned int major);
 
 extern int root_mountflags;
+extern void rd_load_secondary(void);
 
 static int do_remount_sb(struct super_block *sb, int flags, char * data);
 
@@ -104,7 +105,8 @@
 	lptr->mnt_dev = sb->s_dev;
 	lptr->mnt_flags = sb->s_flags;
 
-	sema_init(&lptr->mnt_dquot.semaphore, 1);
+	sema_init(&lptr->mnt_dquot.dqio_sem, 1);
+	sema_init(&lptr->mnt_dquot.dqoff_sem, 1);
 	lptr->mnt_dquot.flags = 0;
 
 	/* N.B. Is it really OK to have a vfsmount without names? */
@@ -1160,9 +1162,9 @@
 
 #ifdef CONFIG_BLK_DEV_FD
 	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_RAM	
 		extern int rd_doload;
-#endif
+#endif		
 		floppy_eject();
 #ifndef CONFIG_BLK_DEV_RAM
 		printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
@@ -1171,7 +1173,7 @@
 		if(rd_doload==2)
 			rd_load_secondary();
 		else
-#endif
+#endif		
 		{
 			printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
 			wait_for_keypress();
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ufs/balloc.c linux.pre11.3/fs/ufs/balloc.c
--- linux.vanilla/fs/ufs/balloc.c	Tue Jan 19 02:57:35 1999
+++ linux.pre11.3/fs/ufs/balloc.c	Tue Jul 20 00:11:04 1999
@@ -360,14 +360,22 @@
 	if (result) {
 		for (i = 0; i < oldcount; i++) {
 			bh = bread (sb->s_dev, tmp + i, sb->s_blocksize);
-			mark_buffer_clean (bh);
-			bh->b_blocknr = result + i;
-			mark_buffer_dirty (bh, 0);
-			if (IS_SYNC(inode)) {
-				ll_rw_block (WRITE, 1, &bh);
-				wait_on_buffer (bh);
+			if(bh)
+			{
+				mark_buffer_clean (bh);
+				bh->b_blocknr = result + i;
+				mark_buffer_dirty (bh, 0);
+				if (IS_SYNC(inode)) {
+					ll_rw_block (WRITE, 1, &bh);
+					wait_on_buffer (bh);
+				}
+				brelse (bh);
+			}
+			else
+			{
+				printk(KERN_ERR "ufs_new_fragments: bread fail\n");
+				return 0;
 			}
-			brelse (bh);
 		}
 		*p = SWAB32(result);
 		*err = 0;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/ufs/super.c linux.pre11.3/fs/ufs/super.c
--- linux.vanilla/fs/ufs/super.c	Fri Apr 16 22:10:59 1999
+++ linux.pre11.3/fs/ufs/super.c	Tue Jul 20 00:11:04 1999
@@ -271,6 +271,8 @@
 				ufs_set_opt (*mount_options, UFSTYPE_44BSD);
 			else if (!strcmp (value, "nextstep"))
 				ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP);
+			else if (!strcmp (value, "nextstep-cd"))
+				ufs_set_opt (*mount_options, UFSTYPE_NEXTSTEP_CD);
 			else if (!strcmp (value, "openstep"))
 				ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
 			else if (!strcmp (value, "sunx86"))
@@ -465,7 +467,8 @@
 	}
 	if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) {
 		printk("You didn't specify the type of your ufs filesystem\n\n"
-		"       mount -t ufs -o ufstype=sun|sunx86|44bsd|old|nextstep|openstep ....\n\n"
+		"mount -t ufs -o ufstype="
+		"sun|sunx86|44bsd|old|nextstep|netxstep-cd|openstep ...\n\n"
 		">>>WARNING<<< Wrong ufstype may corrupt your filesystem, "
 		"default is ufstype=old\n");
 		ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD);
@@ -535,6 +538,20 @@
 		}
 		break;
 	
+	case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD:
+		UFSD(("ufstype=nextstep-cd\n"))
+		uspi->s_fsize = block_size = 2048;
+		uspi->s_fmask = ~(2048 - 1);
+		uspi->s_fshift = 11;
+		uspi->s_sbsize = super_block_size = 2048;
+		uspi->s_sbbase = 0;
+		flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
+		if (!(sb->s_flags & MS_RDONLY)) {
+			printk(KERN_INFO "ufstype=nextstep-cd is supported read-only\n");
+			sb->s_flags |= MS_RDONLY;
+		}
+		break;
+	
 	case UFS_MOUNT_UFSTYPE_OPENSTEP:
 		UFSD(("ufstype=openstep\n"))
 		uspi->s_fsize = block_size = 1024;
@@ -592,6 +609,7 @@
 #endif
 
 	if ((((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP) 
+	  || ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_NEXTSTEP_CD) 
 	  || ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) == UFS_MOUNT_UFSTYPE_OPENSTEP)) 
 	  && uspi->s_sbbase < 256) {
 		ubh_brelse_uspi(uspi);
@@ -616,8 +634,8 @@
 		printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", uspi->s_bsize);
 		goto failed;
 	}
-	if (uspi->s_fsize != 512 && uspi->s_fsize != 1024) {
-		printk("ufs_read_super: fs_fsize %u != {512, 1024}\n", uspi->s_fsize);
+	if (uspi->s_fsize != 512 && uspi->s_fsize != 1024 && uspi->s_fsize != 2048) {
+		printk("ufs_read_super: fs_fsize %u != {512, 1024, 2048}\n", uspi->s_fsize);
 		goto failed;
 	}
 	if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/umsdos/README-WIP.txt linux.pre11.3/fs/umsdos/README-WIP.txt
--- linux.vanilla/fs/umsdos/README-WIP.txt	Thu Dec  3 14:12:00 1998
+++ linux.pre11.3/fs/umsdos/README-WIP.txt	Mon Jul 19 23:26:27 1999
@@ -14,7 +14,7 @@
 Legend: those lines marked with '+' on the beggining of line indicates it
 passed all of my tests, and performed perfect in all of them.
 
-Current status (981129) - UMSDOS dentry-pre 0.84:
+Current status (990202) - UMSDOS 0.85:
 
 (1) pure MSDOS (no --linux-.--- EMD file):
 
@@ -56,7 +56,7 @@
 
 WRITE:
 + create symlink		- works
-- create hardlink		- works, but see portability WARNING below
+- create hardlink		- works
 + create file			- works
 + create special file		- works
 + write to file			- works
@@ -90,24 +90,23 @@
 contains hardlinks will break them.
 
 Note: (about pseudoroot) If you are currently trying to use UMSDOS as root
-partition (with linux installed in c:\linux) it will boot, but there are
+partition (with linux installed in c:\linux) it will boot, but there may be
 some problems. Volunteers ready to test pseudoroot are needed (preferably
-ones with working backups or unimportant data). There are problems with
-different interpretation of hard links in normal in pseudo-root modes,
-resulting is 'silent delete' of them sometimes. Also, '/DOS' pseudo
+ones with working backups or unimportant data).  For example, '/DOS' pseudo
 directory is only partially re-implemented and buggy. It works most of the
 time, though. Update: should work ok in 0.84, although it still does not
 work correctly in combination with initrd featere. Working on this!
 
-Warning: (about creating hardlinks in pseudoroot mode) - hardlinks created in
-pseudoroot mode are not compatibile with 'normal' hardlinks, and vice versa.
-That is because harlink which is /foo in pseudoroot mode, becomes
-/linux/foo in normal mode. I'm thinking about this one. However, since most
-people either always use pseudoroot, or always use normal umsdos filesystem,
-this is no showstopper.
+Note: (about creating hardlinks in pseudoroot mode) - hardlinks created in
+pseudoroot mode are now again compatibile with 'normal' hardlinks, and vice
+versa. Thanks to Sorin Iordachescu <sorin@rodae.ro> for providing fix.
 
-Warning: (about hardlinks) - modifying hardlinks (esp. if there are in
+Warning: (about hardlinks) - modifying hardlinks (esp. if they are in
 different directories) are currently somewhat broken, I'm working on it.
+Problem seems to be that code uses and updates EMD of directory where 'real
+hardlink' is stored, not EMD of directory where our pseudo-hardlink is
+located! I'm looking for ideas how to work around this in clean way, since
+without it modifying hardlinks in any but most simple ways is broken!
 
 ------------------------------------------------------------------------------
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/umsdos/dir.c linux.pre11.3/fs/umsdos/dir.c
--- linux.vanilla/fs/umsdos/dir.c	Thu May 27 22:12:00 1999
+++ linux.pre11.3/fs/umsdos/dir.c	Mon Jul 19 23:26:26 1999
@@ -670,10 +670,20 @@
 	/* N.B. not safe -- fix this soon! */
 	current->fs->root = dentry->d_sb->s_root;
 	path = d_path(dentry, buffer, len);
+
+	if (*path == '/')
+		path++; /* skip leading '/' */
+
+	if (old_root->d_inode == pseudo_root)
+	{
+		*(path-1) = '/';
+		path -= (UMSDOS_PSDROOT_LEN+1);
+		memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);
+	}
+
 	current->fs->root = old_root;
 	return path;
 }
-	
 
 /*
  * Return the dentry which points to a pseudo-hardlink.
@@ -718,7 +728,14 @@
 	/* start at root dentry */
 	dentry_dst = dget(base);
 	path[len] = '\0';
-	pt = path + 1; /* skip leading '/' */
+	
+	pt = path;
+	if (*path == '/')
+		pt++; /* skip leading '/' */
+	
+	if (base->d_inode == pseudo_root)
+		pt += (UMSDOS_PSDROOT_LEN + 1);
+	
 	while (1) {
 		struct dentry *dir = dentry_dst, *demd;
 		char *start = pt;
@@ -741,6 +758,7 @@
 dir->d_parent->d_name.name, dir->d_name.name, start, real);
 #endif
 		dentry_dst = umsdos_lookup_dentry(dir, start, len, real);
+/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 		if (real)
 			d_drop(dir);
 		dput (dir);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/umsdos/file.c linux.pre11.3/fs/umsdos/file.c
--- linux.vanilla/fs/umsdos/file.c	Sun Nov  8 15:06:34 1998
+++ linux.pre11.3/fs/umsdos/file.c	Mon Jul 19 23:26:26 1999
@@ -13,7 +13,6 @@
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/stat.h>
-#include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
 
 #include <asm/uaccess.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/umsdos/inode.c linux.pre11.3/fs/umsdos/inode.c
--- linux.vanilla/fs/umsdos/inode.c	Fri Apr 16 22:10:59 1999
+++ linux.pre11.3/fs/umsdos/inode.c	Mon Jul 19 23:26:26 1999
@@ -60,8 +60,8 @@
 			" Notify jacques@solucorp.qc.ca\n");
 	}
 
-	inode->u.umsdos_i.i_patched = 0;
-	fat_put_inode (inode);
+	if (inode->i_count == 1)
+		inode->u.umsdos_i.i_patched = 0;
 }
 
 
@@ -173,29 +173,6 @@
 }
 
 
-/*
- * Load an inode from disk.
- */
-/* #Specification: Inode / post initialisation
- * To completely initialise an inode, we need access to the owner
- * directory, so we can locate more info in the EMD file. This is
- * not available the first time the inode is accessed, so we use
- * a value in the inode to tell if it has been finally initialised.
- * 
- * New inodes are obtained by the lookup and create routines, and
- * each of these must ensure that the inode gets patched.
- */
-void UMSDOS_read_inode (struct inode *inode)
-{
-	Printk ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ",
-		inode, inode->i_ino));
-	msdos_read_inode (inode);
-
-	/* inode needs patching */
-	inode->u.umsdos_i.i_patched = 0;
-}
-
-
 int umsdos_notify_change_locked(struct dentry *, struct iattr *);
 /*
  * lock the parent dir before starting ...
@@ -341,7 +318,7 @@
 
 static struct super_operations umsdos_sops =
 {
-	UMSDOS_read_inode,	/* read_inode */
+	NULL,			/* read_inode */
 	UMSDOS_write_inode,	/* write_inode */
 	UMSDOS_put_inode,	/* put_inode */
 	fat_delete_inode,	/* delete_inode */
@@ -349,7 +326,8 @@
 	UMSDOS_put_super,	/* put_super */
 	NULL,			/* write_super */
 	fat_statfs,		/* statfs */
-	NULL			/* remount_fs */
+	NULL,			/* remount_fs */
+	fat_clear_inode,	/* clear_inode */
 };
 
 /*
@@ -371,7 +349,7 @@
 	if (!res)
 		goto out_fail;
 
-	printk (KERN_INFO "UMSDOS dentry-pre 0.84 "
+	printk (KERN_INFO "UMSDOS 0.85 "
 		"(compatibility level %d.%d, fast msdos)\n", 
 		UMSDOS_VERSION, UMSDOS_RELEASE);
 
@@ -416,16 +394,20 @@
 /*
  * Check for an alternate root if we're the root device.
  */
+
+extern kdev_t ROOT_DEV;
 static struct dentry *check_pseudo_root(struct super_block *sb)
 {
 	struct dentry *root, *init;
 
 	/*
 	 * Check whether we're mounted as the root device.
-	 * If so, this should be the only superblock.
+	 * must check like this, because we can be used with initrd
 	 */
-	if (sb->s_list.next->next != &sb->s_list)
+		
+	if (sb->s_dev != ROOT_DEV)
 		goto out_noroot;
+		
 printk("check_pseudo_root: mounted as root\n");
 
 	root = lookup_dentry(UMSDOS_PSDROOT_NAME, dget(sb->s_root), 0); 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/vfat/namei.c linux.pre11.3/fs/vfat/namei.c
--- linux.vanilla/fs/vfat/namei.c	Thu May 27 22:12:00 1999
+++ linux.pre11.3/fs/vfat/namei.c	Mon Jul 19 23:26:28 1999
@@ -49,24 +49,6 @@
 # define CHECK_STACK check_stack(__FILE__, __LINE__)
 #endif
 
-struct vfat_find_info {
-	const char *name;
-	int len;
-	int new_filename;
-	int found;
-	int is_long;
-	off_t offset;
-	off_t short_offset;
-	int long_slots;
-	ino_t ino;
-	int posix;
-	int anycase;
-};
-
-void vfat_read_inode(struct inode *inode);
-static int vfat_valid_shortname(const char *,int, int, int);
-static int vfat_format_name(const char *, int, char *, int, int);
-static int vfat_valid_longname(const char *, int, int, int);
 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
@@ -100,9 +82,8 @@
 	}
 };
 
-void vfat_put_super(struct super_block *sb)
+static void vfat_put_super_callback(struct super_block *sb)
 {
-	fat_put_super(sb);
 	MOD_DEC_USE_COUNT;
 }
 
@@ -115,18 +96,6 @@
 	return 0;
 }
 
-static struct super_operations vfat_sops = { 
-	vfat_read_inode,
-	fat_write_inode,
-	fat_put_inode,
-	fat_delete_inode,
-	fat_notify_change,
-	vfat_put_super,
-	NULL, /* write_super */
-	fat_statfs,
-	NULL  /* remount */
-};
-
 static int simple_getbool(char *s, int *setval)
 {
 	if (s) {
@@ -283,40 +252,6 @@
 	return 1;
 }
 
-struct super_block *vfat_read_super(struct super_block *sb,void *data,
-				    int silent)
-{
-	struct super_block *res;
-  
-	MOD_INC_USE_COUNT;
-	
-	MSDOS_SB(sb)->options.isvfat = 1;
-
-	sb->s_op = &vfat_sops;
-	res = fat_read_super(sb, data, silent);
-	if (res == NULL) {
-		sb->s_dev = 0;
-		MOD_DEC_USE_COUNT;
-		return NULL;
-	}
-
-	if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
-		MOD_DEC_USE_COUNT;
-	} else {
-		MSDOS_SB(sb)->options.dotsOK = 0;
-		if (MSDOS_SB(sb)->options.posixfs) {
-			MSDOS_SB(sb)->options.name_check = 's';
-		}
-		if (MSDOS_SB(sb)->options.name_check != 's') {
-			sb->s_root->d_op = &vfat_dentry_ops[0];
-		} else {
-			sb->s_root->d_op = &vfat_dentry_ops[2];
-		}
-	}
-
-	return res;
-}
-
 #ifdef DEBUG
 
 static void
@@ -394,26 +329,17 @@
 static char bad_chars[] = "*?<>|\":/\\";
 static char replace_chars[] = "[];,+=";
 
-static int vfat_find(struct inode *dir,struct qstr* name,
-		      int new_filename,int is_dir,
-		      struct vfat_slot_info *sinfo_out);
-
 /* Checks the validity of a long MS-DOS filename */
 /* Returns negative number on error, 0 for a normal
  * return, and 1 for . or .. */
 
-static int vfat_valid_longname(const char *name, int len, int dot_dirs,
-			       int xlate)
+static int vfat_valid_longname(const char *name, int len, int xlate)
 {
 	const char **reserved, *walk;
 	unsigned char c;
 	int i, baselen;
 
 	if (IS_FREE(name)) return -EINVAL;
-	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
-		if (!dot_dirs) return -EEXIST;
-		return 1;
-	}
 
 	if (len && name[len-1] == ' ') return -EINVAL;
 	if (len >= 256) return -EINVAL;
@@ -443,19 +369,13 @@
 	return 0;
 }
 
-static int vfat_valid_shortname(const char *name,int len,
-				int dot_dirs, int utf8)
+static int vfat_valid_shortname(const char *name,int len,int utf8)
 {
 	const char *walk;
 	unsigned char c;
 	int space;
 	int baselen;
 
-	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
-		if (!dot_dirs) return -EEXIST;
-		return 1;
-	}
-
 	space = 1; /* disallow names starting with a dot */
 	c = 0;
 	for (walk = name; len && walk-name < 8;) {
@@ -499,34 +419,21 @@
 {
 	struct msdos_dir_entry *de;
 	struct buffer_head *bh = NULL;
-	loff_t pos = 0;
+	int ino,res;
 
-	while(fat_get_entry(dir, &pos, &bh, &de) >= 0) {
-		if (de->attr == ATTR_EXT)
-			continue;
-		if (memcmp(de->name,name,MSDOS_NAME))
-			continue;
-		fat_brelse(dir->i_sb,bh);
-		return 0;
-	}
-	fat_brelse(dir->i_sb,bh);
-	return -ENOENT;
+	res=fat_scan(dir,name,&bh,&de,&ino);
+	fat_brelse(dir->i_sb, bh);
+	if (res<0)
+		return -ENOENT;
+	return 0;
 }
 
-static int vfat_format_name(const char *name,int len,char *res,
-			    int dot_dirs,int utf8)
+static int vfat_format_name(const char *name,int len,char *res,int utf8)
 {
 	char *walk;
 	unsigned char c;
 	int space;
 
-	if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
-		if (!dot_dirs) return -EEXIST;
-		memset(res+1,' ',10);
-		while (len--) *res++ = '.';
-		return 0;
-	}
-
 	space = 1; /* disallow names starting with a dot */
 	for (walk = res; len-- && (c=*name++)!='.' ; walk++) {
 		if (walk-res == 8) return -EINVAL;
@@ -588,7 +495,7 @@
 		for (i = 0, p = msdos_name, ip = name; ; i++, p++, ip++) {
 			if (i == len) {
 				if (vfat_format_name(msdos_name,
-						len, name_res, 1, utf8) < 0)
+						len, name_res, utf8) < 0)
 					break;
 				PRINTK3(("vfat_create_shortname 1\n"));
 				if (vfat_find_form(dir, name_res) < 0)
@@ -732,60 +639,6 @@
 	return 0;
 }
 
-static loff_t vfat_find_free_slots(struct inode *dir,int slots)
-{
-	struct super_block *sb = dir->i_sb;
-	loff_t offset, curr;
-	struct msdos_dir_entry *de;
-	struct buffer_head *bh;
-	struct inode *inode;
-	int ino;
-	int row;
-	int done;
-	int res;
-	int added;
-
-	PRINTK2(("vfat_find_free_slots: find %d free slots\n", slots));
-	offset = curr = 0;
-	bh = NULL;
-	row = 0;
-	ino = fat_get_entry(dir,&curr,&bh,&de);
-
-	for (added = 0; added < 2; added++) {
-		while (ino > -1) {
-			done = IS_FREE(de->name);
-			if (done) {
-				inode = iget(sb,ino);
-				if (inode) {
-					/* Directory slots of busy deleted files aren't available yet. */
-					done = !MSDOS_I(inode)->i_busy;
-					/* PRINTK3(("inode %d still busy\n", ino)); */
-					iput(inode);
-				}
-			}
-			if (done) {
-				row++;
-				if (row == slots) {
-					fat_brelse(sb, bh);
-					/* printk("----- Free offset at %d\n", offset); */
-					return offset;
-				}
-			} else {
-				row = 0;
-				offset = curr;
-			}
-			ino = fat_get_entry(dir,&curr,&bh,&de);
-		}
-
-		if ((dir->i_ino == MSDOS_ROOT_INO) &&
-		    (MSDOS_SB(sb)->fat_bits != 32)) 
-			return -ENOSPC;
-		if ((res = fat_add_cluster(dir)) < 0) return res;
-		ino = fat_get_entry(dir,&curr,&bh,&de);
-	}
-	return -ENOSPC;
-}
-
 /* Translate a string, including coded sequences into Unicode */
 static int
 xlate_to_uni(const char *name, int len, char *outname, int *outlen,
@@ -889,249 +742,129 @@
 	PRINTK3(("vfat_fill_long_slots 3: slots=%d\n",*slots));
 
 	for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
-		int end, j;
-
-		PRINTK3(("vfat_fill_long_slots 4\n"));
 		ps->id = slot;
 		ps->attr = ATTR_EXT;
 		ps->reserved = 0;
 		ps->alias_checksum = cksum;
 		ps->start = 0;
-		PRINTK3(("vfat_fill_long_slots 5: uniname=%s\n",uniname));
 		offset = (slot - 1) * 26;
 		ip = &uniname[offset];
-		j = offset;
-		end = 0;
-		for (i = 0; i < 10; i += 2) {
-			ps->name0_4[i] = *ip++;
-			ps->name0_4[i+1] = *ip++;
-		}
-		PRINTK3(("vfat_fill_long_slots 6\n"));
-		for (i = 0; i < 12; i += 2) {
-			ps->name5_10[i] = *ip++;
-			ps->name5_10[i+1] = *ip++;
-		}
-		PRINTK3(("vfat_fill_long_slots 7\n"));
-		for (i = 0; i < 4; i += 2) {
-			ps->name11_12[i] = *ip++;
-			ps->name11_12[i+1] = *ip++;
-		}
+		memcpy(ps->name0_4, ip, 10);
+		memcpy(ps->name5_10, ip+10, 12);
+		memcpy(ps->name11_12, ip+22, 4);
 	}
-	PRINTK3(("vfat_fill_long_slots 8\n"));
 	ds[0].id |= 0x40;
 
 	de = (struct msdos_dir_entry *) ps;
 	PRINTK3(("vfat_fill_long_slots 9\n"));
 	strncpy(de->name, msdos_name, MSDOS_NAME);
+	(*slots)++;
 
 	free_page(page);
 	return 0;
 }
-		
+
+/* We can't get "." or ".." here - VFS takes care of those cases */
+
 static int vfat_build_slots(struct inode *dir,const char *name,int len,
-     struct msdos_dir_slot *ds, int *slots, int *is_long)
+     struct msdos_dir_slot *ds, int *slots)
 {
 	struct msdos_dir_entry *de;
 	char msdos_name[MSDOS_NAME];
 	int res, xlate, utf8;
 	struct nls_table *nls;
 
-	PRINTK2(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
 	de = (struct msdos_dir_entry *) ds;
 	xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
 	utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
 	nls = MSDOS_SB(dir->i_sb)->nls_io;
 
 	*slots = 1;
-	*is_long = 0;
-	if (len == 1 && name[0] == '.') {
-		strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
-	} else if (len == 2 && name[0] == '.' && name[1] == '.') {
-		strncpy(de->name, MSDOS_DOT, MSDOS_NAME);
-	} else {
-		PRINTK3(("vfat_build_slots 4\n"));
-		res = vfat_valid_longname(name, len, 1, xlate);
-		if (res < 0) {
-			return res;
-		}
-		res = vfat_valid_shortname(name, len, 1, utf8);
-		if (res > -1) {
-			PRINTK3(("vfat_build_slots 5a\n"));
-			res = vfat_format_name(name, len, de->name, 1, utf8);
-			PRINTK3(("vfat_build_slots 5b\n"));
-		} else {
-			res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
-			if (res < 0) {
-				return res;
-			}
-
-			*is_long = 1;
-
-			return vfat_fill_long_slots(ds, name, len, msdos_name,
-						    slots, xlate, utf8, nls);
-		}
-	}
-	return 0;
-}
-
-static int vfat_readdir_cb(
-	filldir_t filldir,
-	void * buf,
-	const char * name,
-	int name_len,
-	int is_long,
-	off_t offset,
-	off_t short_offset,
-	int long_slots,
-	ino_t ino)
-{
-	struct vfat_find_info *vf = (struct vfat_find_info *) buf;
-	const char *s1, *s2;
-	int i;
-
-#ifdef DEBUG
-	if (debug) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",
-			  vf->name, vf->len, name, name_len);
-#endif
-
-	if (vf->len != name_len) {
+	res = vfat_valid_longname(name, len, xlate);
+	if (res < 0)
+		return res;
+	if (vfat_valid_shortname(name, len, utf8) >= 0) {
+		vfat_format_name(name, len, de->name, utf8);
 		return 0;
 	}
-
-	s1 = name; s2 = vf->name;
-	for (i = 0; i < name_len; i++) {
-		if (vf->anycase || (vf->new_filename && !vf->posix)) {
-			if (tolower(*s1) != tolower(*s2))
-				return 0;
-		} else {
-			if (*s1 != *s2)
-				return 0;
-		}
-		s1++; s2++;
-	}
-	vf->found = 1;
-	vf->is_long = is_long;
-	vf->offset = (offset == 2) ? 0 : offset;
-	vf->short_offset = (short_offset == 2) ? 0 : short_offset;
-	vf->long_slots = long_slots;
-	vf->ino = ino;
-	return -1;
+	res = vfat_create_shortname(dir, name, len, msdos_name, utf8);
+	if (res < 0)
+		return res;
+	return vfat_fill_long_slots(ds, name, len, msdos_name, slots, xlate,
+					utf8, nls);
 }
 
-static int vfat_find(struct inode *dir,struct qstr* qname,
-    int new_filename,int is_dir,struct vfat_slot_info *sinfo_out)
+static int vfat_add_entry(struct inode *dir,struct qstr* qname,
+	int is_dir,struct vfat_slot_info *sinfo_out,
+	struct buffer_head **bh, struct msdos_dir_entry **de)
 {
 	struct super_block *sb = dir->i_sb;
-	struct vfat_find_info vf;
-	struct file fil;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
 	struct msdos_dir_slot *ps;
 	loff_t offset;
 	struct msdos_dir_slot *ds;
-	int is_long;
 	int slots, slot;
 	int res;
-
-	PRINTK2(("Entering vfat_find\n"));
+	struct msdos_dir_entry *de1;
+	struct buffer_head *bh1;
+	int ino;
+	int len;
+	loff_t dummy;
 
 	ds = (struct msdos_dir_slot *)
 	    kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);
 	if (ds == NULL) return -ENOMEM;
 
-	fil.f_pos = 0;
-	vf.name = qname->name;
-	vf.len = qname->len;
-	while (vf.len && vf.name[vf.len-1] == '.') {
-		vf.len--;
-	}
-	vf.new_filename = new_filename;
-	vf.found = 0;
-	vf.posix = MSDOS_SB(sb)->options.posixfs;
-	vf.anycase = (MSDOS_SB(sb)->options.name_check != 's');
-	res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,1,0);
-	PRINTK3(("vfat_find: Debug 1\n"));
-	if (res < 0) goto cleanup;
-	if (vf.found) {
-		if (new_filename) {
-			res = -EEXIST;
-			goto cleanup;
-		}
-		sinfo_out->longname_offset = vf.offset;
-		sinfo_out->shortname_offset = vf.short_offset;
-		sinfo_out->is_long = vf.is_long;
-		sinfo_out->long_slots = vf.long_slots;
-		sinfo_out->total_slots = vf.long_slots + 1;
-		sinfo_out->ino = vf.ino;
-
-		PRINTK3(("vfat_find: Debug 2\n"));
-		res = 0;
+	len = qname->len;
+	while (len && qname->name[len-1] == '.')
+		len--;
+	res = fat_search_long(dir, qname->name, len,
+			(MSDOS_SB(sb)->options.name_check != 's') ||
+			!MSDOS_SB(sb)->options.posixfs,
+			&dummy, &dummy);
+	if (res > 0) /* found */
+		res = -EEXIST;
+	if (res)
 		goto cleanup;
-	}
 
-	PRINTK3(("vfat_find: Debug 3\n"));
-	if (!new_filename) {
-		res = -ENOENT;
-		goto cleanup;
-	}
-	
-	res = vfat_build_slots(dir, qname->name, vf.len, ds, 
-			       &slots, &is_long);
-	/* Here we either have is_long and slots>=0 or slots==1 */
+	res = vfat_build_slots(dir, qname->name, len, ds, &slots);
 	if (res < 0) goto cleanup;
 
-	de = (struct msdos_dir_entry *) ds;
-
-	bh = NULL;
-
-	PRINTK3(("vfat_find: create file 1\n"));
-	if (is_long) slots++;
-	offset = vfat_find_free_slots(dir, slots);
+	offset = fat_add_entries(dir, slots, &bh1, &de1, &ino);
 	if (offset < 0) {
 		res = offset;
 		goto cleanup;
 	}
+	fat_brelse(sb, bh1);
 
-	PRINTK3(("vfat_find: create file 2\n"));
 	/* Now create the new entry */
-	bh = NULL;
+	*bh = NULL;
 	for (slot = 0, ps = ds; slot < slots; slot++, ps++) {
-		PRINTK3(("vfat_find: create file 3, slot=%d\n",slot));
-		sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);
-		if (sinfo_out->ino < 0) {
-			PRINTK3(("vfat_find: problem\n"));
-			res = sinfo_out->ino;
+		if (fat_get_entry(dir,&offset,bh,de, &sinfo_out->ino) < 0) {
+			res = -EIO;
 			goto cleanup;
 		}
-		memcpy(de, ps, sizeof(struct msdos_dir_slot));
-		fat_mark_buffer_dirty(sb, bh, 1);
+		memcpy(*de, ps, sizeof(struct msdos_dir_slot));
+		fat_mark_buffer_dirty(sb, *bh, 1);
 	}
 
-	PRINTK3(("vfat_find: create file 4\n"));
 	dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
 	mark_inode_dirty(dir);
 
-	PRINTK3(("vfat_find: create file 5\n"));
+	fat_date_unix2dos(dir->i_mtime,&(*de)->time,&(*de)->date);
+	(*de)->ctime_ms = 0;
+	(*de)->ctime = (*de)->time;
+	(*de)->adate = (*de)->cdate = (*de)->date;
+	(*de)->start = 0;
+	(*de)->starthi = 0;
+	(*de)->size = 0;
+	(*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
+	(*de)->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
 
-	fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
-	de->ctime_ms = 0;
-	de->ctime = de->time;
-	de->adate = de->cdate = de->date;
-	de->start = 0;
-	de->starthi = 0;
-	de->size = 0;
-	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
-	de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;
 
-
-	fat_mark_buffer_dirty(sb, bh, 1);
-	fat_brelse(sb, bh);
+	fat_mark_buffer_dirty(sb, *bh, 1);
 
 	/* slots can't be less than 1 */
-	sinfo_out->is_long = (slots > 1);
 	sinfo_out->long_slots = slots - 1;
-	sinfo_out->total_slots = slots;
-	sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);
 	sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;
 	res = 0;
 
@@ -1140,6 +873,29 @@
 	return res;
 }
 
+static int vfat_find(struct inode *dir,struct qstr* qname,
+	struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
+	struct msdos_dir_entry **last_de)
+{
+	struct super_block *sb = dir->i_sb;
+	loff_t offset;
+	int res,len;
+
+	len = qname->len;
+	while (len && qname->name[len-1] == '.') 
+		len--;
+	res = fat_search_long(dir, qname->name, len,
+			(MSDOS_SB(sb)->options.name_check != 's'),
+			&offset,&sinfo->longname_offset);
+	if (res>0) {
+		sinfo->long_slots = res-1;
+		if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->ino)>=0)
+			return 0;
+		res = -EIO;
+	} 
+	return res ? res : -ENOENT;
+}
+
 /* Find a hashed dentry for inode; NULL if there are none */
 static struct dentry *find_alias(struct inode *inode)
 {
@@ -1162,8 +918,10 @@
 {
 	int res;
 	struct vfat_slot_info sinfo;
-	struct inode *result;
+	struct inode *inode;
 	struct dentry *alias;
+	struct buffer_head *bh = NULL;
+	struct msdos_dir_entry *de;
 	int table;
 	
 	PRINTK2(("vfat_lookup: name=%s, len=%d\n", 
@@ -1172,317 +930,162 @@
 	table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
 	dentry->d_op = &vfat_dentry_ops[table];
 
-	result = NULL;
-	if ((res = vfat_find(dir,&dentry->d_name,0,0,&sinfo)) < 0) {
-		result = NULL;
-		table++;
-		goto error;
-	}
-	PRINTK3(("vfat_lookup 4.5\n"));
-	if (!(result = iget(dir->i_sb,sinfo.ino)))
-		return ERR_PTR(-EACCES);
-	PRINTK3(("vfat_lookup 5\n"));
-	if (MSDOS_I(result)->i_busy) { /* mkdir in progress */
-		iput(result);
-		result = NULL;
+	inode = NULL;
+	res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
+	if (res < 0) {
 		table++;
 		goto error;
 	}
-	alias = find_alias(result);
+	inode = fat_build_inode(dir->i_sb, de, sinfo.ino, &res);
+	fat_brelse(dir->i_sb, bh);
+	if (res)
+		return ERR_PTR(res);
+	alias = find_alias(inode);
 	if (alias) {
 		if (d_invalidate(alias)==0)
 			dput(alias);
 		else {
-			iput(result);
+			iput(inode);
 			return alias;
 		}
+		
 	}
-	PRINTK3(("vfat_lookup 6\n"));
 error:
 	dentry->d_op = &vfat_dentry_ops[table];
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
-	d_add(dentry,result);
-	return 0;
+	d_add(dentry,inode);
+	return NULL;
 }
 
-
-static int vfat_create_entry(struct inode *dir,struct qstr* qname,
-    int is_dir, struct inode **result)
+int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
 {
 	struct super_block *sb = dir->i_sb;
-	int res,ino;
-	loff_t offset;
-	struct buffer_head *bh;
+	struct inode *inode = NULL;
+	struct buffer_head *bh = NULL;
 	struct msdos_dir_entry *de;
 	struct vfat_slot_info sinfo;
+	int res;
 
-	*result=0;
-	PRINTK1(("vfat_create_entry: Entering\n"));
-	res = vfat_find(dir, qname, 1, is_dir, &sinfo);
-	if (res < 0) {
+	res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
+	if (res < 0)
 		return res;
-	}
-
-	offset = sinfo.shortname_offset;
-
-	PRINTK3(("vfat_create_entry 2\n"));
-	bh = NULL;
-	ino = fat_get_entry(dir, &offset, &bh, &de);
-	if (ino < 0) {
-		PRINTK3(("vfat_mkdir problem\n"));
-		if (bh)
-			fat_brelse(sb, bh);
-		return ino;
-	}
-	PRINTK3(("vfat_create_entry 3\n"));
-
-	if ((*result = iget(dir->i_sb,ino)) != NULL)
-		vfat_read_inode(*result);
+	inode = fat_build_inode(sb, de, sinfo.ino, &res);
 	fat_brelse(sb, bh);
-	if (!*result)
-		return -EIO;
-	(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
-	    CURRENT_TIME;
-	mark_inode_dirty(*result);
-	(*result)->i_version = ++event;
+	if (!inode)
+		return res;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	inode->i_version = ++event;
 	dir->i_version = event;
-
-	return 0;
-}
-
-int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
-{
-	int res;
-	struct inode *result;
-
-	result=NULL;
-	fat_lock_creation();
-	res = vfat_create_entry(dir,&dentry->d_name,0,&result);
-	fat_unlock_creation();
-	if (res < 0) {
-		PRINTK3(("vfat_create: unable to get new entry\n"));
-	} else {
-		dentry->d_time = dentry->d_parent->d_inode->i_version;
-		d_instantiate(dentry,result);
-	}
-	return res;
-}
-
-static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,
-     struct buffer_head *bh,
-     struct msdos_dir_entry *de,int ino,const char *name, int isdot)
-{
-	struct super_block *sb = dir->i_sb;
-	struct inode *dot;
-
-	PRINTK2(("vfat_create_a_dotdir: Entering\n"));
-
-	/*
-	 * XXX all times should be set by caller upon successful completion.
-	 */
-	dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(dir);
-	memcpy(de->name,name,MSDOS_NAME);
-	de->lcase = 0;
-	de->attr = ATTR_DIR;
-	de->start = 0;
-	de->starthi = 0;
-	fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);
-	de->ctime_ms = 0;
-	de->ctime = de->time;
-	de->adate = de->cdate = de->date;
-	de->size = 0;
-	fat_mark_buffer_dirty(sb, bh, 1);
-	dot = iget(dir->i_sb,ino);
-	if (!dot)
-		return -EIO;
-	vfat_read_inode(dot);
-	dot->i_mtime = dot->i_atime = CURRENT_TIME;
-	mark_inode_dirty(dot);
-	if (isdot) {
-		dot->i_size = dir->i_size;
-		MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
-		MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
-		dot->i_nlink = dir->i_nlink;
-	} else {
-		dot->i_size = parent->i_size;
-		MSDOS_I(dot)->i_start = MSDOS_I(parent)->i_start;
-		MSDOS_I(dot)->i_logstart = MSDOS_I(parent)->i_logstart;
-		dot->i_nlink = parent->i_nlink;
-	}
-
-	iput(dot);
-
-	PRINTK3(("vfat_create_a_dotdir 2\n"));
+	MSDOS_I(dir)->i_last_pos = 0;
+	dentry->d_time = dentry->d_parent->d_inode->i_version;
+	d_instantiate(dentry,inode);
 	return 0;
 }
 
 static int vfat_create_dotdirs(struct inode *dir, struct inode *parent)
 {
 	struct super_block *sb = dir->i_sb;
-	int res;
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	loff_t offset;
+	__u16 date, time;
 
-	PRINTK2(("vfat_create_dotdirs: Entering\n"));
-	if ((res = fat_add_cluster(dir)) < 0) return res;
-
-	PRINTK3(("vfat_create_dotdirs 2\n"));
-	offset = 0;
-	bh = NULL;
-	if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) return res;
-	
-	PRINTK3(("vfat_create_dotdirs 3\n"));
-	res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOT, 1);
-	PRINTK3(("vfat_create_dotdirs 4\n"));
-	if (res < 0) {
-		fat_brelse(sb, bh);
-		return res;
-	}
-	PRINTK3(("vfat_create_dotdirs 5\n"));
-
-	if ((res = fat_get_entry(dir,&offset,&bh,&de)) < 0) {
-		fat_brelse(sb, bh);
-		return res;
-	}
-	PRINTK3(("vfat_create_dotdirs 6\n"));
-
-	res = vfat_create_a_dotdir(dir, parent, bh, de, res, MSDOS_DOTDOT, 0);
-	PRINTK3(("vfat_create_dotdirs 7\n"));
+	if ((bh = fat_add_cluster1(dir)) == NULL) return -ENOSPC;
+	/* zeroed out, so... */
+	fat_date_unix2dos(dir->i_mtime,&time,&date);
+	de = (struct msdos_dir_entry*)&bh->b_data[0];
+	memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
+	memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
+	de[0].attr = de[1].attr = ATTR_DIR;
+	de[0].ctime = de[0].time = de[1].ctime = de[1].time = CT_LE_W(time);
+	de[0].adate = de[0].cdate = de[0].date = de[1].adate =
+		de[1].cdate = de[1].date = CT_LE_W(date);
+	de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);
+	de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);
+	de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart);
+	de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16);
+	fat_mark_buffer_dirty(sb, bh, 1);
 	fat_brelse(sb, bh);
+	dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(dir);
 
-	return res;
-}
-
-/***** See if directory is empty */
-static int vfat_empty(struct inode *dir)
-{
-	struct super_block *sb = dir->i_sb;
-	loff_t pos;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
-
-	if (MSDOS_I(dir)->i_start) { /* may be zero in mkdir */
-		pos = 0;
-		bh = NULL;
-		while (fat_get_entry(dir,&pos,&bh,&de) > -1) {
-			/* Skip extended filename entries */
-			if (de->attr == ATTR_EXT) continue;
-
-			if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
-			    MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
-			    MSDOS_NAME)) {
-				fat_brelse(sb, bh);
-				return -ENOTEMPTY;
-			}
-		}
-		if (bh)
-			fat_brelse(sb, bh);
-	}
 	return 0;
 }
 
-static void vfat_free_ino(struct inode *dir,struct buffer_head *bh,
-     struct msdos_dir_entry *de,struct inode* victim)
+static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
+     struct buffer_head *bh, struct msdos_dir_entry *de)
 {
 	struct super_block *sb = dir->i_sb;
-	victim->i_nlink = 0;
-	victim->i_mtime = dir->i_mtime = CURRENT_TIME;
-	victim->i_atime = dir->i_atime = CURRENT_TIME;
+	loff_t offset;
+	int i,ino;
+
+	/* remove the shortname */
+	dir->i_mtime = CURRENT_TIME;
+	dir->i_atime = CURRENT_TIME;
 	dir->i_version = ++event;
-	MSDOS_I(victim)->i_busy = 1;
+	MSDOS_I(dir)->i_last_pos = 0;
 	mark_inode_dirty(dir);
-	mark_inode_dirty(victim);
 	de->name[0] = DELETED_FLAG;
 	fat_mark_buffer_dirty(sb, bh, 1);
-}
-
-static int vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
-     struct inode* victim)
-{
-	struct super_block *sb = dir->i_sb;
-	loff_t offset;
-	struct buffer_head *bh=NULL;
-	struct msdos_dir_entry *de;
-	int res, i;
-
-	/* remove the shortname */
-	offset = sinfo->shortname_offset;
-	res = fat_get_entry(dir, &offset, &bh, &de);
-	if (res < 0) return res;
-	vfat_free_ino(dir,bh,de,victim);
 	/* remove the longname */
-	offset = sinfo->longname_offset;
+	offset = sinfo->longname_offset; de = NULL;
 	for (i = sinfo->long_slots; i > 0; --i) {
-		if (fat_get_entry(dir, &offset, &bh, &de) < 0)
+		if (fat_get_entry(dir, &offset, &bh, &de, &ino) < 0)
 			continue;
 		de->name[0] = DELETED_FLAG;
 		de->attr = 0;
 		fat_mark_buffer_dirty(sb, bh, 1);
 	}
 	if (bh) fat_brelse(sb, bh);
-	return 0;
 }
 
-static int vfat_rmdirx(struct inode *dir,struct dentry* dentry)
+int vfat_rmdir(struct inode *dir,struct dentry* dentry)
 {
 	int res;
 	struct vfat_slot_info sinfo;
+	struct buffer_head *bh = NULL;
+	struct msdos_dir_entry *de;
 
-	PRINTK1(("vfat_rmdirx: dentry=%p\n", dentry));
-	res = vfat_find(dir,&dentry->d_name,0,0,&sinfo);
+	if (!list_empty(&dentry->d_hash))
+		return -EBUSY;
 
-	if (res >= 0 && sinfo.total_slots > 0) {
-		if (!list_empty(&dentry->d_hash))
-			return -EBUSY;
-		res = vfat_empty(dentry->d_inode);
-		if (res)
-			return res;
-		
-		res = vfat_remove_entry(dir,&sinfo,dentry->d_inode);
-		if (res >= 0) {
-			dir->i_nlink--;
-			res = 0;
-		}
-	}
-	return res;
-}
-
-/***** Remove a directory */
-int vfat_rmdir(struct inode *dir,struct dentry* dentry)
-{
-	int res;
-	PRINTK1(("vfat_rmdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
+	res = fat_dir_empty(dentry->d_inode);
+	if (res)
+		return res;
 
-	res = -EBUSY;
-	if (list_empty(&dentry->d_hash)) {
-		res = vfat_rmdirx(dir, dentry);
-		/* If that went OK all aliases are already dropped */
-	}
-	return res;
+	res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
+	if (res<0)
+		return res;
+	dentry->d_inode->i_nlink = 0;
+	dentry->d_inode->i_mtime = CURRENT_TIME;
+	dentry->d_inode->i_atime = CURRENT_TIME;
+	fat_detach(dentry->d_inode);
+	mark_inode_dirty(dentry->d_inode);
+	/* releases bh */
+	vfat_remove_entry(dir,&sinfo,bh,de);
+	dir->i_nlink--;
+	return 0;
 }
 
-static int vfat_unlinkx(
-	struct inode *dir,
-	struct dentry* dentry,
-	int nospc)	/* Flag special file ? */
+int vfat_unlink(struct inode *dir, struct dentry* dentry)
 {
 	int res;
 	struct vfat_slot_info sinfo;
+	struct buffer_head *bh = NULL;
+	struct msdos_dir_entry *de;
 
-	PRINTK1(("vfat_unlinkx: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
-	res = vfat_find(dir,&dentry->d_name,0,0,&sinfo);
-
-	if (res >= 0 && sinfo.total_slots > 0) {
-		if (!S_ISREG(dentry->d_inode->i_mode) && nospc) {
-			return -EPERM;
-		}
-		res = vfat_remove_entry(dir,&sinfo,dentry->d_inode);
-		if (res > 0) {
-			res = 0;
-		}
-	}
+	PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
+	res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
+	if (res < 0)
+		return res;
+	dentry->d_inode->i_nlink = 0;
+	dentry->d_inode->i_mtime = CURRENT_TIME;
+	dentry->d_inode->i_atime = CURRENT_TIME;
+	fat_detach(dentry->d_inode);
+	mark_inode_dirty(dentry->d_inode);
+	/* releases bh */
+	vfat_remove_entry(dir,&sinfo,bh,de);
+	d_delete(dentry);
 
 	return res;
 }
@@ -1490,64 +1093,47 @@
 
 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
 {
-	struct inode *inode;
+	struct super_block *sb = dir->i_sb;
+	struct inode *inode = NULL;
 	struct vfat_slot_info sinfo;
+	struct buffer_head *bh = NULL;
+	struct msdos_dir_entry *de;
 	int res;
 
-	PRINTK1(("vfat_mkdir: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
-	fat_lock_creation();
-	if ((res = vfat_create_entry(dir,&dentry->d_name,1,&inode)) < 0) {
-		fat_unlock_creation();
+	res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
+	if (res < 0)
 		return res;
-	}
-
+	inode = fat_build_inode(sb, de, sinfo.ino, &res);
+	if (!inode)
+		goto out;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(inode);
+	inode->i_version = ++event;
+	dir->i_version = event;
+	MSDOS_I(dir)->i_last_pos = 0;
 	dir->i_nlink++;
 	inode->i_nlink = 2; /* no need to mark them dirty */
 
 	res = vfat_create_dotdirs(inode, dir);
 	if (res < 0)
 		goto mkdir_failed;
-	fat_unlock_creation();
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
 	d_instantiate(dentry,inode);
+out:
+	fat_brelse(sb, bh);
 	return res;
 
 mkdir_failed:
-	fat_unlock_creation();
-	if (vfat_find(dir,&dentry->d_name,0,0,&sinfo) < 0)
-		goto mkdir_panic;
-	if (vfat_remove_entry(dir, &sinfo, inode) < 0)
-		goto mkdir_panic;
+	inode->i_nlink = 0;
+	inode->i_mtime = CURRENT_TIME;
+	inode->i_atime = CURRENT_TIME;
+	fat_detach(inode);
+	mark_inode_dirty(inode);
+	/* releases bh */
+	vfat_remove_entry(dir,&sinfo,bh,de);
 	iput(inode);
 	dir->i_nlink--;
 	return res;
-
-mkdir_panic:
-	dir->i_version = ++event;
-	fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
-	return res;
-}
-
-/***** Unlink, as called for msdosfs */
-int vfat_unlink(struct inode *dir,struct dentry* dentry)
-{
-	int res;
-
-	PRINTK1(("vfat_unlink: dentry=%p, inode=%p\n", dentry, dentry->d_inode));
-	res = vfat_unlinkx (dir,dentry,1);
-	if (res >= 0)
-		d_delete(dentry);
-	return res;
-}
-
-/***** Unlink, as called for uvfatfs */
-int vfat_unlink_uvfat(struct inode *dir,struct dentry *dentry)
-{
-	int res;
-
-	res = vfat_unlinkx (dir,dentry,0);
-	iput(dir);
-	return res;
 }
  
 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
@@ -1555,148 +1141,87 @@
 {
 	struct super_block *sb = old_dir->i_sb;
 	struct buffer_head *old_bh,*new_bh,*dotdot_bh;
-	struct msdos_dir_entry *old_de,*dotdot_de;
-	loff_t old_offset,new_offset,old_longname_offset;
-	int old_slots,old_ino,new_ino,dotdot_ino;
-	struct inode *old_inode, *new_inode, *dotdot_inode;
-	int res, is_dir, i;
-	int locked = 0;
-	struct vfat_slot_info sinfo;
+	struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
+	int dotdot_ino;
+	struct inode *old_inode, *new_inode;
+	int res, is_dir;
+	struct vfat_slot_info old_sinfo,sinfo;
 
-	PRINTK1(("vfat_rename: Entering: old_dentry=%p, old_inode=%p, old ino=%ld, new_dentry=%p, new_inode=%p, new ino=%ld\n",
-		 old_dentry, old_dentry->d_inode, old_dentry->d_inode->i_ino,
-		 new_dentry, new_dentry->d_inode,
-		 new_dentry->d_inode ? new_dentry->d_inode->i_ino : 0));
-
-	old_bh = new_bh = NULL;
-	old_inode = new_inode = NULL;
-	res = vfat_find(old_dir,&old_dentry->d_name,0,0,&sinfo);
+	old_bh = new_bh = dotdot_bh = NULL;
+	old_inode = old_dentry->d_inode;
+	new_inode = new_dentry->d_inode;
+	res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
 	PRINTK3(("vfat_rename 2\n"));
 	if (res < 0) goto rename_done;
 
-	old_slots = sinfo.total_slots;
-	old_longname_offset = sinfo.longname_offset;
-	old_offset = sinfo.shortname_offset;
-	old_ino = sinfo.ino;
-	res = fat_get_entry(old_dir, &old_offset, &old_bh, &old_de);
-	PRINTK3(("vfat_rename 3\n"));
-	if (res < 0) goto rename_done;
-
-	res = -ENOENT;
-	old_inode = old_dentry->d_inode;
 	is_dir = S_ISDIR(old_inode->i_mode);
 
-	fat_lock_creation(); locked = 1;
+	if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
+				&dotdot_de,&dotdot_ino)) < 0)
+		goto rename_done;
 
 	if (new_dentry->d_inode) {
-		/*
-		 * OK, we have to remove the target. We should do it so
-		 * that nobody might go and find it negative. Actually we
-		 * should give warranties wrt preserving target over the
-		 * possible crash, but that's another story. We can't
-		 * get here with the target unhashed, so the directory entry
-		 * must exist.
-		 */
-
-		new_inode = new_dentry->d_inode;
-		res = vfat_find(new_dir,&new_dentry->d_name,0,is_dir,&sinfo);
-		if (res < 0 || new_inode->i_ino != sinfo.ino) {
+		res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
+				&new_de);
+		if (res < 0 || MSDOS_I(new_inode)->i_location != sinfo.ino) {
 			/* WTF??? Cry and fail. */
 			printk(KERN_WARNING "vfat_rename: fs corrupted\n");
 			goto rename_done;
 		}
 
 		if (is_dir) {
-			res = vfat_empty(new_inode);
+			res = fat_dir_empty(new_inode);
 			if (res)
 				goto rename_done;
 		}
-		res = vfat_remove_entry(new_dir,&sinfo,new_inode);
-		if (res)
-			goto rename_done;
-
-		if (is_dir)
-			new_dir->i_nlink--;
+		fat_detach(new_inode);
+	} else {
+		res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
+					&new_bh,&new_de);
+		if (res < 0) goto rename_done;
 	}
 
-	/* Serious lossage here. FAT uses braindead inode numbers scheme,
-	 * so we can't simply cannibalize the entry. It means that we have
-	 * no warranties that crash here will not make target disappear
-	 * after reboot. Lose, lose. Nothing to do with that until we'll
-	 * separate the functions of i_ino: it serves both as a search key
-	 * in icache and as a part of stat output. It would kill all the
-	 * 'busy' stuff on the spot. Later.
-	 */
-
-	res = vfat_find(new_dir,&new_dentry->d_name,1,is_dir,&sinfo);
-
-	if (res < 0) goto rename_done;
-
-	new_offset = sinfo.shortname_offset;
-	new_ino = sinfo.ino;
-
-	/* XXX: take care of other owners */
+	new_dir->i_version = ++event;
+	MSDOS_I(new_dir)->i_last_pos = 0;
 
-	remove_inode_hash(old_inode);
-	fat_cache_inval_inode(old_inode);
-	old_inode->i_ino = new_ino;
-	old_inode->i_version = ++event;
-	insert_inode_hash(old_inode);
+	/* releases old_bh */
+	vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
+	old_bh=NULL;
+	fat_detach(old_inode);
+	fat_attach(old_inode, sinfo.ino);
 	mark_inode_dirty(old_inode);
 
 	old_dir->i_version = ++event;
-	new_dir->i_version = ++event;
-
-	/* remove the old entry */
-	for (i = old_slots; i > 0; --i) {
-		res = fat_get_entry(old_dir, &old_longname_offset, &old_bh, &old_de);
-		if (res < 0) {
-			printk("vfat_rename: problem 1\n");
-			continue;
-		}
-		old_de->name[0] = DELETED_FLAG;
-		old_de->attr = 0;
-		fat_mark_buffer_dirty(sb, old_bh, 1);
+	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(old_dir);
+	if (new_inode) {
+		new_inode->i_nlink--;
+		new_inode->i_ctime=CURRENT_TIME;
 	}
 
 	if (is_dir) {
-		if ((res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
-		    &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
-		if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
-			fat_brelse(sb, dotdot_bh);
-			res = -EIO;
-			goto rename_done;
-		}
-		MSDOS_I(dotdot_inode)->i_start = MSDOS_I(new_dir)->i_start;
-		MSDOS_I(dotdot_inode)->i_logstart = MSDOS_I(new_dir)->i_logstart;
-		dotdot_de->start = CT_LE_W(MSDOS_I(new_dir)->i_logstart);
-		dotdot_de->starthi = CT_LE_W((MSDOS_I(new_dir)->i_logstart) >> 16);
-		mark_inode_dirty(dotdot_inode);
+		int start = MSDOS_I(new_dir)->i_logstart;
+		dotdot_de->start = CT_LE_W(start);
+		dotdot_de->starthi = CT_LE_W(start>>16);
 		fat_mark_buffer_dirty(sb, dotdot_bh, 1);
 		old_dir->i_nlink--;
-		new_dir->i_nlink++;
-		/* no need to mark them dirty */
-		dotdot_inode->i_nlink = new_dir->i_nlink;
-		iput(dotdot_inode);
-		fat_brelse(sb, dotdot_bh);
+		if (new_inode) {
+			new_inode->i_nlink--;
+		} else {
+			new_dir->i_nlink++;
+			mark_inode_dirty(new_dir);
+		}
 	}
 
-	if (res >= 0)
-		res = 0;
-
 rename_done:
-	if (locked)
-		fat_unlock_creation();
-	if (old_bh)
-		fat_brelse(sb, old_bh);
-	if (new_bh)
-		fat_brelse(sb, new_bh);
+	fat_brelse(sb, dotdot_bh);
+	fat_brelse(sb, old_bh);
+	fat_brelse(sb, new_bh);
 	return res;
 
 }
 
 
-
 /* Public inode operations for the VFAT fs */
 struct inode_operations vfat_dir_inode_operations = {
 	&fat_dir_operations,	/* default directory file-ops */
@@ -1718,10 +1243,38 @@
 	NULL			/* permission */
 };
 
-
-void vfat_read_inode(struct inode *inode)
+struct super_block *vfat_read_super(struct super_block *sb,void *data,
+				    int silent)
 {
-	fat_read_inode(inode, &vfat_dir_inode_operations);
+	struct super_block *res;
+  
+	MOD_INC_USE_COUNT;
+	
+	MSDOS_SB(sb)->options.isvfat = 1;
+
+	res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
+	if (res == NULL) {
+		sb->s_dev = 0;
+		MOD_DEC_USE_COUNT;
+		return NULL;
+	}
+
+	if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
+		MOD_DEC_USE_COUNT;
+	} else {
+		MSDOS_SB(sb)->put_super_callback=vfat_put_super_callback;
+		MSDOS_SB(sb)->options.dotsOK = 0;
+		if (MSDOS_SB(sb)->options.posixfs) {
+			MSDOS_SB(sb)->options.name_check = 's';
+		}
+		if (MSDOS_SB(sb)->options.name_check != 's') {
+			sb->s_root->d_op = &vfat_dentry_ops[0];
+		} else {
+			sb->s_root->d_op = &vfat_dentry_ops[2];
+		}
+	}
+
+	return res;
 }
 
 #ifdef MODULE
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/fs/vfat/vfatfs_syms.c linux.pre11.3/fs/vfat/vfatfs_syms.c
--- linux.vanilla/fs/vfat/vfatfs_syms.c	Sun Nov  8 15:06:35 1998
+++ linux.pre11.3/fs/vfat/vfatfs_syms.c	Mon Jul 19 23:26:28 1999
@@ -21,13 +21,10 @@
 
 EXPORT_SYMBOL(vfat_create);
 EXPORT_SYMBOL(vfat_unlink);
-EXPORT_SYMBOL(vfat_unlink_uvfat);
 EXPORT_SYMBOL(vfat_mkdir);
 EXPORT_SYMBOL(vfat_rmdir);
 EXPORT_SYMBOL(vfat_rename);
-EXPORT_SYMBOL(vfat_put_super);
 EXPORT_SYMBOL(vfat_read_super);
-EXPORT_SYMBOL(vfat_read_inode);
 EXPORT_SYMBOL(vfat_lookup);
 
 int init_vfat_fs(void)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/core_cia.h linux.pre11.3/include/asm-alpha/core_cia.h
--- linux.vanilla/include/asm-alpha/core_cia.h	Thu Jan 14 01:25:27 1999
+++ linux.pre11.3/include/asm-alpha/core_cia.h	Mon Jul 19 23:26:48 1999
@@ -77,14 +77,14 @@
 #define CIA_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define CIA_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define CIA_DMA_WIN_BASE_DEFAULT	(1024*1024*1024)
-#define CIA_DMA_WIN_SIZE_DEFAULT	(1024*1024*1024)
+#define CIA_DMA_WIN_BASE_DEFAULT	(2UL*1024*1024*1024)
+#define CIA_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
 #define CIA_DMA_WIN_BASE		alpha_mv.dma_win_base
 #define CIA_DMA_WIN_SIZE		alpha_mv.dma_win_size
 #else
-#define CIA_DMA_WIN_BASE		CIA_DMA_WIN_SIZE_DEFAULT
+#define CIA_DMA_WIN_BASE		CIA_DMA_WIN_BASE_DEFAULT
 #define CIA_DMA_WIN_SIZE		CIA_DMA_WIN_SIZE_DEFAULT
 #endif
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/core_pyxis.h linux.pre11.3/include/asm-alpha/core_pyxis.h
--- linux.vanilla/include/asm-alpha/core_pyxis.h	Mon Dec 28 23:09:47 1998
+++ linux.pre11.3/include/asm-alpha/core_pyxis.h	Mon Jul 19 23:26:48 1999
@@ -74,8 +74,8 @@
 #define PYXIS_MEM_R2_MASK 0x07ffffff  /* SPARSE Mem region 2 mask is 27 bits */
 #define PYXIS_MEM_R3_MASK 0x03ffffff  /* SPARSE Mem region 3 mask is 26 bits */
 
-#define PYXIS_DMA_WIN_BASE_DEFAULT	(1024*1024*1024)
-#define PYXIS_DMA_WIN_SIZE_DEFAULT	(1024*1024*1024)
+#define PYXIS_DMA_WIN_BASE_DEFAULT	(2UL*1024*1024*1024)
+#define PYXIS_DMA_WIN_SIZE_DEFAULT	(2UL*1024*1024*1024)
 
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
 #define PYXIS_DMA_WIN_BASE		alpha_mv.dma_win_base
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/keyboard.h linux.pre11.3/include/asm-alpha/keyboard.h
--- linux.vanilla/include/asm-alpha/keyboard.h	Wed Apr 28 19:14:32 1999
+++ linux.pre11.3/include/asm-alpha/keyboard.h	Mon Jul 19 23:26:48 1999
@@ -13,6 +13,10 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
@@ -37,6 +41,33 @@
 
 #define SYSRQ_KEY 0x54
 
-#endif /* __KERNEL__ */
+/* resource allocation */
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+#ifndef CONFIG_PCI
+# define AUX_IRQ	9		/* Jensen is odd indeed */
+#else
+# define AUX_IRQ	12
+#endif
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
 
-#endif /* __ASMalpha_KEYBOARD_H */
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
+
+#endif /* __KERNEL__ */
+#endif /* _ALPHA_KEYBOARD_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/machvec.h linux.pre11.3/include/asm-alpha/machvec.h
--- linux.vanilla/include/asm-alpha/machvec.h	Mon Dec 28 23:09:47 1998
+++ linux.pre11.3/include/asm-alpha/machvec.h	Mon Jul 19 23:26:48 1999
@@ -32,7 +32,6 @@
 	int rtc_port;
 	int max_asn;
 	unsigned long max_dma_address;
-	unsigned long mmu_context_mask;
 	unsigned long irq_probe_mask;
 	unsigned long iack_sc;
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/mmu_context.h linux.pre11.3/include/asm-alpha/mmu_context.h
--- linux.vanilla/include/asm-alpha/mmu_context.h	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/include/asm-alpha/mmu_context.h	Tue Jul 20 00:11:23 1999
@@ -26,11 +26,10 @@
  * in use) and the Valid bit set, then entries can also effectively be
  * made coherent by assigning a new, unused ASN to the currently
  * running process and not reusing the previous ASN before calling the
- * appropriate PALcode routine to invalidate the translation buffer
- * (TB)". 
+ * appropriate PALcode routine to invalidate the translation buffer (TB)". 
  *
  * In short, the EV4 has a "kind of" ASN capability, but it doesn't actually
- * work correctly and can thus not be used (explaining the lack of PAL-code
+ * work correctly and can thus not be used (explaining the lack of PALcode
  * support).
  */
 #define EV4_MAX_ASN 63
@@ -49,44 +48,40 @@
 # endif
 #endif
 
-#ifdef __SMP__
-#define WIDTH_THIS_PROCESSOR	5
 /*
- * last_asn[processor]:
+ * cpu_last_asn(processor):
  * 63                                            0
  * +-------------+----------------+--------------+
  * | asn version | this processor | hardware asn |
  * +-------------+----------------+--------------+
  */
-extern unsigned long last_asn[];
-#define asn_cache last_asn[p->processor]
 
+#ifdef __SMP__
+#include <asm/smp.h>
+#define cpu_last_asn(cpuid)	(cpu_data[cpuid].last_asn)
 #else
-#define WIDTH_THIS_PROCESSOR	0
-/*
- * asn_cache:
- * 63                                            0
- * +------------------------------+--------------+
- * |         asn version          | hardware asn |
- * +------------------------------+--------------+
- */
-extern unsigned long asn_cache;
+extern unsigned long last_asn;
+#define cpu_last_asn(cpuid)	last_asn
 #endif /* __SMP__ */
 
 #define WIDTH_HARDWARE_ASN	8
+#ifdef __SMP__
+#define WIDTH_THIS_PROCESSOR	5
+#else
+#define WIDTH_THIS_PROCESSOR	0
+#endif
 #define ASN_FIRST_VERSION (1UL << (WIDTH_THIS_PROCESSOR + WIDTH_HARDWARE_ASN))
 #define HARDWARE_ASN_MASK ((1UL << WIDTH_HARDWARE_ASN) - 1)
 
 /*
  * NOTE! The way this is set up, the high bits of the "asn_cache" (and
- * the "mm->context") are the ASN _version_ code. A version of 0 is
- * always considered invalid, so to invalidate another process you only
- * need to do "p->mm->context = 0".
+ * "mm->context") are the ASN _version_ code. A version of 0 is always
+ * considered invalid, so to invalidate another process you only need
+ * to do "p->mm->context = 0".
  *
  * If we need more ASN's than the processor has, we invalidate the old
  * user TLB's (tbiap()) and start a new ASN version. That will automatically
- * force a new asn for any other processes the next time they want to
- * run.
+ * force a new asn for any other processes the next time they want to run.
  */
 
 #ifndef __EXTERN_INLINE
@@ -96,22 +91,59 @@
 
 extern void get_new_mmu_context(struct task_struct *p, struct mm_struct *mm);
 
-__EXTERN_INLINE void ev4_get_mmu_context(struct task_struct *p)
+static inline unsigned long
+__get_new_mmu_context(void)
 {
-	/* As described, ASN's are broken.  */
+	unsigned long asn = cpu_last_asn(smp_processor_id());
+	unsigned long next = asn + 1;
+
+	/* If we've wrapped, flush the whole user TLB.  */
+	if ((asn & HARDWARE_ASN_MASK) >= MAX_ASN) {
+		tbiap();
+		next = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
+	}
+	cpu_last_asn(smp_processor_id()) = next;
+	return next;
 }
 
-__EXTERN_INLINE void ev5_get_mmu_context(struct task_struct *p)
+__EXTERN_INLINE void
+ev4_get_mmu_context(struct task_struct *p)
 {
-	struct mm_struct * mm = p->mm;
+	/* As described, ASN's are broken.  But we can optimize for
+	   switching between threads -- if the mm is unchanged from
+	   current we needn't flush.  */
+	/* ??? May not be needed because EV4 PALcode recognizes that
+	   ASN's are broken and does a tbiap itself on swpctx, under
+	   the "Must set ASN or flush" rule.  At least this is true
+	   for a 1992 SRM, reports Joseph Martin (jmartin@hlo.dec.com).
+	   I'm going to leave this here anyway, just to Be Sure.  -- r~  */
+
+	if (current->mm != p->mm)
+		tbiap();
+}
 
-	if (mm) {
-		unsigned long asn = asn_cache;
-		/* Check if our ASN is of an older version,
-		   or on a different CPU, and thus invalid.  */
-		if ((mm->context ^ asn) & ~HARDWARE_ASN_MASK)
-			get_new_mmu_context(p, mm);
+__EXTERN_INLINE void
+ev5_get_mmu_context(struct task_struct *p)
+{
+	/* Check if our ASN is of an older version, or on a different CPU,
+	   and thus invalid.  */
+	/* ??? If we have two threads on different cpus, we'll continually
+	   fight over the context.  Find a way to record a per-mm, per-cpu
+	   value for the asn.  */
+
+	unsigned long asn = cpu_last_asn(smp_processor_id());
+	struct mm_struct *mm = p->mm;
+	unsigned long mmc = mm->context;
+	
+	if ((mmc ^ asn) & ~HARDWARE_ASN_MASK) {
+		mmc = __get_new_mmu_context();
+		mm->context = mmc;
 	}
+
+	/* Always update the PCB ASN.  Another thread may have allocated
+	   a new mm->context (via flush_tlb_mm) without the ASN serial
+	   number wrapping.  We have no way to detect when this is needed.  */
+	p->tss.asn = mmc & HARDWARE_ASN_MASK;
 }
 
 #ifdef CONFIG_ALPHA_GENERIC
@@ -124,40 +156,40 @@
 # endif
 #endif
 
-extern inline void init_new_context(struct mm_struct *mm)
+extern inline void
+init_new_context(struct mm_struct *mm)
 {
 	mm->context = 0;
 }
 
-extern inline void destroy_context(struct mm_struct *mm)
+extern inline void
+destroy_context(struct mm_struct *mm)
 {
 	/* Nothing to do.  */
 }
 
+#ifdef __MMU_EXTERN_INLINE
+#undef __EXTERN_INLINE
+#undef __MMU_EXTERN_INLINE
+#endif
 
 /*
  * Force a context reload. This is needed when we change the page
  * table pointer or when we update the ASN of the current process.
  */
 
-#if defined(CONFIG_ALPHA_GENERIC)
-#define MASK_CONTEXT(tss) \
- ((struct thread_struct *)((unsigned long)(tss) & alpha_mv.mmu_context_mask))
-#elif defined(CONFIG_ALPHA_DP264)
-#define MASK_CONTEXT(tss) \
- ((struct thread_struct *)((unsigned long)(tss) & 0xfffffffffful))
-#else
-#define MASK_CONTEXT(tss)  (tss)
+/* Don't get into trouble with dueling __EXTERN_INLINEs.  */
+#ifndef __EXTERN_INLINE
+#include <asm/io.h>
 #endif
 
-__EXTERN_INLINE struct thread_struct *
+extern inline unsigned long
 __reload_tss(struct thread_struct *tss)
 {
-	register struct thread_struct *a0 __asm__("$16");
-	register struct thread_struct *v0 __asm__("$0");
-
-	a0 = MASK_CONTEXT(tss);
+	register unsigned long a0 __asm__("$16");
+	register unsigned long v0 __asm__("$0");
 
+	a0 = virt_to_phys(tss);
 	__asm__ __volatile__(
 		"call_pal %2 #__reload_tss"
 		: "=r"(v0), "=r"(a0)
@@ -167,27 +199,22 @@
 	return v0;
 }
 
-__EXTERN_INLINE void
+extern inline void
 reload_context(struct task_struct *task)
 {
 	__reload_tss(&task->tss);
 }
 
 /*
- * After we have set current->mm to a new value, this activates the
- * context for the new mm so we see the new mappings.
+ * After setting current->mm to a new value, activate the context for the
+ * new mm so we see the new mappings.
  */
 
-__EXTERN_INLINE void
+extern inline void
 activate_context(struct task_struct *task)
 {
-	get_mmu_context(task);
+	get_new_mmu_context(task, task->mm);
 	reload_context(task);
 }
-
-#ifdef __MMU_EXTERN_INLINE
-#undef __EXTERN_INLINE
-#undef __MMU_EXTERN_INLINE
-#endif
 
 #endif /* __ALPHA_MMU_CONTEXT_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/pgtable.h linux.pre11.3/include/asm-alpha/pgtable.h
--- linux.vanilla/include/asm-alpha/pgtable.h	Thu May 27 22:12:00 1999
+++ linux.pre11.3/include/asm-alpha/pgtable.h	Tue Jul 20 00:11:23 1999
@@ -49,7 +49,6 @@
 __EXTERN_INLINE void
 ev5_flush_tlb_current(struct mm_struct *mm)
 {
-	mm->context = 0;
 	get_new_mmu_context(current, mm);
 	reload_context(current);
 }
@@ -71,7 +70,7 @@
 			   struct vm_area_struct *vma,
 			   unsigned long addr)
 {
-	tbi(2 + ((vma->vm_flags & VM_EXEC) != 0), addr);
+	tbi(((vma->vm_flags & VM_EXEC) != 0) ? 3 : 2, addr);
 }
 
 __EXTERN_INLINE void
@@ -299,7 +298,7 @@
 
 #define BAD_PAGETABLE	__bad_pagetable()
 #define BAD_PAGE	__bad_page()
-#define ZERO_PAGE	(PAGE_OFFSET+0x30A000)
+#define ZERO_PAGE(vaddr)	(PAGE_OFFSET+0x30A000)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/smp.h linux.pre11.3/include/asm-alpha/smp.h
--- linux.vanilla/include/asm-alpha/smp.h	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/include/asm-alpha/smp.h	Mon Jul 19 23:26:48 1999
@@ -9,6 +9,7 @@
 
 struct cpuinfo_alpha {
 	unsigned long loops_per_sec;
+	unsigned long last_asn;
 	unsigned long *pgd_cache;
 	unsigned long *pte_cache;
 	unsigned long pgtable_cache_sz;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/smplock.h linux.pre11.3/include/asm-alpha/smplock.h
--- linux.vanilla/include/asm-alpha/smplock.h	Sun Nov  8 15:06:56 1998
+++ linux.pre11.3/include/asm-alpha/smplock.h	Mon Jul 19 23:26:48 1999
@@ -13,22 +13,23 @@
 /*
  * Release global kernel lock and global interrupt lock
  */
-static __inline__ void release_kernel_lock(struct task_struct *task, int cpu)
-{
-	if (task->lock_depth >= 0)
-		spin_unlock(&kernel_flag);
-	release_irqlock(cpu);
-	__sti();
-}
+#define release_kernel_lock(task, cpu) \
+do { \
+	if (task->lock_depth >= 0) \
+		spin_unlock(&kernel_flag); \
+	release_irqlock(cpu); \
+	__sti(); \
+} while (0)
 
 /*
  * Re-acquire the kernel lock
  */
-static __inline__ void reacquire_kernel_lock(struct task_struct *task)
-{
-	if (task->lock_depth >= 0)
-		spin_lock(&kernel_flag);
-}
+#define reacquire_kernel_lock(task) \
+do { \
+	if (task->lock_depth >= 0) \
+		spin_lock(&kernel_flag); \
+} while (0)
+
 
 /*
  * Getting the big kernel lock.
@@ -37,14 +38,14 @@
  * so we only need to worry about other
  * CPU's.
  */
-static __inline__ void lock_kernel(void)
-{
-	if (!++current->lock_depth)
-		spin_lock(&kernel_flag);
-}
+#define lock_kernel() \
+do { \
+	if (!++current->lock_depth) \
+		spin_lock(&kernel_flag); \
+} while(0)
 
-static __inline__ void unlock_kernel(void)
-{
-	if (--current->lock_depth < 0)
-		spin_unlock(&kernel_flag);
-}
+#define unlock_kernel() \
+do { \
+	if (--current->lock_depth < 0) \
+		spin_unlock(&kernel_flag); \
+} while(0)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/socket.h linux.pre11.3/include/asm-alpha/socket.h
--- linux.vanilla/include/asm-alpha/socket.h	Sun Nov  8 15:06:56 1998
+++ linux.pre11.3/include/asm-alpha/socket.h	Mon Jul 19 23:26:48 1999
@@ -48,4 +48,17 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	20
 #define SO_SECURITY_ENCRYPTION_NETWORK		21
 
+#ifdef __KERNEL__
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+#endif
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/spinlock.h linux.pre11.3/include/asm-alpha/spinlock.h
--- linux.vanilla/include/asm-alpha/spinlock.h	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/include/asm-alpha/spinlock.h	Mon Jul 19 23:26:48 1999
@@ -20,7 +20,7 @@
 
 #define spin_lock_init(lock)			((void) 0)
 #define spin_lock(lock)				((void) 0)
-#define spin_trylock(lock)			((void) 0)
+#define spin_trylock(lock)			(1)
 #define spin_unlock_wait(lock)			((void) 0)
 #define spin_unlock(lock)			((void) 0)
 #define spin_lock_irq(lock)			cli()
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-alpha/system.h linux.pre11.3/include/asm-alpha/system.h
--- linux.vanilla/include/asm-alpha/system.h	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/include/asm-alpha/system.h	Mon Jul 19 23:26:46 1999
@@ -347,6 +347,7 @@
 #define xchg(ptr,x) \
   ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 #define tas(ptr) (xchg((ptr),1))
+#define gethere() ({ here: && here;  })
 
 #endif /* __ASSEMBLY__ */
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-arm/arch-arc/keyboard.h linux.pre11.3/include/asm-arm/arch-arc/keyboard.h
--- linux.vanilla/include/asm-arm/arch-arc/keyboard.h	Thu May 27 22:12:00 1999
+++ linux.pre11.3/include/asm-arm/arch-arc/keyboard.h	Mon Jul 19 23:26:50 1999
@@ -7,6 +7,8 @@
  * Copyright (C) 1998 Russell King
  */
 
+#include <linux/ioport.h>
+#include <asm/io.h>
 #include <asm/irq.h>
 
 #define NR_SCANCODES 128
@@ -27,3 +29,29 @@
 #define kbd_enable_irq()		enable_irq(IRQ_KEYBOARDRX)
 
 #define SYSRQ_KEY	13
+
+/* resource allocation */
+#define KEYBOARD_IRQ                   1
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-arm/arch-ebsa285/keyboard.h linux.pre11.3/include/asm-arm/arch-ebsa285/keyboard.h
--- linux.vanilla/include/asm-arm/arch-ebsa285/keyboard.h	Thu May 27 22:12:01 1999
+++ linux.pre11.3/include/asm-arm/arch-ebsa285/keyboard.h	Mon Jul 19 23:26:50 1999
@@ -6,7 +6,9 @@
  * (C) 1998 Russell King
  * (C) 1998 Phil Blundell
  */
+#include <linux/ioport.h>
 #include <asm/irq.h>
+#include <asm/io.h>
 #include <asm/system.h>
 
 extern int have_isa_bridge;
@@ -69,3 +71,29 @@
 #define kbd_enable_irq()
 
 #define SYSRQ_KEY	0x54
+
+/* resource allocation */
+#define KEYBOARD_IRQ                   1
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-arm/arch-rpc/keyboard.h linux.pre11.3/include/asm-arm/arch-rpc/keyboard.h
--- linux.vanilla/include/asm-arm/arch-rpc/keyboard.h	Thu May 27 22:12:01 1999
+++ linux.pre11.3/include/asm-arm/arch-rpc/keyboard.h	Mon Jul 19 23:26:50 1999
@@ -6,6 +6,8 @@
  * (C) 1998 Russell King
  */
 
+#include <linux/ioport.h>
+#include <asm/io.h>
 #include <asm/irq.h>
 
 #define NR_SCANCODES 128
@@ -26,3 +28,32 @@
 #define kbd_enable_irq()		enable_irq(IRQ_KEYBOARDRX)
 
 #define SYSRQ_KEY	13
+
+/* resource allocation */
+#define KEYBOARD_IRQ                   1
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+#define keyboard_setup()						\
+	request_region(0x60, 16, "keyboard")
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-arm/proc-armo/pgtable.h linux.pre11.3/include/asm-arm/proc-armo/pgtable.h
--- linux.vanilla/include/asm-arm/proc-armo/pgtable.h	Thu May 27 22:12:01 1999
+++ linux.pre11.3/include/asm-arm/proc-armo/pgtable.h	Mon Jul 19 23:26:51 1999
@@ -173,7 +173,7 @@
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long) empty_zero_page)
+#define ZERO_PAGE(vaddr) ((unsigned long) empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BYTES_PER_PTR			(sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-arm/proc-armv/pgtable.h linux.pre11.3/include/asm-arm/proc-armv/pgtable.h
--- linux.vanilla/include/asm-arm/proc-armv/pgtable.h	Thu May 27 22:12:01 1999
+++ linux.pre11.3/include/asm-arm/proc-armv/pgtable.h	Mon Jul 19 23:26:51 1999
@@ -187,7 +187,7 @@
 
 #define BAD_PAGETABLE	__bad_pagetable()
 #define BAD_PAGE	__bad_page()
-#define ZERO_PAGE	((unsigned long) empty_zero_page)
+#define ZERO_PAGE(vaddr)	((unsigned long) empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BYTES_PER_PTR	(sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-arm/socket.h linux.pre11.3/include/asm-arm/socket.h
--- linux.vanilla/include/asm-arm/socket.h	Tue Dec 22 23:20:07 1998
+++ linux.pre11.3/include/asm-arm/socket.h	Mon Jul 19 23:26:50 1999
@@ -39,4 +39,16 @@
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/atomic.h linux.pre11.3/include/asm-i386/atomic.h
--- linux.vanilla/include/asm-i386/atomic.h	Sun Nov  8 15:06:53 1998
+++ linux.pre11.3/include/asm-i386/atomic.h	Tue Jul 20 00:11:36 1999
@@ -73,6 +73,17 @@
 	return c != 0;
 }
 
+extern __inline__ int atomic_inc_and_test_greater_zero(volatile atomic_t *v)
+{
+	unsigned char c;
+
+	__asm__ __volatile__(
+		LOCK "incl %0; setg %1"
+		:"=m" (__atomic_fool_gcc(v)), "=qm" (c)
+		:"m" (__atomic_fool_gcc(v)));
+	return c; /* can be only 0 or 1 */
+}
+
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
 __asm__ __volatile__(LOCK "andl %0,%1" \
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/bugs.h linux.pre11.3/include/asm-i386/bugs.h
--- linux.vanilla/include/asm-i386/bugs.h	Tue Jun 15 16:49:56 1999
+++ linux.pre11.3/include/asm-i386/bugs.h	Tue Jul 20 01:31:06 1999
@@ -28,10 +28,12 @@
 	boot_cpu_data.hlt_works_ok = 0;
 }
 
+#ifdef CONFIG_MCA
 __initfunc(static void mca_pentium(char *s, int *ints))
 {
 	mca_pentium_flag = 1;
 }
+#endif
 
 __initfunc(static void no_387(char *s, int *ints))
 {
@@ -356,22 +358,6 @@
 
 __initfunc(static void check_cyrix_coma(void))
 {
-	if (boot_cpu_data.coma_bug) {
-		unsigned char ccr3, tmp;
-		cli();
-		ccr3 = getCx86(CX86_CCR3);
-		setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
-		tmp = getCx86(0x31);
-		setCx86(0x31, tmp | 0xf8);
-		tmp = getCx86(0x32);
-		setCx86(0x32, tmp | 0x7f);
-		setCx86(0x33, 0);
-		tmp = getCx86(0x3c);
-		setCx86(0x3c, tmp | 0x87);
-		setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
-		sti();
-		printk("Cyrix processor with \"coma bug\" found, workaround enabled\n");
-	}
 }
  
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/keyboard.h linux.pre11.3/include/asm-i386/keyboard.h
--- linux.vanilla/include/asm-i386/keyboard.h	Wed Apr 28 19:14:33 1999
+++ linux.pre11.3/include/asm-i386/keyboard.h	Tue Jul 20 01:39:53 1999
@@ -13,6 +13,10 @@
 
 #ifdef __KERNEL__
 
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
@@ -35,6 +39,30 @@
 
 #define SYSRQ_KEY 0x54
 
-#endif /* __KERNEL__ */
+/* resource allocation */
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
 
-#endif /* __ASMi386_KEYBOARD_H */
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
+
+#endif /* __KERNEL__ */
+#endif /* _I386_KEYBOARD_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/page.h linux.pre11.3/include/asm-i386/page.h
--- linux.vanilla/include/asm-i386/page.h	Thu Jan 28 22:00:14 1999
+++ linux.pre11.3/include/asm-i386/page.h	Tue Jul 20 01:31:01 1999
@@ -79,7 +79,10 @@
  *
  * which has the same constant encoded..
  */
-#define __PAGE_OFFSET		(0xC0000000)
+
+#include <asm/page_offset.h>
+
+#define __PAGE_OFFSET		(PAGE_OFFSET_RAW)
 
 #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/page_offset.h linux.pre11.3/include/asm-i386/page_offset.h
--- linux.vanilla/include/asm-i386/page_offset.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-i386/page_offset.h	Tue Jul 20 01:31:01 1999
@@ -0,0 +1,8 @@
+#include <linux/config.h>
+#ifdef CONFIG_1GB
+#define PAGE_OFFSET_RAW 0xC0000000
+#elif defined(CONFIG_2GB)
+#define PAGE_OFFSET_RAW 0x80000000
+#elif defined(CONFIG_3GB)
+#define PAGE_OFFSET_RAW 0x40000000
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/pgtable.h linux.pre11.3/include/asm-i386/pgtable.h
--- linux.vanilla/include/asm-i386/pgtable.h	Fri Apr 16 22:11:00 1999
+++ linux.pre11.3/include/asm-i386/pgtable.h	Tue Jul 20 01:31:06 1999
@@ -286,7 +286,7 @@
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long) empty_zero_page)
+#define ZERO_PAGE(vaddr) ((unsigned long) empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/semaphore-helper.h linux.pre11.3/include/asm-i386/semaphore-helper.h
--- linux.vanilla/include/asm-i386/semaphore-helper.h	Tue Feb 23 14:21:34 1999
+++ linux.pre11.3/include/asm-i386/semaphore-helper.h	Tue Jul 20 00:11:48 1999
@@ -13,14 +13,19 @@
  *
  * This is trivially done with load_locked/store_cond,
  * but on the x86 we need an external synchronizer.
+ *
+ * NOTE: we can't look at the semaphore count here since it can be
+ * unreliable. Even if the count is minor than 1, the semaphore
+ * could be just owned by another process (this because not only up() increases
+ * the semaphore count, also the interruptible/trylock call can increment
+ * the semaphore count when they fails).
  */
 static inline void wake_one_more(struct semaphore * sem)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&semaphore_wake_lock, flags);
-	if (atomic_read(&sem->count) <= 0)
-		sem->waking++;
+	sem->waking++;
 	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
 }
 
@@ -44,9 +49,11 @@
  *	0	go to sleep
  *	-EINTR	interrupted
  *
- * We must undo the sem->count down_interruptible() increment while we are
- * protected by the spinlock in order to make atomic this atomic_inc() with the
- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ * If we give up we must undo our count-decrease we previously did in down().
+ * Subtle: up() can continue to happens and increase the semaphore count
+ * even during our critical section protected by the spinlock. So
+ * we must remeber to undo the sem->waking that will be run from
+ * wake_one_more() some time soon, if the semaphore count become > 0.
  */
 static inline int waking_non_zero_interruptible(struct semaphore *sem,
 						struct task_struct *tsk)
@@ -59,7 +66,8 @@
 		sem->waking--;
 		ret = 1;
 	} else if (signal_pending(tsk)) {
-		atomic_inc(&sem->count);
+		if (atomic_inc_and_test_greater_zero(&sem->count))
+			sem->waking--;
 		ret = -EINTR;
 	}
 	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
@@ -71,9 +79,7 @@
  *	1	failed to lock
  *	0	got the lock
  *
- * We must undo the sem->count down_trylock() increment while we are
- * protected by the spinlock in order to make atomic this atomic_inc() with the
- * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ * Implementation details are the same of the interruptible case.
  */
 static inline int waking_non_zero_trylock(struct semaphore *sem)
 {
@@ -82,8 +88,10 @@
 
 	spin_lock_irqsave(&semaphore_wake_lock, flags);
 	if (sem->waking <= 0)
-		atomic_inc(&sem->count);
-	else {
+	{
+		if (atomic_inc_and_test_greater_zero(&sem->count))
+			sem->waking--;
+	} else {
 		sem->waking--;
 		ret = 0;
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/setup.h linux.pre11.3/include/asm-i386/setup.h
--- linux.vanilla/include/asm-i386/setup.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-i386/setup.h	Mon Jul 19 23:26:45 1999
@@ -0,0 +1,4 @@
+/*
+ *	Just a place holder. We don't want to have to test x86 before
+ *	we include stuff
+ */
\ No newline at end of file
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-i386/socket.h linux.pre11.3/include/asm-i386/socket.h
--- linux.vanilla/include/asm-i386/socket.h	Sun Nov  8 15:06:53 1998
+++ linux.pre11.3/include/asm-i386/socket.h	Tue Jul 20 00:11:48 1999
@@ -39,4 +39,19 @@
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
+/* Nasty libc5 fixup - bletch */
+#if defined(__KERNEL__) || (LIBC_VERSION < 6)
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+#endif					
+
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-m68k/pgtable.h linux.pre11.3/include/asm-m68k/pgtable.h
--- linux.vanilla/include/asm-m68k/pgtable.h	Thu May 27 22:12:02 1999
+++ linux.pre11.3/include/asm-m68k/pgtable.h	Mon Jul 19 23:26:48 1999
@@ -398,7 +398,7 @@
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE empty_zero_page
+#define ZERO_PAGE(vaddr) empty_zero_page
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR			(8*sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-m68k/socket.h linux.pre11.3/include/asm-m68k/socket.h
--- linux.vanilla/include/asm-m68k/socket.h	Sun Nov  8 15:06:58 1998
+++ linux.pre11.3/include/asm-m68k/socket.h	Mon Jul 19 23:26:48 1999
@@ -39,4 +39,16 @@
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/asmmacro.h linux.pre11.3/include/asm-mips/asmmacro.h
--- linux.vanilla/include/asm-mips/asmmacro.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/asmmacro.h	Mon Jul 19 23:26:46 1999
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1998 Ralf Baechle
  *
- * $Id: asmmacro.h,v 1.2 1998/05/01 01:35:44 ralf Exp $
+ * $Id: asmmacro.h,v 1.3 1998/03/27 04:47:58 ralf Exp $
  */
 #ifndef __MIPS_ASMMACRO_H
 #define __MIPS_ASMMACRO_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/atomic.h linux.pre11.3/include/asm-mips/atomic.h
--- linux.vanilla/include/asm-mips/atomic.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/atomic.h	Mon Jul 19 23:26:46 1999
@@ -11,7 +11,7 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: atomic.h,v 1.4 1998/05/01 01:35:45 ralf Exp $
+ * $Id: atomic.h,v 1.5 1998/03/04 09:51:21 ralf Exp $
  */
 #ifndef __ASM_MIPS_ATOMIC_H
 #define __ASM_MIPS_ATOMIC_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/baget/baget.h linux.pre11.3/include/asm-mips/baget/baget.h
--- linux.vanilla/include/asm-mips/baget/baget.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/baget/baget.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,69 @@
+/* $Id$
+ * baget.h: Definitions specific to Baget/MIPS machines.
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+#ifndef _MIPS_BAGET_H
+#define _MIPS_BAGET_H
+
+#include "vic.h"
+#include "vac.h"
+
+#define VIC_BASE         0xBFFC0000 
+#define VAC_BASE         0xBFFD0000
+
+
+/* Baget interrupt registers and their sizes */
+
+struct  baget_int_reg { 
+	unsigned long address;
+	int size;  /* in bytes */
+};
+#define BAGET_INT_NONE   {0,0}
+
+#define BAGET_INT0_ACK   {0xbffa0003,1}
+#define BAGET_INT1_ACK   {0xbffa0008,4}
+#define BAGET_INT5_ACK   {0xbff00000,1}
+
+#define BAGET_WRERR_ACK  ((volatile char*)0xbff00000)
+
+
+/* Baget address spaces */
+
+#define BAGET_A24M_BASE       0xFC000000      /* VME-master A24 base address  */
+#define BAGET_A24S_BASE       0x00000000      /* VME-slave A24 base address   */
+#define BAGET_A24S_MASK       0x00c00000      /* VME-slave A24 address mask   */
+#define BAGET_GSW_BASE        0xf000          /* global switches address base */
+#define BAGET_MSW_BASE(P) (0xe000+(P)*0x100)  /* module switches address base */
+
+#define BAGET_LED_BASE  ((volatile short *)(0xbffd0000 + 0x00001800))
+
+#define BAGET_PIL_NR            8
+#define BAGET_IRQ_NR            NR_IRQS /* 64 */
+#define BAGET_IRQ_MASK(x)       ((NR_IRQS-1) & (x))
+
+#define BAGET_FPU_IRQ           0x26
+#define BAGET_VIC_TIMER_IRQ     0x32 
+#define BAGET_VAC_TIMER_IRQ     0x36 
+#define BAGET_BSM_IRQ           0x3C
+
+#define BAGET_LANCE_MEM_BASE    0xfcf10000
+#define BAGET_LANCE_MEM_SIZE    0x10000
+#define BAGET_LANCE_IO_BASE     0xbffeff00
+
+#define BALO_OFFSET     0x400000 /* sync with ld.script.balo  */
+#define BALO_SIZE       0x200000 /* sync with image segs size */
+
+/* move it to the right place, somehere in include/asm */
+#define CAUSE_DBE       0x1C
+#define CAUSE_MASK      0x7C
+
+/* Simple debug fascilities */
+extern void outc(char);
+extern void outs(char *);
+extern void baget_write(char *s, int l);
+extern int  baget_printk(const char *, ...);
+extern void balo_printf( char *f, ... );
+extern void balo_hungup(void);
+
+#endif /* !(_MIPS_BAGET_H) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/baget/vac.h linux.pre11.3/include/asm-mips/baget/vac.h
--- linux.vanilla/include/asm-mips/baget/vac.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/baget/vac.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,209 @@
+/* $Id$
+ *
+ * vac.h: Various VIC controller defines.  The VIC is a VME controller
+ *        used in Baget/MIPS series.
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+#ifndef _MIPS_VAC_H
+#define _MIPS_VAC_H
+
+#define VAC_SLSEL1_MASK      0x000
+#define VAC_SLSEL1_BASE      0x100
+#define VAC_SLSEL0_MASK      0x200
+#define VAC_SLSEL0_BASE      0x300
+#define VAC_ICFSEL_BASE      0x400
+#define VAC_ICFSEL_GLOBAL_VAL(x) (((x)>>8)&0xff)
+#define VAC_ICFSEL_MODULE_VAL(x) ((x)&0xff)
+#define VAC_DRAM_MASK        0x500
+#define VAC_BNDR2            0x600
+#define VAC_BNDR3            0x700
+#define VAC_A24_BASE         0x800
+#define    VAC_A24_MASK          (0x3f<<9)
+#define    VAC_A24_D32_ENABLE    (1<<8)
+#define    VAC_A24_A24_CACHINH   (1<<7)
+#define    VAC_A24_A16D32_ENABLE (1<<6)  
+#define    VAC_A24_A16D32        (1<<5)  
+#define    VAC_A24_DATAPATH      (1<<4)
+#define    VAC_A24_IO_CACHINH    (1<<3)
+#define VAC_REG1             0x900
+#define VAC_REG2             0xA00
+#define VAC_REG3             0xB00
+#define    VAC_REG_WORD      (1<<15)
+#define    VAC_REG_ASIZ1     (1<<14)
+#define    VAC_REG_ASIZ0     (1<<13)
+#define    VAC_REG_ASIZ_VAL(x) (((x)>>13)&3)
+#define    VAC_REG_CACHINH   (1<<12)
+#define    VAC_REG_INACTIVE  (0<<10)
+#define    VAC_REG_SHARED    (1<<10)
+#define    VAC_REG_VSB       (2<<10)
+#define    VAC_REG_MWB       (3<<10)
+#define    VAC_REG_MASK      (3<<10)
+#define    VAC_REG_MODE(x)   (((x)>>10)&3)
+#define VAC_IOSEL4_CTRL      0xC00
+#define VAC_IOSEL5_CTRL      0xD00
+#define VAC_SHRCS_CTRL       0xE00
+#define VAC_EPROMCS_CTRL     0xF00
+#define VAC_IOSEL0_CTRL      0x1000
+#define VAC_IOSEL1_CTRL      0x1100
+#define VAC_IOSEL2_CTRL      0x1200
+#define VAC_IOSEL3_CTRL      0x1300
+#define    VAC_CTRL_IOWR               (1<<0)
+#define    VAC_CTRL_IORD               (1<<1)
+#define    VAC_CTRL_DELAY_IOSELI(x)    (((x)&3)<<2)
+#define    VAC_CTRL_DELAY_IOSELI_VAL(x) (((x)>>2)&3)
+#define    VAC_CTRL_DELAY_IOWR(x)      (((x)&3)<<4)
+#define    VAC_CTRL_DELAY_IOWR_VAL(x)  (((x)>>4)&3)
+#define    VAC_CTRL_DELAY_IORD(x)      (((x)&3)<<6)
+#define    VAC_CTRL_DELAY_IORD_VAL(x)  (((x)>>6)&3)
+#define    VAC_CTRL_RECOVERY_IOSELI(x) ((((x)-1)&7)<<8)
+#define    VAC_CTRL_RECOVERY_IOSELI_VAL(x) ((((x)>>8)&7)+1)
+#define    VAC_CTRL_DSACK0             (1<<11)
+#define    VAC_CTRL_DSACK1             (1<<12)
+#define    VAC_CTRL_DELAY_DSACKI(x)    ((((x)-1)&7)<<13)
+#define    VAC_CTRL_DELAY_DSACKI_VAL(x) ((((x)>>13)&7)+1)
+#define VAC_DECODE_CTRL      0x1400
+#define    VAC_DECODE_FPUCS   (1<<0)
+#define    VAC_DECODE_CPUCLK(x)  (((x)&3)<<1)
+#define    VAC_DECODE_CPUCLK_VAL(x) (((x)>>1)&3)
+#define    VAC_DECODE_RDR_SLSEL0 (1<<3)
+#define    VAC_DECODE_RDR_SLSEL1 (1<<4)
+#define    VAC_DECODE_DSACK   (1<<5)
+#define    VAC_DECODE_QFY_BNDR    (1<<6)
+#define    VAC_DECODE_QFY_ICFSEL  (1<<7)
+#define    VAC_DECODE_QFY_SLSEL1  (1<<8)
+#define    VAC_DECODE_QFY_SLSEL0  (1<<9)
+#define    VAC_DECODE_CMP_SLSEL1_LO  (1<<10)
+#define    VAC_DECODE_CMP_SLSEL1_HI  (1<<11)
+#define    VAC_DECODE_CMP_SLSEL1_VAL(x) (((x)>>10)&3)
+#define    VAC_DECODE_DRAMCS  (3<<12)
+#define    VAC_DECODE_SHRCS   (2<<12)
+#define    VAC_DECODE_VSBSEL  (1<<12)
+#define    VAC_DECODE_EPROMCS (0<<12)
+#define    VAC_DECODE_MODE_VAL(x) (((x)>>12)&3)
+#define    VAC_DECODE_QFY_DRAMCS  (1<<14)
+#define    VAC_DECODE_DSACKI  (1<<15)
+#define VAC_INT_STATUS       0x1500
+#define VAC_INT_CTRL         0x1600
+#define    VAC_INT_CTRL_TIMER_PIO11    (3<<0)
+#define    VAC_INT_CTRL_TIMER_PIO10    (2<<0)
+#define    VAC_INT_CTRL_TIMER_PIO7     (1<<0)
+#define    VAC_INT_CTRL_TIMER_DISABLE  (0<<0)
+#define    VAC_INT_CTRL_TIMER_MASK     (3<<0)
+#define    VAC_INT_CTRL_UART_B_PIO11   (3<<2)
+#define    VAC_INT_CTRL_UART_B_PIO10   (2<<2)
+#define    VAC_INT_CTRL_UART_B_PIO7    (1<<2)
+#define    VAC_INT_CTRL_UART_B_DISABLE (0<<2)
+#define    VAC_INT_CTRL_UART_A_PIO11   (3<<4)
+#define    VAC_INT_CTRL_UART_A_PIO10   (2<<4)
+#define    VAC_INT_CTRL_UART_A_PIO7    (1<<4)
+#define    VAC_INT_CTRL_UART_A_DISABLE (0<<4)
+#define    VAC_INT_CTRL_MBOX_PIO11     (3<<6)
+#define    VAC_INT_CTRL_MBOX_PIO10     (2<<6)
+#define    VAC_INT_CTRL_MBOX_PIO7      (1<<6)
+#define    VAC_INT_CTRL_MBOX_DISABLE   (0<<6)
+#define    VAC_INT_CTRL_PIO4_PIO11     (3<<8)
+#define    VAC_INT_CTRL_PIO4_PIO10     (2<<8)
+#define    VAC_INT_CTRL_PIO4_PIO7      (1<<8)
+#define    VAC_INT_CTRL_PIO4_DISABLE   (0<<8)
+#define    VAC_INT_CTRL_PIO7_PIO11     (3<<10)
+#define    VAC_INT_CTRL_PIO7_PIO10     (2<<10)
+#define    VAC_INT_CTRL_PIO7_PIO7      (1<<10)
+#define    VAC_INT_CTRL_PIO7_DISABLE   (0<<10)
+#define    VAC_INT_CTRL_PIO8_PIO11     (3<<12)
+#define    VAC_INT_CTRL_PIO8_PIO10     (2<<12)
+#define    VAC_INT_CTRL_PIO8_PIO7      (1<<12)
+#define    VAC_INT_CTRL_PIO8_DISABLE   (0<<12)
+#define    VAC_INT_CTRL_PIO9_PIO11     (3<<14)
+#define    VAC_INT_CTRL_PIO9_PIO10     (2<<14)
+#define    VAC_INT_CTRL_PIO9_PIO7      (1<<14)
+#define    VAC_INT_CTRL_PIO9_DISABLE   (0<<14)
+#define VAC_DEV_LOC          0x1700
+#define    VAC_DEV_LOC_IOSEL(x)   (1<<(x))
+#define VAC_PIO_DATA_OUT     0x1800
+#define VAC_PIO_PIN          0x1900
+#define VAC_PIO_DIRECTION    0x1A00
+#define    VAC_PIO_DIR_OUT(x)     (1<<(x))
+#define    VAC_PIO_DIR_IN(x)      (0<<(x))
+#define    VAC_PIO_DIR_FCIACK     (1<<14)
+#define VAC_PIO_FUNC         0x1B00
+#define    VAC_PIO_FUNC_UART_A_TX (1<<0)
+#define    VAC_PIO_FUNC_UART_A_RX (1<<1)
+#define    VAC_PIO_FUNC_UART_B_TX (1<<2)
+#define    VAC_PIO_FUNC_UART_B_RX (1<<3)
+#define    VAC_PIO_FUNC_IORD      (1<<4)
+#define    VAC_PIO_FUNC_IOWR      (1<<5)
+#define    VAC_PIO_FUNC_IOSEL3    (1<<6)
+#define    VAC_PIO_FUNC_IRQ7      (1<<7)
+#define    VAC_PIO_FUNC_IOSEL4    (1<<8)
+#define    VAC_PIO_FUNC_IOSEL5    (1<<9)
+#define    VAC_PIO_FUNC_IRQ10     (1<<10)
+#define    VAC_PIO_FUNC_IRQ11     (1<<11)
+#define    VAC_PIO_FUNC_OUT       (1<<12)
+#define    VAC_PIO_FUNC_IOSEL2    (1<<13)
+#define    VAC_PIO_FUNC_DELAY     (1<<14)
+#define    VAC_PIO_FUNC_FCIACK    (1<<15)
+#define VAC_CPU_CLK_DIV      0x1C00
+#define VAC_UART_A_MODE      0x1D00
+#define    VAC_UART_MODE_PARITY_ENABLE  (1<<15) /* Inversed in manual ? */
+#define    VAC_UART_MODE_PARITY_ODD     (1<<14) /* Inversed in manual ? */
+#define    VAC_UART_MODE_8BIT_CHAR      (1<<13)
+#define    VAC_UART_MODE_BAUD(x)        (((x)&7)<<10)
+#define    VAC_UART_MODE_CHAR_RX_ENABLE (1<<9)
+#define    VAC_UART_MODE_CHAR_TX_ENABLE (1<<8)
+#define    VAC_UART_MODE_TX_ENABLE      (1<<7)
+#define    VAC_UART_MODE_RX_ENABLE      (1<<6)
+#define    VAC_UART_MODE_SEND_BREAK     (1<<5)
+#define    VAC_UART_MODE_LOOPBACK       (1<<4)
+#define    VAC_UART_MODE_INITIAL        (VAC_UART_MODE_8BIT_CHAR | \
+                                         VAC_UART_MODE_TX_ENABLE | \
+                                         VAC_UART_MODE_RX_ENABLE | \
+                                         VAC_UART_MODE_CHAR_TX_ENABLE | \
+                                         VAC_UART_MODE_CHAR_RX_ENABLE | \
+                                         VAC_UART_MODE_BAUD(5)) /* 9600/4 */
+#define VAC_UART_A_TX        0x1E00
+#define VAC_UART_B_MODE      0x1F00
+#define VAC_UART_A_RX        0x2000
+#define    VAC_UART_RX_ERR_BREAK        (1<<10)
+#define    VAC_UART_RX_ERR_FRAME        (1<<9)
+#define    VAC_UART_RX_ERR_PARITY       (1<<8)
+#define    VAC_UART_RX_DATA_MASK        (0xff)
+#define VAC_UART_B_RX        0x2100
+#define VAC_UART_B_TX        0x2200
+#define VAC_UART_A_INT_MASK  0x2300
+#define    VAC_UART_INT_RX_READY        (1<<15)
+#define    VAC_UART_INT_RX_FULL         (1<<14)
+#define    VAC_UART_INT_RX_BREAK_CHANGE (1<<13)
+#define    VAC_UART_INT_RX_ERRS         (1<<12)
+#define    VAC_UART_INT_TX_READY        (1<<11)
+#define    VAC_UART_INT_TX_EMPTY        (1<<10)
+#define VAC_UART_B_INT_MASK  0x2400
+#define VAC_UART_A_INT_STATUS  0x2500
+#define    VAC_UART_STATUS_RX_READY        (1<<15)
+#define    VAC_UART_STATUS_RX_FULL         (1<<14)
+#define    VAC_UART_STATUS_RX_BREAK_CHANGE (1<<13)
+#define    VAC_UART_STATUS_RX_ERR_PARITY   (1<<12)
+#define    VAC_UART_STATUS_RX_ERR_FRAME    (1<<11)
+#define    VAC_UART_STATUS_RX_ERR_OVERRUN  (1<<10)
+#define    VAC_UART_STATUS_TX_READY        (1<<9)
+#define    VAC_UART_STATUS_TX_EMPTY        (1<<8)
+#define    VAC_UART_STATUS_INTS            (0xff<<8)
+#define VAC_UART_B_INT_STATUS  0x2600
+#define VAC_TIMER_DATA       0x2700
+#define VAC_TIMER_CTRL       0x2800
+#define    VAC_TIMER_ONCE      (1<<15)
+#define    VAC_TIMER_ENABLE    (1<<14)
+#define    VAC_TIMER_PRESCALE(x) (((x)&0x3F)<<8)
+#define VAC_ID               0x2900
+
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#define vac_inb(p)    (*(volatile unsigned char *)(VAC_BASE + (p)))
+#define vac_outb(v,p) (*((volatile unsigned char *)(VAC_BASE + (p))) = v)
+#define vac_inw(p)    (*(volatile unsigned short*)(VAC_BASE + (p)))
+#define vac_outw(v,p) (*((volatile unsigned short*)(VAC_BASE + (p))) = v)
+
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#endif /* !(_MIPS_VAC_H) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/baget/vic.h linux.pre11.3/include/asm-mips/baget/vic.h
--- linux.vanilla/include/asm-mips/baget/vic.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/baget/vic.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,193 @@
+/* $Id$
+ *
+ * vic.h: Various VIC controller defines.  The VIC is an interrupt controller
+ *        used in Baget/MIPS series.
+ *
+ * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
+ */
+#ifndef _MIPS_VIC_H
+#define _MIPS_VIC_H
+
+#define VIC_VME_II       0x3
+#define VIC_VME_INT1     0x7
+#define VIC_VME_INT2     0xB
+#define VIC_VME_INT3     0xF
+#define VIC_VME_INT4     0x13
+#define VIC_VME_INT5     0x17
+#define VIC_VME_INT6     0x1B
+#define VIC_VME_INT7     0x1F
+#define VIC_DMA_INT      0x23
+#define VIC_LINT1        0x27
+#define VIC_LINT2        0x2B
+#define VIC_LINT3        0x2F
+#define VIC_LINT4        0x33
+#define VIC_LINT5        0x37
+#define VIC_LINT6        0x3B
+#define VIC_LINT7        0x3F
+#define VIC_ICGS_INT     0x43
+#define VIC_ICMS_INT     0x47
+#define    VIC_INT_IPL(lev)  ((~(lev))&0x7)
+#define    VIC_INT_ACTIVE    (1<<3)
+#define    VIC_INT_AUTO      (0<<4)
+#define    VIC_INT_NOAUTO    (1<<4)
+#define    VIC_INT_LEVEL     (0<<5)
+#define    VIC_INT_EDGE      (1<<5)
+#define    VIC_INT_LOW       (0<<6)
+#define    VIC_INT_HIGH      (1<<6)
+#define    VIC_INT_ENABLE    (0<<7)
+#define    VIC_INT_DISABLE   (1<<7)
+#define    VIC_INT_SWITCH(x) (1<<(((x)&0x3)+4))
+#define VIC_ERR_INT      0x4B
+#define    VIC_ERR_INT_SYSFAIL_ACTIVE  (1<<3)
+#define    VIC_ERR_INT_SYSFAIL  (1<<4)
+#define    VIC_ERR_INT_TIMO     (1<<5)
+#define    VIC_ERR_INT_WRPOST   (1<<6)
+#define    VIC_ERR_INT_ACFAIL   (1<<7)
+#define VIC_ICGS_BASE    0x4F
+#define VIC_ICMS_BASE    0x53
+#define    VIC_ICxS_BASE_GSWITCH_MASK 0x3
+#define    VIC_ICxS_BASE_ID(x)  (((x)&0x3f)<<2)
+#define VIC_LOCAL_BASE   0x57
+#define    VIC_LOCAL_BASE_LINT_MASK 0x7
+#define    VIC_LOCAL_BASE_ID(x)  (((x)&0x1f)<<3)
+#define VIC_ERR_BASE     0x5B
+#define    VIC_ERR_BASE_ACFAIL   0
+#define    VIC_ERR_BASE_WRPOST   1
+#define    VIC_ERR_BASE_TIMO     2
+#define    VIC_ERR_BASE_SYSFAIL  3
+#define    VIC_ERR_BASE_VMEACK   4
+#define    VIC_ERR_BASE_DMA      5
+#define    VIC_ERR_BASE_ID(x)  (((x)&0x1f)<<3)
+#define VIC_ICS          0x5F
+#define VIC_IC0          0x63
+#define VIC_IC1          0x67
+#define VIC_IC2          0x6B
+#define VIC_IC3          0x6F
+#define VIC_IC4          0x73
+#define VIC_ID           0x77
+#define VIC_IC6          0x7B
+#define    VIC_IC6_IRESET_STATUS (1<<7)
+#define    VIC_IC6_HALT_STATUS   (1<<6)
+#define    VIC_IC6_SYSRESET   (3<<0)
+#define    VIC_IC6_RESET      (2<<0)
+#define    VIC_IC6_HALT       (1<<0)
+#define    VIC_IC6_RUN        (0<<0)
+#define VIC_IC7          0x7F
+#define    VIC_IC7_SYSFAIL     (1<<7)
+#define    VIC_IC7_RESET       (1<<6)
+#define    VIC_IC7_VME_MASTER  (1<<5)
+#define    VIC_IC7_SEMSET(x)   ((1<<(x))&0x1f)
+#define VIC_VME_REQ      0x83
+#define VIC_VME_BASE1    0x87
+#define VIC_VME_BASE2    0x8B
+#define VIC_VME_BASE3    0x8F
+#define VIC_VME_BASE4    0x93
+#define VIC_VME_BASE5    0x97
+#define VIC_VME_BASE6    0x9B
+#define VIC_VME_BASE7    0x9F
+#define VIC_XFER_TIMO    0xA3
+#define    VIC_XFER_TIMO_VME_PERIOD_INF (7<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_512 (6<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_256 (5<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_128 (4<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_64 (3<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_32 (2<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_16 (1<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_4  (0<<5)
+#define    VIC_XFER_TIMO_VME_PERIOD_VAL(x) (((x)>>5)&7)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_INF (7<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_512 (6<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_256 (5<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_128 (4<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_64 (3<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_32 (2<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_16 (1<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_4  (0<<2)
+#define    VIC_XFER_TIMO_LOCAL_PERIOD_VAL(x) (((x)>>2)&7)
+#define    VIC_XFER_TIMO_ARB  (1<<1)
+#define    VIC_XFER_TIMO_VME  (1<<0)
+#define VIC_LOCAL_TIM    0xA7
+#define    VIC_LOCAL_TIM_PAS_ASSERT(x)   (((x)-2)&0xf)
+#define    VIC_LOCAL_TIM_PAS_ASSERT_VAL(x) (((x)&0xf)+2)
+#define    VIC_LOCAT_TIM_DS_DEASSERT(x)  ((((x)-1)&1)<<4)
+#define    VIC_LOCAT_TIM_DS_DEASSERT_VAL(x)  ((((x)>>4)&1)+1)
+#define    VIC_LOCAL_TIM_PAS_DEASSERT(x) ((((x)-1)&0x7)<<5)
+#define    VIC_LOCAL_TIM_PAS_DEASSERT_VAL(x) ((((x)>>5)&0x7)+1)
+#define VIC_BXFER_DEF    0xAB
+#define    VIC_BXFER_DEF_VME_CROSS    (1<<3)
+#define    VIC_BXFER_DEF_LOCAL_CROSS  (1<<2)
+#define    VIC_BXFER_DEF_AMSR   (1<<1)
+#define    VIC_BXFER_DEF_DUAL   (1<<0)
+#define VIC_IFACE_CFG    0xAF
+#define    VIC_IFACE_CFG_RMC3    (1<<7)
+#define    VIC_IFACE_CFG_RMC2    (1<<6)
+#define    VIC_IFACE_CFG_RMC1    (1<<5)
+#define    VIC_IFACE_CFG_HALT    (1<<4)
+#define    VIC_IFACE_CFG_NOHALT  (0<<4)
+#define    VIC_IFACE_CFG_NORMC   (1<<3)
+#define    VIC_IFACE_CFG_DEADLOCK_VAL(x) (((x)>>3)&3)
+#define    VIC_IFACE_CFG_MSTAB   (1<<2)
+#define    VIC_IFACE_CFG_TURBO   (1<<1)
+#define    VIC_IFACE_CFG_NOTURBO (0<<1)
+#define    VIC_IFACE_CFG_VME     (1<<0)
+#define VIC_REQ_CFG      0xB3
+#define    VIC_REQ_CFG_FAIRNESS_DISABLED  0
+#define    VIC_REQ_CFG_FAIRNESS_ENABLED   1
+#define    VIC_REQ_CFG_TIMO_DISABLED      0xf
+#define    VIC_REQ_CFG_DRAM_REFRESH       (1<<4)
+#define    VIC_REQ_CFG_LEVEL(x)           (((x)&3)<<5)
+#define    VIC_REQ_CFG_PRIO_ARBITRATION   (1<<7)
+#define    VIC_REQ_CFG_RR_ARBITRATION     (0<<7)
+#define VIC_AMS          0xB7
+#define    VIC_AMS_AM_2_0   (1<<7)
+#define    VIC_AMS_AM_5_3   (1<<6)
+#define    VIC_AMS_CODE(x)  ((x)&0x1f)
+#define VIC_BERR_STATUS  0xBB
+#define VIC_DMA_STATUS   0xBF
+#define VIC_SS0CR0       0xC3
+#define VIC_SS1CR0       0xCB
+#define    VIC_SSxCR0_LOCAL_XFER_ACCEL  (2)
+#define    VIC_SSxCR0_LOCAL_XFER_SINGLE (1)
+#define    VIC_SSxCR0_LOCAL_XFER_NONE   (0)
+#define    VIC_SSxCR0_A32       (0<<2)
+#define    VIC_SSxCR0_A24       (1<<2)
+#define    VIC_SSxCR0_A16       (2<<2)
+#define    VIC_SSxCR0_USER      (3<<2)
+#define    VIC_SSxCR0_D32       (1<<4)
+#define    VIC_SSxCR0_SUPER     (1<<5)
+#define    VIC_SS0CR0_TIMER_FREQ_MASK   (3<<6)
+#define    VIC_SS0CR0_TIMER_FREQ_NONE   (0<<6)
+#define    VIC_SS0CR0_TIMER_FREQ_50HZ   (1<<6)
+#define    VIC_SS0CR0_TIMER_FREQ_1000HZ (2<<6)
+#define    VIC_SS0CR0_TIMER_FREQ_100HZ  (3<<6)
+#define    VIC_SS1CR0_MASTER_WRPOST (1<<6)
+#define    VIC_SS1CR0_SLAVE_WRPOST  (1<<7)
+#define VIC_SS0CR1       0xC7
+#define VIC_SS1CR1       0xCF
+#define    VIC_SSxCR1_TF2(x)  (((x)&0xf)<<4)
+#define    VIC_SSxCR1_TF1(x)  ((x)&0xf)
+#define VIC_RELEASE      0xD3
+#define    VIC_RELEASE_BLKXFER_BLEN(x) ((x)&0x1f)
+#define    VIC_RELEASE_ROR             (0<<6) 
+#define    VIC_RELEASE_RWD             (1<<6) 
+#define    VIC_RELEASE_ROC             (2<<6) 
+#define    VIC_RELEASE_BCAP            (3<<6) 
+#define VIC_BXFER_CTRL   0xD7
+#define    VIC_BXFER_CTRL_MODULE     (1<<7)
+#define    VIC_BXFER_CTRL_LOCAL      (1<<6)
+#define    VIC_BXFER_CTRL_MOVEM      (1<<5)
+#define    VIC_BXFER_CTRL_READ       (1<<4)
+#define    VIC_BXFER_CTRL_WRITE      (0<<4)
+#define    VIC_BXFER_CTRL_INTERLEAVE(x)  ((x)&0xf)
+#define VIC_BXFER_LEN_LO    0xDB
+#define VIC_BXFER_LEN_HI    0xDF
+#define VIC_SYS_RESET    0xE3
+
+#ifndef __LANGUAGE_ASSEMBLY__
+
+#define vic_inb(p)    (*(volatile unsigned char *)(VIC_BASE + (p)))
+#define vic_outb(v,p) (*((volatile unsigned char *)(VIC_BASE + (p))) = v)
+
+#endif /* __LANGUAGE_ASSEMBLY__ */
+
+#endif /* !(_MIPS_VIC_H) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/bcache.h linux.pre11.3/include/asm-mips/bcache.h
--- linux.vanilla/include/asm-mips/bcache.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/bcache.h	Mon Jul 19 23:26:46 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1997 by Ralf Baechle
  *
- * $Id: bcache.h,v 1.1 1998/05/01 01:35:46 ralf Exp $
+ * $Id: bcache.h,v 1.3 1998/01/04 00:59:35 ralf Exp $
  */
 struct bcache_ops {
 	void (*bc_enable)(void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/bootinfo.h linux.pre11.3/include/asm-mips/bootinfo.h
--- linux.vanilla/include/asm-mips/bootinfo.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/bootinfo.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: bootinfo.h,v 1.5 1998/08/19 21:58:10 ralf Exp $
+/* $Id: bootinfo.h,v 1.7 1999/04/12 18:59:14 harald Exp $
  *
  * bootinfo.h -- Definition of the Linux/MIPS boot information structure
  *
@@ -25,10 +25,10 @@
 #define MACH_GROUP_SNI_RM	4 /* Siemens Nixdorf RM series                */
 #define MACH_GROUP_ACN		5
 #define MACH_GROUP_SGI          6 /* Silicon Graphics workstations and servers */
-#define MACH_GROUP_RESERVED     7 /* No Such Architecture	 	      */
+#define MACH_GROUP_COBALT       7 /* Cobalt servers		 	      */
 
 #define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", \
-                      "SNI", "ACN", "SGI", "NSA" }
+                      "SNI", "ACN", "SGI", "Cobalt" }
 
 /*
  * Valid machtype values for group unknown (low order halfword of mips_machtype)
@@ -49,11 +49,21 @@
 /*
  * Valid machtype for group DEC 
  */
-/* FIXME: this is a very fuzzy name, and we got a big "name space now" */
-/* So otiginal DEC codes can be used -Stoned */
-#define MACH_DECSTATION		0	/* DECStation 5000/2x for now */
-
-#define GROUP_DEC_NAMES { "3min" }
+#define MACH_DSUNKNOWN		0
+#define MACH_DS23100		1	/* DECstation 2100 or 3100	*/
+#define MACH_DS5100		2	/* DECstation 5100		*/
+#define MACH_DS5000_200		3	/* DECstation 5000/200		*/
+#define MACH_DS5000_1XX		4	/* DECstation 5000/120, 125, 133, 150 */
+#define MACH_DS5000_XX		5	/* DECstation 5000/20, 25, 33, 50 */
+#define MACH_DS5000_2X0		6	/* DECstation 5000/240, 260	*/
+#define MACH_DS5400		7	/* DECstation 5400		*/
+#define MACH_DS5500		8	/* DECstation 5500		*/
+#define MACH_DS5800		9	/* DECstation 5800		*/
+
+#define GROUP_DEC_NAMES { "unknown", "DECstation 2100/3100", "DECstation 5100", \
+	"DECstation 5000/200", "DECstation 5000/1xx", "Personal DECstation 5000/xx", \
+	"DECstation 5000/2x0", "DECstation 5400", "DECstation 5500", \
+	"DECstation 5800" }
 
 /*
  * Valid machtype for group ARC
@@ -85,6 +95,13 @@
 #define GROUP_SGI_NAMES { "Indy" }
 
 /*
+ * Valid machtype for group COBALT
+ */
+#define MACH_COBALT_27 		 0	/* Proto "27" hardware */
+
+#define GROUP_COBALT_NAMES { "Microserver 27" }
+
+/*
  * Valid cputype values
  */
 #define CPU_UNKNOWN		0
@@ -144,134 +161,14 @@
 	unsigned short lines;
 } mips_arc_DisplayInfo;
 
-/*
- * New style bootinfo
- *
- * Add new tags only at the end of the enum; *never* remove any tags
- * or you'll break compatibility!
- */
-enum bi_tag {
- 	/*
- 	 * not a real tag
- 	 */
-	tag_dummy,
- 
- 	/*
- 	 * machine type
- 	 */
-	tag_machtype,
- 
- 	/*
- 	 * system CPU & FPU
- 	 */
-	tag_cputype,
- 
- 	/*
- 	 * Installed RAM
- 	 */
-	tag_memlower,
-	tag_memupper,
- 
- 	/*
- 	 * Cache Sizes (0xffffffff = unknown)
- 	 */
-	tag_icache_size,
-	tag_icache_linesize,
-	tag_dcache_size,
-	tag_dcache_linesize,
-	tag_scache_size,
-	tag_scache_linesize,
- 
- 	/*
- 	 * TLB Info
- 	 */
-	tag_tlb_entries,
- 
- 	/*
- 	 * DMA buffer size (Deskstation only)
- 	 */
-	tag_dma_cache_size,
-	tag_dma_cache_base,
- 
- 	/*
-	 * Ramdisk Info 
- 	 */
-	tag_ramdisk_size,		/* ramdisk size in 1024 byte blocks */
-	tag_ramdisk_base,		/* address of the ram disk in mem */
- 
- 	/*
- 	 * Boot flags for the kernel
- 	 */
-	tag_mount_root_rdonly,
-	tag_drive_info,
- 
- 	/*
- 	 * Video ram info (not in tty.h)
- 	 */
-	tag_vram_base,			/* video ram base address */
-       
-	tag_command_line,		/* kernel command line parameters */
-
-        /*
-         * machine group
-         */
-	tag_machgroup,
-
-	/*
-	 * info on the display from the ARC BIOS
-	 */
-	tag_arcdisplayinfo,
-
-	/*
-	 * tag to pass a complete struct screen_info
-	 */
-	tag_screen_info
-};
-
-/* struct defining a tag */
-typedef struct {
-	enum bi_tag tag;
-	unsigned long size;
-} tag;
-
-/* struct to define a tag and it's data */
-typedef struct {
-	tag t;
-	void* d;
-} tag_def;
-
-/* macros for parsing tag list */
-#define TAGVALPTR(t) ((void*)(((void*)(t)) - ((t)->size)))
-#define NEXTTAGPTR(t) ((void*)(TAGVALPTR(t) - (sizeof(tag))))
-
-/* size macros for tag size field */
-#define UCHARSIZE (sizeof(unsigned char))
-#define ULONGSIZE (sizeof(unsigned long))
-#define UINTSIZE  (sizeof(unsigned int))
-#define DRVINFOSIZE (sizeof(struct drive_info_struct))
-#define CMDLINESIZE (sizeof(char[CL_SIZE])
-
-/*
- * For tag readers aka the kernel
- */
-tag *bi_TagFind(enum bi_tag type);
-void bi_EarlySnarf(void);
-
-/* For tag creators aka bootloaders */
-/* Now implemented in Milo 0.26 */
-int bi_TagAdd(enum bi_tag type, unsigned long size, void *data);
-int bi_TagAddList(tag_def* taglist);
-void bi_TagWalk(void); 
-
-
 #ifdef CONFIG_SGI
 /* screen info will dissapear... soon */
 //#define DEFAULT_SCREEN_INFO {0, 0, 0, 0, 0, 158, 0, 0, 0, 62, 0, 16}
 #define DEFAULT_SCREEN_INFO {0, 0, 0, 0, 0, 160, 0, 0, 0, 64, 0, 16}
 #define DEFAULT_DRIVE_INFO { {0,}}
 #else
-/* default values for screen_info variable */
-#define DEFAULT_SCREEN_INFO {0, 0, 0, 52, 3, 80, 4626, 3, 9, 50}
+/* default values for screen_info variable (Colour VGA) */
+#define DEFAULT_SCREEN_INFO {0, 0, 0, 52, 3, 80, 4626, 3, 9, 50, 0x22, 16}
 #endif
 
 /* default values for drive info */
@@ -289,9 +186,6 @@
 extern unsigned long mips_machtype;
 extern unsigned long mips_machgroup;
 extern unsigned long mips_tlb_entries;
-extern unsigned long mips_vram_base;
-extern unsigned long mips_dma_cache_size;
-extern unsigned long mips_dma_cache_base;
 
 #endif /* _LANGUAGE_ASSEMBLY */
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/branch.h linux.pre11.3/include/asm-mips/branch.h
--- linux.vanilla/include/asm-mips/branch.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/branch.h	Mon Jul 19 23:26:46 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  *
- * $Id: branch.h,v 1.2 1998/05/04 09:18:56 ralf Exp $
+ * $Id: branch.h,v 1.2 1998/05/04 09:13:00 ralf Exp $
  */
 #include <asm/ptrace.h>
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/bugs.h linux.pre11.3/include/asm-mips/bugs.h
--- linux.vanilla/include/asm-mips/bugs.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/bugs.h	Mon Jul 19 23:26:46 1999
@@ -4,7 +4,7 @@
  *  Copyright (C) 1995  Waldorf Electronics
  *  Copyright (C) 1997  Ralf Baechle
  *
- * $Id: bugs.h,v 1.4 1998/05/01 01:35:47 ralf Exp $
+ * $Id: bugs.h,v 1.3 1997/12/01 18:00:36 ralf Exp $
  */
 #include <asm/bootinfo.h>
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/byteorder.h linux.pre11.3/include/asm-mips/byteorder.h
--- linux.vanilla/include/asm-mips/byteorder.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/byteorder.h	Mon Jul 19 23:26:46 1999
@@ -1,7 +1,24 @@
+/* $Id: byteorder.h,v 1.7 1999/01/04 16:09:20 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) by Ralf Baechle
+ */
 #ifndef _MIPS_BYTEORDER_H
 #define _MIPS_BYTEORDER_H
 
 #include <asm/types.h>
+
+#ifdef __GNUC__
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __GNUC__ */
 
 #if defined (__MIPSEB__)
 #  include <linux/byteorder/big_endian.h>
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/checksum.h linux.pre11.3/include/asm-mips/checksum.h
--- linux.vanilla/include/asm-mips/checksum.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/checksum.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.6 1998/09/16 13:30:51 ralf Exp $
+/* $Id: checksum.h,v 1.6 1998/09/19 19:19:36 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/cpu.h linux.pre11.3/include/asm-mips/cpu.h
--- linux.vanilla/include/asm-mips/cpu.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/cpu.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: cpu.h,v 1.2 1998/05/01 01:35:49 ralf Exp $
+/* $Id: cpu.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
  * cpu.h: Values of the PRId register used to match up
  *        various MIPS cpu types.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/current.h linux.pre11.3/include/asm-mips/current.h
--- linux.vanilla/include/asm-mips/current.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/current.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: current.h,v 1.4 1998/07/20 17:52:19 ralf Exp $
+/* $Id: current.h,v 1.4 1998/08/25 09:21:55 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/interrupts.h linux.pre11.3/include/asm-mips/dec/interrupts.h
--- linux.vanilla/include/asm-mips/dec/interrupts.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/interrupts.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,80 @@
+/*  
+ * Miscellaneous definitions used to initialise the interrupt vector table
+ * with the machine-specific interrupt routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 by Paul M. Antoine.
+ * reworked 1998 by Harald Koerfgen.
+ */
+
+#ifndef __ASM_DEC_INTERRUPTS_H 
+#define __ASM_DEC_INTERRUPTS_H 
+
+/*
+ * DECstation Interrupts
+ */
+
+/*
+ * This list reflects the priority of the Interrupts.
+ * Exception: on kmins we have to handle Memory Error 
+ * Interrupts before the TC Interrupts.
+ */
+#define CLOCK 	0
+#define SCSI_DMA_INT 	1
+#define SCSI_INT	2
+#define ETHER		3
+#define SERIAL		4
+#define TC0		5
+#define TC1		6
+#define TC2		7
+#define MEMORY		8
+#define FPU		9
+#define HALT		10
+
+#define NR_INTS	11
+
+#ifndef _LANGUAGE_ASSEMBLY
+/*
+ * Data structure to hide the differences between the DECstation Interrupts
+ *
+ * If asic_mask == NULL, the interrupt is directly handled by the CPU.
+ * Otherwise this Interrupt is handled the IRQ Controller.
+ */
+
+typedef struct
+{
+	unsigned int	cpu_mask;	/* checking and enabling interrupts in CP0	*/
+	unsigned int	iemask;		/* enabling interrupts in IRQ Controller	*/
+} decint_t;
+
+/*
+ * Interrupt table structure to hide differences between different
+ * systems such.
+ */
+extern void *cpu_ivec_tbl[8];
+extern long cpu_mask_tbl[8];
+extern long cpu_irq_nr[8];
+extern long asic_irq_nr[32];
+extern long asic_mask_tbl[32];
+
+/*
+ * Common interrupt routine prototypes for all DECStations
+ */
+extern void	dec_intr_unimplemented(void);
+extern void	dec_intr_fpu(void);
+extern void	dec_intr_rtc(void);
+
+extern void	kn02_io_int(void);
+extern void	kn02ba_io_int(void);
+extern void	kn03_io_int(void);
+
+extern void	intr_halt(void);
+
+extern void	asic_intr_unimplemented(void);
+
+#endif
+#endif 
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/ioasic_addrs.h linux.pre11.3/include/asm-mips/dec/ioasic_addrs.h
--- linux.vanilla/include/asm-mips/dec/ioasic_addrs.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/ioasic_addrs.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,82 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Definitions for the address map in the JUNKIO Asic
+ *
+ * Created with Information from:
+ *
+ * "DEC 3000 300/400/500/600/700/800/900 AXP Models System Programmer's Manual"
+ *
+ * and the Mach Sources
+ */
+
+#ifndef IOASIC_ADDRS_H
+#define IOASIC_ADDRS_H
+
+#define CHUNK_SIZE 0x00040000
+
+#define SYSTEM_ROM 	00*CHUNK_SIZE 		/* ??? */
+#define IOCTL 		01*CHUNK_SIZE 
+#define ESAR 		02*CHUNK_SIZE 
+#define LANCE 		03*CHUNK_SIZE 
+#define SCC0 		04*CHUNK_SIZE 
+#define VDAC_HI		05*CHUNK_SIZE		/* maxine only */
+#define SCC1 		06*CHUNK_SIZE 
+#define VDAC_LO		07*CHUNK_SIZE		/* maxine only */
+#define TOY 		08*CHUNK_SIZE 
+#define ISDN 		09*CHUNK_SIZE		/* maxine only */
+#define ERRADDR		09*CHUNK_SIZE 		/* 3maxplus only */
+#define CHKSYN 		10*CHUNK_SIZE 		/* 3maxplus only */
+#define ACCESS_BUS	10*CHUNK_SIZE 		/* maxine only */
+#define MCR 		11*CHUNK_SIZE 		/* 3maxplus only */
+#define FLOPPY 		11*CHUNK_SIZE 		/* maxine only */
+#define SCSI 		12*CHUNK_SIZE
+#define FLOPPY_DMA 	13*CHUNK_SIZE 		/* maxine only */
+#define SCSI_DMA 	14*CHUNK_SIZE 
+#define RESERVED_4 	15*CHUNK_SIZE 
+
+/*
+ * Offsets for IOCTL registers (relative to (system_base + IOCTL))
+ */
+#define SCSI_DMA_P	0x00			/* SCSI DMA Pointer */
+#define SCSI_DMA_BP	0x10			/* SCSI DMA Buffer Pointer */
+#define LANCE_DMA_P	0x20			/* LANCE DMA Pointer */
+#define SCC0_T_DMA_P	0x30			/* Communication Port 1 Transmit DMA Pointer */
+#define SCC0_R_DMA_P	0x40			/* Communication Port 1 Receive DMA Pointer */
+#define SCC1_T_DMA_P	0x50			/* Communication Port 2 Transmit DMA Pointer */
+#define SCC1_R_DMA_P	0x60			/* Communication Port 2 Receive DMA Pointer */
+#define FLOPPY_DMA_P	0x70			/* Floppy DMA Pointer */
+#define ISDN_T_DMA_P	0x80			/* ISDN Transmit DMA Pointer */
+#define ISDN_T_DMA_BP	0x90			/* ISDN Transmit DMA Buffer Pointer */
+#define ISDN_R_DMA_P	0xa0			/* ISDN Receive DMA Pointer */
+#define ISDN_R_DMA_BP	0xb0			/* ISDN Receive DMA Buffer Pointer */
+
+#define SSR		0x100			/* System Support Register */
+#define SIR		0x110			/* System Interrupt Register */
+#define SIMR		0x120			/* System Interrupt Mask Register */
+
+/*
+ * Handle partial word SCSI DMA transfers
+ */
+#define	SCSI_SCR	0x1b0
+#define	SCSI_SDR0	0x1c0
+#define	SCSI_SDR1	0x1d0
+
+/*
+ * DMA defines for the System Support Register
+ */
+#define LANCE_DMA_EN	(1UL<<16)			/* LANCE DMA enable */
+#define SCSI_DMA_EN	(1UL<<17)			/* SCSI DMA enable */
+#define SCSI_DMA_DIR	(1UL<<18)			/* SCSI DMA direction */
+#define ISDN_REC_DMA_EN (1UL<<19)			/* ISDN receive DMA enable */
+#define ISDN_TRN_DMA_EN (1UL<<20)			/* ISDN transmit DMA enable */
+#define FLOPPY_DMA_EN	(1UL<<21)			/* Floppy DMA enable */
+#define FLOPPY_DMA_DIR	(1UL<<22)			/* Floppy DMA direction */
+#define SCC1A_DMA_EN	(1UL<<28)			/* SCC1 Channel A DMA enable */
+#define SCC1B_DMA_EN	(1UL<<29)			/* SCC1 Channel B DMA enable */
+#define SCC0A_DMA_EN	(1UL<<30)			/* SCC0 Channel A DMA enable */
+#define SCC0B_DMA_EN	(1UL<<31)			/* Scc0 Channel B DMA enable */
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/ioasic_ints.h linux.pre11.3/include/asm-mips/dec/ioasic_ints.h
--- linux.vanilla/include/asm-mips/dec/ioasic_ints.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/ioasic_ints.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,109 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Definitions for the interrupt related bits in the JUNKIO Asic
+ * interrupt status register (and the interrupt mask register, of course)
+ *
+ * Created with Information from:
+ *
+ * "DEC 3000 300/400/500/600/700/800/900 AXP Models System Programmer's Manual"
+ *
+ * and the Mach Sources
+ */
+
+/* 
+ * the upper 16 bits are common to all JUNKIO machines
+ * (except the FLOPPY and ISDN bits, which are Maxine sepcific)
+ */
+#define SCC0_TRANS_PAGEEND	0x80000000	/* Serial DMA Errors	*/
+#define SCC0_TRANS_MEMRDERR	0x40000000	/* see below		*/
+#define SCC0_RECV_HALFPAGE	0x20000000
+#define	SCC0_RECV_PAGOVRRUN	0x10000000
+#define SCC1_TRANS_PAGEEND	0x08000000	/* end of page reached	*/
+#define SCC1_TRANS_MEMRDERR	0x04000000	/* SCC1 DMA memory err	*/
+#define SCC1_RECV_HALFPAGE	0x02000000	/* SCC1 half page	*/
+#define	SCC1_RECV_PAGOVRRUN	0x01000000	/* SCC1 receive overrun	*/
+#define FLOPPY_DMA_ERROR	0x00800000	/* FDI DMA error	*/
+#define	ISDN_TRANS_PTR_LOADED	0x00400000	/* xmitbuf ptr loaded	*/
+#define ISDN_RECV_PTR_LOADED	0x00200000	/* rcvbuf ptr loaded	*/
+#define ISDN_DMA_MEMRDERR	0x00100000	/* read or ovrrun error	*/
+#define SCSI_PTR_LOADED		0x00080000
+#define SCSI_PAGOVRRUN		0x00040000	/* page overrun? */
+#define SCSI_DMA_MEMRDERR	0x00020000
+#define LANCE_DMA_MEMRDERR	0x00010000
+
+/*
+ * the lower 16 bits are system specific
+ */
+
+/*
+ * The following three seem to be in common
+ */
+#define SCSI_CHIP		0x00000200
+#define LANCE_CHIP		0x00000100
+#define SCC1_CHIP		0x00000080	/* NOT on maxine	*/
+#define SCC0_CHIP		0x00000040
+
+/*
+ * The rest is different
+ */
+
+/* kmin aka 3min aka kn02ba aka DS5000_1xx */
+#define KMIN_TIMEOUT		0x00001000	/* CPU IO-Write Timeout	*/
+#define KMIN_CLOCK		0x00000020
+#define KMIN_SCSI_FIFO		0x00000004	/* SCSI Data Ready	*/
+
+/* kn02ca aka maxine */
+#define MAXINE_FLOPPY		0x00008000	/* FDI Interrupt        */
+#define MAXINE_TC0		0x00001000	/* TC Option 0      	*/
+#define MAXINE_ISDN		0x00000800	/* ISDN	Chip		*/
+#define MAXINE_FLOPPY_HDS	0x00000080	/* Floppy Status      	*/
+#define MAXINE_TC1		0x00000020	/* TC Option 1		*/
+#define MAXINE_FLOPPY_XDS	0x00000010	/* Floppy Status      	*/
+#define MAXINE_VINT		0x00000008	/* Video Frame		*/
+#define MAXINE_N_VINT		0x00000004	/* Not Video frame	*/
+#define MAXINE_DTOP_TRANS	0x00000002	/* DTI Xmit-Rdy		*/
+#define MAXINE_DTOP_RECV	0x00000001	/* DTI Recv-Available	*/
+
+/* kn03 aka 3max+ aka DS5000_2x0 */
+#define KN03_TC2		0x00004000
+#define KN03_TC1		0x00002000
+#define KN03_TC0		0x00001000
+#define KN03_SCSI_FIFO		0x00000004	/* ??? Info from Mach	*/
+
+/*
+ * Now form groups, i.e. all serial interrupts, all SCSI interrupts and so on. 
+ */
+#define SERIAL_INTS	(SCC0_TRANS_PAGEEND | SCC0_TRANS_MEMRDERR | \
+			SCC0_RECV_HALFPAGE | SCC0_RECV_PAGOVRRUN | \
+			SCC1_TRANS_PAGEEND | SCC1_TRANS_MEMRDERR | \
+			SCC1_RECV_HALFPAGE | SCC1_RECV_PAGOVRRUN | \
+			SCC1_CHIP | SCC0_CHIP)
+
+#define XINE_SERIAL_INTS	(SCC0_TRANS_PAGEEND | SCC0_TRANS_MEMRDERR | \
+			SCC0_RECV_HALFPAGE | SCC0_RECV_PAGOVRRUN | \
+			SCC0_CHIP)
+
+#define SCSI_DMA_INTS	(/* SCSI_PTR_LOADED | */ SCSI_PAGOVRRUN | \
+			SCSI_DMA_MEMRDERR)
+
+#define KMIN_SCSI_INTS	(SCSI_PTR_LOADED | SCSI_PAGOVRRUN | \
+			SCSI_DMA_MEMRDERR | SCSI_CHIP | KMIN_SCSI_FIFO)
+
+#define LANCE_INTS	(LANCE_DMA_MEMRDERR | LANCE_CHIP)
+
+/*
+ * For future use ...
+ */
+#define XINE_FLOPPY_INTS (MAXINE_FLOPPY | MAXINE_FLOPPY_HDS | \
+			FLOPPY_DMA_ERROR | MAXINE_FLOPPY_XDS)
+
+#define XINE_ISDN_INTS	(MAXINE_ISDN | ISDN_TRANS_PTR_LOADED | \
+			ISDN_RECV_PTR_LOADED | ISDN_DMA_MEMRDERR)
+
+#define XINE_DTOP_INTS	(MAXINE_DTOP_TRANS | DTOP_RECV | \
+			ISDN_TRANS_PTR_LOADED | ISDN_RECV_PTR_LOADED | \
+			ISDN_DMA_MEMRDERR)
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/kn01.h linux.pre11.3/include/asm-mips/dec/kn01.h
--- linux.vanilla/include/asm-mips/dec/kn01.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/kn01.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,28 @@
+/*
+ * Hardware info about DEC DECstation DS2100/3100 systems (otherwise known
+ * as pmax or kn01.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
+ * are by curteousy of Chris Fraser.
+ *
+ * This file is under construction - you were warned!
+ */
+#ifndef __ASM_MIPS_DEC_KN01_H 
+#define __ASM_MIPS_DEC_KN01_H 
+
+#include <asm/addrspace.h>
+
+/*
+ * Some port addresses...
+ * FIXME: these addresses are incomplete and need tidying up!
+ */
+
+#define KN01_LANCE_BASE (KSEG1ADDR(0x18000000)) /* 0xB8000000 */
+#define KN01_DZ11_BASE	(KSEG1ADDR(0x1c000000)) /* 0xBC000000 */
+#define KN01_RTC_BASE	(KSEG1ADDR(0x1d000000)) /* 0xBD000000 */
+
+#endif /* __ASM_MIPS_DEC_KN01_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/kn02.h linux.pre11.3/include/asm-mips/dec/kn02.h
--- linux.vanilla/include/asm-mips/dec/kn02.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/kn02.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,41 @@
+/*
+ * Hardware info about DEC DECstation 5000/2xx systems (otherwise known
+ * as 3max or kn02.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
+ * are by curteousy of Chris Fraser.
+ *
+ * This file is under construction - you were warned!
+ */
+#ifndef __ASM_MIPS_DEC_KN02_H 
+#define __ASM_MIPS_DEC_KN02_H 
+
+#include <asm/addrspace.h>
+
+/*
+ * Motherboard regs (kseg1 addresses)
+ */
+#define KN02_CSR_ADDR	KSEG1ADDR(0x1ff00000)	/* system control & status reg */
+
+/*
+ * Some port addresses...
+ * FIXME: these addresses are incomplete and need tidying up!
+ */
+#define KN02_RTC_BASE	KSEG1ADDR(0x1fe80000)
+#define KN02_DZ11_BASE	KSEG1ADDR(0x1fe00000)
+
+/*
+ * Interrupt enable Bits
+ */
+#define KN02_SLOT0	(1<<16)
+#define KN02_SLOT1	(1<<17)
+#define KN02_SLOT2	(1<<18)
+#define KN02_SLOT5	(1<<21)
+#define KN02_SLOT6	(1<<22)
+#define KN02_SLOT7	(1<<23)
+
+#endif /* __ASM_MIPS_DEC_KN02_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/kn02xa.h linux.pre11.3/include/asm-mips/dec/kn02xa.h
--- linux.vanilla/include/asm-mips/dec/kn02xa.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/kn02xa.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,34 @@
+/*
+ * Hardware info about DEC DECstation 5000/1xx systems (otherwise known
+ * as 3min or kn02ba. Apllies to the Personal DECstations 5000/xx (otherwise known
+ * as maxine or kn02ca) as well.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
+ * are by curteousy of Chris Fraser.
+ *
+ * These are addresses which have to be known early in the boot process.
+ * For other addresses refer to tc.h ioasic_addrs.h and friends.
+ */
+#ifndef __ASM_MIPS_DEC_KN02XA_H 
+#define __ASM_MIPS_DEC_KN02XA_H 
+
+#include <asm/addrspace.h>
+
+/*
+ * Motherboard regs (kseg1 addresses)
+ */
+#define KN02XA_SSR_ADDR		KSEG1ADDR(0x1c040100)	/* system control & status reg */
+#define KN02XA_SIR_ADDR		KSEG1ADDR(0x1c040110)	/* system interrupt reg */
+#define KN02XA_SIRM_ADDR	KSEG1ADDR(0x1c040120)	/* system interrupt mask reg */
+
+/*
+ * Some port addresses...
+ * FIXME: these addresses are incomplete and need tidying up!
+ */
+#define KN02XA_RTC_BASE	(KSEG1ADDR(0x1c000000 + 0x200000)) /* ASIC + SL8 */
+
+#endif /* __ASM_MIPS_DEC_KN02XA_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/kn03.h linux.pre11.3/include/asm-mips/dec/kn03.h
--- linux.vanilla/include/asm-mips/dec/kn03.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/kn03.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,33 @@
+/*
+ * Hardware info about DEC DECstation 5000/2x0 systems (otherwise known
+ * as 3max+ or kn03.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995,1996 by Paul M. Antoine, some code and definitions
+ * are by curteousy of Chris Fraser.
+ *
+ * These are addresses which have to be known early in the boot process.
+ * For other addresses refer to tc.h ioasic_addrs.h and friends.
+ */
+#ifndef __ASM_MIPS_DEC_KN03_H 
+#define __ASM_MIPS_DEC_KN03_H 
+
+#include <asm/addrspace.h>
+
+/*
+ * Motherboard regs (kseg1 addresses)
+ */
+#define KN03_SSR_ADDR	KSEG1ADDR(0x1f840100)	/* system control & status reg */
+#define KN03_SIR_ADDR	KSEG1ADDR(0x1f840110)	/* system interrupt reg */
+#define KN03_SIRM_ADDR	KSEG1ADDR(0x1f840120)	/* system interrupt mask reg */
+
+/*
+ * Some port addresses...
+ * FIXME: these addresses are incomplete and need tidying up!
+ */
+#define KN03_RTC_BASE	(KSEG1ADDR(0x1f800000 + 0x200000)) /* ASIC + SL8 */
+
+#endif /* __ASM_MIPS_DEC_KN03_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/machtype.h linux.pre11.3/include/asm-mips/dec/machtype.h
--- linux.vanilla/include/asm-mips/dec/machtype.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/machtype.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,20 @@
+/*
+ * Various machine type definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+#include <asm/bootinfo.h>
+
+#define TURBOCHANNEL	(mips_machtype == MACH_DS5000_200 || \
+			 mips_machtype == MACH_DS5000_1XX || \
+			 mips_machtype == MACH_DS5000_XX  || \
+			 mips_machtype == MACH_DS5000_2X0)
+		      
+#define IOASIC		(mips_machtype == MACH_DS5000_1XX || \
+			 mips_machtype == MACH_DS5000_XX  || \
+			 mips_machtype == MACH_DS5000_2X0)
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/tc.h linux.pre11.3/include/asm-mips/dec/tc.h
--- linux.vanilla/include/asm-mips/dec/tc.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/tc.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,43 @@
+/*
+ * Interface to the TURBOchannel related routines
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+#ifndef ASM_TC_H
+#define ASM_TC_H
+
+extern unsigned long system_base;
+
+/*
+ * Search for a TURBOchannel Option Module
+ * with a certain name. Returns slot number
+ * of the first card not in use or -ENODEV
+ * if none found.
+ */
+extern int search_tc_card(const char *);
+/*
+ * Marks the card in slot as used
+ */
+extern void claim_tc_card(int);
+/*
+ * Marks the card in slot as free
+ */
+extern void release_tc_card(int);
+/*
+ * Return base address of card in slot 
+ */
+extern unsigned long get_tc_base_addr(int);
+/*
+ * Return interrupt number of slot
+ */
+extern unsigned long get_tc_irq_nr(int);
+/*
+ * Return TURBOchannel clock frequency in hz
+ */
+extern unsigned long get_tc_speed(void);
+
+#endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/tcinfo.h linux.pre11.3/include/asm-mips/dec/tcinfo.h
--- linux.vanilla/include/asm-mips/dec/tcinfo.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/tcinfo.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,47 @@
+/* 
+ * Various TURBOchannel related stuff
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Information obtained through the get_tcinfo prom call
+ * created from:
+ *
+ * TURBOchannel Firmware Specification
+ *
+ * EK-TCAAD-FS-004
+ * from Digital Equipment Corporation
+ *
+ * Copyright (c) 1998 Harald Koerfgen
+ */
+
+typedef struct {
+	int revision;
+	int clk_period;
+	int slot_size;
+	int io_timeout;
+	int dma_range;
+	int max_dma_burst;
+	int parity;
+	int reserved[4];
+} tcinfo;
+
+#define MAX_SLOT 7
+
+typedef struct {
+	unsigned long base_addr;
+	unsigned char name[9];
+	unsigned char vendor[9];
+	unsigned char firmware[9];
+	int interrupt;
+	int flags;
+} slot_info;
+
+/*
+ * Values for flags
+ */
+#define FREE 	1<<0
+#define IN_USE	1<<1
+
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dec/tcmodule.h linux.pre11.3/include/asm-mips/dec/tcmodule.h
--- linux.vanilla/include/asm-mips/dec/tcmodule.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/dec/tcmodule.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,35 @@
+/* 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Offsets for the ROM header locations for
+ * TURBOchannel cards
+ *
+ * created from:
+ *
+ * TURBOchannel Firmware Specification
+ *
+ * EK-TCAAD-FS-004
+ * from Digital Equipment Corporation
+ *
+ * Jan.1998 Harald Koerfgen
+ */
+ 
+#define OLDCARD 0x3c0000
+
+#define ROM_WIDTH 0x3e0
+#define ROM_STRIDE 0x3e4
+#define ROM_SIZE 0x3e8
+#define SLOT_SIZE 0x3ec
+#define PATTERN0 0x3f0
+#define PATTERN1 0x3f4
+#define PATTERN2 0x3f8
+#define PATTERN3 0x3fc
+#define FIRM_VER 0x400
+#define VENDOR 0x420
+#define MODULE 0x440
+#define FIRM_TYPE 0x460
+#define FLAGS 0x470
+
+#define ROM_OBJECTS 0x480
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/delay.h linux.pre11.3/include/asm-mips/delay.h
--- linux.vanilla/include/asm-mips/delay.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/delay.h	Mon Jul 19 23:26:46 1999
@@ -1,3 +1,12 @@
+/* $Id: delay.h,v 1.2 1999/01/04 16:09:20 ralf Exp $
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 by Waldorf Electronics
+ * Copyright (C) 1995 - 1998 by Ralf Baechle
+ */
 #ifndef __ASM_MIPS_DELAY_H
 #define __ASM_MIPS_DELAY_H
 
@@ -25,7 +34,7 @@
 extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 {
 	usecs *= 0x000010c6;		/* 2**32 / 1000000 */
-	__asm__("multu\t%0,%1\n\t"
+	__asm__("multu\t%0,%2\n\t"
 		"mfhi\t%0"
 		:"=r" (usecs)
 		:"0" (usecs),"r" (lps));
@@ -39,14 +48,5 @@
 #endif
 
 #define udelay(usecs) __udelay((usecs),__udelay_val)
-
-/*
- * The different variants for 32/64 bit are pure paranoia. The typical
- * range of numbers that appears for MIPS machines avoids overflows.
- */
-extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
-{
-	return (a*b)/c;
-}
 
 #endif /* __ASM_MIPS_DELAY_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/dma.h linux.pre11.3/include/asm-mips/dma.h
--- linux.vanilla/include/asm-mips/dma.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/dma.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.2 1998/10/19 21:29:10 ralf Exp $
+/* $Id: dma.h,v 1.2 1999/01/04 16:09:21 ralf Exp $
  * 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
@@ -16,6 +16,7 @@
 #include <asm/io.h>			/* need byte IO */
 #include <asm/spinlock.h>		/* And spinlocks */
 #include <linux/delay.h>
+#include <asm/system.h>
 
 
 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
@@ -175,8 +176,6 @@
 		dma_outb(dmanr | 4,  DMA1_MASK_REG);
 	else
 		dma_outb((dmanr & 3) | 4,  DMA2_MASK_REG);
-	/* I hate voodoo programming but .. */
-	udelay(20);
 }
 
 /* Clear the 'DMA Pointer Flip Flop'.
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ds1286.h linux.pre11.3/include/asm-mips/ds1286.h
--- linux.vanilla/include/asm-mips/ds1286.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/ds1286.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: ds1286.h,v 1.1 1998/07/09 20:01:30 ralf Exp $
+/* $Id: ds1286.h,v 1.1 1998/07/10 01:14:55 ralf Exp $
  *
  * mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
  * Copyright Torsten Duwe <duwe@informatik.uni-erlangen.de> 1993
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/elf.h linux.pre11.3/include/asm-mips/elf.h
--- linux.vanilla/include/asm-mips/elf.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/elf.h	Mon Jul 19 23:26:46 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: elf.h,v 1.10 1998/05/01 01:35:51 ralf Exp $
+ * $Id: elf.h,v 1.6 1999/02/15 02:22:10 ralf Exp $
  */
 #ifndef __ASM_MIPS_ELF_H
 #define __ASM_MIPS_ELF_H
@@ -53,10 +53,20 @@
 
 #define ELF_PLATFORM  (NULL)
 
-/* See comments in asm-alpha/elf.h, this is the same thing
+/*
+ * See comments in asm-alpha/elf.h, this is the same thing
  * on the MIPS.
  */
-#define ELF_PLAT_INIT(_r)	_r->regs[2] = 0;
+#define ELF_PLAT_INIT(_r)	do { \
+	_r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0;	\
+	_r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0;	\
+	_r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0;	\
+	_r->regs[13] = _r->regs[14] = _r->regs[15] = _r->regs[16] = 0;	\
+	_r->regs[17] = _r->regs[18] = _r->regs[19] = _r->regs[20] = 0;	\
+	_r->regs[21] = _r->regs[22] = _r->regs[23] = _r->regs[24] = 0;	\
+	_r->regs[25] = _r->regs[26] = _r->regs[27] = _r->regs[28] = 0;	\
+	_r->regs[30] = _r->regs[31] = 0;				\
+} while (0)
 
 /* 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/fcntl.h linux.pre11.3/include/asm-mips/fcntl.h
--- linux.vanilla/include/asm-mips/fcntl.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/fcntl.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.3 1998/08/29 20:41:02 ralf Exp $
+/* $Id: fcntl.h,v 1.5 1999/01/04 16:09:21 ralf Exp $
  *
  * 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
@@ -24,9 +24,9 @@
 #define O_NOCTTY	0x0800	/* not fcntl */
 #define FASYNC		0x1000	/* fcntl, for BSD compatibility */
 #define O_LARGEFILE	0x2000	/* allow large file opens - currently ignored */
-#define O_NOFOLLOW	0x4000	/* Don't follow symbolic links */
 #define O_DIRECT	0x8000	/* direct disk access hint - currently ignored */
 #define O_DIRECTORY	0x10000	/* must be a directory */
+#define O_NOFOLLOW	0x20000	/* don't follow links */
 
 #define O_NDELAY	O_NONBLOCK
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/floppy.h linux.pre11.3/include/asm-mips/floppy.h
--- linux.vanilla/include/asm-mips/floppy.h	Sun Nov  8 15:10:25 1998
+++ linux.pre11.3/include/asm-mips/floppy.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.4 1998/05/07 18:38:41 ralf Exp $
+/* $Id: floppy.h,v 1.6.2.1 1999/06/23 22:28:38 ralf Exp $
  *
  * Architecture specific parts of the Floppy driver
  *
@@ -42,30 +42,30 @@
 
 extern struct fd_ops *fd_ops;
 
-#define fd_inb(port)			fd_ops->fd_inb(port)
-#define fd_outb(value,port)		fd_ops->fd_outb(value,port)
+#define fd_inb(port)		fd_ops->fd_inb(port)
+#define fd_outb(value,port)	fd_ops->fd_outb(value,port)
 
-#define fd_enable_dma(channel)		fd_ops->fd_enable_dma(channel)
-#define fd_disable_dma(channel)		fd_ops->fd_disable_dma(channel)
-#define fd_request_dma(channel)		fd_ops->fd_request_dma(channel)
-#define fd_free_dma(channel)		fd_ops->fd_free_dma(channel)
-#define fd_clear_dma_ff(channel)	fd_ops->fd_clear_dma_ff(channel)
-#define fd_set_dma_mode(channel, mode)	fd_ops->fd_set_dma_mode(channel, mode)
-#define fd_set_dma_addr(channel, addr)	fd_ops->fd_set_dma_addr(channel, \
-					         virt_to_bus(addr))
-#define fd_set_dma_count(channel,count)	fd_ops->fd_set_dma_count(channel,count)
-#define fd_get_dma_residue(channel)	fd_ops->fd_get_dma_residue(channel)
-
-#define fd_enable_irq(irq)		fd_ops->fd_enable_irq(irq)
-#define fd_disable_irq(irq)		fd_ops->fd_disable_irq(irq)
-#define fd_request_irq(irq)		request_irq(irq, floppy_interrupt, \
-						    SA_INTERRUPT \
-					            | SA_SAMPLE_RANDOM, \
-				                    "floppy", NULL)
-#define fd_free_irq(irq)		free_irq(irq, NULL);
-#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
+#define fd_enable_dma()		fd_ops->fd_enable_dma(FLOPPY_DMA)
+#define fd_disable_dma()	fd_ops->fd_disable_dma(FLOPPY_DMA)
+#define fd_request_dma()	fd_ops->fd_request_dma(FLOPPY_DMA)
+#define fd_free_dma()		fd_ops->fd_free_dma(FLOPPY_DMA)
+#define fd_clear_dma_ff()	fd_ops->fd_clear_dma_ff(FLOPPY_DMA)
+#define fd_set_dma_mode(mode)	fd_ops->fd_set_dma_mode(FLOPPY_DMA, mode)
+#define fd_set_dma_addr(addr)	fd_ops->fd_set_dma_addr(FLOPPY_DMA, \
+				                       virt_to_bus(addr))
+#define fd_set_dma_count(count)	fd_ops->fd_set_dma_count(FLOPPY_DMA,count)
+#define fd_get_dma_residue()	fd_ops->fd_get_dma_residue(FLOPPY_DMA)
+
+#define fd_enable_irq()		fd_ops->fd_enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq()	fd_ops->fd_disable_irq(FLOPPY_IRQ)
+#define fd_request_irq()	request_irq(FLOPPY_IRQ, floppy_interrupt, \
+				            SA_INTERRUPT | SA_SAMPLE_RANDOM, \
+				            "floppy", NULL)
+#define fd_free_irq()		free_irq(FLOPPY_IRQ, NULL);
+#define fd_dma_mem_alloc(size)	fd_ops->fd_dma_mem_alloc(size)
 #define fd_dma_mem_free(mem,size) fd_ops->fd_dma_mem_free(mem,size)
-#define fd_drive_type(n)		fd_ops->fd_drive_type(n)
+#define fd_drive_type(n)	fd_ops->fd_drive_type(n)
+#define fd_cacheflush(addr,size) dma_cache_wback_inv(addr,size)
 
 #define MAX_BUFFER_SECTORS 24
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/fp.h linux.pre11.3/include/asm-mips/fp.h
--- linux.vanilla/include/asm-mips/fp.h	Sun Nov  8 15:06:56 1998
+++ linux.pre11.3/include/asm-mips/fp.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: fp.h,v 1.1 1998/07/16 17:01:54 ralf Exp $
+/* $Id: fp.h,v 1.1 1998/07/16 19:10:04 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/gdb-stub.h linux.pre11.3/include/asm-mips/gdb-stub.h
--- linux.vanilla/include/asm-mips/gdb-stub.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/gdb-stub.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: gdb-stub.h,v 1.3 1998/07/20 17:52:19 ralf Exp $
+/* $Id: gdb-stub.h,v 1.3 1998/08/25 09:21:55 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/hardirq.h linux.pre11.3/include/asm-mips/hardirq.h
--- linux.vanilla/include/asm-mips/hardirq.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/hardirq.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: hardirq.h,v 1.5 1998/08/29 21:20:21 ralf Exp $
+/* $Id: hardirq.h,v 1.4 1998/09/19 19:19:37 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ide.h linux.pre11.3/include/asm-mips/ide.h
--- linux.vanilla/include/asm-mips/ide.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/ide.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.4 1998/05/08 21:05:26 davem Exp $
+/* $Id: ide.h,v 1.4.2.2 1999/06/17 12:09:40 ralf Exp $
  *
  *  linux/include/asm-mips/ide.h
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/init.h linux.pre11.3/include/asm-mips/init.h
--- linux.vanilla/include/asm-mips/init.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/init.h	Mon Jul 19 23:26:46 1999
@@ -1,11 +1,10 @@
-/*
- * include/asm-mips/init.h
+/* $Id: init.h,v 1.3 1999/02/15 02:22:10 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * $Id: init.h,v 1.3 1998/05/01 01:35:53 ralf Exp $
+ * Copyright 1998, 1999 Ralf Baechle
  */
 #ifndef __MIPS_INIT_H
 #define __MIPS_INIT_H
@@ -26,5 +25,6 @@
 #define __INIT		.section	.text.init,"ax"
 #define __FINIT		.previous
 #define __INITDATA	.section	.data.init,"a"
+#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES)))
 
 #endif /* __MIPS_INIT_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/inventory.h linux.pre11.3/include/asm-mips/inventory.h
--- linux.vanilla/include/asm-mips/inventory.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/inventory.h	Mon Jul 19 23:26:46 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: inventory.h,v 1.2 1998/05/01 01:35:54 ralf Exp $
+ * $Id: inventory.h,v 1.2 1997/12/06 23:55:49 ralf Exp $
  */
 #ifndef __ASM_MIPS_INVENTORY_H
 #define __ASM_MIPS_INVENTORY_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/io.h linux.pre11.3/include/asm-mips/io.h
--- linux.vanilla/include/asm-mips/io.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/io.h	Mon Jul 19 23:26:46 1999
@@ -140,18 +140,21 @@
 /*
  * XXX We need system specific versions of these to handle EISA address bits
  * 24-31 on SNI.
+ * XXX more SNI hacks.
  */
-#define readb(addr) (*(volatile unsigned char *) (isa_slot_offset + (unsigned long)(addr)))
-#define readw(addr) (*(volatile unsigned short *) (isa_slot_offset + (unsigned long)(addr)))
-#define readl(addr) (*(volatile unsigned int *) (isa_slot_offset + (unsigned long)(addr)))
+#define readb(addr) (*(volatile unsigned char *) (0xa0000000 + (unsigned long)(addr)))
+#define readw(addr) (*(volatile unsigned short *) (0xa0000000 + (unsigned long)(addr)))
+#define readl(addr) (*(volatile unsigned int *) (0xa0000000 + (unsigned long)(addr)))
 
-#define writeb(b,addr) (*(volatile unsigned char *) (isa_slot_offset + (unsigned long)(addr)) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (isa_slot_offset + (unsigned long)(addr)) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (isa_slot_offset + (unsigned long)(addr)) = (b))
+#define writeb(b,addr) (*(volatile unsigned char *) (0xa0000000 + (unsigned long)(addr)) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) (0xa0000000 + (unsigned long)(addr)) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) (0xa0000000 + (unsigned long)(addr)) = (b))
 
-#define memset_io(a,b,c)	memset((void *)(isa_slot_offset + (unsigned long)a),(b),(c))
-#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(isa_slot_offset + (unsigned long)(b)),(c))
-#define memcpy_toio(a,b,c)	memcpy((void *)(isa_slot_offset + (unsigned long)(a)),(b),(c))
+#define memset_io(a,b,c)	memset((void *)(0xa0000000 + (unsigned long)a),(b),(c))
+#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(0xa0000000 + (unsigned long)(b)),(c))
+#define memcpy_toio(a,b,c)	memcpy((void *)(0xa0000000 + (unsigned long)(a)),(b),(c))
+
+/* END SNI HACKS ... */
 
 /*
  * We don't have csum_partial_copy_fromio() yet, so we cheat here and
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ioctls.h linux.pre11.3/include/asm-mips/ioctls.h
--- linux.vanilla/include/asm-mips/ioctls.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/ioctls.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: ioctls.h,v 1.5 1998/08/19 21:58:11 ralf Exp $
+/* $Id: ioctls.h,v 1.8 1998/08/25 09:21:56 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ipc.h linux.pre11.3/include/asm-mips/ipc.h
--- linux.vanilla/include/asm-mips/ipc.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/ipc.h	Mon Jul 19 23:26:46 1999
@@ -24,6 +24,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 /* __ASM_MIPS_IPC_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/irq.h linux.pre11.3/include/asm-mips/irq.h
--- linux.vanilla/include/asm-mips/irq.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/irq.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.4 1998/05/28 03:18:13 ralf Exp $
+/* $Id: irq.h,v 1.5 1999/01/04 16:09:22 ralf Exp $
  *
  * 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,9 +10,6 @@
 #ifndef __ASM_MIPS_IRQ_H
 #define __ASM_MIPS_IRQ_H
 
-/*
- * Actually this is a lie but we hide the local device's interrupts ...
- */
 #define NR_IRQS 64
 
 #define TIMER_IRQ 0
@@ -20,18 +17,9 @@
 extern int (*irq_cannonicalize)(int irq);
 
 struct irqaction;
-extern int setup_x86_irq(int irq, struct irqaction * new);
+extern int i8259_setup_irq(int irq, struct irqaction * new);
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
-
-extern unsigned int local_irq_count[];
-
-#ifdef __SMP__
-#error Send superfluous SMP boxes to ralf@uni-koblenz.de
-#else
-#define irq_enter(cpu, irq)     (++local_irq_count[cpu])
-#define irq_exit(cpu, irq)      (--local_irq_count[cpu])
-#endif
 
 /* Machine specific interrupt initialization  */
 extern void (*irq_setup)(void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/jazz.h linux.pre11.3/include/asm-mips/jazz.h
--- linux.vanilla/include/asm-mips/jazz.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/jazz.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: jazz.h,v 1.8 1998/09/16 22:52:41 ralf Exp $
+/* $Id: jazz.h,v 1.10 1998/10/18 13:16:02 tsbogend Exp $
  *
  * 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
@@ -203,15 +203,19 @@
  * This is somewhat broken.  For reasons which nobody can remember anymore
  * we remap the Jazz interrupts to the usual ISA style interrupt numbers.
  */
-#define JAZZ_TIMER_IRQ          0
-#define JAZZ_KEYBOARD_IRQ       1
-#define JAZZ_FLOPPY_IRQ         6 /* needs to be consistent with floppy driver! */
-#define JAZZ_SCSI_IRQ           16
-#define JAZZ_ETHERNET_IRQ       17
-#define JAZZ_SERIAL1_IRQ        18
-#define JAZZ_SERIAL2_IRQ        19
-#define JAZZ_PARALLEL_IRQ       20
-#define JAZZ_MOUSE_IRQ          21
+#define JAZZ_PARALLEL_IRQ       16
+#define JAZZ_FLOPPY_IRQ          6 /* needs to be consistent with floppy driver! */
+#define JAZZ_SOUND_IRQ          18
+#define JAZZ_VIDEO_IRQ          19
+#define JAZZ_ETHERNET_IRQ       20
+#define JAZZ_SCSI_IRQ           21
+#define JAZZ_KEYBOARD_IRQ       22
+#define JAZZ_MOUSE_IRQ          23
+#define JAZZ_SERIAL1_IRQ        24
+#define JAZZ_SERIAL2_IRQ        25
+
+#define JAZZ_TIMER_IRQ          31
+
 
 /*
  * JAZZ DMA Channels
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/jazzdma.h linux.pre11.3/include/asm-mips/jazzdma.h
--- linux.vanilla/include/asm-mips/jazzdma.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/jazzdma.h	Mon Jul 19 23:26:46 1999
@@ -1,7 +1,7 @@
 /*
  * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
  *
- * $Id: jazzdma.h,v 1.6 1998/05/01 01:35:57 ralf Exp $
+ * $Id: jazzdma.h,v 1.6 1998/03/04 09:51:22 ralf Exp $
  */
 #ifndef __ASM_MIPS_JAZZDMA_H
 #define __ASM_MIPS_JAZZDMA_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/keyboard.h linux.pre11.3/include/asm-mips/keyboard.h
--- linux.vanilla/include/asm-mips/keyboard.h	Wed Apr 28 19:14:33 1999
+++ linux.pre11.3/include/asm-mips/keyboard.h	Mon Jul 19 23:26:46 1999
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * $Id: keyboard.h,v 1.12 1998/09/16 22:52:41 ralf Exp $
+ * $Id: keyboard.h,v 1.13 1999/06/13 16:35:53 ralf Exp $
  */
 #ifndef __ASM_MIPS_KEYBOARD_H
 #define __ASM_MIPS_KEYBOARD_H
@@ -17,6 +17,8 @@
 #include <linux/ioport.h>
 #include <asm/bootinfo.h>
 
+#define DISABLE_KBD_DURING_INTERRUPTS 0
+
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
@@ -39,60 +41,36 @@
 /* Some stoneage hardware needs delays after some operations.  */
 #define kbd_pause() do { } while(0)
 
-/* Pointers to keyboard hardware access and init functions.  */
-unsigned char (*kbd_read_input)(void);
-void (*kbd_write_output)(unsigned char val);
-void (*kbd_write_command)(unsigned char val);
-unsigned char (*kbd_read_status)(void);
-
-void (*keyboard_setup)(void);
-
-#ifdef CONFIG_MIPS_JAZZ
-
-extern int jazz_ps2_request_irq(void);
-extern void jazz_ps2_free_irq(void);
-
-#define ps2_request_irq()      jazz_ps2_request_irq()
-#define ps2_free_irq(inode)    jazz_ps2_free_irq()
-
-#endif /* CONFIG_MIPS_JAZZ */
-
-#ifdef CONFIG_SGI
-
-#define DISABLE_KBD_DURING_INTERRUPTS 1
-
-/*
- * Machine specific bits for the PS/2 driver.
- * Aux device and keyboard share the interrupt on the Indy.
- */
-#define ps2_request_irq() 0
-#define ps2_free_irq(void) do { } while(0);
-
-#endif /* CONFIG_SGI */
-
-#if defined(CONFIG_ACER_PICA_61) || defined(CONFIG_SNI_RM200_PCI)
-#define CONF_KEYBOARD_USES_IO_PORTS
-#endif
-
-#ifdef CONF_KEYBOARD_USES_IO_PORTS
-/*
- * Most other MIPS machines access the keyboard controller via
- * memory mapped I/O ports.
- */
-#include <asm/io.h>
-
-/*
- * Machine specific bits for the PS/2 driver
- */
-
-#define AUX_IRQ 12
-
-#define ps2_request_irq()						\
-	request_irq(AUX_IRQ, aux_interrupt, 0, "PS/2 Mouse", NULL)
-
-#define ps2_free_irq(inode) free_irq(AUX_IRQ, NULL)
-
-#endif /* CONF_KEYBOARD_USES_IO_PORTS */
+struct kbd_ops {
+	/* Keyboard driver resource allocation  */
+	void (*kbd_request_region)(void);
+	int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
+
+	/* PSaux driver resource managment  */
+	int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
+	void (*aux_free_irq)(void);
+
+	/* Methods to access the keyboard processor's I/O registers  */
+	unsigned char (*kbd_read_input)(void);
+	void (*kbd_write_output)(unsigned char val);
+	void (*kbd_write_command)(unsigned char val);
+	unsigned char (*kbd_read_status)(void);
+};
+
+extern struct kbd_ops *kbd_ops;
+
+/* Do the actual calls via kbd_ops vector  */
+#define kbd_request_region() kbd_ops->kbd_request_region()
+#define kbd_request_irq(handler) kbd_ops->kbd_request_irq(handler)
+
+#define aux_request_irq(hand, dev_id) kbd_ops->aux_request_irq(hand)
+#define aux_free_irq(dev_id) kbd_ops->aux_free_irq()
+
+#define kbd_read_input() kbd_ops->kbd_read_input()
+#define kbd_write_output(val) kbd_ops->kbd_write_output(val)
+#define kbd_write_command(val) kbd_ops->kbd_write_command(val)
+#define kbd_read_status() kbd_ops->kbd_read_status()
 
 #endif /* __KERNEL */
+
 #endif /* __ASM_MIPS_KEYBOARD_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/linux_logo.h linux.pre11.3/include/asm-mips/linux_logo.h
--- linux.vanilla/include/asm-mips/linux_logo.h	Sun Nov  8 15:06:56 1998
+++ linux.pre11.3/include/asm-mips/linux_logo.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,5 @@
-/* $Id: linux_logo.h,v 1.1 1998/07/30 16:30:31 jj Exp $
+/* $Id: linux_logo.h,v 1.4 1999/01/04 16:09:23 ralf Exp $
+ *
  * include/asm-mips/linux_logo.h: This is a linux logo
  *                                to be displayed on boot.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/mc146818rtc.h linux.pre11.3/include/asm-mips/mc146818rtc.h
--- linux.vanilla/include/asm-mips/mc146818rtc.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/mc146818rtc.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: mc146818rtc.h,v 1.3 1998/06/25 20:19:26 ralf Exp $
+/* $Id: mc146818rtc.h,v 1.2 1998/06/30 00:23:10 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/md.h linux.pre11.3/include/asm-mips/md.h
--- linux.vanilla/include/asm-mips/md.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/md.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: md.h,v 1.1 1998/08/17 10:20:14 ralf Exp $
+/* $Id: md.h,v 1.1 1998/08/25 09:21:57 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/mipsregs.h linux.pre11.3/include/asm-mips/mipsregs.h
--- linux.vanilla/include/asm-mips/mipsregs.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/mipsregs.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: mipsregs.h,v 1.6 1998/08/17 11:27:08 ralf Exp $
+/* $Id: mipsregs.h,v 1.5 1999/04/11 17:13:57 harald Exp $
  *
  * 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
@@ -233,11 +233,12 @@
 /*
  * Bitfields in the R[23]000 cp0 status register.
  */
-#define ST0_KUC			0x00000001
-#define ST0_IEP			0x00000002
-#define ST0_KUP			0x00000004
-#define ST0_IEO			0x00000008
-#define ST0_KUO			0x00000010
+#define ST0_IEC                 0x00000001
+#define ST0_KUC			0x00000002
+#define ST0_IEP			0x00000004
+#define ST0_KUP			0x00000008
+#define ST0_IEO			0x00000010
+#define ST0_KUO			0x00000020
 /* bits 6 & 7 are reserved on R[23]000 */
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/mmu_context.h linux.pre11.3/include/asm-mips/mmu_context.h
--- linux.vanilla/include/asm-mips/mmu_context.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/mmu_context.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.3 1998/10/16 19:22:54 ralf Exp $
+/* $Id: mmu_context.h,v 1.3 1999/01/04 16:09:23 ralf Exp $
  *
  * Switch a MMU context.
  *
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/namei.h linux.pre11.3/include/asm-mips/namei.h
--- linux.vanilla/include/asm-mips/namei.h	Thu Nov 19 18:38:47 1998
+++ linux.pre11.3/include/asm-mips/namei.h	Mon Jul 19 23:26:46 1999
@@ -3,7 +3,7 @@
  *
  * Included from linux/fs/namei.c
  *
- * $Id: namei.h,v 1.10 1998/10/28 08:13:24 jj Exp $
+ * $Id: namei.h,v 1.6 1999/01/04 16:09:23 ralf Exp $
  */
 #ifndef __ASM_MIPS_NAMEI_H
 #define __ASM_MIPS_NAMEI_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/newport.h linux.pre11.3/include/asm-mips/newport.h
--- linux.vanilla/include/asm-mips/newport.h	Sun Nov  8 15:06:56 1998
+++ linux.pre11.3/include/asm-mips/newport.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: newport.h,v 1.1 1998/08/19 21:58:12 ralf Exp $
+/* $Id: newport.h,v 1.2 1999/03/02 23:40:53 tsbogend Exp $
  *
  * newport.h: Defines and register layout for NEWPORT graphics
  *            hardware.
@@ -581,6 +581,13 @@
                         DCB_DATAWIDTH_4 | WAYSLOW_DCB_XMAP9_PROTOCOL; 
         rex->set.dcbdata0.all = ((modereg) << 24) | (data24 & 0xffffff);
 }
+
+#define BT445_PROTOCOL		DCB_CYCLES(1,1,3)
+
+#define BT445_CSR_ADDR_REG	(0 << DCB_CRS_SHIFT)
+#define BT445_CSR_REVISION	(2 << DCB_CRS_SHIFT)
+
+#define BT445_REVISION_REG	0x01
 
 #endif /* !(_SGI_NEWPORT_H) */
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ng1.h linux.pre11.3/include/asm-mips/ng1.h
--- linux.vanilla/include/asm-mips/ng1.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/ng1.h	Mon Jul 19 23:26:46 1999
@@ -5,24 +5,24 @@
 
 typedef struct {
         int flags;
-        u16 w, h;
-        u16 fields_sec;
+        __u16 w, h;
+        __u16 fields_sec;
 } ng1_vof_info_t;
 
 struct ng1_info {
 	struct gfx_info gfx_info;
-	u8 boardrev;
-        u8 rex3rev;
-        u8 vc2rev;
-        u8 monitortype;
-        u8 videoinstalled;
-        u8 mcrev;
-        u8 bitplanes;
-        u8 xmap9rev;
-        u8 cmaprev;
+	__u8 boardrev;
+        __u8 rex3rev;
+        __u8 vc2rev;
+        __u8 monitortype;
+        __u8 videoinstalled;
+        __u8 mcrev;
+        __u8 bitplanes;
+        __u8 xmap9rev;
+        __u8 cmaprev;
         ng1_vof_info_t ng1_vof_info;
-        u8 bt445rev;
-        u8 paneltype;
+        __u8 bt445rev;
+        __u8 paneltype;
 };
 
 #define GFX_NAME_NEWPORT "NG1"
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ng1hw.h linux.pre11.3/include/asm-mips/ng1hw.h
--- linux.vanilla/include/asm-mips/ng1hw.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/ng1hw.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,572 @@
+/* This is the hardware interface for newport graphics.  It's taken from
+   IRIX.
+
+   Alex deVries <puffin@redhat.com>
+
+*/
+
+
+#ifndef __SYS_NG1HW_H__
+#define __SYS_NG1HW_H__
+
+#ident "$Revision: 1.1 $"
+
+#define BIT(n)	(0x1 << n)
+
+
+#ifndef REX_ASMCODE
+
+typedef union {
+    volatile float flt;
+    volatile unsigned int word;
+} float_long;
+
+typedef volatile unsigned int vol_ulong;
+typedef volatile unsigned int fixed16;
+
+typedef union {
+    vol_ulong   byword;
+    struct {
+	volatile unsigned short s0;
+	volatile unsigned short s1;
+    } byshort;
+    struct {
+	volatile unsigned char b0, b1, b2;
+	volatile unsigned char b3;
+    } bybyte;
+} DCB_reg;
+
+#ifndef REXSIM
+typedef struct rex3regs {	/* THE CHIP */
+    vol_ulong drawmode1;	/* extra mode bits for GL 	0x0000 */
+    vol_ulong drawmode0;	/* command register 		0x0004 */
+
+    vol_ulong lsmode;		/* line stipple mode		0x0008 */
+    vol_ulong lspattern;	/* 32 bit pixel lspattern	0x000c */
+    vol_ulong lspatsave;	/* save register for lspattern	0x0010 */
+    vol_ulong zpattern;		/* 32 bit pixel zpattern	0x0014 */
+
+    vol_ulong colorback;	/* background color		0x0018 */
+    vol_ulong colorvram;	/* fast vram clear color	0x001c */
+    vol_ulong alpharef;		/* afunction reference value	0x0020 */
+
+    vol_ulong pad0;		/* padding 			0x0024 */	
+
+    vol_ulong smask0x;		/* screen mask 0, window rel,	0x0028 */
+    vol_ulong smask0y;		/* exclusively for the GL	0x002c */
+    vol_ulong _setup;		/* do line/span setup, no iter  0x0030 */
+    vol_ulong _stepz;		/* Enable ZPATTERN for this pix 0x0034 */
+    vol_ulong _lsrestore;	/* Restore lspattern,count	0x0038 */
+    vol_ulong _lssave;		/* Backup lspattern,count	0x003c */
+
+    char _pad1[0x100-0x40];
+
+    float_long _xstart;		/* 16.4(7) current x		0x0100 */
+    float_long _ystart;		/* 16.4(7) current y		0x0104 */
+    float_long _xend;		/* 16.4(7)			0x0108 */
+    float_long _yend;		/* 16.4(7)			0x010c */
+    vol_ulong xsave;		/* 16	x save for blocks	0x0110 */
+    vol_ulong xymove;		/* x,y copy dest offset		0x0114 */
+    float_long bresd;		/* s19.8 bres d error term	0x0118 */
+    float_long bress1;		/* s2.15 bres s coverage term	0x011c */
+    vol_ulong bresoctinc1;	/* 3(4)17.3 octant+inc1 value	0x0120 */
+    volatile int bresrndinc2;	/* 8(3)18.3 bres inc2 value	0x0124 */
+    vol_ulong brese1;		/* 1.15 bres e1 (minor slope)	0x0128 */
+    vol_ulong bress2;           /* s18.8 bres s2 coverage term  0x012c */
+    vol_ulong aweight0;		/* antialiasing weights		0x0130 */
+    vol_ulong aweight1;		/* antialiasing weights		0x0134 */
+    float_long xstartf;		/* 12.4(7) GL version of _xstart0x0138 */
+    float_long ystartf;		/* 12.4(7)			0x013c */
+    float_long xendf;		/* 12.4(7)			0x0140 */
+    float_long yendf;		/* 12.4(7)			0x0144 */
+    fixed16 xstarti;		/* 16 integer format for xstart 0x0148 */
+    float_long xendf1;		/* 12.4(7) same as xend		0x014c */
+    fixed16 xystarti;		/* 16,16			0x0150 */
+    fixed16 xyendi;		/* 16,16			0x0154 */
+    fixed16 xstartendi;		/* 16,16			0x0158 */
+    char _pad2[0x200-0x15c];
+    float_long colorred;	/* o12.11 red (also foreground)	0x0200 */
+    float_long coloralpha;	/* o8.11 alpha			0x0204 */
+    float_long colorgrn;	/* o8.11 green			0x0208 */
+    float_long colorblue;	/* o8.11 blue			0x020c */
+    float_long slopered;	/* s9.11			0x0210 */
+    float_long slopealpha;	/* s9.11			0x0214 */
+    float_long slopegrn;	/* s9.11			0x0218 */
+    float_long slopeblue;	/* s9.11			0x021c */
+    vol_ulong wrmask;		/* writemask			0x0220 */
+    vol_ulong colori;		/* packed bgr/ci		0x0224 */
+    float_long colorx;		/* 12.11 red (no overflow)	0x0228 */
+    float_long slopered1;	/* same as slopered		0x022c */
+    vol_ulong hostrw0;		/* host PIO/DMA port (msw)	0x0230 */
+    vol_ulong hostrw1;		/* host PIO/DMA port (lsw)	0x0234 */
+    vol_ulong dcbmode;		/* display ctrl bus mode reg 	0x0238 */
+    volatile int pad3;						/* 0x023c */
+    DCB_reg dcbdata0;		/* display ctrl bus port (msw)	0x0240 */
+    vol_ulong dcbdata1;		/* display ctrl bus port (lsw)	0x0244 */
+} Rex3regs;
+	
+
+typedef struct configregs {
+    vol_ulong smask1x;		/* screenmask1 right,left edges 0x1300 */
+    vol_ulong smask1y;		/* screenmask1 bottom,top edges 0x1304 */
+    vol_ulong smask2x;		/* screenmask2 right,left edges 0x1308 */
+    vol_ulong smask2y;		/* screenmask2 bottom,top edges 0x130c */
+    vol_ulong smask3x;		/* screenmask3 right,left edges 0x1310 */
+    vol_ulong smask3y;		/* screenmask3 bottom,top edges 0x1314 */
+    vol_ulong smask4x;		/* screenmask4 right,left edges 0x1318 */
+    vol_ulong smask4y;		/* screenmask4 bottom,top edges 0x131c */
+    vol_ulong topscan;		/* y coord of top screen line	0x1320 */
+    vol_ulong xywin;		/* window offset 		0x1324 */
+    vol_ulong clipmode;		/* cid,smask settings 		0x1328 */
+    vol_ulong pad0;		/*				0x132c */
+    vol_ulong config;		/* miscellaneous  config bits 	0x1330 */
+    vol_ulong pad1;		/*				0x1334 */
+    vol_ulong status;		/* chip busy, FIFO, int status  0x1338 */
+				/* read clears interrupt status bits   */
+    vol_ulong ustatus;		/* padding on rex rev a, 'read-only' 0x133c */
+				/* copy of status on rex rev b.	       */
+    vol_ulong dcbreset;		/* resets DCB and flushes BFIFO 0x1340 */
+} Configregs;
+
+typedef struct rex3chip {
+		/* page 0 */    
+	struct rex3regs set;		/* 0x0000 */
+	char _pad0[0x7fc-sizeof(struct rex3regs)];
+	volatile unsigned int dummy; /* 0x7fc */
+	struct rex3regs go;		/* 0x0800 */
+
+	char _pad1[0x1300-0x800-sizeof(struct rex3regs)];
+
+		/* page 1 */
+	struct {
+	    struct configregs set; 	/* 0x1300 */
+	    char _pad0[0x800-sizeof(struct configregs)];
+	    struct configregs go; 	/* 0x1b00 */
+	} p1;
+} rex3Chip, Rex3chip;
+
+
+#endif /* REX_ASMCODE */
+#endif /* REXSIM */
+
+/* Since alot of flags went away, define here as null bits
+   and leave the code as it is for now, 
+   marking where we have to change stuff.
+
+   NONE of these should be defined !   - billt
+   */
+
+#define LSCONTINUE 0
+#define SHADECONTINUE 0
+#define XYCONTINUE 0
+#define XMAJOR 0
+#define YMAJOR 0
+#define QUADMODE 0
+#define LRQPOLY 0
+/* RGBMODE, DITHER now live in DM1 */
+#define RGBMODECMD 0
+#define DITHER 0
+#define DITHERRANGE 0
+/* BLOCK is a function of ADDRMODE */
+#define BLOCK 0
+#define STOPONX 0
+#define STOPONY 0
+/* COLORCOMPARE is a combo of 3 bits (<, = , >) */
+#define COLORCOMP 0
+/* FRACTIONS are gone... */
+#define INITFRAC 0
+#define FRACTION1 0
+
+/* -- some old AUX1 junk -- */
+#define DOUBLEBUF 0
+#define DBLDST0 0
+#define DBLDST1 0
+#define DBLSRC 0
+#define COLORAUX 0
+
+
+/* --- a couple of old cmds also only for conversion --- */
+#define REX_LDPIXEL 0x1
+#define REX_ANTIAUX 0
+#define REX_DRAW 0
+#define LOGICSRC 0
+/* --- Blech! locicops are in DM1 too! */
+#define REX_LO_ZERO REX_LO_ZERO 
+#define REX_LO_AND DM1_LO_AND
+#define REX_LO_ANDR DM1_LO_ANDR
+#define REX_LO_SRC DM1_LO_SRC
+#define REX_LO_ANDI DM1_LO_ANDI
+#define REX_LO_DST DM1_LO_DST
+#define REX_LO_XOR DM1_LO_XOR
+#define REX_LO_OR DM1_LO_OR
+#define REX_LO_NOR DM1_LO_NOR
+#define REX_LO_XNOR DM1_LO_XNOR
+#define REX_LO_NDST DM1_LO_NDST
+#define REX_LO_ORR DM1_LO_ORR
+#define REX_LO_NSRC DM1_LO_NSRC
+#define REX_LO_ORI DM1_LO_ORI
+#define REX_LO_NAND DM1_LO_NAND
+#define REX_LO_ONE DM1_LO_ONE
+
+
+/*
+ *  drawmode flags
+ */
+#define DM0_OPCODE	0x3		/* opcode(1:0)	*/
+#	define DM0_NOP		0x0
+#	define DM0_READ		0x1
+#	define DM0_DRAW		0x2
+#	define DM0_SCR2SCR	0x3
+#define DM0_ADRMODE_SHIFT	2	/* adrmode(2:0)	*/
+#	define DM0_ADRMODE	(0x7<<DM0_ADRMODE_SHIFT)
+#	define DM0_SPAN		(0x0<<DM0_ADRMODE_SHIFT)
+#	define DM0_BLOCK	(0x1<<DM0_ADRMODE_SHIFT)
+#	define DM0_ILINE	(0x2<<DM0_ADRMODE_SHIFT)
+#	define DM0_FLINE	(0x3<<DM0_ADRMODE_SHIFT)
+#	define DM0_ALINE	(0x4<<DM0_ADRMODE_SHIFT)
+#ifdef OLDJUNK
+
+/* XXX These definitions are obsolete */
+
+#	define DM0_AELINE	(0x5<<DM0_ADRMODE_SHIFT)
+#	define DM0_ACWEDGE	(0x6<<DM0_ADRMODE_SHIFT)
+#	define DM0_ACCWEDGE	(0x7<<DM0_ADRMODE_SHIFT)
+
+#else
+
+/* XXX These are according to 11/2/92 spec */
+
+#       define DM0_TLINE        (0x5<<DM0_ADRMODE_SHIFT)
+#       define DM0_BLINE        (0x6<<DM0_ADRMODE_SHIFT)
+
+#endif /* OLDJUNK */
+
+#define DM0_DOSETUP	BIT(5)
+#define DM0_COLORHOST	BIT(6)
+#define DM0_ALPHAHOST	BIT(7)
+#define DM0_STOPONX	BIT(8)
+#define DM0_STOPONY	BIT(9)
+#define DM0_STOPONXY	(DM0_STOPONX | DM0_STOPONY)
+#define DM0_SKIPFIRST	BIT(10)
+#define DM0_SKIPLAST	BIT(11)
+#define DM0_ENZPATTERN	BIT(12)
+#define DM0_ENLSPATTERN	BIT(13)
+#define DM0_LSADVLAST	BIT(14)
+#define DM0_LENGTH32	BIT(15)
+#define DM0_ZOPAQUE	BIT(16)
+#define DM0_LSOPAQUE	BIT(17)
+#define DM0_SHADE	BIT(18)
+#define DM0_LRONLY	BIT(19)
+
+#ifdef OLDJUNK
+
+/* XXX These definitions are obsolete */
+
+#define DM0_CICLAMP     BIT(20)
+#define DM0_ENDPTFILTER BIT(21)
+
+#else
+
+/* XXX These are according to 11/2/92 spec */
+
+#define DM0_XYOFFSET    BIT(20)
+#define DM0_CICLAMP     BIT(21)
+#define DM0_ENDPTFILTER BIT(22)
+
+#endif	/* OLDJUNK */
+/* New Feature in REX REV B */
+#define	DM0_YSTRIDE	BIT(23)
+
+#define DM1_PLANES_SHIFT	0
+#define DM1_PLANES	0x7		/* planes(2:0)	*/
+#	define DM1_NOPLANES	0x0
+#	define DM1_RGBPLANES	0x1
+#	define DM1_RGBAPLANES	0x2
+#	define DM1_OLAYPLANES	0x4
+#	define DM1_PUPPLANES	0x5
+#	define DM1_CIDPLANES	0x6
+#define DM1_DRAWDEPTH_SHIFT	3	/* drawdepth(1:0)	*/
+#define DM1_DRAWDEPTH_MASK      (3 << DM1_DRAWDEPTH_SHIFT)
+#	define DM1_DRAWDEPTH	(0x3 << DM1_DRAWDEPTH_SHIFT)	
+#	define DM1_DRAWDEPTH4	(0x0 << DM1_DRAWDEPTH_SHIFT)
+#	define DM1_DRAWDEPTH8	(0x1 << DM1_DRAWDEPTH_SHIFT)
+#	define DM1_DRAWDEPTH12	(0x2 << DM1_DRAWDEPTH_SHIFT)
+#	define DM1_DRAWDEPTH24	(0x3 << DM1_DRAWDEPTH_SHIFT)
+#define DM1_DBLSRC		BIT(5)
+#define DM1_YFLIP		BIT(6)
+#define DM1_RWPACKED		BIT(7)
+#define DM1_HOSTDEPTH_SHIFT 	8	/* hostdepth(1:0)	*/
+#define DM1_HOSTDEPTH_MASK      (3 << DM1_HOSTDEPTH_SHIFT)
+#	define DM1_HOSTDEPTH	(0x3 << DM1_HOSTDEPTH_SHIFT)
+#	define DM1_HOSTDEPTH4	(0x0 << DM1_HOSTDEPTH_SHIFT)
+#	define DM1_HOSTDEPTH8	(0x1 << DM1_HOSTDEPTH_SHIFT)
+#	define DM1_HOSTDEPTH12	(0x2 << DM1_HOSTDEPTH_SHIFT)
+#	define DM1_HOSTDEPTH32	(0x3 << DM1_HOSTDEPTH_SHIFT)
+#define DM1_RWDOUBLE		BIT(10)
+#define DM1_SWAPENDIAN		BIT(11)
+#define DM1_COLORCOMPARE_SHIFT  12	/* compare (2:0)	*/
+#define DM1_COLORCOMPARE_MASK  (7 << DM1_COLORCOMPARE_SHIFT)
+#	define DM1_COLORCOMPARE (0x7 << DM1_COLORCOMPARE_SHIFT)
+#	define DM1_COLORCOMPLT	BIT(12)
+#	define DM1_COLORCOMPEQ	BIT(13)
+#	define DM1_COLORCOMPGT	BIT(14)
+#define DM1_RGBMODE		BIT(15)
+#define DM1_ENDITHER		BIT(16)
+#define DM1_FASTCLEAR		BIT(17)
+#define DM1_ENBLEND		BIT(18)
+#define DM1_SF_SHIFT		19	/* sfactor(2:0)	*/
+#define DM1_SF_MASK   		(7 << DM1_SF_SHIFT)
+#	define DM1_SF		(0x7 << DM1_SF_SHIFT)
+#	define DM1_SF_ZERO	(0x0 << DM1_SF_SHIFT)
+#	define DM1_SF_ONE	(0x1 << DM1_SF_SHIFT)
+#	define DM1_SF_DC	(0x2 << DM1_SF_SHIFT)
+#	define DM1_SF_MDC	(0x3 << DM1_SF_SHIFT)
+#	define DM1_SF_SA	(0x4 << DM1_SF_SHIFT)
+#	define DM1_SF_MSA	(0x5 << DM1_SF_SHIFT)
+#define DM1_DF_SHIFT		22	/* dfactor(2:0)	*/
+#define DM1_DF_MASK     (7 << DM1_DF_SHIFT)
+#	define DM1_DF		(0x7 << DM1_DF_SHIFT)
+#	define DM1_DF_ZERO	(0x0 << DM1_DF_SHIFT)
+#	define DM1_DF_ONE	(0x1 << DM1_DF_SHIFT)
+#	define DM1_DF_SC	(0x2 << DM1_DF_SHIFT)
+#	define DM1_DF_MSC	(0x3 << DM1_DF_SHIFT)
+#	define DM1_DF_SA	(0x4 << DM1_DF_SHIFT)
+#	define DM1_DF_MSA	(0x5 << DM1_DF_SHIFT)
+#define DM1_ENBACKBLEND		BIT(25)
+#define DM1_ENPREFETCH		BIT(26)
+#define DM1_BLENDALPHA		BIT(27)
+#define DM1_LO_SHIFT		28	/* logicop(3:0)	*/
+#	define DM1_LO		(0xF << DM1_LO_SHIFT)
+#       define DM1_LO_MASK      DM1_LO
+#	define DM1_LO_ZERO	(0x0 << DM1_LO_SHIFT)
+#	define DM1_LO_AND	(0x1 << DM1_LO_SHIFT)
+#	define DM1_LO_ANDR	(0x2 << DM1_LO_SHIFT)
+#	define DM1_LO_SRC	(0x3 << DM1_LO_SHIFT)
+#	define DM1_LO_ANDI	(0x4 << DM1_LO_SHIFT)
+#	define DM1_LO_DST	(0x5 << DM1_LO_SHIFT)
+#	define DM1_LO_XOR	(0x6 << DM1_LO_SHIFT)
+#	define DM1_LO_OR	(0x7 << DM1_LO_SHIFT)
+#	define DM1_LO_NOR	(0x8 << DM1_LO_SHIFT)
+#	define DM1_LO_XNOR	(0x9 << DM1_LO_SHIFT)
+#	define DM1_LO_NDST	(0xa << DM1_LO_SHIFT)
+#	define DM1_LO_ORR	(0xb << DM1_LO_SHIFT)
+#	define DM1_LO_NSRC	(0xc << DM1_LO_SHIFT)
+#	define DM1_LO_ORI	(0xd << DM1_LO_SHIFT)
+#	define DM1_LO_NAND	(0xe << DM1_LO_SHIFT)
+#	define DM1_LO_ONE	(0xf << DM1_LO_SHIFT)
+
+
+
+/*
+ * Clipmode register bits
+ */
+
+#define SMASK0	BIT(0)
+#define SMASK1	BIT(1)
+#define SMASK2	BIT(2)
+#define SMASK3	BIT(3)
+#define SMASK4	BIT(4)
+#define ALL_SMASKS	31
+
+#define CM_CIDMATCH_SHIFT       9
+#define CM_CIDMATCH_MASK        (0xf << CM_CIDMATCH_SHIFT)
+
+
+/*
+ * Status register bits
+ */
+
+#define REX3VERSION_MASK 7
+#define GFXBUSY         BIT(3)
+#define BACKBUSY        BIT(4)
+#define VRINT           BIT(5)
+#define VIDEOINT        BIT(6)
+#define GFIFO_LEVEL_SHIFT       7
+#define GFIFO_LEVEL_MASK        (0x3f << GFIFO_LEVEL_SHIFT)
+#define BFIFO_LEVEL_SHIFT       13
+#define BFIFO_LEVEL_MASK        (0x1f << BFIFO_LEVEL_SHIFT)
+#define BFIFO_INT        BIT(18)
+#define GFIFO_INT        BIT(19)
+
+
+/*
+ * Config register bits
+ */
+
+#define GIO32MODE       BIT(0)
+#define BUSWIDTH        BIT(1)
+#define EXTREGXCVR      BIT(2)
+#define BFIFODEPTH_SHIFT        3
+#define BFIFODEPTH_MASK         (0xf << BFIFODEPTH_SHIFT)
+#define BFIFOABOVEINT   BIT(7)
+#define GFIFODEPTH_SHIFT        8
+#define GFIFODEPTH_MASK         (0x1f << GFIFODEPTH_SHIFT)
+#define GFIFOABOVEINT   BIT(13)
+#define TIMEOUT_SHIFT   14
+#define TIMEOUT_MASK    (7 << TIMEOUT_SHIFT)
+#define VREFRESH_SHIFT  17
+#define VREFRESH_MASK   (0x7 << VREFRESH_SHIFT)
+#define FB_TYPE         BIT(20)
+
+/*
+ * Display Control Bus (DCB) macros
+ */
+
+#define DCB_DATAWIDTH_MASK  (0x3)
+#define DCB_ENDATAPACK      BIT(2)
+#define DCB_ENCRSINC        BIT(3)
+#define DCB_CRS_SHIFT    4
+#define DCB_CRS_MASK     (0x7 << DCB_CRS_SHIFT)
+#define DCB_ADDR_SHIFT   7
+#define DCB_ADDR_MASK    (0xf << DCB_ADDR_SHIFT)
+#define DCB_ENSYNCACK       BIT(11)
+#define DCB_ENASYNCACK      BIT(12)
+#define DCB_CSWIDTH_SHIFT   13
+#define DCB_CSWIDTH_MASK    (0x1f << CSWIDTH_SHIFT)
+#define DCB_CSHOLD_SHIFT    18
+#define DCB_CSHOLD_MASK     (0x1f << CSHOLD_SHIFT)
+#define DCB_CSSETUP_SHIFT   23
+#define DCB_CSSETUP_MASK    (0x1f << CSSETUP_SHIFT)
+#define DCB_SWAPENDIAN      BIT(28)
+
+
+/*
+ * Some values for DCBMODE fields
+ */
+#define DCB_DATAWIDTH_4		0x0
+#define DCB_DATAWIDTH_1		0x1
+#define DCB_DATAWIDTH_2		0x2
+#define DCB_DATAWIDTH_3		0x3
+
+
+/*
+ * DCB_ADDR values to select the various dcb slave devices
+ */
+#define DCB_VC2          (0 << DCB_ADDR_SHIFT)
+#define DCB_CMAP_ALL     (1 << DCB_ADDR_SHIFT)
+#define DCB_CMAP0        (2 << DCB_ADDR_SHIFT)
+#define DCB_CMAP1        (3 << DCB_ADDR_SHIFT)
+#define DCB_XMAP_ALL     (4 << DCB_ADDR_SHIFT)
+#define DCB_XMAP0        (5 << DCB_ADDR_SHIFT)
+#define DCB_XMAP1        (6 << DCB_ADDR_SHIFT)
+#define DCB_BT445        (7 << DCB_ADDR_SHIFT)
+#define DCB_VCC1         (8 << DCB_ADDR_SHIFT)
+#define DCB_VAB1         (9 << DCB_ADDR_SHIFT)
+#define DCB_LG3_BDVERS0      (10 << DCB_ADDR_SHIFT)
+#define DCB_LG3_ICS1562      (11 << DCB_ADDR_SHIFT)
+#define DCB_RESERVED     (15 << DCB_ADDR_SHIFT)
+
+/*
+ * New DCB Addresses which are used in (new) Indigo2 Video and Galileo 1.5
+ * since these boards have to work with Mardi Gras also. Yet, these
+ * are not necessarily the MGRAS address, these translate to the Mardi Gras
+ * addresses when the lower 2 bits are swapped (which will happen on 
+ * the Newport to new video board flex cable).
+ */
+#define DCB_VAB1_NEW     (9 << DCB_ADDR_SHIFT)
+/*
+ * While the Presenter is currently using address 12 and
+ * conflicting with the CC1, it has been changed for Mardi Gras
+ * To use the new video boards with Newport (an unreleased product)
+ * the presenter probe must be disabled by changing the presenter
+ * DCB address in gfx/kern/sys/pcd.h (and possibly
+ * lotus/stand/arcs/lib/libsk/graphics/NEWPORT/pcd.h), so 
+ * it is probed at address 11.  This will of course not work with
+ * the presenter card but it will allow you to test new video
+ * boards will Newport
+ */
+
+#define DCB_VCC1_NEW     (12 << DCB_ADDR_SHIFT)
+/*#define DCB_VCC1_NEW     (8 << DCB_ADDR_SHIFT)*/
+
+/*
+ * Addresses being used for Galileo 1.5.
+ */
+#define DCB_VCC1_GAL     (8 << DCB_ADDR_SHIFT) /* was 12 and will return */
+#define DCB_VAB1_GAL     (9 << DCB_ADDR_SHIFT)
+#define DCB_TMI_CSC      (13 << DCB_ADDR_SHIFT)
+#define DCB_GAL          (14 << DCB_ADDR_SHIFT)
+
+/*
+ * LG3 - (Newport for Fullhouse) board defines
+ */
+/* Version 0 register */
+#define LG3_VC2_UNRESET BIT(0)
+#define	LG3_GFX_UNRESET	BIT(1)
+#define LG3_PLL_UNRESET BIT(2)
+#define LG3_DLHD_MASTER BIT(3)
+
+#define LG3_BDVERS_PROTOCOL ((2 << DCB_CSWIDTH_SHIFT) | (1 << DCB_CSHOLD_SHIFT) | (1 << DCB_CSSETUP_SHIFT))
+
+#define lg3BdVersGet(rex3, data)			 		\
+        rex3->set.dcbmode = DCB_LG3_BDVERS0 | \
+		LG3_BDVERS_PROTOCOL | DCB_DATAWIDTH_1 ;			\
+        data = rex3->set.dcbdata0.bybyte.b3
+
+#define lg3BdVersSet(rex3, data)			 		\
+        rex3->set.dcbmode = DCB_LG3_BDVERS0 | \
+		LG3_BDVERS_PROTOCOL | DCB_DATAWIDTH_1 ;		\
+	rex3->set.dcbdata0.bybyte.b3 = (data)
+
+#define Ics1562Set(rex3, data)			 		\
+        rex3->set.dcbmode = DCB_LG3_ICS1562 | LG3_BDVERS_PROTOCOL | DCB_DATAWIDTH_1 ; \
+	rex3->set.dcbdata0.bybyte.b3 = (data)
+
+#define	LG3_BD_001	0x7
+#define	LG3_BD_002	0x0
+/*
+ * Lsmode register bits
+ */
+#define LSRCOUNT_SHIFT  0
+#define LSRCOUNT_MASK   (0xff << LSRCOUNT_SHIFT)
+#define LSREPEAT_SHIFT  8
+#define LSREPEAT_MASK   (0xff << LSREPEAT_SHIFT)
+#define LSRCNTSAVE_SHIFT        16
+#define LSRCNTSAVE_MASK (0xff << LSRCNTSAVE_SHIFT)
+#define LSLENGTH_SHIFT  24
+#define LSLENGTH_MASK   (0xf << LSLENGTH_SHIFT)
+
+#if	defined ( _KERNEL ) && defined ( REX3_RUNTIME_REV_CHECK )
+
+extern void _newport_poll_status (register struct rex3chip *, register int);
+
+#define REX3WAIT(rex3)  _newport_poll_status (rex3, GFXBUSY)
+#define BFIFOWAIT(rex3)  _newport_poll_status (rex3, BACKBUSY)
+
+#else
+
+/* XXX  When we drop support for rex rev b,
+ * change status to ustatus in the macros below.
+ */
+#define REX3WAIT(rex3)  while ((rex3)->p1.set.status & GFXBUSY)
+#define BFIFOWAIT(rex3)  while ((rex3)->p1.set.status & BACKBUSY)
+
+#endif
+
+/*
+ * Legal GIO bus addresses for Newport graphics boards.
+ */
+#define REX3_GIO_ADDR_0         0x1f0f0000
+#define REX3_GIO_ADDR_1         0x1f4f0000
+#define REX3_GIO_ADDR_2         0x1f8f0000
+#define REX3_GIO_ADDR_3         0x1fcf0000
+
+#define NG1_XSIZE       1280    /* screen size in x */
+#define NG1_YSIZE       1024    /* screen size in y */
+
+/*
+ * XXX Correct values TBD.  Depends on video timing
+ */
+#define CURSOR_XOFF 29
+#define CURSOR_YOFF 31
+
+#ifdef _STANDALONE
+struct rex3chip;
+struct ng1_info;
+void Ng1RegisterInit(struct rex3chip *, struct ng1_info *);
+extern int ng1checkboard(void);
+extern void vc2LoadSRAM(struct rex3chip *, unsigned short *,
+		unsigned int , unsigned int);
+#endif
+
+#endif /* __SYS_NG1HW_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/offset.h linux.pre11.3/include/asm-mips/offset.h
--- linux.vanilla/include/asm-mips/offset.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/offset.h	Mon Jul 19 23:26:46 1999
@@ -51,36 +51,36 @@
 #define TASK_NEED_RESCHED  20
 #define TASK_COUNTER       24
 #define TASK_PRIORITY      28
-#define TASK_MM            928
+#define TASK_MM            920
 
 /* MIPS specific thread_struct offsets. */
-#define THREAD_REG16   568
-#define THREAD_REG17   572
-#define THREAD_REG18   576
-#define THREAD_REG19   580
-#define THREAD_REG20   584
-#define THREAD_REG21   588
-#define THREAD_REG22   592
-#define THREAD_REG23   596
-#define THREAD_REG29   600
-#define THREAD_REG30   604
-#define THREAD_REG31   608
-#define THREAD_STATUS  612
-#define THREAD_FPU     616
-#define THREAD_BVADDR  880
-#define THREAD_BUADDR  884
-#define THREAD_ECODE   888
-#define THREAD_TRAPNO  892
-#define THREAD_PGDIR   896
-#define THREAD_MFLAGS  900
-#define THREAD_CURDS   904
-#define THREAD_TRAMP   908
-#define THREAD_OLDCTX  912
+#define THREAD_REG16   560
+#define THREAD_REG17   564
+#define THREAD_REG18   568
+#define THREAD_REG19   572
+#define THREAD_REG20   576
+#define THREAD_REG21   580
+#define THREAD_REG22   584
+#define THREAD_REG23   588
+#define THREAD_REG29   592
+#define THREAD_REG30   596
+#define THREAD_REG31   600
+#define THREAD_STATUS  604
+#define THREAD_FPU     608
+#define THREAD_BVADDR  872
+#define THREAD_BUADDR  876
+#define THREAD_ECODE   880
+#define THREAD_TRAPNO  884
+#define THREAD_PGDIR   888
+#define THREAD_MFLAGS  892
+#define THREAD_CURDS   896
+#define THREAD_TRAMP   900
+#define THREAD_OLDCTX  904
 
 /* Linux mm_struct offsets. */
-#define MM_COUNT      12
-#define MM_PGD        8
-#define MM_CONTEXT    32
+#define MM_COUNT      16
+#define MM_PGD        12
+#define MM_CONTEXT    36
 
 /* Linux sigcontext offsets. */
 #define SC_REGMASK    0
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/page.h linux.pre11.3/include/asm-mips/page.h
--- linux.vanilla/include/asm-mips/page.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/page.h	Mon Jul 19 23:26:46 1999
@@ -1,11 +1,12 @@
-/*
+/* $Id: page.h,v 1.6 1999/01/04 16:09:24 ralf Exp $
+ *
  * Definitions for page handling
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1994 - 1998 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_PAGE_H
 #define __ASM_MIPS_PAGE_H
@@ -19,10 +20,8 @@
 
 #define STRICT_MM_TYPECHECKS
 
-#ifndef __LANGUAGE_ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
 
-#define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
-#define free_user_page(page, addr)	free_page(addr)
 extern void (*clear_page)(unsigned long page);
 extern void (*copy_page)(unsigned long to, unsigned long from);
 
@@ -66,7 +65,7 @@
 
 #endif /* !defined (STRICT_MM_TYPECHECKS) */
 
-#endif /* __LANGUAGE_ASSEMBLY__ */
+#endif /* _LANGUAGE_ASSEMBLY */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
@@ -78,8 +77,7 @@
 #define PAGE_OFFSET	0x80000000UL
 #define __pa(x)		((unsigned long) (x) - PAGE_OFFSET)
 #define __va(x)		((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_MASK        0x1fffffffUL
-#define MAP_NR(addr)	((((unsigned long)(addr)) & MAP_MASK) >> PAGE_SHIFT)
+#define MAP_NR(addr)	(__pa(addr) >> PAGE_SHIFT)
 
 #endif /* defined (__KERNEL__) */
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/pci.h linux.pre11.3/include/asm-mips/pci.h
--- linux.vanilla/include/asm-mips/pci.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/pci.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: pci.h,v 1.4 1998/05/08 01:44:30 ralf Exp $
+/* $Id: pci.h,v 1.5 1999/01/04 16:09:24 ralf Exp $
  *
  * 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,7 +10,7 @@
 #define __ASM_MIPS_PCI_H
 
 struct pci_ops {
-	unsigned long (*pcibios_fixup) (void);
+	void (*pcibios_fixup) (void);
 	int (*pcibios_read_config_byte) (unsigned char bus,
 	                                 unsigned char dev_fn,
 	                                 unsigned char where,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/pgtable.h linux.pre11.3/include/asm-mips/pgtable.h
--- linux.vanilla/include/asm-mips/pgtable.h	Wed Mar 24 10:55:25 1999
+++ linux.pre11.3/include/asm-mips/pgtable.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.19 1998/10/26 19:59:39 davem Exp $
+/* $Id: pgtable.h,v 1.19 1999/06/13 16:35:53 ralf Exp $
  *
  * 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
@@ -129,7 +129,7 @@
 #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
 
-#define _PAGE_CHG_MASK  (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
 
 #define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
@@ -356,7 +356,7 @@
 
 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 {
-	return __pte((physpage - PAGE_OFFSET) | pgprot_val(pgprot));
+	return __pte(physpage | pgprot_val(pgprot));
 }
 
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
@@ -580,9 +580,9 @@
 /*
  * Kernel with 32 bit address space
  */
-#define SWP_TYPE(entry) (((entry) >> 8) & 0x7f)
-#define SWP_OFFSET(entry) ((entry) >> 15)
-#define SWP_ENTRY(type,offset) (((type) << 8) | ((offset) << 15))
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x3f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
 
 #define module_map      vmalloc
 #define module_unmap    vfree
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/posix_types.h linux.pre11.3/include/asm-mips/posix_types.h
--- linux.vanilla/include/asm-mips/posix_types.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/posix_types.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: posix_types.h,v 1.5 1998/08/17 13:59:34 ralf Exp $
+/* $Id: posix_types.h,v 1.5 1998/08/25 09:22:00 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/prctl.h linux.pre11.3/include/asm-mips/prctl.h
--- linux.vanilla/include/asm-mips/prctl.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/prctl.h	Mon Jul 19 23:26:46 1999
@@ -3,7 +3,7 @@
  *
  * The IRIX kernel maps a page at PRDA_ADDRESS with the
  * contents of prda and fills it the bits on prda_sys.
- * $Id: prctl.h,v 1.1 1997/12/02 02:28:28 ralf Exp $
+ * $Id: prctl.h,v 1.1 1997/09/21 22:27:19 miguel Exp $
  */
 
 #ifndef __PRCTL_H__
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/processor.h linux.pre11.3/include/asm-mips/processor.h
--- linux.vanilla/include/asm-mips/processor.h	Tue Jan 19 02:57:37 1999
+++ linux.pre11.3/include/asm-mips/processor.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.18 1998/10/14 20:31:12 ralf Exp $
+/* $Id: processor.h,v 1.15 1999/02/15 02:22:12 ralf Exp $
  *
  * 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
@@ -174,6 +174,7 @@
 
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(nr, p, mm) do { } while(0)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/ptrace.h linux.pre11.3/include/asm-mips/ptrace.h
--- linux.vanilla/include/asm-mips/ptrace.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/ptrace.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: ptrace.h,v 1.3 1998/07/09 21:45:21 ralf Exp $
+/* $Id: ptrace.h,v 1.4 1999/01/04 16:09:25 ralf Exp $
  *
  * 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
@@ -15,13 +15,14 @@
 #include <linux/types.h>
 
 /* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
+#define FPR_BASE	32
 #define PC		64
 #define CAUSE		65
-#define MMLO		66
+#define BADVADDR	66
 #define MMHI		67
-#define FPC_CSR		68	/* XXX */
-#define FPC_EIR		69	/* XXX */
-#define FPR_BASE	70	/* XXX */
+#define MMLO		68
+#define FPC_CSR		69
+#define FPC_EIR		70
 
 #ifndef __ASSEMBLY__
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/r4kcache.h linux.pre11.3/include/asm-mips/r4kcache.h
--- linux.vanilla/include/asm-mips/r4kcache.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/r4kcache.h	Mon Jul 19 23:26:46 1999
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r4kcache.h,v 1.7 1997/12/18 13:00:45 ralf Exp $
+ * $Id: r4kcache.h,v 1.5 1998/03/04 05:36:23 ralf Exp $
  *
  * FIXME: Handle split L2 caches.
  */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/resource.h linux.pre11.3/include/asm-mips/resource.h
--- linux.vanilla/include/asm-mips/resource.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/resource.h	Mon Jul 19 23:26:46 1999
@@ -1,11 +1,10 @@
-/*
- * Process resource limits
+/* $Id: resource.h,v 1.2 1999/01/04 16:09:25 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996 by Ralf Baechle
+ * Copyright (C) 1995, 1996, 1998 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_RESOURCE_H
 #define __ASM_MIPS_RESOURCE_H
@@ -35,7 +34,7 @@
 	{LONG_MAX, LONG_MAX},				\
 	{_STK_LIM, _STK_LIM},				\
 	{       0, LONG_MAX},				\
-	{NR_OPEN, NR_OPEN},				\
+	{NR_OPEN,  NR_OPEN},				\
 	{LONG_MAX, LONG_MAX},				\
 	{LONG_MAX, LONG_MAX},				\
 	{MAX_TASKS_PER_USER, MAX_TASKS_PER_USER},	\
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/semaphore-helper.h linux.pre11.3/include/asm-mips/semaphore-helper.h
--- linux.vanilla/include/asm-mips/semaphore-helper.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/semaphore-helper.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,125 @@
+/* $Id: semaphore-helper.h,v 1.2.2.1 1999/06/11 08:47:54 ralf Exp $
+ *
+ * SMP- and interrupt-safe semaphores helper functions.
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ * (C) Copyright 1999 Andrea Arcangeli
+ * (C) Copyright 1999 Ralf Baechle
+ */
+#ifndef __ASM_MIPS_SEMAPHORE_HELPER_H
+#define __ASM_MIPS_SEMAPHORE_HELPER_H
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+static inline void wake_one_more(struct semaphore * sem)
+{
+	atomic_inc(&sem->waking);
+}
+
+static inline int
+waking_non_zero(struct semaphore *sem)
+{
+	int ret, tmp;
+
+	__asm__ __volatile__(
+	"1:\tll\t%1,%2\n\t"
+	"blez\t%1,2f\n\t"
+	"subu\t%0,%1,1\n\t"
+	"sc\t%0,%2\n\t"
+	"beqz\t%0,1b\n\t"
+	"2:"
+	".text"
+	: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
+	: "0"(0));
+
+	return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ *	1	got the lock
+ *	0	go to sleep
+ *	-EINTR	interrupted
+ *
+ * We must undo the sem->count down_interruptible decrement
+ * simultaneously and atomicly with the sem->waking adjustment,
+ * otherwise we can race with wake_one_more.
+ *
+ * This is accomplished by doing a 64-bit ll/sc on the 2 32-bit words.
+ *
+ * This is crazy.  Normally it stricly forbidden to use 64-bit operation
+ * in the 32-bit MIPS kernel.  In this case it's however ok because if an
+ * interrupt has destroyed the upper half of registers sc will fail.
+ */
+static inline int
+waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
+{
+	long ret, tmp;
+
+#ifdef __MIPSEB__
+        __asm__ __volatile__("
+	.set	mips3
+	.set	push
+	.set	noat
+0:	lld	%1,%2
+	li	%0,0
+
+	bltz	%1, 1f
+	dli	$1, 0xffffffff00000000
+	daddu	%1, $1
+	li	%0, 1
+	b	2f
+1:
+
+	beqz	%3, 1f
+	addiu	$1, %1, 1
+	dsll32	$1, $1, 0
+	dsrl32	$1, $1, 0
+	dsrl32	%1, %1, 0
+	dsll32	%1, %1, 0
+	or	%1, $1
+	li	%0, %4
+	b	2f
+1:
+	scd	%1, %2
+2:
+	beqz	%1,0b
+	.set	pop
+	.set	mips0"
+	: "=&r"(ret), "=&r"(tmp), "=m"(*sem)
+	: "r"(signal_pending(tsk)), "i"(-EINTR));
+#endif
+
+#ifdef __MIPSEL__
+#error "FIXME: waking_non_zero_interruptible doesn't support little endian machines yet."
+#endif
+
+	return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ *	1	failed to lock
+ *	0	got the lock
+ *
+ * XXX SMP ALERT
+ */
+#ifdef __SMP__
+#error FIXME, waking_non_zero_trylock is broken for SMP.
+#endif
+static inline int waking_non_zero_trylock(struct semaphore *sem)
+{
+        int ret = 1;
+
+	if (atomic_read(&sem->waking) <= 0)
+		atomic_inc(&sem->count);
+	else {
+		atomic_dec(&sem->waking);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+#endif /* __ASM_MIPS_SEMAPHORE_HELPER_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/semaphore.h linux.pre11.3/include/asm-mips/semaphore.h
--- linux.vanilla/include/asm-mips/semaphore.h	Tue Jan 19 02:57:37 1999
+++ linux.pre11.3/include/asm-mips/semaphore.h	Mon Jul 19 23:26:46 1999
@@ -1,11 +1,13 @@
-/*
+/* $Id: semaphore.h,v 1.5.2.2 1999/06/17 12:09:42 ralf Exp $
+ *
  * SMP- and interrupt-safe semaphores..
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * (C) Copyright 1996  Linus Torvalds, Ralf Baechle
+ * (C) Copyright 1996  Linus Torvalds
+ * (C) Copyright 1998, 1999  Ralf Baechle
  */
 #ifndef __ASM_MIPS_SEMAPHORE_H
 #define __ASM_MIPS_SEMAPHORE_H
@@ -23,44 +25,15 @@
 #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
 #define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
 
-extern void __down(struct semaphore * sem);
-extern int  __down_interruptible(struct semaphore * sem);
-extern void __up(struct semaphore * sem);
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
 
 extern spinlock_t semaphore_wake_lock;
 
 #define sema_init(sem, val)	atomic_set(&((sem)->count), val)
 
-/*
- * These two _must_ execute atomically wrt each other.
- *
- * This is trivially done with load_locked/store_cond,
- * which we have.  Let the rest of the losers suck eggs.
- */
-
-static inline void wake_one_more(struct semaphore * sem)
-{
-	atomic_inc(&sem->waking);
-}
-
-static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
-{
-	int ret, tmp;
-
-	__asm__ __volatile__(
-	"1:\tll\t%1,%2\n"
-	"blez\t%1,2f\n\t"
-	"subu\t%0,%1,1\n\t"
-	"sc\t%0,%2\n\t"
-	"beqz\t%0,1b\n\t"
-	"2:"
-	".text"
-	: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
-	: "0"(0));
-
-	return ret;
-}
-
 extern inline void down(struct semaphore * sem)
 {
 	if (atomic_dec_return(&sem->count) < 0)
@@ -72,6 +45,50 @@
 	int ret = 0;
 	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
+	return ret;
+}
+
+/*
+ * down_trylock returns 0 on success, 1 if we failed to get the lock.
+ *
+ * We must manipulate count and waking simultaneously and atomically.
+ * Do this by using ll/sc on the pair of 32-bit words.
+ */
+extern inline int down_trylock(struct semaphore * sem)
+{
+	long ret, tmp, tmp2, sub;
+
+#ifdef __MIPSEB__
+	__asm__ __volatile__("
+			.set	mips3
+		0:	lld	%1, %4
+			dli	%3, 0x0000000100000000
+			sltu	%0, %1, $0
+
+			bltz	%1, 1f
+			move	%3, $0
+		1:
+
+			sltu	%2, %1, $0
+			and	%0, %0, %2
+			bnez	%0, 2f
+
+			subu	%0, %3
+			scd	%1, %4
+
+			beqz	%1, 0b
+		2:
+
+			.set	mips0"
+		: "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), "=&r"(sub)
+		: "m"(*sem)
+		: "memory");
+#endif
+
+#ifdef __MIPSEL__
+#error "FIXME: down_trylock doesn't support little endian machines yet."
+#endif
+
 	return ret;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/serial.h linux.pre11.3/include/asm-mips/serial.h
--- linux.vanilla/include/asm-mips/serial.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/serial.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: serial.h,v 1.3 1998/08/28 15:55:38 ralf Exp $
+/* $Id: serial.h,v 1.1 1998/05/04 12:43:16 ralf Exp $
  *
  * include/asm-mips/serial.h
  */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/sgialib.h linux.pre11.3/include/asm-mips/sgialib.h
--- linux.vanilla/include/asm-mips/sgialib.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/sgialib.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: sgialib.h,v 1.2 1998/07/08 16:01:13 ralf Exp $
+/* $Id: sgialib.h,v 1.4 1999/02/25 20:55:07 tsbogend Exp $
  * sgialib.h: SGI ARCS firmware interface library for the Linux kernel.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -14,6 +14,9 @@
 extern int prom_argc;
 extern char **prom_argv, **prom_envp;
 
+extern int prom_flags;
+#define PROM_FLAG_ARCS  1
+
 /* Init the PROM library and it's internal data structures.  Called
  * at boot time from head.S before start_kernel is invoked.
  */
@@ -31,6 +34,7 @@
 struct prom_pmemblock {
 	unsigned long base; /* Within KSEG0. */
 	unsigned int size;  /* In bytes. */
+        unsigned int type;  /* free or prom memory */
 };
 
 /* Get next memory descriptor after CURR, returns first descriptor
@@ -71,10 +75,10 @@
 extern long prom_delcomponent(pcomponent *this);
 extern pcomponent *prom_componentbypath(char *path);
 
-/* This is called at prom_init time to setup the tags which the
- * MIPS kernel setup code wants to diddle with. 
+/* This is called at prom_init time to identify the
+ * ARC architecture we are running on
  */
-extern void prom_setup_archtags(void);
+extern void prom_identify_arch(void);
 
 /* Environemt variable routines. */
 extern char *prom_getenv(char *name);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/sgiarcs.h linux.pre11.3/include/asm-mips/sgiarcs.h
--- linux.vanilla/include/asm-mips/sgiarcs.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/sgiarcs.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: sgiarcs.h,v 1.2 1998/07/08 16:01:57 ralf Exp $
+/* $Id: sgiarcs.h,v 1.3 1999/02/25 20:55:08 tsbogend Exp $
  *
  * SGI ARCS firmware interface defines.
  *
@@ -88,19 +88,36 @@
 };
 
 /* ARCS prom memory descriptors. */
-enum linux_memtypes {
-	eblock,  /* exception block */
-	rvpage,  /* ARCS romvec page */
-	fcontig, /* Contiguous and free */
-	free,    /* Generic free memory */
-	bmem,    /* Borken memory, don't use */
-	prog,    /* A loaded program resides here */
-	atmp,    /* ARCS temporary storage area, wish Sparc OpenBoot told this */
-	aperm,   /* ARCS permanent storage... */
+enum arcs_memtypes {
+	arcs_eblock,  /* exception block */
+	arcs_rvpage,  /* ARCS romvec page */
+	arcs_fcontig, /* Contiguous and free */
+	arcs_free,    /* Generic free memory */
+	arcs_bmem,    /* Borken memory, don't use */
+	arcs_prog,    /* A loaded program resides here */
+	arcs_atmp,    /* ARCS temporary storage area, wish Sparc OpenBoot told this */
+	arcs_aperm,   /* ARCS permanent storage... */
+};
+
+/* ARC has slightly different types than ARCS */
+enum arc_memtypes {
+	arc_eblock,  /* exception block */
+	arc_rvpage,  /* romvec page */
+	arc_free,    /* Generic free memory */
+	arc_bmem,    /* Borken memory, don't use */
+	arc_prog,    /* A loaded program resides here */
+	arc_atmp,    /* temporary storage area */
+	arc_aperm,   /* permanent storage */
+	arc_fcontig, /* Contiguous and free */    
+};
+
+union linux_memtypes {
+    enum arcs_memtypes arcs;
+    enum arc_memtypes arc;
 };
 
 struct linux_mdesc {
-	enum linux_memtypes type;
+        union linux_memtypes type;
 	unsigned long base;
 	unsigned long pages;
 };
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/sgihpc.h linux.pre11.3/include/asm-mips/sgihpc.h
--- linux.vanilla/include/asm-mips/sgihpc.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/sgihpc.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: sgihpc.h,v 1.4 1998/09/16 22:52:42 ralf Exp $
+/* $Id: sgihpc.h,v 1.6 1999/04/01 23:24:00 ulfc Exp $
  *
  * sgihpc.h: Various HPC I/O controller defines.  The HPC is basically
  *           the approximate functional equivalent of the Sun SYSIO
@@ -178,8 +178,7 @@
 
 struct hpc3_regs {
 	/* First regs for the PBUS 8 dma channels. */
-	struct hpc3_pbus_dmacregs pbdma0, pbdma1, pbdma2, pbdma3;
-	struct hpc3_pbus_dmacregs pbdma4, pbdma5, pbdma6, pbdma7;
+	struct hpc3_pbus_dmacregs pbdma[8];
 
 	/* Now the HPC scsi registers, we get two scsi reg sets. */
 	struct hpc3_scsiregs scsi_chan0, scsi_chan1;
@@ -191,7 +190,7 @@
 	 * via PIO accesses.  Under normal operation we never stick
 	 * our grubby paws in here so it's just padding.
 	 */
-	char _unused1[PAGE_SIZE * 16];
+	char _unused1[PAGE_SIZE * 24];
 
 	/* HPC3 irq status regs.  Due to a peculiar bug you need to
 	 * look at two different register addresses to get at all of
@@ -223,15 +222,20 @@
 #define HPC3_GIOESTAT_PIDMSK  0x3f700  /* DMA channel parity identifier */
 
 	/* Now direct PIO per-HPC3 peripheral access to external regs. */
-	char _unused2[0x13ff0]; /* Trust me... */
+	char _unused2[0x13fec]; /* Trust me... */
 	hpcreg scsi0_ext[256];  /* SCSI channel 0 external regs */
 	char _unused3[0x07c00]; /* Trust me... */
 	hpcreg scsi1_ext[256];  /* SCSI channel 1 external regs */
 	char _unused4[0x07c00]; /* It'll only hurt a little... */
 
+	/* Did DaveM forget the ethernet external regs?
+	 * Anyhow, they're not here and we need some padding instead.
+	 */
+	char _unused5[0x04000]; /* It'll hurt a lot if you leave this out */
+
 	/* Per-peripheral device external registers and dma/pio control. */
-	hpcreg pbus_extregs[256][10]; /* 2nd indice indexes controller */
-	hpcreg pbus_dmacfgs[128][10]; /* 2nd indice indexes controller */
+	hpcreg pbus_extregs[16][256]; /* 2nd indice indexes controller */
+	hpcreg pbus_dmacfgs[8][128]; /* 2nd indice indexes controller */
 #define HPC3_PIODCFG_D3R    0x00000001 /* Cycles to spend in D3 for reads */
 #define HPC3_PIODCFG_D4R    0x0000001e /* Cycles to spend in D4 for reads */
 #define HPC3_PIODCFG_D5R    0x000001e0 /* Cycles to spend in D5 for reads */
@@ -258,15 +262,15 @@
 	hpcreg pbus_promwe;     /* PROM write enable register */
 #define HPC3_PROM_WENAB     0x1 /* Enable writes to the PROM */
 
-	char _unused5[0x800 - sizeof(hpcreg)];
+	char _unused6[0x800 - sizeof(hpcreg)];
 	hpcreg pbus_promswap;   /* Chip select swap reg */
 #define HPC3_PROM_SWAP      0x1 /* invert GIO addr bit to select prom0 or prom1 */
 
-	char _unused6[0x800 - sizeof(hpcreg)];
+	char _unused7[0x800 - sizeof(hpcreg)];
 	hpcreg pbus_gout;       /* PROM general purpose output reg */
 #define HPC3_PROM_STAT      0x1 /* General purpose status bit in gout */
 
-	char _unused7[0x1000 - sizeof(hpcreg)];
+	char _unused8[0x1000 - sizeof(hpcreg)];
 	hpcreg pbus_promram[16384]; /* 64k of PROM battery backed ram */
 };
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/sgint23.h linux.pre11.3/include/asm-mips/sgint23.h
--- linux.vanilla/include/asm-mips/sgint23.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/sgint23.h	Mon Jul 19 23:26:46 1999
@@ -1,7 +1,8 @@
-/* $Id: sgint23.h,v 1.2 1998/03/11 11:58:36 ralf Exp $
+/* $Id: sgint23.h,v 1.3 1999/05/07 22:35:37 ulfc Exp $
  * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - INT2 corrections
  */
 #ifndef _MIPS_SGINT23_H
 #define _MIPS_SGINT23_H
@@ -20,7 +21,7 @@
 #define SGINT_END      52  /* End of 'spaces' */
 
 /* INT2 occupies HPC PBUS slot 4, INT3 uses slot 6. */
-#define SGI_INT2_BASE 0x1fb80100 /* physical */
+#define SGI_INT2_BASE 0x1fbd9000 /* physical */
 #define SGI_INT3_BASE 0x1fbd9880 /* physical */
 
 struct sgi_ioc_ints {
@@ -128,6 +129,10 @@
 
 #define SGINT_TCSAMP_COUNTER  10255
 
+/* FIXME: What does this really look like?  It was written to have
+ * 17 registers, but there are only 16 in my Indigo2.
+ * I guessed at which one to remove...  	- andrewb
+ */
 struct sgi_int2_regs {
 	struct sgi_ioc_ints ints;
 
@@ -147,8 +152,11 @@
 #endif
 #define INT2_TCLEAR_T0CLR      0x1        /* Clear timer0 IRQ */
 #define INT2_TCLEAR_T1CLR      0x2        /* Clear timer1 IRQ */
-
-	unsigned long _unused[3];
+/* I am guesing there are only two unused registers here 
+ * but I could be wrong...			- andrewb
+ */
+/*	unsigned long _unused[3]; */
+	unsigned long _unused[2];
 	struct sgi_ioc_timers timers;
 };
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/shmparam.h linux.pre11.3/include/asm-mips/shmparam.h
--- linux.vanilla/include/asm-mips/shmparam.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/shmparam.h	Mon Jul 19 23:26:46 1999
@@ -33,7 +33,9 @@
  * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
  */
 
-#define SHMMAX 0x1000000		/* max shared seg size (bytes) */
+#define SHMMAX 0x2000000		/* max shared seg size (bytes) */
+/* Try not to change the default shipped SHMMAX - people rely on it */
+
 #define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
 #define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
 #define SHMALL				/* max shm system wide (pages) */ \
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/sigcontext.h linux.pre11.3/include/asm-mips/sigcontext.h
--- linux.vanilla/include/asm-mips/sigcontext.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/sigcontext.h	Mon Jul 19 23:26:46 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: sigcontext.h,v 1.5 1997/12/14 18:57:19 ralf Exp $
+ * $Id: sigcontext.h,v 1.5 1997/12/16 05:36:43 ralf Exp $
  */
 #ifndef __ASM_MIPS_SIGCONTEXT_H
 #define __ASM_MIPS_SIGCONTEXT_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/siginfo.h linux.pre11.3/include/asm-mips/siginfo.h
--- linux.vanilla/include/asm-mips/siginfo.h	Wed Apr 28 19:14:33 1999
+++ linux.pre11.3/include/asm-mips/siginfo.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.4 1998/08/28 16:23:06 ralf Exp $
+/* $Id: siginfo.h,v 1.4 1999/06/13 16:35:54 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/signal.h linux.pre11.3/include/asm-mips/signal.h
--- linux.vanilla/include/asm-mips/signal.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/signal.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: signal.h,v 1.4 1998/08/18 20:46:42 ralf Exp $
+/* $Id: signal.h,v 1.5 1998/08/25 09:22:01 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/smplock.h linux.pre11.3/include/asm-mips/smplock.h
--- linux.vanilla/include/asm-mips/smplock.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/smplock.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id$
+/* $Id: smplock.h,v 1.1 1998/08/25 09:22:02 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/sni.h linux.pre11.3/include/asm-mips/sni.h
--- linux.vanilla/include/asm-mips/sni.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/sni.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: sni.h,v 1.2 1998/09/16 22:52:43 ralf Exp $
+/* $Id: sni.h,v 1.3 1999/01/04 16:09:26 ralf Exp $
  *
  * SNI specific definitions
  *
@@ -69,10 +69,10 @@
 #define PCIMT_PWDN		0xbfdf0000
 
 /*
- * Interrupt 0-16 are reserved for PCI and EISA interrupts.  The
- * interrupts from 16 are assigned to the other interrupts generated
- * by the PCI chipset.
+ * Interrupt 0-16 are EISA interrupts.  Interrupts from 16 on are assigned
+ * to the other interrupts generated by ASIC PCI.
  */
+#define PCIMT_KEYBOARD_IRQ	 1
 #define PCIMT_IRQ_ETHERNET	16
 #define PCIMT_IRQ_TEMPERATURE	17
 #define PCIMT_IRQ_EISA_NMI	18
@@ -89,9 +89,7 @@
  */
 #define PCIMT_EISA_BASE		0xb0000000
 
-/*
- * The keyboard interrupt is an ISA interrupt
- */
-#define SNI_KEYBOARD_IRQ 1
+/* PCI EISA Interrupt acknowledge  */
+#define PCIMT_INT_ACKNOWLEDGE	0xba000000
 
 #endif /* __ASM_MIPS_SNI_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/socket.h linux.pre11.3/include/asm-mips/socket.h
--- linux.vanilla/include/asm-mips/socket.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/socket.h	Mon Jul 19 23:26:46 1999
@@ -1,5 +1,5 @@
 /*
- * $Id: socket.h,v 1.5 1998/03/15 09:52:54 ralf Exp $
+ * $Id: socket.h,v 1.5 1998/03/17 22:16:17 ralf Exp $
  */
 #ifndef __ASM_MIPS_SOCKET_H
 #define __ASM_MIPS_SOCKET_H
@@ -13,6 +13,7 @@
  */
 #define SOL_SOCKET	0xffff
 
+
 #define SO_DEBUG	0x0001	/* Record debugging information.  */
 #define SO_REUSEADDR	0x0004	/* Allow reuse of local addresses.  */
 #define SO_KEEPALIVE	0x0008	/* Keep connections alive and send
@@ -56,17 +57,20 @@
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
-/* Types of sockets.  */
-#define SOCK_DGRAM 1		/* Connectionless, unreliable datagrams
-				   of fixed maximum length.  */
-#define SOCK_STREAM 2		/* Sequenced, reliable, connection-based
-				   byte streams.  */
-#define SOCK_RAW 3		/* Raw protocol interface.  */
-#define SOCK_RDM 4		/* Reliably-delivered messages.  */
-#define SOCK_SEQPACKET 5	/* Sequenced, reliable, connection-based,
-				   datagrams of fixed maximum length.  */
-#define SOCK_PACKET 10		/* Linux specific way of getting packets at
-				   the dev level.  For writing rarp and
-				   other similar things on the user level.  */
+/* Socket types. */
+
+#ifdef __KERNEL__
 
+#define SOCK_DGRAM	1		/* datagram (conn.less) socket	*/
+#define SOCK_STREAM	2		/* stream (connection) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+
+#endif
 #endif /* __ASM_MIPS_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/softirq.h linux.pre11.3/include/asm-mips/softirq.h
--- linux.vanilla/include/asm-mips/softirq.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/softirq.h	Mon Jul 19 23:26:46 1999
@@ -1,10 +1,10 @@
-/* $Id: softirq.h,v 1.5 1998/08/29 21:20:22 ralf Exp $
+/* $Id: softirq.h,v 1.5 1999/02/15 02:22:12 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1997, 1998, 1999 by Ralf Baechle
  */
 #ifndef __ASM_MIPS_SOFTIRQ_H
 #define __ASM_MIPS_SOFTIRQ_H
@@ -37,14 +37,15 @@
 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;
 }
 
 extern inline void remove_bh(int nr)
 {
-	bh_base[nr] = NULL;
 	bh_mask &= ~(1 << nr);
+	mb();
+	bh_base[nr] = NULL;
 }
 
 extern inline void mark_bh(int nr)
@@ -59,12 +60,12 @@
 extern inline void disable_bh(int nr)
 {
 	bh_mask &= ~(1 << nr);
-	bh_mask_count[nr]++;
+	atomic_inc(&bh_mask_count[nr]);
 }
 
 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 --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/spinlock.h linux.pre11.3/include/asm-mips/spinlock.h
--- linux.vanilla/include/asm-mips/spinlock.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/spinlock.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: spinlock.h,v 1.3 1998/08/28 15:55:39 ralf Exp $
+/* $Id: spinlock.h,v 1.4.2.2 1999/06/17 12:09:42 ralf Exp $
  */
 #ifndef __ASM_MIPS_SPINLOCK_H
 #define __ASM_MIPS_SPINLOCK_H
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/stackframe.h linux.pre11.3/include/asm-mips/stackframe.h
--- linux.vanilla/include/asm-mips/stackframe.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/stackframe.h	Mon Jul 19 23:26:46 1999
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine.
  *
- * $Id: stackframe.h,v 1.7 1998/04/28 19:39:15 ralf Exp $
+ * $Id: stackframe.h,v 1.8 1999/05/01 10:08:19 harald Exp $
  */
 #ifndef __ASM_MIPS_STACKFRAME_H
 #define __ASM_MIPS_STACKFRAME_H
@@ -139,7 +139,12 @@
 		ori	t0, 0x1f;                        \
 		xori	t0, 0x1f;                        \
 		mtc0	t0, CP0_STATUS;                  \
+		li	v1, 0xff00;                      \
+		and	t0, v1;				 \
 		lw	v0, PT_STATUS(sp);               \
+		nor	v1, $0, v1;			 \
+		and	v0, v1;				 \
+		or	v0, t0;				 \
 		mtc0	v0, CP0_STATUS;                  \
 		lw	v1, PT_EPC(sp);                  \
 		mtc0	v1, CP0_EPC;                     \
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/string.h linux.pre11.3/include/asm-mips/string.h
--- linux.vanilla/include/asm-mips/string.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/string.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: string.h,v 1.6 1998/07/20 17:52:21 ralf Exp $
+/* $Id: string.h,v 1.10 1999/04/11 18:37:56 harald Exp $
  *
  * 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
@@ -96,16 +96,16 @@
   __asm__ __volatile__(
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
-	"1:\tlbu\t%3,(%0)\n\t"
+	"1:\tlbu\t%3,(%1)\n\t"
 	"beqz\t%2,2f\n\t"
-	"lbu\t$1,(%1)\n\t"
-	"subu\t%2,1\n\t"
-	"bne\t$1,%3,3f\n\t"
+	"lbu\t$1,(%0)\n\t"
+	"addiu\t%1,1\n\t"
+	"subu\t%3,$1,%3\n\t"
+	"bnez\t%3,2f\n\t"
 	"addiu\t%0,1\n\t"
-	"bnez\t%3,1b\n\t"
-	"addiu\t%1,1\n"
-	"2:\tmove\t%3,$1\n"
-	"3:\tsubu\t%3,$1\n\t"
+	"bnez\t%1,1b\n"
+	"addiu\t%2,-1\n"
+	"2:\n\t"
 	".set\tat\n\t"
 	".set\treorder"
 	: "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res)
@@ -132,12 +132,14 @@
 {
 	char *__end = (char *)__addr + __size;
 
-	__asm__(".set\tnoat\n"
+	__asm__(".set\tpush\n\t"
+		".set\tnoat\n\t"
+		".set\treorder\n\t"
 		"1:\tbeq\t%0,%1,2f\n\t"
 		"addiu\t%0,1\n\t"
 		"lb\t$1,-1(%0)\n\t"
 		"bne\t$1,%4,1b\n"
-		"2:\t.set\tat"
+		"2:\t.set\tpop"
 		: "=r" (__addr), "=r" (__end)
 		: "0" (__addr), "1" (__end), "r" (__c)
 		: "$1");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/system.h linux.pre11.3/include/asm-mips/system.h
--- linux.vanilla/include/asm-mips/system.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/system.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.8 1998/07/20 17:52:21 ralf Exp $
+/* $Id: system.h,v 1.10 1999/06/13 16:35:55 ralf Exp $
  *
  * 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
@@ -88,6 +88,12 @@
 {
 	__asm__ __volatile__(
 		".set\tnoreorder\n\t"
+		"mfc0\t$8,$12\n\t"
+		"li\t$9,0xff00\n\t"
+		"and\t$8,$9\n\t"
+		"nor\t$9,$0,$9\n\t"
+		"and\t%0,$9\n\t"
+		"or\t%0,$8\n\t"
 		"mtc0\t%0,$12\n\t"
 		"nop\n\t"
 		"nop\n\t"
@@ -95,7 +101,7 @@
 		".set\treorder"
 		: /* no output */
 		: "r" (flags)
-		: "memory");
+		: "$8", "$9", "memory");
 }
 
 /*
@@ -107,6 +113,9 @@
 #define save_and_cli(x) __save_and_cli(x)
 #define restore_flags(x) __restore_flags(x)
 
+/*
+ * These are probably defined overly paranoid ...
+ */
 #define mb()						\
 __asm__ __volatile__(					\
 	"# prevent instructions being moved around\n\t"	\
@@ -117,18 +126,20 @@
 	: /* no output */				\
 	: /* no input */				\
 	: "memory")
+#define rmb() mb()
+#define wmb() mb()
 
 #if !defined (_LANGUAGE_ASSEMBLY)
 /*
  * switch_to(n) should switch tasks to task nr n, first
  * checking that n isn't the current task, in which case it does nothing.
  */
-extern asmlinkage void (*resume)(void *tsk);
+extern asmlinkage void *(*resume)(void *last, void *next);
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
-#define switch_to(prev,next) \
+#define switch_to(prev,next,last) \
 do { \
-	resume(next); \
+	(last) = resume(prev, next); \
 } while(0)
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/timex.h linux.pre11.3/include/asm-mips/timex.h
--- linux.vanilla/include/asm-mips/timex.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/timex.h	Mon Jul 19 23:26:46 1999
@@ -1,10 +1,10 @@
-/* $Id: timex.h,v 1.1 1998/08/17 10:20:18 ralf Exp $
+/* $Id: timex.h,v 1.2 1999/02/15 02:22:14 ralf Exp $
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 1999 by Ralf Baechle
  *
  * FIXME: For some of the supported machines this is dead wrong.
  */
@@ -16,5 +16,24 @@
 #define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
 	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
 		<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+/*
+ * Standard way to access the cycle counter.
+ * Currently only used on SMP for scheduling.
+ *
+ * Only the low 32 bits are available as a continuously counting entity. 
+ * But this only means we'll force a reschedule every 8 seconds or so,
+ * which isn't an evil thing.
+ *
+ * We know that all SMP capable CPUs have cycle counters.
+ */
+
+typedef unsigned int cycles_t;
+extern cycles_t cacheflush_time;
+
+static inline cycles_t get_cycles (void)
+{
+	return read_32bit_cp0_register(CP0_COUNT);
+}
 
 #endif /*  __ASM_MIPS_TIMEX_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/uaccess.h linux.pre11.3/include/asm-mips/uaccess.h
--- linux.vanilla/include/asm-mips/uaccess.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/uaccess.h	Mon Jul 19 23:26:46 1999
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  *
- * $Id: uaccess.h,v 1.15 1998/05/03 11:13:54 ralf Exp $
+ * $Id: uaccess.h,v 1.8 1999/01/04 16:09:27 ralf Exp $
  */
 #ifndef __ASM_MIPS_UACCESS_H
 #define __ASM_MIPS_UACCESS_H
@@ -265,6 +265,21 @@
 
 extern void __put_user_unknown(void);
 
+/*
+ * We're generating jump to subroutines which will be outside the range of
+ * jump instructions
+ */
+#ifdef MODULE
+#define __MODULE_JAL(destination) \
+	".set\tnoat\n\t" \
+	"la\t$1, " #destination "\n\t" \
+	"jalr\t$1\n\t" \
+	".set\tat\n\t"
+#else
+#define __MODULE_JAL(destination) \
+	"jal\t" #destination "\n\t"
+#endif
+
 #define copy_to_user_ret(to,from,n,retval) ({ \
 if (copy_to_user(to,from,n)) \
         return retval; \
@@ -289,7 +304,7 @@
 		"move\t$4, %1\n\t" \
 		"move\t$5, %2\n\t" \
 		"move\t$6, %3\n\t" \
-		"jal\t__copy_user\n\t" \
+		__MODULE_JAL(__copy_user) \
 		"move\t%0, $6" \
 		: "=r" (__cu_len) \
 		: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
@@ -313,7 +328,7 @@
 		".set\tnoat\n\t" \
 		"addu\t$1, %2, %3\n\t" \
 		".set\tat\n\t" \
-		"jal\t__copy_user\n\t" \
+		__MODULE_JAL(__copy_user) \
 		"move\t%0, $6" \
 		: "=r" (__cu_len) \
 		: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
@@ -335,7 +350,7 @@
 			"move\t$4, %1\n\t" \
 			"move\t$5, %2\n\t" \
 			"move\t$6, %3\n\t" \
-			"jal\t__copy_user\n\t" \
+			__MODULE_JAL(__copy_user) \
 			"move\t%0, $6" \
 			: "=r" (__cu_len) \
 			: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
@@ -360,7 +375,7 @@
 			".set\tnoat\n\t" \
 			"addu\t$1, %2, %3\n\t" \
 			".set\tat\n\t" \
-			"jal\t__copy_user\n\t" \
+			__MODULE_JAL(__copy_user) \
 			"move\t%0, $6" \
 			: "=r" (__cu_len) \
 			: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
@@ -378,7 +393,7 @@
 		"move\t$4, %1\n\t"
 		"move\t$5, $0\n\t"
 		"move\t$6, %2\n\t"
-		"jal\t__bzero\n\t"
+		__MODULE_JAL(__bzero)
 		"move\t%0, $6"
 		: "=r" (res)
 		: "r" (addr), "r" (size)
@@ -407,7 +422,7 @@
 		"move\t$4, %1\n\t"
 		"move\t$5, %2\n\t"
 		"move\t$6, %3\n\t"
-		"jal\t__strncpy_from_user_nocheck_asm\n\t"
+		__MODULE_JAL(__strncpy_from_user_nocheck_asm)
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (__to), "r" (__from), "r" (__len)
@@ -425,7 +440,7 @@
 		"move\t$4, %1\n\t"
 		"move\t$5, %2\n\t"
 		"move\t$6, %3\n\t"
-		"jal\t__strncpy_from_user_asm\n\t"
+		__MODULE_JAL(__strncpy_from_user_asm)
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (__to), "r" (__from), "r" (__len)
@@ -442,7 +457,7 @@
 
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
-		"jal\t__strlen_user_nocheck_asm\n\t"
+		__MODULE_JAL(__strlen_user_nocheck_asm)
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (s)
@@ -457,7 +472,7 @@
 
 	__asm__ __volatile__(
 		"move\t$4, %1\n\t"
-		"jal\t__strlen_user_asm\n\t"
+		__MODULE_JAL(__strlen_user_asm)
 		"move\t%0, $2"
 		: "=r" (res)
 		: "r" (s)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/umap.h linux.pre11.3/include/asm-mips/umap.h
--- linux.vanilla/include/asm-mips/umap.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/asm-mips/umap.h	Mon Jul 19 23:26:46 1999
@@ -0,0 +1,8 @@
+#ifndef __MIPS_UMAP_H
+#define __MIPS_UMAP_H
+
+void remove_mapping (struct task_struct *task, unsigned long start,
+unsigned long end);
+
+#endif 
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/unistd.h linux.pre11.3/include/asm-mips/unistd.h
--- linux.vanilla/include/asm-mips/unistd.h	Sun Nov  8 15:06:54 1998
+++ linux.pre11.3/include/asm-mips/unistd.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.21 1998/10/19 21:29:15 ralf Exp $
+/* $Id: unistd.h,v 1.14 1999/04/01 23:24:00 ulfc Exp $
  *
  * 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
@@ -1300,7 +1300,7 @@
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)) \
-                  : "$4","$5","$6""$8","$9","$10","$11","$12","$13","$14", \
+                  : "$4","$5","$6","$8","$9","$10","$11","$12","$13","$14", \
                     "$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
@@ -1424,6 +1424,8 @@
 static inline _syscall0(int,sync)
 static inline _syscall0(pid_t,setsid)
 static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
 static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
 static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
@@ -1435,48 +1437,6 @@
 static inline pid_t wait(int * wait_stat)
 {
 	return waitpid(-1,wait_stat,0);
-}
-
-/*
- * This is the mechanism for creating a new kernel thread.
- *
- * NOTE! Only a kernel-only process(ie the swapper or direct descendants
- * who haven't done an "execve()") should use this: it will work within
- * a system call from a "real" process, but the process memory space will
- * not be free'd until both the parent and the child have exited.
- */
-static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	long retval;
-
-	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"move\t$6,$sp\n\t"
-		"move\t$4,%5\n\t"
-		"li\t$2,%1\n\t"
-		"syscall\n\t"
-		"beq\t$6,$sp,1f\n\t"
-		"subu\t$sp,32\n\t"	/* delay slot */
-		"jalr\t%4\n\t"
-		"move\t$4,%3\n\t"	/* delay slot */
-		"move\t$4,$2\n\t"
-		"li\t$2,%2\n\t"
-		"syscall\n"
-		"1:\taddiu\t$sp,32\n\t"
-		"move\t%0,$2\n\t"
-		".set\treorder"
-		:"=r" (retval)
-		:"i" (__NR_clone), "i" (__NR_exit),
-		 "r" (arg), "r" (fn),
-		 "r" (flags | CLONE_VM)
-		 /*
-		  * The called subroutine might have destroyed any of the
-		  * at, result, argument or temporary registers ...
-		  */
-		:"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
-		 "$9","$10","$11","$12","$13","$14","$15","$24","$25");
-
-	return retval;
 }
 
 #endif /* !defined (__KERNEL_SYSCALLS__) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/vga.h linux.pre11.3/include/asm-mips/vga.h
--- linux.vanilla/include/asm-mips/vga.h	Wed Mar 10 21:13:10 1999
+++ linux.pre11.3/include/asm-mips/vga.h	Mon Jul 19 23:26:46 1999
@@ -7,29 +7,14 @@
 #ifndef _LINUX_ASM_VGA_H_
 #define _LINUX_ASM_VGA_H_
 
-#include <asm/io.h>
+/*
+ *	On the PC, we can just recalculate addresses and then
+ *	access the videoram directly without any black magic.
+ */
 
-#define VT_BUF_HAVE_RW
+#define VGA_MAP_MEM(x) ((unsigned long)0xb0000000 + (unsigned long)(x))
 
-extern inline void scr_writew(u16 val, u16 *addr)
-{
-	if ((long) addr < 0)
-		*addr = val;
-	else
-		writew(val, (unsigned long) addr);
-}
-
-extern inline u16 scr_readw(const u16 *addr)
-{
-	if ((long) addr < 0)
-		return *addr;
-	else
-		return readw((unsigned long) addr);
-}
-
-#define vga_readb readb
-#define vga_writeb writeb
-
-#define VGA_MAP_MEM(x) (x)
+#define vga_readb(x) (*(x))
+#define vga_writeb(x,y) (*(y) = (x))
 
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-mips/watch.h linux.pre11.3/include/asm-mips/watch.h
--- linux.vanilla/include/asm-mips/watch.h	Sun Nov  8 15:06:55 1998
+++ linux.pre11.3/include/asm-mips/watch.h	Mon Jul 19 23:26:46 1999
@@ -1,4 +1,4 @@
-/* $Id: watch.h,v 1.3 1998/08/19 21:58:15 ralf Exp $
+/* $Id: watch.h,v 1.3 1998/08/25 09:22:05 ralf Exp $
  *
  * 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
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-ppc/keyboard.h linux.pre11.3/include/asm-ppc/keyboard.h
--- linux.vanilla/include/asm-ppc/keyboard.h	Thu May 27 22:12:02 1999
+++ linux.pre11.3/include/asm-ppc/keyboard.h	Mon Jul 19 23:26:49 1999
@@ -15,6 +15,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/ioport.h>
+#include <asm/io.h>
+
 #include <linux/config.h>
 #include <asm/adb.h>
 #include <asm/machdep.h>
@@ -66,6 +69,31 @@
 #endif
 
 #endif /* CONFIG_APUS */
+
+/* resource allocation */
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
 
 #endif /* __KERNEL__ */
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-ppc/pgtable.h linux.pre11.3/include/asm-ppc/pgtable.h
--- linux.vanilla/include/asm-ppc/pgtable.h	Thu May 27 22:12:02 1999
+++ linux.pre11.3/include/asm-ppc/pgtable.h	Mon Jul 19 23:26:49 1999
@@ -208,7 +208,7 @@
 #endif __ASSEMBLY__
 #define BAD_PAGETABLE	__bad_pagetable()
 #define BAD_PAGE	__bad_page()
-#define ZERO_PAGE	((unsigned long) empty_zero_page)
+#define ZERO_PAGE(vaddr)	((unsigned long) empty_zero_page)
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR	(8*sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-ppc/socket.h linux.pre11.3/include/asm-ppc/socket.h
--- linux.vanilla/include/asm-ppc/socket.h	Sun Nov  8 15:07:02 1998
+++ linux.pre11.3/include/asm-ppc/socket.h	Mon Jul 19 23:26:49 1999
@@ -45,4 +45,17 @@
 #define SO_ATTACH_FILTER	26
 #define SO_DETACH_FILTER	27
 
+/* Socket types. */
+#ifdef __KERNEL__
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+#endif
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-sparc/keyboard.h linux.pre11.3/include/asm-sparc/keyboard.h
--- linux.vanilla/include/asm-sparc/keyboard.h	Wed Apr 28 19:14:33 1999
+++ linux.pre11.3/include/asm-sparc/keyboard.h	Mon Jul 19 23:26:49 1999
@@ -13,6 +13,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/ioport.h>
+#include <asm/io.h>
+
 #define KEYBOARD_IRQ			13
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
@@ -44,6 +47,31 @@
 
 /* #define SYSRQ_KEY 0x54 */	/* sparc64 */
 #define SYSRQ_KEY 0x63		/* sparc */
+
+/* resource allocation */
+#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
 
 #endif /* __KERNEL__ */
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-sparc/pgtable.h linux.pre11.3/include/asm-sparc/pgtable.h
--- linux.vanilla/include/asm-sparc/pgtable.h	Wed Mar 24 10:55:27 1999
+++ linux.pre11.3/include/asm-sparc/pgtable.h	Mon Jul 19 23:26:48 1999
@@ -177,7 +177,7 @@
 
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
-#define ZERO_PAGE ((unsigned long)(&(empty_zero_page)))
+#define ZERO_PAGE(vaddr) ((unsigned long)(&(empty_zero_page)))
 
 /* number of bits that fit into a memory pointer */
 #define BITS_PER_PTR      (8*sizeof(unsigned long))
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-sparc/socket.h linux.pre11.3/include/asm-sparc/socket.h
--- linux.vanilla/include/asm-sparc/socket.h	Sun Nov  8 15:07:00 1998
+++ linux.pre11.3/include/asm-sparc/socket.h	Mon Jul 19 23:26:48 1999
@@ -45,4 +45,18 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
+/* Socket types. */
+#ifdef __KERNEL__
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+#endif					
+
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-sparc64/pgtable.h linux.pre11.3/include/asm-sparc64/pgtable.h
--- linux.vanilla/include/asm-sparc64/pgtable.h	Mon Mar 29 10:25:56 1999
+++ linux.pre11.3/include/asm-sparc64/pgtable.h	Mon Jul 19 23:26:50 1999
@@ -157,7 +157,7 @@
  * hit for all __pa()/__va() operations.
  */
 extern unsigned long phys_base;
-#define ZERO_PAGE	((unsigned long)__va(phys_base))
+#define ZERO_PAGE(vaddr)	((unsigned long)__va(phys_base))
 
 /* Allocate a block of RAM which is aligned to its size.
  * This procedure can be used until the call to mem_init().
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/asm-sparc64/socket.h linux.pre11.3/include/asm-sparc64/socket.h
--- linux.vanilla/include/asm-sparc64/socket.h	Sun Nov  8 15:07:04 1998
+++ linux.pre11.3/include/asm-sparc64/socket.h	Mon Jul 19 23:26:50 1999
@@ -45,4 +45,16 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
 #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
 
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+
 #endif /* _ASM_SOCKET_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/a.out.h linux.pre11.3/include/linux/a.out.h
--- linux.vanilla/include/linux/a.out.h	Sun Nov  8 15:06:47 1998
+++ linux.pre11.3/include/linux/a.out.h	Tue Jul 20 01:31:02 1999
@@ -34,7 +34,7 @@
   /* skip a bunch so we don't run into any of sun's numbers */
   M_386 = 100,
   M_MIPS1 = 151,	/* MIPS R3000/R3000 binary */
-  M_MIPS2 = 152,	/* MIPS R6000/R4000 binary */
+  M_MIPS2 = 152		/* MIPS R6000/R4000 binary */
 };
 
 #if !defined (N_MAGIC)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/b1lli.h linux.pre11.3/include/linux/b1lli.h
--- linux.vanilla/include/linux/b1lli.h	Sun Nov  8 15:06:50 1998
+++ linux.pre11.3/include/linux/b1lli.h	Tue Jul 20 00:12:10 1999
@@ -1,11 +1,52 @@
 /*
- * $Id: b1lli.h,v 1.3 1998/01/31 10:54:37 calle Exp $
+ * $Id: b1lli.h,v 1.8 1999/07/01 15:26:54 calle Exp $
  *
  * ISDN lowlevel-module for AVM B1-card.
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: b1lli.h,v $
+ * Revision 1.8  1999/07/01 15:26:54  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.7  1999/06/21 15:24:25  calle
+ * extend information in /proc.
+ *
+ * Revision 1.6  1999/04/15 19:49:36  calle
+ * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ...
+ *
+ * Revision 1.5  1998/10/25 14:50:28  fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.4  1998/03/29 16:05:02  calle
+ * changes from 2.0 tree merged.
+ *
+ * Revision 1.1.2.9  1998/03/20 14:30:02  calle
+ * added cardnr to detect if you try to add same T1 to different io address.
+ * change number of nccis depending on number of channels.
+ *
+ * Revision 1.1.2.8  1998/03/04 17:32:33  calle
+ * Changes for T1.
+ *
+ * Revision 1.1.2.7  1998/02/27 15:38:29  calle
+ * T1 running with slow link.
+ *
+ * Revision 1.1.2.6  1998/02/24 17:57:36  calle
+ * changes for T1.
+ *
  * Revision 1.3  1998/01/31 10:54:37  calle
  * include changes for PCMCIA cards from 2.0 version
  *
@@ -70,15 +111,16 @@
 	int irq;
 } avmb1_carddef;
 
-#define AVM_CARDTYPE_B1	0
-#define AVM_CARDTYPE_T1	1
-#define AVM_CARDTYPE_M1	2
-#define AVM_CARDTYPE_M2	3
+#define AVM_CARDTYPE_B1		0
+#define AVM_CARDTYPE_T1		1
+#define AVM_CARDTYPE_M1		2
+#define AVM_CARDTYPE_M2		3
 
 typedef struct avmb1_extcarddef {
 	int port;
 	int irq;
         int cardtype;
+        int cardnr;  /* for HEMA/T1 */
 } avmb1_extcarddef;
 
 #define	AVMB1_LOAD		0	/* load image to card */
@@ -87,106 +129,8 @@
 #define	AVMB1_LOAD_AND_CONFIG	3	/* load image and config to card */
 #define	AVMB1_ADDCARD_WITH_TYPE	4	/* add a new card, with cardtype */
 #define AVMB1_GET_CARDINFO	5	/* get cardtype */
+#define AVMB1_REMOVECARD	6	/* remove a card (usefull for T1) */
 
-
-
-/*
- * card states for startup
- */
-
-#define CARD_FREE	0
-#define CARD_DETECTED	1
-#define CARD_LOADING	2
-#define CARD_INITSTATE	4
-#define CARD_RUNNING	5
-#define CARD_ACTIVE	6
-
-#ifdef __KERNEL__
-
-#define	AVMB1_PORTLEN	0x1f
-
-#define AVM_MAXVERSION	8
-#define AVM_NBCHAN	2
-
-#define AVM_NAPPS	30
-#define AVM_NPLCI	5
-#define AVM_NNCCI	6
-
-/*
- * Main driver data
- */
-
-typedef struct avmb1_card {
-	struct avmb1_card *next;
-	int cnr;
-	unsigned short port;
-	unsigned irq;
-	int cardtype;
-	volatile unsigned short cardstate;
-	int interrupt;
-	int blocked;
-	int versionlen;
-	char versionbuf[1024];
-	char *version[AVM_MAXVERSION];
-	char msgbuf[128];	/* capimsg msg part */
-	char databuf[2048];	/* capimsg data part */
-	capi_version cversion;
-	char name[10];
-} avmb1_card;
-
-/*
- * Versions
- */
-
-#define	VER_DRIVER	0
-#define	VER_CARDTYPE	1
-#define	VER_HWID	2
-#define	VER_SERIAL	3
-#define	VER_OPTION	4
-#define	VER_PROTO	5
-#define	VER_PROFILE	6
-#define	VER_CAPI	7
-
-
-/* b1lli.c */
-int B1_detect(unsigned short base, int cardtype);
-void B1_reset(unsigned short base);
-int B1_load_t4file(unsigned short base, avmb1_t4file * t4file);
-int B1_load_config(unsigned short base, avmb1_t4file * config);
-int B1_loaded(unsigned short base);
-unsigned char B1_assign_irq(unsigned short base, unsigned irq, int cardtype);
-unsigned char B1_enable_irq(unsigned short base);
-unsigned char B1_disable_irq(unsigned short base);
-int B1_valid_irq(unsigned irq, int cardtype);
-void B1_handle_interrupt(avmb1_card * card);
-void B1_send_init(unsigned short port,
-	    unsigned int napps, unsigned int nncci, unsigned int cardnr);
-void B1_send_register(unsigned short port,
-		      __u16 appid, __u32 nmsg,
-		      __u32 nb3conn, __u32 nb3blocks, __u32 b3bsize);
-void B1_send_release(unsigned short port, __u16 appid);
-void B1_send_message(unsigned short port, struct sk_buff *skb);
-
-/* b1capi.c */
-void avmb1_handle_new_ncci(avmb1_card * card,
-			   __u16 appl, __u32 ncci, __u32 winsize);
-void avmb1_handle_free_ncci(avmb1_card * card,
-			    __u16 appl, __u32 ncci);
-void avmb1_handle_capimsg(avmb1_card * card, __u16 appl, struct sk_buff *skb);
-void avmb1_card_ready(avmb1_card * card);
-
-/* standard calls, with check and allocation of resources */
-int avmb1_addcard(int port, int irq, int cardtype);
-int avmb1_probecard(int port, int irq, int cardtype);
-
-
-int avmb1_resetcard(int cardnr);
-
-/* calls for pcmcia driver */
-int avmb1_detectcard(int port, int irq, int cardtype);
-int avmb1_registercard(int port, int irq, int cardtype, int allocio);
-int avmb1_unregistercard(int cnr, int freeio);
-
-#endif				/* __KERNEL__ */
+#define	AVMB1_REGISTERCARD_IS_OBSOLETE
 
 #endif				/* _B1LLI_H_ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/b1pcmcia.h linux.pre11.3/include/linux/b1pcmcia.h
--- linux.vanilla/include/linux/b1pcmcia.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/b1pcmcia.h	Tue Jul 20 00:12:10 1999
@@ -0,0 +1,36 @@
+/*
+ * $Id: b1pcmcia.h,v 1.1 1999/07/01 15:26:56 calle Exp $
+ *
+ * Exported functions of module b1pcmcia to be called by
+ * avm_cs card services module.
+ *
+ * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
+ *
+ * $Log: b1pcmcia.h,v $
+ * Revision 1.1  1999/07/01 15:26:56  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ */
+
+#ifndef _B1PCMCIA_H_
+#define _B1PCMCIA_H_
+
+int b1pcmcia_addcard_b1(unsigned int port, unsigned irq);
+int b1pcmcia_addcard_m1(unsigned int port, unsigned irq);
+int b1pcmcia_addcard_m2(unsigned int port, unsigned irq);
+int b1pcmcia_delcard(unsigned int port, unsigned irq);
+
+#endif	/* _B1PCMCIA_H_ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/binfmts.h linux.pre11.3/include/linux/binfmts.h
--- linux.vanilla/include/linux/binfmts.h	Sun Nov  8 15:06:47 1998
+++ linux.pre11.3/include/linux/binfmts.h	Tue Jul 20 01:31:03 1999
@@ -52,6 +52,7 @@
 
 extern int init_elf_binfmt(void);
 extern int init_elf32_binfmt(void);
+extern int init_irix_binfmt(void);
 extern int init_aout_binfmt(void);
 extern int init_aout32_binfmt(void);
 extern int init_script_binfmt(void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/blk.h linux.pre11.3/include/linux/blk.h
--- linux.vanilla/include/linux/blk.h	Sun Nov  8 15:06:49 1998
+++ linux.pre11.3/include/linux/blk.h	Tue Jul 20 01:31:06 1999
@@ -19,7 +19,7 @@
  * NOTE that writes may use only the low 2/3 of these: reads
  * take precedence.
  */
-#define NR_REQUEST	64
+#define NR_REQUEST	128
 
 /*
  * This is used in the elevator algorithm.  We don't prioritise reads
@@ -92,6 +92,19 @@
   case BLKROGET: { int __val = (is_read_only(dev) != 0) ; \
 		    return put_user(__val,(int *) (where)); }
 		 
+/*
+ * end_request() and friends. Must be called with the request queue spinlock
+ * acquired. All functions called within end_request() _must_be_ atomic.
+ *
+ * Several drivers define their own end_request and call
+ * end_that_request_first() and end_that_request_last()
+ * for parts of the original function. This prevents
+ * code duplication in drivers.
+ */
+
+int end_that_request_first(struct request *req, int uptodate, char *name);
+void end_that_request_last(struct request *req);
+
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
 /*
@@ -356,6 +369,15 @@
 #define DEVICE_ON(device) 
 #define DEVICE_OFF(device)
 
+#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
+
+#define DEVICE_NAME "ida"
+#define TIMEOUT_VALUE (25*HZ)
+#define DEVICE_REQUEST do_ida_request0
+#define DEVICE_NR(device) (MINOR(device) >> 4)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
 #endif /* MAJOR_NR == whatever */
 
 #if (MAJOR_NR != SCSI_TAPE_MAJOR)
@@ -418,21 +440,9 @@
 
 #endif /* !defined(IDE_DRIVER) */
 
-/*
- * end_request() and friends. Must be called with the request queue spinlock
- * acquired. All functions called within end_request() _must_be_ atomic.
- *
- * Several drivers define their own end_request and call end_that_request_first()
- * and end_that_request_last() for parts of the original function. This prevents
- * code duplication in drivers.
- */
-
-int end_that_request_first(struct request *req, int uptodate, char *name);
-void end_that_request_last(struct request *req);
-
 #ifndef LOCAL_END_REQUEST	/* If we have our own end_request, we do not want to include this mess */
 
-#if ! SCSI_BLK_MAJOR(MAJOR_NR)
+#if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
 
 static void end_request(int uptodate) {
 	struct request *req = CURRENT;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/blkdev.h linux.pre11.3/include/linux/blkdev.h
--- linux.vanilla/include/linux/blkdev.h	Sun Nov  8 15:06:48 1998
+++ linux.pre11.3/include/linux/blkdev.h	Tue Jul 20 01:31:05 1999
@@ -25,6 +25,7 @@
 	int errors;
 	unsigned long sector;
 	unsigned long nr_sectors;
+	unsigned long nr_segments;
 	unsigned long current_nr_sectors;
 	char * buffer;
 	struct semaphore * sem;
@@ -75,14 +76,18 @@
 
 extern int * max_sectors[MAX_BLKDEV];
 
-#define MAX_SECTORS 244 /* 254 ? */
+extern int * max_segments[MAX_BLKDEV];
+
+#define MAX_SECTORS 128
+
+#define MAX_SEGMENTS MAX_SECTORS
 
 #define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
 #if 0  /* small readahead */
 #define MAX_READAHEAD PageAlignSize(4096*7)
 #define MIN_READAHEAD PageAlignSize(4096*2)
 #else /* large readahead */
-#define MAX_READAHEAD PageAlignSize(4096*18)
+#define MAX_READAHEAD PageAlignSize(4096*31)
 #define MIN_READAHEAD PageAlignSize(4096*3)
 #endif
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/capability.h linux.pre11.3/include/linux/capability.h
--- linux.vanilla/include/linux/capability.h	Thu May 27 22:12:02 1999
+++ linux.pre11.3/include/linux/capability.h	Tue Jul 20 01:31:03 1999
@@ -264,6 +264,10 @@
 #define CAP_SYS_TTY_CONFIG   26
 
 #ifdef __KERNEL__
+/* 
+ * Bounding set
+ */
+extern kernel_cap_t cap_bset;
 
 /*
  * Internal kernel functions only
@@ -289,7 +293,7 @@
 #define CAP_TO_MASK(x) (1 << (x))
 #define cap_raise(c, flag)   (cap_t(c) |=  CAP_TO_MASK(flag))
 #define cap_lower(c, flag)   (cap_t(c) &= ~CAP_TO_MASK(flag))
-#define cap_raised(c, flag)  (cap_t(c) &   CAP_TO_MASK(flag))
+#define cap_raised(c, flag)  (cap_t(c) & CAP_TO_MASK(flag) & cap_bset)
 
 static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
 {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/coda.h linux.pre11.3/include/linux/coda.h
--- linux.vanilla/include/linux/coda.h	Tue Jan 26 09:44:23 1999
+++ linux.pre11.3/include/linux/coda.h	Mon Jul 19 23:26:42 1999
@@ -100,22 +100,35 @@
 
 #if defined(__linux__)
 #define cdev_t u_quad_t
+#ifndef __KERNEL__
 #if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2)
 #define _UQUAD_T_ 1
 typedef unsigned long long u_quad_t;
 #endif
+#else /*__KERNEL__ */
+typedef unsigned long long u_quad_t;
+#endif /* __KERNEL__ */
 #else
 #define cdev_t dev_t
 #endif
 
 #ifdef __CYGWIN32__
-typedef unsigned char u_int8_t;
 struct timespec {
         time_t  tv_sec;         /* seconds */
         long    tv_nsec;        /* nanoseconds */
 };
 #endif
 
+#ifndef __BIT_TYPES_DEFINED__
+#define __BIT_TYPES_DEFINED__
+typedef signed char	      int8_t;
+typedef unsigned char	    u_int8_t;
+typedef short		     int16_t;
+typedef unsigned short	   u_int16_t;
+typedef int		     int32_t;
+typedef unsigned int	   u_int32_t;
+#endif
+
 
 /*
  * Cfs constants
@@ -151,8 +164,8 @@
 struct venus_dirent {
         unsigned long	d_fileno;		/* file number of entry */
         unsigned short	d_reclen;		/* length of this record */
-        char 		d_type;			/* file type, see below */
-        char		d_namlen;		/* length of string in d_name */
+        unsigned char 	d_type;			/* file type, see below */
+        unsigned char	d_namlen;		/* length of string in d_name */
         char		d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */
 };
 #undef DIRSIZ
@@ -215,11 +228,6 @@
 #endif
 
 
-#ifndef __BIT_TYPES_DEFINED__
-#define u_int32_t unsigned int
-#endif
-
-
 #ifndef _VUID_T_
 #define _VUID_T_
 typedef u_int32_t vuid_t;
@@ -229,12 +237,8 @@
 #ifndef _CODACRED_T_
 #define _CODACRED_T_
 struct coda_cred {
-	vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid;
-	vgid_t cr_groupid,     cr_egid, cr_sgid, cr_fsgid;
-#if   defined(CODA_SUPPORTS_SUPPLEMENTARY_GROUPS)
-	int    cr_nsupgps;
-	vgid_t cr_supgps[NGROUPS];
-#endif        /* defined(CODA_SUPPORTS_SUPPLEMENTARY_GROUPS) */
+    vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
+    vgid_t cr_groupid,     cr_egid, cr_sgid, cr_fsgid; /* same for groups */
 };
 #endif 
 
@@ -246,7 +250,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 {
-	int     	va_type;	/* vnode type (for create) */
+	long     	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 */
@@ -266,6 +270,15 @@
 
 #endif 
 
+/* structure used by CODA_STATFS for getting cache information from venus */
+struct coda_statfs {
+    int32_t f_blocks;
+    int32_t f_bfree;
+    int32_t f_bavail;
+    int32_t f_files;
+    int32_t f_ffree;
+};
+
 /*
  * Kernel <--> Venus communications.
  */
@@ -301,7 +314,8 @@
 #define CODA_OPEN_BY_PATH 31
 #define CODA_RESOLVE     32
 #define CODA_REINTEGRATE 33
-#define CODA_NCALLS 34
+#define CODA_STATFS	 34
+#define CODA_NCALLS 35
 
 #define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
 
@@ -675,6 +689,16 @@
 	int path;
 };
 
+/* coda_statfs: NO_IN */
+struct coda_statfs_in {
+    struct coda_in_hdr in;
+};
+
+struct coda_statfs_out {
+    struct coda_out_hdr oh;
+    struct coda_statfs stat;
+};
+
 /* 
  * Occasionally, we don't cache the fid returned by CODA_LOOKUP. 
  * For instance, if the fid is inconsistent. 
@@ -704,7 +728,8 @@
     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;
+    struct coda_open_by_path_in coda_open_by_path;
+    struct coda_statfs_in coda_statfs;
 };
 
 union outputArgs {
@@ -726,7 +751,8 @@
     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;
+    struct coda_open_by_path_out coda_open_by_path;
+    struct coda_statfs_out coda_statfs;
 };    
 
 union coda_downcalls {
@@ -752,20 +778,11 @@
         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	CODA_CONTROL		".CONTROL"
 #define CODA_CONTROLLEN           8
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/coda_proc.h linux.pre11.3/include/linux/coda_proc.h
--- linux.vanilla/include/linux/coda_proc.h	Sun Nov  8 15:06:50 1998
+++ linux.pre11.3/include/linux/coda_proc.h	Mon Jul 19 23:26:44 1999
@@ -98,6 +98,7 @@
 extern struct coda_vfs_stats		coda_vfs_stat;
 extern struct coda_permission_stats	coda_permission_stat;
 extern struct coda_cache_inv_stats	coda_cache_inv_stat;
+extern int				coda_upcall_timestamping;
 
 /* reset statistics to 0 */
 void reset_coda_vfs_stats( void );
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/coda_psdev.h linux.pre11.3/include/linux/coda_psdev.h
--- linux.vanilla/include/linux/coda_psdev.h	Tue Dec 22 23:20:11 1998
+++ linux.pre11.3/include/linux/coda_psdev.h	Mon Jul 19 23:26:44 1999
@@ -80,6 +80,7 @@
 		 unsigned int cmd, struct PioctlData *data);
 int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
 int venus_fsync(struct super_block *sb, struct ViceFid *fid);
+int venus_statfs(struct super_block *sb, struct statfs *sfs);
 
 
 /* messages between coda filesystem in kernel and Venus */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/console.h linux.pre11.3/include/linux/console.h
--- linux.vanilla/include/linux/console.h	Wed Mar 10 21:13:11 1999
+++ linux.pre11.3/include/linux/console.h	Mon Jul 19 23:26:43 1999
@@ -51,6 +51,7 @@
 extern struct consw dummy_con;	/* dummy console buffer */
 extern struct consw fb_con;	/* frame buffer based console */
 extern struct consw vga_con;	/* VGA text console */
+extern struct consw newport_con;	/* SGI Newport console  */
 extern struct consw prom_con;	/* SPARC PROM console */
 
 void take_over_console(struct consw *sw, int first, int last, int deflt);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/cyclades.h linux.pre11.3/include/linux/cyclades.h
--- linux.vanilla/include/linux/cyclades.h	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/include/linux/cyclades.h	Mon Jul 19 23:26:42 1999
@@ -517,7 +517,7 @@
     int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
     int first_line;	/* minor number of first channel on card */
     int bus_index;	/* address shift - 0 for ISA, 1 for PCI */
-    int	inact_ctrl;	/* FW Inactivity control - 0 disabled, 1 enabled */
+    int	intr_enabled;	/* FW Interrupt flag - 0 disabled, 1 enabled */
 };
 
 struct cyclades_chip {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/efs_dir.h linux.pre11.3/include/linux/efs_dir.h
--- linux.vanilla/include/linux/efs_dir.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/efs_dir.h	Mon Jul 19 23:26:45 1999
@@ -0,0 +1,42 @@
+/*
+ * efs_dir.h
+ *
+ * Copyright (c) 1999 Al Smith
+ */
+
+#ifndef __EFS_DIR_H__
+#define __EFS_DIR_H__
+
+#define EFS_DIRBSIZE_BITS	EFS_BLOCKSIZE_BITS
+#define EFS_DIRBSIZE		(1 << EFS_DIRBSIZE_BITS)
+
+struct efs_dentry {
+	unsigned int	inode;
+	unsigned char	namelen;
+	char		name[3];
+};
+
+#define EFS_DENTSIZE	(sizeof(struct efs_dentry) - 3 + 1)
+#define EFS_MAXNAMELEN  ((1 << (sizeof(char) * 8)) - 1)
+
+#define EFS_DIRBLK_HEADERSIZE	4
+#define EFS_DIRBLK_MAGIC	0xbeef	/* moo */
+
+struct efs_dir {
+	unsigned short	magic;
+	unsigned char	firstused;
+	unsigned char	slots;
+
+	unsigned char	space[EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE];
+};
+
+#define EFS_MAXENTS \
+	((EFS_DIRBSIZE - EFS_DIRBLK_HEADERSIZE) / \
+	 (EFS_DENTSIZE + sizeof(char)))
+
+#define EFS_SLOTAT(dir, slot) EFS_REALOFF((dir)->space[slot])
+
+#define EFS_REALOFF(offset) ((offset << 1))
+
+#endif /* __EFS_DIR_H__ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/efs_fs.h linux.pre11.3/include/linux/efs_fs.h
--- linux.vanilla/include/linux/efs_fs.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/efs_fs.h	Tue Jul 20 01:46:21 1999
@@ -0,0 +1,67 @@
+/*
+ * efs_fs.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
+ */
+
+#ifndef __EFS_FS_H__
+#define __EFS_FS_H__
+
+#define EFS_VERSION "1.0b"
+
+static const char cprt[] = "EFS: "EFS_VERSION" - (c) 1999 Al Smith <Al.Smith@aeschi.ch.eu.org>";
+
+#include <asm/uaccess.h>
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#if LINUX_VERSION_CODE < 0x20200
+#error This code is only for linux-2.2 and later.
+#endif
+
+/* 1 block is 512 bytes */
+#define	EFS_BLOCKSIZE_BITS	9
+#define	EFS_BLOCKSIZE		(1 << EFS_BLOCKSIZE_BITS)
+
+#include <linux/efs_fs_i.h>
+#include <linux/efs_dir.h>
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#ifdef _EFS_USE_GENERIC
+#define INODE_INFO(i) (struct efs_inode_info *)	&((i)->u.generic_ip)
+#define SUPER_INFO(s) (struct efs_sb_info *)	&((s)->u.generic_sbp)
+#else
+#define INODE_INFO(i)				&((i)->u.efs_i)
+#define SUPER_INFO(s)				&((s)->u.efs_sb)
+#endif
+
+extern struct inode_operations efs_dir_inode_operations;
+extern struct inode_operations efs_file_inode_operations;
+extern struct inode_operations efs_symlink_inode_operations;
+
+extern int init_module(void);
+extern void cleanup_module(void);
+extern struct super_block *efs_read_super(struct super_block *, void *, int);
+extern void efs_put_super(struct super_block *);
+extern int efs_statfs(struct super_block *, struct statfs *, int);
+
+extern void efs_read_inode(struct inode *);
+extern efs_block_t efs_map_block(struct inode *, efs_block_t);
+
+extern struct dentry *efs_lookup(struct inode *, struct dentry *);
+extern int efs_bmap(struct inode *, int);
+
+extern int init_efs_fs(void);
+
+#endif /* __EFS_FS_H__ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/efs_fs_i.h linux.pre11.3/include/linux/efs_fs_i.h
--- linux.vanilla/include/linux/efs_fs_i.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/efs_fs_i.h	Mon Jul 19 23:26:45 1999
@@ -0,0 +1,68 @@
+/*
+ * efs_fs_i.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from IRIX header files (c) 1988 Silicon Graphics
+ */
+
+#ifndef	__EFS_FS_I_H__
+#define	__EFS_FS_I_H__
+
+typedef	int32_t		efs_block_t;
+typedef uint32_t	efs_ino_t;
+
+#define	EFS_DIRECTEXTENTS	12
+
+/*
+ * layout of an extent, in memory and on disk. 8 bytes exactly.
+ */
+typedef union extent_u {
+	unsigned char raw[8];
+	struct extent_s {
+		unsigned int	ex_magic:8;	/* magic # (zero) */
+		unsigned int	ex_bn:24;	/* basic block */
+		unsigned int	ex_length:8;	/* numblocks in this extent */
+		unsigned int	ex_offset:24;	/* logical offset into file */
+	} cooked;
+} efs_extent;
+
+typedef struct edevs {
+	short		odev;
+	short		dev_filler;	/* force ndev to start */
+	unsigned int	ndev;		/* on a 32-bit boundary */
+} efs_devs;
+
+/*
+ * extent based filesystem inode as it appears on disk.  The efs inode
+ * is exactly 128 bytes long.
+ */
+struct	efs_dinode {
+	u_short		di_mode;	/* mode and type of file */
+	short		di_nlink;	/* number of links to file */
+	u_short		di_uid;		/* owner's user id */
+	u_short		di_gid;		/* owner's group id */
+	int32_t		di_size;	/* number of bytes in file */
+	int32_t		di_atime;	/* time last accessed */
+	int32_t		di_mtime;	/* time last modified */
+	int32_t		di_ctime;	/* time created */
+	uint32_t	di_gen;		/* generation number */
+	short		di_numextents;	/* # of extents */
+	u_char		di_version;	/* version of inode */
+	u_char		di_spare;	/* spare - used by AFS */
+	union di_addr {
+		efs_extent	di_extents[EFS_DIRECTEXTENTS];
+		efs_devs	di_dev;	/* device for IFCHR/IFBLK */
+	} di_u;
+};
+
+/* efs inode storage in memory */
+struct efs_inode_info {
+	int		numextents;
+	int		lastextent;
+
+	efs_extent	extents[EFS_DIRECTEXTENTS];
+};
+
+#endif	/* __EFS_FS_I_H__ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/efs_fs_sb.h linux.pre11.3/include/linux/efs_fs_sb.h
--- linux.vanilla/include/linux/efs_fs_sb.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/efs_fs_sb.h	Mon Jul 19 23:26:45 1999
@@ -0,0 +1,63 @@
+/*
+ * efs_fs_sb.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from IRIX header files (c) 1988 Silicon Graphics
+ */
+
+#ifndef __EFS_FS_SB_H__
+#define __EFS_FS_SB_H__
+
+/* statfs() magic number for EFS */
+#define EFS_SUPER_MAGIC	0x414A53
+
+/* EFS superblock magic numbers */
+#define EFS_MAGIC	0x072959
+#define EFS_NEWMAGIC	0x07295a
+
+#define IS_EFS_MAGIC(x)	((x == EFS_MAGIC) || (x == EFS_NEWMAGIC))
+
+#define EFS_SUPER		1
+#define EFS_ROOTINODE		2
+
+/* efs superblock on disk */
+struct efs_super {
+	int32_t		fs_size;        /* size of filesystem, in sectors */
+	int32_t		fs_firstcg;     /* bb offset to first cg */
+	int32_t		fs_cgfsize;     /* size of cylinder group in bb's */
+	short		fs_cgisize;     /* bb's of inodes per cylinder group */
+	short		fs_sectors;     /* sectors per track */
+	short		fs_heads;       /* heads per cylinder */
+	short		fs_ncg;         /* # of cylinder groups in filesystem */
+	short		fs_dirty;       /* fs needs to be fsck'd */
+	short		fs_filler;	/* force fs_time to start 2bytes later*/
+	int32_t		fs_time;        /* last super-block update */
+	int32_t		fs_magic;       /* magic number */
+	char		fs_fname[6];    /* file system name */
+	char		fs_fpack[6];    /* file system pack name */
+	int32_t		fs_bmsize;      /* size of bitmap in bytes */
+	int32_t		fs_tfree;       /* total free data blocks */
+	int32_t		fs_tinode;      /* total free inodes */
+	int32_t		fs_bmblock;     /* bitmap location. */
+	int32_t		fs_replsb;      /* Location of replicated superblock. */
+	int32_t		fs_lastialloc;  /* last allocated inode */
+	char		fs_spare[20];   /* space for expansion - MUST BE ZERO */
+	int32_t		fs_checksum;    /* checksum of volume portion of fs */
+};
+
+/* efs superblock information in memory */
+struct efs_sb_info {
+	int32_t	fs_magic;	/* superblock magic number */
+	int32_t	fs_start;	/* first block of filesystem */
+	int32_t	first_block;	/* first data block in filesystem */
+	int32_t	total_blocks;	/* total number of blocks in filesystem */
+	int32_t	group_size;	/* # of blocks a group consists of */ 
+	int32_t	data_free;	/* # of free data blocks */
+	int32_t	inode_free;	/* # of free inodes */
+	short	inode_blocks;	/* # of blocks used for inodes in every grp */
+	short	total_groups;	/* # of groups */
+};
+
+#endif /* __EFS_FS_SB_H__ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/efs_vh.h linux.pre11.3/include/linux/efs_vh.h
--- linux.vanilla/include/linux/efs_vh.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/efs_vh.h	Mon Jul 19 23:26:45 1999
@@ -0,0 +1,70 @@
+/*
+ * efs_vh.h
+ *
+ * Copyright (c) 1999 Al Smith
+ *
+ * Portions derived from IRIX header files (c) 1985 MIPS Computer Systems, Inc.
+ */
+
+#ifndef __EFS_VH_H__
+#define __EFS_VH_H__
+
+#define VHMAGIC		0xbe5a941	/* volume header magic number */
+#define NPARTAB		16		/* 16 unix partitions */
+#define NVDIR		15		/* max of 15 directory entries */
+#define BFNAMESIZE	16		/* max 16 chars in boot file name */
+#define VDNAMESIZE	8
+
+struct volume_directory {
+	char	vd_name[VDNAMESIZE];	/* name */
+	int	vd_lbn;			/* logical block number */
+	int	vd_nbytes;		/* file length in bytes */
+};
+
+struct partition_table {	/* one per logical partition */
+	int	pt_nblks;	/* # of logical blks in partition */
+	int	pt_firstlbn;	/* first lbn of partition */
+	int	pt_type;	/* use of partition */
+};
+
+struct volume_header {
+	int	vh_magic;			/* identifies volume header */
+	short	vh_rootpt;			/* root partition number */
+	short	vh_swappt;			/* swap partition number */
+	char	vh_bootfile[BFNAMESIZE];	/* name of file to boot */
+	char	pad[48];			/* device param space */
+	struct volume_directory vh_vd[NVDIR];	/* other vol hdr contents */
+	struct partition_table  vh_pt[NPARTAB];	/* device partition layout */
+	int	vh_csum;			/* volume header checksum */
+	int	vh_fill;			/* fill out to 512 bytes */
+};
+
+/* partition type sysv is used for EFS format CD-ROM partitions */
+#define SGI_SYSV	0x05
+#define SGI_EFS		0x07
+#define IS_EFS(x)	(((x) == SGI_EFS) || ((x) == SGI_SYSV))
+
+struct pt_types {
+	int	pt_type;
+	char	*pt_name;
+} sgi_pt_types[] = {
+	{0x00,		"SGI vh"},
+	{0x01,		"SGI trkrepl"},
+	{0x02,		"SGI secrepl"},
+	{0x03,		"SGI raw"},
+	{0x04,		"SGI bsd"},
+	{SGI_SYSV,	"SGI sysv"},
+	{0x06,		"SGI vol"},
+	{SGI_EFS,	"SGI efs"},
+	{0x08,		"SGI lv"},
+	{0x09,		"SGI rlv"},
+	{0x0A,		"SGI xfs"},
+	{0x0B,		"SGI xfslog"},
+	{0x0C,		"SGI xlv"},
+	{0x82,		"Linux swap"},
+	{0x83,		"Linux native"},
+	{0,		NULL}
+};
+
+#endif /* __EFS_VH_H__ */
+
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/elf.h linux.pre11.3/include/linux/elf.h
--- linux.vanilla/include/linux/elf.h	Sun Nov  8 15:06:48 1998
+++ linux.pre11.3/include/linux/elf.h	Tue Jul 20 01:46:31 1999
@@ -29,6 +29,13 @@
 #define PT_PHDR    6
 #define PT_LOPROC  0x70000000
 #define PT_HIPROC  0x7fffffff
+#define PT_MIPS_REGINFO		0x70000000
+
+/* Flags in the e_flags field of the header */
+#define EF_MIPS_NOREORDER 0x00000001
+#define EF_MIPS_PIC       0x00000002
+#define EF_MIPS_CPIC      0x00000004
+#define EF_MIPS_ARCH      0xf0000000
 
 /* These constants define the different elf file types */
 #define ET_NONE   0
@@ -36,8 +43,8 @@
 #define ET_EXEC   2
 #define ET_DYN    3
 #define ET_CORE   4
-#define ET_LOPROC 5
-#define ET_HIPROC 6
+#define ET_LOPROC 0xff00
+#define ET_HIPROC 0xffff
 
 /* These constants define the various ELF target machines */
 #define EM_NONE  0
@@ -95,6 +102,25 @@
 #define DT_JMPREL	23
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
+#define DT_MIPS_RLD_VERSION	0x70000001
+#define DT_MIPS_TIME_STAMP	0x70000002
+#define DT_MIPS_ICHECKSUM	0x70000003
+#define DT_MIPS_IVERSION	0x70000004
+#define DT_MIPS_FLAGS		0x70000005
+  #define RHF_NONE		  0
+  #define RHF_HARDWAY		  1
+  #define RHF_NOTPOT		  2
+#define DT_MIPS_BASE_ADDRESS	0x70000006
+#define DT_MIPS_CONFLICT	0x70000008
+#define DT_MIPS_LIBLIST		0x70000009
+#define DT_MIPS_LOCAL_GOTNO	0x7000000a
+#define DT_MIPS_CONFLICTNO	0x7000000b
+#define DT_MIPS_LIBLISTNO	0x70000010
+#define DT_MIPS_SYMTABNO	0x70000011
+#define DT_MIPS_UNREFEXTNO	0x70000012
+#define DT_MIPS_GOTSYM		0x70000013
+#define DT_MIPS_HIPAGENO	0x70000014
+#define DT_MIPS_RLD_MAP		0x70000016
 
 /* This info is needed when parsing the symbol table */
 #define STB_LOCAL  0
@@ -163,6 +189,55 @@
 #define R_386_GOTPC	10
 #define R_386_NUM	11
 
+#define R_MIPS_NONE		0
+#define R_MIPS_16		1
+#define R_MIPS_32		2
+#define R_MIPS_REL32		3
+#define R_MIPS_26		4
+#define R_MIPS_HI16		5
+#define R_MIPS_LO16		6
+#define R_MIPS_GPREL16		7
+#define R_MIPS_LITERAL		8
+#define R_MIPS_GOT16		9
+#define R_MIPS_PC16		10
+#define R_MIPS_CALL16		11
+#define R_MIPS_GPREL32		12
+/* The remaining relocs are defined on Irix, although they are not
+   in the MIPS ELF ABI.  */
+#define R_MIPS_UNUSED1		13
+#define R_MIPS_UNUSED2		14
+#define R_MIPS_UNUSED3		15
+#define R_MIPS_SHIFT5		16
+#define R_MIPS_SHIFT6		17
+#define R_MIPS_64		18
+#define R_MIPS_GOT_DISP		19
+#define R_MIPS_GOT_PAGE		20
+#define R_MIPS_GOT_OFST		21
+/*
+ * The following two relocation types are specified in the the MIPS ABI
+ * conformance guide version 1.2 but not yet in the psABI.
+ */
+#define R_MIPS_GOTHI16		22
+#define R_MIPS_GOTLO16		23
+#define R_MIPS_SUB		24
+#define R_MIPS_INSERT_A		25
+#define R_MIPS_INSERT_B		26
+#define R_MIPS_DELETE		27
+#define R_MIPS_HIGHER		28
+#define R_MIPS_HIGHEST		29
+/*
+ * The following two relocation types are specified in the the MIPS ABI
+ * conformance guide version 1.2 but not yet in the psABI.
+ */
+#define R_MIPS_CALLHI16		30
+#define R_MIPS_CALLLO16		31
+/*
+ * This range is reserved for vendor specific relocations.
+ */
+#define R_MIPS_LOVENDOR		100
+#define R_MIPS_HIVENDOR		127
+
+
 /*
  * Sparc ELF relocation types
  */
@@ -400,12 +475,17 @@
 #define SHT_HIPROC	0x7fffffff
 #define SHT_LOUSER	0x80000000
 #define SHT_HIUSER	0xffffffff
+#define SHT_MIPS_LIST		0x70000000
+#define SHT_MIPS_CONFLICT	0x70000002
+#define SHT_MIPS_GPTAB		0x70000003
+#define SHT_MIPS_UCODE		0x70000004
 
 /* sh_flags */
 #define SHF_WRITE	0x1
 #define SHF_ALLOC	0x2
 #define SHF_EXECINSTR	0x4
 #define SHF_MASKPROC	0xf0000000
+#define SHF_MIPS_GPREL	0x10000000
 
 /* special section indexes */
 #define SHN_UNDEF	0
@@ -415,6 +495,7 @@
 #define SHN_ABS		0xfff1
 #define SHN_COMMON	0xfff2
 #define SHN_HIRESERVE	0xffff
+#define SHN_MIPS_ACCOMON	0xff00
  
 typedef struct {
   Elf32_Word	sh_name;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/ext2_fs.h linux.pre11.3/include/linux/ext2_fs.h
--- linux.vanilla/include/linux/ext2_fs.h	Wed Apr 28 19:14:34 1999
+++ linux.pre11.3/include/linux/ext2_fs.h	Tue Jul 20 01:31:03 1999
@@ -504,6 +504,10 @@
 					 ~EXT2_DIR_ROUND)
 
 #ifdef __KERNEL__
+
+/* Filesize hard limits for 64-bit file offsets */
+extern long long ext2_max_sizes[];
+
 /*
  * Function prototypes
  */
@@ -564,6 +568,7 @@
 extern void ext2_put_inode (struct inode *);
 extern void ext2_delete_inode (struct inode *);
 extern int ext2_sync_inode (struct inode *);
+extern int ext2_notify_change(struct dentry *, struct iattr *);
 extern void ext2_discard_prealloc (struct inode *);
 
 /* ioctl.c */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/fs.h linux.pre11.3/include/linux/fs.h
--- linux.vanilla/include/linux/fs.h	Thu May 27 22:12:02 1999
+++ linux.pre11.3/include/linux/fs.h	Tue Jul 20 01:31:03 1999
@@ -269,6 +269,7 @@
 #include <linux/sysv_fs_i.h>
 #include <linux/affs_fs_i.h>
 #include <linux/ufs_fs_i.h>
+#include <linux/efs_fs_i.h>
 #include <linux/coda_fs_i.h>
 #include <linux/romfs_fs_i.h>
 #include <linux/smb_fs_i.h>
@@ -381,12 +382,13 @@
 		struct sysv_inode_info		sysv_i;
 		struct affs_inode_info		affs_i;
 		struct ufs_inode_info		ufs_i;
+		struct efs_inode_info		efs_i;
 		struct romfs_inode_info		romfs_i;
 		struct coda_inode_info		coda_i;
 		struct smb_inode_info		smbfs_i;
 		struct hfs_inode_info		hfs_i;
 		struct adfs_inode_info		adfs_i;
-		struct qnx4_inode_info		qnx4_i;	   
+		struct qnx4_inode_info		qnx4_i;
 		struct socket			socket_i;
 		void				*generic_ip;
 	} u;
@@ -505,6 +507,7 @@
 #include <linux/sysv_fs_sb.h>
 #include <linux/affs_fs_sb.h>
 #include <linux/ufs_fs_sb.h>
+#include <linux/efs_fs_sb.h>
 #include <linux/romfs_fs_sb.h>
 #include <linux/smb_fs_sb.h>
 #include <linux/hfs_fs_sb.h>
@@ -547,6 +550,7 @@
 		struct sysv_sb_info	sysv_sb;
 		struct affs_sb_info	affs_sb;
 		struct ufs_sb_info	ufs_sb;
+		struct efs_sb_info	efs_sb;
 		struct romfs_sb_info	romfs_sb;
 		struct smb_sb_info	smbfs_sb;
 		struct hfs_sb_info	hfs_sb;
@@ -639,7 +643,7 @@
 	int (*alloc_inode) (const struct inode *, unsigned long, uid_t);
 	void (*free_block) (const struct inode *, unsigned long);
 	void (*free_inode) (const struct inode *, unsigned long);
-	int (*transfer) (struct inode *, struct iattr *, char, uid_t);
+	int (*transfer) (struct dentry *, struct iattr *, uid_t);
 };
 
 struct file_system_type {
@@ -652,6 +656,10 @@
 extern int register_filesystem(struct file_system_type *);
 extern int unregister_filesystem(struct file_system_type *);
 
+/* Return value for VFS lock functions - tells locks.c to lock conventionally
+ * REALLY kosha for root NFS and nfs_lock
+ */ 
+#define LOCK_USE_CLNT 1
 
 #define FLOCK_VERIFY_READ  1
 #define FLOCK_VERIFY_WRITE 2
@@ -829,6 +837,8 @@
 #define lnamei(pathname)	__namei(pathname, 0)
 
 extern void iput(struct inode *);
+extern struct inode * igrab(struct inode *inode);
+extern ino_t iunique(struct super_block *, ino_t);
 extern struct inode * iget(struct super_block *, unsigned long);
 extern void clear_inode(struct inode *);
 extern struct inode * get_empty_inode(void);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/genhd.h linux.pre11.3/include/linux/genhd.h
--- linux.vanilla/include/linux/genhd.h	Wed Mar 24 10:55:27 1999
+++ linux.pre11.3/include/linux/genhd.h	Tue Jul 20 01:31:05 1999
@@ -11,6 +11,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
+#include <asm/unaligned.h>
 
 #define CONFIG_MSDOS_PARTITION 1
 
@@ -32,7 +33,9 @@
 #define LINUX_EXTENDED_PARTITION 0x85
 #define WIN98_EXTENDED_PARTITION 0x0f
 
-#define LINUX_SWAP_PARTITION	0x82
+#define LINUX_SWAP_PARTITION		0x82
+#define LINUX_RAID_PARTITION		0xfd	/* autodetect RAID partition */
+#define LINUX_OLD_RAID_PARTITION	0x86
 
 #ifdef CONFIG_SOLARIS_X86_PARTITION
 #define SOLARIS_X86_PARTITION	LINUX_SWAP_PARTITION
@@ -43,6 +46,7 @@
 #define DM6_AUX1PARTITION	0x51	/* no DDO:  use xlated geom */
 #define DM6_AUX3PARTITION	0x53	/* no DDO:  use xlated geom */
 	
+
 struct partition {
 	unsigned char boot_ind;		/* 0x80 - active */
 	unsigned char head;		/* starting head */
@@ -59,7 +63,31 @@
 struct hd_struct {
 	long start_sect;
 	long nr_sects;
+	int type;		/* RAID or normal */
 };
+
+/*
+ * partition types Linux cares about.
+ *
+ * currently there are 'normal' and RAID types.
+ */
+
+static inline unsigned int ptype (unsigned char raw_type)
+{
+	switch (raw_type) {
+		case LINUX_OLD_RAID_PARTITION:
+			return LINUX_OLD_RAID_PARTITION;
+		case LINUX_RAID_PARTITION:
+			return LINUX_RAID_PARTITION;
+		default:
+	}
+	return 0;
+}
+
+/*
+ * the maximum length a given partition name can take (eg. "scd11")
+ */
+#define MAX_DISKNAME_LEN 32
 
 struct gendisk {
 	int major;			/* major number of driver */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/i2c.h linux.pre11.3/include/linux/i2c.h
--- linux.vanilla/include/linux/i2c.h	Tue Jan 19 02:57:38 1999
+++ linux.pre11.3/include/linux/i2c.h	Tue Jul 20 00:15:11 1999
@@ -30,11 +30,15 @@
 struct i2c_driver;
 struct i2c_device;
 
-#define I2C_DRIVERID_MSP3400     1
-#define I2C_DRIVERID_TUNER       2
-#define I2C_DRIVERID_VIDEOTEXT	 3
+#define I2C_DRIVERID_MSP3400    	 1
+#define I2C_DRIVERID_TUNER      	 2
+#define I2C_DRIVERID_VIDEOTEXT		 3
+#define I2C_DRIVERID_VIDEODECODER	 4
+#define I2C_DRIVERID_VIDEOENCODER	 5
 
 #define I2C_BUSID_BT848		1	/* I2C bus on a BT848 */
+	/* 2 is used in 2.3.x */
+#define I2C_BUSID_BUZ		3	/* I2C bus on a BUZ */
 
 /*
  * struct for a driver for a i2c chip (tuner, soundprocessor,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/if_shaper.h linux.pre11.3/include/linux/if_shaper.h
--- linux.vanilla/include/linux/if_shaper.h	Wed Mar 10 21:13:11 1999
+++ linux.pre11.3/include/linux/if_shaper.h	Mon Jul 19 23:26:43 1999
@@ -23,7 +23,8 @@
 	__u32 shapeclock;
 	__u32 recovery;		/* Time we can next clock a packet out on
 				   an empty queue */
-	unsigned long locked;
+        unsigned long locked;
+        struct net_device_stats stats;
 	struct device *dev;
 	int  (*hard_start_xmit) (struct sk_buff *skb,
 		struct device *dev);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/isdn.h linux.pre11.3/include/linux/isdn.h
--- linux.vanilla/include/linux/isdn.h	Sun Jan 24 19:55:40 1999
+++ linux.pre11.3/include/linux/isdn.h	Tue Jul 20 00:15:27 1999
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.37 1998/02/22 19:45:24 fritz Exp $
+/* $Id: isdn.h,v 1.69 1999/07/13 20:47:53 werner Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -20,11 +20,92 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
- * Note: This file differs from the corresponding revision as present in the
- * isdn4linux CVS repository because some later bug fixes have been extracted
- * from the repository and merged into this file. -- Henner Eisen
- *
  * $Log: isdn.h,v $
+ * Revision 1.69  1999/07/13 20:47:53  werner
+ * added channel bit ISDN_USAGE_DISABLED for limiting b-channel access.
+ *
+ * Revision 1.68  1999/07/11 17:07:37  armin
+ * Added tty modem register S23.
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ *
+ * Revision 1.67  1999/07/07 10:17:24  detabc
+ * remove unused messages
+ *
+ * Revision 1.66  1999/07/01 08:35:37  keil
+ * compatibility to 2.3
+ *
+ * Revision 1.65  1999/06/10 11:51:27  paul
+ * fixed comment for NET_DV
+ *
+ * Revision 1.64  1999/04/18 14:57:14  fritz
+ * Removed TIMRU stuff
+ *
+ * Revision 1.63  1999/04/18 14:07:18  fritz
+ * Removed TIMRU stuff.
+ *
+ * Revision 1.62  1999/04/12 13:16:54  fritz
+ * Changes from 2.0 tree.
+ *
+ * Revision 1.61  1999/03/02 11:43:21  armin
+ * Added variable to store connect-message of Modem.
+ * Added Timer-define for RegS7 (Wait for Carrier).
+ *
+ * Revision 1.60  1998/10/25 14:50:29  fritz
+ * Backported from MIPS (Cobalt).
+ *
+ * Revision 1.59  1998/10/23 10:18:55  paul
+ * Implementation of "dialmode" (successor of "status")
+ * You also need current isdnctrl for this!
+ *
+ * Revision 1.58  1998/10/23 10:10:06  fritz
+ * Test-Checkin
+ *
+ * Revision 1.57  1998/08/31 21:10:01  he
+ * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface'
+ *     peer phone number)
+ *
+ * Revision 1.56  1998/07/26 18:46:52  armin
+ * Added silence detection in voice receive mode.
+ *
+ * Revision 1.55  1998/06/26 15:13:17  fritz
+ * Added handling of STAT_ICALL with incomplete CPN.
+ * Added AT&L for ttyI emulator.
+ * Added more locking stuff in tty_write.
+ *
+ * Revision 1.54  1998/06/18 23:32:01  fritz
+ * Replaced cli()/restore_flags() in isdn_tty_write() by locking.
+ * Removed direct-senddown feature in isdn_tty_write because it will
+ * never succeed with locking and is useless anyway.
+ *
+ * Revision 1.53  1998/06/17 19:51:51  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.46  1998/04/14 16:28:59  he
+ * Fixed user space access with interrupts off and remaining
+ * copy_{to,from}_user() -> -EFAULT return codes
+ *
+ * Revision 1.45  1998/03/24 16:33:12  hipp
+ * More CCP changes. BSD compression now "works" on a local loopback link.
+ * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h
+ *
+ * Revision 1.44  1998/03/22 18:50:56  hipp
+ * Added BSD Compression for syncPPP .. UNTESTED at the moment
+ *
+ * Revision 1.43  1998/03/09 17:46:44  he
+ * merged in 2.1.89 changes
+ *
+ *
+ * Revision 1.40  1998/03/08 01:08:29  fritz
+ * Increased NET_DV because of TIMRU
+ *
+ * Revision 1.39  1998/03/07 22:42:49  fritz
+ * Starting generic module support (Nothing usable yet).
+ *
+ * Revision 1.38  1998/03/07 18:21:29  cal
+ * Dynamic Timeout-Rule-Handling vs. 971110 included
+ *
  * Revision 1.37  1998/02/22 19:45:24  fritz
  * Some changes regarding V.110
  *
@@ -163,6 +244,8 @@
 #ifndef isdn_h
 #define isdn_h
 
+#include <linux/isdn_compat.h>
+#include <linux/config.h>
 #include <linux/ioctl.h>
 
 #define ISDN_TTY_MAJOR    43
@@ -174,14 +257,20 @@
  * the correspondent code in isdn.c
  */
 
+#ifdef CONFIG_COBALT_MICRO_SERVER
+/* Save memory */
+#define ISDN_MAX_DRIVERS    2
+#define ISDN_MAX_CHANNELS   8
+#else
 #define ISDN_MAX_DRIVERS    32
 #define ISDN_MAX_CHANNELS   64
+#endif
 #define ISDN_MINOR_B        0
 #define ISDN_MINOR_BMAX     (ISDN_MAX_CHANNELS-1)
-#define ISDN_MINOR_CTRL     ISDN_MAX_CHANNELS
-#define ISDN_MINOR_CTRLMAX  (2*ISDN_MAX_CHANNELS-1)
-#define ISDN_MINOR_PPP      (2*ISDN_MAX_CHANNELS)
-#define ISDN_MINOR_PPPMAX   (3*ISDN_MAX_CHANNELS-1)
+#define ISDN_MINOR_CTRL     64
+#define ISDN_MINOR_CTRLMAX  (64 + (ISDN_MAX_CHANNELS-1))
+#define ISDN_MINOR_PPP      128
+#define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
 #define ISDN_MINOR_STATUS   255
 
 /* New ioctl-codes */
@@ -192,8 +281,8 @@
 #define IIOCNETANM  _IO('I',5)
 #define IIOCNETDNM  _IO('I',6)
 #define IIOCNETGNM  _IO('I',7)
-#define IIOCGETSET  _IO('I',8)
-#define IIOCSETSET  _IO('I',9)
+#define IIOCGETSET  _IO('I',8) /* no longer supported */
+#define IIOCSETSET  _IO('I',9) /* no longer supported */
 #define IIOCSETVER  _IO('I',10)
 #define IIOCNETHUP  _IO('I',11)
 #define IIOCSETGST  _IO('I',12)
@@ -211,6 +300,8 @@
 #define IIOCNETALN  _IO('I',32)
 #define IIOCNETDLN  _IO('I',33)
 
+#define IIOCNETGPN  _IO('I',34)
+
 #define IIOCDBGVAR  _IO('I',127)
 
 #define IIOCDRVCTL  _IO('I',128)
@@ -233,11 +324,14 @@
 #define ISDN_USAGE_VOICE      4
 #define ISDN_USAGE_FAX        5
 #define ISDN_USAGE_MASK       7 /* Mask to get plain usage */
+#define ISDN_USAGE_DISABLED  32 /* This bit is set, if channel is disabled */
 #define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
 #define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing  */
 
-#define ISDN_MODEM_ANZREG    23        /* Number of Modem-Registers        */
+#define ISDN_MODEM_ANZREG    24        /* Number of Modem-Registers        */
 #define ISDN_MSNLEN          20
+#define ISDN_LMSNLEN         255 /* Length of tty's Listen-MSN string */
+#define ISDN_CMSGLEN	     50	 /* Length of CONNECT-Message to add for Modem */
 
 typedef struct {
   char drvid[25];
@@ -256,8 +350,9 @@
   int  outgoing;
 } isdn_net_ioctl_phone;
 
-#define NET_DV 0x04 /* Data version for net_cfg     */
-#define TTY_DV 0x04 /* Data version for iprofd etc. */
+#define NET_DV 0x05  /* Data version for isdn_net_ioctl_cfg   */
+#define TTY_DV 0x05  /* Data version for iprofd etc.          */
+#define INF_DV 0x01  /* Data version for /dev/isdninfo        */
 
 typedef struct {
   char name[10];     /* Name of interface                     */
@@ -282,8 +377,17 @@
   int  pppbind;      /* ippp device for bindings              */
   int  chargeint;    /* Use fixed charge interval length      */
   int  triggercps;   /* BogoCPS needed for triggering slave   */
+  int  dialtimeout;  /* Dial-Timeout                          */
+  int  dialwait;     /* Time to wait after failed dial        */
+  int  dialmode;     /* Flag: off / on / auto                 */
 } isdn_net_ioctl_cfg;
 
+#define ISDN_NET_DIALMODE_MASK 0xC0  /* bits for status                   */
+#define  ISDN_NET_DM_OFF	0x00    /* this interface is stopped      */
+#define  ISDN_NET_DM_MANUAL	0x40    /* this interface is on (manual)  */
+#define  ISDN_NET_DM_AUTO	0x80    /* this interface is autodial     */
+#define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK)
+
 #ifdef __KERNEL__
 
 #ifndef STANDALONE
@@ -331,6 +435,7 @@
 
 #include <linux/isdnif.h>
 
+
 #define ISDN_DRVIOCTL_MASK       0x7f  /* Mask for Device-ioctl */
 
 /* Until now unused */
@@ -354,6 +459,7 @@
 #define USG_MODEM(x)        ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM)
 #define USG_VOICE(x)        ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)
 #define USG_NET(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET)
+#define USG_FAX(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX)
 #define USG_OUTGOING(x)     ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING)
 #define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \
                              ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)     )
@@ -372,14 +478,17 @@
 #define ISDN_TIMER_NETHANGUP  32
 #define ISDN_TIMER_IPPP       64 
 #define ISDN_TIMER_KEEPALIVE 128 /* Cisco-Keepalive */
+#define ISDN_TIMER_CARRIER   256 /* Wait for Carrier */
 #define ISDN_TIMER_FAST      (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
                               ISDN_TIMER_MODEMXMIT)
 #define ISDN_TIMER_SLOW      (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
-                              ISDN_TIMER_NETDIAL | ISDN_TIMER_KEEPALIVE)
+                              ISDN_TIMER_NETDIAL | ISDN_TIMER_KEEPALIVE | \
+                              ISDN_TIMER_CARRIER)
 
 /* Timeout-Values for isdn_net_dial() */
 #define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
 #define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
+#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
 
 /* GLOBAL_FLAGS */
 #define ISDN_GLOBAL_STOPPED 1
@@ -398,6 +507,7 @@
 #define ISDN_NET_TMP        0x10       /* tmp interface until getting an IP */
 #define ISDN_NET_DYNAMIC    0x20       /* this link is dynamically allocated */
 #endif
+
 #define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
 
 /* Phone-list-element */
@@ -488,6 +598,11 @@
 				    struct device *,
                                     unsigned char *);
   int  pppbind;                        /* ippp device for bindings         */
+  int					dialtimeout;	/* How long shall we try on dialing? (jiffies) */
+  int					dialwait;		/* How long shall we wait after failed attempt? (jiffies) */
+  ulong					dialstarted;	/* jiffies of first dialing-attempt */
+  ulong					dialwait_timer;	/* jiffies of earliest next dialing-attempt */
+  int					huptimeout;		/* How long will the connection be up? (seconds) */
 #ifdef CONFIG_ISDN_X25
   struct concap_device_ops *dops;      /* callbacks used by encapsulator   */
 #endif
@@ -496,18 +611,6 @@
   ulong cisco_yourseq;                 /* Remote keepalive seq. for Cisco  */
 } isdn_net_local;
 
-#ifdef CONFIG_ISDN_PPP
-struct ippp_bundle {
-  int mp_mrru;                        /* unused                             */
-  struct mpqueue *last;               /* currently defined in isdn_net_dev  */
-  int min;                            /* currently calculated 'on the fly'  */
-  long next_num;                      /* we wanna see this seq.-number next */
-  struct sqqueue *sq;
-  int modify:1;                       /* set to 1 while modifying sqqueue   */
-  int bundled:1;                      /* bundle active ?                    */
-};
-#endif
-
 /* the interface itself */
 typedef struct isdn_net_dev_s {
   isdn_net_local *local;
@@ -567,6 +670,10 @@
 	u_char       mdmreg[ISDN_MODEM_ANZREG];  /* Modem-Registers                    */
 	char         pmsn[ISDN_MSNLEN];          /* EAZ/MSNs Profile 0                 */
 	char         msn[ISDN_MSNLEN];           /* EAZ/MSN                            */
+	char         plmsn[ISDN_LMSNLEN];        /* Listening MSNs Profile 0           */
+	char         lmsn[ISDN_LMSNLEN];         /* Listening MSNs                     */
+	char         cpn[ISDN_MSNLEN];           /* CalledPartyNumber on incoming call */
+	char         connmsg[ISDN_CMSGLEN];	 /* CONNECT-Msg from HL-Driver	       */
 #ifdef CONFIG_ISDN_AUDIO
 	u_char       vpar[10];                   /* Voice-parameters                   */
 	int          lastDLE;                    /* Flag for voice-coding: DLE seen    */
@@ -574,6 +681,7 @@
 	int          mdmcmdl;                    /* Length of Modem-Commandbuffer      */
 	int          pluscount;                  /* Counter for +++ sequence           */
 	int          lastplus;                   /* Timestamp of last +                */
+	int	     carrierwait;                /* Seconds of carrier waiting         */
 	char         mdmcmd[255];                /* Modem-Commandbuffer                */
 	unsigned int charge;                     /* Charge units of current connection */
 } atemu;
@@ -593,7 +701,7 @@
   long			pgrp;		 /* pgrp of opening process        */
   int                   online;          /* 1 = B-Channel is up, drop data */
 					 /* 2 = B-Channel is up, deliver d.*/
-  int                   dialing;         /* Dial in progress               */
+  int                   dialing;         /* Dial in progress or ATA        */
   int                   rcvsched;        /* Receive needs schedule         */
   int                   isdn_driver;	 /* Index to isdn-driver           */
   int                   isdn_channel;    /* Index to isdn-channel          */
@@ -612,6 +720,7 @@
   int                   xmit_count;      /* # of chars in xmit_buf         */
   unsigned char         *xmit_buf;       /* transmit buffer                */
   struct sk_buff_head   xmit_queue;      /* transmit queue                 */
+  atomic_t              xmit_lock;       /* Semaphore for isdn_tty_write   */
 #ifdef CONFIG_ISDN_AUDIO
   int                   vonline;         /* Voice-channel status           */
 					 /* Bit 0 = recording              */
@@ -621,13 +730,19 @@
   void                  *adpcms;         /* state for adpcm decompression  */
   void                  *adpcmr;         /* state for adpcm compression    */
   void                  *dtmf_state;     /* state for dtmf decoder         */
+  void                  *silence_state;  /* state for silence detection    */
 #endif
   struct tty_struct 	*tty;            /* Pointer to corresponding tty   */
   atemu                 emu;             /* AT-emulator data               */
   struct termios	normal_termios;  /* For saving termios structs     */
   struct termios	callout_termios;
+#ifdef COMPAT_HAS_NEW_WAITQ
+  wait_queue_head_t	open_wait, close_wait;
+#else
   struct wait_queue	*open_wait;
   struct wait_queue	*close_wait;
+#endif
+  struct semaphore      write_sem;
 } modem_info;
 
 #define ISDN_MODEM_WINSIZE 8
@@ -645,72 +760,6 @@
 
 /*======================= End of ISDN-tty stuff ============================*/
 
-/*======================= Start of sync-ppp stuff ==========================*/
-
-
-#define NUM_RCV_BUFFS     64
-#define PPP_HARD_HDR_LEN 4
-
-#ifdef CONFIG_ISDN_PPP
-
-struct sqqueue {
-  struct sqqueue *next;
-  long sqno_start;
-  long sqno_end;
-  struct sk_buff *skb;
-  long timer;
-};
-  
-struct mpqueue {
-  struct mpqueue *next;
-  struct mpqueue *last;
-  long sqno;
-  struct sk_buff *skb;
-  int BEbyte;
-  unsigned long time;
-}; 
-
-struct ippp_buf_queue {
-  struct ippp_buf_queue *next;
-  struct ippp_buf_queue *last;
-  char *buf;                 /* NULL here indicates end of queue */
-  int len;
-};
-
-struct ippp_struct {
-  struct ippp_struct *next_link;
-  int state;
-  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
-  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
-  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
-  struct wait_queue *wq;
-  struct wait_queue *wq1;
-  struct task_struct *tk;
-  unsigned int mpppcfg;
-  unsigned int pppcfg;
-  unsigned int mru;
-  unsigned int mpmru;
-  unsigned int mpmtu;
-  unsigned int maxcid;
-  isdn_net_local *lp;
-  int unit; 
-  int minor;
-  long last_link_seqno;
-  long mp_seqno;
-  long range;
-#ifdef CONFIG_ISDN_PPP_VJ
-  unsigned char *cbuf;
-  struct slcompress *slcomp;
-#endif
-  unsigned long debug;
-  struct isdn_ppp_compressor *compressor,*link_compressor;
-  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
-};
-
-#endif
-
-/*======================== End of sync-ppp stuff ===========================*/
-
 /*======================== Start of V.110 stuff ============================*/
 #define V110_BUFSIZE 1024
 
@@ -743,69 +792,103 @@
 	char *private;
 } infostruct;
 
+typedef struct isdn_module {
+	struct isdn_module *prev;
+	struct isdn_module *next;
+	char *name;
+	int (*get_free_channel)(int, int, int, int, int);
+	int (*free_channel)(int, int, int);
+	int (*status_callback)(isdn_ctrl *);
+	int (*command)(isdn_ctrl *);
+	int (*receive_callback)(int, int, struct sk_buff *);
+	int (*writebuf_skb)(int, int, int, struct sk_buff *);
+	int (*net_start_xmit)(struct sk_buff *, struct device *);
+	int (*net_receive)(struct device *, struct sk_buff *);
+	int (*net_open)(struct device *);
+	int (*net_close)(struct device *);
+	int priority;
+} isdn_module;
+
+#define DRV_FLAG_RUNNING 1
+#define DRV_FLAG_REJBUS  2
+#define DRV_FLAG_LOADED  4
+
 /* Description of hardware-level-driver */
 typedef struct {
-  ulong               flags;            /* Flags                            */
-  int                 channels;         /* Number of channels               */
-  int                 reject_bus;       /* Flag: Reject rejected call on bus*/
-  struct wait_queue  *st_waitq;         /* Wait-Queue for status-read's     */
-  int                 maxbufsize;       /* Maximum Buffersize supported     */
-  unsigned long       pktcount;         /* Until now: unused                */
-  int                 running;          /* Flag: Protocolcode running       */
-  int                 loaded;           /* Flag: Driver loaded              */
-  int                 stavail;          /* Chars avail on Status-device     */
-  isdn_if            *interface;        /* Interface to driver              */
-  int                *rcverr;           /* Error-counters for B-Ch.-receive */
-  int                *rcvcount;         /* Byte-counters for B-Ch.-receive  */
+	ulong               online;           /* Channel-Online flags             */
+	ulong               flags;            /* Misc driver Flags                */
+	int                 locks;            /* Number of locks for this driver  */
+	int                 channels;         /* Number of channels               */
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
+#else
+	struct wait_queue  *st_waitq;         /* Wait-Queue for status-read's     */
+#endif
+	int                 maxbufsize;       /* Maximum Buffersize supported     */
+	unsigned long       pktcount;         /* Until now: unused                */
+	int                 stavail;          /* Chars avail on Status-device     */
+	isdn_if            *interface;        /* Interface to driver              */
+	int                *rcverr;           /* Error-counters for B-Ch.-receive */
+	int                *rcvcount;         /* Byte-counters for B-Ch.-receive  */
 #ifdef CONFIG_ISDN_AUDIO
-  unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
+	unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
 #endif
-  struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
-  struct wait_queue  **rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
-  struct wait_queue  **snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
-  char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
+	struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t  *rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
+	wait_queue_head_t  *snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
+#else
+	struct wait_queue  **rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
+	struct wait_queue  **snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
+#endif
+	char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
 } driver;
 
 /* Main driver-data */
 typedef struct isdn_devt {
-  unsigned short    flags;		       /* Bitmapped Flags:           */
-				               /*                            */
-  int               drivers;		       /* Current number of drivers  */
-  int               channels;		       /* Current number of channels */
-  int               net_verbose;               /* Verbose-Flag               */
-  int               modempoll;		       /* Flag: tty-read active      */
-  int               tflags;                    /* Timer-Flags:               */
-				               /*  see ISDN_TIMER_..defines  */
-  int               global_flags;
-  infostruct        *infochain;                /* List of open info-devs.    */
-  struct wait_queue *info_waitq;               /* Wait-Queue for isdninfo    */
-  struct timer_list timer;		       /* Misc.-function Timer       */
-  int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
-  int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
-  int               usage[ISDN_MAX_CHANNELS];  /* Used by tty/ip/voice       */
-  char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
-                                               /* Remote number of active ch.*/
-  int               m_idx[ISDN_MAX_CHANNELS];  /* Index for mdm....          */
-  driver            *drv[ISDN_MAX_DRIVERS];    /* Array of drivers           */
-  isdn_net_dev      *netdev;		       /* Linked list of net-if's    */
-  char              drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID                 */
-  struct task_struct *profd;                   /* For iprofd                 */
-  modem             mdm;		       /* tty-driver-data            */
-  isdn_net_dev      *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers     */
-  isdn_net_dev      *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers   */
-  ulong             ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes  */
-  ulong             obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes  */
-  int               v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
-  atomic_t          v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
-  isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
-  struct semaphore  sem;                       /* serialize list access*/
+	unsigned short    flags;		       /* Bitmapped Flags:           */
+	/*                            */
+	int               drivers;		       /* Current number of drivers  */
+	int               channels;		       /* Current number of channels */
+	int               net_verbose;               /* Verbose-Flag               */
+	int               modempoll;		       /* Flag: tty-read active      */
+	int               tflags;                    /* Timer-Flags:               */
+	/*  see ISDN_TIMER_..defines  */
+	int               global_flags;
+	infostruct        *infochain;                /* List of open info-devs.    */
+#ifdef COMPAT_HAS_NEW_WAITQ
+	wait_queue_head_t info_waitq;               /* Wait-Queue for isdninfo    */
+#else
+	struct wait_queue *info_waitq;               /* Wait-Queue for isdninfo    */
+#endif
+	struct timer_list timer;		       /* Misc.-function Timer       */
+	int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
+	int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
+	int               usage[ISDN_MAX_CHANNELS];  /* Used by tty/ip/voice       */
+	char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
+	/* Remote number of active ch.*/
+	int               m_idx[ISDN_MAX_CHANNELS];  /* Index for mdm....          */
+	driver            *drv[ISDN_MAX_DRIVERS];    /* Array of drivers           */
+	isdn_net_dev      *netdev;		       /* Linked list of net-if's    */
+	char              drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID                 */
+	struct task_struct *profd;                   /* For iprofd                 */
+	modem             mdm;		       /* tty-driver-data            */
+	isdn_net_dev      *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers     */
+	isdn_net_dev      *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers   */
+	ulong             ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes  */
+	ulong             obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes  */
+	int               v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
+	atomic_t          v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
+	isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
+	struct semaphore  sem;                       /* serialize list access*/
+	isdn_module       *modules;
 } isdn_dev;
 
 extern isdn_dev *dev;
 
+
 /* Utility-Macros */
 #define MIN(a,b) ((a<b)?a:b)
 #define MAX(a,b) ((a>b)?a:b)
-
 #endif /* __KERNEL__ */
 #endif /* isdn_h */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/isdn_compat.h linux.pre11.3/include/linux/isdn_compat.h
--- linux.vanilla/include/linux/isdn_compat.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/isdn_compat.h	Tue Jul 20 00:15:27 1999
@@ -0,0 +1,102 @@
+#ifdef __KERNEL__
+/* Compatibility for various Linux kernel versions */
+
+#ifndef _LINUX_ISDN_COMPAT_H
+#define _LINUX_ISDN_COMPAT_H
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+#ifndef KERNEL_VERSION
+#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
+#include <linux/mm.h>
+
+#define ioremap vremap
+#define iounmap vfree
+
+static inline unsigned long copy_from_user(void *to, const void *from, unsigned long n)
+{
+	int i;
+	if ((i = verify_area(VERIFY_READ, from, n)) != 0)
+		return i;
+	memcpy_fromfs(to, from, n);
+	return 0;
+}
+
+static inline unsigned long copy_to_user(void *to, const void *from, unsigned long n)
+{
+	int i;
+	if ((i = verify_area(VERIFY_WRITE, to, n)) != 0)
+		return i;
+	memcpy_tofs(to, from, n);
+	return 0;
+}
+
+#define GET_USER(x, addr) ( x = get_user(addr) )
+#ifdef __alpha__ /* needed for 2.0.x with alpha-patches */
+#define RWTYPE long
+#define LSTYPE long
+#define RWARG unsigned long
+#else
+#define RWTYPE int
+#define LSTYPE int
+#define RWARG int
+#endif
+#define LSARG off_t
+#else
+#include <asm/uaccess.h>
+#define GET_USER get_user
+#define PUT_USER put_user
+#define RWTYPE long
+#define LSTYPE long long
+#define RWARG unsigned long
+#define LSARG long long
+#endif /* LINUX_VERSION_CODE */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,15)
+#define SET_SKB_FREE(x) ( x->free = 1 )
+#define idev_kfree_skb(a,b) dev_kfree_skb(a,b)
+#else
+#define SET_SKB_FREE(x)
+#define idev_kfree_skb(a,b) dev_kfree_skb(a)
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,18)
+#define COMPAT_HAS_NEW_SYMTAB
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31)
+#define CLOSETYPE void
+#define CLOSEVAL
+#else
+#define CLOSETYPE int
+#define CLOSEVAL (0)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,37)
+#define test_and_clear_bit clear_bit
+#define test_and_set_bit set_bit
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,81)
+#define kstat_irqs( PAR ) kstat.interrupts[PAR]
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,91)
+#define COMPAT_HAS_NEW_PCI
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127)
+#define schedule_timeout(a) current->timeout = jiffies + (a); schedule ();
+#endif
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
+#define COMPAT_HAS_NEW_WAITQ
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ISDN_COMPAT_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/isdn_divertif.h linux.pre11.3/include/linux/isdn_divertif.h
--- linux.vanilla/include/linux/isdn_divertif.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/isdn_divertif.h	Tue Jul 20 00:15:27 1999
@@ -0,0 +1,62 @@
+/* 
+ * $Id: isdn_divertif.h,v 1.3 1999/07/05 20:22:00 werner Exp $
+ *
+ * Header for the diversion supplementary interface for i4l.
+ *
+ * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
+ * $Log: isdn_divertif.h,v $
+ * Revision 1.3  1999/07/05 20:22:00  werner
+ * changes to use diversion sources for all kernel versions.
+ * removed static device, only proc filesystem used
+ *
+ * Revision 1.2  1999/07/04 21:38:38  werner
+ * ported from kernel version 2.0
+ *
+ *
+ */
+
+
+/***********************************************************/
+/* magic value is also used to control version information */
+/***********************************************************/
+#define DIVERT_IF_MAGIC 0x25873401
+#define DIVERT_CMD_REG  0x00  /* register command */
+#define DIVERT_CMD_REL  0x01  /* release command */
+#define DIVERT_NO_ERR   0x00  /* return value no error */
+#define DIVERT_CMD_ERR  0x01  /* invalid cmd */
+#define DIVERT_VER_ERR  0x02  /* magic/version invalid */
+#define DIVERT_REG_ERR  0x03  /* module already registered */
+#define DIVERT_REL_ERR  0x04  /* module not registered */
+#define DIVERT_REG_NAME isdn_register_divert
+
+/***************************************************************/
+/* structure exchanging data between isdn hl and divert module */
+/***************************************************************/ 
+typedef struct
+  { ulong if_magic; /* magic info and version */
+    int cmd; /* command */
+    int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */
+    int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
+    char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
+    int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
+  } isdn_divert_if;
+
+/*********************/
+/* function register */
+/*********************/
+extern int DIVERT_REG_NAME(isdn_divert_if *);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/isdn_ppp.h linux.pre11.3/include/linux/isdn_ppp.h
--- linux.vanilla/include/linux/isdn_ppp.h	Sun Nov  8 15:06:49 1998
+++ linux.pre11.3/include/linux/isdn_ppp.h	Tue Jul 20 00:15:27 1999
@@ -1,19 +1,22 @@
+/* -*- mode: c; c-basic-offset: 2 -*- */
+
 #ifndef _LINUX_ISDN_PPP_H
 #define _LINUX_ISDN_PPP_H
 
-extern int isdn_ppp_dial_slave(char *);
-extern int isdn_ppp_hangup_slave(char *);
+#include <linux/isdn_compat.h>
 
 #define CALLTYPE_INCOMING 0x1
 #define CALLTYPE_OUTGOING 0x2
 #define CALLTYPE_CALLBACK 0x4
 
+#define IPPP_VERSION    "2.2.0"
+
 struct pppcallinfo
 {
-	int calltype;
-	unsigned char local_num[64];
-	unsigned char remote_num[64];
-	int charge_units;
+  int calltype;
+  unsigned char local_num[64];
+  unsigned char remote_num[64];
+  int charge_units;
 };
 
 #define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo)
@@ -22,50 +25,216 @@
 #define PPPIOCSMPFLAGS _IOW('t',131,int)
 #define PPPIOCSMPMTU   _IOW('t',132,int)
 #define PPPIOCSMPMRU   _IOW('t',133,int)
-#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long)
+#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8])
 #define PPPIOCSCOMPRESSOR _IOW('t',135,int)
+#define PPPIOCGIFNAME      _IOR('t',136, char [IFNAMSIZ] )
 
 #define PPP_MP          0x003d
 #define PPP_LINK_COMP   0x00fb
+#define PPP_LINK_CCP    0x80fb
 
 #define SC_MP_PROT       0x00000200
 #define SC_REJ_MP_PROT   0x00000400
 #define SC_OUT_SHORT_SEQ 0x00000800
 #define SC_IN_SHORT_SEQ  0x00004000
 
+#define SC_DECOMP_ON		0x01
+#define SC_COMP_ON		0x02
+#define SC_DECOMP_DISCARD	0x04
+#define SC_COMP_DISCARD		0x08
+#define SC_LINK_DECOMP_ON	0x10
+#define SC_LINK_COMP_ON		0x20
+#define SC_LINK_DECOMP_DISCARD	0x40
+#define SC_LINK_COMP_DISCARD	0x80
+
+#define DECOMP_ERR_NOMEM	(-10)
+
 #define MP_END_FRAG    0x40
 #define MP_BEGIN_FRAG  0x80
 
+#define ISDN_PPP_COMP_MAX_OPTIONS 16
+
+#define IPPP_COMP_FLAG_XMIT 0x1
+#define IPPP_COMP_FLAG_LINK 0x2
+
+struct isdn_ppp_comp_data {
+  int num;
+  unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
+  int optlen;
+  int flags;
+};
+
 #ifdef __KERNEL__
+
+/*
+ * We need a way for the decompressor to influence the generation of CCP
+ * Reset-Requests in a variety of ways. The decompressor is already returning
+ * a lot of information (generated skb length, error conditions) so we use
+ * another parameter. This parameter is a pointer to a structure which is
+ * to be marked valid by the decompressor and only in this case is ever used.
+ * Furthermore, the only case where this data is used is when the decom-
+ * pressor returns DECOMP_ERROR.
+ *
+ * We use this same struct for the reset entry of the compressor to commu-
+ * nicate to its caller how to deal with sending of a Reset Ack. In this
+ * case, expra is not used, but other options still apply (supressing
+ * sending with rsend, appending arbitrary data, etc).
+ */
+
+#define IPPP_RESET_MAXDATABYTES	32
+
+struct isdn_ppp_resetparams {
+  unsigned char valid:1;	/* rw Is this structure filled at all ? */
+  unsigned char rsend:1;	/* rw Should we send one at all ? */
+  unsigned char idval:1;	/* rw Is the id field valid ? */
+  unsigned char dtval:1;	/* rw Is the data field valid ? */
+  unsigned char expra:1;	/* rw Is an Ack expected for this Req ? */
+  unsigned char id;		/* wo Send CCP ResetReq with this id */
+  unsigned short maxdlen;	/* ro Max bytes to be stored in data field */
+  unsigned short dlen;		/* rw Bytes stored in data field */
+  unsigned char *data;		/* wo Data for ResetReq info field */
+};
+
 /*
  * this is an 'old friend' from ppp-comp.h under a new name 
  * check the original include for more information
  */
 struct isdn_ppp_compressor {
-	struct isdn_ppp_compressor *next,*prev;
-	int num; /* CCP compression protocol number */
-	void *(*comp_alloc) (unsigned char *options, int opt_len);
-	void (*comp_free) (void *state);
-	int  (*comp_init) (void *state, unsigned char *options, int opt_len,
-		 int unit, int opthdr, int debug);
-	void (*comp_reset) (void *state);
-	int  (*compress) (void *state,struct sk_buff *in, struct sk_buff *skb_out,
-		 int proto);
-	void (*comp_stat) (void *state, struct compstat *stats);
-	void *(*decomp_alloc) (unsigned char *options, int opt_len);
-	void (*decomp_free) (void *state);
-	int  (*decomp_init) (void *state, unsigned char *options,
-			int opt_len, int unit, int opthdr, int mru, int debug);
-	void (*decomp_reset) (void *state);
-	int  (*decompress) (void *state, unsigned char *ibuf, int isize, unsigned char *obuf, int osize);
-	void (*incomp) (void *state, unsigned char *ibuf, int icnt);
-	void (*decomp_stat) (void *state, struct compstat *stats);
+  struct isdn_ppp_compressor *next, *prev;
+  int num; /* CCP compression protocol number */
+  
+  void *(*alloc) (struct isdn_ppp_comp_data *);
+  void (*free) (void *state);
+  int  (*init) (void *state, struct isdn_ppp_comp_data *,
+		int unit,int debug);
+  
+  /* The reset entry needs to get more exact information about the
+     ResetReq or ResetAck it was called with. The parameters are
+     obvious. If reset is called without a Req or Ack frame which
+     could be handed into it, code MUST be set to 0. Using rsparm,
+     the reset entry can control if and how a ResetAck is returned. */
+  
+  void (*reset) (void *state, unsigned char code, unsigned char id,
+		 unsigned char *data, unsigned len,
+		 struct isdn_ppp_resetparams *rsparm);
+  
+  int  (*compress) (void *state, struct sk_buff *in,
+		    struct sk_buff *skb_out, int proto);
+  
+	int  (*decompress) (void *state,struct sk_buff *in,
+			    struct sk_buff *skb_out,
+			    struct isdn_ppp_resetparams *rsparm);
+  
+  void (*incomp) (void *state, struct sk_buff *in,int proto);
+  void (*stat) (void *state, struct compstat *stats);
 };
 
 extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *);
 extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
+extern int isdn_ppp_dial_slave(char *);
+extern int isdn_ppp_hangup_slave(char *);
 
-#endif /* __KERNEL__ */
+struct ippp_bundle {
+  int mp_mrru;                        /* unused                             */
+  struct mpqueue *last;               /* currently defined in isdn_net_dev  */
+  int min;                            /* currently calculated 'on the fly'  */
+  long next_num;                      /* we wanna see this seq.-number next */
+  struct sqqueue *sq;
+  int modify:1;                       /* set to 1 while modifying sqqueue   */
+  int bundled:1;                      /* bundle active ?                    */
+};
 
-#endif /* _LINUX_ISDN_PPP_H */
+#define NUM_RCV_BUFFS     64
+
+struct sqqueue {
+  struct sqqueue *next;
+  long sqno_start;
+  long sqno_end;
+  struct sk_buff *skb;
+  long timer;
+};
 
+struct mpqueue {
+  struct mpqueue *next;
+  struct mpqueue *last;
+  long sqno;
+  struct sk_buff *skb;
+  int BEbyte;
+  unsigned long time;
+};
+
+struct ippp_buf_queue {
+  struct ippp_buf_queue *next;
+  struct ippp_buf_queue *last;
+  char *buf;                 /* NULL here indicates end of queue */
+  int len;
+};
+
+/* The data structure for one CCP reset transaction */
+enum ippp_ccp_reset_states {
+  CCPResetIdle,
+  CCPResetSentReq,
+  CCPResetRcvdReq,
+  CCPResetSentAck,
+  CCPResetRcvdAck
+};
+
+struct ippp_ccp_reset_state {
+  enum ippp_ccp_reset_states state;	/* State of this transaction */
+  struct ippp_struct *is;		/* Backlink to device stuff */
+  unsigned char id;			/* Backlink id index */
+  unsigned char ta:1;			/* The timer is active (flag) */
+  unsigned char expra:1;		/* We expect a ResetAck at all */
+  int dlen;				/* Databytes stored in data */
+  struct timer_list timer;		/* For timeouts/retries */
+  /* This is a hack but seems sufficient for the moment. We do not want
+     to have this be yet another allocation for some bytes, it is more
+     memory management overhead than the whole mess is worth. */
+  unsigned char data[IPPP_RESET_MAXDATABYTES];
+};
+
+/* The data structure keeping track of the currently outstanding CCP Reset
+   transactions. */
+struct ippp_ccp_reset {
+  struct ippp_ccp_reset_state *rs[256];	/* One per possible id */
+  unsigned char lastid;			/* Last id allocated by the engine */
+};
+
+struct ippp_struct {
+  struct ippp_struct *next_link;
+  int state;
+  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
+  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
+  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
+#ifdef COMPAT_HAS_NEW_WAITQ
+  wait_queue_head_t wq;
+#else
+  struct wait_queue *wq;
+#endif
+  struct task_struct *tk;
+  unsigned int mpppcfg;
+  unsigned int pppcfg;
+  unsigned int mru;
+  unsigned int mpmru;
+  unsigned int mpmtu;
+  unsigned int maxcid;
+  struct isdn_net_local_s *lp;
+  int unit;
+  int minor;
+  long last_link_seqno;
+  long mp_seqno;
+  long range;
+#ifdef CONFIG_ISDN_PPP_VJ
+  unsigned char *cbuf;
+  struct slcompress *slcomp;
+#endif
+  unsigned long debug;
+  struct isdn_ppp_compressor *compressor,*decompressor;
+  struct isdn_ppp_compressor *link_compressor,*link_decompressor;
+  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
+  struct ippp_ccp_reset *reset;	/* Allocated on demand, may never be needed */
+  unsigned long compflags;
+};
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_ISDN_PPP_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/isdnif.h linux.pre11.3/include/linux/isdnif.h
--- linux.vanilla/include/linux/isdnif.h	Sun Nov  8 15:06:49 1998
+++ linux.pre11.3/include/linux/isdnif.h	Tue Jul 20 00:15:27 1999
@@ -1,8 +1,4 @@
-/* X25 changes:
-   Added constants ISDN_PROTO_L2_X25DTE/DCE and corresponding ISDN_FEATURE_..
-   */
-
-/* $Id: isdnif.h,v 1.23 1998/02/20 17:36:52 fritz Exp $
+/* $Id: isdnif.h,v 1.28 1999/07/13 20:57:48 werner Exp $
  *
  * Linux ISDN subsystem
  *
@@ -26,6 +22,25 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdnif.h,v $
+ * Revision 1.28  1999/07/13 20:57:48  werner
+ * added callback ISDN_STAT_DISCH for limiting b-channel resources.
+ *
+ * Revision 1.27  1999/07/11 17:07:39  armin
+ * Added tty modem register S23.
+ * Added new layer 2 and 3 protocols for Fax and DSP functions.
+ *
+ * Revision 1.26  1999/07/01 08:35:44  keil
+ * compatibility to 2.3
+ *
+ * Revision 1.25  1998/06/17 19:51:55  he
+ * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay())
+ * brute force fix to avoid Ugh's in isdn_tty_write()
+ * cleaned up some dead code
+ *
+ * Revision 1.24  1998/03/19 13:18:57  keil
+ * Start of a CAPI like interface for supplementary Service
+ * first service: SUSPEND
+ *
  * Revision 1.23  1998/02/20 17:36:52  fritz
  * Added L2-protocols for V.110, changed FEATURE-Flag-constants.
  *
@@ -116,6 +131,8 @@
 #ifndef isdnif_h
 #define isdnif_h
 
+#include <linux/isdn_compat.h>
+
 /*
  * Values for general protocol-selection
  */
@@ -139,18 +156,106 @@
 #define ISDN_PROTO_L2_V11096 7   /* V.110 bitrate adaption 9600 Baud  */
 #define ISDN_PROTO_L2_V11019 8   /* V.110 bitrate adaption 19200 Baud */
 #define ISDN_PROTO_L2_V11038 9   /* V.110 bitrate adaption 38400 Baud */
+#define ISDN_PROTO_L2_MODEM  10  /* Analog Modem on Board */
+#define ISDN_PROTO_L2_FAX    11  /* Fax Group 2/3         */
 #define ISDN_PROTO_L2_MAX    15  /* Max. 16 Protocols                 */
 
 /*
  * Values for Layer-3-protocol-selection
  */
 #define ISDN_PROTO_L3_TRANS  0   /* Transparent                 */
+#define ISDN_PROTO_L3_TRANSDSP 1   /* Transparent with DSP    */
+#define ISDN_PROTO_L3_FAX    2   /* Fax Group 2/3             */
 #define ISDN_PROTO_L3_MAX    7   /* Max. 8 Protocols            */
 
 #ifdef __KERNEL__
 
 #include <linux/skbuff.h>
 
+/***************************************************************************/
+/* Extensions made by Werner Cornelius (werner@ikt.de)                     */
+/*                                                                         */ 
+/* The proceed command holds a incoming call in a state to leave processes */
+/* enough time to check whether ist should be accepted.                    */
+/* The PROT_IO Command extends the interface to make protocol dependant    */
+/* features available (call diversion, call waiting...).                   */
+/*                                                                         */ 
+/* The PROT_IO Command is executed with the desired driver id and the arg  */
+/* parameter coded as follows:                                             */
+/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE    */
+/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/
+/* Any additional data is protocol and command specific.                   */
+/* This mechanism also applies to the statcallb callback STAT_PROT.        */    
+/*                                                                         */
+/* This suggested extension permits an easy expansion of protocol specific */
+/* handling. Extensions may be added at any time without changing the HL   */
+/* driver code and not getting conflicts without certifications.           */
+/* The well known CAPI 2.0 interface handles such extensions in a similar  */
+/* way. Perhaps a protocol specific module may be added and separately     */
+/* loaded and linked to the basic isdn module for handling.                */                    
+/***************************************************************************/
+
+/*****************/
+/* DSS1 commands */ 
+/*****************/
+#define DSS1_CMD_INVOKE       ((0x00 << 8) | ISDN_PTYPE_EURO)   /* invoke a supplementary service */
+#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO)   /* abort a invoke cmd */
+
+/*******************************/
+/* DSS1 Status callback values */
+/*******************************/
+#define DSS1_STAT_INVOKE_RES  ((0x80 << 8) | ISDN_PTYPE_EURO)   /* Result for invocation */
+#define DSS1_STAT_INVOKE_ERR  ((0x81 << 8) | ISDN_PTYPE_EURO)   /* Error Return for invocation */
+#define DSS1_STAT_INVOKE_BRD  ((0x82 << 8) | ISDN_PTYPE_EURO)   /* Deliver invoke broadcast info */
+
+
+/*********************************************************************/
+/* structures for DSS1 commands and callback                         */
+/*                                                                   */
+/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/
+/* timeout, datalen and data fields must be set before calling.      */
+/*                                                                   */
+/* The return value is a positive hl_id value also delivered in the  */
+/* hl_id field. A value of zero signals no more left hl_id capacitys.*/
+/* A negative return value signals errors in LL. So if the return    */
+/* value is <= 0 no action in LL will be taken -> request ignored    */
+/*                                                                   */
+/* The timeout field must be filled with a positive value specifying */
+/* the amount of time the INVOKED process waits for a reaction from  */
+/* the network.                                                      */
+/* If a response (either error or result) is received during this    */
+/* intervall, a reporting callback is initiated and the process will */
+/* be deleted, the hl identifier will be freed.                      */
+/* If no response is received during the specified intervall, a error*/
+/* callback is initiated with timeout set to -1 and a datalen set    */
+/* to 0.                                                             */
+/* If timeout is set to a value <= 0 during INVOCATION the process is*/
+/* immediately deleted after sending the data. No callback occurs !  */
+/*                                                                   */
+/* A currently waiting process may be aborted with INVOKE_ABORT. No  */
+/* callback will occur when a process has been aborted.              */
+/*                                                                   */
+/* Broadcast invoke frames from the network are reported via the     */
+/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */
+/* are supplied by the network and not by the HL.                    */   
+/*********************************************************************/
+typedef struct
+  { ulong ll_id; /* ID supplied by LL when executing    */
+		 /* a command and returned by HL for    */
+                 /* INVOKE_RES and INVOKE_ERR           */
+    int hl_id;   /* ID supplied by HL when called       */
+                 /* for executing a cmd and delivered   */
+                 /* for results and errors              */
+                 /* must be supplied by LL when aborting*/  
+    int proc;    /* invoke procedure used by CMD_INVOKE */
+                 /* returned by callback and broadcast  */ 
+    int timeout; /* timeout for INVOKE CMD in ms        */
+                 /* -1  in stat callback when timed out */
+                 /* error value when error callback     */
+    int datalen; /* length of cmd or stat data          */
+    u_char *data;/* pointer to data delivered or send   */
+  } dss1_cmd_stat;
+
 /*
  * Commands from linklevel to lowlevel
  *
@@ -173,6 +278,13 @@
 #define ISDN_CMD_UNLOCK  15       /* Release usage-lock                    */
 #define ISDN_CMD_SUSPEND 16       /* Suspend connection                    */
 #define ISDN_CMD_RESUME  17       /* Resume connection                     */
+#define ISDN_CMD_PROCEED 18       /* Proceed with call establishment       */
+#define ISDN_CMD_ALERT   19       /* Alert after Proceeding                */
+#define ISDN_CMD_REDIR   20       /* Redir a incoming call                 */
+#define ISDN_CMD_PROT_IO 21       /* Protocol specific commands            */
+#define CAPI_PUT_MESSAGE 22       /* CAPI message send down or up          */
+#define ISDN_CMD_FAXCMD  23       /* FAX commands to HL-driver             */
+#define ISDN_CMD_AUDIO   24       /* DSP, DTMF, ... settings               */
 
 /*
  * Status-Values delivered from lowlevel to linklevel via
@@ -194,7 +306,20 @@
 #define ISDN_STAT_NODCH   268    /* Signal no D-Channel                   */
 #define ISDN_STAT_ADDCH   269    /* Add more Channels                     */
 #define ISDN_STAT_CAUSE   270    /* Cause-Message                         */
-#define ISDN_STAT_L1ERR   271    /* Signal Layer-1 Error                  */
+#define ISDN_STAT_ICALLW  271    /* Incoming call without B-chan waiting  */
+#define ISDN_STAT_REDIR   272    /* Redir result                          */
+#define ISDN_STAT_PROT    273    /* protocol IO specific callback         */
+#define ISDN_STAT_DISPLAY 274    /* deliver a received display message    */
+#define ISDN_STAT_L1ERR   275    /* Signal Layer-1 Error                  */
+#define ISDN_STAT_FAXIND  276    /* FAX indications from HL-driver        */
+#define ISDN_STAT_AUDIO   277    /* DTMF, DSP indications                 */
+#define ISDN_STAT_DISCH   278    /* Disable/Enable channel usage          */
+
+/*
+ * Audio commands
+ */
+#define ISDN_AUDIO_SETDD	0	/* Set DTMF detection           */
+#define ISDN_AUDIO_DTMF		1	/* Rx/Tx DTMF                   */
 
 /*
  * Values for errcode field
@@ -216,12 +341,16 @@
 #define ISDN_FEATURE_L2_V11096  (0x0001 << ISDN_PROTO_L2_V11096)
 #define ISDN_FEATURE_L2_V11019  (0x0001 << ISDN_PROTO_L2_V11019)
 #define ISDN_FEATURE_L2_V11038  (0x0001 << ISDN_PROTO_L2_V11038)
+#define ISDN_FEATURE_L2_MODEM   (0x0001 << ISDN_PROTO_L2_MODEM)
+#define ISDN_FEATURE_L2_FAX	(0x0001 << ISDN_PROTO_L2_FAX)
 
 #define ISDN_FEATURE_L2_MASK    (0x0FFFF) /* Max. 16 protocols */
 #define ISDN_FEATURE_L2_SHIFT   (0)
 
 /* Layer 3 */
 #define ISDN_FEATURE_L3_TRANS   (0x10000 << ISDN_PROTO_L3_TRANS)
+#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
+#define ISDN_FEATURE_L3_FAX	(0x10000 << ISDN_PROTO_L3_FAX)
 
 #define ISDN_FEATURE_L3_MASK    (0x0FF0000) /* Max. 8 Protocols */
 #define ISDN_FEATURE_L3_SHIFT   (16)
@@ -236,28 +365,53 @@
 #define ISDN_FEATURE_P_SHIFT    (24)
 
 typedef struct setup_parm {
-    char phone[32];         /* Remote Phone-Number */
-    char eazmsn[32];        /* Local EAZ or MSN    */
+    unsigned char phone[32];	/* Remote Phone-Number */
+    unsigned char eazmsn[32];	/* Local EAZ or MSN    */
     unsigned char si1;      /* Service Indicator 1 */
     unsigned char si2;      /* Service Indicator 2 */
     unsigned char plan;     /* Numbering plan      */
     unsigned char screen;   /* Screening info      */
 } setup_parm;
 
+/* CAPI structs */
+
+/* this is compatible to the old union size */
+#define MAX_CAPI_PARA_LEN 50
+
+typedef struct {
+	/* Header */
+	__u16 Length;
+	__u16 ApplId;
+	__u8 Command;
+	__u8 Subcommand;
+	__u16 Messagenumber;
+
+	/* Parameter */
+	union {
+		__u32 Controller;
+		__u32 PLCI;
+		__u32 NCCI;
+	} adr;
+	__u8 para[MAX_CAPI_PARA_LEN];
+} capi_msg;
+
 /*
  * Structure for exchanging above infos
  *
  */
 typedef struct {
-  int   driver;                  /* Lowlevel-Driver-ID                    */
-  int   command;                 /* Command or Status (see above)         */
-  ulong arg;                     /* Additional Data                       */
-  union {
-	ulong errcode;               /* Type of error with STAT_L1ERR         */
-	int   length;                /* Amount of bytes sent with STAT_BSENT  */
-	char  num[50];               /* Additional Data                       */
-	setup_parm setup;
-  } parm;
+	int   driver;		/* Lowlevel-Driver-ID            */
+	int   command;		/* Command or Status (see above) */
+	ulong arg;		/* Additional Data               */
+	union {
+		ulong errcode;	/* Type of error with STAT_L1ERR         */
+		int length;	/* Amount of bytes sent with STAT_BSENT  */
+		u_char num[50];/* Additional Data			*/
+		setup_parm setup;/* For SETUP msg			*/
+		capi_msg cmsg;	/* For CAPI like messages		*/
+		char display[85];/* display message data          */ 
+		dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */
+	} parm;
 } isdn_ctrl;
 
 /*
@@ -378,10 +532,6 @@
  *
  */
 extern int register_isdn(isdn_if*);
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
 #include <asm/uaccess.h>
 
 #endif /* __KERNEL__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/isicom.h linux.pre11.3/include/linux/isicom.h
--- linux.vanilla/include/linux/isicom.h	Tue Dec 22 23:20:11 1998
+++ linux.pre11.3/include/linux/isicom.h	Tue Jul 20 00:15:27 1999
@@ -52,6 +52,13 @@
 #define		ISICOM_NAME	"ISICom"
 
 /*
+ *      PCI definitions
+ */
+
+ #define        DEVID_COUNT     9
+ #define        VENDOR_ID       0x10b5
+
+/*
  *	These are now officially allocated numbers
  */
 
@@ -129,6 +136,7 @@
 	unsigned short		shift_count;
 	struct isi_port		* ports;
 	signed char		count;
+	unsigned char		isa;
 };
 
 struct	isi_port {
@@ -166,7 +174,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
@@ -186,7 +194,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
@@ -205,7 +213,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
@@ -224,7 +232,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
@@ -243,7 +251,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
@@ -262,7 +270,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
@@ -282,7 +290,7 @@
 	struct isi_board * card = port->card;
 	unsigned short base = card->base;
 	unsigned char channel = port->channel;
-	short wait=300;
+	short wait=400;
 	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
 	if (wait <= 0) {
 		printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/kernel.h linux.pre11.3/include/linux/kernel.h
--- linux.vanilla/include/linux/kernel.h	Thu Dec 31 18:10:47 1998
+++ linux.pre11.3/include/linux/kernel.h	Tue Jul 20 01:31:02 1999
@@ -41,6 +41,7 @@
 #endif
 
 extern void math_error(void);
+extern struct notifier_block *panic_notifier_list;
 NORET_TYPE void panic(const char * fmt, ...)
 	__attribute__ ((NORET_AND format (printf, 1, 2)));
 NORET_TYPE void do_exit(long error_code)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/kernelcapi.h linux.pre11.3/include/linux/kernelcapi.h
--- linux.vanilla/include/linux/kernelcapi.h	Sun Nov  8 15:06:50 1998
+++ linux.pre11.3/include/linux/kernelcapi.h	Tue Jul 20 00:15:27 1999
@@ -1,11 +1,30 @@
 /*
- * $Id: kernelcapi.h,v 1.1 1997/03/04 21:27:33 calle Exp $
+ * $Id: kernelcapi.h,v 1.3 1999/07/01 15:26:56 calle Exp $
  * 
  * Kernel CAPI 2.0 Interface for Linux
  * 
  * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: kernelcapi.h,v $
+ * Revision 1.3  1999/07/01 15:26:56  calle
+ * complete new version (I love it):
+ * + new hardware independed "capi_driver" interface that will make it easy to:
+ *   - support other controllers with CAPI-2.0 (i.e. USB Controller)
+ *   - write a CAPI-2.0 for the passive cards
+ *   - support serial link CAPI-2.0 boxes.
+ * + wrote "capi_driver" for all supported cards.
+ * + "capi_driver" (supported cards) now have to be configured with
+ *   make menuconfig, in the past all supported cards where included
+ *   at once.
+ * + new and better informations in /proc/capi/
+ * + new ioctl to switch trace of capi messages per controller
+ *   using "avmcapictrl trace [contr] on|off|...."
+ * + complete testcircle with all supported cards and also the
+ *   PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done.
+ *
+ * Revision 1.2  1999/06/21 15:24:26  calle
+ * extend information in /proc.
+ *
  * Revision 1.1  1997/03/04 21:27:33  calle
  * First version in isdn4linux
  *
@@ -17,17 +36,37 @@
  *
  * 
  */
-#ifndef __KERNEL_CAPI_H__
-#define __KERNEL_CAPI_H__
+#ifndef __KERNELCAPI_H__
+#define __KERNELCAPI_H__
 
 #define CAPI_MAXAPPL	20	/*
 				   * maximum number of applications 
 				 */
-#define CAPI_MAXCONTR	4	/*
+#define CAPI_MAXCONTR	10	/*
 				   * maximum number of controller 
 				 */
 #define CAPI_MAXDATAWINDOW	8
 
+
+typedef struct kcapi_flagdef {
+	int contr;
+	int flag;
+} kcapi_flagdef;
+
+/* new ioctls >= 10 */
+#define KCAPI_CMD_TRACE		10
+
+/* 
+ * flag > 2 => trace also data
+ * flag & 1 => show trace
+ */
+#define KCAPI_TRACE_OFF			0
+#define KCAPI_TRACE_SHORT_NO_DATA	1
+#define KCAPI_TRACE_FULL_NO_DATA	2
+#define KCAPI_TRACE_SHORT		3
+#define KCAPI_TRACE_FULL		4
+
+
 #ifdef __KERNEL__
 
 struct capi_interface {
@@ -58,6 +97,7 @@
 struct capi_interface_user {
 	char name[20];
 	void (*callback) (unsigned int cmd, __u16 contr, void *data);
+	/* internal */
 	struct capi_interface_user *next;
 };
 
@@ -93,4 +133,4 @@
 
 #endif				/* __KERNEL__ */
 
-#endif				/* __KERNEL_CAPI_H__ */
+#endif				/* __KERNELCAPI_H__ */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/major.h linux.pre11.3/include/linux/major.h
--- linux.vanilla/include/linux/major.h	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/include/linux/major.h	Tue Jul 20 00:15:36 1999
@@ -63,6 +63,8 @@
 #define ACSI_MAJOR	28
 #define AZTECH_CDROM_MAJOR 29
 #define GRAPHDEV_MAJOR	29	/* SparcLinux & Linux/68k /dev/fb */
+#define SHMIQ_MAJOR	85	/* Linux/MIPS, SGI /dev/shmiq */
+#define USEMA_MAJOR	86	/* Linux/MIPS, SGI /dev/usema */
 #define CM206_CDROM_MAJOR 32
 #define IDE2_MAJOR	33
 #define IDE3_MAJOR	34
@@ -74,6 +76,7 @@
 #define DDV_MAJOR       39   /* AP1000 DDV block device */
 #define NBD_MAJOR	43   /* Network block device	*/
 #define RISCOM8_NORMAL_MAJOR 48
+#define DAC960_MAJOR	48	/* 48..55 */
 #define RISCOM8_CALLOUT_MAJOR 49
 #define MKISS_MAJOR	55
 #define DSP56K_MAJOR    55   /* DSP56001 processor device */
@@ -89,8 +92,21 @@
 #define SCSI_DISK6_MAJOR	70
 #define SCSI_DISK7_MAJOR	71
 
+#define LVM_BLK_MAJOR	58	/* Logical Volume Manager */
+
+#define COMPAQ_SMART2_MAJOR	72
+#define COMPAQ_SMART2_MAJOR1	73
+#define COMPAQ_SMART2_MAJOR2	74
+#define COMPAQ_SMART2_MAJOR3	75
+#define COMPAQ_SMART2_MAJOR4	76
+#define COMPAQ_SMART2_MAJOR5	77
+#define COMPAQ_SMART2_MAJOR6	78
+#define COMPAQ_SMART2_MAJOR7	79
+
 #define SPECIALIX_NORMAL_MAJOR 75
 #define SPECIALIX_CALLOUT_MAJOR 76
+
+#define LVM_CHAR_MAJOR	109	/* Logical Volume Manager */
 
 #define AURORA_MAJOR 79
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/miscdevice.h linux.pre11.3/include/linux/miscdevice.h
--- linux.vanilla/include/linux/miscdevice.h	Wed Mar 10 21:13:11 1999
+++ linux.pre11.3/include/linux/miscdevice.h	Mon Jul 19 23:26:43 1999
@@ -19,6 +19,14 @@
 #define I2O_MINOR 166
 #define MISC_DYNAMIC_MINOR 255
 
+#define SGI_GRAPHICS_MINOR   146
+#define SGI_OPENGL_MINOR     147
+#define SGI_GFX_MINOR        148
+#define SGI_STREAMS_MOUSE    149
+#define SGI_STREAMS_KEYBOARD 150
+/* drivers/sgi/char/usema.c */
+#define SGI_USEMACLONE	     151
+
 extern int misc_init(void);
 
 struct miscdevice 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/mount.h linux.pre11.3/include/linux/mount.h
--- linux.vanilla/include/linux/mount.h	Sun Nov  8 15:06:49 1998
+++ linux.pre11.3/include/linux/mount.h	Tue Jul 20 00:15:51 1999
@@ -17,11 +17,12 @@
 struct quota_mount_options
 {
 	unsigned int flags;			/* Flags for diskquotas on this device */
-	struct semaphore semaphore;		/* lock device while I/O in progress */
+	struct semaphore dqio_sem;		/* lock device while I/O in progress */
+	struct semaphore dqoff_sem;		/* serialize quota_off() and quota_on() on device */
 	struct file *files[MAXQUOTAS];		/* fp's to quotafiles */
 	time_t inode_expire[MAXQUOTAS];		/* expiretime for inode-quota */
 	time_t block_expire[MAXQUOTAS];		/* expiretime for block-quota */
-	char rsquash[MAXQUOTAS];		/* for quotas threath root as any other user */
+	char rsquash[MAXQUOTAS];		/* for quotas treat root as any other user */
 };
 
 struct vfsmount
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/msdos_fs.h linux.pre11.3/include/linux/msdos_fs.h
--- linux.vanilla/include/linux/msdos_fs.h	Wed Apr 28 19:14:34 1999
+++ linux.pre11.3/include/linux/msdos_fs.h	Tue Jul 20 01:46:20 1999
@@ -183,12 +183,9 @@
 
 #ifdef __KERNEL__
 
-typedef int (*fat_filldir_t)(filldir_t filldir, void *, const char *,
-			     int, int, off_t, off_t, int, ino_t);
-
 struct fat_cache {
 	kdev_t device; /* device number. 0 means unused. */
-	int ino; /* inode number. */
+	int start_cluster; /* first cluster of the chain. */
 	int file_cluster; /* cluster number in the file. */
 	int disk_cluster; /* cluster number on disk. */
 	struct fat_cache *next; /* next cache entry */
@@ -199,15 +196,29 @@
 extern void lock_fat(struct super_block *sb);
 extern void unlock_fat(struct super_block *sb);
 extern int fat_add_cluster(struct inode *inode);
+extern struct buffer_head *fat_add_cluster1(struct inode *inode);
 extern int date_dos2unix(__u16 time, __u16 date);
 extern void fat_fs_panic(struct super_block *s,const char *msg);
 extern void fat_lock_creation(void);
 extern void fat_unlock_creation(void);
 extern void fat_date_unix2dos(int unix_date,__u16 *time, __u16 *date);
-extern int fat_get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh,
-			 struct msdos_dir_entry **de);
+extern int fat__get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh,
+			 struct msdos_dir_entry **de,int *ino);
+static __inline__ int fat_get_entry(struct inode *dir,loff_t *pos,
+		struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
+{
+	/* Fast stuff first */
+	if (*bh && *de &&
+	    	(*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_DPB-1) {
+		*pos += sizeof(struct msdos_dir_entry);
+		(*de)++;
+		(*ino)++;
+		return 0;
+	}
+	return fat__get_entry(dir,pos,bh,de,ino);
+}
 extern int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh,
-		    struct msdos_dir_entry **res_de,int *ino,char scantype);
+		    struct msdos_dir_entry **res_de,int *ino);
 extern int fat_parent_ino(struct inode *dir,int locked);
 extern int fat_subdirs(struct inode *dir);
 void fat_clusters_flush(struct super_block *sb);
@@ -224,26 +235,32 @@
 int fat_get_cluster(struct inode *inode,int cluster);
 
 /* inode.c */
+extern void fat_hash_init(void);
 extern int fat_bmap(struct inode *inode,int block);
 extern int fat_notify_change(struct dentry *, struct iattr *);
-extern void fat_put_inode(struct inode *inode);
+extern void fat_clear_inode(struct inode *inode);
 extern void fat_delete_inode(struct inode *inode);
 extern void fat_put_super(struct super_block *sb);
-extern void fat_read_inode(struct inode *inode, struct inode_operations *dir_ops);
-extern struct super_block *fat_read_super(struct super_block *s, void *data, int silent);
+extern void fat_attach(struct inode *inode, int ino);
+extern void fat_detach(struct inode *inode);
+extern struct inode *fat_iget(struct super_block*,int);
+extern struct inode *fat_build_inode(struct super_block*,struct msdos_dir_entry*,int,int*);
+extern struct super_block *fat_read_super(struct super_block *s, void *data, int silent, struct inode_operations *dir_ops);
 extern void msdos_put_super(struct super_block *sb);
 extern int fat_statfs(struct super_block *sb,struct statfs *buf, int);
 extern void fat_write_inode(struct inode *inode);
 
 /* dir.c */
 extern struct file_operations fat_dir_operations;
-extern int fat_readdirx(struct inode *inode, struct file *filp, void *dirent,
-			fat_filldir_t fat_filldir, filldir_t filldir,
-			int shortnames, int longnames, int both);
+extern int fat_search_long(struct inode *dir, const char *name, int len,
+			   int anycase, loff_t *spos, loff_t *lpos);
 extern int fat_readdir(struct file *filp,
 		       void *dirent, filldir_t);
 extern int fat_dir_ioctl(struct inode * inode, struct file * filp,
 			 unsigned int cmd, unsigned long arg);
+int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
+		  struct msdos_dir_entry **de, int *ino);
+int fat_dir_empty(struct inode *dir);
 
 /* file.c */
 extern struct inode_operations fat_file_inode_operations;
@@ -276,7 +293,6 @@
 extern int msdos_rmdir(struct inode *dir,struct dentry *dentry);
 extern int msdos_mkdir(struct inode *dir,struct dentry *dentry,int mode);
 extern int msdos_unlink(struct inode *dir,struct dentry *dentry);
-extern int msdos_unlink_umsdos(struct inode *dir,struct dentry *dentry);
 extern int msdos_rename(struct inode *old_dir,struct dentry *old_dentry,
 			struct inode *new_dir,struct dentry *new_dentry);
 
@@ -303,12 +319,10 @@
 /* vfat/namei.c - these are for dmsdos */
 extern int vfat_create(struct inode *dir,struct dentry *dentry,int mode);
 extern int vfat_unlink(struct inode *dir,struct dentry *dentry);
-extern int vfat_unlink_uvfat(struct inode *dir,struct dentry *dentry);
 extern int vfat_mkdir(struct inode *dir,struct dentry *dentry,int mode);
 extern int vfat_rmdir(struct inode *dir,struct dentry *dentry);
 extern int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
 		       struct inode *new_dir,struct dentry *new_dentry);
-extern void vfat_put_super(struct super_block *sb);
 extern struct super_block *vfat_read_super(struct super_block *sb,void *data,
 					   int silent);
 extern void vfat_read_inode(struct inode *inode);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/msdos_fs_i.h linux.pre11.3/include/linux/msdos_fs_i.h
--- linux.vanilla/include/linux/msdos_fs_i.h	Sun Nov  8 15:06:47 1998
+++ linux.pre11.3/include/linux/msdos_fs_i.h	Mon Jul 19 23:26:42 1999
@@ -29,9 +29,11 @@
 	int i_logstart;	/* logical first cluster */
 	int i_attrs;	/* unused attribute bits */
 	int i_ctime_ms;	/* unused change time in milliseconds */
-	int i_busy;	/* file is either deleted but still open, or
-			   inconsistent (mkdir) */
 	int i_binary;	/* file contains non-text data */
+	int i_location;	/* on-disk position of directory entry or 0 */
+	struct inode *i_fat_inode;	/* struct inode of this one */
+	struct list_head i_fat_hash;	/* hash by i_location */
+	off_t i_last_pos;/* position of last lookup */
 };
 
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/msdos_fs_sb.h linux.pre11.3/include/linux/msdos_fs_sb.h
--- linux.vanilla/include/linux/msdos_fs_sb.h	Mon Dec 28 23:09:47 1998
+++ linux.pre11.3/include/linux/msdos_fs_sb.h	Tue Jul 20 01:31:03 1999
@@ -51,7 +51,9 @@
 	struct nls_table *nls_disk;  /* Codepage used on disk */
 	struct nls_table *nls_io;    /* Charset used for input and display */
 	struct cvf_format* cvf_format;
-	void* private_data;	
+	void *dir_ops;		     /* Opaque; default directory operations */
+	void (*put_super_callback)(struct super_block *);
+	void *private_data;	
 };
 
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/pc_keyb.h linux.pre11.3/include/linux/pc_keyb.h
--- linux.vanilla/include/linux/pc_keyb.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/linux/pc_keyb.h	Mon Jul 19 23:26:45 1999
@@ -0,0 +1,130 @@
+/*
+ *	include/linux/pc_keyb.h
+ *
+ *	PC Keyboard And Keyboard Controller
+ *
+ *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+/*
+ *	Configuration Switches
+ */
+
+#undef KBD_REPORT_ERR			/* Report keyboard errors */
+#define KBD_REPORT_UNKN			/* Report unknown scan codes */
+#define KBD_REPORT_TIMEOUTS		/* Report keyboard timeouts */
+#undef KBD_IS_FOCUS_9000		/* We have the brain-damaged FOCUS-9000 keyboard */
+#undef INITIALIZE_MOUSE			/* Define if your PS/2 mouse needs initialization. */
+
+
+
+#define KBD_INIT_TIMEOUT 1000		/* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250			/* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 1000		/* Timeout in ms for keyboard command acknowledge */
+
+/*
+ *	Internal variables of the driver
+ */
+
+extern unsigned char pckbd_read_mask;
+extern unsigned char aux_device_present;
+
+/*
+ *	Keyboard Controller Registers on normal PCs.
+ */
+
+#define KBD_STATUS_REG		0x64	/* Status register (R) */
+#define KBD_CNTL_REG		0x64	/* Controller command register (W) */
+#define KBD_DATA_REG		0x60	/* Keyboard data register (R/W) */
+
+/*
+ *	Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE	0x20	/* Read mode bits */
+#define KBD_CCMD_WRITE_MODE	0x60	/* Write mode bits */
+#define KBD_CCMD_GET_VERSION	0xA1	/* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE	0xA7	/* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE	0xA8	/* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE	0xA9	/* Mouse interface test */
+#define KBD_CCMD_SELF_TEST	0xAA	/* Controller self test */
+#define KBD_CCMD_KBD_TEST	0xAB	/* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE	0xAD	/* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE	0xAE	/* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF	0xD3    /* Write to output buffer as if
+					   initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE	0xD4	/* Write the following byte to the mouse */
+
+/*
+ *	Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS	0xED	/* Set keyboard leds */
+#define KBD_CMD_SET_RATE	0xF3	/* Set typematic rate */
+#define KBD_CMD_ENABLE		0xF4	/* Enable scanning */
+#define KBD_CMD_DISABLE		0xF5	/* Disable scanning */
+#define KBD_CMD_RESET		0xFF	/* Reset */
+
+/*
+ *	Keyboard Replies
+ */
+
+#define KBD_REPLY_POR		0xAA	/* Power on reset */
+#define KBD_REPLY_ACK		0xFA	/* Command ACK */
+#define KBD_REPLY_RESEND	0xFE	/* Command NACK, send the cmd again */
+
+/*
+ *	Status Register Bits
+ */
+
+#define KBD_STAT_OBF 		0x01	/* Keyboard output buffer full */
+#define KBD_STAT_IBF 		0x02	/* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST	0x04	/* Self test successful */
+#define KBD_STAT_CMD		0x08	/* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED	0x10	/* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF	0x20	/* Mouse output buffer full */
+#define KBD_STAT_GTO 		0x40	/* General receive/xmit timeout */
+#define KBD_STAT_PERR 		0x80	/* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *	Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT	0x01	/* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT	0x02	/* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 		0x04	/* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK	0x08	/* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD	0x10	/* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE	0x20	/* Disable mouse interface */
+#define KBD_MODE_KCC 		0x40	/* Scan code conversion to PC format */
+#define KBD_MODE_RFU		0x80
+
+/*
+ *	Mouse Commands
+ */
+
+#define AUX_SET_RES		0xE8	/* Set resolution */
+#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
+#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
+#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
+#define AUX_SET_STREAM		0xEA	/* Set stream mode */
+#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
+#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
+#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
+#define AUX_RESET		0xFF	/* Reset aux device */
+#define AUX_ACK			0xFA	/* Command byte ACK. */
+
+#define AUX_BUF_SIZE		2048	/* This might be better divisible by
+					   three to make overruns stay in sync
+					   but then the read function would need
+					   a lock etc - ick */
+
+struct aux_queue {
+	unsigned long head;
+	unsigned long tail;
+	struct wait_queue *proc_list;
+	struct fasync_struct *fasync;
+	unsigned char buf[AUX_BUF_SIZE];
+};
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/pci.h linux.pre11.3/include/linux/pci.h
--- linux.vanilla/include/linux/pci.h	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/include/linux/pci.h	Tue Jul 20 01:41:55 1999
@@ -305,6 +305,7 @@
 #define PCI_DEVICE_ID_NCR_53C895	0x000c
 #define PCI_DEVICE_ID_NCR_53C885	0x000d
 #define PCI_DEVICE_ID_NCR_53C875	0x000f
+#define PCI_DEVICE_ID_NCR_53C1510	0x0010
 #define PCI_DEVICE_ID_NCR_53C875J	0x008f
 
 #define PCI_VENDOR_ID_ATI		0x1002
@@ -368,6 +369,8 @@
 #define PCI_DEVICE_ID_DEC_21152		0x0024
 #define PCI_DEVICE_ID_DEC_21153		0x0025
 #define PCI_DEVICE_ID_DEC_21154		0x0026
+#define PCI_DEVICE_ID_DEC_21285		0x1065
+#define PCI_DEVICE_ID_COMPAQ_42XX	0x0046
 
 #define PCI_VENDOR_ID_CIRRUS		0x1013
 #define PCI_DEVICE_ID_CIRRUS_7548	0x0038
@@ -403,6 +406,7 @@
 
 #define PCI_VENDOR_ID_AMD		0x1022
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
+#define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
 
 #define PCI_VENDOR_ID_TRIDENT		0x1023
@@ -547,6 +551,12 @@
 #define PCI_DEVICE_ID_PICOP_PT86C52X	0x0001
 #define PCI_DEVICE_ID_PICOP_PT80C524	0x8002
 
+#define PCI_VENDOR_ID_MYLEX		0x1069
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V2	0x0001
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V3	0x0002
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V4	0x0010
+#define PCI_DEVICE_ID_MYLEX_DAC960P_V5	0x0020
+
 #define PCI_VENDOR_ID_APPLE		0x106b
 #define PCI_DEVICE_ID_APPLE_BANDIT	0x0001
 #define PCI_DEVICE_ID_APPLE_GC		0x0002
@@ -559,6 +569,7 @@
 #define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
 #define PCI_DEVICE_ID_QLOGIC_ISP1022	0x1022
 #define PCI_DEVICE_ID_QLOGIC_ISP2100	0x2100
+#define PCI_DEVICE_ID_QLOGIC_ISP2200	0x2200
 
 #define PCI_VENDOR_ID_CYRIX		0x1078
 #define PCI_DEVICE_ID_CYRIX_5510	0x0000
@@ -682,6 +693,8 @@
 #define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128V 0x0002
 #define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZV 0x0003
 #define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_NM2160 0x0004
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICMEDIA_256AV       0x0005
+#define PCI_DEVICE_ID_NEOMAGIC_MAGICGRAPH_128ZVPLUS   0x0083
 
 #define PCI_VENDOR_ID_ASP		0x10cd
 #define PCI_DEVICE_ID_ASP_ABP940	0x1200
@@ -861,6 +874,9 @@
 #define PCI_VENDOR_ID_OMEGA		0x119b
 #define PCI_DEVICE_ID_OMEGA_82C092G	0x1221
 
+#define PCI_VENDOR_ID_GALILEO		0x11ab
+#define PCI_DEVICE_ID_GALILEO_GT64011	0x4146
+
 #define PCI_VENDOR_ID_LITEON		0x11ad
 #define PCI_DEVICE_ID_LITEON_LNE100TX	0x0002
 
@@ -959,6 +975,7 @@
 
 #define PCI_VENDOR_ID_ENSONIQ		0x1274
 #define PCI_DEVICE_ID_ENSONIQ_AUDIOPCI	0x5000
+#define PCI_DEVICE_ID_ENSONIQ_ES1371    0x1371
 
 #define PCI_VENDOR_ID_ALTEON		0x12ae
 #define PCI_DEVICE_ID_ALTEON_ACENIC	0x0001
@@ -1021,12 +1038,17 @@
 #define PCI_VENDOR_ID_DCI       0x6666
 #define PCI_DEVICE_ID_DCI_PCCOM4    0x0001
 
+#define PCI_VENDOR_ID_GENROCO		0x5555
+#define PCI_DEVICE_ID_GENROCO_HFP832	0x0003
+
 #define PCI_VENDOR_ID_INTEL		0x8086
+#define PCI_DEVICE_ID_INTEL_21145	0x0039
 #define PCI_DEVICE_ID_INTEL_82375	0x0482
 #define PCI_DEVICE_ID_INTEL_82424	0x0483
 #define PCI_DEVICE_ID_INTEL_82378	0x0484
 #define PCI_DEVICE_ID_INTEL_82430	0x0486
 #define PCI_DEVICE_ID_INTEL_82434	0x04a3
+#define PCI_DEVICE_ID_INTEL_I960	0x0960
 #define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
 #define PCI_DEVICE_ID_INTEL_82092AA_1	0x1222
 #define PCI_DEVICE_ID_INTEL_7116	0x1223
@@ -1065,6 +1087,7 @@
 #define PCI_VENDOR_ID_ADAPTEC		0x9004
 #define PCI_DEVICE_ID_ADAPTEC_7810	0x1078
 #define PCI_DEVICE_ID_ADAPTEC_7821	0x2178
+#define PCI_DEVICE_ID_ADAPTEC_38602	0x3860
 #define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
 #define PCI_DEVICE_ID_ADAPTEC_7855	0x5578
 #define PCI_DEVICE_ID_ADAPTEC_5800	0x5800
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/personality.h linux.pre11.3/include/linux/personality.h
--- linux.vanilla/include/linux/personality.h	Sun Nov  8 15:06:48 1998
+++ linux.pre11.3/include/linux/personality.h	Tue Jul 20 01:31:03 1999
@@ -24,6 +24,9 @@
 #define PER_BSD			(0x0006)
 #define PER_XENIX		(0x0007 | STICKY_TIMEOUTS)
 #define PER_LINUX32		(0x0008)
+#define PER_IRIX32              (0x0009 | STICKY_TIMEOUTS) /* IRIX5 32-bit     */
+#define PER_IRIXN32             (0x000a | STICKY_TIMEOUTS) /* IRIX6 new 32-bit */
+#define PER_IRIX64              (0x000b | STICKY_TIMEOUTS) /* IRIX6 64-bit     */
 
 /* Prototype for an lcall7 syscall handler. */
 typedef void (*lcall7_func)(struct pt_regs *);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/proc_fs.h linux.pre11.3/include/linux/proc_fs.h
--- linux.vanilla/include/linux/proc_fs.h	Wed Apr 28 19:14:34 1999
+++ linux.pre11.3/include/linux/proc_fs.h	Tue Jul 20 01:31:05 1999
@@ -200,12 +200,14 @@
 	PROC_SCSI_ATARI,
 	PROC_SCSI_MAC,
 	PROC_SCSI_IDESCSI,
+	PROC_SCSI_SGIWD93,
 	PROC_SCSI_MESH,
 	PROC_SCSI_53C94,
 	PROC_SCSI_PLUTO,
 	PROC_SCSI_INI9100U,
- 	PROC_SCSI_INIA100,
+	PROC_SCSI_INIA100,
 	PROC_SCSI_FCAL,
+	PROC_SCSI_I2O,
 	PROC_SCSI_SCSI_DEBUG,	
 	PROC_SCSI_NOT_PRESENT,
 	PROC_SCSI_FILE,                        /* I'm assuming here that we */
@@ -443,12 +445,12 @@
 
 #else
 
-extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) {};
-extern inline int proc_unregister(struct proc_dir_entry *a, int b) {};
-extern inline int proc_net_register(struct proc_dir_entry *a) {};
-extern inline int proc_net_unregister(int x) {};
-extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) {};
-extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x);
+extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; };
+extern inline int proc_unregister(struct proc_dir_entry *a, int b) { return 0; };
+extern inline int proc_net_register(struct proc_dir_entry *a) { return 0; };
+extern inline int proc_net_unregister(int x) { return 0; };
+extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; };
+extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; };
 
 extern inline struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 					 struct proc_dir_entry *parent)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/quotaops.h linux.pre11.3/include/linux/quotaops.h
--- linux.vanilla/include/linux/quotaops.h	Wed Mar 24 10:55:27 1999
+++ linux.pre11.3/include/linux/quotaops.h	Tue Jul 20 01:39:56 1999
@@ -31,8 +31,8 @@
 extern void dquot_free_block(const struct inode *inode, unsigned long number);
 extern void dquot_free_inode(const struct inode *inode, unsigned long number);
 
-extern int  dquot_transfer(struct inode *inode, struct iattr *iattr,
-                           char direction, uid_t initiator);
+extern int  dquot_transfer(struct dentry *dentry, struct iattr *iattr,
+                           uid_t initiator);
 
 /*
  * Operations supported for diskquotas.
@@ -101,15 +101,10 @@
 	if (dentry->d_inode->i_sb->dq_op) {
 		if (IS_QUOTAINIT(dentry->d_inode) == 0)
 			dentry->d_inode->i_sb->dq_op->initialize(dentry->d_inode, -1);
-		if (dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 0, current->fsuid))
-			goto out;
-		error = notify_change(dentry, iattr);
-		if (error)
-			dentry->d_inode->i_sb->dq_op->transfer(dentry->d_inode, iattr, 1, current->fsuid);
+		error = dentry->d_inode->i_sb->dq_op->transfer(dentry, iattr, current->fsuid);
 	} else {
 		error = notify_change(dentry, iattr);
 	}
-out:
 	return error;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/socket.h linux.pre11.3/include/linux/socket.h
--- linux.vanilla/include/linux/socket.h	Fri Apr 16 22:11:00 1999
+++ linux.pre11.3/include/linux/socket.h	Tue Jul 20 01:31:01 1999
@@ -128,18 +128,6 @@
 	__u32	gid;
 };
 
-/* Socket types. */
-
-#define SOCK_STREAM	1		/* stream (connection) socket	*/
-#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
-#define SOCK_RAW	3		/* raw socket			*/
-#define SOCK_RDM	4		/* reliably-delivered message	*/
-#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
-#define SOCK_PACKET	10		/* linux specific way of	*/
-					/* getting packets at the dev	*/
-					/* level.  For writing rarp and	*/
-					/* other similar things on the	*/
-					/* user level.			*/
 
 /* Supported address families. */
 #define AF_UNSPEC	0
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/soundcard.h linux.pre11.3/include/linux/soundcard.h
--- linux.vanilla/include/linux/soundcard.h	Sun Nov  8 15:10:26 1998
+++ linux.pre11.3/include/linux/soundcard.h	Tue Jul 20 01:56:22 1999
@@ -891,6 +891,12 @@
 #define SOUND_MIXER_ACCESS		_SIOWR('M', 102, mixer_record)
 
 /*
+ * Two ioctls for special souncard function
+ */
+#define SOUND_MIXER_AGC  _SIOWR('M', 103, int)
+#define SOUND_MIXER_3DSE  _SIOWR('M', 104, int)
+
+/*
  * The SOUND_MIXER_PRIVATE# commands can be redefined by low level drivers.
  * These features can be used when accessing device specific features.
  */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/sysctl.h linux.pre11.3/include/linux/sysctl.h
--- linux.vanilla/include/linux/sysctl.h	Wed Apr 28 19:14:35 1999
+++ linux.pre11.3/include/linux/sysctl.h	Mon Jul 19 23:26:43 1999
@@ -78,7 +78,7 @@
 	KERN_NODENAME=7,
 	KERN_DOMAINNAME=8,
 
-	KERN_SECURELVL=14,	/* int: system security level */
+	KERN_CAP_BSET=14,	/* int: capability bounding set */
 	KERN_PANIC=15,		/* int: panic timeout */
 	KERN_REALROOTDEV=16,	/* real root device to mount after initrd */
 
@@ -102,7 +102,8 @@
 	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 */
+	KERN_MSGPOOL=37,         /* int: Maximum system message pool size */
+	KERN_SYSRQ=38		/* int: Sysreq enable */
 };
 
 
@@ -451,6 +452,8 @@
 			 void *, size_t *);
 extern int proc_dointvec(ctl_table *, int, struct file *,
 			 void *, size_t *);
+extern int proc_dointvec_bset(ctl_table *, int, struct file *,
+			      void *, size_t *);
 extern int proc_dointvec_minmax(ctl_table *, int, struct file *,
 				void *, size_t *);
 extern int proc_dointvec_jiffies(ctl_table *, int, struct file *,
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/sysrq.h linux.pre11.3/include/linux/sysrq.h
--- linux.vanilla/include/linux/sysrq.h	Sun Nov  8 15:06:50 1998
+++ linux.pre11.3/include/linux/sysrq.h	Tue Jul 20 01:31:26 1999
@@ -36,3 +36,5 @@
 #else
 #define CHECK_EMERGENCY_SYNC
 #endif
+
+extern int sysrq_enabled;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/tty.h linux.pre11.3/include/linux/tty.h
--- linux.vanilla/include/linux/tty.h	Sat Jan  9 21:50:50 1999
+++ linux.pre11.3/include/linux/tty.h	Tue Jul 20 01:31:04 1999
@@ -118,6 +118,9 @@
 
 #define VIDEO_TYPE_PMAC		0x60	/* PowerMacintosh frame buffer. */
 
+#define VIDEO_TYPE_SGI          0x70    /* Various SGI graphics hardware */
+#define VIDEO_TYPE_MIPS_G364	0x71    /* MIPS Magnum 4000 G364 video  */
+
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
  * a c_cc[] character, but indicates that a particular special character
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/linux/ufs_fs.h linux.pre11.3/include/linux/ufs_fs.h
--- linux.vanilla/include/linux/ufs_fs.h	Wed Apr 28 19:14:35 1999
+++ linux.pre11.3/include/linux/ufs_fs.h	Tue Jul 20 01:31:03 1999
@@ -111,13 +111,14 @@
 #define UFS_MOUNT_ONERROR_UMOUNT	0x00000004
 #define UFS_MOUNT_ONERROR_REPAIR	0x00000008
 
-#define UFS_MOUNT_UFSTYPE		0x000003F0
+#define UFS_MOUNT_UFSTYPE		0x000007F0
 #define UFS_MOUNT_UFSTYPE_OLD		0x00000010
 #define UFS_MOUNT_UFSTYPE_44BSD		0x00000020
 #define UFS_MOUNT_UFSTYPE_SUN		0x00000040
 #define UFS_MOUNT_UFSTYPE_NEXTSTEP	0x00000080
-#define UFS_MOUNT_UFSTYPE_OPENSTEP	0x00000100
-#define UFS_MOUNT_UFSTYPE_SUNx86	0x00000200
+#define UFS_MOUNT_UFSTYPE_NEXTSTEP_CD	0x00000100
+#define UFS_MOUNT_UFSTYPE_OPENSTEP	0x00000200
+#define UFS_MOUNT_UFSTYPE_SUNx86	0x00000400
 
 #define ufs_clear_opt(o,opt)	o &= ~UFS_MOUNT_##opt
 #define ufs_set_opt(o,opt)	o |= UFS_MOUNT_##opt
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/net/ip_masq.h linux.pre11.3/include/net/ip_masq.h
--- linux.vanilla/include/net/ip_masq.h	Wed Mar 24 10:55:28 1999
+++ linux.pre11.3/include/net/ip_masq.h	Tue Jul 20 01:48:16 1999
@@ -11,6 +11,7 @@
 #include <linux/netdevice.h>
 #include <linux/ip.h>
 #include <linux/skbuff.h>
+#include <linux/list.h>
 #endif /* __KERNEL__ */
 
 /*
@@ -57,6 +58,7 @@
 
 #define IP_MASQ_F_MPORT		      0x1000 	/* own mport specified */
 #define IP_MASQ_F_USER		      0x2000	/* from uspace */
+#define IP_MASQ_F_SIMPLE_HASH	      0x8000	/* prevent s+d and m+d hashing */
 
 /*
  *	Delta seq. info structure
@@ -73,7 +75,8 @@
  *	MASQ structure allocated for each masqueraded association
  */
 struct ip_masq {
-        struct ip_masq  *m_link, *s_link; /* hashed link ptrs */
+	struct list_head m_list, s_list, d_list;
+			/* hashed d-linked list heads */
 	atomic_t refcnt;		/* reference count */
 	struct timer_list timer;	/* Expiration timer */
 	__u16 		protocol;	/* Which protocol are we talking? */
@@ -145,8 +148,9 @@
 	int (*info)(char *, char **, off_t, int, int);
 };
 
-extern struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE];
-extern struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
+extern struct list_head ip_masq_m_table[IP_MASQ_TAB_SIZE];
+extern struct list_head ip_masq_s_table[IP_MASQ_TAB_SIZE];
+extern struct list_head ip_masq_d_table[IP_MASQ_TAB_SIZE];
 extern const char * ip_masq_state_name(int state);
 extern struct ip_masq_hook *ip_masq_user_hook;
 extern u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/net/ip_masq_mod.h linux.pre11.3/include/net/ip_masq_mod.h
--- linux.vanilla/include/net/ip_masq_mod.h	Sun Nov  8 15:07:02 1998
+++ linux.pre11.3/include/net/ip_masq_mod.h	Mon Jul 19 23:26:49 1999
@@ -64,7 +64,7 @@
  *	init functions protos
  */
 extern int ip_portfw_init(void);
-extern int ip_markfw_init(void);
+extern int ip_mfw_init(void);
 extern int ip_autofw_init(void);
 
 /*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/net/sock.h linux.pre11.3/include/net/sock.h
--- linux.vanilla/include/net/sock.h	Wed Apr 28 19:14:37 1999
+++ linux.pre11.3/include/net/sock.h	Tue Jul 20 01:40:36 1999
@@ -584,9 +584,7 @@
 	/* Keeping track of sk's, looking them up, and port selection methods. */
 	void			(*hash)(struct sock *sk);
 	void			(*unhash)(struct sock *sk);
-	void			(*rehash)(struct sock *sk);
-	unsigned short		(*good_socknum)(void);
-	int			(*verify_bind)(struct sock *sk, unsigned short snum);
+	int			(*get_port)(struct sock *sk, unsigned short snum);
 
 	unsigned short		max_header;
 	unsigned long		retransmits;
@@ -622,22 +620,26 @@
 /* Some things in the kernel just want to get at a protocols
  * entire socket list commensurate, thus...
  */
+static __inline__ void __add_to_prot_sklist(struct sock *sk)
+{
+	struct proto *p = sk->prot;
+
+	sk->sklist_prev = (struct sock *) p;
+	sk->sklist_next = p->sklist_next;
+	p->sklist_next->sklist_prev = sk;
+	p->sklist_next = sk;
+
+	/* Charge the protocol. */
+	sk->prot->inuse += 1;
+	if(sk->prot->highestinuse < sk->prot->inuse)
+		sk->prot->highestinuse = sk->prot->inuse;
+}
+
 static __inline__ void add_to_prot_sklist(struct sock *sk)
 {
 	SOCKHASH_LOCK();
-	if(!sk->sklist_next) {
-		struct proto *p = sk->prot;
-
-		sk->sklist_prev = (struct sock *) p;
-		sk->sklist_next = p->sklist_next;
-		p->sklist_next->sklist_prev = sk;
-		p->sklist_next = sk;
-
-		/* Charge the protocol. */
-		sk->prot->inuse += 1;
-		if(sk->prot->highestinuse < sk->prot->inuse)
-			sk->prot->highestinuse = sk->prot->inuse;
-	}
+	if(!sk->sklist_next)
+		__add_to_prot_sklist(sk);
 	SOCKHASH_UNLOCK();
 }
 
@@ -671,8 +673,7 @@
 /* debugging code: the test isn't even 100% correct, but it can catch bugs */
 /* Note that a double lock is ok in theory - it's just _usually_ a bug */
 	if (atomic_read(&sk->sock_readers)) {
-		__label__ here;
-		printk("double lock on socket at %p\n", &&here);
+		printk("double lock on socket at %p\n", gethere());
 here:
 	}
 #endif
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/net/tcp.h linux.pre11.3/include/net/tcp.h
--- linux.vanilla/include/net/tcp.h	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/include/net/tcp.h	Tue Jul 20 01:46:42 1999
@@ -75,11 +75,7 @@
  */
 struct tcp_bind_bucket {
 	unsigned short		port;
-	unsigned short		flags;
-#define TCPB_FLAG_LOCKED	0x0001
-#define TCPB_FLAG_FASTREUSE	0x0002
-#define TCPB_FLAG_GOODSOCKNUM	0x0004
-
+	unsigned short		fastreuse;
 	struct tcp_bind_bucket	*next;
 	struct sock		*owners;
 	struct tcp_bind_bucket	**pprev;
@@ -116,32 +112,6 @@
 	return (lport & (TCP_BHTABLE_SIZE - 1));
 }
 
-static __inline__ void tcp_sk_bindify(struct sock *sk)
-{
-	struct tcp_bind_bucket *tb;
-	unsigned short snum = sk->num;
-
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)]; tb->port != snum; tb = tb->next)
-		;
-	/* Update bucket flags. */
-	if(tb->owners == NULL) {
-		/* We're the first. */
-		if(sk->reuse && sk->state != TCP_LISTEN)
-			tb->flags = TCPB_FLAG_FASTREUSE;
-		else
-			tb->flags = 0;
-	} else {
-		if((tb->flags & TCPB_FLAG_FASTREUSE) &&
-		   ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
-			tb->flags &= ~TCPB_FLAG_FASTREUSE;
-	}
-	if((sk->bind_next = tb->owners) != NULL)
-		tb->owners->bind_pprev = &sk->bind_next;
-	tb->owners = sk;
-	sk->bind_pprev = &tb->owners;
-	sk->prev = (struct sock *) tb;
-}
-
 /* This is a TIME_WAIT bucket.  It works around the memory consumption
  * problems of sockets in such a state on heavily loaded servers, but
  * without violating the protocol specification.
@@ -478,7 +448,9 @@
 extern struct proto tcp_prot;
 extern struct tcp_mib tcp_statistics;
 
-extern unsigned short		tcp_good_socknum(void);
+extern void			tcp_put_port(struct sock *sk);
+extern void			__tcp_put_port(struct sock *sk);
+extern void			tcp_inherit_port(struct sock *sk, struct sock *child);
 
 extern void			tcp_v4_err(struct sk_buff *skb,
 					   unsigned char *, int);
@@ -631,8 +603,7 @@
 #define TCP_SLT_SYNACK		0
 #define TCP_SLT_KEEPALIVE	1
 #define TCP_SLT_TWKILL		2
-#define TCP_SLT_BUCKETGC	3
-#define TCP_SLT_MAX		4
+#define TCP_SLT_MAX		3
 
 extern struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX];
  
@@ -1068,17 +1039,6 @@
 	struct tcp_sl_timer *slt = &tcp_slt_array[timer];
 
 	atomic_dec(&slt->count);
-}
-
-/* This needs to use a slow timer, so it is here. */
-static __inline__ void tcp_sk_unbindify(struct sock *sk)
-{
-	struct tcp_bind_bucket *tb = (struct tcp_bind_bucket *) sk->prev;
-	if(sk->bind_next)
-		sk->bind_next->bind_pprev = sk->bind_pprev;
-	*sk->bind_pprev = sk->bind_next;
-	if(tb->owners == NULL)
-		tcp_inc_slow_timer(TCP_SLT_BUCKETGC);
 }
 
 extern const char timer_bug_msg[];
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/net/udp.h linux.pre11.3/include/net/udp.h
--- linux.vanilla/include/net/udp.h	Sun Nov  8 15:07:02 1998
+++ linux.pre11.3/include/net/udp.h	Tue Jul 20 01:46:42 1999
@@ -23,6 +23,7 @@
 #define _UDP_H
 
 #include <linux/udp.h>
+#include <net/sock.h>
 
 #define UDP_HTABLE_SIZE		128
 
@@ -32,10 +33,20 @@
  */
 extern struct sock *udp_hash[UDP_HTABLE_SIZE];
 
-extern unsigned short udp_good_socknum(void);
-
 #define UDP_NO_CHECK	0
 
+extern int udp_port_rover;
+
+static inline int udp_lport_inuse(u16 num)
+{
+	struct sock *sk = udp_hash[num & (UDP_HTABLE_SIZE - 1)];
+
+	for(; sk != NULL; sk = sk->next) {
+		if(sk->num == num)
+			return 1;
+	}
+	return 0;
+}
 
 extern struct proto udp_prot;
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/include/video/fbcon-vga-planes.h linux.pre11.3/include/video/fbcon-vga-planes.h
--- linux.vanilla/include/video/fbcon-vga-planes.h	Thu Jan  1 01:00:00 1970
+++ linux.pre11.3/include/video/fbcon-vga-planes.h	Mon Jul 19 23:26:51 1999
@@ -0,0 +1,37 @@
+/*
+ *  FBcon low-level driver for VGA 4-plane modes
+ */
+
+#ifndef _VIDEO_FBCON_VGA_PLANES_H
+#define _VIDEO_FBCON_VGA_PLANES_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_VGA_PLANES) || defined(CONFIG_FBCON_VGA_PLANES_MODULE)
+#define FBCON_HAS_VGA_PLANES
+#endif
+#else
+#if defined(CONFIG_FBCON_VGA_PLANES)
+#define FBCON_HAS_VGA_PLANES
+#endif
+#endif
+
+extern struct display_switch fbcon_vga_planes;
+extern struct display_switch fbcon_ega_planes;
+extern void fbcon_vga_planes_setup(struct display *p);
+extern void fbcon_vga_planes_bmove(struct display *p, int sy, int sx, int dy, int dx,
+				   int height, int width);
+extern void fbcon_vga_planes_clear(struct vc_data *conp, struct display *p, int sy,
+				   int sx, int height, int width);
+extern void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c,
+				  int yy, int xx);
+extern void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c,
+				  int yy, int xx);
+extern void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p,
+				   const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p,
+				   const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_vga_planes_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_VGA_PLANES_H */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/init/main.c linux.pre11.3/init/main.c
--- linux.vanilla/init/main.c	Thu May 27 22:12:03 1999
+++ linux.pre11.3/init/main.c	Tue Jul 20 00:20:29 1999
@@ -67,6 +67,7 @@
 
 static int init(void *);
 extern int bdflush(void *);
+extern int kupdate(void *);
 extern int kswapd(void *);
 extern int kpiod(void *);
 extern void kswapd_setup(void);
@@ -332,6 +333,9 @@
 #ifdef CONFIG_LTPC
 extern void ltpc_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_BLK_CPQ_DA
+extern void cpqarray_setup(char *str, int *ints);
+#endif
 
 #if defined(CONFIG_SYSVIPC)
 extern void ipc_init(void);
@@ -403,6 +407,9 @@
 #ifdef CONFIG_ROOT_NFS
 	{ "nfs",     0x00ff },
 #endif
+#ifdef CONFIG_BLK_DEV_LOOP
+	{ "loop",    0x0700 },
+#endif
 #ifdef CONFIG_BLK_DEV_IDE
 	{ "hda",     0x0300 },
 	{ "hdb",     0x0340 },
@@ -435,6 +442,24 @@
 	{ "sdo",     0x08e0 },
 	{ "sdp",     0x08f0 },
 #endif
+#ifdef CONFIG_BLK_DEV_DAC960
+	{ "rd/c0d0p",0x3000 },
+	{ "rd/c0d1p",0x3008 },
+	{ "rd/c0d2p",0x3010 },
+	{ "rd/c0d3p",0x3018 },
+	{ "rd/c0d4p",0x3020 },
+	{ "rd/c0d5p",0x3028 },
+	{ "rd/c0d6p",0x3030 },
+	{ "rd/c0d7p",0x3038 },
+	{ "rd/c0d8p",0x3040 },
+	{ "rd/c0d9p",0x3048 },
+	{ "rd/c0d10p",0x3050 },
+	{ "rd/c0d11p",0x3058 },
+	{ "rd/c0d12p",0x3060 },
+	{ "rd/c0d13p",0x3068 },
+	{ "rd/c0d14p",0x3070 },
+	{ "rd/c0d15p",0x3078 },
+#endif
 #ifdef CONFIG_ATARI_ACSI
 	{ "ada",     0x1c00 },
 	{ "adb",     0x1c10 },
@@ -582,6 +607,8 @@
 	{ "no-hlt", no_halt },
 	{ "no387", no_387 },
 	{ "reboot=", reboot_setup },
+#endif
+#ifdef CONFIG_MCA
 	{ "mca-pentium", mca_pentium },
 #endif
 #ifdef CONFIG_INET
@@ -861,6 +888,9 @@
 #ifdef CONFIG_LTPC
 	{ "ltpc=", ltpc_setup },
 #endif
+#ifdef CONFIG_BLK_CPQ_DA
+	{ "smart2=", cpqarray_setup },
+#endif
 	{ 0, 0 }
 };
 
@@ -1291,6 +1321,7 @@
 
 	/* Launch bdflush from here, instead of the old syscall way. */
 	kernel_thread(bdflush, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+	kernel_thread(kupdate, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 	/* Start the background pageout daemon. */
 	kswapd_setup();
 	kernel_thread(kpiod, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
@@ -1323,21 +1354,6 @@
 
 	/* Mount the root filesystem.. */
 	mount_root();
-
-#ifdef CONFIG_UMSDOS_FS
-	{
-		/*
-			When mounting a umsdos fs as root, we detect
-			the pseudo_root (/linux) and initialise it here.
-			pseudo_root is defined in fs/umsdos/inode.c
-		*/
-		extern struct inode *pseudo_root;
-		if (pseudo_root != NULL){
-			current->fs->root = pseudo_root->i_sb->s_root;
-			current->fs->pwd  = pseudo_root->i_sb->s_root;
-		}
-	}
-#endif
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	root_mountflags = real_root_mountflags;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/kernel/capability.c linux.pre11.3/kernel/capability.c
--- linux.vanilla/kernel/capability.c	Thu Dec  3 13:48:38 1998
+++ linux.pre11.3/kernel/capability.c	Mon Jul 19 23:26:40 1999
@@ -17,6 +17,8 @@
  * uninteresting and/or not to be changed.
  */
 
+kernel_cap_t cap_bset = CAP_FULL_SET;
+
 asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
 {
      int error, pid;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/kernel/ksyms.c linux.pre11.3/kernel/ksyms.c
--- linux.vanilla/kernel/ksyms.c	Wed Mar 24 10:55:28 1999
+++ linux.pre11.3/kernel/ksyms.c	Tue Jul 20 00:21:01 1999
@@ -38,6 +38,7 @@
 #include <linux/console.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
+#include <linux/capability.h>
 
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
@@ -116,6 +117,8 @@
 EXPORT_SYMBOL(get_fs_type);
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(__fput);
+EXPORT_SYMBOL(igrab);
+EXPORT_SYMBOL(iunique);
 EXPORT_SYMBOL(iget);
 EXPORT_SYMBOL(iput);
 EXPORT_SYMBOL(__namei);
@@ -184,6 +187,7 @@
 EXPORT_SYMBOL(vfs_unlink);
 EXPORT_SYMBOL(vfs_rename);
 EXPORT_SYMBOL(__pollwait);
+EXPORT_SYMBOL(ROOT_DEV);
 
 #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
 EXPORT_SYMBOL(do_nfsservctl);
@@ -222,6 +226,7 @@
 EXPORT_SYMBOL(find_buffer);
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL(max_sectors);
+EXPORT_SYMBOL(max_segments);
 EXPORT_SYMBOL(max_readahead);
 
 /* tty routines */
@@ -338,6 +343,7 @@
 EXPORT_SYMBOL(secure_tcp_sequence_number);
 EXPORT_SYMBOL(get_random_bytes);
 EXPORT_SYMBOL(securebits);
+EXPORT_SYMBOL(cap_bset);
 
 /* Program loader interfaces */
 EXPORT_SYMBOL(setup_arg_pages);
@@ -398,3 +404,6 @@
 
 /* library functions */
 EXPORT_SYMBOL(strnicmp);
+
+/* init task, for moving kthread roots - ought to export a function ?? */
+EXPORT_SYMBOL(init_task_union);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/kernel/panic.c linux.pre11.3/kernel/panic.c
--- linux.vanilla/kernel/panic.c	Mon Dec 28 23:09:49 1998
+++ linux.pre11.3/kernel/panic.c	Mon Jul 19 23:26:40 1999
@@ -11,6 +11,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
+#include <linux/notifier.h>
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
@@ -25,6 +26,8 @@
 
 int panic_timeout = 0;
 
+struct notifier_block *panic_notifier_list = NULL;
+
 void __init panic_setup(char *str, int *ints)
 {
 	if (ints[0] == 1)
@@ -52,6 +55,9 @@
 #ifdef __SMP__
 	smp_send_stop();
 #endif
+
+	notifier_call_chain(&panic_notifier_list, 0, NULL);
+
 	if (panic_timeout > 0)
 	{
 		/*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/kernel/signal.c linux.pre11.3/kernel/signal.c
--- linux.vanilla/kernel/signal.c	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/kernel/signal.c	Mon Jul 19 23:26:40 1999
@@ -29,7 +29,7 @@
 
 static kmem_cache_t *signal_queue_cachep;
 
-int nr_queued_signals;
+atomic_t nr_queued_signals;
 int max_queued_signals = 1024;
 
 void __init signals_init(void)
@@ -60,7 +60,7 @@
 	while (q) {
 		n = q->next;
 		kmem_cache_free(signal_queue_cachep, q);
-		nr_queued_signals--;
+		atomic_dec(&nr_queued_signals);
 		q = n;
 	}
 }
@@ -157,7 +157,7 @@
 					current->sigqueue_tail = pp;
 				*info = q->info;
 				kmem_cache_free(signal_queue_cachep,q);
-				nr_queued_signals--;
+				atomic_dec(&nr_queued_signals);
 				
 				/* then see if this signal is still pending. */
 				q = *pp;
@@ -323,13 +323,13 @@
 
 		struct signal_queue *q = 0;
 
-		if (nr_queued_signals < max_queued_signals) {
+		if (atomic_read(&nr_queued_signals) < max_queued_signals) {
 			q = (struct signal_queue *)
 			    kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
 		}
 		
 		if (q) {
-			nr_queued_signals++;
+			atomic_inc(&nr_queued_signals);
 			q->next = NULL;
 			*t->sigqueue_tail = q;
 			t->sigqueue_tail = &q->next;
@@ -872,7 +872,7 @@
 					else {
 						*pp = q->next;
 						kmem_cache_free(signal_queue_cachep, q);
-						nr_queued_signals--;
+						atomic_dec(&nr_queued_signals);
 					}
 					q = *pp;
 				}
@@ -1067,7 +1067,9 @@
 
 	return old;
 }
+#endif /* !defined(__alpha__) */
 
+#if !defined(__alpha__) && !defined(__mips__)
 /*
  * For backwards compatibility.  Functionality superseded by sigaction.
  */
@@ -1084,4 +1086,4 @@
 
 	return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
 }
-#endif /* !alpha */
+#endif /* !defined(__alpha__) && !defined(__mips__) */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/kernel/sysctl.c linux.pre11.3/kernel/sysctl.c
--- linux.vanilla/kernel/sysctl.c	Tue Feb 23 14:21:34 1999
+++ linux.pre11.3/kernel/sysctl.c	Mon Jul 19 23:26:40 1999
@@ -18,9 +18,10 @@
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
-#include <linux/swapctl.h>
+#include <linux/capability.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/sysrq.h>
 
 #include <asm/uaccess.h>
 
@@ -164,6 +165,8 @@
 	 0644, NULL, &proc_doutsstring, &sysctl_string},
 	{KERN_PANIC, "panic", &panic_timeout, sizeof(int),
 	 0644, NULL, &proc_dointvec},
+	{KERN_CAP_BSET, "cap-bound", &cap_bset, sizeof(kernel_cap_t),
+	 0600, NULL, &proc_dointvec_bset},
 #ifdef CONFIG_BLK_DEV_INITRD
 	{KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int),
 	 0644, NULL, &proc_dointvec},
@@ -212,6 +215,10 @@
 	{KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
 	 0644, NULL, &proc_dointvec},
 #endif
+#ifdef CONFIG_MAGIC_SYSRQ
+	{KERN_SYSRQ, "sysrq", &sysrq_enabled, sizeof (int),
+	 0644, NULL, &proc_dointvec},
+#endif	 
 	{0}
 };
 
@@ -563,7 +570,6 @@
 				continue;
 		}
 
-		/* Don't unregoster proc entries that are still being used.. */
 		if (de->count)
 			continue;
 
@@ -684,8 +690,13 @@
 	return r;
 }
 
+#define OP_SET	0
+#define OP_AND	1
+#define OP_OR	2
+#define OP_MAX	3
+#define OP_MIN	4
 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
-		  void *buffer, size_t *lenp, int conv)
+		  void *buffer, size_t *lenp, int conv, int op)
 {
 	int *i, vleft, first=1, len, left, neg, val;
 	#define TMPBUFLEN 20
@@ -736,7 +747,17 @@
 				val = -val;
 			buffer += len;
 			left -= len;
-			*i = val;
+			switch(op) {
+			case OP_SET:	*i = val; break;
+			case OP_AND:	*i &= val; break;
+			case OP_OR:	*i |= val; break;
+			case OP_MAX:	if(*i < val)
+						*i = val;
+					break;
+			case OP_MIN:	if(*i > val)
+						*i = val;
+					break;
+			}
 		} else {
 			p = buf;
 			if (!first)
@@ -778,9 +799,21 @@
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
 		     void *buffer, size_t *lenp)
 {
-    return do_proc_dointvec(table,write,filp,buffer,lenp,1);
+    return do_proc_dointvec(table,write,filp,buffer,lenp,1,OP_SET);
+}
+
+/*
+ *	init may raise the set.
+ */
+ 
+int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+			void *buffer, size_t *lenp)
+{
+	return do_proc_dointvec(table,write,filp,buffer,lenp,1,
+		(current->pid == 1) ? OP_SET : OP_AND);
 }
 
+
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
 {
@@ -883,7 +916,7 @@
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
 			  void *buffer, size_t *lenp)
 {
-    return do_proc_dointvec(table,write,filp,buffer,lenp,HZ);
+    return do_proc_dointvec(table,write,filp,buffer,lenp,HZ,OP_SET);
 }
 
 #else /* CONFIG_PROC_FS */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/lib/string.c linux.pre11.3/lib/string.c
--- linux.vanilla/lib/string.c	Sun Nov  8 15:06:44 1998
+++ linux.pre11.3/lib/string.c	Tue Jul 20 00:21:13 1999
@@ -339,3 +339,17 @@
 	return NULL;
 }
 #endif
+
+#ifndef __HAVE_ARCH_MEMCHR
+void *memchr(const void *s, int c, size_t n)
+{
+	unsigned char *p = s;
+	while (n-- != 0) {
+        	if ((unsigned char)c == *p++) {
+			return p-1;
+		}
+	}
+	return NULL;
+}
+
+#endif
\ No newline at end of file
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/mm/memory.c linux.pre11.3/mm/memory.c
--- linux.vanilla/mm/memory.c	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/mm/memory.c	Mon Jul 19 23:26:41 1999
@@ -52,7 +52,7 @@
  */
 static inline void copy_cow_page(unsigned long from, unsigned long to)
 {
-	if (from == ZERO_PAGE) {
+	if (from == ZERO_PAGE(to)) {
 		clear_page(to);
 		return;
 	}
@@ -407,7 +407,8 @@
 	}
 }
 
-static inline void zeromap_pte_range(pte_t * pte, unsigned long address, unsigned long size, pte_t zero_pte)
+static inline void zeromap_pte_range(pte_t * pte, unsigned long address,
+                                     unsigned long size, pgprot_t prot)
 {
 	unsigned long end;
 
@@ -416,6 +417,8 @@
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
 	do {
+		pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(address),
+		                               prot));
 		pte_t oldpage = *pte;
 		set_pte(pte, zero_pte);
 		forget_pte(oldpage);
@@ -424,7 +427,8 @@
 	} while (address < end);
 }
 
-static inline int zeromap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size, pte_t zero_pte)
+static inline int zeromap_pmd_range(pmd_t * pmd, unsigned long address,
+                                    unsigned long size, pgprot_t prot)
 {
 	unsigned long end;
 
@@ -436,7 +440,7 @@
 		pte_t * pte = pte_alloc(pmd, address);
 		if (!pte)
 			return -ENOMEM;
-		zeromap_pte_range(pte, address, end - address, zero_pte);
+		zeromap_pte_range(pte, address, end - address, prot);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
 	} while (address < end);
@@ -449,9 +453,7 @@
 	pgd_t * dir;
 	unsigned long beg = address;
 	unsigned long end = address + size;
-	pte_t zero_pte;
 
-	zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE, prot));
 	dir = pgd_offset(current->mm, address);
 	flush_cache_range(current->mm, beg, end);
 	while (address < end) {
@@ -459,7 +461,7 @@
 		error = -ENOMEM;
 		if (!pmd)
 			break;
-		error = zeromap_pmd_range(pmd, address, end - address, zero_pte);
+		error = zeromap_pmd_range(pmd, address, end - address, prot);
 		if (error)
 			break;
 		address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -811,9 +813,9 @@
 /*
  * This only needs the MM semaphore
  */
-static int do_anonymous_page(struct task_struct * tsk, struct vm_area_struct * vma, pte_t *page_table, int write_access)
+static int do_anonymous_page(struct task_struct * tsk, struct vm_area_struct * vma, pte_t *page_table, int write_access, unsigned long addr)
 {
-	pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE, vma->vm_page_prot));
+	pte_t entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
 	if (write_access) {
 		unsigned long page = __get_free_page(GFP_USER);
 		if (!page)
@@ -848,7 +850,8 @@
 
 	if (!vma->vm_ops || !vma->vm_ops->nopage) {
 		unlock_kernel();
-		return do_anonymous_page(tsk, vma, page_table, write_access);
+		return do_anonymous_page(tsk, vma, page_table, write_access,
+		                         address);
 	}
 
 	/*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/mm/mremap.c linux.pre11.3/mm/mremap.c
--- linux.vanilla/mm/mremap.c	Thu Dec  3 13:48:38 1998
+++ linux.pre11.3/mm/mremap.c	Tue Jul 20 00:21:25 1999
@@ -115,7 +115,7 @@
 	flush_cache_range(mm, new_addr, new_addr + len);
 	while ((offset += PAGE_SIZE) < len)
 		move_one_page(mm, new_addr + offset, old_addr + offset);
-	zap_page_range(mm, new_addr, new_addr + len);
+	zap_page_range(mm, new_addr, len);
 	flush_tlb_range(mm, new_addr, new_addr + len);
 	return -1;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/mm/page_alloc.c linux.pre11.3/mm/page_alloc.c
--- linux.vanilla/mm/page_alloc.c	Thu May 27 22:12:03 1999
+++ linux.pre11.3/mm/page_alloc.c	Tue Jul 20 00:21:36 1999
@@ -155,12 +155,12 @@
 	change_bit((index) >> (1+(order)), (area)->map)
 #define CAN_DMA(x) (PageDMA(x))
 #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT))
-#define RMQUEUE(order, gfp_mask) \
+#define RMQUEUE_DMA(order) \
 do { struct free_area_struct * area = free_area+order; \
      unsigned long new_order = order; \
 	do { struct page *prev = memory_head(area), *ret = prev->next; \
 		while (memory_head(area) != ret) { \
-			if (!(gfp_mask & __GFP_DMA) || CAN_DMA(ret)) { \
+			if (CAN_DMA(ret)) { \
 				unsigned long map_nr; \
 				(prev->next = ret->next)->prev = prev; \
 				map_nr = ret - mem_map; \
@@ -176,6 +176,45 @@
 		new_order++; area++; \
 	} while (new_order < NR_MEM_LISTS); \
 } while (0)
+#define RMQUEUE_NODMA(order) \
+do { struct free_area_struct * area = free_area+order; \
+     unsigned long new_order = order; \
+	do { struct page *prev = memory_head(area), *ret = prev->next; \
+		while (memory_head(area) != ret) { \
+			if (!CAN_DMA(ret)) { \
+				unsigned long map_nr; \
+				(prev->next = ret->next)->prev = prev; \
+				map_nr = ret - mem_map; \
+				MARK_USED(map_nr, new_order, area); \
+				nr_free_pages -= 1 << order; \
+				EXPAND(ret, map_nr, order, new_order, area); \
+				spin_unlock_irqrestore(&page_alloc_lock, flags); \
+				return ADDRESS(map_nr); \
+			} \
+			prev = ret; \
+			ret = ret->next; \
+		} \
+		new_order++; area++; \
+	} while (new_order < NR_MEM_LISTS); \
+} while (0)
+#define RMQUEUE_ANY(order) \
+do { struct free_area_struct * area = free_area+order; \
+     unsigned long new_order = order; \
+	do { struct page *prev = memory_head(area), *ret = prev->next; \
+		if (memory_head(area) != ret) { \
+			unsigned long map_nr; \
+			(prev->next = ret->next)->prev = prev; \
+			map_nr = ret - mem_map; \
+			MARK_USED(map_nr, new_order, area); \
+			nr_free_pages -= 1 << order; \
+			EXPAND(ret, map_nr, order, new_order, area); \
+			spin_unlock_irqrestore(&page_alloc_lock, flags); \
+			return ADDRESS(map_nr); \
+		 \
+		} \
+		new_order++; area++; \
+	} while (new_order < NR_MEM_LISTS); \
+} while (0)
 
 #define EXPAND(map,index,low,high,area) \
 do { unsigned long size = 1 << high; \
@@ -236,7 +275,12 @@
 	}
 ok_to_allocate:
 	spin_lock_irqsave(&page_alloc_lock, flags);
-	RMQUEUE(order, gfp_mask);
+	if (gfp_mask & __GFP_DMA)
+		RMQUEUE_DMA(order);
+	else {
+		RMQUEUE_NODMA(order);
+		RMQUEUE_ANY(order);
+	}
 	spin_unlock_irqrestore(&page_alloc_lock, flags);
 
 	/*
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/mm/swapfile.c linux.pre11.3/mm/swapfile.c
--- linux.vanilla/mm/swapfile.c	Tue Jun 15 16:49:57 1999
+++ linux.pre11.3/mm/swapfile.c	Tue Jul 20 00:21:45 1999
@@ -5,7 +5,6 @@
  *  Swap reorganised 29.12.95, Stephen Tweedie
  */
 
-#include <linux/config.h>
 #include <linux/malloc.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
@@ -649,7 +648,8 @@
 			else
 				p->swap_map[page] = SWAP_MAP_BAD;
 		}
-		nr_good_pages = swap_header->info.last_page - i;
+		nr_good_pages = swap_header->info.last_page -
+		                swap_header->info.nr_badpages - 1;
 		lock_map_size = (p->max + 7) / 8;
 		if (error) 
 			goto bad_swap;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/appletalk/ddp.c linux.pre11.3/net/appletalk/ddp.c
--- linux.vanilla/net/appletalk/ddp.c	Mon Mar 29 10:25:57 1999
+++ linux.pre11.3/net/appletalk/ddp.c	Mon Jul 19 23:27:11 1999
@@ -894,7 +894,7 @@
 			else
 			{
 				limit = ntohs(nr->nr_lastnet);
-				if(limit - ntohs(nr->nr_firstnet) > 256)
+				if(limit - ntohs(nr->nr_firstnet) > 4096)
 				{
 					printk(KERN_WARNING "Too many routes/iface.\n");
 					return (-EINVAL);
@@ -987,6 +987,8 @@
                                 return (-EPERM);
                         if(sa->sat_family != AF_APPLETALK)
                                 return (-EINVAL);
+                        if (atif == NULL)
+                                return (-EADDRNOTAVAIL);
 
                         /*
                          * give to aarp module to remove proxy entry
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ax25/af_ax25.c linux.pre11.3/net/ax25/af_ax25.c
--- linux.vanilla/net/ax25/af_ax25.c	Wed Mar 10 21:13:12 1999
+++ linux.pre11.3/net/ax25/af_ax25.c	Mon Jul 19 23:27:11 1999
@@ -462,6 +462,9 @@
 	if ((ax25_dev = ax25_addr_ax25dev(&ax25_ctl.port_addr)) == NULL)
 		return -ENODEV;
 
+	if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
+		return -EINVAL;
+
 	digi.ndigi = ax25_ctl.digi_count;
 	for (k = 0; k < digi.ndigi; k++)
 		digi.calls[k] = ax25_ctl.digi_addr[k];
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/bridge/br.c linux.pre11.3/net/bridge/br.c
--- linux.vanilla/net/bridge/br.c	Wed Mar 10 21:13:12 1999
+++ linux.pre11.3/net/bridge/br.c	Mon Jul 19 23:27:17 1999
@@ -1831,12 +1831,8 @@
 			
 /*			printk("Flood to port %d\n",i);*/
 			nskb->nh.raw = nskb->data + ETH_HLEN;
-#if LINUX_VERSION_CODE >= 0x20100
 			nskb->priority = 1;
 			dev_queue_xmit(nskb);
-#else
-			dev_queue_xmit(nskb,nskb->dev,1);
-#endif
 		}
 	}
 	return(0);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/core/dev.c linux.pre11.3/net/core/dev.c
--- linux.vanilla/net/core/dev.c	Mon Mar 29 10:25:57 1999
+++ linux.pre11.3/net/core/dev.c	Mon Jul 19 23:27:12 1999
@@ -19,6 +19,7 @@
  *		Adam Sulmicki <adam@cfar.umd.edu>
  *
  *	Changes:
+ *		Marcelo Tosatti <marcelo@conectiva.com.br> : dont accept mtu 0 or <
  *		Alan Cox	:	device private ioctl copies fields back.
  *		Alan Cox	:	Transmit queue code does relevant stunts to
  *					keep the queue safe.
@@ -1470,7 +1471,7 @@
 			 *	MTU must be positive.
 			 */
 			 
-			if (ifr->ifr_mtu<0)
+			if (ifr->ifr_mtu<=0)
 				return -EINVAL;
 
 			if (dev->change_mtu)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/core/neighbour.c linux.pre11.3/net/core/neighbour.c
--- linux.vanilla/net/core/neighbour.c	Wed Apr 28 19:14:38 1999
+++ linux.pre11.3/net/core/neighbour.c	Mon Jul 19 23:27:12 1999
@@ -354,8 +354,8 @@
 	u32 h;
 
 	for (h=0; h<=PNEIGH_HASHMASK; h++) {
-		np = &tbl->phash_buckets[h]; 
-		for (np = &tbl->phash_buckets[h]; (n=*np) != NULL; np = &n->next) {
+		np = &tbl->phash_buckets[h];
+		while ((n=*np) != NULL) {
 			if (n->dev == dev || dev == NULL) {
 				*np = n->next;
 				synchronize_bh();
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/core/rtnetlink.c linux.pre11.3/net/core/rtnetlink.c
--- linux.vanilla/net/core/rtnetlink.c	Wed Mar 24 10:55:28 1999
+++ linux.pre11.3/net/core/rtnetlink.c	Mon Jul 19 23:27:12 1999
@@ -14,6 +14,7 @@
  *
  *	Fixes:
  *	Vitaly E. Lavrov		RTA_OK arithmetics was wrong.
+ *	Alexey Zhuravlev		ifi_change does something useful 
  */
 
 #include <linux/config.h>
@@ -139,7 +140,7 @@
 }
 
 static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct device *dev,
-				 int type, u32 pid, u32 seq)
+				 int type, u32 pid, u32 seq, u32 change)
 {
 	struct ifinfomsg *r;
 	struct nlmsghdr  *nlh;
@@ -152,7 +153,7 @@
 	r->ifi_type = dev->type;
 	r->ifi_index = dev->ifindex;
 	r->ifi_flags = dev->flags;
-	r->ifi_change = ~0U;
+	r->ifi_change = change;
 
 	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
 	if (dev->addr_len) {
@@ -192,7 +193,7 @@
 	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
 		if (idx < s_idx)
 			continue;
-		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq) <= 0)
+		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
 			break;
 	}
 	cb->args[0] = idx;
@@ -235,7 +236,7 @@
 	if (!skb)
 		return;
 
-	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0) < 0) {
+	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, ~0U) < 0) {
 		kfree_skb(skb);
 		return;
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/af_inet.c linux.pre11.3/net/ipv4/af_inet.c
--- linux.vanilla/net/ipv4/af_inet.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/af_inet.c	Mon Jul 19 23:27:12 1999
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.87.2.1 1999/05/29 04:32:01 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.87.2.3 1999/07/01 10:43:51 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -262,8 +262,7 @@
 {
 	/* We may need to bind the socket. */
 	if (sk->num == 0) {
-		sk->num = sk->prot->good_socknum();
-		if (sk->num == 0) 
+		if (sk->prot->get_port(sk, 0) != 0)
 			return(-EAGAIN);
 		sk->sport = htons(sk->num);
 		sk->prot->hash(sk);
@@ -279,28 +278,38 @@
 int inet_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk = sock->sk;
+	unsigned char old_state;
 
 	if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
 		return(-EINVAL);
 
-	if (inet_autobind(sk) != 0)
-		return -EAGAIN;
-
-	/* We might as well re use these. */ 
 	if ((unsigned) backlog == 0)	/* BSDism */
 		backlog = 1;
 	if ((unsigned) backlog > SOMAXCONN)
 		backlog = SOMAXCONN;
 	sk->max_ack_backlog = backlog;
-	if (sk->state != TCP_LISTEN) {
-		sk->ack_backlog = 0;
+
+	/* Really, if the socket is already in listen state
+	 * we can only allow the backlog to be adjusted.
+	 */
+	old_state = sk->state;
+	if (old_state != TCP_LISTEN) {
 		sk->state = TCP_LISTEN;
+		sk->ack_backlog = 0;
+		if (sk->num == 0) {
+			if (sk->prot->get_port(sk, 0) != 0) {
+				sk->state = old_state;
+				return -EAGAIN;
+			}
+			sk->sport = htons(sk->num);
+			add_to_prot_sklist(sk);
+		}
+
 		dst_release(xchg(&sk->dst_cache, NULL));
-		sk->prot->rehash(sk);
-		add_to_prot_sklist(sk);
+		sk->prot->hash(sk);
+		sk->socket->flags |= SO_ACCEPTCON;
 	}
-	sk->socket->flags |= SO_ACCEPTCON;
-	return(0);
+	return 0;
 }
 
 /*
@@ -471,11 +480,9 @@
 		 */
 		timeout = 0;
 		if (sk->linger && !(current->flags & PF_EXITING)) {
-			timeout = MAX_SCHEDULE_TIMEOUT;
-
-			/* XXX This makes no sense whatsoever... -DaveM */
-			if (!sk->lingertime)
-				timeout = HZ*sk->lingertime;
+			timeout = HZ * sk->lingertime;
+			if (!timeout)
+				timeout = MAX_SCHEDULE_TIMEOUT;
 		}
 		sock->sk = NULL;
 		sk->socket = NULL;
@@ -528,20 +535,17 @@
 	if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END))
 		return -EADDRINUSE;
 #endif		 
-	if (snum == 0) 
-		snum = sk->prot->good_socknum();
-	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
 		return(-EACCES);
 	
 	/* Make sure we are allowed to bind here. */
-	if(sk->prot->verify_bind(sk, snum))
+	if (sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
-	sk->num = snum;
-	sk->sport = htons(snum);
+	sk->sport = htons(sk->num);
 	sk->daddr = 0;
 	sk->dport = 0;
-	sk->prot->rehash(sk);
+	sk->prot->hash(sk);
 	add_to_prot_sklist(sk);
 	dst_release(sk->dst_cache);
 	sk->dst_cache=NULL;
@@ -611,11 +615,13 @@
 		if (flags & O_NONBLOCK)
 			return -EALREADY;
 	} else {
+		if (sk->prot->connect == NULL) 
+			return(-EOPNOTSUPP);
+
 		/* We may need to bind the socket. */
 		if (inet_autobind(sk) != 0)
 			return(-EAGAIN);
-		if (sk->prot->connect == NULL) 
-			return(-EOPNOTSUPP);
+
 		err = sk->prot->connect(sk, uaddr, addr_len);
 		/* Note: there is a theoretical race here when an wake up
 		   occurred before inet_wait_for_connect is entered. In 2.3
@@ -789,7 +795,7 @@
 		return sock_error(sk);
 
 	/* We may need to bind the socket. */
-	if(inet_autobind(sk) != 0)
+	if (inet_autobind(sk) != 0)
 		return -EAGAIN;
 
 	return sk->prot->sendmsg(sk, msg, size);
@@ -808,9 +814,11 @@
 		       2->3 */
 	if ((how & ~SHUTDOWN_MASK) || how==0)	/* MAXINT->0 */
 		return(-EINVAL);
+	if (!sk)
+		return(-ENOTCONN);
 	if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
 		sock->state = SS_CONNECTED;
-	if (!sk || !tcp_connected(sk->state)) 
+	if (!tcp_connected(sk->state)) 
 		return(-ENOTCONN);
 	sk->shutdown |= how;
 	if (sk->prot->shutdown)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/arp.c linux.pre11.3/net/ipv4/arp.c
--- linux.vanilla/net/ipv4/arp.c	Wed Mar 24 10:55:28 1999
+++ linux.pre11.3/net/ipv4/arp.c	Mon Jul 19 23:27:12 1999
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.77 1999/03/21 05:22:30 davem Exp $
+ * Version:	$Id: arp.c,v 1.77.2.1 1999/06/28 10:39:23 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
@@ -383,9 +383,9 @@
 			end_bh_atomic();
 			return 0;
 		}
+		neigh_release(n);
 	} else
 		kfree_skb(skb);
-	neigh_release(n);
 	end_bh_atomic();
 	return 1;
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/devinet.c linux.pre11.3/net/ipv4/devinet.c
--- linux.vanilla/net/ipv4/devinet.c	Thu May 27 22:12:03 1999
+++ linux.pre11.3/net/ipv4/devinet.c	Mon Jul 19 23:27:12 1999
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.28 1999/05/08 20:00:16 davem Exp $
+ *	Version: $Id: devinet.c,v 1.28.2.1 1999/06/28 10:39:30 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -100,6 +100,9 @@
 {
 	struct in_device *in_dev;
 
+	if (dev->mtu < 68)
+		return NULL;
+
 	in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
 	if (!in_dev)
 		return NULL;
@@ -721,6 +724,10 @@
 	case NETDEV_DOWN:
 		ip_mc_down(in_dev);
 		break;
+	case NETDEV_CHANGEMTU:	
+		if (dev->mtu >= 68)
+			break;
+		/* MTU falled under minimal IP mtu. Disable IP. */
 	case NETDEV_UNREGISTER:
 		inetdev_destroy(in_dev);
 		break;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/icmp.c linux.pre11.3/net/ipv4/icmp.c
--- linux.vanilla/net/ipv4/icmp.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/icmp.c	Mon Jul 19 23:27:12 1999
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.52.2.1 1999/06/09 01:56:07 davem Exp $
+ *	Version: $Id: icmp.c,v 1.52.2.2 1999/06/20 21:27:39 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -699,8 +699,8 @@
 			case ICMP_FRAG_NEEDED:
 				if (ipv4_config.no_pmtu_disc) {
 					if (net_ratelimit())
-						printk(KERN_INFO "ICMP: %s: fragmentation needed and DF set.\n",
-					       in_ntoa(iph->daddr));
+						printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n",
+					       NIPQUAD(iph->daddr));
 				} else {
 					unsigned short new_mtu;
 					new_mtu = ip_rt_frag_needed(iph, ntohs(icmph->un.frag.mtu));
@@ -711,7 +711,7 @@
 				break;
 			case ICMP_SR_FAILED:
 				if (net_ratelimit())
-					printk(KERN_INFO "ICMP: %s: Source Route Failed.\n", in_ntoa(iph->daddr));
+					printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr));
 				break;
 			default:
 				break;
@@ -741,8 +741,8 @@
 		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));
+				printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n",
+			       	NIPQUAD(skb->nh.iph->saddr));
 			return; 
 		}
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ip_masq.c linux.pre11.3/net/ipv4/ip_masq.c
--- linux.vanilla/net/ipv4/ip_masq.c	Wed Mar 24 10:55:29 1999
+++ linux.pre11.3/net/ipv4/ip_masq.c	Mon Jul 19 23:27:12 1999
@@ -4,7 +4,7 @@
  *
  * 	Copyright (c) 1994 Pauline Middelink
  *
- *	$Id: ip_masq.c,v 1.34 1999/03/17 01:53:51 davem Exp $
+ *	$Id: ip_masq.c,v 1.34.2.1 1999/07/02 10:10:00 davem Exp $
  *
  *
  *	See ip_fw.c for original log
@@ -46,6 +46,7 @@
  *	Juan Jose Ciarlante	: 	make masq_proto_doff() robust against fake sized/corrupted packets
  *	Kai Bankett		:	do not toss other IP protos in proto_doff()
  *	Dan Kegel		:	pointed correct NAT behavior for UDP streams
+ *	Julian Anastasov	:	use daddr and dport as hash keys
  *	
  */
 
@@ -315,9 +316,7 @@
  *	Will cycle in MASQ_PORT boundaries.
  */
 static __u16 masq_port = PORT_MASQ_BEGIN;
-#ifdef __SMP__
 static spinlock_t masq_port_lock = SPIN_LOCK_UNLOCKED;
-#endif
 
 /*
  *	free ports counters (UDP & TCP)
@@ -366,17 +365,24 @@
 EXPORT_SYMBOL(ip_masq_control_del);
 EXPORT_SYMBOL(ip_masq_control_get);
 EXPORT_SYMBOL(ip_masq_user_hook);
-EXPORT_SYMBOL(ip_masq_m_tab);
 EXPORT_SYMBOL(ip_masq_state_name);
 EXPORT_SYMBOL(ip_masq_select_addr);
 EXPORT_SYMBOL(__ip_masq_lock);
+EXPORT_SYMBOL(ip_masq_m_table);
+EXPORT_SYMBOL(ip_masq_s_table);
+EXPORT_SYMBOL(ip_masq_d_table);
 
 /*
- *	2 ip_masq hash tables: for input and output pkts lookups.
+ *	3 ip_masq hash double linked tables: 
+ *	  2 for input  m{addr,port}  and output s{addr,port} pkts lookups.
+ *	  1 for extra modules support (daddr)
  */
+  
+#define IP_MASQ_NTABLES 3
 
-struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE];
-struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
+struct list_head ip_masq_m_table[IP_MASQ_TAB_SIZE];
+struct list_head ip_masq_s_table[IP_MASQ_TAB_SIZE];
+struct list_head ip_masq_d_table[IP_MASQ_TAB_SIZE];
 
 /*
  * timeouts
@@ -450,21 +456,44 @@
 			__builtin_return_address(0));
                 return 0;
         }
-        /*
-         *	Hash by proto,m{addr,port}
-         */
-        hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
-        ms->m_link = ip_masq_m_tab[hash];
-	atomic_inc(&ms->refcnt);
-        ip_masq_m_tab[hash] = ms;
+	atomic_add(IP_MASQ_NTABLES, &ms->refcnt);
+
+	if ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |
+		IP_MASQ_F_SIMPLE_HASH)) == 0)
+		/*
+		 *	Hash by proto,m{addr,port},d{addr,port}
+		 */
+		hash = ip_masq_hash_key(ms->protocol,
+			ms->maddr^ms->daddr, ms->mport^ms->dport);
+	else
+		/*
+		 *	Hash by proto,m{addr,port}
+		 */
+		hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
+
+	list_add(&ms->m_list, &ip_masq_m_table[hash]);
+
+	if ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |
+		IP_MASQ_F_NO_SADDR | IP_MASQ_F_NO_SPORT |
+		IP_MASQ_F_SIMPLE_HASH)) == 0)
+		/*
+		 *	Hash by proto,s{addr,port},d{addr,port}
+		 */
+		hash = ip_masq_hash_key(ms->protocol,
+			ms->saddr^ms->daddr, ms->sport^ms->dport);
+	else
+		/*
+		 *	Hash by proto,s{addr,port}
+		 */
+		hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
+
+	list_add(&ms->s_list, &ip_masq_s_table[hash]);
 
         /*
-         *	Hash by proto,s{addr,port}
+         *	Hash by proto,d{addr,port}
          */
-        hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
-        ms->s_link = ip_masq_s_tab[hash];
-	atomic_inc(&ms->refcnt);
-        ip_masq_s_tab[hash] = ms;
+        hash = ip_masq_hash_key(ms->protocol, ms->daddr, ms->dport);
+	list_add(&ms->d_list, &ip_masq_d_table[hash]);
 
 
         ms->flags |= IP_MASQ_F_HASHED;
@@ -479,34 +508,16 @@
 
 static int ip_masq_unhash(struct ip_masq *ms)
 {
-        unsigned hash;
-        struct ip_masq ** ms_p;
         if (!(ms->flags & IP_MASQ_F_HASHED)) {
                 IP_MASQ_ERR( "ip_masq_unhash(): request for unhash flagged, called from %p\n",
 			__builtin_return_address(0));
                 return 0;
         }
-        /*
-         *	UNhash by m{addr,port}
-         */
-        hash = ip_masq_hash_key(ms->protocol, ms->maddr, ms->mport);
-        for (ms_p = &ip_masq_m_tab[hash]; *ms_p ; ms_p = &(*ms_p)->m_link)
-                if (ms == (*ms_p))  {
-			atomic_dec(&ms->refcnt);
-			*ms_p = ms->m_link;
-                        break;
-                }
+	list_del(&ms->m_list);
+	list_del(&ms->s_list);
+	list_del(&ms->d_list);
 
-        /*
-         *	UNhash by s{addr,port}
-         */
-        hash = ip_masq_hash_key(ms->protocol, ms->saddr, ms->sport);
-        for (ms_p = &ip_masq_s_tab[hash]; *ms_p ; ms_p = &(*ms_p)->s_link)
-                if (ms == (*ms_p))  {
-			atomic_dec(&ms->refcnt);
-			*ms_p = ms->s_link;
-                        break;
-                }
+	atomic_sub(IP_MASQ_NTABLES, &ms->refcnt);
 
         ms->flags &= ~IP_MASQ_F_HASHED;
         return 1;
@@ -535,10 +546,34 @@
 {
         unsigned hash;
         struct ip_masq *ms = NULL;
+	struct list_head *l,*e;
+
+	hash = ip_masq_hash_key(protocol, d_addr^s_addr, d_port^s_port);
+
+	l = &ip_masq_m_table[hash];
+	for (e=l->next; e!=l; e=e->next) {
+		ms = list_entry(e, struct ip_masq, m_list);
+		if (s_port==ms->dport && s_addr==ms->daddr &&
+		    d_port==ms->mport && protocol==ms->protocol &&
+		    d_addr==ms->maddr &&
+		    ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS)) == 0)
+		    ) {
+			IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX OK\n",
+			       protocol,
+			       s_addr,
+			       s_port,
+			       d_addr,
+			       d_port);
+			atomic_inc(&ms->refcnt);
+                        goto out;
+		}
+        }
 
         hash = ip_masq_hash_key(protocol, d_addr, d_port);
 
-        for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
+	l = &ip_masq_m_table[hash];
+	for (e=l->next; e!=l; e=e->next) {
+		ms = list_entry(e, struct ip_masq, m_list);
 		if (protocol==ms->protocol && 
 		    (d_addr==ms->maddr && d_port==ms->mport) &&
 		    (s_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&
@@ -561,6 +596,7 @@
 	       d_addr,
 	       d_port);
 
+	ms = NULL;
 out:
         return ms;
 }
@@ -585,13 +621,40 @@
 {
         unsigned hash;
         struct ip_masq *ms = NULL;
+	struct list_head *l,*e;
 
 	/*	
 	 *	Check for "full" addressed entries
 	 */
+	hash = ip_masq_hash_key(protocol, s_addr^d_addr, s_port^d_port);
+
+	l = &ip_masq_s_table[hash];
+	for (e=l->next; e!=l; e=e->next) {
+		ms = list_entry(e, struct ip_masq, s_list);
+		if (d_addr==ms->daddr && d_port==ms->dport &&
+		   s_addr==ms->saddr && s_port==ms->sport &&
+		   protocol==ms->protocol &&
+		   ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |
+		   IP_MASQ_F_NO_SADDR | IP_MASQ_F_NO_SPORT)) == 0)
+                   ) {
+			IP_MASQ_DEBUG(2, "lk/out0 %d %08X:%04hX->%08X:%04hX OK\n",
+			       protocol,
+			       s_addr,
+			       s_port,
+			       d_addr,
+			       d_port);
+
+			atomic_inc(&ms->refcnt);
+			goto out;
+		}
+
+        }
+
         hash = ip_masq_hash_key(protocol, s_addr, s_port);
 	
-        for(ms = ip_masq_s_tab[hash]; ms ; ms = ms->s_link) {
+	l = &ip_masq_s_table[hash];
+	for (e=l->next; e!=l; e=e->next) {
+		ms = list_entry(e, struct ip_masq, s_list);
 		if (protocol == ms->protocol &&
 		    s_addr == ms->saddr && s_port == ms->sport &&
 		    (d_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&
@@ -614,7 +677,9 @@
 	 *	Check for NO_SPORT entries
 	 */
         hash = ip_masq_hash_key(protocol, s_addr, 0);
-        for(ms = ip_masq_s_tab[hash]; ms ; ms = ms->s_link) {
+	l = &ip_masq_s_table[hash];
+	for (e=l->next; e!=l; e=e->next) {
+		ms = list_entry(e, struct ip_masq, s_list);
 		if (ms->flags & IP_MASQ_F_NO_SPORT &&
 		    protocol == ms->protocol &&
 		    s_addr == ms->saddr && 
@@ -639,6 +704,7 @@
 	       d_addr,
 	       d_port);
 
+	ms = NULL;
 out:
         return ms;
 }
@@ -710,9 +776,9 @@
 	__ip_masq_put(ms);
 
 	/*
-	 *	if refcnt==2  (2 hashes)	
+	 *	if refcnt==IP_MASQ_NTABLES
 	 */
-	if (atomic_read(&ms->refcnt)==2) {
+	if (atomic_read(&ms->refcnt)==IP_MASQ_NTABLES) {
 		__ip_masq_set_expire(ms, ms->timeout);
 	} else {
 		IP_MASQ_DEBUG(0, "did not set timer with refcnt=%d, called from %p\n",
@@ -845,6 +911,9 @@
         }
 	MOD_INC_USE_COUNT;
         memset(ms, 0, sizeof(*ms));
+	INIT_LIST_HEAD(&ms->s_list);
+	INIT_LIST_HEAD(&ms->m_list);
+	INIT_LIST_HEAD(&ms->d_list);
 	init_timer(&ms->timer);
 	ms->timer.data     = (unsigned long)ms;
 	ms->timer.function = masq_expire;
@@ -1157,11 +1226,11 @@
 		 */
 
 		if ( ms->flags & IP_MASQ_F_NO_SPORT && ms->protocol == IPPROTO_TCP ) {
-			ms->flags &= ~IP_MASQ_F_NO_SPORT;
 
 			write_lock(&__ip_masq_lock);
 			
 			ip_masq_unhash(ms);
+			ms->flags &= ~IP_MASQ_F_NO_SPORT;
 			ms->sport = h.portp[0];
 			ip_masq_hash(ms);	/* hash on new sport */
 
@@ -2011,16 +2080,30 @@
 			ms->daddr = iph->saddr;
 		} else {
                 if ( ms->flags & IP_MASQ_F_NO_DPORT ) { /*  && ms->protocol == IPPROTO_TCP ) { */
+
+			write_lock(&__ip_masq_lock);
+
+			ip_masq_unhash(ms);
                         ms->flags &= ~IP_MASQ_F_NO_DPORT;
                         ms->dport = h.portp[0];
+			ip_masq_hash(ms);	/* hash on new dport */
+
+			write_unlock(&__ip_masq_lock);
 
                         IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled dport=%d\n",
                                ntohs(ms->dport));
 
                 }
                 if (ms->flags & IP_MASQ_F_NO_DADDR ) { /*  && ms->protocol == IPPROTO_TCP)  { */
+
+			write_lock(&__ip_masq_lock);
+
+			ip_masq_unhash(ms);
                         ms->flags &= ~IP_MASQ_F_NO_DADDR;
                         ms->daddr = iph->saddr;
+			ip_masq_hash(ms);	/* hash on new daddr */
+
+			write_unlock(&__ip_masq_lock);
 
                         IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled daddr=%lX\n",
                                ntohl(ms->daddr));
@@ -2162,7 +2245,7 @@
 	char temp[129];
         int idx = 0;
 	int len=0;
-
+	struct list_head *l,*e;
 
 	if (offset < 128)
 	{
@@ -2183,8 +2266,9 @@
 	 */
 	read_lock_bh(&__ip_masq_lock);
 
-        for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
-	{
+	l = &ip_masq_m_table[idx];
+	for (e=l->next; e!=l; e=e->next) {
+		ms = list_entry(e, struct ip_masq, m_list);
 		pos += 128;
 		if (pos <= offset) {
 			len = 0;
@@ -2400,6 +2484,12 @@
  */
 __initfunc(int ip_masq_init(void))
 {
+	int idx;
+        for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)  {
+		INIT_LIST_HEAD(&ip_masq_s_table[idx]);
+		INIT_LIST_HEAD(&ip_masq_m_table[idx]);
+		INIT_LIST_HEAD(&ip_masq_d_table[idx]);
+	}
 #ifdef CONFIG_PROC_FS        
 	proc_net_register(&(struct proc_dir_entry) {
 		PROC_NET_IPMSQHST, 13, "ip_masquerade",
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ip_masq_irc.c linux.pre11.3/net/ipv4/ip_masq_irc.c
--- linux.vanilla/net/ipv4/ip_masq_irc.c	Sun Nov  8 15:07:12 1998
+++ linux.pre11.3/net/ipv4/ip_masq_irc.c	Mon Jul 19 23:27:12 1999
@@ -2,7 +2,7 @@
  *		IP_MASQ_IRC irc masquerading module
  *
  *
- * Version:	@(#)ip_masq_irc.c 0.03   97/11/30
+ * Version:	@(#)ip_masq_irc.c 0.04   99/06/19
  *
  * Author:	Juan Jose Ciarlante
  *		
@@ -18,6 +18,8 @@
  *	Oliver Wagner 		:  more IRC cmds processing
  *	  <winmute@lucifer.gv.kotnet.org>
  *	Juan Jose Ciarlante	:  put new ms entry to listen()
+ *	Scottie Shore		:  added support for clients that add extra args
+ *	  <sshore@escape.ca>
  *
  * FIXME:
  *	- detect also previous "PRIVMSG" string ?.
@@ -82,15 +84,14 @@
 {
   char *match;
   int matchlen;
-  int xtra_args;
 };
 
 struct dccproto dccprotos[NUM_DCCPROTO] = {
- { "SEND ", 5, 1 },
- { "CHAT ", 5, 0, },
- { "MOVE ", 5, 1 },
- { "TSEND ", 6, 1, },
- { "SCHAT ", 6, 0, }
+ { "SEND ", 5 },
+ { "CHAT ", 5 },
+ { "MOVE ", 5 },
+ { "TSEND ", 6 },
+ { "SCHAT ", 6 }
 };
 #define MAXMATCHLEN 6
 
@@ -121,7 +122,6 @@
 	char buf[20];		/* "m_addr m_port" (dec base)*/
         unsigned buf_len;
 	int diff;
-        int xtra_args = 0;      /* extra int args wanted after addr */
         char *dcc_p, *addr_beg_p, *addr_end_p;
 
         skb = *skb_p;
@@ -132,12 +132,11 @@
         /*
 	 *	Hunt irc DCC string, the _shortest_:
 	 *
-	 *	strlen("DCC CHAT chat AAAAAAAA P\x01\n")=26
-	 *	strlen("DCC SCHAT chat AAAAAAAA P\x01\n")=27
-	 *	strlen("DCC SEND F AAAAAAAA P S\x01\n")=25
-	 *	strlen("DCC MOVE F AAAAAAAA P S\x01\n")=25
-	 *	strlen("DCC TSEND F AAAAAAAA P S\x01\n")=26
-	 *	strlen("DCC MOVE F AAAAAAAA P S\x01\n")=25
+	 *	strlen("\1DCC CHAT chat AAAAAAAA P\1\n")=27
+	 *	strlen("\1DCC SCHAT chat AAAAAAAA P\1\n")=28
+	 *	strlen("\1DCC SEND F AAAAAAAA P S\1\n")=26
+	 *	strlen("\1DCC MOVE F AAAAAAAA P S\1\n")=26
+	 *	strlen("\1DCC TSEND F AAAAAAAA P S\1\n")=27
 	 *		AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits)
 	 *		P:         bound port (min 1 d )
 	 *		F:         filename   (min 1 d )
@@ -147,16 +146,16 @@
 
         data_limit = skb->h.raw + skb->len;
         
-	while (data < (data_limit - ( 21 + MAXMATCHLEN ) ) )
+	while (data < (data_limit - ( 22 + MAXMATCHLEN ) ) )
 	{
 		int i;
-		if (memcmp(data,"DCC ",4))  {
+		if (memcmp(data,"\1DCC ",5))  {
 			data ++;
 			continue;
 		}
 
 		dcc_p = data;
-		data += 4;     /* point to DCC cmd */
+		data += 5;     /* point to DCC cmd */
 
 		for(i=0; i<NUM_DCCPROTO; i++)
 		{
@@ -166,7 +165,6 @@
 
 			if( memcmp(data, dccprotos[i].match, dccprotos[i].matchlen ) == 0 )
 			{
-				xtra_args = dccprotos[i].xtra_args;
 				data += dccprotos[i].matchlen;
 
 				/*
@@ -176,7 +174,7 @@
 				while( *data++ != ' ')
 
 					/*
-					 *	must still parse, at least, "AAAAAAAA P\x01\n",
+					 *	must still parse, at least, "AAAAAAAA P\1\n",
 					 *      12 bytes left.
 					 */
 					if (data > (data_limit-12)) return 0;
@@ -198,29 +196,6 @@
 
 				s_port = simple_strtoul(data,&data,10);
 				addr_end_p = data;
-
-				/*
-				 *	should check args consistency?
-				 */
-
-				while(xtra_args) {
-					if (*data != ' ')
-						break;
-					data++;
-					simple_strtoul(data,&data,10);
-					xtra_args--;
-				}
-
-				if (xtra_args != 0) continue;
-
-				/*
-				 *	terminators.
-				 */
-
-				if (data[0] != 0x01)
-					continue;
-				if (data[1]!='\r' && data[1]!='\n')
-					continue;
 
 				/*
 				 *	Now create an masquerade entry for it
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ip_masq_mfw.c linux.pre11.3/net/ipv4/ip_masq_mfw.c
--- linux.vanilla/net/ipv4/ip_masq_mfw.c	Tue Feb 23 14:21:34 1999
+++ linux.pre11.3/net/ipv4/ip_masq_mfw.c	Mon Jul 19 23:27:14 1999
@@ -3,7 +3,7 @@
  *
  *	Does (reverse-masq) forwarding based on skb->fwmark value
  *
- *	$Id: ip_masq_mfw.c,v 1.3 1999/01/26 05:33:47 davem Exp $
+ *	$Id: ip_masq_mfw.c,v 1.3.2.1 1999/07/02 10:10:03 davem Exp $
  *
  * Author:	Juan Jose Ciarlante   <jjciarla@raiz.uncu.edu.ar>
  *		  based on Steven Clarke's portfw
@@ -73,16 +73,12 @@
 	__u32 fwmark;			/* key: firewall mark */
 	struct list_head hosts;		/* list of forward-to hosts */
 	atomic_t nhosts;		/* number of "" */
-#ifdef __SMP__
 	rwlock_t lock;
-#endif
 };
 
 
 static struct semaphore mfw_sema = MUTEX;
-#ifdef __SMP__
 static rwlock_t mfw_lock = RW_LOCK_UNLOCKED;
-#endif
 
 static struct ip_masq_mfw *ip_masq_mfw_table[IP_MASQ_MFW_HSIZE];
 
@@ -143,9 +139,7 @@
 	MOD_INC_USE_COUNT;
 	memset(mfw, 0, sizeof(*mfw));
 	mfw->fwmark = fwmark;
-#ifdef __SMP__
-	mfw->lock = (rwlock_t) RW_LOCK_UNLOCKED;
-#endif
+	mfw->lock = RW_LOCK_UNLOCKED;
 
 	INIT_LIST_HEAD(&mfw->hosts);
 out:
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ip_masq_mod.c linux.pre11.3/net/ipv4/ip_masq_mod.c
--- linux.vanilla/net/ipv4/ip_masq_mod.c	Sun Nov  8 15:07:13 1998
+++ linux.pre11.3/net/ipv4/ip_masq_mod.c	Mon Jul 19 23:27:13 1999
@@ -4,7 +4,7 @@
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
- * 	$Id: ip_masq_mod.c,v 1.5 1998/08/29 23:51:09 davem Exp $
+ * 	$Id: ip_masq_mod.c,v 1.5.2.1 1999/07/02 10:10:03 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -33,9 +33,7 @@
 EXPORT_SYMBOL(ip_masq_mod_lkp_link);
 EXPORT_SYMBOL(ip_masq_mod_lkp_unlink);
 
-#ifdef __SMP__
 static spinlock_t masq_mod_lock = SPIN_LOCK_UNLOCKED;
-#endif
 
 /*
  *	Base pointer for registered modules
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ip_masq_portfw.c linux.pre11.3/net/ipv4/ip_masq_portfw.c
--- linux.vanilla/net/ipv4/ip_masq_portfw.c	Wed Jan  6 23:02:32 1999
+++ linux.pre11.3/net/ipv4/ip_masq_portfw.c	Mon Jul 19 23:27:13 1999
@@ -2,7 +2,7 @@
  *		IP_MASQ_PORTFW masquerading module
  *
  *
- *	$Id: ip_masq_portfw.c,v 1.3 1998/12/08 05:42:12 davem Exp $
+ *	$Id: ip_masq_portfw.c,v 1.3.2.1 1999/07/02 10:10:02 davem Exp $
  *
  * Author:	Steven Clarke <steven.clarke@monmouth.demon.co.uk>
  *
@@ -51,9 +51,7 @@
 /*
  *	Lock
  */
-#ifdef __SMP__
-static spinlock_t portfw_lock = SPIN_LOCK_UNLOCKED;
-#endif
+static rwlock_t portfw_lock = RW_LOCK_UNLOCKED;
 
 static struct list_head portfw_list[2];
 static __inline__ int portfw_idx(int protocol)
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ip_masq_user.c linux.pre11.3/net/ipv4/ip_masq_user.c
--- linux.vanilla/net/ipv4/ip_masq_user.c	Sun Nov  8 15:07:15 1998
+++ linux.pre11.3/net/ipv4/ip_masq_user.c	Mon Jul 19 23:27:14 1999
@@ -347,8 +347,10 @@
 	struct ip_masq *ms;
 	char temp[129];
         int idx = 0;
+	int col;
 	int len=0;
 	int magic_control;
+	struct list_head *l,*e;
 
 	MOD_INC_USE_COUNT;
 
@@ -357,7 +359,7 @@
 	if (offset < 128)
 	{
 		sprintf(temp,
-			"Prot SrcIP    SPrt DstIP    DPrt MAddr    MPrt State        Flgs Ref Ctl Expires (free=%d,%d,%d)",
+			"Prot SrcIP    SPrt DstIP    DPrt MAddr    MPrt State        Flgs Ref Ctl Expires HRow HCol (free=%d,%d,%d)",
 			atomic_read(ip_masq_free_ports), 
 			atomic_read(ip_masq_free_ports+1), 
 			atomic_read(ip_masq_free_ports+2));
@@ -371,9 +373,12 @@
 	 *	Lock is actually only need in next loop 
 	 *	we are called from uspace: must stop bh.
 	 */
+	col=0;
 	read_lock_bh(&__ip_masq_lock);
-        for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
-	{
+	l = &ip_masq_m_table[idx];
+	for (e=l->next; e!=l; e=e->next) {
+		col++;
+		ms = list_entry(e, struct ip_masq, m_list);
 		if (ms->protocol != proto) {
 			continue;
 		}
@@ -392,7 +397,7 @@
 
 		magic_control = atomic_read(&ms->n_control);
 		if (!magic_control && ms->control) magic_control = -1;
-		sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3X %4d %3d %7lu",
+		sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3X %4d %3d %7lu %4d %4d",
 			masq_proto_name(ms->protocol),
 			ntohl(ms->saddr), ntohs(ms->sport),
 			ntohl(ms->daddr), ntohs(ms->dport),
@@ -401,7 +406,8 @@
 			ms->flags,
 			atomic_read(&ms->refcnt),
 			magic_control,
-			(ms->timer.expires-jiffies)/HZ);
+			(ms->timer.expires-jiffies)/HZ,
+			idx, col);
 		len += sprintf(buffer+len, "%-127s\n", temp);
 
 		if(len >= length) {
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ipconfig.c linux.pre11.3/net/ipv4/ipconfig.c
--- linux.vanilla/net/ipv4/ipconfig.c	Mon Mar 29 10:25:57 1999
+++ linux.pre11.3/net/ipv4/ipconfig.c	Mon Jul 19 23:27:13 1999
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.20 1999/03/28 10:18:28 davem Exp $
+ *  $Id: ipconfig.c,v 1.20.2.1 1999/06/28 11:33:27 davem Exp $
  *
  *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
  *  information to configure own IP address and routes.
@@ -662,7 +662,7 @@
 	    b->vendor_area[2] == 83 &&
 	    b->vendor_area[3] == 99) {
 		u8 *ext = &b->vendor_area[4];
-		u8 *end = (u8 *) b + len;
+                u8 *end = (u8 *) b + ntohs(b->iph.tot_len);
 		while (ext < end && *ext != 0xff) {
 			if (*ext == 0)		/* Padding */
 				ext++;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/ipmr.c linux.pre11.3/net/ipv4/ipmr.c
--- linux.vanilla/net/ipv4/ipmr.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/ipmr.c	Mon Jul 19 23:27:12 1999
@@ -9,7 +9,7 @@
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *
- *	Version: $Id: ipmr.c,v 1.40.2.1 1999/06/09 01:56:17 davem Exp $
+ *	Version: $Id: ipmr.c,v 1.40.2.2 1999/06/20 21:27:44 davem Exp $
  *
  *	Fixes:
  *	Michael Chastain	:	Incorrect size of copying.
@@ -23,6 +23,8 @@
  *	Brad Parker		:	Better behaviour on mrouted upcall
  *					overflow.
  *      Carlos Picoto           :       PIMv1 Support
+ *	Pavlin Ivanov Radoslavov:	PIMv2 Registers must checksum only PIM header
+ *					Relax this requrement to work with older peers.
  *
  */
 
@@ -431,7 +433,7 @@
 				skb_trim(skb, nlh->nlmsg_len);
 				((struct nlmsgerr*)NLMSG_DATA(nlh))->error = -EMSGSIZE;
 			}
-			err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+			err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT);
 		} else
 #endif
 			ip_mr_forward(skb, cache, 0);
@@ -1343,7 +1345,8 @@
 	    pim->type != ((PIM_VERSION<<4)|(PIM_REGISTER)) ||
 	    (pim->flags&PIM_NULL_REGISTER) ||
 	    reg_dev == NULL ||
-	    ip_compute_csum((void *)pim, len)) {
+	    (ip_compute_csum((void *)pim, sizeof(*pim)) &&
+	     ip_compute_csum((void *)pim, len))) {
 		kfree_skb(skb);
                 return -EINVAL;
         }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/raw.c linux.pre11.3/net/ipv4/raw.c
--- linux.vanilla/net/ipv4/raw.c	Thu Nov 19 18:38:51 1998
+++ linux.pre11.3/net/ipv4/raw.c	Mon Jul 19 23:27:12 1999
@@ -5,7 +5,7 @@
  *
  *		RAW - implementation of IP "raw" sockets.
  *
- * Version:	$Id: raw.c,v 1.39 1998/11/08 11:17:04 davem Exp $
+ * Version:	$Id: raw.c,v 1.39.2.1 1999/06/20 20:14:50 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -70,57 +70,25 @@
 
 static void raw_v4_hash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
+	struct sock **skp = &raw_v4_htable[sk->num & (RAWV4_HTABLE_SIZE - 1)];
 
-	num &= (RAWV4_HTABLE_SIZE - 1);
-	skp = &raw_v4_htable[num];
 	SOCKHASH_LOCK();
-	sk->next = *skp;
+	if ((sk->next = *skp) != NULL)
+		(*skp)->pprev = &sk->next;
 	*skp = sk;
-	sk->hashent = num;
+	sk->pprev = skp;
 	SOCKHASH_UNLOCK();
 }
 
 static void raw_v4_unhash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
-
-	num &= (RAWV4_HTABLE_SIZE - 1);
-	skp = &raw_v4_htable[num];
-
-	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
-	}
-	SOCKHASH_UNLOCK();
-}
-
-static void raw_v4_rehash(struct sock *sk)
-{
-	struct sock **skp;
-	int num = sk->num;
-	int oldnum = sk->hashent;
-
-	num &= (RAWV4_HTABLE_SIZE - 1);
-	skp = &raw_v4_htable[oldnum];
-
 	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
+	if (sk->pprev) {
+		if (sk->next)
+			sk->next->pprev = sk->pprev;
+		*sk->pprev = sk->next;
+		sk->pprev = NULL;
 	}
-	sk->next = raw_v4_htable[num];
-	raw_v4_htable[num] = sk;
-	sk->hashent = num;
 	SOCKHASH_UNLOCK();
 }
 
@@ -596,9 +564,7 @@
 	raw_rcv_skb,			/* backlog_rcv */
 	raw_v4_hash,			/* hash */
 	raw_v4_unhash,			/* unhash */
-	raw_v4_rehash,			/* rehash */
-	NULL,				/* good_socknum */
-	NULL,				/* verify_bind */
+	NULL,				/* get_port */
 	128,				/* max_header */
 	0,				/* retransmits */
 	"RAW",				/* name */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/route.c linux.pre11.3/net/ipv4/route.c
--- linux.vanilla/net/ipv4/route.c	Thu May 27 22:12:03 1999
+++ linux.pre11.3/net/ipv4/route.c	Mon Jul 19 23:27:12 1999
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.67 1999/05/08 20:00:20 davem Exp $
+ * Version:	$Id: route.c,v 1.67.2.1 1999/06/28 10:39:11 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -599,6 +599,22 @@
 	return 0;
 }
 
+static void rt_del(unsigned hash, struct rtable *rt)
+{
+	struct rtable **rthp;
+
+	start_bh_atomic();
+	ip_rt_put(rt);
+	for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) {
+		if (*rthp == rt) {
+			*rthp = rt->u.rt_next;
+			rt_free(rt);
+			break;
+		}
+	}
+	end_bh_atomic();
+}
+
 void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
 		    u32 saddr, u8 tos, struct device *dev)
 {
@@ -669,6 +685,7 @@
 				rt->u.dst.lastuse = jiffies;
 				rt->u.dst.neighbour = NULL;
 				rt->u.dst.hh = NULL;
+				rt->u.dst.obsolete = 0;
 
 				rt->rt_flags |= RTCF_REDIRECTED;
 
@@ -687,10 +704,10 @@
 					break;
 				}
 
-				*rthp = rth->u.rt_next;
+				rt_del(hash, rth);
+
 				if (!rt_intern_hash(hash, rt, &rt))
 					ip_rt_put(rt);
-				rt_drop(rth);
 				break;
 			}
 		}
@@ -718,20 +735,10 @@
 		}
 		if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
 			unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
-			struct rtable **rthp;
 #if RT_CACHE_DEBUG >= 1
 			printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos);
 #endif
-			start_bh_atomic();
-			ip_rt_put(rt);
-			for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) {
-				if (*rthp == rt) {
-					*rthp = rt->u.rt_next;
-					rt_free(rt);
-					break;
-				}
-			}
-			end_bh_atomic();
+			rt_del(hash, rt);
 			return NULL;
 		}
 	}
@@ -980,6 +987,8 @@
 			rt->u.dst.pmtu = rt->u.dst.dev->mtu;
 			if (rt->u.dst.pmtu > IP_MAX_MTU)
 				rt->u.dst.pmtu = IP_MAX_MTU;
+			if (rt->u.dst.pmtu < 68)
+				rt->u.dst.pmtu = 68;
 			if (rt->u.dst.mxlock&(1<<RTAX_MTU) &&
 			    rt->rt_gateway != rt->rt_dst &&
 			    rt->u.dst.pmtu > 576)
@@ -994,6 +1003,8 @@
 		rt->u.dst.pmtu	= rt->u.dst.dev->mtu;
 		if (rt->u.dst.pmtu > IP_MAX_MTU)
 			rt->u.dst.pmtu = IP_MAX_MTU;
+		if (rt->u.dst.pmtu < 68)
+			rt->u.dst.pmtu = 68;
 		rt->u.dst.window= 0;
 		rt->u.dst.rtt	= TCP_TIMEOUT_INIT;
 	}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/tcp.c linux.pre11.3/net/ipv4/tcp.c
--- linux.vanilla/net/ipv4/tcp.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/tcp.c	Tue Jul 20 00:22:37 1999
@@ -1332,12 +1332,12 @@
 		break;
 	}
 
-	if(copied > 0 && msg->msg_name)
+	if(copied >= 0 && msg->msg_name) {
 		tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
 					       msg->msg_name);       
-
 	if(addr_len)
 		*addr_len = tp->af_specific->sockaddr_len;
+	}
 
 	remove_wait_queue(sk->sleep, &wait);
 	current->state = TASK_RUNNING;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/tcp_input.c linux.pre11.3/net/ipv4/tcp_input.c
--- linux.vanilla/net/ipv4/tcp_input.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/tcp_input.c	Mon Jul 19 23:27:12 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.164.2.3 1999/06/02 04:15:06 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.5 1999/06/30 09:27:05 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -916,13 +916,20 @@
 
 void tcp_timewait_kill(struct tcp_tw_bucket *tw)
 {
-	/* Unlink from various places. */
+	struct tcp_bind_bucket *tb = tw->tb;
+
+	/* Disassociate with bind bucket. */
 	if(tw->bind_next)
 		tw->bind_next->bind_pprev = tw->bind_pprev;
 	*(tw->bind_pprev) = tw->bind_next;
-	if(tw->tb->owners == NULL)
-		tcp_inc_slow_timer(TCP_SLT_BUCKETGC);
+	if (tb->owners == NULL) {
+		if (tb->next)
+			tb->next->pprev = tb->pprev;
+		*(tb->pprev) = tb->next;
+		kmem_cache_free(tcp_bucket_cachep, tb);
+	}
 
+	/* Unlink from established hashes. */
 	if(tw->next)
 		tw->next->pprev = tw->pprev;
 	*tw->pprev = tw->next;
@@ -1023,6 +1030,7 @@
 		sk->bind_next->bind_pprev = &tw->bind_next;
 	tw->bind_pprev = sk->bind_pprev;
 	*sk->bind_pprev = (struct sock *)tw;
+	sk->prev = NULL;
 
 	/* Step 3: Same for the protocol sklist. */
 	(tw->sklist_next = sk->sklist_next)->sklist_prev = (struct sock *)tw;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/tcp_ipv4.c linux.pre11.3/net/ipv4/tcp_ipv4.c
--- linux.vanilla/net/ipv4/tcp_ipv4.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/tcp_ipv4.c	Mon Jul 19 23:27:12 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.175.2.2 1999/06/02 04:06:15 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.175.2.6 1999/07/02 10:09:59 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -130,27 +130,9 @@
 	return tcp_hashfn(laddr, lport, faddr, fport);
 }
 
-/* Invariant, sk->num is non-zero. */
-void tcp_bucket_unlock(struct sock *sk)
-{
-	struct tcp_bind_bucket *tb;
-	unsigned short snum = sk->num;
-
-	SOCKHASH_LOCK();
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)]; tb; tb = tb->next) {
-		if(tb->port == snum) {
-			if(tb->owners == NULL &&
-			   (tb->flags & TCPB_FLAG_LOCKED)) {
-				tb->flags &= ~(TCPB_FLAG_LOCKED |
-					       TCPB_FLAG_FASTREUSE);
-				tcp_inc_slow_timer(TCP_SLT_BUCKETGC);
-			}
-			break;
-		}
-	}
-	SOCKHASH_UNLOCK();
-}
-
+/* Allocate and initialize a new TCP local port bind bucket.
+ * Always runs inside the socket hashing lock.
+ */
 struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
 {
 	struct tcp_bind_bucket *tb;
@@ -160,7 +142,7 @@
 		struct tcp_bind_bucket **head =
 			&tcp_bound_hash[tcp_bhashfn(snum)];
 		tb->port = snum;
-		tb->flags = TCPB_FLAG_LOCKED;
+		tb->fastreuse = 0;
 		tb->owners = NULL;
 		if((tb->next = *head) != NULL)
 			tb->next->pprev = &tb->next;
@@ -172,139 +154,182 @@
 
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 /* Ensure that the bound bucket for the port exists.
- * Return 0 on success.
+ * Return 0 and bump bucket reference count on success.
+ *
+ * Must run in a BH atomic section.
  */
-static __inline__ int tcp_bucket_check(unsigned short snum)
+static __inline__ int __tcp_bucket_check(unsigned short snum)
 {
-	struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(snum)];
+	struct tcp_bind_bucket *tb;
+
+	tb = tcp_bound_hash[tcp_bhashfn(snum)];
 	for( ; (tb && (tb->port != snum)); tb = tb->next)
 		;
-	if(tb == NULL && tcp_bucket_create(snum) == NULL)
-		return 1;
-	else
-		return 0;
+	if (tb == NULL) {
+		if ((tb = tcp_bucket_create(snum)) == NULL)
+			return 1;
+	}
+
+	return 0;
 }
 #endif
 
-static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum)
+static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+	struct tcp_bind_bucket *tb = (struct tcp_bind_bucket *)sk->prev;
+
+	if ((child->bind_next = tb->owners) != NULL)
+		tb->owners->bind_pprev = &child->bind_next;
+	tb->owners = child;
+	child->bind_pprev = &tb->owners;
+	child->prev = (struct sock *) tb;
+}
+
+__inline__ void tcp_inherit_port(struct sock *sk, struct sock *child)
+{
+	SOCKHASH_LOCK();
+	__tcp_inherit_port(sk, child);
+	SOCKHASH_UNLOCK();
+}
+
+/* Obtain a reference to a local port for the given sock,
+ * if snum is zero it means select any available local port.
+ */
+static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
 {
 	struct tcp_bind_bucket *tb;
-	int result = 0;
 
 	SOCKHASH_LOCK();
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)];
-	    (tb && (tb->port != snum));
-	    tb = tb->next)
-		;
-	if(tb && tb->owners) {
-		/* Fast path for reuse ports, see include/net/tcp.h for a very
-		 * detailed description of why this works, and why it is worth
-		 * the effort at all. -DaveM
-		 */
-		if((tb->flags & TCPB_FLAG_FASTREUSE)	&&
-		   (sk->reuse != 0)) {
-			goto go_like_smoke;
+	if (snum == 0) {
+		int rover = tcp_port_rover;
+		int low = sysctl_local_port_range[0];
+		int high = sysctl_local_port_range[1];
+		int remaining = (high - low) + 1;
+
+		do {	rover++;
+			if ((rover < low) || (rover > high))
+				rover = low;
+			tb = tcp_bound_hash[tcp_bhashfn(rover)];
+			for ( ; tb; tb = tb->next)
+				if (tb->port == rover)
+					goto next;
+			break;
+		next:
+		} while (--remaining > 0);
+		tcp_port_rover = rover;
+
+		/* Exhausted local port range during search? */
+		if (remaining <= 0)
+			goto fail;
+
+		/* OK, here is the one we will use. */
+		snum = rover;
+		tb = NULL;
+	} else {
+		for (tb = tcp_bound_hash[tcp_bhashfn(snum)];
+		     tb != NULL;
+		     tb = tb->next)
+			if (tb->port == snum)
+				break;
+	}
+	if (tb != NULL && tb->owners != NULL) {
+		if (tb->fastreuse != 0 && sk->reuse != 0) {
+			goto success;
 		} else {
-			struct sock *sk2;
+			struct sock *sk2 = tb->owners;
 			int sk_reuse = sk->reuse;
 
-			/* We must walk the whole port owner list in this case. -DaveM */
-			for(sk2 = tb->owners; sk2; sk2 = sk2->bind_next) {
+			for( ; sk2 != NULL; sk2 = sk2->bind_next) {
 				if (sk->bound_dev_if == sk2->bound_dev_if) {
-					if(!sk_reuse || !sk2->reuse || sk2->state == TCP_LISTEN) {
-						if(!sk2->rcv_saddr		||
-						   !sk->rcv_saddr		||
-						   (sk2->rcv_saddr == sk->rcv_saddr))
+					if (!sk_reuse	||
+					    !sk2->reuse	||
+					    sk2->state == TCP_LISTEN) {
+						if (!sk2->rcv_saddr	||
+						    !sk->rcv_saddr	||
+						    (sk2->rcv_saddr == sk->rcv_saddr))
 							break;
 					}
 				}
 			}
-			if(sk2 != NULL)
-				result = 1;
+			/* If we found a conflict, fail. */
+			if (sk2 != NULL)
+				goto fail;
 		}
 	}
-	if(result == 0) {
-		if(tb == NULL) {
-			if((tb = tcp_bucket_create(snum)) == NULL)
-				result = 1;
-			else if (sk->reuse && sk->state != TCP_LISTEN)
-				tb->flags |= TCPB_FLAG_FASTREUSE;
-		} else {
-			/* It could be pending garbage collection, this
-			 * kills the race and prevents it from disappearing
-			 * out from under us by the time we use it.  -DaveM
-			 */
-			if(tb->owners == NULL) {
-				if (!(tb->flags & TCPB_FLAG_LOCKED)) {
-					tb->flags = (TCPB_FLAG_LOCKED |
-						     ((sk->reuse &&
-						       sk->state != TCP_LISTEN) ?
-						      TCPB_FLAG_FASTREUSE : 0));
-					tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
-				} else if (!(tb->flags & TCPB_FLAG_GOODSOCKNUM)) {
-					/* Someone is in between the bind
-					 * and the actual connect or listen.
-					 * See if it was a legitimate reuse
-					 * and we are as well, else punt.
-					 */
-					if (sk->reuse == 0 ||
-					    !(tb->flags & TCPB_FLAG_FASTREUSE))
-						result = 1;
-				} else
-					tb->flags &= ~TCPB_FLAG_GOODSOCKNUM;
-			}
-		}
-	}
-go_like_smoke:
+	if (tb == NULL &&
+	    (tb = tcp_bucket_create(snum)) == NULL)
+			goto fail;
+	if (tb->owners == NULL) {
+		if (sk->reuse && sk->state != TCP_LISTEN)
+			tb->fastreuse = 1;
+		else
+			tb->fastreuse = 0;
+	} else if (tb->fastreuse &&
+		   ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+		tb->fastreuse = 0;
+success:
+	sk->num = snum;
+	if ((sk->bind_next = tb->owners) != NULL)
+		tb->owners->bind_pprev = &sk->bind_next;
+	tb->owners = sk;
+	sk->bind_pprev = &tb->owners;
+	sk->prev = (struct sock *) tb;
+
 	SOCKHASH_UNLOCK();
-	return result;
+	return 0;
+
+fail:
+	SOCKHASH_UNLOCK();
+	return 1;
 }
 
-unsigned short tcp_good_socknum(void)
+/* Get rid of any references to a local port held by the
+ * given sock.
+ */
+__inline__ void __tcp_put_port(struct sock *sk)
 {
 	struct tcp_bind_bucket *tb;
-	int low = sysctl_local_port_range[0];
-	int high = sysctl_local_port_range[1];
-	int remaining = (high - low) + 1;
-	int rover;
 
+	tb = (struct tcp_bind_bucket *) sk->prev;
+	if (sk->bind_next)
+		sk->bind_next->bind_pprev = sk->bind_pprev;
+	*(sk->bind_pprev) = sk->bind_next;
+	sk->prev = NULL;
+	if (tb->owners == NULL) {
+		if (tb->next)
+			tb->next->pprev = tb->pprev;
+		*(tb->pprev) = tb->next;
+		kmem_cache_free(tcp_bucket_cachep, tb);
+	}
+}
+
+void tcp_put_port(struct sock *sk)
+{
 	SOCKHASH_LOCK();
-	rover = tcp_port_rover;
-	do {
-		rover += 1;
-		if((rover < low) || (rover > high))
-			rover = low;
-		tb = tcp_bound_hash[tcp_bhashfn(rover)];
-		for( ; tb; tb = tb->next) {
-			if(tb->port == rover)
-				goto next;
-		}
-		break;
-	next:
-	} while(--remaining > 0);
-	tcp_port_rover = rover;
-	tb = NULL;
-	if((remaining <= 0) || ((tb = tcp_bucket_create(rover)) == NULL))
-		rover = 0;
-	if (tb != NULL)
-		tb->flags |= TCPB_FLAG_GOODSOCKNUM;
+	__tcp_put_port(sk);
 	SOCKHASH_UNLOCK();
+}
+
+static __inline__ void __tcp_v4_hash(struct sock *sk)
+{
+	struct sock **skp;
+
+	if(sk->state == TCP_LISTEN)
+		skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+	else
+		skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
 
-	return rover;
+	if((sk->next = *skp) != NULL)
+		(*skp)->pprev = &sk->next;
+	*skp = sk;
+	sk->pprev = skp;
 }
 
 static void tcp_v4_hash(struct sock *sk)
 {
 	if (sk->state != TCP_CLOSE) {
-		struct sock **skp;
-
 		SOCKHASH_LOCK();
-		skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
-		if((sk->next = *skp) != NULL)
-			(*skp)->pprev = &sk->next;
-		*skp = sk;
-		sk->pprev = skp;
-		tcp_sk_bindify(sk);
+		__tcp_v4_hash(sk);
 		SOCKHASH_UNLOCK();
 	}
 }
@@ -318,38 +343,7 @@
 		*sk->pprev = sk->next;
 		sk->pprev = NULL;
 		tcp_reg_zap(sk);
-		tcp_sk_unbindify(sk);
-	}
-	SOCKHASH_UNLOCK();
-}
-
-static void tcp_v4_rehash(struct sock *sk)
-{
-	unsigned char state;
-
-	SOCKHASH_LOCK();
-	state = sk->state;
-	if(sk->pprev != NULL) {
-		if(sk->next)
-			sk->next->pprev = sk->pprev;
-		*sk->pprev = sk->next;
-		sk->pprev = NULL;
-		tcp_reg_zap(sk);
-	}
-	if(state != TCP_CLOSE) {
-		struct sock **skp;
-
-		if(state == TCP_LISTEN)
-			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
-		else
-			skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
-
-		if((sk->next = *skp) != NULL)
-			(*skp)->pprev = &sk->next;
-		*skp = sk;
-		sk->pprev = skp;
-		if(state == TCP_LISTEN)
-			tcp_sk_bindify(sk);
+		__tcp_put_port(sk);
 	}
 	SOCKHASH_UNLOCK();
 }
@@ -1468,7 +1462,7 @@
 	 * later will require to destroy just created newsk in the case of fail.
 	 * 1998/04/22 Andrey V. Savochkin <saw@msu.ru>
 	 */
-	if (tcp_bucket_check(ntohs(skb->h.th->dest)))
+	if (__tcp_bucket_check(ntohs(skb->h.th->dest)))
 		goto exit;
 #endif
 
@@ -1503,8 +1497,13 @@
 	if (newsk->sndbuf < (3 * newtp->pmtu_cookie))
 		newsk->sndbuf = min ((3 * newtp->pmtu_cookie), sysctl_wmem_max);
  
-	tcp_v4_hash(newsk);
-	add_to_prot_sklist(newsk);
+	/* We run in BH processing itself or within a BH atomic
+	 * sequence (backlog) so no locking is needed.
+	 */
+	__tcp_v4_hash(newsk);
+	__tcp_inherit_port(sk, newsk);
+	__add_to_prot_sklist(newsk);
+
 	sk->data_ready(sk, 0); /* Deliver SIGIO */ 
 
 	return newsk;
@@ -1727,6 +1726,25 @@
 	goto discard_it;
 }
 
+static void __tcp_v4_rehash(struct sock *sk)
+{
+	struct sock **skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+
+	SOCKHASH_LOCK();
+	if(sk->pprev) {
+		if(sk->next)
+			sk->next->pprev = sk->pprev;
+		*sk->pprev = sk->next;
+		sk->pprev = NULL;
+		tcp_reg_zap(sk);
+	}
+	if((sk->next = *skp) != NULL)
+		(*skp)->pprev = &sk->next;
+	*skp = sk;
+	sk->pprev = skp;
+	SOCKHASH_UNLOCK();
+}
+
 int tcp_v4_rebuild_header(struct sock *sk)
 {
 	struct rtable *rt = (struct rtable *)sk->dst_cache;
@@ -1800,7 +1818,12 @@
 
 		sk->saddr = new_saddr;
 		sk->rcv_saddr = new_saddr;
-		tcp_v4_rehash(sk);
+
+		/* XXX The only one ugly spot where we need to
+		 * XXX really change the sockets identity after
+		 * XXX it has entered the hashes. -DaveM
+		 */
+		__tcp_v4_rehash(sk);
 	} 
         
 	return 0;
@@ -1895,13 +1918,11 @@
   	while((skb = __skb_dequeue(&tp->out_of_order_queue)) != NULL)
 		kfree_skb(skb);
 
-	/* Clean up a locked TCP bind bucket, this only happens if a
+	/* Clean up a referenced TCP bind bucket, this only happens if a
 	 * port is allocated for a socket, but it never fully connects.
-	 * In which case we will find num to be non-zero and daddr to
-	 * be zero.
 	 */
-	if(sk->daddr == 0 && sk->num != 0)
-		tcp_bucket_unlock(sk);
+	if(sk->prev != NULL)
+		tcp_put_port(sk);
 
 	return 0;
 }
@@ -1928,9 +1949,7 @@
 	tcp_v4_do_rcv,			/* backlog_rcv */
 	tcp_v4_hash,			/* hash */
 	tcp_v4_unhash,			/* unhash */
-	tcp_v4_rehash,			/* rehash */
-	tcp_good_socknum,		/* good_socknum */
-	tcp_v4_verify_bind,		/* verify_bind */
+	tcp_v4_get_port,		/* get_port */
 	128,				/* max_header */
 	0,				/* retransmits */
 	"TCP",				/* name */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/tcp_timer.c linux.pre11.3/net/ipv4/tcp_timer.c
--- linux.vanilla/net/ipv4/tcp_timer.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv4/tcp_timer.c	Mon Jul 19 23:27:12 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.62.2.2 1999/06/02 04:06:21 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.62.2.3 1999/06/20 20:14:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -31,7 +31,6 @@
 static void tcp_sltimer_handler(unsigned long);
 static void tcp_syn_recv_timer(unsigned long);
 static void tcp_keepalive(unsigned long data);
-static void tcp_bucketgc(unsigned long);
 static void tcp_twkill(unsigned long);
 
 struct timer_list	tcp_slow_timer = {
@@ -44,8 +43,7 @@
 struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX] = {
 	{ATOMIC_INIT(0), TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK	*/
 	{ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive},  /* KEEPALIVE	*/
-	{ATOMIC_INIT(0), TCP_TWKILL_PERIOD, 0, tcp_twkill},        /* TWKILL	*/
-	{ATOMIC_INIT(0), TCP_BUCKETGC_PERIOD, 0, tcp_bucketgc}     /* BUCKETGC	*/
+	{ATOMIC_INIT(0), TCP_TWKILL_PERIOD, 0, tcp_twkill}         /* TWKILL	*/
 };
 
 const char timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
@@ -246,40 +244,6 @@
 		}
 	}
 	return res;
-}
-
-/* Garbage collect TCP bind buckets. */
-static void tcp_bucketgc(unsigned long data)
-{
-	int i, reaped = 0;;
-
-	for(i = 0; i < TCP_BHTABLE_SIZE; i++) {
-		struct tcp_bind_bucket *tb = tcp_bound_hash[i];
-
-		while(tb) {
-			struct tcp_bind_bucket *next = tb->next;
-
-			if((tb->owners == NULL) &&
-			   !(tb->flags & TCPB_FLAG_LOCKED)) {
-				reaped++;
-
-				/* Unlink bucket. */
-				if(tb->next)
-					tb->next->pprev = tb->pprev;
-				*tb->pprev = tb->next;
-
-				/* Finally, free it up. */
-				kmem_cache_free(tcp_bucket_cachep, tb);
-			}
-			tb = next;
-		}
-	}
-	if(reaped != 0) {
-		struct tcp_sl_timer *slt = (struct tcp_sl_timer *)data;
-
-		/* Eat timer references. */
-		atomic_sub(reaped, &slt->count);
-	}
 }
 
 /* Kill off TIME_WAIT sockets once their lifetime has expired. */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv4/udp.c linux.pre11.3/net/ipv4/udp.c
--- linux.vanilla/net/ipv4/udp.c	Thu May 27 22:12:04 1999
+++ linux.pre11.3/net/ipv4/udp.c	Tue Jul 20 00:22:46 1999
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.66 1999/05/08 20:00:25 davem Exp $
+ * Version:	$Id: udp.c,v 1.66.2.1 1999/06/20 20:14:48 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -123,108 +123,75 @@
 
 struct sock *udp_hash[UDP_HTABLE_SIZE];
 
-static int udp_v4_verify_bind(struct sock *sk, unsigned short snum)
-{
-	struct sock *sk2;
-	int retval = 0, sk_reuse = sk->reuse;
+/* Shared by v4/v6 udp. */
+int udp_port_rover = 0;
 
+static int udp_v4_get_port(struct sock *sk, unsigned short snum)
+{
 	SOCKHASH_LOCK();
-	for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
-		if((sk2->num == snum) && (sk2 != sk)) {
-			unsigned char state = sk2->state;
-			int sk2_reuse = sk2->reuse;
-
-			/* Two sockets can be bound to the same port if they're
-			 * bound to different interfaces.
-			 */
+	if (snum == 0) {
+		int best_size_so_far, best, result, i;
 
-			if(sk2->bound_dev_if != sk->bound_dev_if)
-				continue;
-
-			if(!sk2->rcv_saddr || !sk->rcv_saddr) {
-				if((!sk2_reuse)			||
-				   (!sk_reuse)			||
-				   (state == TCP_LISTEN)) {
-					retval = 1;
-					break;
-				}
-			} else if(sk2->rcv_saddr == sk->rcv_saddr) {
-				if((!sk_reuse)			||
-				   (!sk2_reuse)			||
-				   (state == TCP_LISTEN)) {
-					retval = 1;
-					break;
-				}
+		if (udp_port_rover > sysctl_local_port_range[1] ||
+		    udp_port_rover < sysctl_local_port_range[0])
+			udp_port_rover = sysctl_local_port_range[0];
+		best_size_so_far = 32767;
+		best = result = udp_port_rover;
+		for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
+			struct sock *sk;
+			int size;
+
+			sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+			if (!sk) {
+				if (result > sysctl_local_port_range[1])
+					result = sysctl_local_port_range[0] +
+						((result - sysctl_local_port_range[0]) &
+						 (UDP_HTABLE_SIZE - 1));
+				goto gotit;
 			}
+			size = 0;
+			do {
+				if (++size >= best_size_so_far)
+					goto next;
+			} while ((sk = sk->next) != NULL);
+			best_size_so_far = size;
+			best = result;
+		next:
 		}
-	}
-	SOCKHASH_UNLOCK();
-	return retval;
-}
-
-static inline int udp_lport_inuse(u16 num)
-{
-	struct sock *sk = udp_hash[num & (UDP_HTABLE_SIZE - 1)];
+		result = best;
+		for(;; result += UDP_HTABLE_SIZE) {
+			if (result > sysctl_local_port_range[1])
+				result = sysctl_local_port_range[0]
+					+ ((result - sysctl_local_port_range[0]) &
+					   (UDP_HTABLE_SIZE - 1));
+			if (!udp_lport_inuse(result))
+				break;
+		}
+gotit:
+		udp_port_rover = snum = result;
+	} else {
+		struct sock *sk2;
 
-	for(; sk != NULL; sk = sk->next) {
-		if(sk->num == num)
-			return 1;
+		for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+		     sk2 != NULL;
+		     sk2 = sk2->next) {
+			if (sk2->num == snum &&
+			    sk2 != sk &&
+			    sk2->bound_dev_if == sk->bound_dev_if &&
+			    (!sk2->rcv_saddr ||
+			     !sk->rcv_saddr ||
+			     sk2->rcv_saddr == sk->rcv_saddr) &&
+			    (!sk2->reuse || !sk->reuse))
+				goto fail;
+		}
 	}
+	sk->num = snum;
+	SOCKHASH_UNLOCK();
 	return 0;
-}
-
-/* Shared by v4/v6 tcp. */
-unsigned short udp_good_socknum(void)
-{
-	int result;
-	static int start = 0;
-	int i, best, best_size_so_far;
-
-	SOCKHASH_LOCK();
-        if (start > sysctl_local_port_range[1] || start < sysctl_local_port_range[0])
-                start = sysctl_local_port_range[0];
 
-	best_size_so_far = 32767;	/* "big" num */
-        best = result = start;
-
-        for(i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
-		struct sock *sk;
-		int size;
-
-		sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
-
-                if(!sk) {
-                        if (result > sysctl_local_port_range[1])
-                                result = sysctl_local_port_range[0]
-                                        + ((result - sysctl_local_port_range[0]) & (UDP_HTABLE_SIZE - 1));
-			goto out;
-                }
-
-		/* Is this one better than our best so far? */
-		size = 0;
-		do {
-			if(++size >= best_size_so_far)
-				goto next;
-		} while((sk = sk->next) != NULL);
-		best_size_so_far = size;
-		best = result;
-        next:
-	}
-
-	result = best;
-
-        for(;; result += UDP_HTABLE_SIZE) {
-                /* Get into range (but preserve hash bin)... */
-                if (result > sysctl_local_port_range[1])
-                        result = sysctl_local_port_range[0]
-                                + ((result - sysctl_local_port_range[0]) & (UDP_HTABLE_SIZE - 1));
-                if (!udp_lport_inuse(result))
-                        break;
-        }
-out:
-	start = result;
+fail:
 	SOCKHASH_UNLOCK();
-	return result;
+	return 1;
 }
 
 /* Last hit UDP socket cache, this is ipv4 specific so make it static. */
@@ -234,62 +201,27 @@
 
 static void udp_v4_hash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
-
-	num &= (UDP_HTABLE_SIZE - 1);
-	skp = &udp_hash[num];
+	struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)];
 
 	SOCKHASH_LOCK();
-	sk->next = *skp;
+	if ((sk->next = *skp) != NULL)
+		(*skp)->pprev = &sk->next;
 	*skp = sk;
-	sk->hashent = num;
+	sk->pprev = skp;
 	SOCKHASH_UNLOCK();
 }
 
 static void udp_v4_unhash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
-
-	num &= (UDP_HTABLE_SIZE - 1);
-	skp = &udp_hash[num];
-
-	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
-	}
-	if(uh_cache_sk == sk)
-		uh_cache_sk = NULL;
-	SOCKHASH_UNLOCK();
-}
-
-static void udp_v4_rehash(struct sock *sk)
-{
-	struct sock **skp;
-	int num = sk->num;
-	int oldnum = sk->hashent;
-
-	num &= (UDP_HTABLE_SIZE - 1);
-	skp = &udp_hash[oldnum];
-
 	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
+	if (sk->pprev) {
+		if (sk->next)
+			sk->next->pprev = sk->pprev;
+		*sk->pprev = sk->next;
+		sk->pprev = NULL;
+		if(uh_cache_sk == sk)
+			uh_cache_sk = NULL;
 	}
-	sk->next = udp_hash[num];
-	udp_hash[num] = sk;
-	sk->hashent = num;
-	if(uh_cache_sk == sk)
-		uh_cache_sk = NULL;
 	SOCKHASH_UNLOCK();
 }
 
@@ -810,7 +742,6 @@
 		{
 			unsigned long amount;
 
-			if (sk->state == TCP_LISTEN) return(-EINVAL);
 			amount = sock_wspace(sk);
 			return put_user(amount, (int *)arg);
 		}
@@ -820,8 +751,6 @@
 			struct sk_buff *skb;
 			unsigned long amount;
 
-			if (sk->state == TCP_LISTEN)
-				return(-EINVAL);
 			amount = 0;
 			/* N.B. Is this interrupt safe??
 			   -> Yes. Interrupts do not remove skbs. --ANK (980725)
@@ -860,12 +789,6 @@
   	struct sk_buff *skb;
   	int copied, err;
 
-	/*
-	 *	Check any passed addresses
-	 */
-  	if (addr_len) 
-  		*addr_len=sizeof(*sin);
-
 	if (flags & MSG_ERRQUEUE)
 		return ip_recv_error(sk, msg, len);
 
@@ -916,6 +839,12 @@
 	/* Copy the address. */
 	if (sin)
 	{
+		/*
+		 *	Check any passed addresses
+		 */
+		if (addr_len) 
+			*addr_len=sizeof(*sin);
+
 		sin->sin_family = AF_INET;
 		sin->sin_port = skb->h.uh->source;
 		sin->sin_addr.s_addr = skb->nh.iph->saddr;
@@ -1244,9 +1173,7 @@
 	udp_queue_rcv_skb,		/* backlog_rcv */
 	udp_v4_hash,			/* hash */
 	udp_v4_unhash,			/* unhash */
-	udp_v4_rehash,			/* rehash */
-	udp_good_socknum,		/* good_socknum */
-	udp_v4_verify_bind,		/* verify_bind */
+	udp_v4_get_port,		/* good_socknum */
 	128,				/* max_header */
 	0,				/* retransmits */
  	"UDP",				/* name */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv6/addrconf.c linux.pre11.3/net/ipv6/addrconf.c
--- linux.vanilla/net/ipv6/addrconf.c	Mon Mar 29 10:25:57 1999
+++ linux.pre11.3/net/ipv6/addrconf.c	Mon Jul 19 23:27:15 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: addrconf.c,v 1.48 1999/03/25 10:04:43 davem Exp $
+ *	$Id: addrconf.c,v 1.48.2.1 1999/06/28 10:39:39 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -889,7 +889,6 @@
 	struct inet6_ifaddr *ifp;
 	struct inet6_dev *idev;
 	struct device *dev;
-	int scope;
 	
 	if ((dev = dev_get_by_index(ifindex)) == NULL)
 		return -ENODEV;
@@ -897,11 +896,9 @@
 	if ((idev = ipv6_get_idev(dev)) == NULL)
 		return -ENXIO;
 
-	scope = ipv6_addr_scope(pfx);
-
 	start_bh_atomic();
 	for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) {
-		if (ifp->scope == scope && ifp->prefix_len == plen &&
+		if (ifp->prefix_len == plen &&
 		    (!memcmp(pfx, &ifp->addr, sizeof(struct in6_addr)))) {
 			ipv6_del_addr(ifp);
 			end_bh_atomic();
@@ -1529,6 +1526,8 @@
 			return -EINVAL;
 		pfx = RTA_DATA(rta[IFA_LOCAL-1]);
 	}
+	if (pfx == NULL)
+		return -EINVAL;
 
 	return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
@@ -1551,6 +1550,8 @@
 			return -EINVAL;
 		pfx = RTA_DATA(rta[IFA_LOCAL-1]);
 	}
+	if (pfx == NULL)
+		return -EINVAL;
 
 	return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv6/af_inet6.c linux.pre11.3/net/ipv6/af_inet6.c
--- linux.vanilla/net/ipv6/af_inet6.c	Wed Apr 28 19:14:38 1999
+++ linux.pre11.3/net/ipv6/af_inet6.c	Mon Jul 19 23:27:15 1999
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.43 1999/04/22 10:07:39 davem Exp $
+ *	$Id: af_inet6.c,v 1.43.2.1 1999/06/20 20:15:06 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -236,20 +236,17 @@
 		       sizeof(struct in6_addr));
 
 	snum = ntohs(addr->sin6_port);
-	if (snum == 0) 
-		snum = sk->prot->good_socknum();
-	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
 		return(-EACCES);
 
 	/* Make sure we are allowed to bind here. */
-	if(sk->prot->verify_bind(sk, snum))
+	if(sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
-	sk->num = snum;
 	sk->sport = ntohs(sk->num);
 	sk->dport = 0;
 	sk->daddr = 0;
-	sk->prot->rehash(sk);
+	sk->prot->hash(sk);
 	add_to_prot_sklist(sk);
 
 	return(0);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv6/ip6_fw.c linux.pre11.3/net/ipv6/ip6_fw.c
--- linux.vanilla/net/ipv6/ip6_fw.c	Sun Nov  8 15:07:17 1998
+++ linux.pre11.3/net/ipv6/ip6_fw.c	Tue Jul 20 00:23:01 1999
@@ -91,12 +91,11 @@
 	struct ip6_fw_rule *rl;
 
 	rl = kmalloc(sizeof(struct ip6_fw_rule), GFP_ATOMIC);
-
-	memset(rl, 0, sizeof(struct ip6_fw_rule));
-
 	if (rl)
+	{
+		memset(rl, 0, sizeof(struct ip6_fw_rule));
 		rl->flowr.ops = &ip6_fw_ops;
-
+	}
 	return rl;
 }
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv6/raw.c linux.pre11.3/net/ipv6/raw.c
--- linux.vanilla/net/ipv6/raw.c	Wed Apr 28 19:14:38 1999
+++ linux.pre11.3/net/ipv6/raw.c	Mon Jul 19 23:27:15 1999
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/raw.c
  *
- *	$Id: raw.c,v 1.24 1999/04/22 10:07:45 davem Exp $
+ *	$Id: raw.c,v 1.24.2.1 1999/06/20 20:14:58 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -45,57 +45,25 @@
 
 static void raw_v6_hash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
+	struct sock **skp = &raw_v6_htable[sk->num & (RAWV6_HTABLE_SIZE - 1)];
 
-	num &= (RAWV6_HTABLE_SIZE - 1);
-	skp = &raw_v6_htable[num];
 	SOCKHASH_LOCK();
-	sk->next = *skp;
+	if ((sk->next = *skp) != NULL)
+		(*skp)->pprev = &sk->next;
 	*skp = sk;
-	sk->hashent = num;
+	sk->pprev = skp;
 	SOCKHASH_UNLOCK();
 }
 
 static void raw_v6_unhash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
-
-	num &= (RAWV6_HTABLE_SIZE - 1);
-	skp = &raw_v6_htable[num];
-
-	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
-	}
-	SOCKHASH_UNLOCK();
-}
-
-static void raw_v6_rehash(struct sock *sk)
-{
-	struct sock **skp;
-	int num = sk->num;
-	int oldnum = sk->hashent;
-
-	num &= (RAWV6_HTABLE_SIZE - 1);
-	skp = &raw_v6_htable[oldnum];
-
 	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
+	if (sk->pprev) {
+		if (sk->next)
+			sk->next->pprev = sk->pprev;
+		*sk->pprev = sk->next;
+		sk->pprev = NULL;
 	}
-	sk->next = raw_v6_htable[num];
-	raw_v6_htable[num] = sk;
-	sk->hashent = num;
 	SOCKHASH_UNLOCK();
 }
 
@@ -667,9 +635,7 @@
 	rawv6_rcv_skb,			/* backlog_rcv */
 	raw_v6_hash,			/* hash */
 	raw_v6_unhash,			/* unhash */
-	raw_v6_rehash,			/* rehash */
-	NULL,				/* good_socknum */
-	NULL,				/* verify_bind */
+	NULL,				/* get_port */
 	128,				/* max_header */
 	0,				/* retransmits */
 	"RAW",				/* name */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv6/tcp_ipv6.c linux.pre11.3/net/ipv6/tcp_ipv6.c
--- linux.vanilla/net/ipv6/tcp_ipv6.c	Tue Jun 15 16:49:58 1999
+++ linux.pre11.3/net/ipv6/tcp_ipv6.c	Mon Jul 19 23:27:15 1999
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.104.2.2 1999/06/02 04:06:27 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.104.2.4 1999/06/30 09:27:12 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -84,101 +84,120 @@
  * But it doesn't matter, the recalculation is in the rarest path
  * this function ever takes.
  */
-static int tcp_v6_verify_bind(struct sock *sk, unsigned short snum)
+static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
 {
 	struct tcp_bind_bucket *tb;
-	int result = 0;
 
 	SOCKHASH_LOCK();
-	for(tb = tcp_bound_hash[tcp_bhashfn(snum)];
-	    (tb && (tb->port != snum));
-	    tb = tb->next)
-		;
-	if(tb && tb->owners) {
-		/* Fast path for reuse ports, see include/net/tcp.h for a very
-		 * detailed description of why this works, and why it is worth
-		 * the effort at all. -DaveM
-		 */
-		if((tb->flags & TCPB_FLAG_FASTREUSE)	&&
-		   (sk->reuse != 0)) {
-			goto go_like_smoke;
+	if (snum == 0) {
+		int rover = tcp_port_rover;
+		int low = sysctl_local_port_range[0];
+		int high = sysctl_local_port_range[1];
+		int remaining = (high - low) + 1;
+
+		do {	rover++;
+			if ((rover < low) || (rover > high))
+				rover = low;
+			tb = tcp_bound_hash[tcp_bhashfn(rover)];
+			for ( ; tb; tb = tb->next)
+				if (tb->port == rover)
+					goto next;
+			break;
+		next:
+		} while (--remaining > 0);
+		tcp_port_rover = rover;
+
+		/* Exhausted local port range during search? */
+		if (remaining <= 0)
+			goto fail;
+
+		/* OK, here is the one we will use. */
+		snum = rover;
+		tb = NULL;
+	} else {
+		for (tb = tcp_bound_hash[tcp_bhashfn(snum)];
+		     tb != NULL;
+		     tb = tb->next)
+			if (tb->port == snum)
+				break;
+	}
+	if (tb != NULL && tb->owners != NULL) {
+		if (tb->fastreuse != 0 && sk->reuse != 0) {
+			goto success;
 		} else {
-			struct sock *sk2;
+			struct sock *sk2 = tb->owners;
 			int sk_reuse = sk->reuse;
 			int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
 
-			/* We must walk the whole port owner list in this case. -DaveM */
-			for(sk2 = tb->owners; sk2; sk2 = sk2->bind_next) {
-				if(sk->bound_dev_if == sk2->bound_dev_if) {
-					if(!sk_reuse || !sk2->reuse || sk2->state == TCP_LISTEN) {
-						if(addr_type == IPV6_ADDR_ANY	||
-						   !sk2->rcv_saddr		||
-						   !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
-								  &sk2->net_pinfo.af_inet6.rcv_saddr))
+			for( ; sk2 != NULL; sk2 = sk2->bind_next) {
+				if (sk->bound_dev_if == sk2->bound_dev_if) {
+					if (!sk_reuse	||
+					    !sk2->reuse	||
+					    sk2->state == TCP_LISTEN) {
+						if (!sk2->rcv_saddr	||
+						    !addr_type == IPV6_ADDR_ANY ||
+						    !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
+								   &sk2->net_pinfo.af_inet6.rcv_saddr))
 							break;
 					}
 				}
 			}
-			if(sk2 != NULL)
-				result = 1;
+			/* If we found a conflict, fail. */
+			if (sk2 != NULL)
+				goto fail;
 		}
 	}
-	if(result == 0) {
-		if(tb == NULL) {
-			if((tb = tcp_bucket_create(snum)) == NULL)
-				result = 1;
-			else if (sk->reuse && sk->state != TCP_LISTEN)
-				tb->flags |= TCPB_FLAG_FASTREUSE;
-		} else {
-			/* It could be pending garbage collection, this
-			 * kills the race and prevents it from disappearing
-			 * out from under us by the time we use it.  -DaveM
-			 */
-			if(tb->owners == NULL) {
-				if (!(tb->flags & TCPB_FLAG_LOCKED)) {
-					tb->flags = (TCPB_FLAG_LOCKED |
-						     ((sk->reuse &&
-						       sk->state != TCP_LISTEN) ?
-						      TCPB_FLAG_FASTREUSE : 0));
-					tcp_dec_slow_timer(TCP_SLT_BUCKETGC);
-				} else if (!(tb->flags & TCPB_FLAG_GOODSOCKNUM)) {
-					/* Someone is in between the bind
-					 * and the actual connect or listen.
-					 * See if it was a legitimate reuse
-					 * and we are as well, else punt.
-					 */
-					if (sk->reuse == 0 ||
-					    !(tb->flags & TCPB_FLAG_FASTREUSE))
-						result = 1;
-				} else
-					tb->flags &= ~TCPB_FLAG_GOODSOCKNUM;
-			}
-		}
-	}
-go_like_smoke:
+	if (tb == NULL &&
+	    (tb = tcp_bucket_create(snum)) == NULL)
+			goto fail;
+	if (tb->owners == NULL) {
+		if (sk->reuse && sk->state != TCP_LISTEN)
+			tb->fastreuse = 1;
+		else
+			tb->fastreuse = 0;
+	} else if (tb->fastreuse &&
+		   ((sk->reuse == 0) || (sk->state == TCP_LISTEN)))
+		tb->fastreuse = 0;
+
+success:
+	sk->num = snum;
+	if ((sk->bind_next = tb->owners) != NULL)
+		tb->owners->bind_pprev = &sk->bind_next;
+	tb->owners = sk;
+	sk->bind_pprev = &tb->owners;
+	sk->prev = (struct sock *) tb;
+
 	SOCKHASH_UNLOCK();
-	return result;
+	return 0;
+
+fail:
+	SOCKHASH_UNLOCK();
+	return 1;
 }
 
 static void tcp_v6_hash(struct sock *sk)
 {
-	/* Well, I know that it is ugly...
-	   All this ->prot, ->af_specific etc. need LARGE cleanup --ANK
-	 */
-	if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) {
-		tcp_prot.hash(sk);
-		return;
-	}
 	if(sk->state != TCP_CLOSE) {
 		struct sock **skp;
 
+		/* Well, I know that it is ugly...
+		 * All this ->prot, ->af_specific etc. need LARGE cleanup --ANK
+		 */
+		if (sk->tp_pinfo.af_tcp.af_specific == &ipv6_mapped) {
+			tcp_prot.hash(sk);
+			return;
+		}
+
+		if(sk->state == TCP_LISTEN)
+			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
+		else
+			skp = &tcp_established_hash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
+
 		SOCKHASH_LOCK();
-		skp = &tcp_established_hash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
 		if((sk->next = *skp) != NULL)
 			(*skp)->pprev = &sk->next;
 		*skp = sk;
 		sk->pprev = skp;
-		tcp_sk_bindify(sk);
 		SOCKHASH_UNLOCK();
 	}
 }
@@ -191,39 +210,8 @@
 			sk->next->pprev = sk->pprev;
 		*sk->pprev = sk->next;
 		sk->pprev = NULL;
-		tcp_sk_unbindify(sk);
 		tcp_reg_zap(sk);
-	}
-	SOCKHASH_UNLOCK();
-}
-
-static void tcp_v6_rehash(struct sock *sk)
-{
-	unsigned char state;
-
-	SOCKHASH_LOCK();
-	state = sk->state;
-	if(sk->pprev != NULL) {
-		if(sk->next)
-			sk->next->pprev = sk->pprev;
-		*sk->pprev = sk->next;
-		sk->pprev = NULL;
-		tcp_reg_zap(sk);
-	}
-	if(state != TCP_CLOSE) {
-		struct sock **skp;
-
-		if(state == TCP_LISTEN)
-			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
-		else
-			skp = &tcp_established_hash[(sk->hashent = tcp_v6_sk_hashfn(sk))];
-
-		if((sk->next = *skp) != NULL)
-			(*skp)->pprev = &sk->next;
-		*skp = sk;
-		sk->pprev = skp;
-		if(state == TCP_LISTEN)
-			tcp_sk_bindify(sk);
+		__tcp_put_port(sk);
 	}
 	SOCKHASH_UNLOCK();
 }
@@ -1048,8 +1036,8 @@
 	newsk->rcv_saddr= LOOPBACK4_IPV6;
 
 	newsk->prot->hash(newsk);
+	tcp_inherit_port(sk, newsk);
 	add_to_prot_sklist(newsk);
-
 	sk->data_ready(sk, 0); /* Deliver SIGIO */ 
 
 	return newsk;
@@ -1633,11 +1621,9 @@
 
 	/* Clean up a locked TCP bind bucket, this only happens if a
 	 * port is allocated for a socket, but it never fully connects.
-	 * In which case we will find num to be non-zero and daddr to
-	 * be zero.
 	 */
-	if(ipv6_addr_any(&(sk->net_pinfo.af_inet6.daddr)) && sk->num != 0)
-		tcp_bucket_unlock(sk);
+	if(sk->prev != NULL)
+		tcp_put_port(sk);
 
 	return inet6_destroy_sock(sk);
 }
@@ -1664,9 +1650,7 @@
 	tcp_v6_do_rcv,			/* backlog_rcv */
 	tcp_v6_hash,			/* hash */
 	tcp_v6_unhash,			/* unhash */
-	tcp_v6_rehash,			/* rehash */
-	tcp_good_socknum,		/* good_socknum */
-	tcp_v6_verify_bind,		/* verify_bind */
+	tcp_v6_get_port,		/* get_port */
 	128,				/* max_header */
 	0,				/* retransmits */
 	"TCPv6",			/* name */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipv6/udp.c linux.pre11.3/net/ipv6/udp.c
--- linux.vanilla/net/ipv6/udp.c	Thu May 27 22:12:04 1999
+++ linux.pre11.3/net/ipv6/udp.c	Mon Jul 19 23:27:16 1999
@@ -7,7 +7,7 @@
  *
  *	Based on linux/ipv4/udp.c
  *
- *	$Id: udp.c,v 1.40 1999/05/08 20:00:32 davem Exp $
+ *	$Id: udp.c,v 1.40.2.1 1999/06/20 20:14:55 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -49,104 +49,101 @@
 /* Grrr, addr_type already calculated by caller, but I don't want
  * to add some silly "cookie" argument to this method just for that.
  */
-static int udp_v6_verify_bind(struct sock *sk, unsigned short snum)
+static int udp_v6_get_port(struct sock *sk, unsigned short snum)
 {
-	struct sock *sk2;
-	int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
-	int retval = 0, sk_reuse = sk->reuse;
-
 	SOCKHASH_LOCK();
-	for(sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; sk2 != NULL; sk2 = sk2->next) {
-		if((sk2->num == snum) && (sk2 != sk)) {
-			unsigned char state = sk2->state;
-			int sk2_reuse = sk2->reuse;
-
-			/* Two sockets can be bound to the same port if they're
-			 * bound to different interfaces.
-			 */
+	if (snum == 0) {
+		int best_size_so_far, best, result, i;
 
-			if(sk2->bound_dev_if != sk->bound_dev_if)
-				continue;
-
-			if(addr_type == IPV6_ADDR_ANY || (!sk2->rcv_saddr)) {
-				if((!sk2_reuse)			||
-				   (!sk_reuse)			||
-				   (state == TCP_LISTEN)) {
-					retval = 1;
-					break;
-				}
-			} else if(!ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
-						 &sk2->net_pinfo.af_inet6.rcv_saddr)) {
-				if((!sk_reuse)			||
-				   (!sk2_reuse)			||
-				   (state == TCP_LISTEN)) {
-					retval = 1;
-					break;
-				}
+		if (udp_port_rover > sysctl_local_port_range[1] ||
+		    udp_port_rover < sysctl_local_port_range[0])
+			udp_port_rover = sysctl_local_port_range[0];
+		best_size_so_far = 32767;
+		best = result = udp_port_rover;
+		for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
+			struct sock *sk;
+			int size;
+
+			sk = udp_hash[result & (UDP_HTABLE_SIZE - 1)];
+			if (!sk) {
+				if (result > sysctl_local_port_range[1])
+					result = sysctl_local_port_range[0] +
+						((result - sysctl_local_port_range[0]) &
+						 (UDP_HTABLE_SIZE - 1));
+				goto gotit;
 			}
+			size = 0;
+			do {
+				if (++size >= best_size_so_far)
+					goto next;
+			} while ((sk = sk->next) != NULL);
+			best_size_so_far = size;
+			best = result;
+		next:
+		}
+		result = best;
+		for(;; result += UDP_HTABLE_SIZE) {
+			if (result > sysctl_local_port_range[1])
+				result = sysctl_local_port_range[0]
+					+ ((result - sysctl_local_port_range[0]) &
+					   (UDP_HTABLE_SIZE - 1));
+			if (!udp_lport_inuse(result))
+				break;
+		}
+gotit:
+		udp_port_rover = snum = result;
+	} else {
+		struct sock *sk2;
+		int addr_type = ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr);
+
+		for (sk2 = udp_hash[snum & (UDP_HTABLE_SIZE - 1)];
+		     sk2 != NULL;
+		     sk2 = sk2->next) {
+			if (sk2->num == snum &&
+			    sk2 != sk &&
+			    sk2->bound_dev_if == sk->bound_dev_if &&
+			    (!sk2->rcv_saddr ||
+			     addr_type == IPV6_ADDR_ANY ||
+			     !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr,
+					    &sk2->net_pinfo.af_inet6.rcv_saddr)) &&
+			    (!sk2->reuse || !sk->reuse))
+				goto fail;
 		}
 	}
+
+	sk->num = snum;
+	SOCKHASH_UNLOCK();
+	return 0;
+
+fail:
 	SOCKHASH_UNLOCK();
-	return retval;
+	return 1;
 }
 
 static void udp_v6_hash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
-
-	num &= (UDP_HTABLE_SIZE - 1);
-	skp = &udp_hash[num];
+	struct sock **skp = &udp_hash[sk->num & (UDP_HTABLE_SIZE - 1)];
 
 	SOCKHASH_LOCK();
-	sk->next = *skp;
+	if ((sk->next = *skp) != NULL)
+		(*skp)->pprev = &sk->next;
 	*skp = sk;
-	sk->hashent = num;
+	sk->pprev = skp;
 	SOCKHASH_UNLOCK();
 }
 
 static void udp_v6_unhash(struct sock *sk)
 {
-	struct sock **skp;
-	int num = sk->num;
-
-	num &= (UDP_HTABLE_SIZE - 1);
-	skp = &udp_hash[num];
-
 	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
+	if (sk->pprev) {
+		if (sk->next)
+			sk->next->pprev = sk->pprev;
+		*sk->pprev = sk->next;
+		sk->pprev = NULL;
 	}
 	SOCKHASH_UNLOCK();
 }
 
-static void udp_v6_rehash(struct sock *sk)
-{
-	struct sock **skp;
-	int num = sk->num;
-	int oldnum = sk->hashent;
-
-	num &= (UDP_HTABLE_SIZE - 1);
-	skp = &udp_hash[oldnum];
-
-	SOCKHASH_LOCK();
-	while(*skp != NULL) {
-		if(*skp == sk) {
-			*skp = sk->next;
-			break;
-		}
-		skp = &((*skp)->next);
-	}
-	sk->next = udp_hash[num];
-	udp_hash[num] = sk;
-	sk->hashent = num;
-	SOCKHASH_UNLOCK();
-}
-
 static struct sock *udp_v6_lookup(struct in6_addr *saddr, u16 sport,
 				  struct in6_addr *daddr, u16 dport, int dif)
 {
@@ -893,7 +890,6 @@
 	"UDPv6"			/* name			*/
 };
 
-
 struct proto udpv6_prot = {
 	(struct sock *)&udpv6_prot,	/* sklist_next */
 	(struct sock *)&udpv6_prot,	/* sklist_prev */
@@ -916,9 +912,7 @@
 	udpv6_queue_rcv_skb,		/* backlog_rcv */
 	udp_v6_hash,			/* hash */
 	udp_v6_unhash,			/* unhash */
-	udp_v6_rehash,			/* rehash */
-	udp_good_socknum,		/* good_socknum */
-	udp_v6_verify_bind,		/* verify_bind */
+	udp_v6_get_port,		/* get_port */
 	128,				/* max_header */
 	0,				/* retransmits */
 	"UDP",				/* name */
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/ipx/af_ipx.c linux.pre11.3/net/ipx/af_ipx.c
--- linux.vanilla/net/ipx/af_ipx.c	Tue Feb 23 14:21:35 1999
+++ linux.pre11.3/net/ipx/af_ipx.c	Tue Jul 20 00:23:10 1999
@@ -794,7 +794,8 @@
 					if(call_fw_firewall(PF_IPX, skb->dev, ipx, NULL, &skb) == FW_ACCEPT)
 					{
 					        skb2=skb_clone(skb, GFP_ATOMIC);
-						ipxrtr_route_skb(skb2);
+						if(skb2)
+							ipxrtr_route_skb(skb2);
 					}
 				}
 			}
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/netrom/af_netrom.c linux.pre11.3/net/netrom/af_netrom.c
--- linux.vanilla/net/netrom/af_netrom.c	Sat Jan  9 21:50:52 1999
+++ linux.pre11.3/net/netrom/af_netrom.c	Tue Jul 20 00:23:18 1999
@@ -63,7 +63,6 @@
 #include <linux/proc_fs.h>
 #include <net/ip.h>
 #include <net/arp.h>
-#include <linux/if_arp.h>
 #include <linux/init.h>
 
 int nr_ndevs = 4;
@@ -1311,6 +1310,11 @@
 
 	for (i = 0; i < nr_ndevs; i++) {
 		dev_nr[i].name = kmalloc(20, GFP_KERNEL);
+		if(dev_nr[i].name==NULL)
+		{
+			printk(KERN_ERR "Netrom: unable to register devices.\n");
+			break;
+		}
 		sprintf(dev_nr[i].name, "nr%d", i);
 		dev_nr[i].init = nr_init;
 		register_netdev(&dev_nr[i]);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/netsyms.c linux.pre11.3/net/netsyms.c
--- linux.vanilla/net/netsyms.c	Wed Apr 28 19:14:40 1999
+++ linux.pre11.3/net/netsyms.c	Tue Jul 20 00:23:27 1999
@@ -25,6 +25,7 @@
 #include <linux/hippidevice.h>
 #endif
 #include <net/pkt_sched.h>
+#include <net/scm.h>
 
 #ifdef CONFIG_BRIDGE
 #include <net/br.h>
@@ -32,7 +33,6 @@
 
 #ifdef CONFIG_INET
 #include <linux/ip.h>
-#include <linux/etherdevice.h>
 #include <net/protocol.h>
 #include <net/arp.h>
 #include <net/ip.h>
@@ -40,9 +40,7 @@
 #include <net/tcp.h>
 #include <net/icmp.h>
 #include <net/route.h>
-#include <net/scm.h>
 #include <net/inet_common.h>
-#include <net/pkt_sched.h>
 #include <linux/inet.h>
 #include <linux/mroute.h>
 #include <linux/igmp.h>
@@ -56,18 +54,18 @@
 #include <linux/icmpv6.h>
 #include <net/ipv6.h>
 #include <net/ndisc.h>
-#include <net/dst.h>
 #include <net/transp_v6.h>
 
 extern int tcp_tw_death_row_slot;
+extern int sysctl_local_port_range[2];
+extern int tcp_port_rover;
+extern int udp_port_rover;
 #endif
 
 #endif
 
 #include <linux/rtnetlink.h>
 
-#include <net/scm.h>
-
 #if	defined(CONFIG_ULTRA)	||	defined(CONFIG_WD80x3)		|| \
 	defined(CONFIG_EL2)	||	defined(CONFIG_NE2000)		|| \
 	defined(CONFIG_E2100)	||	defined(CONFIG_HPLAN_PLUS)	|| \
@@ -90,10 +88,6 @@
 
 #ifdef CONFIG_ATALK_MODULE
 #include <net/sock.h>
-#include <net/dst.h>
-#include <net/checksum.h>
-#include <linux/etherdevice.h>
-#include <net/pkt_sched.h>
 #endif
 
 #ifdef CONFIG_SYSCTL
@@ -278,11 +272,9 @@
 EXPORT_SYMBOL(inet_recvmsg);
 
 /* Socket demultiplexing. */
-EXPORT_SYMBOL(tcp_good_socknum);
 EXPORT_SYMBOL(tcp_established_hash);
 EXPORT_SYMBOL(tcp_listening_hash);
 EXPORT_SYMBOL(tcp_bound_hash);
-EXPORT_SYMBOL(udp_good_socknum);
 EXPORT_SYMBOL(udp_hash);
 
 EXPORT_SYMBOL(destroy_sock);
@@ -323,7 +315,9 @@
 EXPORT_SYMBOL(tcp_v4_conn_request);
 EXPORT_SYMBOL(tcp_create_openreq_child);
 EXPORT_SYMBOL(tcp_bucket_create);
-EXPORT_SYMBOL(tcp_bucket_unlock);
+EXPORT_SYMBOL(__tcp_put_port);
+EXPORT_SYMBOL(tcp_put_port);
+EXPORT_SYMBOL(tcp_inherit_port);
 EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
 EXPORT_SYMBOL(tcp_v4_do_rcv);
 EXPORT_SYMBOL(tcp_v4_connect);
@@ -339,6 +333,9 @@
 EXPORT_SYMBOL(tcp_connect);
 EXPORT_SYMBOL(tcp_make_synack);
 EXPORT_SYMBOL(tcp_tw_death_row_slot);
+EXPORT_SYMBOL(sysctl_local_port_range);
+EXPORT_SYMBOL(tcp_port_rover);
+EXPORT_SYMBOL(udp_port_rover);
 EXPORT_SYMBOL(tcp_sync_mss);
 EXPORT_SYMBOL(net_statistics); 
 
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/rose/af_rose.c linux.pre11.3/net/rose/af_rose.c
--- linux.vanilla/net/rose/af_rose.c	Sun Nov  8 15:07:18 1998
+++ linux.pre11.3/net/rose/af_rose.c	Tue Jul 20 00:24:09 1999
@@ -54,7 +54,6 @@
 #include <linux/proc_fs.h>
 #include <net/ip.h>
 #include <net/arp.h>
-#include <linux/if_arp.h>
 #include <linux/init.h>
 
 int rose_ndevs = 10;
@@ -1509,6 +1508,11 @@
 
 	for (i = 0; i < rose_ndevs; i++) {
 		dev_rose[i].name = kmalloc(20, GFP_KERNEL);
+		if(dev_rose[i].name == NULL)
+		{
+			printk(KERN_ERR "Rose: unable to register ROSE devices.\n");
+			break;
+		}
 		sprintf(dev_rose[i].name, "rose%d", i);
 		dev_rose[i].init = rose_init;
 		register_netdev(&dev_rose[i]);
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/sched/sch_red.c linux.pre11.3/net/sched/sch_red.c
--- linux.vanilla/net/sched/sch_red.c	Wed Mar 24 10:55:31 1999
+++ linux.pre11.3/net/sched/sch_red.c	Mon Jul 19 23:27:19 1999
@@ -231,7 +231,6 @@
 		 */
 		if (((q->qave - q->qth_min)>>q->Wlog)*q->qcount < q->qR)
 			goto enqueue;
-printk(KERN_DEBUG "Drop %d\n", q->qcount);
 		q->qcount = 0;
 		q->qR = net_random()&q->Rmask;
 		sch->stats.overlimits++;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/net/unix/af_unix.c linux.pre11.3/net/unix/af_unix.c
--- linux.vanilla/net/unix/af_unix.c	Thu May 27 22:12:08 1999
+++ linux.pre11.3/net/unix/af_unix.c	Mon Jul 19 23:27:10 1999
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.76 1999/05/08 05:54:55 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.76.2.1 1999/06/28 10:40:07 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
@@ -103,6 +103,7 @@
 #include <net/scm.h>
 #include <linux/init.h>
 #include <linux/poll.h>
+#include <linux/smp_lock.h>
 
 #include <asm/checksum.h>
 
@@ -981,7 +982,11 @@
 		unix_attach_fds(scm, skb);
 
 	skb->h.raw = skb->data;
+
+	unlock_kernel();
 	err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+	lock_kernel();
+
 	if (err)
 		goto out_free;
 
@@ -1013,7 +1018,7 @@
 	while (skb_queue_len(&other->receive_queue) >=
 	       sysctl_unix_max_dgram_qlen)
 	{
-		if (sock->file->f_flags & O_NONBLOCK)
+		if (msg->msg_flags&MSG_DONTWAIT)
 		{
 			err = -EAGAIN;
 			goto out_unlock;
@@ -1137,11 +1142,19 @@
 		if (scm->fp)
 			unix_attach_fds(scm, skb);
 
-		if (memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) {
-			kfree_skb(skb);
-			if (sent)
-				goto out;
-			return -EFAULT;
+		{
+			int err;
+
+			unlock_kernel();
+			err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size);
+			lock_kernel();
+
+			if(err) {
+				kfree_skb(skb);
+				if (sent)
+					goto out;
+				return -EFAULT;
+			}
 		}
 
 		other=unix_peer(sk);
@@ -1219,7 +1232,10 @@
 	else if (size < skb->len)
 		msg->msg_flags |= MSG_TRUNC;
 
+	unlock_kernel();
 	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size);
+	lock_kernel();
+
 	if (err)
 		goto out_free;
 
@@ -1339,11 +1355,19 @@
 		}
 
 		chunk = min(skb->len, size);
-		if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
-			skb_queue_head(&sk->receive_queue, skb);
-			if (copied == 0)
-				copied = -EFAULT;
-			break;
+		{
+			int err;
+
+			unlock_kernel();
+			err = memcpy_toiovec(msg->msg_iov, skb->data, chunk);
+			lock_kernel();
+
+			if(err) {
+				skb_queue_head(&sk->receive_queue, skb);
+				if (copied == 0)
+					copied = -EFAULT;
+				break;
+			}
 		}
 		copied += chunk;
 		size -= chunk;
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/scripts/mkdep.c linux.pre11.3/scripts/mkdep.c
--- linux.vanilla/scripts/mkdep.c	Sat Jan  9 21:50:52 1999
+++ linux.pre11.3/scripts/mkdep.c	Mon Jul 19 23:28:58 1999
@@ -193,7 +193,7 @@
  * Thus, there is one memory access per sizeof(unsigned long) characters.
  */
 
-#if defined(__alpha__) || defined(__i386__) || defined(__arm__)
+#if defined(__alpha__) || defined(__i386__) || defined(__MIPSEL__) || defined(__arm__)
 #define LE_MACHINE
 #endif
 
Binary files linux.vanilla/scripts/split-include and linux.pre11.3/scripts/split-include differ
diff -u --new-file --recursive --exclude-from ../exclude linux.vanilla/scripts/ver_linux linux.pre11.3/scripts/ver_linux
--- linux.vanilla/scripts/ver_linux	Fri Apr 16 22:11:05 1999
+++ linux.pre11.3/scripts/ver_linux	Tue Jul 20 00:24:29 1999
@@ -21,10 +21,12 @@
 ps --version 2>&1 | awk 'NR==1{print "Procps                ", $NF}'
 mount --version | awk -F\- '{print "Mount                 ", $NF}'
 hostname -V 2>&1 | awk 'NR==1{print "Net-tools             ", $NF}'
+# Kbd needs 'loadkeys -h',
 loadkeys -h 2>&1 | awk \
-'(NR==1 && $3) {ver=$3}
- (NR==2 && $1 ~ /console-tools/) {print "Console-tools         ",$3; done=1}
- END {if (!done) print "Kbd                   ",ver}'
+'(NR==1 && ($3 !~ /option/)) {print "Kbd                   ", $3}'
+# while console-tools needs 'loadkeys -V'.
+loadkeys -V 2>&1 | awk \
+'(NR==1 && ($2 ~ /console-tools/)) {print "Console-tools         ", $3}'
 expr --v | awk '{print "Sh-utils              ", $NF}'
 X=`cat /proc/modules | sed -e "s/ .*$//"`
 echo "Modules Loaded         "$X
