diff -u --recursive --new-file v2.1.100/linux/Documentation/ARM-README linux/Documentation/ARM-README
--- v2.1.100/linux/Documentation/ARM-README	Sat May  2 14:19:50 1998
+++ linux/Documentation/ARM-README	Fri May  8 00:42:37 1998
@@ -1,15 +1,12 @@
-			   ARM Linux 2.1.78
+			   ARM Linux 2.1.99
 			   ================
 
- **  The ARM support contained within is NOT complete - it will not build.   **
- **    If you want to build it, then please obtain a full copy of the ARM    **
- ** patches from ftp://ftp.arm.uk.linux.org/pub/armlinux/kernel-sources/v2.1 **
-
   Since this is a development kernel, it will not be as stable as the 2.0
   series, and can cause very nasty problems (eg, trashing your hard disk).
   When running one of these kernels, I advise you to back up the complete
   contents of all your hard disks.
 
+
 Contributors
 ------------
 
@@ -28,26 +25,16 @@
   Mail: Philip.Blundell@pobox.com
   Desc: Architecture and processor selection during make config.
 
+
 Todo list
 ---------
 
   This is the list of changes to be done (roughly prioritorised):
 
-  * fully test new A5000 & older MEMC translation code
+  * fully test new MEMC translation code
   * fully test new AcornSCSI driver.
   * reply to email ;)
 
-Bugs
-----
-
-  Fixed bugs in this version 2.1.76:
-
-  Modules believed to be buggy (please report your successes/failures):
-
-  * AcornSCSI believed to occasionally corrupt hard drives.
-  * All NCR5380-based SCSI devices [Cumana I, Oak, EcoSCSI] are slow,
-    and may not allow write access.
-  * A5000 and older machine kernel builds may not be as stable as they were.
 
 			     Notes
 			     =====
@@ -76,12 +63,13 @@
 	to
     CROSS_COMPILE=<your-path-to-your-compiler-without-gcc>
 	eg.
-    CROSS_COMPILE=/usr/src/bin/arm/arm-linuxelf-
+    CROSS_COMPILE=/usr/bin/arm-unknown-linuxelf-
 
   Do a 'make config', followed by 'make dep', and finally 'make all' to
   build the kernel (vmlinux).  A compressed image can be built by doing
   a 'make zImage' instead of 'make all'.
 
+
 Bug reports etc
 ---------------
 
@@ -96,6 +84,7 @@
   For patches, please include some explanation as to what the patch does
   and why (if relevant).
 
+
 Modules
 -------
 
@@ -108,6 +97,7 @@
   as such Acorn RiscPCs and other architectures using these processors can
   make good use of modularisation.
 
+
 ADFS Image files
 ----------------
 
@@ -118,6 +108,7 @@
   Please note that the PCEmulator DOS partitions have a partition table at
   the start, and as such, you will have to give '-o offset' to losetup.
 
+
 Kernel initialisation abort codes
 ---------------------------------
 
@@ -128,17 +119,19 @@
     Stripes of White,Red,Yellow,Green:
        Kernel does not support the processor architecture detected.
 
+
 Request to developers
 ---------------------
 
   When writing device drivers which include a separate assember file, please
   include it in with the C file, and not the arch/arm/lib directory.  This
   allows the driver to be compiled as a loadable module without requiring
-  half the code to be needlessly compiled into the kernel image.
+  half the code to be compiled into the kernel image.
 
   In general, try to avoid using assembler unless it is really necessary.  It
   makes drivers far less easy to port to other hardware.
 
+
 ST506 hard drives
 -----------------
 
@@ -167,3 +160,22 @@
   hasn't got any code for disc change detection in there at the moment which
   could be a bit of a problem!  Suggestions on the correct way to do this
   are welcome.
+
+
+Kernel entry (head-armv.S)
+--------------------------
+  The initial entry into the kernel made via head-armv.S uses architecture
+  independent code.  The architecture is selected by the value of 'r1' on
+  entry, which must be kept unique.  You can register a new architecture
+  by mailing the following details to rmk@arm.uk.linux.org.  Please give
+  the mail a subject of 'Register new architecture':
+
+    Name: <name of your architecture>
+    ARCHDIR: <name of include/asm-arm/arch-* directory>
+    Description:
+    <description of your architecture>
+
+  Please follow this format - it is an automated system.  You should
+  receive a reply the next day.
+---
+Russell King (03/05/1998)
diff -u --recursive --new-file v2.1.100/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.100/linux/Documentation/Configure.help	Thu May  7 22:51:45 1998
+++ linux/Documentation/Configure.help	Fri May  8 00:42:38 1998
@@ -742,6 +742,24 @@
   want to compile it as a module, say M here and read
   Documentation/modules.txt. If unsure, say Y.
 
+IDE card support
+CONFIG_BLK_DEV_IDE_CARDS
+  On Acorn systems, enable this if you wish to use an IDE interface
+  expansion card. If you do not or are unsure, say N to this.
+
+ICS IDE interface
+CONFIG_BLK_DEV_IDE_ICS
+  On Acorn systems, enable this if you wish to use the ICS IDE
+  interface card.  This is not required for ICS partition support.
+  If you are unsure, say N to this.
+
+ADFS partition support
+CONFIG_BLK_DEV_PART
+  This allows Linux on Acorn systems to determine its partitions in
+  the 'non-ADFS' partition area of the hard disk - usually located
+  after the ADFS partition.  You are probably using this system, so
+  you should enable it.
+
 Boot support (linear, striped)
 CONFIG_MD_BOOT
   To boot with an initial linear or striped md device you have to say
@@ -3585,6 +3603,51 @@
   important data. This is primarily of use to people trying to debug
   the middle and upper layers of the SCSI subsystem. If unsure, say N.
 
+AcornSCSI support
+CONFIG_SCSI_ACORNSCSI_3
+  This enables support for the Acorn SCSI card (aka30).  If you have an
+  Acorn system with one of these, say Y.  If unsure, say N.
+
+Acorn SCSI tagged queue support
+CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
+  Say Y here to enable tagged queuing support on the Acorn SCSI card.
+
+Acorn SCSI Synchronous transfers support
+CONFIG_SCSI_ACORNSCSI_SYNC
+  Say Y here to enable synchronous transfer negociation with all targets
+  on the Acorn SCSI card.
+
+Oak SCSI support
+CONFIG_SCSI_OAK1
+  This enables support for the Oak SCSI card.  If you have an Acorn system
+  with one of these, say Y.  If unsure, say N.
+
+Cumana SCSI I support
+CONFIG_SCSI_CUMANA_1
+  This enables support for the Cumana SCSI I card.  If you have an Acorn
+  system with one of these, say Y.  If unsure, say N.
+
+Cumana SCSI II support
+CONFIG_SCSI_CUMANA_2
+  This enables support for the Cumana SCSI II card.  If you have an Acorn
+  system with one of these, say Y.  If unsure, say N.
+
+EcoSCSI support
+CONFIG_SCSI_ECOSCSI
+  This enables support for the EcoSCSI card - a small card that sits in
+  the Econet socket.  If you have an Acorn system with one of these,
+  say Y.  If unsure, say N.
+
+EESOX SCSI support
+CONFIG_SCSI_EESOXSCSI
+  This enables support for the EESOX SCSI card.  If you have an Acorn
+  system with one of these, say Y, otherwise say N.
+
+Powertec SCSI support
+CONFIG_SCSI_POWERTECSCSI
+  This enables support for the Powertec SCSI card on Acorn systems.  If
+  you have one of these, say Y.  If unsure, say N.  
+
 Network device support?
 CONFIG_NETDEVICES
   You can say N here if you don't intend to connect to any other
@@ -3816,6 +3879,17 @@
   Enter either 0x30f or 0x20f here.  The card default is 0x30f, if you
   haven't changed the jumper setting on the card.
 
+Aztech/Packard Bell Radio
+CONFIG_RADIO_AZTECH
+  Choose Y here if you have one of these, and then fill in the port
+  address below.
+
+Aztech/Packard Bell radio card i/o port
+CONFIG_RADIO_AZTECH_PORT
+  Enter either 0x350 or 0x358 here.  The card default is 0x350, if you
+  haven't changed the setting of jumper JP3 on the card.  Removing the
+  jumper sets the card to 0x358.
+
 LAPB over Ethernet driver
 CONFIG_LAPBETHER
   This is a driver for a pseudo device (typically called /dev/lapb0)
@@ -5061,6 +5135,26 @@
   This is support for the DIGITAL series of EISA (DEFEA) and PCI
   (DEFPA) controllers which can connect you to a local FDDI network.
 
+Acorn Ether1 card
+CONFIG_ARM_ETHER1
+  If you have an Acorn system with one of these (AKA25) network cards,
+  you should say Y to this option if you wish to use it with Linux.
+
+Acorn/ANT Ether3 card
+CONFIG_ARM_ETHER3
+  If you have an Acorn system with one of these network cards, you
+  should say Y to this option if you wish to use it with Linux.
+
+I Cubed EtherH card
+CONFIG_ARM_ETHERH
+  If you have an Acorn system with one of these network cards, you
+  should say Y to this option if you wish to use it with Linux.
+
+EBSA-110 ethernet interface
+CONFIG_AM79C961A
+  If you wish to compile a kernel for the EBSA-110, then you should
+  always answer Y to this.
+
 Support CDROM drives that are not SCSI or IDE/ATAPI
 CONFIG_CD_NO_IDESCSI
   If you have a CDROM drive that is neither SCSI nor IDE/ATAPI, say Y
@@ -6441,6 +6535,13 @@
   or change their color depending on the virtual console you're on.
   See Documentation/VGA-softcursor.txt for more information.
 
+Acorn's ADFS filesystem support (read only) (EXPERIMENTAL)
+CONFIG_ADFS_FS
+  The Advanced Disk File System is the filesystem used on floppy and
+  hard disks by Acorn Systems.  Currently in development, as a read-
+  only driver for hard disks.  These should be the first partition
+  (eg. /dev/[sh]d?1) on each of your drives.  If unsure, say N.
+
 Standard/generic serial support
 CONFIG_SERIAL
   This selects whether you want to include the driver for the standard
@@ -7413,6 +7514,17 @@
   inserted in and removed from the running kernel whenever you want).
   The module will be called joystick.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
+
+Atomwide Serial Support
+CONFIG_ATOMWIDE_SERIAL
+  If you have an Atomwide Serial card for an Acorn system, say Y to
+  this option.  The driver can handle 1, 2, or 3 port cards.
+  If unsure, say N
+
+The Serial Port Dual Serial Port
+CONFIG_DUALSP_SERIAL
+  If you have the Serial Port's dual serial card for an Acorn system,
+  say Y to this option.  If unsure, say N
 
 Sound card support
 CONFIG_SOUND
diff -u --recursive --new-file v2.1.100/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt
--- v2.1.100/linux/Documentation/filesystems/affs.txt	Sat May  2 14:19:51 1998
+++ linux/Documentation/filesystems/affs.txt	Thu May  7 22:58:04 1998
@@ -26,7 +26,7 @@
 
 All of the above filesystems allow block sizes from 512 to 32K bytes.
 Supported block sizes are: 512, 1024, 2048 and 4096 bytes. Larger blocks
-speed up almost everything with the expense of wasted disk space. The speed
+speed up almost everything at the expense of wasted disk space. The speed
 gain above 4K seems not really worth the price, so you don't lose too
 much here, either.
 
@@ -45,12 +45,13 @@
 
 mode=mode	Sets the mode flags to the given (octal) value, regardless
 		of the original permissions. Directories will get an x
-		permission, if the corresponding r bit is set.
+		permission if the corresponding r bit is set.
 		This is useful since most of the plain AmigaOS files
 		will map to 600.
 
 reserved=num	Sets the number of reserved blocks at the start of the
-		partition to num. Default is 2.
+		partition to num. You should never need this option.
+		Default is 2.
 
 root=block	Sets the block number of the root block. This should never
 		be necessary.
@@ -71,11 +72,13 @@
 		as one.
 
 prefix=path	Path will be prefixed to every absolute path name of
-		symbolic links on an AFFS partition. Default = /
+		symbolic links on an AFFS partition. Default = "/".
+		(See below.)
 
 volume=name	When symbolic links with an absolute path are created
-		on an AFFS partition, volume will be prepended as the
+		on an AFFS partition, name will be prepended as the
 		volume name. Default = "" (empty string).
+		(See below.)
 
 Handling of the Users/Groups and protection flags
 =================================================
@@ -92,11 +95,13 @@
 
   - H and P are always retained and ignored under Linux.
 
-  - A is always reset when written.
+  - A is always reset when a file is written to.
 
 User id and group id will be used unless set[gu]id are given as mount
 options. Since most of the Amiga file systems are single user systems
-they will be owned by root.
+they will be owned by root. The root directory of the Amiga filesystem
+(i. e. the mount point) will be owned by the user who actually mounts
+the filesystem (the root directory doesn't have uid/gid fields).
 
 Linux -> Amiga:
 
@@ -139,12 +144,12 @@
 Examples
 ========
 
-Command line
-    mount  Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,reserved=4
+Command line:
+    mount  Archive/Amiga/Workbench3.1.adf /mnt -t affs -o loop,verbose
     mount  /dev/sda3 /Amiga -t affs
 
-/etc/fstab example
-    /dev/sdb5	/d/f    affs    ro
+/etc/fstab entry:
+    /dev/sdb5	/amiga/Workbench    affs    noauto,user,exec,verbose 0 0
 
 Bugs, Restrictions, Caveats
 ===========================
@@ -159,10 +164,10 @@
 in include/linux/amigaffs.h).
 
 Case is ignored by the affs in filename matching, but Linux shells
-do care about the case. Example (with /mnt being an affs mounted fs):
-    rm /mnt/WRONGCASE
+do care about the case. Example (with /wb being an affs mounted fs):
+    rm /wb/WRONGCASE
 will remove /mnt/wrongcase, but
-    rm /mnt/WR*
+    rm /wb/WR*
 will not since the names are matched by the shell.
 
 The block allocation is designed for hard disk partitions. If more
@@ -170,14 +175,20 @@
 in an ugly way (but the real AFFS doesn't do much better). This
 is also true when space gets tight.
 
+You cannot execute programs on an OFS (Old File System), since the
+program files cannot be memory mapped due to the 488 byte blocks.
+For the same reason you cannot mount an image on such a filesystem
+via the loopback device.
+
 The bitmap valid flag in the root block may not be accurate when the
 system crashes while an affs partition is mounted. There's currently
-no way to fix this without an Amiga (disk validator) or manually
-(who would do this?). Maybe later.
+no way to fix a garbled filesystem without an Amiga (disk validator)
+or manually (who would do this?). Maybe later.
 
 A fsck.affs and mkfs.affs will probably be available in the future.
-Until then, you should do
-    ln -s /bin/true /etc/fs/mkfs.affs
+If you mount them on system startup, you may want to tell fsck
+that the fs should not be checked (place a '0' in the sixth field
+of /etc/fstab).
 
 It's not possible to read floppy disks with a normal PC or workstation
 due to an incompatibility with the Amiga floppy controller.
diff -u --recursive --new-file v2.1.100/linux/Documentation/transname.txt linux/Documentation/transname.txt
--- v2.1.100/linux/Documentation/transname.txt	Sat May  2 14:19:52 1998
+++ linux/Documentation/transname.txt	Wed Dec 31 16:00:00 1969
@@ -1,264 +0,0 @@
-Transname version 1.9 (C) 1997 Thomas Schoebel-Theuer
-
-transname enables diskless clients, X-terminals etc to mount the
-*root filesystem* of the server. This make administration of
-large pools a lot easier.
-
-Wherefore is linux-2.0.21-transname.patch?
-
-Currently different diskless clients must have their root / on different
-directories on the server, beause each client has _some_ different
-configuration files. However, most files (typically about 99%) have the same
-contents on the clients and on the server, but have to be replicated
-(and maintained separately) just because of the 1% differences.
-This duplication causes very large efforts in practise, since at least
-the /etc directory has to be duplicated for every client. Even in /etc
-many files are identical, for example sendmail.cf, initrc scripts and
-others. Maintaining a large pool requires means to ensure coherence among 
-the duplicates. Classical methods like symlinks are inconvenient
-for this task because they have to be valid in the view of mounted
-filesystems at all clients, not at the server.
-
-Linux transname overcomes this problem by allowing filenames
-to be context-dependent. For example, if you have a file /etc/config
-that should differ on the hosts "myserver" and "myclient", you just
-create two different files named /etc/config#host=myserver# and
-/etc/config#host=myclient# . On host "myserver", the file
-/etc/config#host=myserver# will appear as if it were hardlinked to
-file /etc/config (without the #...=...# suffix). On host "myclient",
-the corresponding other file will appear as /etc/config. So you
-can access the right file contents under the _same_ name, depending
-on which host you are working on.
-
-A similar concept can be found in older HP-UX versions, but with
-so-called "hidden directories" which don't allow contemporary viewing of
-all versions by default. In contrast, transname shows all context-dependent
-files in the dir listing and they can be edited using the
-fully qualified name.
-
-Transname was developed for and is used at our Linux pool at the
-University of Stuttgart with good results. Maintenance of the pool is
-at a minimum, and adding new clients is child's play. No worry with
-keeping up mail configurations, newly installed tools, changed /etc/services,
-/etc/shells, /etc/resolv.conf and many, many others. In contrast to a
-sophisticated symlink solution, adding a new file to the /etc directory
-is seen immediately by all clients.
-
-An example for the use of linux-2.0-transname.patch:
-
-For example, you can make your /etc/fstab context-dependent. If you want
-to do that, you should create an /etc/fstab#ktype=default# for the
-server and an /etc/fstab#ktype=diskless# for all clients. This is because
-your clients may not yet know their own hostname when they attempt to mount
-the root filesystem. You can compile in the kerneltypes "default" and
-"diskless" into different kernels for servers and clients. Of course,
-if your clients boot via bootp and know their names when mounting the root,
-you can use /etc/fstab#host=myclient# instead. But at least servers
-booting from disk normally don't know their hostname at root mount time,
-so you can mix methods and use /etc/fstab#ktype=default# for the server,
-/etc/fstab#ktype=diskless# for the majority of the clients and
-/etc/fstab#host=myclient# for some specific client, because translation
-of #host=...# is given precedence over #ktype=...# by default.
-
-This sort of name translation works with any underlying file system
-and with any inode type (i.e. with directories, symlinks, devices etc),
-because it is implemented in the VFS layer of the kernel. Currently,
-five types of default translations are supported:
-
- * <name>#host=<hostname>#  depends on the hostname, see "uname -n"
- * <name>#kname=<string>#   works with a hard compiled-in string
- * <name>#ktype=<string>#   works with a hard compiled-in string
- * <name>#machine=<id>#     depends on architecture, see "uname -m"
- * <name>#system=<id>#      currently only supported by Linux, see "uname -s"
-
-Others may be added in future.
-
-The current translations are displayed at boot time in the kernel messages
-for easier debugging, and can be retrieved by reading
-/proc/sys/kernel/nametrans which is a special file containing the currently
-valid translations.
-
-The default translations change whenever the hostname(1) is set or changed.
-Thus, the hostname is not set (or set to the name "(none)") at boot time
-before init(8) sets it. So, if you want to use the hostname before that
-moment, there are three ways:
-
- a) set the hostname before via bootp or similar.
- b) use the compiled-in translations kname and ktype solely.
- c) set all translations by lilo (or on the boot command line) with
-    kernel parameter   nametrans=#host=banana#:#ktype=diskless# ,
-    thus overriding and hiding the default (built-in) translations.
-
-Note that by supplying the colon-separated list of at most 16 suffixes, you
-can also use other translation types that are not defined in the default
-translations. However, you must ensure that the syntax #...=...# is correct.
-The specified contexts will be tried in the specified order *instead* of the
-default translations. 
-
-You can override the default (or parameter-supplied) translations at runtime
-by executing
-echo "#host=$HOST#:#ktype=diskless#:#myconfig=something#" > /proc/sys/kernel/nametrans
-However, after doing this (or setting as kernel parameter) the built-in
-default translations have no effect any more, thus changing the hostname
-will not be reflected in the overridden translations. You can switch
-back to the default translations by executing
-echo "" > /proc/sys/kernel/nametrans
-
-Another drawback is that administration tools currently are not aware of
-context-dependent files, so you cannot switch between contexts inside
-one tool session. However, you can simulate administration sessions
-on the server as if they were running on some client. To do this,
-you have to set an environment variable NAMETRANS which has to be the
-*first* environment variable in the list. For example, you can execute
-'env - NAMETRANS=#host=mango#:#ktype=diskless# "`env`" command ...'
-where the command will see the same files as if it had been executed on host
-"mango" with a "diskless" kernel. To switch off translations entirely, use
-an empty list, e.g. 'env - NAMETRANS= "`env`" command ...'.
-
-Hopefully the creators of administration tools and maintainers of Linux 
-distributions will support changing environments in future, so that
-maintaining different views will be very easy.
-
-Some hints:
-
-Archivers like tar, dump, restore should be used with translation
-switched off, in order to avoid doubled space in archive files and when
-extracting from them. Also, make sure that nfsd, mountd (and similar ones
-like samba daemons) run without translation, in order to avoid doubled
-(or even wrong) translation at the server and at the client. You can
-automatically force the creation of context-dependent filenames if there
-exists a template filename like /etc/mtab#host=CREATE#. As soon as a
-process running on "mango" tries to create a file /etc/mtab, the version
-/etc/mtab#host=mango# is created instead (which appears in turn as
-hardlinked to /etc/mtab). Note that if you want to make /etc/fstab
-context-dependent, you should execute "touch /etc/mtab#host=CREATE#" and
-"touch /etc/mtab.tmp#host=CREATE#", because mount, umount and others
-running on different hosts would otherwise try to create one shared
-/etc/mtab which would result in a clash. Also one should execute
-"touch /etc/nologin#host=CREATE#" to prevent global side effects from
-shutdown resp. runlevel.
-
-Which files you have to make context-dependent will differ for different
-needs and different applications. Hopefully some day a standard will
-cover the most common cases and the mist common Linux distributions.
-A HOWTO on this subject is in preparation.
-
-How to install linux-2.0.21-transname.patch?
-
-First of all, keep a backup of your kernel on your disk. Second, keep a
-floppy with a miniroot handy, so you can boot from the floppy, mount
-your harddisk root filesystem and change the names of your configuration
-files back to their old names in case of emergency.
-
-Then, make a kernel with transname support enabled. With "make config"
-or "make xconfig", just go to the section "filesystems". Take a look at
-the help texts that are associated with the transname options, they tell
-you further hints not mentioned in this README. Then build your kernel as
-usual, install it with a *new* kernel-filename, add a *new* entry to
-/etc/lilo.conf and run lilo. **DON'T CHANGE** any configuration files for the
-first reboot!
-
-Just reboot the new kernel and play a little bit around with
-creating context-dependent filenames in your home directory.
-Try all modes including setting NAMETRANS to different values.
-
-As an example for the changes necessary on our LST-1.8-based Linux pool,
-here is the output of the command
-find / /tmp -xdev -name "*#*#" -print | sort -u | xargs ls -ld
-
--r--r--r--   1 root     root         1725 Dec 21  1995 /etc/X11R6/xdm/xdm-config#host=eiche#
--r--r--r--   3 root     root         9509 Feb 15 17:35 /etc/XF86Config#host=balsa#
--r--r--r--   1 root     root         9401 Feb 15 17:34 /etc/XF86Config#host=eiche#
--rw-r--r--   1 root     root         9820 Feb 21 17:00 /etc/XF86Config#host=fichte#
--rw-r--r--   1 root     root         9822 Feb 14 15:45 /etc/XF86Config#host=laerche#
--r--r--r--   3 root     root         9509 Feb 15 17:35 /etc/XF86Config#host=mahagoni#
--r--r--r--   3 root     root         9509 Feb 15 17:35 /etc/XF86Config#host=palisander#
--r--r--r--   2 root     root         9509 Feb 15 17:41 /etc/XF86Config#host=pcbs10#
--r--r--r--   2 root     root         9509 Feb 15 17:41 /etc/XF86Config#host=pcbs11#
--rw-r--r--   1 root     root          586 Jun 11 23:13 /etc/fstab#ktype=default#
--rw-r--r--   1 root     root          242 May 29 17:35 /etc/fstab#ktype=diskless#
--rw-------   1 root     root          338 Jun 14 16:37 /etc/lilo.conf#host=eiche#
--rw-------   1 root     root         5236 Dec 16  1995 /etc/lst.cnf#host=balsa#
--rw-------   1 root     root         5254 Dec 16  1995 /etc/lst.cnf#host=eiche#
--rw-------   1 root     root         5236 Dec 19  1995 /etc/lst.cnf#host=fichte#
--rw-------   1 root     root         5236 Jan 11 13:47 /etc/lst.cnf#host=laerche#
--rw-------   1 root     root         5236 Feb 14 16:57 /etc/lst.cnf#host=mahagoni#
--rw-------   1 root     root         5236 Jan  4  1996 /etc/lst.cnf#host=palisander#
--rw-------   1 root     root         5236 Feb 15 13:57 /etc/lst.cnf#host=pcbs10#
--rw-------   1 root     root         5236 Feb 14 17:06 /etc/lst.cnf#host=pcbs11#
--rw-r--r--   1 root     root            0 Dec 18  1995 /etc/mtab#host=CREATE#
--rw-r--r--   1 root     root          157 Jun 23 21:16 /etc/mtab#host=balsa#
--rw-r--r--   1 root     root          466 Jul  1 16:15 /etc/mtab#host=eiche#
--rw-r--r--   1 root     root          239 Jul  4 11:10 /etc/mtab#host=fichte#
--rw-r--r--   1 root     root          239 Jun 18 14:17 /etc/mtab#host=laerche#
--rw-r--r--   1 root     root          239 May 23 10:50 /etc/mtab#host=mahagoni#
--rw-r--r--   1 root     root          239 Jul  3 10:36 /etc/mtab#host=palisander#
--rw-r--r--   1 root     root           47 Feb 15 14:57 /etc/mtab#host=pcbs10#
--rw-r--r--   1 root     root           47 Feb 14 20:04 /etc/mtab#host=pcbs11#
--rw-r--r--   1 root     root            0 Dec 18  1995 /etc/mtab.tmp#host=CREATE#
--rw-r--r--   1 root     root            0 Dec 19  1995 /etc/nologin#host=CREATE#
-----------   1 root     root          115 Feb 15 14:57 /etc/nologin#host=pcbs10#
-----------   1 root     root          115 Feb 14 20:04 /etc/nologin#host=pcbs11#
--rw-r--r--   1 root     root         4818 Dec 16  1995 /etc/system.cnf#host=balsa#
-lrwxrwxrwx   1 root     root           25 Dec 22  1995 /etc/system.cnf#host=eiche# -> system.cnf#ktype=default#
--rw-r--r--   1 root     root         4821 Dec 19  1995 /etc/system.cnf#host=fichte#
--rw-r--r--   1 root     root         4824 Jan 11 13:47 /etc/system.cnf#host=laerche#
--rw-r--r--   1 root     root         4827 Feb 14 16:57 /etc/system.cnf#host=mahagoni#
--rw-r--r--   1 root     root         4833 Jan  4  1996 /etc/system.cnf#host=palisander#
--rw-r--r--   1 root     root         4840 Feb 15 14:10 /etc/system.cnf#host=pcbs10#
--rw-r--r--   1 root     root         4846 Feb 14 18:23 /etc/system.cnf#host=pcbs11#
--rw-r--r--   1 root     root         4818 Dec 13  1995 /etc/system.cnf#ktype=default#
-drwxrwxrwt  16 root     root         3072 Jul  4 14:29 /tmp#ktype=default#
-lrwxrwxrwx   1 root     root           26 Jul  4 14:22 /tmp#ktype=diskless# -> /tmp#ktype=default#/client
--rw-rw-rw-   1 root     root            0 Feb 15 14:57 /tmp/client#host=CREATE#
-drwxrwxrwx   4 root     root         1024 Jun 28 12:15 /tmp/client#host=balsa#
-drwxrwxrwx   3 root     root         1024 Jul  4 11:10 /tmp/client#host=fichte#
-drwxrwxrwx   3 root     root         1024 Jun 18 14:18 /tmp/client#host=laerche#
-drwxrwxrwx   3 root     root         1024 May 24 13:06 /tmp/client#host=mahagoni#
-drwxrwxrwx   3 root     root         1024 Jul  3 10:37 /tmp/client#host=palisander#
-drwxrwxrwx   4 root     root         1024 Feb 15 14:57 /tmp/client#host=pcbs10#
-drwxrwxrwx   3 root     root         1024 Feb 20 06:43 /tmp/client#host=pcbs11#
-lrwxrwxrwx   1 root     root            9 Feb 15 13:58 /usr/X11R6/bin/X#host=pcbs10# -> XF86_SVGA
-lrwxrwxrwx   1 root     root            9 Feb 14 17:37 /usr/X11R6/bin/X#host=pcbs11# -> XF86_SVGA
-lrwxrwxrwx   1 root     root            7 Feb 14 17:15 /usr/X11R6/bin/X#ktype=diskless# -> XF86_S3
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=balsa#
-drwxr-xr-x  23 root     root         1024 Jan 12 14:22 /var#host=eiche#
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=fichte#
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=laerche#
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=mahagoni#
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=palisander#
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=pcbs10#
-drwxr-xr-x  22 root     root         1024 Dec 13  1995 /var#host=pcbs11#
-
-Notes: The /tmp directory has an own filesystem on server "eiche",
-in order to prevent users from filling the whole filestore (we dont use
-quotas). Each client needs a different /tmp because of possible name clashes.
-Also, the whole /var hierarchy is kept differently to prevent any risk, but
-that could be optimized perhaps. Note that nfsd and mountd have been
-replaced by a script which switches off translations, in the style
-
--rwxr-xr-x   2 root     root           70 Mar 22 12:54 /usr/sbin/rpc.mountd
--rwxr-xr-x   1 root     root        32772 Jun 11  1995 /usr/sbin/rpc.mountd.notrans
--rwxr-xr-x   2 root     root           70 Mar 22 12:54 /usr/sbin/rpc.nfsd
--rwxr-xr-x   1 root     root        45060 Jun 11  1995 /usr/sbin/rpc.nfsd.notrans
-
-where /usr/sbin/rpc.mountd has the contents
-
-#!/bin/sh
-exec /usr/bin/env - NAMETRANS= "`/usr/bin/env`" $0.notrans $*
-
-Of course, that could be improved, but is a quick hack to get things to work.
-
-Enjoy,
-
--- Thomas
-
-
-The author can be contacted under
-   schoebel@informatik.uni-stuttgart.de
-or snailmail
-   Thomas Schoebel-Theuer
-   Institut fuer Informatik
-   Breitwiesenstr. 20-22
-   D-70565 Stuttgart
-
diff -u --recursive --new-file v2.1.100/linux/Makefile linux/Makefile
--- v2.1.100/linux/Makefile	Thu May  7 22:51:46 1998
+++ linux/Makefile	Fri May  8 00:09:20 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 100
+SUBLEVEL = 101
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
 
@@ -355,7 +355,7 @@
 	fi
 	rm -f submenu*
 
-mrproper: clean
+mrproper: clean archmrproper
 	rm -f include/linux/autoconf.h include/linux/version.h
 	rm -f drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h
 	rm -f drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h
diff -u --recursive --new-file v2.1.100/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.1.100/linux/arch/alpha/Makefile	Sat Apr 25 18:13:10 1998
+++ linux/arch/alpha/Makefile	Fri May  8 00:09:20 1998
@@ -76,6 +76,8 @@
 archclean:
 	@$(MAKEBOOT) clean
 
+archmrproper:
+
 archdep:
 	@$(MAKEBOOT) dep
 
diff -u --recursive --new-file v2.1.100/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.1.100/linux/arch/alpha/config.in	Sat May  2 14:19:52 1998
+++ linux/arch/alpha/config.in	Fri May  8 17:54:39 1998
@@ -184,6 +184,7 @@
 fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
diff -u --recursive --new-file v2.1.100/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.1.100/linux/arch/alpha/kernel/alpha_ksyms.c	Wed Apr  8 19:36:24 1998
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Fri May  8 00:23:41 1998
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <asm/softirq.h>
 #include <asm/fpu.h>
+#include <asm/irq.h>
 
 #define __KERNEL_SYSCALLS__
 #include <asm/unistd.h>
@@ -43,6 +44,8 @@
 
 EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
 
 /* platform dependent support */
 EXPORT_SYMBOL(_inb);
diff -u --recursive --new-file v2.1.100/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.1.100/linux/arch/arm/Makefile	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/Makefile	Fri May  8 00:42:38 1998
@@ -12,52 +12,54 @@
 #
 # Copyright (C) 1995, 1996 by Russell King
 
-CFLAGS_PROC	:=
-ASFLAGS_PROC	:=
+CFLAGS_PROC		:=
+ASFLAGS_PROC		:=
 
-ifeq ($(CONFIG_CPU_ARM2),y)
-PROCESSOR	 = armo
-ASFLAGS_PROC	+= -m2
-ifeq ($(CONFIG_BINUTILS_NEW),y)
-CFLAGS_PROC	+= -mcpu=arm2
-ASFLAGS_PROC	+= -m2
-else
-CFLAGS_PROC	+= -m2
-ASFLAGS_PROC	+= -m2
-endif
-endif
-
-ifeq ($(CONFIG_CPU_ARM3),y)
-PROCESSOR	 = armo
-ifeq ($(CONFIG_BINUTILS_NEW),y)
-CFLAGS_PROC	+= -mcpu=arm3
-ASFLAGS_PROC	+= -m3
-else
-CFLAGS_PROC	+= -m3
-ASFLAGS_PROC	+= -m3
-endif
-endif
-
-ifeq ($(CONFIG_CPU_ARM6),y)
-PROCESSOR	 = armv
-ifeq ($(CONFIG_BINUTILS_NEW),y)
-CFLAGS_PROC	+= -mcpu=arm6
-ASFLAGS_PROC	+= -m6
-else
-CFLAGS_PROC	+= -m6
-ASFLAGS_PROC	+= -m6
-endif
-endif
-
-ifeq ($(CONFIG_CPU_SA110),y)
-PROCESSOR	 = armv
-ifeq ($(CONFIG_BINUTILS_NEW),y)
-CFLAGS_PROC	+= -mcpu=strongarm110
-ASFLAGS_PROC	+= -m6
-else
-CFLAGS_PROC	+= -m6
-ASFLAGS_PROC	+= -m6
-endif
+# All processors get `-mshort-load-bytes' for now, to work around alignment
+# problems.  This is more of a hack that just happens to work than a real fix
+# but it will do for now.
+
+ifeq ($(CONFIG_CPU_26),y)
+  PROCESSOR		 = armo
+  ifeq ($(CONFIG_BINUTILS_NEW),y)
+    CFLAGS_PROC		+= -mapcs-26 -mshort-load-bytes
+    ifeq ($(CONFIG_CPU_ARM2),y)
+      CFLAGS_PROC	+= -mcpu=arm2
+      ASFLAGS_PROC	+= -m2
+    endif
+    ifeq ($(CONFIG_CPU_ARM3),y)
+      CFLAGS_PROC	+= -mcpu=arm3
+      ASFLAGS_PROC	+= -m3
+    endif
+  else
+    ifeq ($(CONFIG_CPU_ARM2),y)
+      CFLAGS_PROC	+= -m2
+      ASFLAGS_PROC	+= -m2
+    endif
+    ifeq ($(CONFIG_CPU_ARM3),y)
+      CFLAGS_PROC	+= -m3
+      ASFLAGS_PROC	+= -m3
+    endif
+  endif
+endif
+
+ifeq ($(CONFIG_CPU_32),y)
+  PROCESSOR		 = armv
+  ifeq ($(CONFIG_BINUTILS_NEW),y)
+    CFLAGS_PROC		+= -mapcs-32 -mshort-load-bytes
+    ifeq ($(CONFIG_CPU_ARM6),y)
+      CFLAGS_PROC	+= -mcpu=arm6
+    endif
+    ifeq ($(CONFIG_CPU_ARM7),y)
+      CFLAGS_PROC	+= -mcpu=arm7
+    endif
+    ifeq ($(CONFIG_CPU_SA110),y)
+      CFLAGS_PROC	+= -mcpu=strongarm110
+    endif
+  else
+    CFLAGS_PROC		+= -m6
+  endif
+  ASFLAGS_PROC		+= -m6
 endif
 
 # Processor Architecture
@@ -71,9 +73,6 @@
 COMPRESSED_HEAD	 = head.o
 
 ifeq ($(PROCESSOR),armo)
-ifeq ($(CONFIG_BINUTILS_NEW),y)
-CFLAGS_PROC	+= -mapcs-26 -mshort-load-bytes
-endif
 TEXTADDR	 = 0x02080000
 ZTEXTADDR	 = 0x01800000
 ZRELADDR	 = 0x02080000
@@ -92,11 +91,7 @@
 endif
 
 ifeq ($(PROCESSOR),armv)
-ifeq ($(CONFIG_BINUTILS_NEW),y)
-CFLAGS_PROC	+= -mapcs-32 -mshort-load-bytes
-endif
 TEXTADDR	 = 0xC0008000
-endif
 
 ifeq ($(CONFIG_ARCH_RPC),y)
 MACHINE		 = rpc
@@ -122,21 +117,27 @@
 
 ifeq ($(CONFIG_ARCH_NEXUSPCI),y)
 MACHINE		 = nexuspci
+ARCHDIR		 = nexuspci
 TEXTADDR	 = 0xc0000000
 ZTEXTADDR	 = 0x40200000
 ZRELADDR	 = 0x40000000
 COMPRESSED_EXTRA = $(TOPDIR)/arch/arm/lib/ll_char_wr_scc.o
 COMPRESSED_HEAD	 = head-nexuspci.o
 endif
+endif
 
-OBJDUMP		 = $(CROSS_COMPILE)objdump
 PERL		 = perl
+ifeq ($(CONFIG_BINUTILS_NEW),y)
+LD		 = $(CROSS_COMPILE)ld -m elf32arm
+else
 LD		 = $(CROSS_COMPILE)ld -m elf_arm
-CPP		 = $(CC) -E
+endif
 OBJCOPY		 = $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+OBJDUMP		 = $(CROSS_COMPILE)objdump
+CPP		 = $(CC) -E
 ARCHCC		:= $(word 1,$(CC))
 GCCLIB		:= `$(ARCHCC) $(CFLAGS_PROC) --print-libgcc-file-name`
-GCCARCH		:= -B/usr/src/bin/arm/arm-linuxelf- 
+#GCCARCH		:= -B/usr/bin/arm-linuxelf- 
 HOSTCFLAGS	:= $(CFLAGS:-fomit-frame-pointer=)
 ifeq ($(CONFIG_FRAME_POINTER),y)
 CFLAGS		:= $(CFLAGS:-fomit-frame-pointer=)
@@ -225,5 +226,8 @@
 	@$(MAKEBOOT) clean
 	$(RM) arch/arm/lib/constants.h
 
+archmrproper:
+
 archdep:
 	@$(MAKEBOOT) dep
+sed -e /^MACHINE..*=/s,= .*,= rpc,;/^PROCESSOR..*=/s,= .*,= armv, linux/arch/arm/Makefile.normal
diff -u --recursive --new-file v2.1.100/linux/arch/arm/boot/tools/build.c linux/arch/arm/boot/tools/build.c
--- v2.1.100/linux/arch/arm/boot/tools/build.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/boot/tools/build.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <a.out.h>
+
+typedef unsigned char byte;
+typedef unsigned short word;
+typedef unsigned long u32;
+
+void die(const char * str, ...)
+{
+	va_list args;
+	va_start(args, str);
+	vfprintf(stderr, str, args);
+	fputc('\n', stderr);
+	exit (1);
+}
+
+int main(int argc, char **argv)
+{
+	void *data;
+	struct exec ex;
+	FILE *f;
+	int totlen;
+
+	if (argc < 2) {
+		fprintf(stderr, "Usage: build kernel-name\n");
+		exit(1);
+	}
+
+	f = fopen(argv[1], "rb");
+	if (!f)
+		die("Unable to open `%s': %m", argv[1]);
+
+	fread(&ex, 1, sizeof(ex), f);
+
+	if(N_MAGIC(ex) == ZMAGIC) {
+		fseek(f, 4096, SEEK_SET);
+		totlen = ex.a_text + ex.a_data;
+	} else
+	if(N_MAGIC(ex) == QMAGIC) {
+		unsigned long my_header;
+		
+		fseek(f, 4, SEEK_SET);
+
+		my_header = 0xea000006;
+
+		fwrite(&my_header, 4, 1, stdout);
+
+		totlen = ex.a_text + ex.a_data - 4;
+	} else {
+		fprintf(stderr, "Unacceptable a.out header on kernel\n");
+		fclose(f);
+		exit(1);
+	}
+
+	fprintf(stderr, "Kernel is %dk (%dk text, %dk data, %dk bss)\n",
+		(ex.a_text + ex.a_data + ex.a_bss)/1024,
+		 ex.a_text/1024, ex.a_data/1024, ex.a_bss/1024);
+
+	data = malloc(totlen);
+	fread(data, 1, totlen, f);
+	fwrite(data, 1, totlen, stdout);
+
+	free(data);
+	fclose(f);
+	fflush(stdout);
+	return 0;
+}
diff -u --recursive --new-file v2.1.100/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.1.100/linux/arch/arm/config.in	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/config.in	Fri May  8 00:42:38 1998
@@ -7,7 +7,7 @@
 define_bool CONFIG_ARM y
 
 mainmenu_option next_comment
-comment 'System type and processor type'
+comment 'System and processor type'
 choice 'ARM system type'	\
 	"Archimedes		CONFIG_ARCH_ARC \
 	 A5000			CONFIG_ARCH_A5K \
@@ -20,29 +20,55 @@
 else
   define_bool CONFIG_ARCH_ACORN n
 fi
-if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
+if [ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
   define_bool CONFIG_PCI y
 else
-  define_bool CONFIG_PCI n
+  if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
+    bool "PCI support" CONFIG_PCI
+  fi
 fi
-if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
-  define_bool CONFIG_CPU_SA110 y
+
+# Figure out whether this system uses 26-bit or 32-bit CPUs.  Nobody has
+# ever built a machine that can take both, and now that ARM3 is obsolete
+# nobody is likely to either.
+
+if [ "$CONFIG_ARCH_RPC" = "y" -o "$CONFIG_ARCH_NEXUSPCI" = "y" -o "$CONFIG_ARCH_EBSA110" = "y" -o "$CONFIG_ARCH_EBSA285" = "y" ]; then
+  define_bool CONFIG_CPU_32 y
+  define_bool CONFIG_CPU_26 n
 else
-  if [ "$CONFIG_ARCH_A5K" = "y" ]; then
-    define_bool CONFIG_CPU_ARM3 y
-  else
-    choice 'ARM cpu type'		\
-	"ARM2			CONFIG_CPU_ARM2 \
-	 ARM3			CONFIG_CPU_ARM3 \
-	 ARM6/7			CONFIG_CPU_ARM6 \
-	 StrongARM		CONFIG_CPU_SA110" StrongARM
+  if [ "$CONFIG_ARCH_ARC" = "y" -o "$CONFIG_ARCH_A5K" = "y" ]; then
+    define_bool CONFIG_CPU_32 n
+    define_bool CONFIG_CPU_26 y
   fi
 fi
+
+# Now allow the user to choose a more precise CPU.  This is only used to set
+# the flags we pass to GCC, not in any code.
+
+choice 'Optimise for CPU'		\
+	"ARM2		CONFIG_CPU_ARM2 \
+	 ARM3		CONFIG_CPU_ARM3 \
+	 ARM6		CONFIG_CPU_ARM6 \
+	 ARM7		CONFIG_CPU_ARM7 \
+	 SA110		CONFIG_CPU_SA110" ARM6
+
+if [ "$CONFIG_CPU_26" = "y" ]; then
+
+# For 26-bit CPUs, the page size changes with the amount of physical RAM!
+# The default is 4MB but if the user has less they have to own up to it here.
+
+  choice 'Physical memory size'		\
+	"4MB+		CONFIG_PAGESIZE_32	\
+	 2MB		CONFIG_PAGESIZE_16	\
+	 1MB/512K	CONFIG_PAGESIZE_8" 4MB+
+fi
 endmenu
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW
+bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
 endmenu
 
 mainmenu_option next_comment
@@ -56,33 +82,50 @@
 
 mainmenu_option next_comment
 comment 'General setup'
-bool 'Compile kernel with frame pointer (for useful debugging)' CONFIG_FRAME_POINTER
-bool 'Use new compilation options (for GCC 2.8)' CONFIG_BINUTILS_NEW
-bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
-# This needs kernel/acct.c to be updated
-#bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-#  tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
-  define_bool CONFIG_BINFMT_JAVA n
-fi
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
   dep_tristate '  PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
+  dep_tristate '  Archimedes hardware' CONFIG_PARPORT_ARC $CONFIG_PARPORT
+# If exactly one hardware type is selected then parport will optimise away
+# support for loading any others.  Defeat this if the user is keen.
+  if [ "$CONFIG_PARPORT_PC" = "n" -o "$CONFIG_PARPORT_ARC" = "n" ]; then
+    if [ "$CONFIG_PARPORT_PC" != "n" -o "$CONFIG_PARPORT_ARC" != "n" ]; then
+      bool '   Support foreign hardware' CONFIG_PARPORT_OTHER
+    fi
+  fi
 fi
 endmenu
 
 source arch/arm/drivers/block/Config.in
 source drivers/acorn/block/Config.in
 
+source arch/arm/drivers/char/Config.in
+bool 'Support Frame buffer devices' CONFIG_FB
+source drivers/video/Config.in
+
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
 fi
 
+if [ "$CONFIG_NET" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Network device support'
+
+  bool 'Network device support?' CONFIG_NETDEVICES
+  if [ "$CONFIG_NETDEVICES" = "y" ]; then
+    source drivers/net/Config.in
+  fi
+  endmenu
+fi
+
 mainmenu_option next_comment
 comment 'SCSI support'
 
@@ -93,13 +136,13 @@
 fi
 endmenu
 
-if [ "$CONFIG_NET" = "y" ]; then
+if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
   mainmenu_option next_comment
-  comment 'Network device support'
+  comment 'Sound'
 
-  bool 'Network device support?' CONFIG_NETDEVICES
-  if [ "$CONFIG_NETDEVICES" = "y" ]; then
-    source drivers/net/Config.in
+  tristate 'Sound support' CONFIG_SOUND
+  if [ "$CONFIG_SOUND" != "n" ]; then
+    source drivers/sound/Config.in
   fi
   endmenu
 fi
@@ -113,37 +156,14 @@
 # fi
 # endmenu
 
-# Conditionally compile in the Uniform CD-ROM driver
-if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" ]; then
-  define_bool CONFIG_CDROM y
-else
-  if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" ]; then
-    define_bool CONFIG_CDROM m
-  else
-    define_bool CONFIG_CDROM n
-  fi
-fi
-
 source fs/Config.in
 
 source fs/nls/Config.in
 
-source arch/arm/drivers/char/Config.in
-
-if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
-  mainmenu_option next_comment
-  comment 'Sound'
-
-  tristate 'Sound support' CONFIG_SOUND
-  if [ "$CONFIG_SOUND" != "n" ]; then
-    source drivers/sound/Config.in
-  fi
-  endmenu
-fi
-
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
+bool 'Debug kernel errors' CONFIG_DEBUG_ERRORS
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.1.100/linux/arch/arm/kernel/Makefile	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/Makefile	Fri May  8 00:42:38 1998
@@ -11,7 +11,7 @@
 O_TARGET := kernel.o
 O_OBJS   := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o signal.o sys_arm.o time.o traps.o
 
-all: kernel.o $(HEAD_OBJ) init_task.o
+all: lib kernel.o $(HEAD_OBJ) init_task.o
 
 ifeq ($(CONFIG_MODULES),y)
 OX_OBJS = armksyms.o
@@ -19,28 +19,31 @@
 O_OBJS += armksyms.o
 endif
 
-ifdef CONFIG_PCI
-  O_OBJS += bios32.o
-endif
-
 ifdef CONFIG_ARCH_ACORN
-  O_OBJS += setup.o ecard.o iic.o dma.o
+  O_OBJS += setup.o ecard.o iic.o
   ifdef CONFIG_ARCH_ARC
     O_OBJS += oldlatches.o
   endif
   O_OBJS += dma-$(MACHINE).o
+  OX_OBJS += dma.o
 endif
 
 ifeq ($(MACHINE),ebsa110)
-  O_OBJS += setup-ebsa110.o dma.o dma-dummy.o
+  O_OBJS += setup-ebsa110.o dma-dummy.o
 endif
 
 ifeq ($(MACHINE),ebsa285)
-  O_OBJS += dma.o dma-dummy.o leds-ebsa285.o setup-ebsa110.o
+  O_OBJS += dma-dummy.o leds-ebsa285.o setup-ebsa110.o
+  ifdef CONFIG_PCI
+    O_OBJS += dec21285.o
+  endif
 endif
 
 ifeq ($(MACHINE),nexuspci)
-  O_OBJS += setup-ebsa110.o
+  O_OBJS += setup-ebsa110.o dma-dummy.o
+  ifdef CONFIG_PCI
+    O_OBJS += plx9080.o
+  endif
 endif
 
 $(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
@@ -53,7 +56,7 @@
 
 $(ENTRY_OBJ): ../lib/constants.h
 
-.PHONY: ../lib/constants.h
+.PHONY: lib
 
-../lib/constants.h:
+lib:
 	$(MAKE) -C ../lib constants.h
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.1.100/linux/arch/arm/kernel/armksyms.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/armksyms.c	Fri May  8 00:42:38 1998
@@ -100,16 +100,6 @@
 EXPORT_SYMBOL(__bad_pmd);
 EXPORT_SYMBOL(__bad_pmd_kernel);
 
-/* dma */
-EXPORT_SYMBOL(dma_str);
-EXPORT_SYMBOL(enable_dma);
-EXPORT_SYMBOL(disable_dma);
-EXPORT_SYMBOL(set_dma_addr);
-EXPORT_SYMBOL(set_dma_count);
-EXPORT_SYMBOL(set_dma_mode);
-EXPORT_SYMBOL(get_dma_residue);
-EXPORT_SYMBOL(set_dma_sg);
-
 /*
  * floating point math emulator support.
  * These symbols will never change their calling convention...
@@ -155,12 +145,12 @@
 EXPORT_SYMBOL_NOVERS(memzero);
 
 	/* user mem (segment) */
-#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)
+#if defined(CONFIG_CPU_32)
 EXPORT_SYMBOL(__arch_copy_from_user);
 EXPORT_SYMBOL(__arch_copy_to_user);
 EXPORT_SYMBOL(__arch_clear_user);
 EXPORT_SYMBOL(__arch_strlen_user);
-#elif defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
+#elif defined(CONFIG_CPU_26)
 EXPORT_SYMBOL(uaccess_kernel);
 EXPORT_SYMBOL(uaccess_user);
 #endif
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.1.100/linux/arch/arm/kernel/bios32.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/bios32.c	Wed Dec 31 16:00:00 1969
@@ -1,144 +0,0 @@
-/*
- * arch/arm/kernel/bios32.c: PCI functions for ARM
- *
- * Copyright (C) 1998 Russell King
- */
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-int pcibios_present(void)
-{
-	return 1;
-}
-
-static unsigned long pcibios_base_address(unsigned char dev_fn)
-{
-	int slot = PCI_SLOT(dev_fn);
-
-	if (slot < 4)
-		return 0xf8000000 + (1 << (19 - slot));
-	else
-		return 0;
-}
-
-int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
-			     unsigned char where, unsigned char *val)
-{
-	unsigned long addr = pcibios_base_address(dev_fn);
-	unsigned char v;
-
-	if (addr) {
-		__asm__("ldr%?b	%0, [%1, %2]"
-			: "=r" (v)
-			: "r" (addr), "r" (where));
-		*val = v;
-	} else
-		*val = 0xff;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
-			     unsigned char where, unsigned short *val)
-{
-	unsigned long addr = pcibios_base_address(dev_fn);
-	unsigned short v;
-
-	if (addr) {
-		__asm__("ldrh%?	%0, [%1, %2]"
-			: "=r" (v)
-			: "r" (addr), "r" (where));
-		*val = v;
-	} else
-		*val = 0xffff;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
-			      unsigned char where, unsigned int *val)
-{
-	unsigned long addr = pcibios_base_address(dev_fn);
-	unsigned int v;
-
-	if (addr) {
-		__asm__("ldr%?	%0, [%1, %2]"
-			: "=r" (v)
-			: "r" (addr), "r" (where));
-		*val = v;
-	} else
-		*val = 0xffffffff;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
-			     unsigned char where, unsigned char val)
-{
-	unsigned long addr = pcibios_base_address(dev_fn);
-
-	if (addr)
-		__asm__("str%?b	%0, [%1, %2]"
-			: : "r" (val), "r" (addr), "r" (where));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
-			      unsigned char where, unsigned short val)
-{
-	unsigned long addr = pcibios_base_address(dev_fn);
-
-	if (addr)
-		__asm__("strh%?	%0, [%1, %2]"
-			: : "r" (val), "r" (addr), "r" (where));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
-			       unsigned char where, unsigned int val)
-{
-	unsigned long addr = pcibios_base_address(dev_fn);
-
-	if (addr)
-		__asm__("str%?	%0, [%1, %2]"
-			: : "r" (val), "r" (addr), "r" (where));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int irq[] = { 18, 8, 9, 11 };
-
-__initfunc(void pcibios_fixup(void))
-{
-	struct pci_dev *dev;
-	unsigned char pin;
-
-	for (dev = pci_devices; dev; dev = dev->next) {
-		pcibios_read_config_byte(dev->bus->number,
-					 dev->devfn,
-					 PCI_INTERRUPT_PIN,
-					 &pin);
-
-		dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3];
-
-		pcibios_write_config_byte(dev->bus->number,
-					  dev->devfn,
-					  PCI_INTERRUPT_LINE,
-					  dev->irq);
-
-		printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n",
-			dev->bus->number, dev->devfn,
-			dev->vendor, dev->device,
-			pin, dev->irq);
-	}
-}
-
-__initfunc(void pcibios_init(void))
-{
-	int rev;
-
-	rev = *(unsigned char *)0xfe000008;
-	printk("DEC21285 PCI revision %02X\n", rev);
-}
-
-__initfunc(char *pcibios_setup(char *str))
-{
-	return str;
-}
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S
--- v2.1.100/linux/arch/arm/kernel/calls.S	Wed Apr  8 19:36:24 1998
+++ linux/arch/arm/kernel/calls.S	Fri May  8 00:42:38 1998
@@ -190,7 +190,11 @@
 		.long	SYMBOL_NAME(sys_rt_sigsuspend_wrapper)
 /* 180 */	.long	SYMBOL_NAME(sys_pread)
 		.long	SYMBOL_NAME(sys_pwrite)
+#if 0
 		.long	SYMBOL_NAME(sys_xstat)
 		.long	SYMBOL_NAME(sys_xmknod)
+#else
+		.space	8
+#endif
 		.space	(NR_syscalls - 184) * 4
 #endif
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
--- v2.1.100/linux/arch/arm/kernel/dec21285.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/dec21285.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,145 @@
+/*
+ * arch/arm/kernel/dec21285.c: PCI functions for DEC 21285
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+int pcibios_present(void)
+{
+	return 1;
+}
+
+static unsigned long pcibios_base_address(unsigned char dev_fn)
+{
+	int slot = PCI_SLOT(dev_fn);
+
+	if (slot < 4)
+		return 0xf8000000 + (1 << (19 - slot));
+	else
+		return 0;
+}
+
+int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+			     unsigned char where, unsigned char *val)
+{
+	unsigned long addr = pcibios_base_address(dev_fn);
+	unsigned char v;
+
+	if (addr)
+		__asm__("ldr%?b	%0, [%1, %2]"
+			: "=r" (v)
+			: "r" (addr), "r" (where));
+	else
+		v = 0xff;
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+			     unsigned char where, unsigned short *val)
+{
+	unsigned long addr = pcibios_base_address(dev_fn);
+	unsigned short v;
+
+	if (addr)
+		__asm__("ldr%?h	%0, [%1, %2]"
+			: "=r" (v)
+			: "r" (addr), "r" (where));
+	else
+		v = 0xffff;
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+			      unsigned char where, unsigned int *val)
+{
+	unsigned long addr = pcibios_base_address(dev_fn);
+	unsigned int v;
+
+	if (addr)
+		__asm__("ldr%?	%0, [%1, %2]"
+			: "=r" (v)
+			: "r" (addr), "r" (where));
+	else
+		v = 0xffffffff;
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+			     unsigned char where, unsigned char val)
+{
+	unsigned long addr = pcibios_base_address(dev_fn);
+
+	if (addr)
+		__asm__("str%?b	%0, [%1, %2]"
+			: : "r" (val), "r" (addr), "r" (where));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+			      unsigned char where, unsigned short val)
+{
+	unsigned long addr = pcibios_base_address(dev_fn);
+
+	if (addr)
+		__asm__("str%?h	%0, [%1, %2]"
+			: : "r" (val), "r" (addr), "r" (where));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+			       unsigned char where, unsigned int val)
+{
+	unsigned long addr = pcibios_base_address(dev_fn);
+
+	if (addr)
+		__asm__("str%?	%0, [%1, %2]"
+			: : "r" (val), "r" (addr), "r" (where));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int irq[] = { 18, 8, 9, 11 };
+
+__initfunc(void pcibios_fixup(void))
+{
+	struct pci_dev *dev;
+	unsigned char pin;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		pcibios_read_config_byte(dev->bus->number,
+					 dev->devfn,
+					 PCI_INTERRUPT_PIN,
+					 &pin);
+
+		dev->irq = irq[(PCI_SLOT(dev->devfn) + pin) & 3];
+
+		pcibios_write_config_byte(dev->bus->number,
+					  dev->devfn,
+					  PCI_INTERRUPT_LINE,
+					  dev->irq);
+
+		printk("PCI: %02x:%02x [%04x/%04x] pin %d irq %d\n",
+			dev->bus->number, dev->devfn,
+			dev->vendor, dev->device,
+			pin, dev->irq);
+	}
+}
+
+__initfunc(void pcibios_init(void))
+{
+	int rev;
+
+	rev = *(unsigned char *)0xfe000008;
+	printk("DEC21285 PCI revision %02X\n", rev);
+}
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	return str;
+}
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dma-a5k.c linux/arch/arm/kernel/dma-a5k.c
--- v2.1.100/linux/arch/arm/kernel/dma-a5k.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/dma-a5k.c	Fri May  8 00:42:38 1998
@@ -11,12 +11,13 @@
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
+#include <asm/pgtable.h>
 
 #include "dma.h"
 
-int arch_request_dma(dmach_t channel, dma_t *dma)
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
 {
-	if (channel == DMA_VIRTUAL_FLOPPY0)
+	if (channel == DMA_VIRTUAL_FLOPPY)
 		return 0;
 	else
 		return -EINVAL;
@@ -24,14 +25,14 @@
 
 void arch_free_dma(dmach_t channel, dma_t *dma)
 {
-	if (channel != DMA_VIRTUAL_FLOPPY0)
+	if (channel != DMA_VIRTUAL_FLOPPY)
 		printk ("arch_free_dma: invalid channel %d\n", channel);
 }
 
 int arch_get_dma_residue(dmach_t channel, dma_t *dma)
 {
-	if (channel != DMA_VIRTUAL_FLOPPY0)
-		printk ("arch_dma_count: invalid channel %d\n", dmanr);
+	if (channel != DMA_VIRTUAL_FLOPPY)
+		printk ("arch_dma_count: invalid channel %d\n", channel);
 	else {
 		extern int floppy_fiqresidual(void);
 		return floppy_fiqresidual();
@@ -41,7 +42,7 @@
 
 void arch_enable_dma(dmach_t channel, dma_t *dma)
 {
-	if (channel != DMA_VIRTUAL_FLOPPY0)
+	if (channel != DMA_VIRTUAL_FLOPPY)
 		printk ("arch_enable_dma: invalid channel %d\n", channel);
 	else {
 		void *fiqhandler_start;
@@ -67,7 +68,7 @@
 
 void arch_disable_dma(dmach_t channel, dma_t *dma)
 {
-	if (channel != DMA_VIRTUAL_FLOPPY0)
+	if (channel != DMA_VIRTUAL_FLOPPY)
 		printk ("arch_disable_dma: invalid channel %d\n", channel);
 	else
 		disable_irq (dma->dma_irq);
@@ -75,5 +76,5 @@
 
 __initfunc(void arch_dma_init(dma_t *dma))
 {
-	dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
+	dma[DMA_VIRTUAL_FLOPPY].dma_irq = 64;
 }
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dma-dummy.c linux/arch/arm/kernel/dma-dummy.c
--- v2.1.100/linux/arch/arm/kernel/dma-dummy.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/dma-dummy.c	Fri May  8 00:42:38 1998
@@ -1,45 +1,28 @@
 /*
  * arch/arm/kernel/dma-dummy.c
  *
- * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998 Philip Blundell
+ * Copyright (c) 1998 Russell King
  *
  * Dummy DMA functions
  */
-#include <linux/sched.h>
+#include <linux/errno.h>
 #include <linux/init.h>
 
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/hardware.h>
-
-#include "dma.h"
-
-int arch_request_dma(dmach_t channel, dma_t *dma, const char *devname)
+int request_dma(int channel, const char *device_id)
 {
 	return -EINVAL;
 }
 
-void arch_free_dma(dmach_t channel, dma_t *dma)
-{
-	printk ("arch_free_dma: invalid channel %d\n", channel);
-}
-
-void arch_enable_dma(dmach_t channel, dma_t *dma)
-{
-	printk ("arch_enable_dma: invalid channel %d\n", channel);
-}
-
-void arch_disable_dma(dmach_t channel, dma_t *dma)
+void free_dma(int channel)
 {
-	printk ("arch_disable_dma: invalid channel %d\n", channel);
 }
 
-int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+int get_dma_list(char *buf)
 {
-	printk ("arch_get_dma_residue: invalid channel %d\n", channel);
 	return 0;
 }
 
-__initfunc(void arch_dma_init(dma_t *dma))
+__initfunc(void init_dma(void))
 {
 }
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c
--- v2.1.100/linux/arch/arm/kernel/dma.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/dma.c	Fri May  8 00:42:38 1998
@@ -15,6 +15,7 @@
  * Moved DMA resource allocation here...
  */
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <linux/malloc.h>
 #include <linux/mman.h>
 #include <linux/init.h>
@@ -28,6 +29,8 @@
 
 #include "dma.h"
 
+const char dma_str[] = "%s: dma %d not supported\n";
+
 static dma_t dma_chan[MAX_DMA_CHANNELS];
 
 /* Get dma list
@@ -182,6 +185,15 @@
 {
 	return arch_get_dma_residue(channel, &dma_chan[channel]);
 }
+
+EXPORT_SYMBOL(dma_str);
+EXPORT_SYMBOL(enable_dma);
+EXPORT_SYMBOL(disable_dma);
+EXPORT_SYMBOL(set_dma_addr);
+EXPORT_SYMBOL(set_dma_count);
+EXPORT_SYMBOL(set_dma_mode);
+EXPORT_SYMBOL(get_dma_residue);
+EXPORT_SYMBOL(set_dma_sg);
 
 __initfunc(void init_dma(void))
 {
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S
--- v2.1.100/linux/arch/arm/kernel/entry-armo.S	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/kernel/entry-armo.S	Fri May  8 00:42:38 1998
@@ -189,7 +189,7 @@
 		 */
 		.macro	adrsvc, cond, reg, label
 		adr\cond	\reg, \label
-		orr\cond	\reg, \reg, #3
+		orr\cond	\reg, \reg, #0x08000003
 		.endm
 
 #if 0
@@ -422,7 +422,7 @@
 		@ routine called with r0 = irq number, r1 = struct pt_regs *
 		@
 		adr	lr, 1b
-		orr	lr, lr, #3			@ Force SVC
+		orr	lr, lr, #0x08000003		@ Force SVC
 		bne	do_IRQ
 		b	ret_with_reschedule
 
@@ -442,7 +442,7 @@
 		@ routine called with r0 = irq number, r1 = struct pt_regs *
 		@
 		adr	lr, 1b
-		orr	lr, lr, #3			@ Force SVC
+		orr	lr, lr, #0x08000003		@ Force SVC
 		bne	do_IRQ				@ Returns to 1b
 		SVC_RESTORE_ALL
 
@@ -512,17 +512,11 @@
 		b	Ldata_ldcstc_pre	@ ldc	rd, [rn, #m]
 		b	Ldata_unknown
 Ldata_unknown:	@ Part of jumptable
-		ldr	r3, [sp, #15 * 4]
-		str	r3, [sp, #-4]!
-		mov	r1, r1, lsr #2
-		mov	r2, r0
-		mov	r3, r4
-		adr	r0, Ltt
-		bl	SYMBOL_NAME(printk)
-Llpxx:		b	Llpxx
-
-Ltt:		.ascii	"Unknown data abort code %d [pc=%p, *pc=%p]\nLR=%p\0"
-		.align
+		mov	r0, r1
+		mov	r1, r4
+		mov	r2, r3
+	mov r3, lr
+		b	baddataabort
 
 Ldata_ldrstr_post:
 		mov	r0, r4, lsr #14		@ Get Rn
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.1.100/linux/arch/arm/kernel/entry-armv.S	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/entry-armv.S	Fri May  8 00:42:38 1998
@@ -206,6 +206,26 @@
 		.macro	irq_prio_table
 		.endm
 
+#elif defined(CONFIG_ARCH_NEXUSPCI)
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base
+		ldr	r4, =0xffe00000
+		ldr	\irqstat, [r4, #0x180]		@ get interrupts
+		mov	\irqnr, #0
+1001:		tst	\irqstat, #1
+		addeq	\irqnr, \irqnr, #1
+		moveq	\irqstat, \irqstat, lsr #1
+		tsteq	\irqnr, #32
+		beq	1001b
+		teq	\irqnr, #32
+		.endm
+
+		.macro	irq_prio_table
+		.endm
+
 #else
 #error Unknown architecture
 #endif
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
--- v2.1.100/linux/arch/arm/kernel/entry-common.S	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/entry-common.S	Fri May  8 00:42:38 1998
@@ -207,6 +207,7 @@
  * 0x1c onwards is reserved for FIQ, so I think that I will allocate 0xe0 onwards for
  * the actuall address to jump to.
  */
+#if defined(CONFIG_CPU_32)
 /*
  * these go into 0x00
  */
@@ -237,13 +238,42 @@
 		initialise_traps_extra
 		mov	r0, #0xe4
 		adr	r1, .Ljump_addresses
-		ldmia	r1, {r1 - r6}
-		stmia	r0, {r1 - r6}
+		ldmia	r1, {r1 - r7}
+		stmia	r0, {r1 - r7}
 		mov	r0, #0
 		adr	r1, .Lbranches
 		ldmia	r1, {r1 - r7}
 		stmia	r0, {r1 - r7}
 		LOADREGS(fd, sp!, {r4 - r7, pc})
+#elif defined(CONFIG_CPU_26)
+.Ljump_addresses:
+		swi	SYS_ERROR0
+		.word	vector_undefinstr	- 12
+		.word	vector_swi		- 16
+		.word	vector_prefetch		- 20
+		.word	vector_data		- 24
+		.word	vector_addrexcptn	- 28
+		.word	vector_IRQ		- 32
+		.word	_unexp_fiq		- 36
+		b	. + 8
+/*
+ * initialise the trap system
+ */
+ENTRY(trap_init)
+		stmfd	sp!, {r4 - r7, lr}
+		adr	r1, .Ljump_addresses
+		ldmia	r1, {r1 - r7, ip, lr}
+		orr	r2, lr, r2, lsr #2
+		orr	r3, lr, r3, lsr #2
+		orr	r4, lr, r4, lsr #2
+		orr	r5, lr, r5, lsr #2
+		orr	r6, lr, r6, lsr #2
+		orr	r7, lr, r7, lsr #2
+		orr	ip, lr, ip, lsr #2
+		mov	r0, #0
+		stmia	r0, {r1 - r7, ip}
+		ldmfd	sp!, {r4 - r7, pc}^
+#endif
 
 /*============================================================================
  * FP support
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S
--- v2.1.100/linux/arch/arm/kernel/head-armv.S	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/head-armv.S	Fri May  8 00:42:38 1998
@@ -7,6 +7,9 @@
  */
 #include <linux/config.h>
 #include <linux/linkage.h>
+
+#define DEBUG
+
 		.text
 		.align
 
@@ -245,8 +248,11 @@
 		mov	fp, #0
 		b	SYMBOL_NAME(start_kernel)
 
-#if 1
-
+#ifdef DEBUG
+/*
+ * Some debugging routines (useful if you've got MM problems and
+ * printk isn't working).  For DEBUGGING ONLY!!!
+ */
 #if defined(CONFIG_ARCH_RPC)
 		.macro	addruart,rx
 		mov	\rx, #0xe0000000
@@ -309,6 +315,26 @@
 
 		.macro	waituart,rd,rx
 		.endm
+
+#elif defined(CONFIG_ARCH_NEXUSPCI)
+		.macro	addruart,rx
+		ldr	\rx, =0xfff00000
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0xc]
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #0x4]
+		tst	\rd, #1 << 0
+		bne	1001b
+		.endm
+
+		.macro	waituart,rd,rx
+		.endm
+#else
+#error Unknown architecture
 #endif
 
 /*
@@ -358,6 +384,8 @@
 		mov	r1, r0
 		mov	r0, #0
 		b	1b
+
+		.ltorg
 
 		.bss
 hexbuf:		.space 16
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.1.100/linux/arch/arm/kernel/process.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/process.c	Fri May  8 00:42:38 1998
@@ -112,9 +112,7 @@
 
 	flags = condition_codes(regs);
 
-	printk("\n"
-		"pc : [<%08lx>]\n"
-		"lr : [<%08lx>]\n"
+	printk( "pc : [<%08lx>]    lr : [<%08lx>]\n"
 		"sp : %08lx  ip : %08lx  fp : %08lx\n",
 		instruction_pointer(regs),
 		regs->ARM_lr, regs->ARM_sp,
@@ -133,22 +131,23 @@
 		flags & CC_Z_BIT ? 'Z' : 'z',
 		flags & CC_C_BIT ? 'C' : 'c',
 		flags & CC_V_BIT ? 'V' : 'v');
-	printk("  IRQs %s  FIQs %s  Mode %s\n",
+	printk("  IRQs %s  FIQs %s  Mode %s  Segment %s\n",
 		interrupts_enabled(regs) ? "on" : "off",
 		fast_interrupts_enabled(regs) ? "on" : "off",
-		processor_modes[processor_mode(regs)]);
-#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)
-{ int ctrl, transbase, dac;
-  __asm__ (
-"	mrc p15, 0, %0, c1, c0\n"
-"	mrc p15, 0, %1, c2, c0\n"
-"	mrc p15, 0, %2, c3, c0\n"
- : "=r" (ctrl), "=r" (transbase), "=r" (dac));
-  printk("Control: %04X  Table: %08X  DAC: %08X  ",
-  	ctrl, transbase, dac);
-  }
+		processor_modes[processor_mode(regs)],
+		get_fs() == get_ds() ? "kernel" : "user");
+#if defined(CONFIG_CPU_32)
+	{
+		int ctrl, transbase, dac;
+		  __asm__ (
+		"	mrc p15, 0, %0, c1, c0\n"
+		"	mrc p15, 0, %1, c2, c0\n"
+		"	mrc p15, 0, %2, c3, c0\n"
+		: "=r" (ctrl), "=r" (transbase), "=r" (dac));
+		printk("Control: %04X  Table: %08X  DAC: %08X\n",
+		  	ctrl, transbase, dac);
+	}
 #endif
-  	printk ("Segment %s\n", get_fs() == get_ds() ? "kernel" : "user");
 }
 
 /*
@@ -172,7 +171,15 @@
 	current->flags &= ~PF_USEDFPU;
 }
 
+void release_segments(struct mm_struct *mm)
+{
+}
+
 void release_thread(struct task_struct *dead_task)
+{
+}
+
+void copy_segments(int nr, struct task_struct *p, struct mm_struct *new_mm)
 {
 }
 
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/setup-ebsa110.c linux/arch/arm/kernel/setup-ebsa110.c
--- v2.1.100/linux/arch/arm/kernel/setup-ebsa110.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/setup-ebsa110.c	Fri May  8 00:42:38 1998
@@ -18,7 +18,6 @@
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/ldt.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
@@ -30,6 +29,7 @@
 
 #include <asm/hardware.h>
 #include <asm/pgtable.h>
+#include <asm/procinfo.h>
 #include <asm/segment.h>
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -41,17 +41,25 @@
 
 #define MEM_SIZE	(16*1024*1024)
 
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
-       char saved_command_line[COMMAND_LINE_SIZE];
-
-struct processor processor;
 struct screen_info screen_info;
+struct processor processor;
 unsigned char aux_device_present;
+
+extern const struct processor sa110_processor_functions;
+
+struct armversions armidlist[] = {
+	{ 0x4401a100, 0xfffffff0, F_MMU|F_32BIT	, "DEC",	"sa110"		, &sa110_processor_functions  , "sa1x"},
+	{ 0x00000000, 0x00000000, 0		, "***",	"*unknown*"	, NULL			      , NULL  }
+};
+
 unsigned long arm_id;
+int armidindex;
 
 extern int root_mountflags;
 extern int _etext, _edata, _end;
-extern const struct processor sa110_processor_functions;
+
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+       char saved_command_line[COMMAND_LINE_SIZE];
 
 #ifdef CONFIG_BLK_DEV_RAM
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
@@ -110,6 +118,8 @@
 	int len = 0;
 
 	memory_start = (unsigned long)&_end;
+
+	armidindex = 0;
 
 	processor = sa110_processor_functions;
 	processor._proc_init();
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.1.100/linux/arch/arm/kernel/setup.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/setup.c	Fri May  8 00:42:38 1998
@@ -50,19 +50,18 @@
 extern const struct processor sa110_processor_functions;
 
 struct armversions armidlist[] = {
-#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
-	{ 0x41560200, 0xfffffff0, F_MEMC	, "ARM/VLSI",	"arm2"		, &arm2_processor_functions   },
-	{ 0x41560250, 0xfffffff0, F_MEMC	, "ARM/VLSI",	"arm250"	, &arm250_processor_functions },
-	{ 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, "ARM/VLSI",	"arm3"		, &arm3_processor_functions   },
+#if defined(CONFIG_CPU_26)
+	{ 0x41560200, 0xfffffff0, F_MEMC	, "ARM/VLSI",	"arm2"		, &arm2_processor_functions   , "arm2"},
+	{ 0x41560250, 0xfffffff0, F_MEMC	, "ARM/VLSI",	"arm250"	, &arm250_processor_functions , "arm3"},
+	{ 0x41560300, 0xfffffff0, F_MEMC|F_CACHE, "ARM/VLSI",	"arm3"		, &arm3_processor_functions   , "arm3"},
+#elif defined(CONFIG_CPU_32)
+	{ 0x41560600, 0xfffffff0, F_MMU|F_32BIT	, "ARM/VLSI",	"arm6"		, &arm6_processor_functions   , "arm6"},
+	{ 0x41560610, 0xfffffff0, F_MMU|F_32BIT	, "ARM/VLSI",	"arm610"	, &arm6_processor_functions   , "arm6"},
+	{ 0x41007000, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI",   "arm7"		, &arm7_processor_functions   , "arm6"},
+	{ 0x41007100, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI",   "arm710"	, &arm7_processor_functions   , "arm6"},
+	{ 0x4401a100, 0xfffffff0, F_MMU|F_32BIT	, "DEC",	"sa110"		, &sa110_processor_functions  , "sa1x"},
 #endif
-#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)
-	{ 0x41560600, 0xfffffff0, F_MMU|F_32BIT	, "ARM/VLSI",	"arm6"		, &arm6_processor_functions   },
-	{ 0x41560610, 0xfffffff0, F_MMU|F_32BIT	, "ARM/VLSI",	"arm610"	, &arm6_processor_functions   },
-	{ 0x41007000, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI",   "arm7"		, &arm7_processor_functions   },
-	{ 0x41007100, 0xffffff00, F_MMU|F_32BIT , "ARM/VLSI",   "arm710"	, &arm7_processor_functions   },
-	{ 0x4401a100, 0xfffffff0, F_MMU|F_32BIT	, "DEC",	"sa110"		, &sa110_processor_functions  },
-#endif
-	{ 0x00000000, 0x00000000, 0		, "***",	"*unknown*"	, NULL }
+	{ 0x00000000, 0x00000000, 0		, "***",	"*unknown*"	, NULL			      , NULL  }
 };
 
 static struct param_struct *params = (struct param_struct *)PARAMS_BASE;
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c
--- v2.1.100/linux/arch/arm/kernel/signal.c	Mon Feb 23 18:12:01 1998
+++ linux/arch/arm/kernel/signal.c	Fri May  8 00:42:38 1998
@@ -154,7 +154,7 @@
 	__get_user(regs->ARM_sp, &sc->arm_sp);
 	__get_user(regs->ARM_lr, &sc->arm_lr);
 	__get_user(regs->ARM_pc, &sc->arm_pc);		/* security! */
-#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)
+#ifdef CONFIG_CPU_32
 	__get_user(regs->ARM_cpsr, &sc->arm_cpsr);	/* security! */
 #endif
 
@@ -238,7 +238,7 @@
 	__put_user (regs->ARM_sp, &sc->arm_sp);
 	__put_user (regs->ARM_lr, &sc->arm_lr);
 	__put_user (regs->ARM_pc, &sc->arm_pc);		/* security! */
-#if defined(CONFIG_CPU_ARM6) || defined(CONFIG_CPU_SA110)
+#ifdef CONFIG_CPU_32
 	__put_user (regs->ARM_cpsr, &sc->arm_cpsr);	/* security! */
 #endif
 
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.1.100/linux/arch/arm/kernel/sys_arm.c	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/kernel/sys_arm.c	Fri May  8 00:42:38 1998
@@ -30,8 +30,6 @@
  */
 /* proc/system.h */
 const char xchg_str[] = "xchg";
-/* arch/dma.h */
-const char dma_str[] = "%s: dma %d not supported\n";
 
 /*
  * sys_pipe() is the normal C calling standard for creating
diff -u --recursive --new-file v2.1.100/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.1.100/linux/arch/arm/kernel/traps.c	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/kernel/traps.c	Fri May  8 00:42:38 1998
@@ -49,7 +49,7 @@
 
 static int verify_stack_pointer (unsigned long stackptr, int size)
 {
-#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
+#ifdef CONFIG_CPU_26
 	if (stackptr < 0x02048000 || stackptr + size > 0x03000000)
         	return -EFAULT;
 #else
@@ -90,38 +90,52 @@
 #define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
-static void dump_instr (unsigned long pc)
+static void dump_instr(unsigned long pc, int user)
 {
 	unsigned long module_start, module_end;
 	int pmin = -2, pmax = 3, ok = 0;
 	extern char start_kernel, _etext;
 
-	module_start = VMALLOC_START;
-	module_end   = module_start + MODULE_RANGE;
+	if (!user) {
+		module_start = VMALLOC_START;
+		module_end   = module_start + MODULE_RANGE;
+
+		if ((pc >= (unsigned long) &start_kernel) &&
+		    (pc <= (unsigned long) &_etext)) {
+			if (pc + pmin < (unsigned long) &start_kernel)
+				pmin = ((unsigned long) &start_kernel) - pc;
+			if (pc + pmax > (unsigned long) &_etext)
+				pmax = ((unsigned long) &_etext) - pc;
+			ok = 1;
+		} else if (pc >= module_start && pc <= module_end) {
+			if (pc + pmin < module_start)
+				pmin = module_start - pc;
+			if (pc + pmax > module_end)
+				pmax = module_end - pc;
+			ok = 1;
+		}
+	} else
+		ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0;
 
-	if ((pc >= (unsigned long) &start_kernel) &&
-	    (pc <= (unsigned long) &_etext)) {
-		if (pc + pmin < (unsigned long) &start_kernel)
-			pmin = ((unsigned long) &start_kernel) - pc;
-		if (pc + pmax > (unsigned long) &_etext)
-			pmax = ((unsigned long) &_etext) - pc;
-		ok = 1;
-	} else if (pc >= module_start && pc <= module_end) {
-		if (pc + pmin < module_start)
-			pmin = module_start - pc;
-		if (pc + pmax > module_end)
-			pmax = module_end - pc;
-		ok = 1;
-	}
 	printk ("Code: ");
 	if (ok) {
 		int i;
 		for (i = pmin; i < pmax; i++)
-			printk("%08lx ", ((unsigned long *)pc)[i]);
+			printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]);
 		printk ("\n");
 	} else
 		printk ("pc not in code space\n");
-}	
+}
+
+static void dump_state(char *str, struct pt_regs *regs, int err)
+{
+	console_verbose();
+	printk("Internal error: %s: %x\n", str, err);
+	printk("CPU: %d\n", smp_processor_id());
+	show_regs(regs);
+	printk("Process %s (pid: %d, stackpage=%08lx)\n",
+		current->comm, current->pid, 4096+(unsigned long)current);
+}
 
 /*
  * This function is protected against kernel-mode re-entrancy.  If it
@@ -149,12 +163,7 @@
 		break;
 	}
 
-	console_verbose();
-	printk("Internal error: %s: %x\n", str, err);
-	printk("CPU: %d", smp_processor_id());
-	show_regs(regs);
-	printk("Process %s (pid: %d, stackpage=%08lx)\n",
-		current->comm, current->pid, 4096+(unsigned long)current);
+	dump_state(str, regs, err);
 
 	cstack = (unsigned long)(regs + 1);
 	sstack = 4096+(unsigned long)current;
@@ -180,7 +189,7 @@
 		}
 	}
 
-	dump_instr(instruction_pointer(regs));
+	dump_instr(instruction_pointer(regs), 0);
 	died = 0;
 	if (ret != -1)
 		do_exit (ret);
@@ -268,13 +277,13 @@
 {
 	switch (no) {
 	case 0: /* branch through 0 */
-		printk ("[%d] %s: branch through zero\n", current->pid, current->comm);
-		force_sig (SIGILL, current);
-		if (user_mode(regs)) {
-			show_regs (regs);
-			c_backtrace (regs->ARM_fp, processor_mode(regs));
-		}
-		die_if_kernel ("Oops", regs, 0, SIGILL);
+		force_sig(SIGSEGV, current);
+//		if (user_mode(regs)) {
+//			dump_state("branch through zero", regs, 0);
+//			if (regs->ARM_fp)
+//				c_backtrace (regs->ARM_fp, processor_mode(regs));
+//		}
+		die_if_kernel ("branch through zero", regs, 0, SIGSEGV);
 		break;
 
 	case 1: /* SWI_BREAK_POINT */
@@ -297,8 +306,7 @@
 
 asmlinkage void deferred(int n, struct pt_regs *regs)
 {
-	printk ("[%d] %s: old system call %X\n", current->pid, current->comm, n);
-	show_regs (regs);
+	dump_state("old system call", regs, 0);
 	force_sig (SIGILL, current);
 }
 
@@ -312,3 +320,37 @@
 	printk ("Invalid pointer size in %s (PC=%p) size %d\n",
 		function, __builtin_return_address(0), size);
 }
+
+#ifdef CONFIG_CPU_26
+asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs)
+{
+	unsigned long phys, addr = instruction_pointer(regs);
+
+#ifdef CONFIG_DEBUG_ERRORS
+	printk("pid=%d\n", current->pid);
+
+	show_regs(regs);
+	dump_instr(instruction_pointer(regs), 1);
+	{
+		pgd_t *pgd;
+
+		printk ("current->tss.memmap = %08lX\n", current->tss.memmap);
+		pgd = pgd_offset(current->mm, addr);
+		printk ("*pgd = %08lx", pgd_val (*pgd));
+		if (!pgd_none (*pgd)) {
+			pmd_t *pmd;
+			pmd = pmd_offset (pgd, addr);
+			printk (", *pmd = %08lx", pmd_val (*pmd));
+			if (!pmd_none (*pmd)) {
+				unsigned long ptr = pte_page(*pte_offset(pmd, addr));
+				printk (", *pte = %08lx", pte_val (*pte_offset (pmd, addr)));
+				phys = ptr + (addr & 0x7fff);
+			}
+		}
+		printk ("\n");
+	}
+#endif
+	panic("unknown data abort code %d [pc=%08lx *pc=%08lx lr=%08lx sp=%08lx]",
+		code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp);
+}
+#endif
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.1.100/linux/arch/arm/lib/Makefile	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/lib/Makefile	Fri May  8 00:42:38 1998
@@ -6,7 +6,7 @@
 
 L_TARGET := lib.a
 L_OBJS   := backtrace.o bitops.o checksum.o delay.o fp_support.o \
-	    loaders.o memcpy.o memfastset.o system.o string.o uaccess.o
+	    loaders.o memcpy.o system.o string.o uaccess.o
 
 ifeq ($(PROCESSOR),armo)
   L_OBJS += uaccess-armo.o
@@ -37,6 +37,8 @@
 
 getconsdata.o: getconsdata.c
 	$(CC) $(CFLAGS) -c getconsdata.c
+
+checksum.o: constants.h
 
 %.o: %.S
 ifneq ($(CONFIG_BINUTILS_NEW),y)
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/backtrace.S linux/arch/arm/lib/backtrace.S
--- v2.1.100/linux/arch/arm/lib/backtrace.S	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/lib/backtrace.S	Fri May  8 00:42:38 1998
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1995, 1996 Russell King
  */
+#include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 		.text
@@ -21,9 +22,13 @@
 
 ENTRY(c_backtrace)
 		stmfd	sp!, {r4 - r8, lr}	@ Save an extra register so we have a location...
+#ifdef CONFIG_CPU_32
 		tst	r1, #0x10		@ 26 or 32-bit?
 		moveq	mask, #0xfc000003
 		movne	mask, #0
+#else
+		mov	mask, #0xfc000003
+#endif
 		tst	mask, r0
 		movne	r0, #0
 		movs	frame, r0
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/checksum.S linux/arch/arm/lib/checksum.S
--- v2.1.100/linux/arch/arm/lib/checksum.S	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/lib/checksum.S	Fri May  8 00:42:38 1998
@@ -3,9 +3,11 @@
  *
  * Copyright (C) 1995, 1996, 1997, 1998 Russell King
  */
+#include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
+#include "constants.h"
 
 		.text
 
@@ -66,25 +68,147 @@
  * Params  : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err
  * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
  */
+#if defined(CONFIG_CPU_32)
 
-#define USER_LDR(instr...)			\
-9999:		instr;				\
-		.section __ex_table, "a";	\
-		.align	3;			\
-		.long	9999b, 6001f;		\
-		.previous;
+		.macro	save_regs
+		stmfd	sp!, {r4 - r8, fp, ip, lr, pc}
+		.endm
+
+#define LOAD_REGS(cond)					\
+		LOADREGS(##cond##ea,fp,{r4 - r8, fp, sp, pc})
+
+		.macro	load1b,	reg1
+9999:		ldrbt	\reg1, [r0], $1
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2b, reg1, reg2
+9999:		ldrbt	\reg1, [r0], $1
+9998:		ldrbt	\reg2, [r0], $1
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load1l, reg1
+9999:		ldrt	\reg1, [r0], $4
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2l, reg1, reg2
+9999:		ldrt	\reg1, [r0], $4
+9998:		ldrt	\reg2, [r0], $4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load4l, reg1, reg2, reg3, reg4
+9999:		ldrt	\reg1, [r0], $4
+9998:		ldrt	\reg2, [r0], $4
+9997:		ldrt	\reg3, [r0], $4
+9996:		ldrt	\reg4, [r0], $4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.long	9997b, 6001f
+		.long	9996b, 6001f
+		.previous
+		.endm
+
+#elif defined(CONFIG_CPU_26)
+
+		.macro	save_regs
+		stmfd	sp!, {r4 - r9, fp, ip, lr, pc}
+		mov	r9, sp, lsr #13
+		mov	r9, r9, lsl #13
+		ldr	r9, [r9, #TSK_ADDR_LIMIT]
+		mov	r9, r9, lsr #24
+		.endm
+
+#define LOAD_REGS(cond)					\
+		LOADREGS(##cond##ea,fp,{r4 - r9, fp, sp, pc})
+
+		.macro	load1b,	reg1
+		tst	r9, #0x01
+9999:		ldreqbt	\reg1, [r0], #1
+		ldrneb	\reg1, [r0], #1
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2b, reg1, reg2
+		tst	r9, #0x01
+9999:		ldreqbt	\reg1, [r0], #1
+		ldrneb	\reg1, [r0], #1
+9998:		ldreqbt	\reg2, [r0], #1
+		ldrneb	\reg2, [r0], #1
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load1l, reg1
+		tst	r9, #0x01
+9999:		ldreqt	\reg1, [r0], #4
+		ldrne	\reg1, [r0], #4
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2l, reg1, reg2
+		tst	r9, #0x01
+		ldmneia	r0!, {\reg1, \reg2}
+9999:		ldreqt	\reg1, [r0], #4
+9998:		ldreqt	\reg2, [r0], #4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load4l, reg1, reg2, reg3, reg4
+		tst	r9, #0x01
+		ldmneia	r0!, {\reg1, \reg2, \reg3, \reg4}
+9999:		ldreqt	\reg1, [r0], #4
+9998:		ldreqt	\reg2, [r0], #4
+9997:		ldreqt	\reg3, [r0], #4
+9996:		ldreqt	\reg4, [r0], #4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.long	9997b, 6001f
+		.long	9996b, 6001f
+		.previous
+		.endm
+
+#else
+#error Unknown CPU architecture
+#endif
 
 ENTRY(csum_partial_copy_from_user)
 		mov	ip, sp
-		stmfd	sp!, {r4 - r8, fp, ip, lr, pc}
+		save_regs
 		sub	fp, ip, #4
 		cmp	r2, #4
 		blt	.too_small_user
 		tst	r1, #2			@ Test destination alignment
 		beq	.dst_aligned_user
 		subs	r2, r2, #2		@ We dont know if SRC is aligned...
-USER_LDR(	ldrbt	ip, [r0], #1)
-USER_LDR(	ldrbt	r8, [r0], #1)
+		load2b	ip, r8
 		orr	ip, ip, r8, lsl #8
 		adds	r3, r3, ip
 		adcs	r3, r3, #0
@@ -97,11 +221,7 @@
 		adds	r3, r3, #0
 		bics	ip, r2, #15		@ Routine for src & dst aligned
 		beq	2f
-1:
-USER_LDR(	ldrt	r4, [r0], #4)
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
-USER_LDR(	ldrt	r7, [r0], #4)
+1:		load4l	r4, r5, r6, r7
 		stmia	r1!, {r4, r5, r6, r7}
 		adcs	r3, r3, r4
 		adcs	r3, r3, r5
@@ -114,21 +234,19 @@
 		beq	4f
 		tst	ip, #8
 		beq	3f
-USER_LDR(	ldrt	r4, [r0], #4)
-USER_LDR(	ldrt	r5, [r0], #4)
+		load2l	r4, r5
 		stmia	r1!, {r4, r5}
 		adcs	r3, r3, r4
 		adcs	r3, r3, r5
 		tst	ip, #4
 		beq	4f
-3:
-USER_LDR(	ldrt	r4, [r0], #4)
+3:		load1l	r4
 		str	r4, [r1], #4
 		adcs	r3, r3, r4
 4:		ands	r2, r2, #3
 		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-USER_LDR(	ldrt	r4, [r0], #4)
+		LOAD_REGS(eq)
+		load1l	r4
 		tst	r2, #2
 		beq	.exit
 		adcs	r3, r3, r4, lsl #16
@@ -141,33 +259,33 @@
 		andne	r4, r4, #255
 		adcnes	r3, r3, r4
 		adcs	r0, r3, #0
-		LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
+		LOAD_REGS(al)
 
 .too_small_user:
 		teq	r2, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		LOAD_REGS(eq)
 		cmp	r2, #2
 		blt	.too_small_user1
-USER_LDR(	ldrbt	ip, [r0], #1)
-USER_LDR(	ldrbt	r8, [r0], #1)
+		load2b	ip, r8
 		orr	ip, ip, r8, lsl #8
 		adds	r3, r3, ip
 		strb	ip, [r1], #1
 		strb	r8, [r1], #1
 		tst	r2, #1
-.too_small_user1:
-USER_LDR(	ldrnebt	ip, [r0], #1)
-		strneb	ip, [r1], #1
-		adcnes	r3, r3, ip
-		adcs	r0, r3, #0
-		LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
+.too_small_user1:				@ C = 0
+		beq	.csum_exit
+		load1b	ip
+		strb	ip, [r1], #1
+		adcs	r3, r3, ip
+.csum_exit:	adc	r0, r3, #0
+		LOAD_REGS(al)
 
 .src_not_aligned_user:
 		cmp	r2, #4
 		blt	.too_small_user
 		and	ip, r0, #3
 		bic	r0, r0, #3
-USER_LDR(	ldrt	r4, [r0], #4)
+		load1l	r4
 		cmp	ip, #2
 		beq	.src2_aligned_user
 		bhi	.src3_aligned_user
@@ -175,11 +293,7 @@
 		adds	r3, r3, #0
 		bics	ip, r2, #15
 		beq	2f
-1:
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
-USER_LDR(	ldrt	r7, [r0], #4)
-USER_LDR(	ldrt	r8, [r0], #4)
+1:		load4l	r5, r6, r7, r8
 		orr	r4, r4, r5, lsl #24
 		mov	r5, r5, lsr #8
 		orr	r5, r5, r6, lsl #24
@@ -200,8 +314,7 @@
 		beq	4f
 		tst	ip, #8
 		beq	3f
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
+		load2l	r5, r6
 		orr	r4, r4, r5, lsl #24
 		mov	r5, r5, lsr #8
 		orr	r5, r5, r6, lsl #24
@@ -211,15 +324,14 @@
 		mov	r4, r6, lsr #8
 		tst	ip, #4
 		beq	4f
-3:
-USER_LDR(	ldrt	r5, [r0], #4)
+3:		load1l	r5
 		orr	r4, r4, r5, lsl #24
 		str	r4, [r1], #4
 		adcs	r3, r3, r4
 		mov	r4, r5, lsr #8
 4:		ands	r2, r2, #3
 		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		LOAD_REGS(eq)
 		tst	r2, #2
 		beq	.exit
 		adcs	r3, r3, r4, lsl #16
@@ -234,11 +346,7 @@
 		adds	r3, r3, #0
 		bics	ip, r2, #15
 		beq	2f
-1:
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
-USER_LDR(	ldrt	r7, [r0], #4)
-USER_LDR(	ldrt	r8, [r0], #4)
+1:		load4l	r5, r6, r7, r8
 		orr	r4, r4, r5, lsl #16
 		mov	r5, r5, lsr #16
 		orr	r5, r5, r6, lsl #16
@@ -259,8 +367,7 @@
 		beq	4f
 		tst	ip, #8
 		beq	3f
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
+		load2l	r5, r6
 		orr	r4, r4, r5, lsl #16
 		mov	r5, r5, lsr #16
 		orr	r5, r5, r6, lsl #16
@@ -270,22 +377,21 @@
 		mov	r4, r6, lsr #16
 		tst	ip, #4
 		beq	4f
-3:
-USER_LDR(	ldrt	r5, [r0], #4)
+3:		load1l	r5
 		orr	r4, r4, r5, lsl #16
 		str	r4, [r1], #4
 		adcs	r3, r3, r4
 		mov	r4, r5, lsr #16
 4:		ands	r2, r2, #3
 		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		LOAD_REGS(eq)
 		tst	r2, #2
 		beq	.exit
 		adcs	r3, r3, r4, lsl #16
 		strb	r4, [r1], #1
 		mov	r4, r4, lsr #8
 		strb	r4, [r1], #1
-USER_LDR(	ldrb	r4, [r0], #1)
+		load1b	r4
 		b	.exit
 
 .src3_aligned_user:
@@ -293,11 +399,7 @@
 		adds	r3, r3, #0
 		bics	ip, r2, #15
 		beq	2f
-1:
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
-USER_LDR(	ldrt	r7, [r0], #4)
-USER_LDR(	ldrt	r8, [r0], #4)
+1:		load4l	r5, r6, r7, r8
 		orr	r4, r4, r5, lsl #8
 		mov	r5, r5, lsr #24
 		orr	r5, r5, r6, lsl #8
@@ -318,8 +420,7 @@
 		beq	4f
 		tst	ip, #8
 		beq	3f
-USER_LDR(	ldrt	r5, [r0], #4)
-USER_LDR(	ldrt	r6, [r0], #4)
+		load2l	r5, r6
 		orr	r4, r4, r5, lsl #8
 		mov	r5, r5, lsr #24
 		orr	r5, r5, r6, lsl #8
@@ -329,20 +430,19 @@
 		mov	r4, r6, lsr #24
 		tst	ip, #4
 		beq	4f
-3:
-USER_LDR(	ldrt	r5, [r0], #4)
+3:		load1l	r5
 		orr	r4, r4, r5, lsl #8
 		str	r4, [r1], #4
 		adcs	r3, r3, r4
 		mov	r4, r5, lsr #24
 4:		ands	r2, r2, #3
 		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		LOAD_REGS(eq)
 		tst	r2, #2
 		beq	.exit
 		adcs	r3, r3, r4, lsl #16
 		strb	r4, [r1], #1
-USER_LDR(	ldrt	r4, [r0], #4)
+		load1l	r4
 		strb	r4, [r1], #1
 		adcs	r3, r3, r4, lsl #24
 		mov	r4, r4, lsr #8
@@ -351,14 +451,16 @@
 		.section .fixup,"ax"
 		.align	4
 6001:		mov	r4, #-EFAULT
-		ldr	r5, [sp, #4*8]
+		ldr	r5, [fp, #4]
 		str	r4, [r5]
-		LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
+		LOAD_REGS(al)
+		.previous
 
 /* Function: __u32 csum_partial_copy (const char *src, char *dst, int len, __u32 sum)
  * Params  : r0 = src, r1 = dst, r2 = len, r3 = checksum
  * Returns : r0 = new checksum
  */
+ENTRY(csum_partial_copy_nocheck)
 ENTRY(csum_partial_copy)
 		mov	ip, sp
 		stmfd	sp!, {r4 - r8, fp, ip, lr, pc}
@@ -598,3 +700,21 @@
 		adcs	r3, r3, r4, lsl #24
 		mov	r4, r4, lsr #8
 		b	Lexit
+
+ENTRY(csum_ipv6_magic)
+		stmfd	sp!, {lr}
+		adds	ip, r2, r3
+		ldmia	r1, {r1 - r3, lr}
+		adcs	ip, ip, r1
+		adcs	ip, ip, r2
+		adcs	ip, ip, r3
+		adcs	ip, ip, lr
+		ldmia	r0, {r0 - r3}
+		adcs	r0, ip, r0
+		adcs	r0, r0, r1
+		adcs	r0, r0, r2
+		adcs	r0, r0, r3
+		ldr	r3, [sp, #4]
+		adcs	r0, r0, r3
+		adcs	r0, r0, #0
+		LOADREGS(fd, sp!, {pc})
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/extractconstants.pl linux/arch/arm/lib/extractconstants.pl
--- v2.1.100/linux/arch/arm/lib/extractconstants.pl	Tue Apr 14 14:29:19 1998
+++ linux/arch/arm/lib/extractconstants.pl	Fri May  8 00:42:38 1998
@@ -34,7 +34,7 @@
 	if ($elf) {
 		chomp;
 		$addr = substr ($_, 0, 8);
-		$name = substr ($_, 32);
+		$name = substr ($_, rindex($_, " ") + 1);
 		$nam[hex($addr)] = $name;
 	}
 }
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/extractinfo.perl linux/arch/arm/lib/extractinfo.perl
--- v2.1.100/linux/arch/arm/lib/extractinfo.perl	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/extractinfo.perl	Fri May  8 00:42:38 1998
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+
+$OBJDUMP=$ARGV[0];
+
+sub swapdata {
+	local ($num) = @_;
+
+	return substr($num, 6, 2).substr($num, 4, 2).substr ($num, 2, 2).substr ($num, 0, 2);
+}
+
+open (DATA, $OBJDUMP.' --full-contents --section=.data getconsdata.o | grep \'^ 00\' |') ||
+	die ('Cant objdump!');
+while (<DATA>) {
+	($addr, $data0, $data1, $data2, $data3) = split (' ');
+	$dat[hex($addr)] = hex(&swapdata($data0));
+	$dat[hex($addr)+4] = hex(&swapdata($data1));
+	$dat[hex($addr)+8] = hex(&swapdata($data2));
+	$dat[hex($addr)+12] = hex(&swapdata($data3));
+}
+close (DATA);
+
+open (DATA, $OBJDUMP.' --syms getconsdata.o |') || die ('Cant objdump!');
+while (<DATA>) {
+	/elf32/ && ( $elf = 1 );
+	/a.out/ && ( $aout = 1 );
+	next if ($aout && ! / 07 /);
+	next if ($elf && ! (/^00...... g/ && /.data/));
+	next if (!$aout && !$elf);
+
+	($addr, $flags, $sect, $a1, $a2, $a3, $name) = split (' ') if $aout;
+	$nam[hex($addr)] = substr($name, 1) if $aout;
+	if ($elf) {
+		chomp;
+		$addr = substr ($_, 0, 8);
+		$name = substr ($_, 32);
+		$nam[hex($addr)] = $name;
+	}
+}
+close (DATA);
+
+print "/*\n * *** THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT! ***\n */\n";
+for ($i = 0; $i < hex($addr)+12; $i ++) {
+	print "unsigned long $nam[$i] = $dat[$i];\n" if $dat[$i];
+	print "#define __HAS_$nam[$i]\n" if $dat[$i];
+}
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/getconsdata.c linux/arch/arm/lib/getconsdata.c
--- v2.1.100/linux/arch/arm/lib/getconsdata.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/lib/getconsdata.c	Fri May  8 00:42:38 1998
@@ -10,6 +10,8 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 
+#undef PAGE_READONLY
+
 #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n)
 #define OFF_MM(n) (unsigned long)&(((struct mm_struct *)0)->n)
 
@@ -31,7 +33,7 @@
 unsigned long TSS_MEMMAP = OFF_TSK(tss.memmap);
 unsigned long TSS_SAVE = OFF_TSK(tss.save);
 unsigned long TSS_FPESAVE = OFF_TSK(tss.fpstate.soft.save);
-#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
+#ifdef CONFIG_CPU_26
 unsigned long TSS_MEMCMAP = OFF_TSK(tss.memcmap);
 #endif
 
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/getconstants.c linux/arch/arm/lib/getconstants.c
--- v2.1.100/linux/arch/arm/lib/getconstants.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/getconstants.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,74 @@
+/*
+ * linux/arch/arm/lib/getconstants.c
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+#include <stdio.h>
+#include <linux/unistd.h>
+
+void printdef(char *def, int no)
+{
+	printf("#define %s\t%d\n", def, no);
+}
+
+#include "getconstants.h"
+
+int main()
+{
+	printf("/*\n *  contants.h generated by getconstants\n * DO NOT EDIT!\n */\n");
+
+	printf("#define _current\t_%s\n", "current_set");
+
+#ifdef _PAGE_PRESENT
+	printdef("PAGE_PRESENT",	_PAGE_PRESENT);
+#endif
+#ifdef _PAGE_RW
+	printdef("PAGE_RW",		_PAGE_RW);
+#endif
+#ifdef _PAGE_USER
+	printdef("PAGE_USER",		_PAGE_USER);
+#endif
+#ifdef _PAGE_ACCESSED
+	printdef("PAGE_ACCESSED",	_PAGE_ACCESSED);
+#endif
+#ifdef _PAGE_DIRTY
+	printdef("PAGE_DIRTY",		_PAGE_DIRTY);
+#endif
+#ifdef _PAGE_READONLY
+	printdef("PAGE_READONLY",	_PAGE_READONLY);
+#endif
+#ifdef _PAGE_NOT_USER
+	printdef("PAGE_NOT_USER",	_PAGE_NOT_USER);
+#endif
+#ifdef _PAGE_OLD
+	printdef("PAGE_OLD",		_PAGE_OLD);
+#endif
+#ifdef _PAGE_CLEAN
+	printdef("PAGE_CLEAN",		_PAGE_CLEAN);
+#endif
+	printdef("TSS_MEMMAP",		(int)tss_memmap);
+	printdef("TSS_SAVE",		(int)tss_save);
+#ifdef __HAS_tss_memcmap
+	printdef("TSS_MEMCMAP",		(int)tss_memcmap);
+#endif
+#ifdef __HAS_addr_limit
+	printdef("ADDR_LIMIT",		(int)addr_limit);
+#endif
+#ifdef __HAS_kernel_domain
+	printdef("KERNEL_DOMAIN",	kernel_domain);
+#endif
+#ifdef __HAS_user_domain
+	printdef("USER_DOMAIN",		user_domain);
+#endif
+	printdef("TSS_FPESAVE",		(int)tss_fpesave);
+	printdef("MM",			(int)mm);
+	printdef("PGD",			(int)pgd);
+
+	printf("#define KSWI_BASE	0x900000\n");
+	printf("#define KSWI_SYS_BASE	0x9F0000\n");
+	printf("#define SYS_ERROR0	0x9F0000\n");
+	return 0;
+}
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/getconstants.h linux/arch/arm/lib/getconstants.h
--- v2.1.100/linux/arch/arm/lib/getconstants.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/getconstants.h	Fri May  8 00:42:38 1998
@@ -0,0 +1,17 @@
+/*
+ * *** THIS FILE IS AUTOMATICALLY GENERATED.  DO NOT EDIT! ***
+ */
+unsigned long addr_limit = 56;
+#define __HAS_addr_limit
+unsigned long tss_memmap = 640;
+#define __HAS_tss_memmap
+unsigned long mm = 1676;
+#define __HAS_mm
+unsigned long pgd = 8;
+#define __HAS_pgd
+unsigned long tss_save = 636;
+#define __HAS_tss_save
+unsigned long tss_fpesave = 492;
+#define __HAS_tss_fpesave
+unsigned long tss_memcmap = 644;
+#define __HAS_tss_memcmap
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/io-acorn.S linux/arch/arm/lib/io-acorn.S
--- v2.1.100/linux/arch/arm/lib/io-acorn.S	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/lib/io-acorn.S	Fri May  8 00:42:38 1998
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1995, 1996 Russell King
  */
-#include <linux/config.h> /* for CONFIG_CPU_ARM2 and CONFIG_CPU_ARM3 */
+#include <linux/config.h> /* for CONFIG_CPU_nn */
 #include <linux/autoconf.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -171,7 +171,7 @@
 @ Proto  : void memc_write(int register, int value);
 @ Returns: nothing
 
-#if defined(CONFIG_CPU_ARM2) || defined(CONFIG_CPU_ARM3)
+#if defined(CONFIG_CPU_26)
 ENTRY(memc_write)
 		cmp	r0, #7
 		RETINSTR(movgt,pc,lr)
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/io-ebsa285.S linux/arch/arm/lib/io-ebsa285.S
--- v2.1.100/linux/arch/arm/lib/io-ebsa285.S	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/lib/io-ebsa285.S	Fri May  8 00:42:38 1998
@@ -1,4 +1,3 @@
-#define __ASSEMBLER__
 #include <linux/linkage.h>
 
 ENTRY(insl)
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/ll_char_wr.S linux/arch/arm/lib/ll_char_wr.S
--- v2.1.100/linux/arch/arm/lib/ll_char_wr.S	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/lib/ll_char_wr.S	Fri May  8 00:42:38 1998
@@ -100,13 +100,13 @@
 Lrow8bpplp:	mov	ip, r7, lsr #4
 		ldr	ip, [lr, ip, lsl #2]
 		mul	r4, r2, ip
-		and	ip, r7, #15
-		eor	r4, r3, r4
-		ldr	ip, [lr, ip, lsl #2]
-		mul	ip, r2, ip
-		tst	r1, #7
+		and	ip, r7, #15			@ avoid r4
+		ldr	ip, [lr, ip, lsl #2]		@ avoid r4
+		mul	ip, r2, ip			@ avoid r4
+		eor	r4, r3, r4			@ avoid ip
+		tst	r1, #7				@ avoid ip
+		sub	r0, r0, r5			@ avoid ip
 		eor	ip, r3, ip
-		sub	r0, r0, r5
 		stmia	r0, {r4, ip}
 		LOADREGS(eqfd, sp!, {r4 - r7, pc})
 		sub	r1, r1, #1
@@ -114,13 +114,13 @@
 		mov	ip, r7, lsr #4
 		ldr	ip, [lr, ip, lsl #2]
 		mul	r4, r2, ip
-		and	ip, r7, #15
-		eor	r4, r3, r4
-		ldr	ip, [lr, ip, lsl #2]
-		mul	ip, r2, ip
-		tst	r1, #7
+		and	ip, r7, #15			@ avoid r4
+		ldr	ip, [lr, ip, lsl #2]		@ avoid r4
+		mul	ip, r2, ip			@ avoid r4
+		eor	r4, r3, r4			@ avoid ip
+		tst	r1, #7				@ avoid ip
+		sub	r0, r0, r5			@ avoid ip
 		eor	ip, r3, ip
-		sub	r0, r0, r5
 		stmia	r0, {r4, ip}
 		subne	r1, r1, #1
 		ldrneb	r7, [r6, r1]
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/memfastset.S linux/arch/arm/lib/memfastset.S
--- v2.1.100/linux/arch/arm/lib/memfastset.S	Tue Jan 20 16:39:42 1998
+++ linux/arch/arm/lib/memfastset.S	Wed Dec 31 16:00:00 1969
@@ -1,35 +0,0 @@
-/*
- * linux/arch/arm/lib/memfastset.S
- *
- * Copyright (C) 1995, 1996 Russell King
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-		.text
-@ Prototype: void memsetl (unsigned long *d, unsigned long c, size_t n);
-
-ENTRY(memsetl)
-		stmfd	sp!, {lr}
-		cmp	r2, #16
-		blt	5f
-		mov	r3, r1
-		mov	ip, r1
-		mov	lr, r1
-		subs	r2, r2, #32
-		bmi	2f
-1:		stmia	r0!, {r1, r3, ip, lr}
-		stmia	r0!, {r1, r3, ip, lr}
-		LOADREGS(eqfd, sp!, {pc})
-		subs	r2, r2, #32
-		bpl	1b
-2:		adds	r2, r2, #16
-		bmi	4f
-3:		stmia	r0!, {r1, r3, ip, lr}
-		LOADREGS(eqfd, sp!, {pc})
-		subs	r2, r2, #16
-		bpl	3b
-4:		add	r2, r2, #16
-5:		subs	r2, r2, #4
-		strge	r1, [r0], #4
-		bgt	5b 
-		LOADREGS(fd, sp!, {pc})
diff -u --recursive --new-file v2.1.100/linux/arch/arm/lib/string.S linux/arch/arm/lib/string.S
--- v2.1.100/linux/arch/arm/lib/string.S	Tue Jan 20 16:39:42 1998
+++ linux/arch/arm/lib/string.S	Fri May  8 00:42:38 1998
@@ -1,24 +1,55 @@
 /*
  * linux/arch/arm/lib/string.S
  *
- * Copyright (C) 1995, 1996 Russell King
+ * Copyright (C) 1995-1998 Russell King
+ *
+ * This is commonly used to clear the frame buffer and the frame
+ * backing buffer.  As such, it will be rarely called with r2 < 32.
+ *
+ * Optimisations by Matthew Wilcox
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 		.text
 # Prototype: char *strrchr(const char *s,char c);
 
-@ r0 = pointer, r1 = length
-		.global	memzero
-memzero:	stmfd	sp!, {lr}
-		mov	r2, #0
-		mov	r3, #0
-		mov	ip, #0
-		mov	lr, #0
-1:		subs	r1, r1, #4*8
-		stmgeia	r0!, {r2, r3, ip, lr}
-		stmgeia	r0!, {r2, r3, ip, lr}
+/*
+ * Prototype: void memzero(void *d, size_t n)
+ */
+ENTRY(memzero)
+		mov	r2, r1
+		mov	r1, #0
+/*
+ * Prototype: void memsetl(unsigned long *d, unsigned long c, size_t n)
+ */
+ENTRY(memsetl)
+		teq	r2, #0
+		RETINSTR(moveq,pc,lr)
+		stmfd	sp!, {lr}
+		mov	lr, r1
+		mov	r3, r1
+		mov	ip, r1
+
+		@ r2 = {32 ... 4}
+
+1:		subs	r2, r2, #32
+		stmgeia	r0!, {r1, r3, ip, lr}
+		stmgeia	r0!, {r1, r3, ip, lr}
 		bgt	1b
+		LOADREGS(eqfd, sp!, {pc})
+
+		@ r2 can be {-4 ... -28}
+
+		cmp	r2, #-16
+		stmgeia	r0!, {r1, r3, ip, lr}
+		addlts	r2, r2, #16
+		LOADREGS(eqfd, sp!, {pc})
+
+		@ r2 can be {-4 ... -12}
+
+		cmp	r2, #-8
+		stmgeia	r0!, {r1, r3}
+		strne	r1, [r0]
 		LOADREGS(fd, sp!, {pc})
 
 		.global	__page_memcpy
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile
--- v2.1.100/linux/arch/arm/mm/Makefile	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/Makefile	Fri May  8 00:42:38 1998
@@ -7,6 +7,7 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+all:	lib first_rule
 ifeq ($(MACHINE),a5k)
 MMARCH=arc
 else
@@ -30,13 +31,14 @@
 proc-arm6,7.o:	../lib/constants.h
 proc-sa110.o:	../lib/constants.h
 
-.PHONY: ../lib/constants.h
-../lib/constants.h:
-	@$(MAKE) -C ../lib constants.h
-
-ifneq ($(CONFIG_BINUTILS_NEW),y)
 %.o: %.S
+ifneq ($(CONFIG_BINUTILS_NEW),y)
 	$(CC) $(CFLAGS) -D__ASSEMBLY__ -E $< | tr ';$$' '\n#' > ..$@.tmp.s
 	$(CC) $(CFLAGS:-pipe=) -c -o $@ ..$@.tmp.s
 	$(RM) ..$@.tmp.s
+else
+	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
 endif
+
+.PHONY:	lib
+lib:;	@$(MAKE) -C ../lib constants.h
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/fault-armo.c linux/arch/arm/mm/fault-armo.c
--- v2.1.100/linux/arch/arm/mm/fault-armo.c	Wed Apr  8 19:36:24 1998
+++ linux/arch/arm/mm/fault-armo.c	Fri May  8 00:42:38 1998
@@ -27,11 +27,25 @@
 #define FAULT_CODE_WRITE	0x02
 #define FAULT_CODE_USER		0x01
 
+#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
+
 struct pgtable_cache_struct quicklists;
 
-void __bad_pte(pmd_t *pmd)
+void __bad_pmd(pmd_t *pmd)
 {
 	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+#ifdef CONFIG_DEBUG_ERRORS
+	__backtrace();
+#endif
+	set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+}
+
+void __bad_pmd_kernel(pmd_t *pmd)
+{
+	printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
+#ifdef CONFIG_DEBUG_ERRORS
+	__backtrace();
+#endif
 	set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
 }
 
@@ -65,7 +79,7 @@
 	}
 	kfree (pte);
 	if (pmd_bad(*pmd)) {
-		__bad_pte(pmd);
+		__bad_pmd(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + offset;
@@ -145,11 +159,11 @@
 bad_area:
 	up(&mm->mmap_sem);
 	if (mode & FAULT_CODE_USER) {
-extern int console_loglevel;
-cli();
+//extern int console_loglevel;
+//cli();
 		tsk->tss.error_code = mode;
 		tsk->tss.trap_no = 14;
-console_loglevel = 9;
+//console_loglevel = 9;
 		printk ("%s: memory violation at pc=0x%08lx, lr=0x%08lx (bad address=0x%08lx, code %d)\n",
 			tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
 //#ifdef DEBUG
@@ -157,7 +171,7 @@
 		c_backtrace (regs->ARM_fp, 0);
 //#endif
 		force_sig(SIGSEGV, tsk);
-while (1);
+//while (1);
 		goto out;
 	}
 
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.1.100/linux/arch/arm/mm/fault-armv.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/fault-armv.c	Fri May  8 00:42:38 1998
@@ -25,6 +25,8 @@
 #define FAULT_CODE_READ		0x02
 #define FAULT_CODE_USER		0x01
 
+#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
+
 struct pgtable_cache_struct quicklists;
 
 void __bad_pmd(pmd_t *pmd)
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.1.100/linux/arch/arm/mm/init.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/init.c	Fri May  8 00:42:38 1998
@@ -119,10 +119,10 @@
 	memzero (empty_zero_page, PAGE_SIZE);
 	start_mem = setup_pagetables (start_mem, end_mem);
 
-	flush_tlb_all ();
-	update_mm_cache_all ();
+	flush_tlb_all();
+	update_memc_all();
 
-	return free_area_init (start_mem, end_mem);
+	return free_area_init(start_mem, end_mem);
 }
 
 /*
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/mm-a5k.c linux/arch/arm/mm/mm-a5k.c
--- v2.1.100/linux/arch/arm/mm/mm-a5k.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mm/mm-a5k.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,7 @@
+/*
+ * arch/arm/mm/mm-a5k.c
+ *
+ * Extra MM routines for the Archimedes architecture
+ *
+ * Copyright (C) 1998 Russell King
+ */
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/mm-arc.c linux/arch/arm/mm/mm-arc.c
--- v2.1.100/linux/arch/arm/mm/mm-arc.c	Tue Apr 14 14:29:20 1998
+++ linux/arch/arm/mm/mm-arc.c	Fri May  8 00:42:38 1998
@@ -5,4 +5,78 @@
  *
  * Copyright (C) 1998 Russell King
  */
-#include <asm/arch/mm-init.h>
+#include <asm/hardware.h>
+#include <asm/pgtable.h>
+
+unsigned long phys_screen_end;
+
+/*
+ * This routine needs more work to make it dynamically release/allocate mem!
+ */
+unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update)
+{
+	static int updated = 0;
+
+	if (updated)
+		return 0;
+
+	updated = update;
+
+	if (update) {
+		unsigned long address = log_start, offset;
+		pgd_t *pgdp;
+
+		kmem = (kmem + 3) & ~3;
+
+		pgdp = pgd_offset (&init_mm, address);				/* +31 */
+		offset = SCREEN_START;
+		while (address < SCREEN1_END) {
+			unsigned long addr_pmd, end_pmd;
+			pmd_t *pmdp;
+
+			/* if (pgd_none (*pgdp)) alloc pmd */
+			pmdp = pmd_offset (pgdp, address);			/* +0 */
+			addr_pmd = address & ~PGDIR_MASK;			/* 088000 */
+			end_pmd = addr_pmd + SCREEN1_END - address;		/* 100000 */
+			if (end_pmd > PGDIR_SIZE)
+				end_pmd = PGDIR_SIZE;
+
+			do {
+				unsigned long addr_pte, end_pte;
+				pte_t *ptep;
+
+				if (pmd_none (*pmdp)) {
+					pte_t *new_pte = (pte_t *)kmem;
+					kmem += PTRS_PER_PTE * BYTES_PER_PTR;
+					memzero (new_pte, PTRS_PER_PTE * BYTES_PER_PTR);
+					set_pmd (pmdp, mk_pmd(new_pte));
+				}
+
+				ptep = pte_offset (pmdp, addr_pmd);		/* +11 */
+				addr_pte = addr_pmd & ~PMD_MASK;		/* 088000 */
+				end_pte = addr_pte + end_pmd - addr_pmd;	/* 100000 */
+				if (end_pte > PMD_SIZE)
+					end_pte = PMD_SIZE;
+
+				do {
+					set_pte (ptep, mk_pte(offset, PAGE_KERNEL));
+					addr_pte += PAGE_SIZE;
+					offset += PAGE_SIZE;
+					ptep++;
+				} while (addr_pte < end_pte);
+
+				pmdp++;
+				addr_pmd = (addr_pmd + PMD_SIZE) & PMD_MASK;
+			} while (addr_pmd < end_pmd);
+
+			address = (address + PGDIR_SIZE) & PGDIR_MASK;
+			pgdp ++;
+		}
+
+		phys_screen_end = offset;
+		flush_tlb_all ();
+		update_mm_cache_all ();
+	}
+	return kmem;
+}
+
diff -u --recursive --new-file v2.1.100/linux/arch/arm/mm/proc-arm2,3.S linux/arch/arm/mm/proc-arm2,3.S
--- v2.1.100/linux/arch/arm/mm/proc-arm2,3.S	Tue Jan 20 16:39:42 1998
+++ linux/arch/arm/mm/proc-arm2,3.S	Fri May  8 00:42:38 1998
@@ -383,13 +383,13 @@
 		mov	r0, #0x001f0000
 		orr	r0, r0, #0x0000ff00
 		orr	r0, r0, #0x000000ff
-		mcr	p15, 0, r0, c3, c0
-		mcr     p15, 0, r0, c4, c0
+		mcr	p15, 0, r0, c3, c0		@ ARM3 Cacheable
+		mcr     p15, 0, r0, c4, c0		@ ARM3 Updateable
 		mov	r0, #0
-		mcr     p15, 0, r0, c5, c0
+		mcr     p15, 0, r0, c5, c0		@ ARM3 Disruptive
+		mcr     p15, 0, r0, c1, c0		@ ARM3 Flush
 		mov	r0, #3
-		mcr     p15, 0, r0, c1, c0
-		mcr     p15, 0, r0, c2, c0
+		mcr     p15, 0, r0, c2, c0		@ ARM3 Control
 		movs	pc, lr
 
 /*
diff -u --recursive --new-file v2.1.100/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.1.100/linux/arch/i386/Makefile	Wed Apr  8 19:36:24 1998
+++ linux/arch/i386/Makefile	Fri May  8 00:09:20 1998
@@ -92,5 +92,7 @@
 archclean:
 	@$(MAKEBOOT) clean
 
+archmrproper:
+
 archdep:
 	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.1.100/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.100/linux/arch/i386/defconfig	Sat May  2 14:19:52 1998
+++ linux/arch/i386/defconfig	Fri May  8 18:21:04 1998
@@ -73,6 +73,7 @@
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
diff -u --recursive --new-file v2.1.100/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.1.100/linux/arch/i386/kernel/i386_ksyms.c	Sat May  2 14:19:52 1998
+++ linux/arch/i386/kernel/i386_ksyms.c	Fri May  8 00:23:41 1998
@@ -16,6 +16,7 @@
 #include <asm/io.h>
 #include <asm/hardirq.h>
 #include <asm/delay.h>
+#include <asm/irq.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
@@ -37,6 +38,9 @@
 EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.1.100/linux/arch/m68k/Makefile	Tue Feb 17 13:12:44 1998
+++ linux/arch/m68k/Makefile	Fri May  8 00:09:20 1998
@@ -107,4 +107,6 @@
 archclean:
 	rm -f vmlinux.gz
 
+archmrproper:
+
 archdep:
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.1.100/linux/arch/m68k/amiga/config.c	Tue Feb 17 13:12:44 1998
+++ linux/arch/m68k/amiga/config.c	Fri May  8 00:15:21 1998
@@ -76,7 +76,6 @@
 #endif
 static void amiga_reset (void);
 static int amiga_wait_key (struct console *co);
-extern struct consw fb_con;
 extern void zorro_init(void);
 extern void amiga_init_sound(void);
 static void amiga_savekmsg_init(void);
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/apollo/config.c linux/arch/m68k/apollo/config.c
--- v2.1.100/linux/arch/m68k/apollo/config.c	Tue Feb 17 13:12:44 1998
+++ linux/arch/m68k/apollo/config.c	Fri May  8 00:15:21 1998
@@ -14,7 +14,6 @@
 #include <asm/irq.h>
 #include <asm/machdep.h>
 
-extern struct consw fb_con;
 extern void dn_sched_init(void (*handler)(int,void *,struct pt_regs *));
 extern int dn_keyb_init(void);
 extern int dn_dummy_kbdrate(struct kbd_repeat *);
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c
--- v2.1.100/linux/arch/m68k/atari/config.c	Tue Feb 17 13:12:44 1998
+++ linux/arch/m68k/atari/config.c	Fri May  8 00:15:21 1998
@@ -70,7 +70,6 @@
 #ifdef CONFIG_HEARTBEAT
 static void atari_heartbeat( int on );
 #endif
-extern struct consw fb_con;
 
 /* atari specific timer functions (in time.c) */
 extern void atari_sched_init(void (*)(int, void *, struct pt_regs *));
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.1.100/linux/arch/m68k/config.in	Wed Apr  1 20:11:48 1998
+++ linux/arch/m68k/config.in	Fri May  8 00:15:21 1998
@@ -196,7 +196,7 @@
     bool 'A4000T SCSI support' CONFIG_A4000T_SCSI
     bool 'A4091 SCSI support' CONFIG_A4091_SCSI
     bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
-#    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
+    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
 #    bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
   fi
 fi
@@ -286,7 +286,6 @@
   if [ "$CONFIG_VT" = "y" ]; then
     bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
   fi
-  define_bool CONFIG_FB_CONSOLE y
 fi
 
 if [ "$CONFIG_ATARI" = "y" ]; then
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.1.100/linux/arch/m68k/kernel/m68k_ksyms.c	Thu Mar 26 15:57:02 1998
+++ linux/arch/m68k/kernel/m68k_ksyms.c	Fri May  8 00:15:21 1998
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/linkage.h>
 #include <linux/sched.h>
@@ -44,6 +43,8 @@
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(local_bh_count);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.1.100/linux/arch/m68k/kernel/process.c	Tue Mar 17 22:18:14 1998
+++ linux/arch/m68k/kernel/process.c	Fri May  8 00:15:21 1998
@@ -66,6 +66,7 @@
 	current->priority = -100;
 	current->counter = -100;
 	for (;;){
+		check_pgt_cache();
 		if (!need_resched)
 #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
 			/* block out HSYNC on the atari (falcon) */
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c
--- v2.1.100/linux/arch/m68k/mac/adb-bus.c	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/mac/adb-bus.c	Fri May  8 00:15:22 1998
@@ -6,9 +6,11 @@
  *		Copyright (C) 1996 Paul Mackerras.
  *
  *	MSch (9/97) Partial rewrite of interrupt handler to MacII style
- *	ADB handshake, based on:
- *		- Guide to Mac Hardware
- *		- Guido Koerber's session with a logic analyzer
+ *		ADB handshake, based on:
+ *			- Guide to Mac Hardware
+ *			- Guido Koerber's session with a logic analyzer
+ *
+ *	MSch (1/98) Integrated start of IIsi driver by Robert Thompson
  */
  
 #include <stdarg.h>
@@ -63,6 +65,9 @@
 #define SR_DATA		0x08		/* Shift register data */
 #define SR_CLOCK	0x10		/* Shift register clock */
 
+/* JRT */
+#define ADB_DELAY 150
+
 static struct adb_handler {
     void (*handler)(unsigned char *, int, struct pt_regs *);
 } adb_handler[16];
@@ -98,6 +103,8 @@
 extern void adb_data_interrupt(int irq, void *arg, struct pt_regs *regs);
 static void adb_input(unsigned char *buf, int nb, struct pt_regs *regs);
 
+static void adb_hw_setup_IIsi(void);
+
 /*
  * Misc. defines for testing 
  */
@@ -118,11 +125,13 @@
 #define ADBDEBUG_INPUT		(2048)
 #define ADBDEBUG_DEVICE		(4096)
 
+#define ADBDEBUG_IISI		(8192)
+
 
 #define DEBUG_ADB
 
 #ifdef DEBUG_ADB
-#define ADBDEBUG	(ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST)
+#define ADBDEBUG	(ADBDEBUG_INPUT | ADBDEBUG_READ | ADBDEBUG_START | ADBDEBUG_WRITE | ADBDEBUG_SRQ | ADBDEBUG_REQUEST)
 #else
 #define ADBDEBUG	(0)
 #endif
@@ -132,7 +141,7 @@
 void adb_bus_init(void)
 {
 	unsigned long flags;
-	unsigned char c;
+	unsigned char c, i;
 	
 	save_flags(flags);
 	cli();
@@ -174,31 +183,7 @@
 		 	via_write(via1, vIER, IER_SET|SR_INT); 
 		 	/* This clears the interrupt bit */
 		 	via_write(via1, vIFR, SR_INT);
-#if 0 	
-		 	ct=1000;
- 			while( ct-- && (via_read(via1, vBufB)&TREQ))
- 				udelay(1000);
-		 	if(ct<0)
- 				printk("No sync occured\n");
- 			ct=1000;
- 			while( ct-- && !(via_read(via1, vIFR)&SR_INT))
- 				udelay(1000);
-		 	if(ct<0)
-		 		printk("No sync 2 occured\n");
-		 	via_read(via1, vSR);
-		 	via_write(via1, vBufB, via_read(via1, vBufB)|TACK);
-		 	while( ct-- && !(via_read(via1, vBufB)&TREQ))
- 				udelay(1000);
-		 	if(ct<0)
- 				printk("No sync 3 occured\n");
- 			ct=1000;
- 			while( ct-- && !(via_read(via1, vIFR)&SR_INT))
- 				udelay(1000);
-		 	if(ct<0)
- 				printk("No sync 4 occured\n");
-		 	via_read(via1, vSR);
- 			via_write(via1, vBufB, via_read(via1, vBufB)|TIP);
-#endif
+
 		 	/*
 		 	 *	Ok we probably ;) have a ready to use adb bus. Its also
 		 	 *	hopefully idle (Im assuming the mac didnt leave a half
@@ -214,7 +199,6 @@
 			 */
 		case MAC_ADB_CUDA:
 			printk("adb: CUDA interface.\n");
-#ifdef TRY_CUDA
 			/* don't know what to set up here ... */
 			adb_state = idle;
 			/* Set the lines up. We want TREQ as input TACK|TIP as output */
@@ -222,12 +206,47 @@
 			request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, 
 				    "adb CUDA interrupt", adb_cuda_interrupt);
 			break;
-#else
-			goto nosupp;
-#endif
 		case MAC_ADB_IISI:
 			printk("adb: Using IIsi hardware.\n");
-			goto nosupp;
+			printk("\tDEBUG_JRT\n");
+			/* Set the lines up. We want TREQ as input TACK|TIP as output */
+		 	via_write(via1, vDirB, ((via_read(via1,vDirB)|TACK|TIP)&~TREQ));
+
+			/*
+			 * MSch: I'm pretty sure the setup is mildly wrong
+			 * for the IIsi. 
+			 */
+			/* Initial state: idle (clear state bits) */
+		 	via_write(via1, vBufB, (via_read(via1, vBufB) & ~(TIP|TACK)) );
+			last_status = (via_read(via1, vBufB)&~ST_MASK);
+		 	/* Shift register on input */
+		 	c=via_read(via1, vACR);
+		 	c&=~SR_CTRL;		/* Clear shift register bits */
+		 	c|=SR_EXT;		/* Shift on external clock; out or in? */
+		 	via_write(via1, vACR, c);
+		 	/* Wipe any pending data and int */
+		 	via_read(via1, vSR);
+
+		 	/* This is interrupts on enable SR for keyboard */
+		 	via_write(via1, vIER, IER_SET|SR_INT); 
+		 	/* This clears the interrupt bit */
+		 	via_write(via1, vIFR, SR_INT);
+
+			/* get those pesky clock ticks we missed while booting */
+			for ( i = 0; i < 30; i++) {
+				udelay(ADB_DELAY);
+				adb_hw_setup_IIsi();
+				udelay(ADB_DELAY);
+				if (via_read(via1, vBufB) & TREQ)
+					break;
+			}
+		 	/*
+		 	 *	Ok we probably ;) have a ready to use adb bus. Its also
+ 			 */
+			request_irq(IRQ_MAC_ADB, adb_cuda_interrupt, IRQ_FLG_LOCK, 
+				    "adb interrupt", adb_cuda_interrupt);
+			adb_state = idle;
+ 			break;
 		default:
 			printk("adb: Unknown hardware interface.\n");
 		nosupp:
@@ -255,6 +274,62 @@
 	restore_flags(flags);	
 } 
 	
+void adb_hw_setup_IIsi(void)
+{
+	int dummy;
+	long poll_timeout;
+
+	printk("adb_IIsi: cleanup!\n");
+
+	/* ??? */
+	udelay(ADB_DELAY);
+
+	/* disable SR int. */
+	via_write(via1, vIER, IER_CLR|SR_INT);
+	/* set SR to shift in */
+	via_write(via1, vACR, via_read(via1, vACR ) & ~SR_OUT);
+
+	/* this is required, especially on faster machines */
+	udelay(ADB_DELAY);
+
+	if (!(via_read(via1, vBufB) & TREQ)) { /* IRQ on */
+		/* start frame */
+		via_write(via1, vBufB,via_read(via1,vBufB) | TIP);
+
+		while (1) {
+			/* poll for ADB interrupt and watch for timeout */
+			/* if time out, keep going in hopes of not hanging the
+			 * ADB chip - I think */
+			poll_timeout = ADB_DELAY * 5;
+			while ( !(via_read(via1, vIFR) & SR_INT) 
+				&& (poll_timeout-- > 0) )
+				dummy = via_read(via1, vBufB);
+
+			dummy = via_read(via1, vSR);	/* reset interrupt flag */
+
+			/* perhaps put in a check here that ignores all data
+			 * after the first ADB_MAX_MSG_LENGTH bytes ??? */
+
+			/* end of frame reached ?? */
+			if (via_read(via1, vBufB) & TREQ)
+				break;
+
+			/* set ACK */
+			via_write(via1,vBufB,via_read(via1, vBufB) | TACK);
+			/* delay */
+			udelay(ADB_DELAY);
+			/* clear ACK */
+			via_write(via1,vBufB,via_read(via1, vBufB) & ~TACK);
+		}
+		/* end frame */
+		via_write(via1, vBufB,via_read(via1,vBufB) & ~TIP);
+		/* probably don't need to delay this long */
+		udelay(ADB_DELAY);
+	}
+	/* re-enable SR int. */
+	via_write(via1, vIER, IER_SET|SR_INT);
+}
+
 #define WAIT_FOR(cond, what)				\
     do {						\
 	for (x = 1000; !(cond); --x) {			\
@@ -288,7 +363,7 @@
 	/*
 	 * skip first byte if not CUDA 
 	 */
-	if (macintosh_config->adb_type != MAC_ADB_CUDA) {
+	if (macintosh_config->adb_type == MAC_ADB_II) {
 		start =  va_arg(list, int);
 		nbytes--;
 	}
@@ -390,8 +465,12 @@
 		printk("adb: Polling %d\n",pod);
 #endif
 
-	/* XXX: that's a TALK, register 0, MacII version */
-	adb_build_request(&r,NULL, 1, (pod<<4|0xC));
+	if (macintosh_config->adb_type == MAC_ADB_II)
+		/* XXX: that's a TALK, register 0, MacII version */
+		adb_build_request(&r,NULL, 1, (pod<<4|0xC));
+	else
+		/* CUDA etc. version */
+		adb_build_request(&r,NULL, 2, 0, (pod<<4|0xC));
 
 	r.reply_expected=0;
 	r.done=NULL;
@@ -545,7 +624,7 @@
 	 * IRQ signaled ?? (means ADB controller wants to send, or might 
 	 * be end of packet if we were reading)
 	 */
-	if ((via_read(via1, vBufB)& TREQ) == 0) 
+	if ((via_read(via1, vBufB) & TREQ) == 0) 
 	{
 		switch(macintosh_config->adb_type)
 		{
@@ -560,7 +639,12 @@
 				/* printk("device busy - fail\n"); */
 				restore_flags(flags);
 				/* a byte is coming in from the CUDA */
-				return;			
+				return;
+			case MAC_ADB_IISI:
+				printk("adb_start: device busy - fail\n");
+				retry_req = req;
+				restore_flags(flags);
+				return;
 			case MAC_ADB_II:
 				/*
 				 * if the interrupt handler set the need_poll
@@ -635,6 +719,19 @@
 			via_write(via1, vSR, req->data[0]);
 			via_write(via1, vBufB, via_read(via1, vBufB)&~TIP);
 			break;
+		case MAC_ADB_IISI:
+			/* store command byte (first byte is 'type' byte) */
+			command_byte = req->data[1];
+			/* set ADB state to 'active' */
+			via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+			/* switch ACK off (in case it was left on) */
+			via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+			/* set the shift register to shift out and send a byte */
+			via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); 
+			via_write(via1, vSR, req->data[0]);
+			/* signal 'byte ready' */
+			via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+			break;
 		case MAC_ADB_II:
 			/* store command byte */
 			command_byte = req->data[0];
@@ -653,14 +750,14 @@
 #endif
 			break;
 	}
+	adb_state = sent_first_byte;
+	data_index = 1;
 #if (ADBDEBUG & ADBDEBUG_START)
 	if (console_loglevel == 10)
 		printk("sent first byte of %d: %x, (%x %x) ... ", 
 			req->nbytes, req->data[0], adb_state, 
 			(via_read(via1, vBufB) & (ST_MASK|TREQ)) );
 #endif
-	adb_state = sent_first_byte;
-	data_index = 1;
 	restore_flags(flags);
 }
 
@@ -748,6 +845,12 @@
  * and retransmit (Talk to the last active device). Cleanup of code and 
  * testing of the CUDA functionality is required, though. 
  * Note2: As of 13/12/97, CUDA support is definitely broken ...
+ * Note3: As of 21/12/97, CUDA works on a P475. What was broken? The assumption
+ * that Q700 and Q800 use CUDA :-(
+ *
+ * 27/01/98: IIsi driver implemented (thanks to Robert Thompson for the 
+ * initial bits). See adb_cuda_interrupts ...
+ *
  * Next TODO: implementation of IIsi ADB protocol (maybe the USE_ORIG 
  * conditionals can be a start?)
  */
@@ -786,6 +889,26 @@
 				x = via_read(via1, vSR); 
 				via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
 			}
+			else if(macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				udelay(150);
+				/* set SR to IN (??? no byte received else) */
+				via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); 
+		 		/* signal start of frame */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+				/* read first byte */
+				x = via_read(via1, vSR);
+				first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+				if (console_loglevel == 10)
+					printk("adb_macIIsi : receiving unsol. packet: %x (%x %x) ", 
+						x, adb_state, status);
+#endif
+				/* ACK adb chip */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				udelay(150);
+		 		via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+			}
 			else if(macintosh_config->adb_type==MAC_ADB_II)
 			{
 #if (ADBDEBUG & ADBDEBUG_STATUS)
@@ -801,12 +924,8 @@
 					printk("adb_macII: receiving unsol. packet: %x (%x %x) ", 
 						x, adb_state, status);
 #endif
-#ifdef USE_ORIG
-				via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
-#else
 				/* set ADB state = even for first data byte */
 				via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
-#endif
 			}
 			adb_state = reading;
 			reply_ptr = cuda_rbuf;
@@ -831,7 +950,34 @@
 				x = via_read(via1, vSR); 
 				via_write(via1,vBufB, 
 					via_read(via1, vBufB)&~TIP);
-			} else if(macintosh_config->adb_type==MAC_ADB_II) {
+			} 
+			else if(macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				/* set SR to IN */
+				via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); 
+		 		/* signal start of frame */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+				/* read first byte */
+				x = via_read(via1, vSR);
+				first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+				if (console_loglevel == 10)
+					printk("adb_macIIsi: reading reply: %x (%x %x) ",
+						x, adb_state, status);
+#endif
+#if 0
+				if( via_read(via1,vBufB) & TREQ)
+					ending = 1;
+				else
+					ending = 0;
+#endif
+				/* ACK adb chip */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				udelay(150);
+		 		via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+			}
+			else if(macintosh_config->adb_type==MAC_ADB_II) 
+			{
 				/* handshake etc. for II ?? */
 				x = via_read(via1, vSR);
 				first_byte = x;
@@ -840,12 +986,8 @@
 					printk("adb_macII: reading reply: %x (%x %x) ",
 						x, adb_state, status);
 #endif
-#ifdef USE_ORIG
-				via_write(via1, vBufB, via_read(via1, vBufB)&~(TIP|TACK));
-#else
 				/* set ADB state = even for first data byte */
 				via_write(via1, vBufB, (via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
-#endif
 			}
 			adb_state = reading;			
 			reply_ptr = current_req->reply;
@@ -862,6 +1004,11 @@
 			break;
 
 		case sent_first_byte:
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+			if (console_loglevel == 10)
+				printk(" sending: %x (%x %x) ",
+					current_req->data[1], adb_state, status);
+#endif
 			if(macintosh_config->adb_type==MAC_ADB_CUDA)
 			{
 				if (status == TREQ + TIP + SR_OUT) 
@@ -886,14 +1033,45 @@
 					adb_state = sending;
 				}
 			}
-			else if(macintosh_config->adb_type==MAC_ADB_II)
+			else if(macintosh_config->adb_type==MAC_ADB_IISI)
 			{
-				/* how to detect a collision here ?? */
+				/* switch ACK off */
+				via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+				if ( !(via_read(via1, vBufB) & TREQ) ) 
+				{
+					/* collision */
 #if (ADBDEBUG & ADBDEBUG_WRITE)
-				if (console_loglevel == 10)
-					printk(" sending: %x (%x %x) ",
-						current_req->data[1], adb_state, status);
+					if (console_loglevel == 10)
+						printk("adb_macIIsi: send collison, aborting!\n");
 #endif
+					/* set shift in */
+					via_write(via1, vACR,
+						via_read(via1, vACR)&~SR_OUT); 
+					/* clear SR int. */
+					x = via_read(via1, vSR); 
+					/* set ADB state to 'idle' */
+					via_write(via1, vBufB,
+						via_read(via1,vBufB) & ~(TIP|TACK)); 
+					adb_state = idle;
+				}
+				else
+				{
+					/* delay */
+					udelay(ADB_DELAY);
+					/* set the shift register to shift out and send a byte */
+#if 0
+					via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); 
+#endif
+					via_write(via1, vSR, current_req->data[1]);
+					/* signal 'byte ready' */
+					via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+					data_index=2;			
+					adb_state = sending;
+				}
+			}
+			else if(macintosh_config->adb_type==MAC_ADB_II)
+			{
+				/* how to detect a collision here ?? */
 				/* maybe we're already done (Talk, or Poll)? */
 				if (data_index >= current_req->nbytes) 
 				{
@@ -934,14 +1112,9 @@
 					via_write(via1, vACR,
 						via_read(via1, vACR) & ~SR_OUT);
 					x=via_read(via1, vSR);
-#ifdef USE_ORIG
-					via_write(via1, vBufB,
-						via_read(via1, vBufB)|TACK|TIP);
-#else
 					/* set ADB state idle - might get SRQ */
 					via_write(via1, vBufB,
 						(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
 					break;
 				}
 #if (ADBDEBUG & ADBDEBUG_STATUS)
@@ -951,14 +1124,9 @@
 #endif
 				/* SR already set to shift out; send byte */
 				via_write(via1, vSR, current_req->data[1]);
-#ifdef USE_ORIG
-				via_write(via1, vBufB,
-					via_read(via1, vBufB)^TACK);
-#else
 				/* set state to ST_EVEN (first byte was: ST_CMD) */
 				via_write(via1, vBufB,
 					(via_read(via1, vBufB)&~ST_MASK)|ST_EVEN);
-#endif
 				data_index=2;			
 				adb_state = sending;
 			}
@@ -968,6 +1136,11 @@
 			req = current_req;
 			if (data_index >= req->nbytes) 
 			{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+				if (console_loglevel == 10)
+					printk(" -> end (%d of %d) (%x %x)!\n",
+						data_index-1, req->nbytes, adb_state, status);
+#endif
 				/* end of packet */
 				if(macintosh_config->adb_type==MAC_ADB_CUDA)
 				{
@@ -977,29 +1150,34 @@
 					via_write(via1, vBufB,
 						via_read(via1,vBufB)|TACK|TIP); 
 				}
+				else if(macintosh_config->adb_type==MAC_ADB_IISI)
+				{
+					/* XXX maybe clear ACK here ??? */
+					/* switch ACK off */
+					via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+					/* delay */
+					udelay(ADB_DELAY);
+					/* set the shift register to shift in */
+					via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); 
+					/* clear SR int. */
+					x = via_read(via1, vSR); 
+					/* set ADB state 'idle' (end of frame) */
+					via_write(via1, vBufB,
+						via_read(via1,vBufB) & ~(TACK|TIP)); 
+				}
 				else if(macintosh_config->adb_type==MAC_ADB_II)
 				{
 					/*
 					 * XXX Not sure: maybe only switch to 
 					 * input mode on Talk ??
 					 */
-#if (ADBDEBUG & ADBDEBUG_WRITE)
-					if (console_loglevel == 10)
-						printk(" -> end (%d of %d) (%x %x)!\n",
-							data_index-1, req->nbytes, adb_state, status);
-#endif
 					/* set to shift in */
 					via_write(via1, vACR,
 						via_read(via1, vACR) & ~SR_OUT);
 					x=via_read(via1, vSR);
-#ifdef USE_ORIG
-					via_write(via1, vBufB,
-						via_read(via1, vBufB)|TACK|TIP);
-#else
 					/* set ADB state idle - might get SRQ */
 					via_write(via1, vBufB,
 						(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
-#endif
 				}
 				req->sent = 1;
 				if (req->reply_expected) 
@@ -1008,7 +1186,12 @@
 					 * maybe fake a reply here on Listen ?? 
 					 * Otherwise, a Listen hangs on success
 					 */
-					if ( ((req->data[0]&0xc) == 0xc) )
+					if ( macintosh_config->adb_type==MAC_ADB_II
+					     && ((req->data[0]&0xc) == 0xc) )
+						adb_state = awaiting_reply;
+					else if ( macintosh_config->adb_type != MAC_ADB_II
+						  && ( req->data[0]      == 0x0) 
+						  && ((req->data[1]&0xc) == 0xc) )
 						adb_state = awaiting_reply;
 					else {
 						/*
@@ -1063,34 +1246,46 @@
 			}
 			else 
 			{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+				if (console_loglevel == 10)
+					printk(" %x (%x %x) ",
+						req->data[data_index], adb_state, status);
+#endif
 				if(macintosh_config->adb_type==MAC_ADB_CUDA)
 				{
 					via_write(via1, vSR, req->data[data_index++]); 
 					via_write(via1, vBufB, 
 						via_read(via1, vBufB)^TACK); 
 				}
-				else if(macintosh_config->adb_type==MAC_ADB_II)
+				else if(macintosh_config->adb_type==MAC_ADB_IISI)
 				{
-#if (ADBDEBUG & ADBDEBUG_WRITE)
-					if (console_loglevel == 10)
-						printk(" %x (%x %x) ",
-							req->data[data_index], adb_state, status);
+					/* switch ACK off */
+					via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+					/* delay */
+					udelay(ADB_DELAY);
+					/* XXX: need to check for collision?? */
+					/* set the shift register to shift out and send a byte */
+#if 0
+					via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); 
 #endif
 					via_write(via1, vSR, req->data[data_index++]);
-#ifdef USE_ORIG
-					via_write(via1, vBufB,
-						via_read(via1, vBufB)^TACK);
-#else
+					/* signal 'byte ready' */
+					via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				}
+				else if(macintosh_config->adb_type==MAC_ADB_II)
+				{
+					via_write(via1, vSR, req->data[data_index++]);
 					/* invert state bits, toggle ODD/EVEN */
 					x = via_read(via1, vBufB);
 					via_write(via1, vBufB,
 						(x&~ST_MASK)|~(x&ST_MASK));
-#endif
 				}
 			}
 			break;
 
 		case reading:
+
+			/* timeout / SRQ handling for II hw */
 #ifdef POLL_ON_TIMEOUT
 			if((reply_len-prefix_len)==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
 #else
@@ -1128,16 +1323,12 @@
 						x, adb_state, status);
 #endif
 
-#ifdef USE_ORIG
-				via_write(via1, vBufB,
-					via_read(via1, vBufB)|TACK|TIP);
-#else
 #if 0	/* XXX leave status unchanged!! - need to check this again! */
+	/* XXX Only touch status on II !!! */
 				/* set ADB state to idle (required by adb_start()) */
 				via_write(via1, vBufB,
 					(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE);
 #endif
-#endif
 
 				/*
 				 * What if the timeout happens on reading a 
@@ -1206,6 +1397,7 @@
 				 */
 				break;
 			}
+			/* end timeout / SRQ handling for II hw. */
 			if((reply_len-prefix_len)>3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
 			{
 				/* SRQ tacked on data packet */
@@ -1241,7 +1433,7 @@
 				reply_len++;
 			}
 			/* The usual handshake ... */
-			if(macintosh_config->adb_type==MAC_ADB_CUDA)
+			if (macintosh_config->adb_type==MAC_ADB_CUDA)
 			{
 				if (status == TIP)
 				{
@@ -1259,7 +1451,27 @@
 						via_read(via1, vBufB)^TACK); 
 				}
 			}
-			if(macintosh_config->adb_type==MAC_ADB_II)
+			else if (macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				/* ACK adb chip (maybe check for end first?) */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				udelay(150);
+		 		via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+				/* end of frame?? */
+				if (status & TREQ)
+				{
+#if (ADBDEBUG & ADBDEBUG_READ)
+					if (console_loglevel == 10)
+						printk("adb_IIsi: end of frame!\n");
+#endif
+					/* that's all folks */
+					via_write(via1, vBufB,
+						via_read(via1, vBufB) & ~(TACK|TIP)); 
+					adb_state = read_done;
+					/* maybe process read_done here?? Handshake anyway?? */
+				}
+			}
+			else if (macintosh_config->adb_type==MAC_ADB_II)
 			{
 				/*
 				 * NetBSD hints that the next to last byte 
@@ -1277,10 +1489,6 @@
 					if (console_loglevel == 10)
 						printk(" -> read done!\n");
 #endif
-#ifdef USE_ORIG
-					via_write(via1, vBufB,
-						via_read(via1, vBufB)|TACK|TIP);
-#else
 #if 0		/* XXX: we take one more byte (why?), so handshake! */
 					/* set ADB state to idle */
 					via_write(via1, vBufB,
@@ -1291,7 +1499,6 @@
 					via_write(via1, vBufB,
 						(x&~ST_MASK)|~(x&ST_MASK));
 #endif
-#endif
 					/* adjust packet length */
 					reply_len--;
 					reply_ptr--;
@@ -1303,10 +1510,6 @@
 					if(status!=TIP+TREQ)
 						printk("macII_adb: state=reading status=%x\n", status);
 #endif
-#ifdef USE_ORIG
-					via_write(via1, vBufB, 
-						via_read(via1, vBufB)^TACK);
-#else
 					/* not caught: ST_CMD */
 					/* required for re-entry 'reading'! */
 					if ((status&ST_MASK) == ST_IDLE) {
@@ -1319,7 +1522,6 @@
 						via_write(via1, vBufB,
 							(x&~ST_MASK)|~(x&ST_MASK));
 					}
-#endif
 				}
 			}
 			break;
@@ -1352,7 +1554,6 @@
 			last_reply = command_byte;
 			last_active = (command_byte&0xf0)>>4;
 
-
 			/*
 			 * Assert status = ST_IDLE ??
 			 */
@@ -1374,15 +1575,6 @@
 				break;
 			}
 
-#ifdef USE_ORIG
-			/*
-			 * This will fail - TREQ is active low -> 0 is IRQ !!
-			 */ 
-			if (status == TREQ) 
-			{
-				via_write(via1, vBufB,
-					via_read(via1, vBufB)|~TIP); 
-#else
 			/*
 			 * /IRQ seen, so the ADB controller has data for us
 			 */
@@ -1391,7 +1583,7 @@
 				/* set ADB state to idle */
 				via_write(via1, vBufB,
 					(via_read(via1, vBufB)&~ST_MASK)|ST_IDLE); 
-#endif
+
 				adb_state = reading;
 				reply_ptr = cuda_rbuf;
 				reply_len = 0;
@@ -1428,29 +1620,72 @@
  * Restart of CUDA support: please modify this interrupt handler while 
  * working at the Quadra etc. ADB driver. We can try to merge them later, or
  * remove the CUDA stuff from the MacII handler
+ *
+ * MSch 27/01/98: Implemented IIsi driver based on initial code by Robert 
+ * Thompson and hints from the NetBSD driver. CUDA and IIsi seem more closely
+ * related than to the MacII code, so merging all three might be a bad
+ * idea.
  */
 
 void adb_cuda_interrupt(int irq, void *arg, struct pt_regs *regs)
 {
 	int x, status;
 	struct adb_request *req;
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
 
-	status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
+	if(macintosh_config->adb_type==MAC_ADB_CUDA)
+		status = (~via_read(via1, vBufB) & (TIP|TREQ)) | (via_read(via1, vACR) & SR_OUT);
+	else
+		status = via_read(via1, vBufB) & (TIP|TREQ);
+
+#if (ADBDEBUG & ADBDEBUG_INT)
 	if (console_loglevel == 10)
 		printk("adb_interrupt: state=%d status=%x\n", adb_state, status);
+#endif
 
 	switch (adb_state) 
 	{
 		case idle:
+			first_byte = 0;
 			if(macintosh_config->adb_type==MAC_ADB_CUDA)
 			{
+#if (ADBDEBUG & ADBDEBUG_STATUS)
 				/* CUDA has sent us the first byte of data - unsolicited */
 				if (status != TREQ)
 					printk("cuda: state=idle, status=%x want=%x\n", 
 						status, TREQ);
+#endif
 				x = via_read(via1, vSR); 
+#if (ADBDEBUG & ADBDEBUG_READ)
+				if (console_loglevel == 10)
+					printk("adb_cuda: receiving unsol. packet: %x (%x %x) ", 
+						x, adb_state, status);
+#endif
 				via_write(via1, vBufB, via_read(via1,vBufB)&~TIP);
 			}
+			else if(macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				udelay(150);
+				/* set SR to IN */
+				via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); 
+		 		/* signal start of frame */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+				/* read first byte */
+				x = via_read(via1, vSR);
+				first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+				if (console_loglevel == 10)
+					printk("adb_IIsi : receiving unsol. packet: %x (%x %x) ", 
+						x, adb_state, status);
+#endif
+				/* ACK adb chip */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				udelay(150);
+		 		via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+			}
 			else if(macintosh_config->adb_type==MAC_ADB_II)
 			{
 				if (status != TREQ)
@@ -1469,13 +1704,46 @@
 			if(macintosh_config->adb_type==MAC_ADB_CUDA)
 			{
 				/* CUDA has sent us the first byte of data of a reply */
+#if (ADBDEBUG & ADBDEBUG_STATUS)
 				if (status != TREQ)
 					printk("cuda: state=awaiting_reply, status=%x want=%x\n", 
 						status, TREQ);
+#endif
 				x = via_read(via1, vSR); 
+#if (ADBDEBUG & ADBDEBUG_READ)
+				if (console_loglevel == 10)
+					printk("adb_cuda: reading reply: %x (%x %x) ",
+						x, adb_state, status);
+#endif
 				via_write(via1,vBufB, 
 					via_read(via1, vBufB)&~TIP);
 			}
+			else if(macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				/* udelay(150);*/
+				/* set SR to IN */
+				via_write(via1, vACR,via_read(via1, vACR)&~SR_OUT); 
+		 		/* signal start of frame */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TIP);
+				/* read first byte */
+				x = via_read(via1, vSR);
+				first_byte = x;
+#if (ADBDEBUG & ADBDEBUG_READ)
+				if (console_loglevel == 10)
+					printk("adb_IIsi: reading reply: %x (%x %x) ",
+						x, adb_state, status);
+#endif
+#if 0
+				if( via_read(via1,vBufB) & TREQ)
+					ending = 1;
+				else
+					ending = 0;
+#endif
+				/* ACK adb chip */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				udelay(150);
+		 		via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+			}
 			adb_state = reading;			
 			reply_ptr = current_req->reply;
 			reading_reply = 1;
@@ -1485,11 +1753,16 @@
 		case sent_first_byte:
 			if(macintosh_config->adb_type==MAC_ADB_CUDA)
 			{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+				if (console_loglevel == 10)
+					printk(" sending: %x (%x %x) ",
+						current_req->data[1], adb_state, status);
+#endif
 				if (status == TREQ + TIP + SR_OUT) 
 				{
 					/* collision */
 					if (console_loglevel == 10)
-						printk("cuda: send collision!\n");
+						printk("adb_cuda: send collision!\n");
 					via_write(via1, vACR,
 						via_read(via1, vACR)&~SR_OUT); 
 					x = via_read(via1, vSR); 
@@ -1500,9 +1773,11 @@
 				else
 				{
 					/* assert status == TIP + SR_OUT */
+#if (ADBDEBUG & ADBDEBUG_STATUS)
 					if (status != TIP + SR_OUT)
-						printk("cuda: state=sent_first_byte status=%x want=%x\n", 
+						printk("adb_cuda: state=sent_first_byte status=%x want=%x\n", 
 							status, TIP + SR_OUT);
+#endif
 					via_write(via1,vSR,current_req->data[1]); 
 					via_write(via1, vBufB,
 						via_read(via1, vBufB)^TACK); 
@@ -1510,6 +1785,42 @@
 					adb_state = sending;
 				}
 			}
+			else if(macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				/* switch ACK off */
+				via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+				if ( !(via_read(via1, vBufB) & TREQ) ) 
+				{
+					/* collision */
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+					if (console_loglevel == 10)
+						printk("adb_macIIsi: send collison, aborting!\n");
+#endif
+					/* set shift in */
+					via_write(via1, vACR,
+						via_read(via1, vACR)&~SR_OUT); 
+					/* clear SR int. */
+					x = via_read(via1, vSR); 
+					/* set ADB state to 'idle' */
+					via_write(via1, vBufB,
+						via_read(via1,vBufB) & ~(TIP|TACK)); 
+					adb_state = idle;
+				}
+				else
+				{
+					/* delay */
+					udelay(ADB_DELAY);
+					/* set the shift register to shift out and send a byte */
+#if 0
+					via_write(via1, vACR, via_read(via1, vACR) | SR_OUT); 
+#endif
+					via_write(via1, vSR, current_req->data[1]);
+					/* signal 'byte ready' */
+					via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+					data_index=2;			
+					adb_state = sending;
+				}
+			}
 			else if(macintosh_config->adb_type==MAC_ADB_II)
 			{
 				if(status!=TIP+SR_OUT)
@@ -1527,6 +1838,11 @@
 			req = current_req;
 			if (data_index >= req->nbytes) 
 			{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+				if (console_loglevel == 10)
+					printk(" -> end (%d of %d) (%x %x)!\n",
+						data_index-1, req->nbytes, adb_state, status);
+#endif
 				if(macintosh_config->adb_type==MAC_ADB_CUDA)
 				{
 					via_write(via1, vACR,
@@ -1535,6 +1851,21 @@
 					via_write(via1, vBufB,
 						via_read(via1,vBufB)|TACK|TIP); 
 				}
+				else if(macintosh_config->adb_type==MAC_ADB_IISI)
+				{
+					/* XXX maybe clear ACK here ??? */
+					/* switch ACK off */
+					via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+					/* delay */
+					udelay(ADB_DELAY);
+					/* set the shift register to shift in */
+					via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); 
+					/* clear SR int. */
+					x = via_read(via1, vSR); 
+					/* set ADB state 'idle' (end of frame) */
+					via_write(via1, vBufB,
+						via_read(via1,vBufB) & ~(TACK|TIP)); 
+				}
 				else if(macintosh_config->adb_type==MAC_ADB_II)
 				{
 					via_write(via1, vACR,
@@ -1546,7 +1877,40 @@
 				req->sent = 1;
 				if (req->reply_expected) 
 				{
-					adb_state = awaiting_reply;
+					/* 
+					 * maybe fake a reply here on Listen ?? 
+					 * Otherwise, a Listen hangs on success
+					 * CUDA+IIsi: only ADB Talk considered
+					 * RTC/PRAM read (0x1 0x3) to follow.
+					 */
+					if ( (req->data[0] == 0x0) && ((req->data[1]&0xc) == 0xc) )
+						adb_state = awaiting_reply;
+					else {
+						/*
+						 * Reply expected, but none
+						 * possible -> fake reply.
+						 */
+#if (ADBDEBUG & ADBDEBUG_PROT)
+						printk("ADB: reply expected on Listen, faking reply\n");
+#endif
+						/* make it look weird */
+						/* XXX: return reply_len -1? */
+						/* XXX: fake ADB header? */
+						req->reply[0] = req->reply[1] = req->reply[2] = 0xFF;  
+						req->reply_len = 3;
+						req->got_reply = 1;
+						current_req = req->next;
+						if (req->done)
+							(*req->done)(req);
+						/* 
+						 * ready with this one, run 
+						 * next command !
+						 */
+						/* set state to idle !! */
+						adb_state = idle;
+						if (current_req || retry_req)
+							adb_start();
+					}
 				}
 				else
 				{
@@ -1560,12 +1924,32 @@
 			}
 			else 
 			{
+#if (ADBDEBUG & ADBDEBUG_WRITE)
+				if (console_loglevel == 10)
+					printk(" %x (%x %x) ",
+						req->data[data_index], adb_state, status);
+#endif
 				if(macintosh_config->adb_type==MAC_ADB_CUDA)
 				{
 					via_write(via1, vSR, req->data[data_index++]); 
 					via_write(via1, vBufB, 
 						via_read(via1, vBufB)^TACK); 
 				}
+				else if(macintosh_config->adb_type==MAC_ADB_IISI)
+				{
+					/* switch ACK off */
+					via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+					/* delay */
+					udelay(ADB_DELAY);
+					/* XXX: need to check for collision?? */
+					/* set the shift register to shift out and send a byte */
+#if 0
+					via_write(via1, vACR, via_read(via1, vACR)|SR_OUT); 
+#endif
+					via_write(via1, vSR, req->data[data_index++]);
+					/* signal 'byte ready' */
+					via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				}
 				else if(macintosh_config->adb_type==MAC_ADB_II)
 				{
 					via_write(via1, vSR, req->data[data_index++]);
@@ -1579,14 +1963,17 @@
 			if(reply_len==3 && memcmp(reply_ptr-3,"\xFF\xFF\xFF",3)==0)
 			{
 				/* Terminate the SRQ packet */
-				printk("CUDA: Got an SRQ\n");
+#if (ADBDEBUG & ADBDEBUG_SRQ)
+				if (console_loglevel == 10)
+					printk("adb: Got an SRQ\n");
+#endif
 				adb_state = idle;
 				adb_queue_poll();
 				break;
 			}
 			/* Sanity check - botched in orig. code! */
 			if(reply_len>15) {
-				printk("CUDA: reply buffer overrun!\n");
+				printk("adb_cuda: reply buffer overrun!\n");
 				/* wrap buffer */
 				reply_len=0;
 				if (reading_reply)
@@ -1595,9 +1982,11 @@
 					reply_ptr = cuda_rbuf;
 			}
 			*reply_ptr = via_read(via1, vSR); 
+#if (ADBDEBUG & ADBDEBUG_READ)
 			if (console_loglevel == 10)
-				printk(" %p-> %x (%x %x) ", 
-					reply_ptr, *reply_ptr, adb_state, status);
+				printk(" %x (%x %x) ", 
+					*reply_ptr, adb_state, status);
+#endif
 			reply_ptr++;
 			reply_len++;
 			if(macintosh_config->adb_type==MAC_ADB_CUDA)
@@ -1612,13 +2001,36 @@
 				else 
 				{
 					/* assert status == TIP | TREQ */
+#if (ADBDEBUG & ADBDEBUG_STATUS)
 					if (status != TIP + TREQ)
 						printk("cuda: state=reading status=%x want=%x\n", 
 							status, TIP + TREQ);
+#endif
 					via_write(via1, vBufB, 
 						via_read(via1, vBufB)^TACK); 
 				}
 			}
+			else if (macintosh_config->adb_type==MAC_ADB_IISI)
+			{
+				/* ACK adb chip (maybe check for end first?) */
+		 		via_write(via1, vBufB, via_read(via1, vBufB) | TACK);
+				udelay(150);
+		 		via_write(via1, vBufB, via_read(via1, vBufB) & ~TACK);
+				/* end of frame?? */
+				if (status & TREQ)
+				{
+#if (ADBDEBUG & ADBDEBUG_READ)
+					if (console_loglevel == 10)
+						printk("adb_IIsi: end of frame!\n");
+#endif
+					/* that's all folks */
+					via_write(via1, vBufB,
+						via_read(via1, vBufB) & ~(TACK|TIP)); 
+					adb_state = read_done;
+					/* XXX maybe process read_done here?? 
+					   Handshake anyway?? */
+				}
+			}
 			if(macintosh_config->adb_type==MAC_ADB_II)
 			{
 				if( status == TIP)
@@ -1629,16 +2041,26 @@
 				}
 				else
 				{
+#if (ADBDEBUG & ADBDEBUG_STATUS)
 					if(status!=TIP+TREQ)
 						printk("macII_adb: state=reading status=%x\n", status);
+#endif
 					via_write(via1, vBufB, 
 						via_read(via1, vBufB)^TACK);
 				}
 			}
-			break;
+			/* fall through for IIsi on end of frame */
+			if (macintosh_config->adb_type != MAC_ADB_IISI
+			    || adb_state != read_done)
+				break;
 
 		case read_done:
 			x = via_read(via1, vSR); 
+#if (ADBDEBUG & ADBDEBUG_READ)
+			if (console_loglevel == 10)
+				printk("adb: read done: %x (%x %x)!\n", 
+					x, adb_state, status);
+#endif
 			if (reading_reply) 
 			{
 				req = current_req;
@@ -1653,10 +2075,21 @@
 				adb_input(cuda_rbuf, reply_ptr - cuda_rbuf, regs);
 			}
 
-			if (status == TREQ) 
+			if (macintosh_config->adb_type==MAC_ADB_CUDA 
+			      &&   status & TREQ) 
 			{
 				via_write(via1, vBufB,
-					via_read(via1, vBufB)|~TIP); 
+					via_read(via1, vBufB)&~TIP); 
+				adb_state = reading;
+				reply_ptr = cuda_rbuf;
+				reading_reply = 0;
+			}
+			else if  (macintosh_config->adb_type==MAC_ADB_IISI
+			      && !(status & TREQ))
+			{
+				udelay(150);
+				via_write(via1, vBufB,
+					via_read(via1, vBufB) | TIP); 
 				adb_state = reading;
 				reply_ptr = cuda_rbuf;
 				reading_reply = 0;
@@ -1669,8 +2102,11 @@
 			break;
 
 		default:
-			printk("adb_interrupt: unknown adb_state %d?\n", adb_state);
+			printk("adb_cuda_interrupt: unknown adb_state %d?\n", adb_state);
 	}
+
+	restore_flags(flags);
+
 }
 
 /*
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c
--- v2.1.100/linux/arch/m68k/mac/config.c	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/mac/config.c	Fri May  8 00:15:22 1998
@@ -59,6 +59,12 @@
 
 void *mac_env;		/* Loaded by the boot asm */
 
+/* The locgial video addr. determined by head.S - testing */
+extern unsigned long mac_videobase;
+
+/* The phys. video addr. - might be bogus on some machines */
+unsigned long mac_orig_videoaddr;
+
 extern int mac_keyb_init(void);
 extern int mac_kbdrate(struct kbd_repeat *k);
 extern void mac_kbd_leds(unsigned int leds);
@@ -183,8 +189,6 @@
 	;
 }
 
-extern struct consw fb_con;
-extern struct fb_info *mac_fb_init(long *);
 extern void mac_video_setup(char *, int *);
 
 void mac_debug_init (void)
@@ -213,15 +217,13 @@
     int unknown = 0;
     const u_long *data = record->data;
 
-    if (compat_bi)
-        return(unknown);
-
     switch (record->tag) {
 	case BI_MAC_MODEL:
 	    mac_bi_data.id = *data;
 	    break;
 	case BI_MAC_VADDR:
-	    mac_bi_data.videoaddr = *data;
+	    mac_orig_videoaddr = *data;
+	    mac_bi_data.videoaddr = mac_videobase;
 	    break;
 	case BI_MAC_VDEPTH:
 	    mac_bi_data.videodepth = *data;
@@ -256,39 +258,6 @@
     return(unknown);
 }
 
-__initfunc(void mac_copy_compat(void))
-{
-    int i;
-
-    compat_bi = 1;
-    
-    for (i=0; i<compat_boot_info.num_memory; i++) {
-    	m68k_memory[m68k_num_memory].addr = compat_boot_info.memory[i].addr;
-    	m68k_memory[m68k_num_memory].size = compat_boot_info.memory[i].size;
-	m68k_num_memory++;
-    }
-
-    m68k_ramdisk.addr = compat_boot_info.ramdisk_addr;
-    m68k_ramdisk.size = compat_boot_info.ramdisk_size;
-
-    strncpy(m68k_command_line, (const char *)compat_boot_info.command_line, 
-            CL_SIZE);
-    m68k_command_line[CL_SIZE-1] = '\0';
-                                
-    mac_bi_data.id = compat_boot_info.bi_mac.id;
-    mac_bi_data.videoaddr =  compat_boot_info.bi_mac.videoaddr;
-    mac_bi_data.videodepth = compat_boot_info.bi_mac.videodepth;
-    mac_bi_data.videorow = compat_boot_info.bi_mac.videorow;
-    mac_bi_data.dimensions = compat_boot_info.bi_mac.dimensions;
-    mac_bi_data.videological = compat_boot_info.bi_mac.videological;
-    mac_bi_data.sccbase = compat_boot_info.bi_mac.sccbase;
-    mac_bi_data.boottime = compat_boot_info.bi_mac.boottime;
-    mac_bi_data.gmtbias = compat_boot_info.bi_mac.gmtbias;
-    mac_bi_data.memsize = compat_boot_info.bi_mac.memsize;
-    mac_bi_data.cpuid = compat_boot_info.bi_mac.cpuid;
-
-}
-
 __initfunc(void config_mac(void))
 {
 
@@ -320,8 +289,7 @@
     mach_mksound         = mac_mksound;
 #endif
     mach_reset           = mac_reset;
-#ifdef CONFIG_BLK_DEV_FD
-    mach_floppy_init	 = mac_floppy_init;
+#ifdef CONFIG_MAC_FLOPPY
     mach_floppy_setup	 = mac_floppy_setup;
 #endif
     conswitchp	         = &fb_con;
@@ -361,6 +329,8 @@
      */
 
     nubus_sweep_video();
+
+    mac_debugging_penguin(6);
 }	
 
 
@@ -405,7 +375,7 @@
 	{	MAC_MODEL_CCL,  "Color Classic",	MAC_ADB_IISI,	MAC_VIA_IIci,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,     MAC_ETHER_NONE,	MAC_NUBUS},
 
 	/*
-	 *	Some Mac LC machines. Basically the same as the IIci
+	 *	Some Mac LC machines. Basically the same as the IIci, ADB like IIsi
 	 */
 	
 	{	MAC_MODEL_LCII,	"LC II",  MAC_ADB_IISI,	MAC_VIA_IIci,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
@@ -420,28 +390,24 @@
 	 */	 
 	 
 	{	MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
-	{	MAC_MODEL_Q610, "Quadra 610", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
+	{	MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II,   MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
 	{	MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
- 	{	MAC_MODEL_Q650, "Quadra 650", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
+ 	{	MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II,   MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
 	/*	The Q700 does have a NS Sonic */
-#if 0
-	{	MAC_MODEL_Q700, "Quadra 700", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
-	{	MAC_MODEL_Q800, "Quadra 800", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
-#else
-	{	MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
-	{	MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
-#endif
+	{	MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II,   MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
+	{	MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II,   MAC_VIA_QUADRA, MAC_SCSI_QUADRA,  MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_SONIC,	MAC_NUBUS},
 	/* Does the 840 have ethernet ??? documents seem to indicate its not quite a
 	   Quadra in this respect ? */
 	{	MAC_MODEL_Q840, "Quadra 840", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II,	        MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_Q900, "Quadra 900", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
-	{	MAC_MODEL_Q950, "Quadra 950", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
+	/* These might have IOP problems */
+	{	MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
+	{	MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2,	MAC_ETHER_SONIC,	MAC_NUBUS},
 
 	/* 
 	 *	Performa - more LC type machines
 	 */
 
-	{	MAC_MODEL_P460, "Performa 460", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_P460, "Performa 460", MAC_ADB_IISI, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P475, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	{	MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
@@ -454,37 +420,37 @@
 	 *	Centris - just guessing again; maybe like Quadra
 	 */
 
-	{	MAC_MODEL_C610, "Centris 610",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_C650, "Centris 650",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_C610, "Centris 610",   MAC_ADB_II,   MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_C650, "Centris 650",   MAC_ADB_II,   MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
 
 	/*
 	 *      Power books - seem similar to early Quadras ? (most have 030 though)
 	 */
 
-	{	MAC_MODEL_PB140,  "PowerBook 140",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB145,  "PowerBook 145",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB140,  "PowerBook 140",   MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB145,  "PowerBook 145",   MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
 	/*	The PB150 has IDE, and IIci style VIA */
-	{	MAC_MODEL_PB150,  "PowerBook 150",   MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_QUADRA, MAC_IDE_PB,	  MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB160,  "PowerBook 160",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB165,  "PowerBook 165",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB165C, "PowerBook 165c",  MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB170,  "PowerBook 170",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB180,  "PowerBook 180",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB180C, "PowerBook 180c",  MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB190,  "PowerBook 190cs", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB520,  "PowerBook 520",   MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB150,  "PowerBook 150",   MAC_ADB_PB1, MAC_VIA_IIci,   MAC_SCSI_QUADRA, MAC_IDE_PB,	  MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB160,  "PowerBook 160",   MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB165,  "PowerBook 165",   MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB165C, "PowerBook 165c",  MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB170,  "PowerBook 170",   MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB180,  "PowerBook 180",   MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB180C, "PowerBook 180c",  MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB190,  "PowerBook 190cs", MAC_ADB_PB1, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB520,  "PowerBook 520",   MAC_ADB_PB2, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
 
 	/*
 	 *      Power book Duos - similar to Power books, I hope
 	 */
 
-	{	MAC_MODEL_PB210,  "PowerBook Duo 210",  MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB230,  "PowerBook Duo 230",  MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB250,  "PowerBook Duo 250",  MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB280,  "PowerBook Duo 280",  MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB210,  "PowerBook Duo 210",  MAC_ADB_PB2,  MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB230,  "PowerBook Duo 230",  MAC_ADB_PB2,  MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB250,  "PowerBook Duo 250",  MAC_ADB_PB2,  MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB270C, "PowerBook Duo 270c", MAC_ADB_PB2,  MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB280,  "PowerBook Duo 280",  MAC_ADB_PB2,  MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_PB280C, "PowerBook Duo 280c", MAC_ADB_PB2,  MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA,	MAC_ETHER_NONE,	MAC_NUBUS},
 
 	/*
 	 *	Other stuff ??
@@ -541,14 +507,17 @@
 		mac_bi_data.videoaddr, mac_bi_data.videorow, 
 		mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, 
 		mac_bi_data.dimensions >> 16); 
+	printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+		mac_bi_data.videological, mac_orig_videoaddr, 
+		mac_bi_data.sccbase); 
 	printk (" Boottime: 0x%lx GMTBias: 0x%lx \n",
 		mac_bi_data.boottime, mac_bi_data.gmtbias); 
-	printk (" Videological 0x%lx, SCC at 0x%lx \n",
-		mac_bi_data.videological, mac_bi_data.sccbase); 
 	printk (" Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
 		mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize); 
+#if 0
 	printk ("Ramdisk: addr 0x%lx size 0x%lx\n", 
 		m68k_ramdisk.addr, m68k_ramdisk.size);
+#endif
 
 	/*
 	 *	Save the pointer
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c
--- v2.1.100/linux/arch/m68k/mac/debug.c	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/mac/debug.c	Fri May  8 00:15:22 1998
@@ -16,6 +16,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/init.h>
@@ -131,7 +132,7 @@
 	if (!MACH_IS_MAC) 
 		return;
 
-	if (compat_boot_info.bi_mac.videodepth ==1) 
+	if (mac_videodepth ==1) 
 		pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
 			   +5*peng;
 	else
@@ -163,13 +164,13 @@
 	int i;
 	
 	if(!boomoffset)
-		if (compat_boot_info.bi_mac.videodepth == 1) {
+		if (mac_videodepth == 1) {
 			boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes);
 		} else {
 			boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes);
 		}
 	else
-		if (compat_boot_info.bi_mac.videodepth == 1)
+		if (mac_videodepth == 1)
 			boomoffset+=5;
 		else
 			boomoffset+=32;	
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c
--- v2.1.100/linux/arch/m68k/mac/macints.c	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/mac/macints.c	Fri May  8 00:15:22 1998
@@ -174,8 +174,6 @@
 {
         int i;
 
-	mac_debugging_penguin(6);
-
 #ifdef DEBUG_MACINTS
 	printk("Mac interrupt stuff initializing ...\n");
 #endif
@@ -274,7 +272,6 @@
 	param_table[2]   =   &rbv_param[0];
 	param_table[3]   = &nubus_param[0];
 
-	mac_debugging_penguin(7);
 #ifdef DEBUG_MACINTS
 	printk("Mac interrupt init done!\n");
 #endif
@@ -626,7 +623,7 @@
 	 
 	if(events==0)
 	{
-		printk("via_irq: nothing pending!\n");
+		printk("via%d_irq: nothing pending!\n", *viaidx + 1);
 		return;
 	}
 
@@ -869,14 +866,14 @@
  
 static int nubus_active=0;
  
-int nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *))
+int nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *))
 {
 	slot-=9;
 /*	printk("Nubus request irq for slot %d\n",slot);*/
 	if(nubus_handler[slot].handler!=nubus_wtf)
 		return -EBUSY;
 	nubus_handler[slot].handler=handler;
-	nubus_handler[slot].dev_id =handler;
+	nubus_handler[slot].dev_id =dev_id;
 	nubus_param[slot].flags    = IRQ_FLG_LOCK;
 	nubus_param[slot].devname  = "nubus";
 
@@ -964,7 +961,7 @@
 		{
 			if(map&(1<<i))
 			{
-				(nubus_handler[i].handler)(i+9, via, regs);
+				(nubus_handler[i].handler)(i+9, nubus_handler[i].dev_id, regs);
 			}
 		}
 		/* clear it */
diff -u --recursive --new-file v2.1.100/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.1.100/linux/arch/m68k/mm/init.c	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/mm/init.c	Fri May  8 00:15:22 1998
@@ -30,6 +30,40 @@
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void init_kpointer_table(void);
 extern void show_net_buffers(void);
+extern const char PgtabStr_bad_pmd[];
+
+struct pgtable_cache_struct quicklists;
+
+void __bad_pte(pmd_t *pmd)
+{
+	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+	pmd_set(pmd, BAD_PAGETABLE);
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+	pte_t *pte;
+
+	pte = (pte_t *) __get_free_page(GFP_KERNEL);
+	if (pmd_none(*pmd)) {
+		if (pte) {
+			memset(pte, 0, PAGE_SIZE)
+ 			flush_page_to_ram((unsigned long)pte);
+			flush_tlb_kernel_page((unsigned long)pte);
+			nocache_page((unsigned long)pte);
+			pmd_set(pmd, pte);
+			return pte + offset;
+		}
+		pmd_set(pmd, BAD_PAGETABLE);
+		return NULL;
+	}
+	free_page((unsigned long)pte);
+	if (pmd_bad(*pmd)) {
+		__bad_pte(pmd);
+		return NULL;
+	}
+	return (pte_t *) pmd_page(*pmd) + offset;
+}
 
 /*
  * BAD_PAGE is the page that is used for page faults when linux
@@ -76,7 +110,7 @@
 	total++;
 	if (PageReserved(mem_map+i))
 	    reserved++;
-	if (PageSwapCache(mem_map+i))
+	else if (PageSwapCache(mem_map+i))
 	    cached++;
 	else if (!atomic_read(&mem_map[i].count))
 	    free++;
@@ -91,6 +125,7 @@
     printk("%d pages nonshared\n",nonshared);
     printk("%d pages shared\n",shared);
     printk("%d pages swap cached\n",cached);
+    printk("%d pages in page table cache\n",pgtable_cache_size);
     show_buffers();
 #ifdef CONFIG_NET
     show_net_buffers();
diff -u --recursive --new-file v2.1.100/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v2.1.100/linux/arch/mips/Makefile	Tue Mar 10 10:03:30 1998
+++ linux/arch/mips/Makefile	Fri May  8 00:13:22 1998
@@ -13,7 +13,7 @@
 # Copyright (C) 1994, 1995, 1996 by Ralf Baechle
 # DECStation modifications by Paul M. Antoine, 1996
 #
-# $Id: Makefile,v 1.9 1997/09/19 08:34:54 ralf Exp $
+# $Id: Makefile,v 1.14 1998/05/01 01:33:20 ralf Exp $
 #
 
 #
@@ -100,31 +100,12 @@
 SUBDIRS       += arch/mips/algor
 #LOADADDR      += 0x80000000
 endif
-ifdef CONFIG_DECSTATION
-CORE_FILES    += arch/mips/dec/dec.o
-SUBDIRS       += arch/mips/dec
-LINKSCRIPT    += arch/mips/dec/ld.script
-LOADADDR      += 0x80000000
-endif
-ifdef CONFIG_DESKSTATION_RPC44
-CORE_FILES    += arch/mips/deskstation/deskstation.o
-SUBDIRS       += arch/mips/deskstation
-LOADADDR      += 0x80100000
-endif
-ifdef CONFIG_DESKSTATION_TYNE
-CORE_FILES    += arch/mips/deskstation/deskstation.o
-SUBDIRS       += arch/mips/deskstation
-LOADADDR      += 0x80000000
-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
-endif
-ifdef CONFIG_MIPS_MAGNUM_3000
 LOADADDR      += 0x80000000
 endif
 ifdef CONFIG_SNI_RM200_PCI
diff -u --recursive --new-file v2.1.100/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.1.100/linux/arch/mips/config.in	Tue Mar 17 22:18:14 1998
+++ linux/arch/mips/config.in	Fri May  8 00:13:22 1998
@@ -14,20 +14,10 @@
 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 DECstation' CONFIG_DECSTATION
-  bool 'Support for Deskstation RPC44' CONFIG_DESKSTATION_RPC44
-  bool 'Support for Deskstation Tyne' CONFIG_DESKSTATION_TYNE
-  bool 'Support for Mips Magnum 3000' CONFIG_MIPS_MAGNUM_3000
 fi
 bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  bool 'Support for SGI workstations' CONFIG_SGI
-  if [ "$CONFIG_SGI" = "y" ]; then
-    bool 'Support for SGI graphic devices' CONFIG_SGI_GRAPHICS
-    define_bool CONFIG_UMISC y
-  fi
-fi
+bool 'Support for SGI workstations' CONFIG_SGI
 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
 
 #
@@ -42,18 +32,15 @@
 fi
 if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
-       define_bool CONFIG_VIDEO_G364 y
+	define_bool CONFIG_MIPS_JAZZ y
+	define_bool CONFIG_VIDEO_G364 y
+	define_bool CONFIG_VGA_CONSOLE y
 fi
-if [ "$CONFIG_DESKSTATION_RPC44" = "y" -o \
-     "$CONFIG_DESKSTATION_TYNE" = "y" ]; then
-	define_bool CONFIG_MIPS_ARC y
-fi
-if [ "$CONFIG_ACER_PICA_61" = "y" -o \
-     "$CONFIG_OLIVETTI_M700" = "y" -o \
-     "$CONFIG_MIPS_MAGNUM_4000" = "y" ]; then
+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
@@ -96,12 +83,12 @@
 
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
 if [ "$CONFIG_SGI" != "y" ]; then
   tristate 'Parallel port support' CONFIG_PARPORT
 fi
-
 endmenu
 
 mainmenu_option next_comment
@@ -111,6 +98,7 @@
   bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
   bool 'Kernel module loader' CONFIG_KMOD
 fi
+endmenu
 
 source drivers/block/Config.in
 
@@ -174,6 +162,8 @@
 fi
 
 if [ "$CONFIG_SGI" != "y" ]; then
+	source drivers/net/hamradio/Config.in
+
 	mainmenu_option next_comment
 	comment 'ISDN subsystem'
 
@@ -193,32 +183,34 @@
 	endmenu
 fi
 
+# Conditionally compile in the Uniform CD-ROM driver
+if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_CM206" = "y" -o "$CONFIG_CDU31A" = "y" ]; then
+  define_bool CONFIG_CDROM y
+else
+  if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" -o "$CONFIG_SBPCD" = "m" -o "$CONFIG_MCD" = "m" -o "$CONFIG_CM206" = "m" -o "$CONFIG_CDU31A" = "m" ]; then
+    define_bool CONFIG_CDROM m
+  else
+    define_bool CONFIG_CDROM n
+  fi
+fi
+
 source fs/Config.in
 
 source fs/nls/Config.in
 
-if [ "$CONFIG_SGI" != "y" ]; then
-  source drivers/char/Config.in
+source drivers/char/Config.in
 
-  mainmenu_option next_comment
-  comment 'Sound'
+mainmenu_option next_comment
+comment 'Sound'
 
-  tristate 'Sound card support' CONFIG_SOUND
-  if [ "$CONFIG_SOUND" != "n" ]; then
-    source drivers/sound/Config.in
-  fi
-  endmenu
-else
-  comment 'SGI Character Devices'
-  bool 'Virtual terminal' CONFIG_VT
-  if [ "$CONFIG_VT" = "y" ]; then
-    bool 'Console on virtual terminal' CONFIG_VT_CONSOLE
-  fi
-  tristate 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
-  bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL
-  if [ "$CONFIG_SGI_SERIAL" != "n" ]; then
-    define_bool CONFIG_SERIAL y
-  fi
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+  source drivers/sound/Config.in
+fi
+endmenu
+
+if [ "$CONFIG_SGI" = "y" ]; then
+  source drivers/sgi/char/Config.in
 fi
 
 mainmenu_option next_comment
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile
--- v2.1.100/linux/arch/mips/dec/Makefile	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/dec/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,24 +0,0 @@
-#
-# 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	 := boot.o int-handler.o decstation.o hw-access.o reset.o setup.o
-
-boot.o:	boot.S
-
-int-handler.o:	int-handler.S
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/boot.S linux/arch/mips/dec/boot.S
--- v2.1.100/linux/arch/mips/dec/boot.S	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/dec/boot.S	Wed Dec 31 16:00:00 1969
@@ -1,92 +0,0 @@
-/*
- * arch/mips/dec/boot.S
- *
- * Copyright (C) 1995, 1996 Paul M. Antoine
- *
- * Written by Ralf Baechle and Andreas Busse, modified for DECStation
- * support by Paul Antoine.
- *
- * NOTE: There are references to R4X00 code in here, because there is an
- *	 upgrade module for Personal DECStations with such a CPU!
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/bootinfo.h>
-
-/*
- * dec_entry: Called by the boot PROM loader to do DECStation setup, prior
- *	      to calling dec_setup() to fill in the boot_info structure.
- *
- *	      This code should also go in the boot loader for loading off
- *	      floppy and HD... in addition to the tags code in dec_setup().
- *
- *   FIXME:   arrange for this code only to be linked in when building a
- *	      kernel image to be booted via tftp from the boot prom??
- */
-		.text
-		.globl	dec_entry
-dec_entry:
-		/* Save the address of the REX call vector for later
-		 * use in printing debug messages.
-		 */
-		sw	a3,pmax_rex_base
-		sw	a2,rex_prom_magic
-		la	a0,dec_signon
-		jal	pmax_printf
-		nop
-
-		/* Now set up the bootinfo with things that
-		 * should be loaded by the boot loader, except that
-		 * for the moment we're booting using tftp.
-		 */
-		jal	dec_setup
-		nop
-/*
- * Now we need to move exception vector handler routines that appear
- * in head.S down to the right addresses, 'cos the DECStation loads
- * kernels at 0x80030000... <sigh>
- */
-
-/*
- * First move the TLB refill code down to offset 0x000, at addr 0x80000000
- */
-		la	t0,except_vec0		# begining of exception code
-		la	t1,except_vec1		# end of exception code
-		la	t2,0x80000000		# where the code should live
-		lw	t3,(t0)			# get first word
-1:		sw	t3,(t2)			# put it where it should go
-		addiu	t0,4			# increment both pointers
-		addiu	t2,4
-		lw	t3,(t0)			# will be in the delay slot
-		bne	t0,t1,1b
-/*
- * Now move the General Exception code down to offset 0x080 at 0x80000000
- */
-		la	t0,except_vec3		# begining of general exception code
-		la	t1,end_except		# end of general exception code
-		la	t2,0x80000080		# where the code should live
-		lw	t3,(t0)			# get first word
-1:		sw	t3,(t2)
-		addiu	t0,4
-		addiu	t2,4
-		lw	t3,(t0)
-		bne	t0,t1,1b
-
-		la	a0,dec_launch		# say where we are going
-		jal	pmax_printf
-		nop
-
-		la	t0,mach_mem_upper	# get upper memory bound
-		lw	a0,(t0)
-		j	kernel_entry
-		nop
-
-		.data
-		.align	2
-dec_signon:	.ascii	"\n\nLinux/MIPS DECStation Boot\n";
-		.asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n";
-dec_launch:	.asciiz	"Setup complete, launching kernel...\n";
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/decstation.S linux/arch/mips/dec/decstation.S
--- v2.1.100/linux/arch/mips/dec/decstation.S	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/dec/decstation.S	Wed Dec 31 16:00:00 1969
@@ -1,369 +0,0 @@
-/*
- * arch/mips/kernel/decstation.S
- *
- * Copyright (C) 1995, 1996 Paul M. Antoine
- *
- * Written by Ralf Baechle and Andreas Busse, modified for DECStation
- * support by Paul Antoine.
- *
- * NOTE: There are references to R4X00 code in here, because I believe
- * 	 that there is an upgrade module for Personal DECStations with
- *	 such CPU's!
- *
- * FIXME: still plenty to do in this file, as much of the code towards
- * 	  the end hasn't been modified to suit the DECStation's interrupts.
- *        (Paul, you need to fix this file to comply with NAPS.  Won't be
- *         too hard - Ralf)
- */
-#include <asm/asm.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/decstation.h>
-#include <asm/stackframe.h>
-#include <asm/bootinfo.h>
-
-/*
- * dec_entry: Called at boot in head.S to do DECStation setup, and to
- * fill in the boot_info structure.
- */
-		.text
-		.globl	dec_entry
-dec_entry:
-		/* Save the address of the REX call vector for later
-		 * use in printing debug messages.
-		 */
-		sw	a3,pmax_rex_base
-		la	a0,dec_signon
-		jal	pmax_printf
-		nop
-		/* Now set up the bootinfo structure with things that
-		 * should be loaded by the boot loader, except that
-		 * for the moment we're booting using tftp.
-		 */
-		la	t0,boot_info
-		li	t1,0x40			# 64 TLB entries
-/*
- * FIXME: Ideally, all DEC workstations should be supported, so here we
- *	  should put some clevernesses to determine machine type and CPU
- *	  type.  Needs a hierarchy of DEC machine types.  Perhaps Machine
- *	  AND Model fields in bootinfo structure?
- */
-		sw	t1,OFFSET_BOOTINFO_TLB_ENTRIES(t0)
-		li	t1,MACH_DECSTATION	# Machine type
-		sw	t1,(t0)
-		li	t1,CPU_R3000A		# CPU type
-		sw	t1,OFFSET_BOOTINFO_CPUTYPE(t0)
-/*
- * FIXME: the following should find the memory size from the boot PROM
- */
-		li	t1,0x80000000		# Lower memory bound
-		sw	t1,OFFSET_BOOTINFO_MEMLOWER(t0)
-		li	t1,0x88000000		# Upper memory bound (8MB)
-		sw	t1,OFFSET_BOOTINFO_MEMUPPER(t0)
-/*
- * FIXME: the following should determine the cache size a la the method
- *	  used in MACH.  For now we just guess - PMA.
- */
-		li	t1,0x100000		# 64K icache
-		sw	t1,OFFSET_BOOTINFO_ICACHE_SIZE(t0)
-		li	t1,0x100000		# 64K dcache
-		sw	t1,OFFSET_BOOTINFO_DCACHE_SIZE(t0)
-
-/*
- * FIXME: template for other bootinfo fields that probably need filling in...
- *
-		li	t1,0x80000000
-		sw	t1,OFFSET_BOOTINFO_(t0)
-*/
-
-/*
- * Now we need to move exception vector handler routines that appear
- * in head.S down to the right addresses, 'cos the DECStation loads
- * kernels at 0x80030000... <sigh>
- */
-
-/*
- * First move the TLB refill code down to offset 0x000, at addr 0x80000000
- */
-		la	t0,except_vec0		# begining of TLB exception code
-		la	t1,except_vec1		# end of TLB exception code
-		la	t2,0x80000000		# where the code should live
-		lw	t3,(t0)			# get first word
-1:		sw	t3,(t2)			# put it where it should go
-		addiu	t0,4			# increment both pointers
-		addiu	t2,4
-		lw	t3,(t0)			# will be in the delay slot
-		bne	t0,t1,1b
-
-/*
- * Now move the General Exception code down to offset 0x080 at 0x80000000
- */
-		la	t0,except_vec3		# begining of general exception code
-		la	t1,kernel_entry		# end of general exception code
-		la	t2,0x80000080		# where the code should live
-		lw	t3,(t0)			# get first word
-1:		sw	t3,(t2)
-		addiu	t0,4
-		addiu	t2,4
-		lw	t3,(t0)
-		bne	t0,t1,1b
-
-/*
- * FIXME: Don't forget to set the gp regster... why do I need this?
- */
-		la	gp,_gp
-		la	a0,dec_launch		# say where we are going
-		jal	pmax_printf
-		nop
-		j	kernel_entry
-		nop
-
-		.data
-		.align	2
-dec_signon:	.ascii	"\n\nLinux/MIPS DECStation Boot\n";
-		.asciiz "Copyright (C) Paul M. Antoine 1995, 1996 and others, 1994, 1995, 1996\n\n";
-dec_launch:	.asciiz	"Launching kernel...\n";
-		.text
-		.set	noreorder
-/*
- * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x
- *
- * FIXME: this is *extremely* experimental, though it is probably o.k. for
- *	  most DECStation models.
- */
-		NESTED(decstation_handle_int, FR_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		REG_S	sp,FR_ORIG_REG2(sp)
-		CLI
-		.set	at
-
-		/*
-		 * Get pending interrupts
-		 */
-		mfc0	t0,CP0_CAUSE		# get pending interrupts
-		mfc0	t1,CP0_STATUS		# get enabled interrupts
-		and	t0,t1			# isolate allowed ones
-		andi	t0,0xff00		# isolate pending bits
-/*
- * FIXME: The following branch was:
- *					beqz	t0,spurious_interrupt
- *
- *	  ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 )
- *	  to complain:
- *
- *		  "Can not represent relocation in this object file format"...
- *
- *	  hence this hack to branch foward a bit, and then jump <sigh>
- *	  Perhaps a later version of gas will cope? - Paul
- *	  (No, this is impossible in COFF as well as in ELF. - Ralf)
- */
-		beqz	t0,3f;
-		sll	t0,16			# delay slot
-
-		/*
-		 * Find irq with highest priority
-		 * FIXME: This is slow
-		 */
-		la	t1,ll_vectors
-1:		bltz	t0,2f			# found pending irq
-		sll	t0,1
-		b	1b
-		subu	t1,PTRSIZE		# delay slot
-
-		/*
-		 * Do the low-level stuff
-		 */
-		.set	reorder
-2:		LOAD_L	t0,(t1)
-		jr	t0
-		.set	noreorder
-		END(decstation_handle_int)
-
-/*
- * FIXME: The hack mentioned above.
- */
-3:		j	spurious_interrupt
-		nop
-
-/*
- * FIXME: the rest of this is pretty suspect, as it's straight from
- * 	  jazz.S... and I really haven't altered it at all - Paul
- */
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- * (Paul, even for i386 this is no longer being used -- Ralf)
- */
-ll_sw0:		li	s1,~IE_SW0
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-	PRINT("sw0 received...\n")
-		li	t1,1
-		b	call_real
-		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
-
-ll_sw1:		li	s1,~IE_SW1
-		PANIC("Unimplemented sw1 handler")
-
-loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
-loc_sound:	PANIC("Unimplemented loc_sound handler")
-loc_video:	PANIC("Unimplemented loc_video handler")
-loc_scsi:	PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Ethernet interrupt, remapped to level 15
- * NOTE: Due to a bug somewhere in the kernel I was not able
- * to figure out, the PRINT() is necessary. Without this,
- * I get a "gfp called nonatomically from interrupt 00000000".
- * Only god knows why... Tell me if you find the reason!
- * (You were fouled by the caches and this is the wrong file for this
- *  comment - Ralf)
- * Andy, 6/16/95
- */
-loc_ethernet:	PANIC("Unimplemented loc_ethernet\n")
-
-/*
- * Keyboard interrupt, remapped to level 1
- */
-loc_keyboard:	PANIC("Unimplemented loc_keyboard\n")
-
-loc_mouse:	PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1:	PANIC("Unimplemented loc_serial handler")
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2:	PANIC("Unimplemented loc_serial handler")
-
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel:	PANIC("Unimplemented loc_parallel handler")
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy:	PANIC("Unimplemented loc_floppy handler")
-  
-/*
- * Now call the real handler
- */
-loc_call:	la	t0,IRQ_vectors			# delay slot
-
-		/*
-		 * Temporarily disable interrupt source
-		 */
-/*		lhu	t2,JAZZ_IO_IRQ_ENABLE
-*/
-		addu	t0,t3			# make ptr to IRQ handler
-		LOAD_L	t0,(t0)
-		and	t2,s1			# delay slot
-/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
-		jalr	t0			# call IRQ handler
-		nor	s1,zero,s1		# delay slot
-
-		/*
-		 * Reenable interrupt
-		 */
-/*		lhu	t2,JAZZ_IO_IRQ_ENABLE */
-		or	t2,s1
-/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
-
-		jr	v0
-		nop				# delay slot
-
-ll_tc3:		PANIC("Unimplemented tc3 interrupt handler")
-
-ll_fpu:		PANIC("Unimplemented fpu interrupt handler")
-
-ll_io_error:	PANIC("Unimplemented I/O write timeout interrupt handler")
-
-ll_rtc:		PANIC("Unimplemented RTC interrupt handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to a IBM compatible
- */
-ll_timer:	PANIC("Timer interrupt!\n");
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_reset:	li	a0,0
-		jal	pmax_halt
-		li	a1,0			# delay slot
-
-/*
- * Now call the real handler
- */
-call_real:	la	t0,IRQ_vectors			# delay slot
-
-		/*
-		 * temporarily disable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		and	t2,s1
-
-		addu	t0,t3
-		LOAD_L	t0,(t0)
-		mtc0	t2,CP0_STATUS		# delay slot
-		jalr	t0
-		nor	s1,zero,s1		# delay slot
-
-		/*
-		 * reenable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		or	t2,s1
-		mtc0	t2,CP0_STATUS
-
-		jr	v0
-		nop				# delay slot
-
-/*
- * Just for debugging... load a0 with address of the point inside the
- * framebuffer at which you want to draw a line of 16x32 pixels.
- * Maxine's framebuffer starts at 0xaa000000.
- */
-		.set	reorder
-		LEAF(drawline)
-		li	t1,0xffffffff		# set all pixels on
-		li	t2,0x10			# we will write 16 words
-1:		sw	t1,(a0)			# write the first word
-		addiu	a0,a0,4			# move our framebuffer pointer
-		addiu	t2,t2,-1		# one less to do
-		bnez	t2,1b			# finished?
-		jr 	ra
-		END(drawline)
-
-/*
- * FIXME: I have begun to alter this table to reflect Personal DECStation
- *	  (i.e. Maxine) interrupts... Paul.
- */
-		.data
-		PTR	ll_sw0			# SW0
-		PTR	ll_sw1			# SW1
-		PTR	ll_timer		# Periodic interrupt
-		PTR	ll_rtc			# RTC periodic interrupt
-		PTR	ll_io_error		# Timeout on I/O writes
-		PTR	ll_tc3			# TC slot 3, motherboard
-		PTR	ll_reset		# Halt keycode (CTRL+ALT+ENTER)
-ll_vectors:	PTR	ll_fpu			# FPU
-
-local_vector:	PTR	loc_no_irq
-		PTR	loc_parallel
-		PTR	loc_floppy
-		PTR	loc_sound
-		PTR	loc_video
-		PTR	loc_ethernet
-		PTR	loc_scsi
-		PTR	loc_keyboard
-		PTR	loc_mouse
-		PTR	loc_serial1
-		PTR	loc_serial2
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/decstation.c linux/arch/mips/dec/decstation.c
--- v2.1.100/linux/arch/mips/dec/decstation.c	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/dec/decstation.c	Wed Dec 31 16:00:00 1969
@@ -1,200 +0,0 @@
-/*
- * arch/mips/dec/decstation.c
- *
- * Copyright (C) 1996 Paul M. Antoine
- *
- * Written by Paul Antoine.
- *
- * FIXME: still plenty to do in this file, as we don't yet fully fill
- *        the boot info structure with DEC-specific tags.  Also still
- *	  too specific to the Person Decstattion 5000/2x!!
- */
-
-#include <asm/dec/decstation.h>
-#include <asm/dec/maxine.h>	/* FIXME: what about other decstations? */
-#include <asm/bootinfo.h>
-
-/*
- * dec_setup: Called at boot from dec_entry() in boot.S to do 
- *            DECStation-specific setup, and to fill in the kernel argument
- *            tags.
- *
- * FIXME: I'm not sure all DEC workstations are correctly supported.  This
- *        code may not need to be here when booting off floppy or HD??
- */
-
-unsigned long mach_mem_upper = 0;
-unsigned long mach_mem_lower = 0;
-unsigned long mips_dcache_size = 0;
-unsigned long mips_icache_size = 0;
-unsigned long rex_prom_magic; /* from boot.S */
-unsigned long dec_get_memory_size(void);
-
-void dec_setup(void)
-{
-    unsigned long int mem_mask = 0;
-    unsigned long tag_data_dummy, dec_sysid;
-    unsigned char dec_cpunum, dec_systype, dec_firmrev, dec_etc;
-    extern const char *linux_banner;
-
-    pmax_printf("%s\n", linux_banner);
-    /* First we need the memory upper bound before we can add tag entries... */
-    mach_mem_lower = 0x80000000L;
-    mach_mem_upper = mach_mem_lower + dec_get_memory_size();
-
-    /* First tag is always memory upper limit, right Stoned?? */
-    (void)bi_TagAdd(tag_memupper, ULONGSIZE, &mach_mem_upper);
-
-    /* We're obviously one of the DEC machines */
-    tag_data_dummy = MACH_GROUP_DEC;
-    (void)bi_TagAdd(tag_machgroup, ULONGSIZE, &tag_data_dummy);
-
-    /* Now let's try to figure out what type of DECStation we are */
-    pmax_printf("System id is: ");
-    if ((dec_sysid = pmax_getsysid()) != 0)
-      pmax_printf("%x\n", dec_sysid);
-    else
-      pmax_printf("unknown\n");
-
-    dec_cpunum = (dec_sysid & 0xff000000) >> 24;
-    dec_systype = (dec_sysid & 0xff0000) >> 16;
-    dec_firmrev = (dec_sysid & 0xff00) >> 8;
-    dec_etc = dec_sysid & 0xff;
-
-    /*
-     * FIXME: for now use the PROM to determine the CPU type - should
-     *        probably just get the CPU to tell us.
-     */
-    pmax_printf("System has an ");
-    switch(dec_cpunum)
-    {
-	case 0x82:
-	    {
-	        pmax_printf("R3000 CPU\n");
-		tag_data_dummy = CPU_R3000A;
-		break;
-	    }
-	case 0x84:
-	    {
-	        pmax_printf("R4000 CPU\n");
-		/* FIXME: assume a plain R4000PC for now */
-		tag_data_dummy = CPU_R4000PC;
-		break;
-	    }
-    	default:
-	    {
-	        pmax_printf("unknown CPU, code is %x\n", dec_cpunum);
-		/* FIXME: assume an R2000 for now */
-		tag_data_dummy = CPU_R2000;
-		break;
-	    }
-    }
-    /* Add the CPU type */
-    (void)bi_TagAdd(tag_cputype, ULONGSIZE, &tag_data_dummy);
-
-    pmax_printf("System has firmware type: ");
-    if (dec_firmrev == 2)
-      pmax_printf("TCF0\n");
-    else
-      pmax_printf("TCF1\n");
-
-    pmax_printf("This DECStation is a: ");
-    switch(dec_systype) {
-    case 1: /* DS2100/3100 Pmax */
-            pmax_printf("DS2100/3100\n");
-	    tag_data_dummy = MACH_DECSTATION;
-	    break;
-    case 2: /* DS5000 3max */
-            pmax_printf("DS5000\n");
-	    tag_data_dummy = MACH_DECSTATION;
-	    break;
-    case 3: /* DS5000/100 3min */
-            pmax_printf("DS5000/1x0\n");
-	    tag_data_dummy = MACH_DECSTATION;
-	    break;
-    case 7: /* Personal DS5000/2x */
-            pmax_printf("Personal DS5000/2x\n");
-	    tag_data_dummy = MACH_DECSTATION;
-	    break;
-    default:
-            pmax_printf("unknown, id is: %x\n", dec_systype);
-	    tag_data_dummy = MACH_UNKNOWN;
-	    break;
-    }
-
-    /* Add the machine type */
-    (void)bi_TagAdd(tag_machtype, ULONGSIZE, &tag_data_dummy);
-
-    /* Add the number of tlb entries */
-    tag_data_dummy = 64;
-    (void)bi_TagAdd(tag_tlb_entries, ULONGSIZE, &tag_data_dummy);
-
-    /*
-     * Add the instruction cache size
-     * FIXME: should determine this somehow
-     */
-    tag_data_dummy = 0x100000;		/* set it to 64K for now */
-    (void)bi_TagAdd(tag_icache_size, ULONGSIZE, &tag_data_dummy);
-    mips_icache_size = tag_data_dummy;
-
-    /*
-     * Add the data cache size
-     * FIXME: should determine this somehow
-     */
-    tag_data_dummy = 0x100000;		/* set it to 64K for now */
-    (void)bi_TagAdd(tag_dcache_size, ULONGSIZE, &tag_data_dummy);
-    mips_dcache_size = tag_data_dummy;
-
-    /* FIXME: should determine vram_base properly */
-    tag_data_dummy = 0xa8000000;
-    (void)bi_TagAdd(tag_vram_base, ULONGSIZE, &tag_data_dummy);
-
-    /* FIXME: dummy drive info tag */
-    tag_data_dummy = 0;
-    (void)bi_TagAdd(tag_drive_info, ULONGSIZE, &tag_data_dummy);
-
-    /* FIXME: do we need a dummy tag at the end? */
-    tag_data_dummy = 0;
-    (void)bi_TagAdd(tag_dummy, 0, &tag_data_dummy);
-
-    pmax_printf("Added tags\n");
-} /* dec_setup */
-
-unsigned long dec_get_memory_size()
-{
-    int i, bitmap_size;
-    unsigned long mem_size = 0;
-    struct pmax_bitmap {
-      int		pagesize;
-      unsigned char	bitmap[64*1024*1024 - 4];
-    } *bm;
-
-    /* some free 64k */
-    bm = (struct pmax_bitmap *)0x8002f000;
-    bitmap_size = pmax_getbitmap(bm);
-
-    pmax_printf("Page size is: %x\n", bm->pagesize);
-    pmax_printf("Bitmap size is: %d bytes\n", bitmap_size);
-
-    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);
-    }
-    pmax_printf("Main memory size is: %d KB\n", (mem_size / 1024));
-    return(mem_size);
-} /* dec_get_memory_size */
-
-unsigned char maxine_rtc_read_data(unsigned long addr)
-{
-    char *rtc = (char *)(PMAX_RTC_BASE);
-    return(rtc[addr * 4]);
-} /* maxine_rtc_read_data */
-
-void maxine_rtc_write_data(unsigned char data, unsigned long addr)
-{
-    char *rtc = (char *)(PMAX_RTC_BASE);
-    rtc[addr * 4] = data;
-} /* maxine_rtc_read_data */
-
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/hw-access.c linux/arch/mips/dec/hw-access.c
--- v2.1.100/linux/arch/mips/dec/hw-access.c	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/dec/hw-access.c	Wed Dec 31 16:00:00 1969
@@ -1,26 +0,0 @@
-/*
- * DECstation specific hardware access code.
- *
- * 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 Paul Antoine
- */
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <asm/mc146818rtc.h>
-#include <asm/vector.h>
-
-asmlinkage void decstation_handle_int(void);
-extern unsigned char maxine_rtc_read_data(unsigned long);
-extern void maxine_rtc_write_data(unsigned char, unsigned long);
-
-/*
- * FIXME: Don't have any of the goo required to access fd etc.
- */
-struct feature decstation_feature = {
-	0,0,0,0,0,0,0,0,0,0,0,0,0,
-	maxine_rtc_read_data,
-	maxine_rtc_write_data
-};
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/int-handler.S linux/arch/mips/dec/int-handler.S
--- v2.1.100/linux/arch/mips/dec/int-handler.S	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/dec/int-handler.S	Wed Dec 31 16:00:00 1969
@@ -1,260 +0,0 @@
-/*
- * arch/mips/dec/int-handler.S
- *
- * Copyright (C) 1995, 1996 Paul M. Antoine
- *
- * Written by Ralf Baechle and Andreas Busse, modified for DECStation
- * support by Paul Antoine.
- *
- * NOTE: There are references to R4X00 code in here, because there is an
- *	 upgrade module for Personal DECStations with such a CPU!
- *
- * FIXME: still plenty to do in this file, as much of the code hasn't been
- *	  modified to suit the DECStation's interrupts.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/bootinfo.h>
-
-		.text
-		.set	noreorder
-/*
- * decstation_handle_int: Interrupt handler for Personal DECStation 5000/2x
- *
- * FIXME: this is *extremely* experimental, though it is probably o.k. for
- *	  most DECStation models.
- */
-		NESTED(decstation_handle_int, FR_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		CLI
-		.set	at
-
-		/*
-		 * Get pending interrupts
-		 */
-		mfc0	t0,CP0_CAUSE		# get pending interrupts
-		mfc0	t1,CP0_STATUS		# get enabled interrupts
-		and	t0,t1			# isolate allowed ones
-		andi	t0,0xff00		# isolate pending bits
-/*
- * FIXME: The following branch was:
- *					beqz	t0,spurious_interrupt
- *
- *	  ...but the wonders of ecoff cause the gas assembler (ver 2.5.1 )
- *	  to complain:
- *
- *		  "Can not represent relocation in this object file format"...
- *
- *	  hence this hack to branch foward a bit, and then jump <sigh>
- *	  Perhaps a later version of gas will cope? - Paul
- */
-		beqz	t0,3f;
-		sll	t0,16			# delay slot
-
-		/*
-		 * Find irq with highest priority
-		 * FIXME: This is slow
-		 */
-		la	t1,ll_vectors
-1:		bltz	t0,2f			# found pending irq
-		sll	t0,1
-		b	1b
-		subu	t1,PTRSIZE		# delay slot
-
-		/*
-		 * Do the low-level stuff
-		 */
-2:		lw	t0,(t1)
-		jr	t0
-		nop				# delay slot
-		END(decstation_handle_int)
-
-/*
- * FIXME: The hack mentioned above.
- */
-3:		j	spurious_interrupt
-		nop
-
-/*
- * FIXME: the rest of this is pretty suspect, as it's straight from
- * 	  jazz.S... and I really haven't altered it at all - Paul
- */
-
-/*
- * Used for keyboard driver's fake_keyboard_interrupt()
- * (Paul, even for i386 this is no longer being used -- Ralf)
- */
-ll_sw0:		li	s1,~IE_SW0
-		mfc0	t0,CP0_CAUSE
-		and	t0,s1
-		mtc0	t0,CP0_CAUSE
-	PRINT("sw0 received...\n")
-		li	t1,1
-		b	call_real
-		li	t3,PTRSIZE	# delay slot, re-map to irq level 1
-
-ll_sw1:		li	s1,~IE_SW1
-		PANIC("Unimplemented sw1 handler")
-
-loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
-loc_sound:	PANIC("Unimplemented loc_sound handler")
-loc_video:	PANIC("Unimplemented loc_video handler")
-loc_scsi:	PANIC("Unimplemented loc_scsi handler")
-
-/*
- * Ethernet interrupt, remapped to level 15
- * NOTE: Due to a bug somewhere in the kernel I was not able
- * to figure out, the PRINT() is necessary. Without this,
- * I get a "gfp called nonatomically from interrupt 00000000".
- * Only god knows why... Tell me if you find the reason!
- * Andy, 6/16/95
- */
-loc_ethernet:	PANIC("Unimplemented loc_ethernet\n")
-
-/*
- * Keyboard interrupt, remapped to level 1
- */
-loc_keyboard:	PANIC("Unimplemented loc_keyboard\n")
-
-loc_mouse:	PANIC("Unimplemented loc_mouse handler")
-
-/*
- * Serial port 1 IRQ, remapped to level 3
- */
-loc_serial1:	PANIC("Unimplemented loc_serial handler")
-
-/*
- * Serial port 2 IRQ, remapped to level 4
- */
-loc_serial2:	PANIC("Unimplemented loc_serial handler")
-
-/*
- * Parallel port IRQ, remapped to level 5
- */
-loc_parallel:	PANIC("Unimplemented loc_parallel handler")
-
-/*
- * Floppy IRQ, remapped to level 6
- */
-loc_floppy:	PANIC("Unimplemented loc_floppy handler")
-  
-/*
- * Now call the real handler
- */
-loc_call:	la	t0,IRQ_vectors			# delay slot
-
-		/*
-		 * Temporarily disable interrupt source
-		 */
-/*		lhu	t2,JAZZ_IO_IRQ_ENABLE
-*/
-		addu	t0,t3			# make ptr to IRQ handler
-		lw	t0,(t0)
-		and	t2,s1			# delay slot
-/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
-		jalr	t0			# call IRQ handler
-		nor	s1,zero,s1		# delay slot
-
-		/*
-		 * Reenable interrupt
-		 */
-/*		lhu	t2,JAZZ_IO_IRQ_ENABLE */
-		or	t2,s1
-/*		sh	t2,JAZZ_IO_IRQ_ENABLE */
-
-		jr	v0
-		nop				# delay slot
-
-ll_tc3:		PANIC("Unimplemented tc3 interrupt handler")
-
-ll_fpu:		PANIC("Unimplemented fpu interrupt handler")
-
-ll_io_error:	PANIC("Unimplemented I/O write timeout interrupt handler")
-
-ll_rtc:		PANIC("Unimplemented RTC interrupt handler")
-
-/*
- * Timer IRQ
- * We remap the timer irq to be more similar to a IBM compatible
- */
-ll_timer:	PANIC("Timer interrupt!\n");
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_reset:	li	a0,0
-		jal	pmax_halt
-		li	a1,0			# delay slot
-
-/*
- * Now call the real handler
- */
-call_real:	la	t0,IRQ_vectors			# delay slot
-
-		/*
-		 * temporarily disable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		and	t2,s1
-
-		addu	t0,t3
-		lw	t0,(t0)
-		mtc0	t2,CP0_STATUS		# delay slot
-		jalr	t0
-		nor	s1,zero,s1		# delay slot
-
-		/*
-		 * reenable interrupt
-		 */
-		mfc0	t2,CP0_STATUS
-		or	t2,s1
-		mtc0	t2,CP0_STATUS
-
-		jr	v0
-		nop				# delay slot
-
-/*
- * Just for debugging... load a0 with address of the point inside the
- * framebuffer at which you want to draw a line of 16x32 pixels.
- * Maxine's framebuffer starts at 0xaa000000.
- */
-		.set	reorder
-		LEAF(drawline)
-		li	t1,0xffffffff		# set all pixels on
-		li	t2,0x10			# we will write 16 words
-1:		sw	t1,(a0)			# write the first word
-		addiu	a0,a0,4			# move our framebuffer pointer
-		addiu	t2,t2,-1		# one less to do
-		bnez	t2,1b			# finished?
-		jr 	ra
-		END(drawline)
-
-/*
- * FIXME: I have begun to alter this table to reflect Personal DECStation
- *	  (i.e. Maxine) interrupts... Paul.
- */
-		.data
-		PTR	ll_sw0			# SW0
-		PTR	ll_sw1			# SW1
-		PTR	ll_timer		# Periodic interrupt
-		PTR	ll_rtc			# RTC periodic interrupt
-		PTR	ll_io_error		# Timeout on I/O writes
-		PTR	ll_tc3			# TC slot 3, motherboard
-		PTR	ll_reset		# Halt keycode (CTRL+ALT+ENTER)
-ll_vectors:	PTR	ll_fpu			# FPU
-
-local_vector:	PTR	loc_no_irq
-		PTR	loc_parallel
-		PTR	loc_floppy
-		PTR	loc_sound
-		PTR	loc_video
-		PTR	loc_ethernet
-		PTR	loc_scsi
-		PTR	loc_keyboard
-		PTR	loc_mouse
-		PTR	loc_serial1
-		PTR	loc_serial2
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/ld.script linux/arch/mips/dec/ld.script
--- v2.1.100/linux/arch/mips/dec/ld.script	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/dec/ld.script	Wed Dec 31 16:00:00 1969
@@ -1,47 +0,0 @@
-OUTPUT_FORMAT("ecoff-littlemips")
-OUTPUT_ARCH(mips)
-ENTRY(dec_entry)
-SECTIONS
-{
-  /* This is probably a little simplistic, and is based on work by
-   * Chris Fraser of Softway Pty Ltd as used in his port of Vsta to
-   * the DECStation - Paul M. Antoine 21/1/96.
-   */
-  . = 0x80030000;
-  .text :
-  {
-    *(.text)
-    . = ALIGN(0x10);
-    _etext = .;
-    __etext = .;
-  }
-  .lit8 : {
- 	  *(.lit8)
-  }
-  .lit4 : {
-       	  *(.lit4)
-  }
-  . = ALIGN(0x1000);
-  .data :
-  {
-    *(.data .rdata .rodata)
-    _edata  =  .;
-    __edata  =  .;
-  }
-  __bss_start = ALIGN(16) + 0x8000;
-  .sbss :
-  {
-    *(.sbss)
-    *(.scommon)
-  }
-  .bss :
-  {
-   *(.bss)
-   *(COMMON)
-   _end = ALIGN(4) ;
-   __end = ALIGN(4) ;
-  }
-  .reginfo : {
-    *(.reginfo)
-  }
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c
--- v2.1.100/linux/arch/mips/dec/reset.c	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/dec/reset.c	Wed Dec 31 16:00:00 1969
@@ -1,28 +0,0 @@
-/*
- *  linux/arch/mips/dec/process.c
- *
- *  Reset a DECstation.
- */
-#include <linux/kernel.h>
-#include <asm/reboot.h>
-
-void dec_machine_restart(char *command)
-{
-	printk("Implement dec_machine_restart().\n");
-	printk("Press reset to continue.\n");
-	while(1);
-}
-
-void dec_machine_halt(void)
-{
-	printk("Implement dec_machine_halt().\n");
-	printk("Press reset to continue.\n");
-	while(1);
-}
-
-void dec_machine_power_off(void)
-{
-	printk("Implement dec_machine_power_off().\n");
-	printk("Press reset to continue.\n");
-	while(1);
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c
--- v2.1.100/linux/arch/mips/dec/setup.c	Tue Mar 10 10:03:30 1998
+++ linux/arch/mips/dec/setup.c	Wed Dec 31 16:00:00 1969
@@ -1,50 +0,0 @@
-/*
- * Setup pointers to hardware-dependent 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) 1996 by Ralf Baechle
- */
-#include <asm/ptrace.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/reboot.h>
-#include <asm/vector.h>
-
-extern struct feature decstation_feature;
-
-static void
-dec_irq_setup(void)
-{
-	/* FIXME: should set up the clock as per above? */
-	pmax_printf("Please write the IRQ setup code for the DECStation!\n");
-}
-
-void (*board_time_init)(struct irqaction *irq);
-
-static void dec_time_init(struct irqaction *irq)
-{
-	pmax_printf("Please write the time init code for the DECStation!\n");
-}
-
-extern void dec_machine_restart(char *command);
-extern void dec_machine_halt(void);
-extern void dec_machine_power_off(void).
-
-void
-decstation_setup(void)
-{
-	irq_setup = dec_irq_setup;
-	board_time_init = dec_time_init;
-	/* FIXME: Setup fd_cacheflush */
-	feature = &decstation_feature;		/* FIXME: Will go away */
-
-	_machine_restart = dec_machine_restart;
-	_machine_halt = dec_machine_halt;
-	_machine_power_off = dec_machine_power_off;
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.1.100/linux/arch/mips/defconfig	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/defconfig	Fri May  8 00:13:23 1998
@@ -13,8 +13,10 @@
 CONFIG_ACER_PICA_61=y
 # 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
 
 #
@@ -39,6 +41,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_PARPORT is not set
 
@@ -64,7 +67,7 @@
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
-# CONFIG_BLK_DEV_TRITON is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
 # CONFIG_IDE_CHIPSETS is not set
 
 #
@@ -74,28 +77,34 @@
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_EZ is not set
+CONFIG_PARIDE_PARPORT=y
+# CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
 # Networking options
 #
+# CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
 # CONFIG_NET_ALIAS is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
 # CONFIG_IP_ACCT is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_ALIAS is not set
 # CONFIG_SYN_COOKIES is not set
 
 #
 # (it is safe to leave these untouched)
 #
-# CONFIG_INET_PCTCP is not set
 # CONFIG_INET_RARP is not set
-CONFIG_PATH_MTU_DISCOVERY=y
 CONFIG_IP_NOSR=y
 # CONFIG_SKB_LARGE is not set
 
@@ -104,12 +113,68 @@
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
-# CONFIG_AX25 is not set
 
 #
 # SCSI support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 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_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+CONFIG_SCSI_NCR53C8XX=y
+# CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT is not set
+# CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
+CONFIG_SCSI_NCR53C8XX_SYNC=5
+# CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP 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
 
 #
 # Network device support
@@ -138,14 +203,26 @@
 # CONFIG_FDDI is not set
 # CONFIG_DLCI is not set
 # CONFIG_PPP is not set
-# CONFIG_NET_RADIO is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_RADIO is not set
 # CONFIG_TR is not set
 # CONFIG_WAN_DRIVERS is not set
 # CONFIG_LAPBETHER is not set
 # CONFIG_X25_ASY is not set
 
 #
+# AX.25 network device drivers
+#
+# CONFIG_MKISS is not set
+# CONFIG_BPQETHER is not set
+# CONFIG_DMASCC is not set
+# CONFIG_SCC is not set
+# CONFIG_BAYCOM_SER_FDX is not set
+# CONFIG_BAYCOM_SER_HDX is not set
+# CONFIG_BAYCOM_PAR is not set
+# CONFIG_SOUNDMODEM is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
@@ -154,6 +231,7 @@
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
+CONFIG_CDROM=y
 
 #
 # Filesystems
@@ -169,25 +247,25 @@
 CONFIG_VFAT_FS=y
 CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_RNFS_BOOTP=y
-# CONFIG_RNFS_RARP is not set
 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_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_MAC_PARTITION is not set
+CONFIG_NLS=y
 
 #
 # Native Language Support
 #
-CONFIG_NLS=y
 # CONFIG_NLS_CODEPAGE_437 is not set
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
@@ -221,6 +299,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_MOUSE is not set
@@ -228,6 +307,7 @@
 # CONFIG_APM is not set
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
 # CONFIG_NVRAM is not set
 # CONFIG_JOYSTICK is not set
 # CONFIG_MISC_RADIO is not set
diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/Makefile linux/arch/mips/deskstation/Makefile
--- v2.1.100/linux/arch/mips/deskstation/Makefile	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/deskstation/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-#
-# Makefile for the Deskstation 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: deskstation.o
-O_TARGET := deskstation.o
-O_OBJS	 := hw-access.o int-handler.o reset.o setup.o
-
-int-handler.o: int-handler.S
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/hw-access.c linux/arch/mips/deskstation/hw-access.c
--- v2.1.100/linux/arch/mips/deskstation/hw-access.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/deskstation/hw-access.c	Wed Dec 31 16:00:00 1969
@@ -1,228 +0,0 @@
-/*
- * Low-level hardware access stuff for Deskstation rPC44/Tyne
- *
- * 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 by Ralf Baechle
- *
- * $Id: hw-access.c,v 1.3 1997/07/29 17:46:42 ralf Exp $
- */
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/kbdcntrlr.h>
-#include <linux/kernel.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/vector.h>
-
-extern int FLOPPY_IRQ;
-extern int FLOPPY_DMA;
-
-asmlinkage extern void deskstation_handle_int(void);
-
-/*
- * How to access the FDC's registers.
- */
-static unsigned char
-fd_inb(unsigned int port)
-{
-	return inb_p(port);
-}
-
-static void
-fd_outb(unsigned char value, unsigned int port)
-{
-	outb_p(value, port);
-}
-
-/*
- * How to access the floppy DMA functions.
- */
-static void
-fd_enable_dma(int channel)
-{
-	enable_dma(channel);
-}
-
-static void
-fd_disable_dma(int channel)
-{
-	disable_dma(int channel);
-}
-
-static int
-fd_request_dma(int channel)
-{
-	return request_dma(channel, "floppy");
-}
-
-static void
-fd_free_dma(int channel)
-{
-	free_dma(channel);
-}
-
-static void
-fd_clear_dma_ff(int channel)
-{
-	clear_dma_ff(channel);
-}
-
-static void
-fd_set_dma_mode(int channel, char mode)
-{
-	set_dma_mode(channel, mode);
-}
-
-static void
-fd_set_dma_addr(int channel, unsigned int addr)
-{
-	set_dma_addr(channel, addr);
-}
-
-static void
-fd_set_dma_count(int channel, unsigned int count)
-{
-	set_dma_count(channel, count);
-}
-
-static int
-fd_get_dma_residue(int channel)
-{
-	return get_dma_residue(channel);
-}
-
-static void
-fd_enable_irq(int irq)
-{
-	enable_irq(irq);
-}
-
-static void
-fd_disable_irq(int irq)
-{
-	disable_irq(irq);
-}
-
-void
-deskstation_fd_cacheflush(const void *addr, size_t size)
-{
-	flush_cache_all();
-}
-
-/*
- * RTC stuff
- */
-static unsigned char *
-rtc_read_data()
-{
-	return 0;
-}
-
-static void
-rtc_write_data(unsigned char data)
-{
-}
-
-/*
- * KLUDGE
- */
-static unsigned long
-vdma_alloc(unsigned long paddr, unsigned long size)
-{
-	return 0;
-}
-
-#ifdef CONFIG_DESKSTATION_TYNE
-struct feature deskstation_tyne_feature = {
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	fd_inb,
-	fd_outb,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	fd_enable_dma,
-	fd_disable_dma,
-	fd_request_dma,
-	fd_free_dma,
-	fd_clear_dma_ff,
-	fd_set_dma_mode,
-	fd_set_dma_addr,
-	fd_set_dma_count,
-	fd_get_dma_residue,
-	fd_enable_irq,
-	fd_disable_irq,
-	/*
-	 * How to access the RTC functions.
-	 */
-	rtc_read_data,
-	rtc_write_data
-};
-#endif
-
-#ifdef CONFIG_DESKSTATION_RPC44
-struct feature deskstation_rpc44_feature = {
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	fd_inb,
-	fd_outb,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	fd_enable_dma,
-	fd_disable_dma,
-	fd_request_dma,
-	fd_free_dma,
-	fd_clear_dma_ff,
-	fd_set_dma_mode,
-	fd_set_dma_addr,
-	fd_set_dma_count,
-	fd_get_dma_residue,
-	fd_enable_irq,
-	fd_disable_irq,
-	/*
-	 * How to access the RTC functions.
-	 */
-	rtc_read_data,
-	rtc_write_data
-};
-#endif
-
-static unsigned char dtc_read_input(void)
-{
-	return inb(KBD_DATA_REG);
-}
-
-static void dtc_write_output(unsigned char val)
-{
-	outb(val, KBD_DATA_REG);
-}
-
-static void dtc_write_command(unsigned char val)
-{
-	outb(val, KBD_CNTL_REG);
-}
-
-static unsigned char dtc_read_status(void)
-{
-	return inb(KBD_STATUS_REG);
-}
-
-static void dtc_rm200_keyboard_setup(void)
-{
-	kbd_read_input = dtc_read_input;
-	kbd_write_output = dtc_write_output;
-	kbd_write_command = dtc_write_command;
-	kbd_read_status = dtc_read_status;
-	request_region(0x60, 16, "keyboard");
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/int-handler.S linux/arch/mips/deskstation/int-handler.S
--- v2.1.100/linux/arch/mips/deskstation/int-handler.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/deskstation/int-handler.S	Wed Dec 31 16:00:00 1969
@@ -1,104 +0,0 @@
-/*
- * Deskstation rPC44/Tyne specific interrupt handler code
- *
- * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle
- *
- * $Id: int-handler.S,v 1.3 1997/09/20 19:20:09 root Exp $
- */
-#include <asm/asm.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#error "FIXME - PORT_BASE is defined to mips_io_port_base which breaks this file"
-
-		.text
-		.set	noreorder
-		.set	noat
-		.align	5
-		NESTED(deskstation_handle_int, PT_SIZE, sp)
-		SAVE_ALL
-		REG_S	sp,PT_OR2(sp)
-		CLI
-		.set	at
-		lui	s0,%hi(PORT_BASE)
-		li	a0,0x0f
-		sb	a0,%lo(PORT_BASE+0x20)(s0)	# poll command
-		lb	a0,%lo(PORT_BASE+0x20)(s0)	# read result
-		bgtz	a0,poll_second
-		andi	a0,7
-		beq	a0,2,poll_second		# cascade?
-		li	s1,1				# delay slot
-		/*
-		 * Acknowledge first pic
-		 */
-		lb	t2,%lo(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(PORT_BASE+0x21)(s0)
-		li	t2,0x20
-		sb	t2,%lo(PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		jal	do_IRQ
-		 move	a1,sp
-		/*
-		 * Unblock first pic
-		 */
-		lbu	t1,%lo(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(PORT_BASE+0x21)(s0)	# delay slot
-
-		/*
-		 * Cascade interrupt from second PIC
-		 */
-		.align	5
-poll_second:	li	a0,0x0f
-		sb	a0,%lo(PORT_BASE+0xa0)(s0)	# poll command
-		lb	a0,%lo(PORT_BASE+0xa0)(s0)	# read result
-		bgtz	a0,3f
-		andi	a0,7
-		/*
-		 * Acknowledge second pic
-		 */
-		lbu	t2,%lo(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(PORT_BASE+0xa1)(s0)
-		li	t3,0x20
-		sb	t3,%lo(PORT_BASE+0xa0)(s0)
-		sb	t3,%lo(PORT_BASE+0x20)(s0)
-		/*
-		 * Now call the real handler
-		 */
-		jal	do_IRQ
-		 nop
-		/*
-		 * Unblock second pic
-		 */
-		lb	t1,%lo(PORT_BASE+0xa1)(s0)
-		lb	t1,%lo(cache_A1)(s4)
-		nor	s1,zero,s1
-		and	t1,t1,s1
-		sb	t1,%lo(cache_A1)(s4)
-		j	ret_from_irq
-		 sb	t1,%lo(PORT_BASE+0xa1)(s0)
-
-/*
- * "Jump extender" to reach spurious_interrupt
- */
-3:		j	spurious_interrupt
-		 nop
-		END(deskstation_handle_int)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/io.c linux/arch/mips/deskstation/io.c
--- v2.1.100/linux/arch/mips/deskstation/io.c	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/deskstation/io.c	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-/*
- * 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 Jazz family machine.
- *
- * FIXME: This implementation fits the Tyne.  How does the EISA rPC44 handle
- * the eight high address bits?
- */
-#include <linux/string.h>
-#include <asm/mipsconfig.h>
-#include <asm/addrspace.h>
-#include <asm/sni.h>
-
-/*
- * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
- * for the processor.
- */
-extern unsigned long isa_slot_offset;
-
-static unsigned char deskstation_readb(unsigned long addr)
-{
-	return *(volatile unsigned char *) (isa_slot_offset + addr);
-}
-
-static unsigned short deskstation_readw(unsigned long addr)
-{
-	return *(volatile unsigned short *) (isa_slot_offset + addr);
-}
-
-static unsigned int deskstation_readl(unsigned long addr)
-{
-	return *(volatile unsigned int *) (isa_slot_offset + addr);
-}
-
-static void deskstation_writeb(unsigned char val, unsigned long addr)
-{
-	*(volatile unsigned char *) (isa_slot_offset + addr) = val;
-}
-
-static void deskstation_writew(unsigned short val, unsigned long addr)
-{
-	*(volatile unsigned char *) (isa_slot_offset + addr) = val;
-}
-
-static void deskstation_writel(unsigned int val, unsigned long addr)
-{
-	*(volatile unsigned char *) (isa_slot_offset + addr) = val;
-}
-
-static void deskstation_memset_io(unsigned long addr, int val, unsigned long len)
-{
-	addr += isa_slot_offset;
-	memset((void *)addr, val, len);
-}
-
-static void deskstation_memcpy_fromio(unsigned long to, unsigned long from, unsigned long len)
-{
-	from += isa_slot_offset;
-	memcpy((void *)to, (void *)from, len);
-}
-
-static void deskstation_memcpy_toio(unsigned long to, unsigned long from, unsigned long len)
-{
-	to += isa_slot_offset;
-	memcpy((void *)to, (void *)from, len);
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/reset.c linux/arch/mips/deskstation/reset.c
--- v2.1.100/linux/arch/mips/deskstation/reset.c	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/deskstation/reset.c	Wed Dec 31 16:00:00 1969
@@ -1,29 +0,0 @@
-/*
- * linux/arch/mips/deskstation/process.c
- *
- * Reset a Deskstation.
- */
-#include <asm/io.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void deskstation_machine_restart(void)
-{
-	printk("Implement deskstation_machine_restart().\n");
-	printk("Press reset to continue.\n");
-	while(1);
-}
-
-void deskstation_machine_halt(void)
-{
-	printk("Implement deskstation_machine_halt().\n");
-	printk("Press reset to continue.\n");
-	while(1);
-}
-
-void deskstation_machine_power_off(void)
-{
-	printk("Implement dec_machine_power_off().\n");
-	printk("Press reset to continue.\n");
-	while(1);
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c
--- v2.1.100/linux/arch/mips/deskstation/setup.c	Tue Mar 10 10:03:30 1998
+++ linux/arch/mips/deskstation/setup.c	Wed Dec 31 16:00:00 1969
@@ -1,113 +0,0 @@
-/*
- * Setup pointers to hardware-dependent 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) 1996, 1997 by Ralf Baechle
- *
- * $Id: setup.c,v 1.2 1997/07/23 17:40:54 ralf Exp $
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/ptrace.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/vector.h>
-
-/*
- * Initial irq handlers.
- */
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
-
-extern asmlinkage void deskstation_handle_int(void);
-extern asmlinkage void deskstation_fd_cacheflush(const void *addr, size_t size);
-extern struct feature deskstation_tyne_feature;
-extern struct feature deskstation_rpc44_feature;
-
-extern void deskstation_machine_reboot(void);
-extern void deskstation_machine_halt(void);
-extern void deskstation_machine_power_off(void);
-
-#ifdef CONFIG_DESKSTATION_TYNE
-unsigned long mips_dma_cache_size = 0;
-unsigned long mips_dma_cache_base = KSEG0;
-
-__initfunc(static void tyne_irq_setup(void))
-{
-	set_except_vector(0, deskstation_handle_int);
-	/* set the clock to 100 Hz */
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	outb(LATCH >> 8 , 0x40);	/* MSB */
-	request_region(0x20,0x20, "pic1");
-	request_region(0xa0,0x20, "pic2");	
-	setup_x86_irq(2, &irq2);
-}
-#endif
-
-#ifdef CONFIG_DESKSTATION_RPC44
-__initfunc(static void rpc44_irq_setup(void))
-{
-	/*
-	 * For the moment just steal the TYNE support.  In the
-	 * future, we need to consider merging the two -- imp
-	 */
-	set_except_vector(0, deskstation_handle_int);
-	/* set the clock to 100 Hz */
-	outb_p(0x34, 0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	outb(LATCH >> 8 , 0x40);	/* MSB */
-	request_region(0x20,0x20, "pic1");
-	request_region(0xa0,0x20, "pic2");
-	setup_x86_irq(2, &irq2);
-	set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
-}
-#endif
-
-__initfunc(void deskstation_setup(void))
-{
-	switch(mips_machtype) {
-#ifdef CONFIG_DESKSTATION_TYNE
-	case MACH_DESKSTATION_TYNE:
-		atag = bi_TagFind(tag_dma_cache_size);
-		memcpy(&mips_dma_cache_size, TAGVALPTR(atag), atag->size);
-
-		atag = bi_TagFind(tag_dma_cache_base);
-		memcpy(&mips_dma_cache_base, TAGVALPTR(atag), atag->size);
-
-		irq_setup = tyne_irq_setup;
-                feature = &deskstation_tyne_feature;
-                isa_slot_offset = 0xe3000000;		// Will go away
-		break;
-#endif
-#ifdef CONFIG_DESKSTATION_RPC44
-	case MACH_DESKSTATION_RPC44:
-		irq_setup = rpc44_irq_setup;
-		mips_memory_upper = KSEG0 + (32 << 20); /* xxx fixme imp */
-		feature = &deskstation_rpc44_feature;	// Will go away
-		isa_slot_offset = 0xa0000000;
-		break;
-#endif
-	}
-	fd_cacheflush = deskstation_fd_cacheflush;
-	keyboard_setup = dtc_keyboard_setup;
-	request_region(0x00,0x20,"dma1");
-	request_region(0x40,0x20,"timer");
-	request_region(0x70,0x10,"rtc");
-	request_region(0x80,0x10,"dma page reg");
-	request_region(0xc0,0x20,"dma2");
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/g364.c linux/arch/mips/jazz/g364.c
--- v2.1.100/linux/arch/mips/jazz/g364.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/jazz/g364.c	Fri May  8 00:13:23 1998
@@ -10,6 +10,8 @@
  * Olivetti M700-10 ie. an Inmos G364 based card in a dedicated video slot,
  * 2MB dual ported VRAM with a 64 bit data path, 256 color lookup table,
  * palette of 16.7M and a user definable 64x64 hardware cursor.
+ *
+ * $Id: g364.c,v 1.7 1998/05/01 01:33:35 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -431,4 +433,12 @@
 void
 set_vesa_blanking(const unsigned long arg)
 {
+}
+
+/*
+ * FIXME: how can we probe for the video board?
+ */
+__initfunc(int con_is_present())
+{
+	return;
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/hw-access.c linux/arch/mips/jazz/hw-access.c
--- v2.1.100/linux/arch/mips/jazz/hw-access.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/jazz/hw-access.c	Fri May  8 00:13:23 1998
@@ -7,9 +7,10 @@
  *
  * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
- * $Id: hw-access.c,v 1.4 1997/07/29 17:46:45 ralf Exp $
+ * $Id: hw-access.c,v 1.4 1998/05/01 01:33:36 ralf Exp $
  */
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <linux/linkage.h>
 #include <linux/types.h>
 #include <linux/mm.h>
@@ -173,11 +174,12 @@
 	return jazz_kh->command;
 }
 
-void jazz_keyboard_setup(void)
+__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_region(0x60, 16, "keyboard");
+	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | JAZZ_IE_KEYBOARD);
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S
--- v2.1.100/linux/arch/mips/jazz/int-handler.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/jazz/int-handler.S	Fri May  8 00:13:23 1998
@@ -10,7 +10,7 @@
  *        Squeeze the last cycles out of the handlers.  Only a dead
  *        cycle is a good cycle.
  *
- * $Id: int-handler.S,v 1.3 1997/09/20 19:20:11 root Exp $
+ * $Id: int-handler.S,v 1.5 1998/05/01 01:33:37 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/mipsconfig.h>
@@ -114,16 +114,8 @@
 		 */
 		jal	do_IRQ
 		 move	a1,sp
-		/*
-		 * Unblock first pic
-		 */
-		lbu	a0,%lo(JAZZ_PORT_BASE)+0x21(s0)
-		lb	a0,%lo(cache_21)(s4)
-		nor	s1,zero,s1
-		and	a0,s1
-		sb	a0,%lo(cache_21)(s4)
 		j	ret_from_irq
-		 sb	a0,%lo(JAZZ_PORT_BASE)+0x21(s0)
+		nop
 
 		.align	5
 ack_second:	/*
@@ -142,19 +134,12 @@
 		/*
 		 * Now call the real handler
 		 */
+		or      a0, 8
 		jal	do_IRQ
 		 move	a1,sp
 
-		/*
-		 * Unblock second pic
-		 */
-		lb	a0,%lo(JAZZ_PORT_BASE)+0xa1(s0)
-		lb	a0,%lo(cache_A1)(s4)
-		nor	s1,zero,s1
-		and	a0,s1
-		sb	a0,%lo(cache_A1)(s4)
 		j	ret_from_irq
-		 sb	a0,%lo(JAZZ_PORT_BASE)+0xa1(s0)
+		nop
 
 /*
  * Hmm...  This is not just a plain PC clone so the question is
@@ -236,7 +221,7 @@
 		.set	reorder
 loc_no_irq:	PANIC("Unimplemented loc_no_irq handler")
 /*
- * Parallel port IRQ, remapped to level 5
+ * Parallel port IRQ
  */
 loc_parallel:	li	s1,~JAZZ_IE_PARALLEL
 		li	a0,JAZZ_PARALLEL_IRQ
@@ -256,14 +241,17 @@
 loc_video:	PANIC("Unimplemented loc_video handler")
 
 /*
- * Ethernet interrupt handler, remapped to level 13
+ * Ethernet interrupt handler
  */
 loc_ethernet: 	li	s1,~JAZZ_IE_ETHERNET
 		li	a0,JAZZ_ETHERNET_IRQ
 		b	loc_call
 
+/*
+ * SCSI interrupt handler
+ */
 loc_scsi:	li	s1,~JAZZ_IE_SCSI
-		li	a0,12         # JAZZ_SCSI_IRQ
+		li	a0,JAZZ_SCSI_IRQ
 		b	loc_call
 
 /*
@@ -276,14 +264,14 @@
 loc_mouse:	PANIC("Unimplemented loc_mouse handler")
 
 /*
- * Serial port 1 IRQ, remapped to level 3
+ * Serial port 1 IRQ
  */
 loc_serial1:	li	s1,~JAZZ_IE_SERIAL1
 		li	a0,JAZZ_SERIAL1_IRQ
 		b	loc_call
 
 /*
- * Serial port 2 IRQ, remapped to level 4
+ * Serial port 2 IRQ
  */
 loc_serial2:	li	s1,~JAZZ_IE_SERIAL2
 		li	a0,JAZZ_SERIAL2_IRQ
diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/jazzdma.c linux/arch/mips/jazz/jazzdma.c
--- v2.1.100/linux/arch/mips/jazz/jazzdma.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/jazz/jazzdma.c	Fri May  8 00:13:23 1998
@@ -514,3 +514,18 @@
   
     return residual;
 }
+
+/*
+ * Get DMA channel enable register
+ */
+int vdma_get_enable(int channel)
+{
+    int enable;
+    
+    enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
+    
+    if (vdma_debug)
+	printk("vdma_get_enable: channel %d: enable=%d\n",channel,enable);
+    
+    return enable;
+}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c
--- v2.1.100/linux/arch/mips/jazz/reset.c	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/jazz/reset.c	Fri May  8 00:13:23 1998
@@ -2,16 +2,36 @@
  *  linux/arch/mips/jazz/process.c
  *
  *  Reset a Jazz machine.
+ *
+ *  $Id: reset.c,v 1.2 1998/05/01 01:33:40 ralf Exp $
  */
+
+#include <linux/sched.h>
+#include <asm/jazz.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/reboot.h>
+#include <asm/delay.h>
+#include <asm/keyboard.h>
+
+static inline void kb_wait(void)
+{
+	unsigned long start = jiffies;
+
+	do {
+		if (! (kbd_read_status() & 0x02))
+			return;
+	} while (jiffies - start < 50);
+}
 
 void jazz_machine_restart(char *command)
 {
-	printk("Implement jazz_machine_restart().\n");
-	printk("Press reset to continue.\n");
-	while(1);
+    while (1) {
+	kb_wait ();    
+	kbd_write_command (0xd1);
+	kb_wait ();
+	kbd_write_output (0x00);
+    }
 }
 
 void jazz_machine_halt(void)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c
--- v2.1.100/linux/arch/mips/jazz/setup.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/jazz/setup.c	Fri May  8 00:13:23 1998
@@ -1,5 +1,5 @@
 /*
- * Setup pointers to hardware dependand routines.
+ * Setup pointers to hardware dependant 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
@@ -7,20 +7,25 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: setup.c,v 1.5 1997/12/02 05:51:05 ralf Exp $
+ * $Id: setup.c,v 1.6 1998/05/04 09:17:45 ralf Exp $
  */
+#include <linux/config.h>
+#include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/mm.h>
 #include <asm/bootinfo.h>
 #include <asm/keyboard.h>
+#include <asm/ide.h>
 #include <asm/irq.h>
 #include <asm/jazz.h>
 #include <asm/ptrace.h>
 #include <asm/reboot.h>
 #include <asm/vector.h>
 #include <asm/io.h>
+#include <asm/pgtable.h>
 
 /*
  * Initial irq handlers.
@@ -41,6 +46,8 @@
 extern void jazz_machine_halt(void);
 extern void jazz_machine_power_off(void);
 
+extern struct ide_ops std_ide_ops;
+
 void (*board_time_init)(struct irqaction *irq);
 
 __initfunc(static void jazz_time_init(struct irqaction *irq))
@@ -118,4 +125,8 @@
 	_machine_restart = jazz_machine_restart;
 	_machine_halt = jazz_machine_halt;
 	_machine_power_off = jazz_machine_power_off;
+
+#ifdef CONFIG_BLK_DEV_IDE
+	ide_ops = &std_ide_ops;
+#endif
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile
--- v2.1.100/linux/arch/mips/kernel/Makefile	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/Makefile	Fri May  8 00:13:23 1998
@@ -14,8 +14,8 @@
 O_TARGET := kernel.o
 O_OBJS	:= branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
 	   ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \
-	   r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \
-	   r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o
+	   r4k_switch.o r4k_misc.o r4k_fpu.o r2300_switch.o r2300_misc.o \
+	   r2300_fpu.o r6000_fpu.o scall_o32.o unaligned.o
 OX_OBJS := mips_ksyms.o
 
 ifdef CONFIG_MIPS_FPE_MODULE
@@ -68,15 +68,11 @@
 #
 #r4k_misc.o: r4k_misc.S
 #
-#r4k_scall.o: r4k_scall.S
-#
 #r4k_fpu.o: r4k_fpu.S
 #
 #r2300_switch.o: r2300_switch.S
 #
 #r2300_misc.o: r2300_misc.S
-#
-#r2300_scall.o: r2300_scall.S
 #
 #r2300_fpu.o: r2300_fpu.S
 #
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S
--- v2.1.100/linux/arch/mips/kernel/entry.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/entry.S	Fri May  8 00:13:23 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
  *
- * $Id: entry.S,v 1.4 1997/09/20 19:20:13 root Exp $
+ * $Id: entry.S,v 1.9 1998/05/04 09:17:50 ralf Exp $
  */
 
 /*
@@ -40,7 +40,7 @@
 		.set	noreorder
 		.set	mips3
 		.align 4
-handle_bottom_half:
+EXPORT(handle_bottom_half)
 		jal	do_bottom_half
 		 nop
 		b	9f
@@ -57,24 +57,16 @@
 		bnez	t0,handle_bottom_half
 9:		 lw	t0,PT_STATUS(sp)	# returning to kernel mode?
 
-		andi	t1,t0, 0x10
-		beqz	t1,return		# -> yes
-		 lw	t1,need_resched
-		bnez	t1,reschedule
-		 GET_CURRENT(s0)
-		lw	t0,task
-		lw	a0,TASK_BLOCKED(s0)
-
-		beq	s0,t0,return		# task[0] cannot have signals
-		 lw	t0,TASK_SIGNAL(s0)
-
-		nor	t1,zero,a0
-		and	t1,t0,t1
-		beqz	t1,return
+		andi	t1, t0, 0x10
+		beqz	t1, return		# -> yes
+		 lw	t1, need_resched
+		bnez	t1, reschedule
+		lw	v0, TASK_SIGPENDING($28)
+		 move	a0, zero
+		beqz	v0, return
 		 nop
-
 		jal	do_signal
-		 move	a1,sp
+		 move	a1, sp
 
 EXPORT(return)	.set	noat
 		RESTORE_ALL
@@ -104,14 +96,22 @@
  * the C preprocessor ...
  */
 #define __BUILD_clear_none(exception)
+#define __BUILD_clear_sti(exception)                                    \
+		STI
+#define __BUILD_clear_cli(exception)                                    \
+		CLI
+#define __BUILD_clear_kmode(exception)                                  \
+		KMODE
 #define __BUILD_clear_fpe(exception)                                    \
 		cfc1	a1,fcr31;                                       \
 		li	a2,~(0x3f<<12);                                 \
 		and	a2,a1;                                          \
-		ctc1	a2,fcr31;
+		ctc1	a2,fcr31;                                       \
+		STI
 #define __BUILD_clear_ade(exception)                                    \
 		MFC0	t0,CP0_BADVADDR;                                \
-		REG_S	t0,PT_BVADDR(sp);
+		REG_S	t0,PT_BVADDR(sp);                               \
+		STI
 #define __BUILD_silent(exception)
 
 #define fmt "Got %s at %08lx.\n"
@@ -137,32 +137,28 @@
 		.set	noat;                                           \
 		SAVE_ALL;                                               \
 		__BUILD_clear_##clear(exception);                       \
-		STI;                                                    \
 		.set	at;                                             \
 		__BUILD_##verbose(exception);                           \
-		li	t0,-1;                    /* not a sys call */  \
-		REG_S	t0,PT_OR2(sp);                                  \
 		jal	do_##handler;                                   \
 		 move	a0,sp;                                          \
 		j	ret_from_sys_call;                              \
 		 nop;                                                   \
 		END(handle_##exception)
 
-		BUILD_HANDLER(adel,ade,ade,silent)		/* #4  */
-		BUILD_HANDLER(ades,ade,ade,silent)		/* #5  */
-		BUILD_HANDLER(ibe,ibe,none,verbose)		/* #6  */
-		BUILD_HANDLER(dbe,dbe,none,verbose)		/* #7  */
-		BUILD_HANDLER(sys,sys,none,silent)		/* #8  */
-		BUILD_HANDLER(bp,bp,none,silent)		/* #9  */
-		BUILD_HANDLER(ri,ri,none,silent)		/* #10 */
-		BUILD_HANDLER(cpu,cpu,none,silent)		/* #11 */
-		BUILD_HANDLER(ov,ov,none,silent)		/* #12 */
-		BUILD_HANDLER(tr,tr,none,silent)		/* #13 */
-		BUILD_HANDLER(vcei,vcei,none,verbose)		/* #14 */
+		BUILD_HANDLER(adel,ade,kmode,silent)		/* #4  */
+		BUILD_HANDLER(ades,ade,kmode,silent)		/* #5  */
+		BUILD_HANDLER(ibe,ibe,cli,verbose)		/* #6  */
+		BUILD_HANDLER(dbe,dbe,cli,verbose)		/* #7  */
+		BUILD_HANDLER(bp,bp,sti,silent)			/* #9  */
+		BUILD_HANDLER(ri,ri,sti,silent)			/* #10 */
+		BUILD_HANDLER(cpu,cpu,sti,silent)		/* #11 */
+		BUILD_HANDLER(ov,ov,sti,silent)			/* #12 */
+		BUILD_HANDLER(tr,tr,sti,silent)			/* #13 */
+		BUILD_HANDLER(vcei,vcei,sti,verbose)		/* #14 */
 		BUILD_HANDLER(fpe,fpe,fpe,silent)		/* #15 */
-		BUILD_HANDLER(watch,watch,none,verbose)		/* #23 */
-		BUILD_HANDLER(vced,vced,none,verbose)		/* #31 */
-		BUILD_HANDLER(reserved,reserved,none,verbose)	/* others */
+		BUILD_HANDLER(watch,watch,sti,verbose)		/* #23 */
+		BUILD_HANDLER(vced,vced,sti,verbose)		/* #31 */
+		BUILD_HANDLER(reserved,reserved,sti,verbose)	/* others */
 
 /*
  * Table of syscalls
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c
--- v2.1.100/linux/arch/mips/kernel/fpe.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/fpe.c	Fri May  8 00:13:23 1998
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 1997 Ralf Baechle
  *
- * $Id: fpe.c,v 1.1 1997/08/11 04:17:18 ralf Exp $
+ * $Id: fpe.c,v 1.2 1998/05/01 01:33:48 ralf Exp $
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -18,7 +18,7 @@
 #include <asm/branch.h>
 #include <asm/ptrace.h>
 
-MODULE_AUTHOR("Ralf Baechle <ralf@gnu.ai.mit.edu>");
+MODULE_AUTHOR("Ralf Baechle <ralf@gnu.org>");
 MODULE_DESCRIPTION("Experimental floating point exception handler");
 MODULE_SUPPORTED_DEVICE("MIPS FPU");
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S
--- v2.1.100/linux/arch/mips/kernel/gdb-low.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/gdb-low.S	Fri May  8 00:13:23 1998
@@ -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 1998/05/01 01:33:50 ralf Exp $
  */
 
 #include <linux/sys.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c
--- v2.1.100/linux/arch/mips/kernel/gdb-stub.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/gdb-stub.c	Fri May  8 00:13:23 1998
@@ -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 1998/05/01 01:33:51 ralf Exp $
  */
 
 /*
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S
--- v2.1.100/linux/arch/mips/kernel/head.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/head.S	Fri May  8 00:13:23 1998
@@ -8,7 +8,7 @@
  *
  *  Head.S contains the MIPS exception handler and startup code.
  *
- * $Id: head.S,v 1.10 1997/11/13 12:55:29 ralf Exp $
+ * $Id: head.S,v 1.9 1998/05/01 01:33:53 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/tasks.h>
@@ -397,6 +397,11 @@
 	 nop
 #endif
 
+#ifdef CONFIG_COBALT_MICRO_SERVER
+	jal	SetUpBootInfo
+	 nop
+#endif
+
 	/* Get the very one tags we need early in the boot process */
 	nop
 	jal	bi_EarlySnarf
@@ -442,9 +447,10 @@
 	 nop	
 
 	/*
-	 * Stack for kernel and init
+	 * Stack for kernel and init, current variable
 	 */
-9:	la	t0, init_task_union+KERNEL_STACK_SIZE-32
+9:	la	$28, init_task_union
+	addiu	t0, $28, KERNEL_STACK_SIZE-32
 	sw	t0, kernelsp
 	subu	sp, t0, 4*SZREG
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/init_task.c linux/arch/mips/kernel/init_task.c
--- v2.1.100/linux/arch/mips/kernel/init_task.c	Tue Mar 17 22:18:14 1998
+++ linux/arch/mips/kernel/init_task.c	Fri May  8 00:13:23 1998
@@ -1,6 +1,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 
+#include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
 static struct vm_area_struct init_mmap = INIT_MMAP;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/ipc.c linux/arch/mips/kernel/ipc.c
--- v2.1.100/linux/arch/mips/kernel/ipc.c	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/kernel/ipc.c	Fri May  8 00:13:23 1998
@@ -101,7 +101,7 @@
 			}
 			case 1:	/* iBCS2 emulator entry point */
 				ret = -EINVAL;
-				if (get_fs() != get_ds())
+				if (!segment_eq(get_fs(), get_ds()))
 					goto out;
 				ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
 				goto out;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h
--- v2.1.100/linux/arch/mips/kernel/irix5sys.h	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/irix5sys.h	Fri May  8 00:13:23 1998
@@ -1,4 +1,4 @@
-/* $Id: irix5sys.h,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $
+/* $Id: irix5sys.h,v 1.3 1998/05/01 01:33:55 ralf Exp $
  * irix5sys.h: 32-bit IRIX5 ABI system call table.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- v2.1.100/linux/arch/mips/kernel/irixelf.c	Mon Jan 12 14:52:46 1998
+++ linux/arch/mips/kernel/irixelf.c	Fri May  8 00:13:23 1998
@@ -30,6 +30,8 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/mipsregs.h>
+#include <asm/prctl.h>
 
 #include <linux/config.h>
 
@@ -52,6 +54,11 @@
 #endif
 };
 
+#ifndef elf_addr_t
+#define elf_addr_t unsigned long
+#define elf_caddr_t char *
+#endif
+
 #ifdef DEBUG_ELF
 /* Debugging routines. */
 static char *get_elf_p_type(Elf32_Word p_type)
@@ -152,68 +159,67 @@
 				   unsigned int interp_load_addr,
 				   struct pt_regs *regs, struct elf_phdr *ephdr)
 {
-	char **argv, **envp;
-	unsigned long *sp;
-	unsigned long *csp;
-
+	elf_caddr_t *argv;
+	elf_caddr_t *envp;
+	elf_addr_t *sp, *csp;
+	
 #ifdef DEBUG_ELF
 	printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
 	       "load_addr[%08x] interp_load_addr[%08x]\n",
 	       p, argc, envc, load_addr, interp_load_addr);
 #endif
-	sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
-
-	/* Make sure we will be aligned properly at the end of this. */
+	sp = (elf_addr_t *) (~15UL & (unsigned long) p);
 	csp = sp;
 	csp -= exec ? DLINFO_ITEMS*2 : 2;
-	csp -= envc + 1;
+	csp -= envc+1;
 	csp -= argc+1;
-	if (!(((unsigned long) csp) & 4))
-	    sp--;
-
-	sp -= exec ? DLINFO_ITEMS*2 : 2;
-	sp -= envc+1;
-	envp = (char **) sp;
-	sp -= argc+1;
-	argv = (char **) sp;
-
-	__put_user((unsigned long)argc, --sp);
+	csp -= 1;		/* argc itself */
+	if ((unsigned long)csp & 15UL) {
+		sp -= (16UL - ((unsigned long)csp & 15UL)) / sizeof(*sp);
+	}
 
+	/*
+	 * Put the ELF interpreter info on the stack
+	 */
 #define NEW_AUX_ENT(nr, id, val) \
-	__put_user ((id), sp+(nr*2)); \
-	__put_user ((val), sp+(nr*2+1)); \
+	  __put_user ((id), sp+(nr*2)); \
+	  __put_user ((val), sp+(nr*2+1)); \
 
-#define INTERP_ALIGN  (~((64 * 1024) - 1))
+	sp -= 2;
+	NEW_AUX_ENT(0, AT_NULL, 0);
 
-	NEW_AUX_ENT (0, AT_NULL, 0);
 	if(exec) {
-		struct elf_phdr * eppnt;
-		eppnt = (struct elf_phdr *) exec->e_phoff;
+		sp -= 11*2;
 
-		/* Put this here for an ELF program interpreter */
-		NEW_AUX_ENT (0, AT_PHDR, ephdr->p_vaddr);
+		NEW_AUX_ENT (0, AT_PHDR, load_addr + exec->e_phoff);
 		NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
 		NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
-		NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE);
-		NEW_AUX_ENT (4, AT_BASE, (interp_load_addr & (INTERP_ALIGN)));
+		NEW_AUX_ENT (3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
+		NEW_AUX_ENT (4, AT_BASE, interp_load_addr);
 		NEW_AUX_ENT (5, AT_FLAGS, 0);
-		NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry);
-		NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid);
-		NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid);
-		NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid);
-		NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid);
+		NEW_AUX_ENT (6, AT_ENTRY, (elf_addr_t) exec->e_entry);
+		NEW_AUX_ENT (7, AT_UID, (elf_addr_t) current->uid);
+		NEW_AUX_ENT (8, AT_EUID, (elf_addr_t) current->euid);
+		NEW_AUX_ENT (9, AT_GID, (elf_addr_t) current->gid);
+		NEW_AUX_ENT (10, AT_EGID, (elf_addr_t) current->egid);
 	}
 #undef NEW_AUX_ENT
 
+	sp -= envc+1;
+	envp = (elf_caddr_t *) sp;
+	sp -= argc+1;
+	argv = (elf_caddr_t *) sp;
+
+	__put_user((elf_addr_t)argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
-		__put_user(p, argv++);
+		__put_user((elf_caddr_t)(unsigned long)p,argv++);
 		p += strlen_user(p);
 	}
 	__put_user(NULL, argv);
 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 	while (envc-->0) {
-		__put_user(p, envp++);
+		__put_user((elf_caddr_t)(unsigned long)p,envp++);
 		p += strlen_user(p);
 	}
 	__put_user(NULL, envp);
@@ -441,7 +447,8 @@
 					    struct elf_phdr *epp,
 					    struct linux_binprm *bprm, int pnum)
 {
-	int i, old_fs;
+	mm_segment_t old_fs;
+	int i;
 	int retval = -EINVAL;
 	struct dentry *dentry = NULL;
 
@@ -473,9 +480,8 @@
 			retval = PTR_ERR(dentry);
 			goto out;
 		}
-
 		retval = read_exec(dentry, 0, bprm->buf, 128, 1);
-		if(retval)
+		if(retval < 0)
 			goto dput_and_out;
 
 		*interp_elf_ex = *((struct elfhdr *) bprm->buf);
@@ -546,7 +552,7 @@
 
 static inline int map_interpreter(struct elf_phdr *epp, struct elfhdr *ihp,
 				  struct dentry *identry, unsigned int *iladdr,
-				  int pnum, int old_fs,
+				  int pnum, mm_segment_t old_fs,
 				  unsigned int *eentry)
 {
 	int i;
@@ -573,6 +579,32 @@
 	return 0;
 }
 
+/*
+ * IRIX maps a page at 0x200000 that holds information about the 
+ * process and the system, here we map the page and fill the
+ * structure
+ */
+void irix_map_prda_page (void)
+{
+	unsigned long v;
+	struct prda *pp;
+
+	v =  do_mmap (NULL, PRDA_ADDRESS, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+		      MAP_FIXED | MAP_PRIVATE, 0);
+	
+	if (v < 0)
+		return;
+
+	pp = (struct prda *) v;
+	pp->prda_sys.t_pid  = current->pid;
+	pp->prda_sys.t_prid = read_32bit_cp0_register (CP0_PRID);
+	pp->prda_sys.t_rpid = current->pid;
+
+	/* We leave the rest set to zero */
+}
+	
+
+	
 /* These are the functions used to load ELF style executables and shared
  * libraries.  There is no binary dependent code anywhere else.
  */
@@ -585,8 +617,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 old_fs, elf_exec_fileno, retval, has_interp, has_ephdr, i;
+	int elf_exec_fileno, retval, has_interp, has_ephdr, i;
 	char *elf_interpreter;
+	mm_segment_t old_fs;
 	
 	load_addr = 0;
 	has_interp = has_ephdr = 0;
@@ -760,6 +793,12 @@
 	 */
 	set_brk(elf_bss, elf_brk);
 
+	/*
+	 * IRIX maps a page at 0x200000 which holds some system
+	 * information.  Programs depend on this.
+	 */
+	irix_map_prda_page ();
+
 	padzero(elf_bss);
 
 #ifdef DEBUG_ELF
@@ -1086,7 +1125,7 @@
 	struct file file;
 	struct dentry *dentry;
 	struct inode *inode;
-	unsigned short fs;
+	mm_segment_t fs;
 	char corefile[6+sizeof(current->comm)];
 	int segs;
 	int i;
@@ -1190,8 +1229,8 @@
 	notes[0].datasz = sizeof(prstatus);
 	notes[0].data = &prstatus;
 	prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
-	prstatus.pr_sigpend = current->signal;
-	prstatus.pr_sighold = current->blocked;
+	prstatus.pr_sigpend = current->signal.sig[0];
+	prstatus.pr_sighold = current->blocked.sig[0];
 	psinfo.pr_pid = prstatus.pr_pid = current->pid;
 	psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;
 	psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixinv.c linux/arch/mips/kernel/irixinv.c
--- v2.1.100/linux/arch/mips/kernel/irixinv.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/irixinv.c	Fri May  8 00:13:23 1998
@@ -5,9 +5,10 @@
  *
  * Miguel de Icaza, 1997.
  *
- * $Id: irixinv.c,v 1.2 1997/12/06 21:29:58 ralf Exp $
+ * $Id: irixinv.c,v 1.2 1998/05/01 01:33:58 ralf Exp $
  */
 #include <linux/mm.h>
+#include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <asm/inventory.h>
@@ -52,8 +53,7 @@
 	return inventory_items * sizeof (inventory_t);
 }
 
-void
-init_inventory (void)
+__initfunc(void init_inventory (void))
 {
 	/* gross hack while we put the right bits all over the kernel
 	 * most likely this will not let just anyone run the X server
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c
--- v2.1.100/linux/arch/mips/kernel/irixioctl.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/irixioctl.c	Fri May  8 00:13:23 1998
@@ -1,4 +1,4 @@
-/* $Id: irixioctl.c,v 1.2 1997/12/02 05:51:06 ralf Exp $
+/* $Id: irixioctl.c,v 1.6 1998/05/01 01:33:59 ralf Exp $
  * irixioctl.c: A fucking mess...
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -56,8 +56,8 @@
 asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
 {
 	struct tty_struct *tp, *rtp;
+	mm_segment_t old_fs;
 	int error = 0;
-	int old_fs;
 
 	lock_kernel();
 #ifdef DEBUG_IOCTLS
@@ -237,7 +237,7 @@
 
 	default: {
 #ifdef DEBUG_MISSING_IOCTL
-		char *msg = "Unimplemented IOCTL cmd tell dm@engr.sgi.com\n";
+		char *msg = "Unimplemented IOCTL cmd tell linux@engr.sgi.com\n";
 
 #ifdef DEBUG_IOCTLS
 		printk("UNIMP_IOCTL, %08lx)\n", arg);
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- v2.1.100/linux/arch/mips/kernel/irixsig.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/irixsig.c	Fri May  8 00:13:23 1998
@@ -1,7 +1,9 @@
-/* $Id: irixsig.c,v 1.5 1997/12/06 09:57:38 ralf Exp $
+/*
  * irixsig.c: WHEEE, IRIX signals!  YOW, am I compatable or what?!?!
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: irixsig.c,v 1.8 1998/05/01 01:34:00 ralf Exp $
  */
 
 #include <linux/kernel.h>
@@ -15,12 +17,19 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+                         int options, unsigned long *ru);
+
 #undef DEBUG_SIG
 
 #define _S(nr) (1<<((nr)-1))
 
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
+typedef struct {
+	unsigned long sig[4];
+} irix_sigset_t;
+
 struct sigctx_irix5 {
 	u32 rmask, cp0_status;
 	u64 pc;
@@ -29,7 +38,7 @@
 	u32 usedfp, fpcsr, fpeir, sstk_flags;
 	u64 hi, lo;
 	u64 cp0_cause, cp0_badvaddr, _unused0;
-	u32 sigset[4];
+	irix_sigset_t sigset;
 	u64 weird_fpu_thing;
 	u64 _unused1[31];
 };
@@ -63,14 +72,15 @@
 	       (unsigned long) c->hi, (unsigned long) c->lo,
 	       (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
 	printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
-	       "sigset<3>[%08lx]\n", (unsigned long) c->sigset[0],
-	       (unsigned long) c->sigset[1], (unsigned long) c->sigset[2],
-	       (unsigned long) c->sigset[3]);
+	       "sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0],
+	       (unsigned long) c->sigset.sig[1],
+	       (unsigned long) c->sigset.sig[2],
+	       (unsigned long) c->sigset.sig[3]);
 }
 #endif
 
-static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs,
-			     int signr, unsigned long oldmask)
+static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
+			     int signr, sigset_t *oldmask)
 {
 	unsigned long sp;
 	struct sigctx_irix5 *ctx;
@@ -98,10 +108,7 @@
 
 	__put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
 
-	__put_user(0, &ctx->sigset[1]);
-	__put_user(0, &ctx->sigset[2]);
-	__put_user(0, &ctx->sigset[3]);
-	__put_user(oldmask, &ctx->sigset[0]);
+	__copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t));
 
 #ifdef DEBUG_SIG
 	dump_irix5_sigctx(ctx);
@@ -110,7 +117,7 @@
 	regs->regs[5] = 0; /* XXX sigcode XXX */
 	regs->regs[4] = (unsigned long) signr;
 	regs->regs[6] = regs->regs[29] = sp;
-	regs->regs[7] = (unsigned long) sa->sa_handler;
+	regs->regs[7] = (unsigned long) ka->sa.sa_handler;
 	regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline;
 	return;
 
@@ -120,52 +127,121 @@
 	unlock_kernel();
 }
 
-asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
-                         int options, unsigned long *ru);
+static void inline
+setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+               int signr, sigset_t *oldmask, siginfo_t *info)
+{
+	lock_kernel();
+	printk("Aiee: setup_tr_frame wants to be written");
+	do_exit(SIGSEGV);
+	unlock_kernel();
+}
+
+static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
+        siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_irix_rt_frame(ka, regs, sig, oldset, info);
+	else
+		setup_irix_frame(ka, regs, sig, oldset);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sigmask_lock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+	sigaddset(&current->blocked,sig);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	}
+}
+
+static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
+{
+	switch(regs->regs[0]) {
+	case ERESTARTNOHAND:
+		regs->regs[2] = EINTR;
+		break;
+	case ERESTARTSYS:
+		if(!(ka->sa.sa_flags & SA_RESTART)) {
+			regs->regs[2] = EINTR;
+			break;
+		}
+	/* fallthrough */
+	case ERESTARTNOINTR:		/* Userland will reload $v0.  */
+		regs->cp0_epc -= 8;
+	}
 
-asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
+	regs->regs[0] = 0;		/* Don't deal with this again.  */
+}
+
+asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
 {
-	unsigned long mask = ~current->blocked;
-	unsigned long handler_signal = 0;
-	unsigned long signr;
-	struct sigaction * sa;
+	struct k_sigaction *ka;
+	siginfo_t info;
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	for (;;) {
+		unsigned long signr;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		if (!signr)
+			break;
 
-#ifdef DEBUG_SIG
-	printk("[%s:%d] Delivering IRIX signal oldmask=%08lx\n",
-	       current->comm, current->pid, oldmask);
-#endif
-	while ((signr = current->signal & mask)) {
-		signr = ffz(~signr);
-		clear_bit(signr, &current->signal);
-		sa = current->sig->action + signr;
-		signr++;
 		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+			/* Let the debugger run.  */
 			current->exit_code = signr;
 			current->state = TASK_STOPPED;
 			notify_parent(current, SIGCHLD);
 			schedule();
+
+			/* We're back.  Did the debugger cancel the sig?  */
 			if (!(signr = current->exit_code))
 				continue;
 			current->exit_code = 0;
+
+			/* The debugger continued.  Ignore SIGSTOP.  */
 			if (signr == SIGSTOP)
 				continue;
-			if (_S(signr) & current->blocked) {
-				current->signal |= _S(signr);
+
+			/* Update the siginfo structure.  Is this good?  */
+			if (signr != info.si_signo) {
+				info.si_signo = signr;
+				info.si_errno = 0;
+				info.si_code = SI_USER;
+				info.si_pid = current->p_pptr->pid;
+				info.si_uid = current->p_pptr->uid;
+			}
+
+			/* If the (new) signal is now blocked, requeue it.  */
+			if (sigismember(&current->blocked, signr)) {
+				send_sig_info(signr, &info, current);
 				continue;
 			}
-			sa = current->sig->action + signr - 1;
 		}
-		if (sa->sa_handler == SIG_IGN) {
+
+		ka = &current->sig->action[signr-1];
+		if (ka->sa.sa_handler == SIG_IGN) {
 			if (signr != SIGCHLD)
 				continue;
-			/* check for SIGCHLD: it's special */
-			while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
 				/* nothing */;
 			continue;
 		}
-		if (sa->sa_handler == SIG_DFL) {
+
+		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr;
+
+			/* Init gets no signals it doesn't want.  */
 			if (current->pid == 1)
 				continue;
+
 			switch (signr) {
 			case SIGCONT: case SIGCHLD: case SIGWINCH:
 				continue;
@@ -173,78 +249,55 @@
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
 				if (is_orphaned_pgrp(current->pgrp))
 					continue;
+				/* FALLTHRU */
+
 			case SIGSTOP:
-				if (current->flags & PF_PTRACED)
-					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
-						SA_NOCLDSTOP))
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
-			case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
 				lock_kernel();
-				if (current->binfmt && current->binfmt->core_dump) {
-					if (current->binfmt->core_dump(signr, regs))
-						signr |= 0x80;
-				}
+				if (current->binfmt
+				    && current->binfmt->core_dump
+				    && current->binfmt->core_dump(signr, regs))
+					exit_code |= 0x80;
 				unlock_kernel();
-				/* fall through */
+				/* FALLTHRU */
+
 			default:
-				current->signal |= _S(signr & 0x7f);
+				lock_kernel();
+				sigaddset(&current->signal, signr);
 				current->flags |= PF_SIGNALED;
-				lock_kernel(); /* 8-( */
-				do_exit(signr);
-				unlock_kernel();
+				do_exit(exit_code);
+				/* NOTREACHED */
 			}
 		}
-		/*
-		 * OK, we're invoking a handler
-		 */
-		if (regs->orig_reg2 >= 0) {
-			if (regs->regs[2] == ERESTARTNOHAND) {
-				regs->regs[2] = EINTR;
-			} else if((regs->regs[2] == ERESTARTSYS &&
-				   !(sa->sa_flags & SA_RESTART))) {
-				regs->regs[2] = regs->orig_reg2;
-				regs->cp0_epc -= 8;
-			}
-		}
-		handler_signal |= 1 << (signr-1);
-		mask &= ~sa->sa_mask;
+
+		if (regs->regs[0])
+			syscall_restart(regs, ka);
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, ka, &info, oldset, regs);
+		return 1;
 	}
+
 	/*
 	 * Who's code doesn't conform to the restartable syscall convention
 	 * dies here!!!  The li instruction, a single machine instruction,
 	 * must directly be followed by the syscall instruction.
 	 */
-	if (regs->orig_reg2 >= 0 &&
-	    (regs->regs[2] == ERESTARTNOHAND ||
-	     regs->regs[2] == ERESTARTSYS ||
-	     regs->regs[2] == ERESTARTNOINTR)) {
-		regs->regs[2] = regs->orig_reg2;
-		regs->cp0_epc -= 8;
-	}
-	if (!handler_signal)		/* no handler will be called - return 0 */
-		return 0;
-	signr = 1;
-	sa = current->sig->action;
-	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
-		if (mask > handler_signal)
-			break;
-		if (!(mask & handler_signal))
-			continue;
-		setup_irix_frame(sa, regs, signr, oldmask);
-		if (sa->sa_flags & SA_ONESHOT)
-			sa->sa_handler = NULL;
-		current->blocked |= sa->sa_mask;
-		oldmask |= sa->sa_mask;
+	if (regs->regs[0]) {
+		if (regs->regs[2] == ERESTARTNOHAND ||
+		    regs->regs[2] == ERESTARTSYS ||
+		    regs->regs[2] == ERESTARTNOINTR) {
+			regs->cp0_epc -= 8;
+		}
 	}
-
-	return 1;
+	return 0;
 }
 
 asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs)
@@ -253,6 +306,7 @@
 	unsigned long umask, mask;
 	u64 *fregs, res;
 	int sig, i, base = 0;
+	sigset_t blocked;
 
 	if(regs->regs[2] == 1000)
 		base = 1;
@@ -291,11 +345,24 @@
 
 	/* XXX do sigstack crapola here... XXX */
 
-	regs->orig_reg2 = -1;
-	__get_user(current->blocked, &context->sigset[0]);
-	current->blocked &= _BLOCKABLE;
-	__get_user(res, &context->regs[2]);
-	return res;
+	if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))
+		goto badframe;
+
+	sigdelsetmask(&blocked, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = blocked;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	/*
+	 * Don't let your children do this ...
+	 */
+	__asm__ __volatile__(
+		"move\t$29,%0\n\t"
+		"j\tret_from_sys_call"
+		:/* no outputs */
+		:"r" (&regs));
+		/* Unreached */
 
 badframe:
 	lock_kernel();
@@ -321,27 +388,12 @@
 }
 #endif
 
-static inline void check_pending(int signum)
+asmlinkage int 
+irix_sigaction(int sig, const struct sigaction *act,
+	      struct sigaction *oact, unsigned long trampoline)
 {
-	struct sigaction *p;
-
-	p = signum - 1 + current->sig->action;
-	spin_lock(&current->sigmask_lock);
-	if (p->sa_handler == SIG_IGN) {
-		current->signal &= ~_S(signum);
-	} else if (p->sa_handler == SIG_DFL) {
-		if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
-			return;
-		current->signal &= ~_S(signum);
-	}	
-	spin_unlock(&current->sigmask_lock);
-}
-
-asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
-			      struct sigact_irix5 *old, unsigned long trampoline)
-{
-	struct sigaction new_sa, *p;
-	int res;
+	struct k_sigaction new_ka, old_ka;
+	int ret;
 
 #ifdef DEBUG_SIG
 	printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),
@@ -350,110 +402,103 @@
 		dump_sigact_irix5(new); printk(" ");
 	}
 #endif
-	if(sig < 1 || sig > 32) {
-		return -EINVAL;
-	}
-	p = sig - 1 + current->sig->action;
+	if (act) {
+		sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+			return -EFAULT;
 
-	if(new) {
-		res = verify_area(VERIFY_READ, new, sizeof(*new));
-		if(res)
-			return res;
-		if(sig == SIGKILL || sig == SIGSTOP) {
-			return -EINVAL;
-		}
-		__get_user(new_sa.sa_flags, &new->flags);
-		__get_user(new_sa.sa_handler, &(__sighandler_t) new->handler);
-		__get_user(new_sa.sa_mask, &new->sigset[0]);
-
-		if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
-			res = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
-			if(res)
-				return res;
-		}
+		__copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
+		new_ka.ka_restorer = NULL;
 	}
-	/* Hmmm... methinks IRIX libc always passes a valid trampoline
+
+	/*
+	 * Hmmm... methinks IRIX libc always passes a valid trampoline
 	 * value for all invocations of sigaction.  Will have to
 	 * investigate.  POSIX POSIX, die die die...
 	 */
 	current->tss.irix_trampoline = trampoline;
-	if(old) {
-		int res = verify_area(VERIFY_WRITE, old, sizeof(*old));
-		if(res)
-			return res;
-		__put_user(p->sa_flags, &old->flags);
-		__put_user(p->sa_handler, &old->handler);
-		__put_user(p->sa_mask, &old->sigset[0]);
-		__put_user(0, &old->sigset[1]);
-		__put_user(0, &old->sigset[2]);
-		__put_user(0, &old->sigset[3]);
-		__put_user(0, &old->_unused0[0]);
-		__put_user(0, &old->_unused0[1]);
-	}
-	if(new) {
-		spin_lock_irq(&current->sig->siglock);
-		*p = new_sa;
-		check_pending(sig);
-		spin_unlock_irq(&current->sig->siglock);
+
+/* XXX Implement SIG_SETMASK32 for IRIX compatibility */
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+			return -EFAULT;
+		__copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
+		               sizeof(sigset_t));
 	}
 
-	return 0;
+	return ret;
 }
 
-asmlinkage int irix_sigpending(unsigned long *set)
+asmlinkage int irix_sigpending(irix_sigset_t *set)
 {
-	int res;
-
 	lock_kernel();
-	res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4));
-	if(!res) {
-		/* fill in "set" with signals pending but blocked. */
-		spin_lock_irq(&current->sigmask_lock);
-		__put_user(0, &set[1]);
-		__put_user(0, &set[2]);
-		__put_user(0, &set[3]);
-		__put_user((current->blocked & current->signal), &set[0]);
-		spin_unlock_irq(&current->sigmask_lock);
-	}
-	return res;
+	if (verify_area(VERIFY_WRITE, set, sizeof(*set)) < 0)
+		return -EFAULT;
+
+	/* fill in "set" with signals pending but blocked. */
+	spin_lock_irq(&current->sigmask_lock);
+	__put_user(current->blocked.sig[0] & current->signal.sig[0],
+	           &set->sig[0]);
+	__put_user(current->blocked.sig[1] & current->signal.sig[1],
+	           &set->sig[1]);
+	__put_user(current->blocked.sig[2] & current->signal.sig[2],
+	           &set->sig[2]);
+	__put_user(current->blocked.sig[3] & current->signal.sig[3],
+	           &set->sig[3]);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	return 0;
 }
 
-asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old)
+asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
 {
-	unsigned long bits, oldbits = current->blocked;
+	sigset_t oldbits, newbits;
 	int error;
 
+
 	if(new) {
-		error = verify_area(VERIFY_READ, new, (sizeof(unsigned long) * 4));
+		error = verify_area(VERIFY_READ, new, sizeof(*new));
 		if(error)
 			return error;
-		bits = new[0] & _BLOCKABLE;
+		__copy_from_user(&newbits, new, sizeof(unsigned long)*4);
+		sigdelsetmask(&newbits, ~_BLOCKABLE);
+
+		spin_lock_irq(&current->sigmask_lock);
+		oldbits = current->blocked;
+
 		switch(how) {
 		case 1:
-			current->blocked |= bits;
+			sigorsets(&newbits, &oldbits, &newbits);
 			break;
 
 		case 2:
-			current->blocked &= ~bits;
+			sigandsets(&newbits, &oldbits, &newbits);
 			break;
 
 		case 3:
+			break;
+
 		case 256:
-			current->blocked = bits;
+			siginitset(&newbits, newbits.sig[0]);
 			break;
 
 		default:
 			return -EINVAL;
 		}
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
 	}
 	if(old) {
-		error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4));
+		error = verify_area(VERIFY_WRITE, old, sizeof(*old));
 		if(error)
 			return error;
-		__put_user(0, &old[1]);
-		__put_user(0, &old[2]);
-		__put_user(0, &old[3]);
-		__put_user(oldbits, &old[0]);
+		__copy_to_user(old, &current->blocked, sizeof(unsigned long)*4);
 	}
 
 	return 0;
@@ -461,26 +506,25 @@
 
 asmlinkage int irix_sigsuspend(struct pt_regs *regs)
 {
-	unsigned int mask;
-	unsigned long *uset;
-	int base = 0, error;
+	sigset_t *uset, saveset, newset;
 
-	if(regs->regs[2] == 1000)
-		base = 1;
-
-	uset = (unsigned long *) regs->regs[base + 4];
-	if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4)))
+	uset = (sigset_t *) regs->regs[4];
+	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 		return -EFAULT;
-	mask = current->blocked;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
 
-	current->blocked = uset[0] & _BLOCKABLE;
-	while(1) {
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	spin_unlock_irq(&current->sigmask_lock);
+
+	regs->regs[2] = -EINTR;
+	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if(do_irix_signal(mask, regs))
+		if (do_irix_signal(&saveset, regs))
 			return -EINTR;
 	}
-	return error;
 }
 
 /* hate hate hate... */
@@ -524,8 +568,9 @@
 asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
 				struct timespec *tp)
 {
-	unsigned long mask, kset, expire = 0;
-	int sig, error, timeo = 0;
+	unsigned long expire = 0;
+	sigset_t kset;
+	int i, sig, error, timeo = 0;
 
 	lock_kernel();
 #ifdef DEBUG_SIG
@@ -537,11 +582,15 @@
 	if(!set)
 		return -EINVAL;
 
-	error = get_user(kset, &set[0]);
-	if(error)
+	error = verify_area(VERIFY_READ, set, sizeof(kset));
+	if (error)
 		goto out;
 
-	if(info && clear_user(info, sizeof(*info))) {
+	__copy_from_user(&kset, set, sizeof(set));
+	if (error)
+		goto out;
+
+	if (info && clear_user(info, sizeof(*info))) {
 		error = -EFAULT;
 		goto out;
 	}
@@ -559,21 +608,32 @@
 	}
 
 	while(1) {
+		long tmp = 0;
+
 		current->state = TASK_INTERRUPTIBLE; schedule();
-		if(current->signal & kset) break;
-		if(tp && expire <= jiffies) {
+
+		for (i=0; i<=4; i++)
+			tmp |= (current->signal.sig[i] & kset.sig[i]);
+
+		if (tmp)
+			break;
+		if (tp && expire <= jiffies) {
 			timeo = 1;
 			break;
 		}
-		if(signal_pending(current)) return -EINTR;
+		if (signal_pending(current))
+			return -EINTR;
 	}
+	if (timeo)
+		return -EAGAIN;
 
-	if(timeo) return -EAGAIN;
-	for(sig = 1, mask = 2; mask; mask <<= 1, sig++) {
-		if(!(mask & kset)) continue;
-		if(mask & current->signal) {
+	for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
+		if (sigismember (&kset, sig))
+			continue;
+		if (sigismember (&current->signal, sig)) {
 			/* XXX need more than this... */
-			if(info) info->sig = sig;
+			if (info)
+				info->sig = sig;
 			error = 0;
 			goto out;
 		}
@@ -724,6 +784,7 @@
 {
 	int error, i, base = 0;
 	struct irix5_context *ctx;
+	unsigned long flags;
 
 	lock_kernel();
 	if(regs->regs[2] == 1000)
@@ -738,28 +799,32 @@
 	error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx));
 	if(error)
 		goto out;
-	ctx->flags = 0x0f;
-	ctx->link = current->tss.irix_oldctx;
-	ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0;
-	ctx->sigmask[0] = current->blocked;
+	__put_user(current->tss.irix_oldctx, &ctx->link);
+
+	__copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t));
 
 	/* XXX Do sigstack stuff someday... */
-	ctx->stack.sp = ctx->stack.size = ctx->stack.flags = 0;
+	__put_user(0, &ctx->stack.sp);
+	__put_user(0, &ctx->stack.size);
+	__put_user(0, &ctx->stack.flags);
 
-	ctx->weird_graphics_thing = 0;
-	ctx->regs[0] = 0;
+	__put_user(0, &ctx->weird_graphics_thing);
+	__put_user(0, &ctx->regs[0]);
 	for(i = 1; i < 32; i++)
-		ctx->regs[i] = regs->regs[i];
-	ctx->regs[32] = regs->lo;
-	ctx->regs[33] = regs->hi;
-	ctx->regs[34] = regs->cp0_cause;
-	ctx->regs[35] = regs->cp0_epc;
+		__put_user(regs->regs[i], &ctx->regs[i]);
+	__put_user(regs->lo, &ctx->regs[32]);
+	__put_user(regs->hi, &ctx->regs[33]);
+	__put_user(regs->cp0_cause, &ctx->regs[34]);
+	__put_user(regs->cp0_epc, &ctx->regs[35]);
+
+	flags = 0x0f;
 	if(!current->used_math) {
-		ctx->flags &= ~(0x08);
+		flags &= ~(0x08);
 	} else {
 		/* XXX wheee... */
 		printk("Wheee, no code for saving IRIX FPU context yet.\n");
 	}
+	__put_user(flags, &ctx->flags);
 	error = 0;
 
 out:
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.1.100/linux/arch/mips/kernel/irq.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/irq.c	Fri May  8 00:13:23 1998
@@ -4,7 +4,7 @@
  * Copyright (C) 1992 Linus Torvalds
  * Copyright (C) 1994, 1995, 1996, 1997 Ralf Baechle
  *
- * $Id: irq.c,v 1.7 1997/09/26 11:51:33 ralf Exp $
+ * $Id: irq.c,v 1.11 1998/05/01 01:34:02 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -29,6 +29,7 @@
 unsigned char cache_21 = 0xff;
 unsigned char cache_A1 = 0xff;
 
+unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 unsigned long spurious_count = 0;
 
@@ -104,7 +105,7 @@
 		if (!action) 
 			continue;
 		len += sprintf(buf+len, "%2d: %8d %c %s",
-			i, kstat.interrupts[i],
+			i, kstat.irqs[0][i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
@@ -133,7 +134,7 @@
 
 	cpu = smp_processor_id();
 	irq_enter(cpu, irq);
-	kstat.interrupts[irq]++;
+	kstat.irqs[cpu][irq]++;
 
 	/*
 	 * mask and ack quickly, we don't want the irq controller
@@ -162,6 +163,7 @@
         	} while (action);
 		if (do_random & SA_SAMPLE_RANDOM)
 			add_interrupt_randomness(irq);
+		unmask_irq (irq);
 		__cli();
 	}
 	irq_exit(cpu, irq);
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c
--- v2.1.100/linux/arch/mips/kernel/mips_ksyms.c	Tue Mar 17 22:18:14 1998
+++ linux/arch/mips/kernel/mips_ksyms.c	Fri May  8 00:13:23 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: mips_ksyms.c,v 1.4 1997/08/11 04:17:18 ralf Exp $
+ * $Id: mips_ksyms.c,v 1.7 1998/05/04 09:17:52 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -32,7 +32,6 @@
 /*
  * String functions
  */
-EXPORT_SYMBOL_NOVERS(bcopy);
 EXPORT_SYMBOL_NOVERS(memcmp);
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
@@ -47,13 +46,13 @@
 
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(__mips_bh_counter);
+EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
 
 /*
  * Userspace access stuff.
  */
 EXPORT_SYMBOL(__copy_user);
-EXPORT_SYMBOL(active_ds);
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/pci.c linux/arch/mips/kernel/pci.c
--- v2.1.100/linux/arch/mips/kernel/pci.c	Mon Apr  6 17:40:59 1998
+++ linux/arch/mips/kernel/pci.c	Fri May  8 00:13:24 1998
@@ -5,6 +5,7 @@
  *
  * MIPS implementation of PCI BIOS services for PCI support.
  */
+#include <linux/bios32.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -35,6 +36,53 @@
 }
 
 /*
+ * Given the vendor and device ids, find the n'th instance of that device
+ * in the system.  
+ */
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+			 unsigned short index, unsigned char *bus,
+			 unsigned char *devfn)
+{
+	unsigned int curr = 0;
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		if (dev->vendor == vendor && dev->device == device_id) {
+			if (curr == index) {
+				*devfn = dev->devfn;
+				*bus = dev->bus->number;
+				return PCIBIOS_SUCCESSFUL;
+			}
+			++curr;
+		}
+	}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * Given the class, find the n'th instance of that device
+ * in the system.
+ */
+int pcibios_find_class (unsigned int class_code, unsigned short index,
+			unsigned char *bus, unsigned char *devfn)
+{
+	unsigned int curr = 0;
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next) {
+		if (dev->class == class_code) {
+			if (curr == index) {
+				*devfn = dev->devfn;
+				*bus = dev->bus->number;
+				return PCIBIOS_SUCCESSFUL;
+			}
+			++curr;
+		}
+	}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
  * The functions below are machine specific and must be reimplented for
  * each PCI chipset configuration.  We just run the hook to the machine
  * specific implementation.
@@ -79,11 +127,6 @@
                                 unsigned char where, unsigned int val)
 {
 	return pci_ops->pcibios_write_config_dword(bus, dev_fn, where, val);
-}
-
-__initfunc(char *pcibios_setup(char *str))
-{
-	return str;
 }
 
 #endif /* defined(CONFIG_PCI) */
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v2.1.100/linux/arch/mips/kernel/process.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/process.c	Fri May  8 00:13:24 1998
@@ -1,13 +1,13 @@
 /*
- *  linux/arch/mips/kernel/process.c
+ * linux/arch/mips/kernel/process.c
  *
- *  Copyright (C) 1995 Ralf Baechle
+ * 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.
  *
- *  Modified for R3000/DECStation support by Paul M. Antoine 1995, 1996
+ * Copyright (C) 1994 - 1998 by Ralf Baechle and others.
  *
- * This file handles the architecture-dependent parts of initialization,
- * though it does not yet currently fully support the DECStation,
- * or R3000 - PMA.
+ * $Id: process.c,v 1.10 1998/05/04 09:17:53 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -32,11 +32,6 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/elf.h>
-#ifdef CONFIG_SGI
-#include <asm/sgialib.h>
-#endif
-
-int active_ds = USER_DS;
 
 asmlinkage void ret_from_sys_call(void);
 
@@ -54,10 +49,22 @@
 
 void exit_thread(void)
 {
+	/* Forget lazy fpu state */
+	if (last_task_used_math == current) {
+		set_cp0_status(ST0_CU1, ST0_CU1);
+		__asm__ __volatile__("cfc1\t$0,$31");
+		last_task_used_math = NULL;
+	}
 }
 
 void flush_thread(void)
 {
+	/* Forget lazy fpu state */
+	if (last_task_used_math == current) {
+		set_cp0_status(ST0_CU1, ST0_CU1);
+		__asm__ __volatile__("cfc1\t$0,$31");
+		last_task_used_math = NULL;
+	}
 }
 
 void release_thread(struct task_struct *dead_task)
@@ -72,6 +79,10 @@
 
 	childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
 
+	if (last_task_used_math == current) {
+		set_cp0_status(ST0_CU1, ST0_CU1);
+		r4xx0_save_fp(p);
+	}
 	/* set up new TSS. */
 	childregs = (struct pt_regs *) childksp - 1;
 	*childregs = *regs;
@@ -87,13 +98,13 @@
 		regs->regs[3] = 0;
 	}
 	if (childregs->cp0_status & ST0_CU0) {
+		childregs->regs[28] = (unsigned long) p;
 		childregs->regs[29] = childksp;
 		p->tss.current_ds = KERNEL_DS;
 	} else {
 		childregs->regs[29] = usp;
 		p->tss.current_ds = USER_DS;
 	}
-	p->tss.ksp = childksp;
 	p->tss.reg29 = (unsigned long) childregs;
 	p->tss.reg31 = (unsigned long) ret_from_sys_call;
 
@@ -102,7 +113,7 @@
 	 * switching for most programs since they don't use the fpu.
 	 */
 	p->tss.cp0_status = read_32bit_cp0_register(CP0_STATUS) &
-                            ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL);
+                            ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU);
 	childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1);
 	p->mm->context = 0;
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v2.1.100/linux/arch/mips/kernel/ptrace.c	Thu May  7 22:51:46 1998
+++ linux/arch/mips/kernel/ptrace.c	Fri May  8 00:13:24 1998
@@ -343,8 +343,8 @@
 			struct pt_regs *regs;
 			unsigned long tmp;
 
-			regs = (struct pt_regs *)
-				(child->tss.ksp - sizeof(struct pt_regs));
+			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];
@@ -399,8 +399,8 @@
 			struct pt_regs *regs;
 			int res = 0;
 
-			regs = (struct pt_regs *)
-				(child->tss.ksp - sizeof(struct pt_regs));
+			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) {
@@ -436,7 +436,7 @@
 
 		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 		case PTRACE_CONT: { /* restart after signal. */
-			if ((unsigned long) data > NSIG) {
+			if ((unsigned long) data > _NSIG) {
 				res = -EIO;
 				goto out;
 			}
@@ -465,7 +465,7 @@
 		}
 
 		case PTRACE_DETACH: { /* detach a process that was attached. */
-			if ((unsigned long) data > NSIG) {
+			if ((unsigned long) data > _NSIG) {
 				res = -EIO;
 				goto out;
 			}
@@ -503,9 +503,7 @@
 	 * stopping signal is not SIGTRAP.  -brl
 	 */
 	if (current->exit_code) {
-		spin_lock_irq(&current->sigmask_lock);
-		current->signal |= (1 << (current->exit_code - 1));
-		spin_unlock_irq(&current->sigmask_lock);
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
 	}
-	current->exit_code = 0;
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S
--- v2.1.100/linux/arch/mips/kernel/r2300_fpu.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r2300_fpu.S	Fri May  8 00:13:24 1998
@@ -10,7 +10,7 @@
  * 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 $
+ * $Id: r2300_fpu.S,v 1.4 1998/05/01 01:34:08 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_misc.S linux/arch/mips/kernel/r2300_misc.S
--- v2.1.100/linux/arch/mips/kernel/r2300_misc.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r2300_misc.S	Fri May  8 00:13:24 1998
@@ -1,4 +1,4 @@
-/* $Id: r2300_misc.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $
+/* $Id: r2300_misc.S,v 1.2 1998/05/01 01:34:10 ralf Exp $
  * r2300_misc.S: Misc. exception handling code for R3000/R2000.
  *
  * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_scall.S linux/arch/mips/kernel/r2300_scall.S
--- v2.1.100/linux/arch/mips/kernel/r2300_scall.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r2300_scall.S	Wed Dec 31 16:00:00 1969
@@ -1,84 +0,0 @@
-/* $Id: r2300_scall.S,v 1.1.1.1 1997/06/01 03:16:42 ralf Exp $
- * r2300_scall.S: R2000/R3000 specific code to handle system calls.
- *
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
- *
- * Multi-arch abstraction and beautification:
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * do_syscall calls the function in a1 with upto 7 arguments.  If over
- * four arguments are being requested, the additional arguments will
- * be copied from the user stack pointed to by a0->reg29.
- *
- * a0 (struct pt_regs *)  pointer to user registers
- * a1 (syscall_t)         pointer to syscall to do
- * a2 (int)               number of arguments to syscall
- */
-	.set	noreorder
-NESTED(r2300_do_syscalls, 32, sp)
-	subu	sp,32
-	sw	ra,28(sp)
-	sll	a2,a2,PTRLOG
-	lw	t0,dst(a2)
-	move	t2,a1
-	jalr	t0
-	 lw	t0,PT_R29(a0)		# get old user stack pointer
-
-7:
-	lw	t1,24(t0)		# parameter #7 from usp
-	nop				# delay slot
-	sw	t1,24(sp)
-6:
-	lw	t1,20(t0)		# parameter #6 from usp
-	nop				# delay slot
-	sw	t1,20(sp)
-5:
-	lw	t1,16(t0)		# parameter #5 from usp
-	nop				# delay slot
-	sw	t1,16(sp)
-4:
-	lw	a3,PT_R7(a0)		# 4 args
-3:
-	lw	a2,PT_R6(a0)		# 3 args
-2:
-	lw	a1,PT_R5(a0)		# 2 args
-1:
-	jalr	t2			# 1 args
-	 lw	a0,PT_R4(a0)
-
-	lw	ra,28(sp)
-	addiu	sp,32
-	jr	ra
-	 nop
-
-0:
-	jalr	t2			# 0 args, just pass a0
-	 lw	ra,28(sp)
-	addiu	sp,32
-
-	jr	ra
-	 nop				# delay slot
-	END(r2300_do_syscalls)
-
-		.rdata
-		.align	PTRLOG
-dst:		PTR	0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
-
-		.section	__ex_table,"a"
-		PTR	7b,bad_stack
-		PTR	6b,bad_stack
-		PTR	5b,bad_stack
-		.previous
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
--- v2.1.100/linux/arch/mips/kernel/r2300_switch.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r2300_switch.S	Fri May  8 00:13:24 1998
@@ -1,10 +1,12 @@
-/* $Id: r2300_switch.S,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $
+/*
  * r2300_switch.S: R3000/R2000 specific task switching code.
  *
  * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and 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.2 1998/05/01 01:34:14 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
@@ -25,40 +27,34 @@
 MODE_ALIAS	=	0x00e0			# uncachable, dirty, valid
 
 	.text
-	.set	mips3
+	.set	mips1
+	.set	noreorder
 /*
  * Code necessary to switch tasks on an Linux/MIPS machine.
  * FIXME: We don't need to disable interrupts anymore.
  */
 	.align	5
 	LEAF(r2300_resume)
-	GET_CURRENT(t0)
 	mfc0	t1,CP0_STATUS		# Save status register
-	addu	t0,a1			# Add tss offset
-	sw	t1,THREAD_STATUS(t0)
+	sw	t1,THREAD_STATUS($28)
 	ori	t2,t1,0x1f		# Disable interrupts
 	xori	t2,0x1e
 	mtc0	t2,CP0_STATUS
-	CPU_SAVE_NONSCRATCH(t0)
+	CPU_SAVE_NONSCRATCH($28)
 	sll	t2,t1,2			# Save floating point state
-	bgez	t2,2f
-	 sw	ra,THREAD_REG31(t0)
-	sll	t2,t1,5
 	bgez	t2,1f
-	 swc1	$f0, (THREAD_FPU + 0x00)(t0)
-	FPU_SAVE_16ODD(t0)
+	 sw	ra,THREAD_REG31($28)
+	FPU_SAVE($28, t0)
 1:
-	FPU_SAVE_16EVEN(t0, t1)
-2:
-	addu	a0,a1			# Add tss offset
-	lw	t0,THREAD_PGDIR(a0)	# Switch the root pointer
+	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(a0)
+	lw	a2,THREAD_STATUS($28)
 	tlbwi
 
 	/* Flush TLB. */
@@ -82,19 +78,13 @@
 	xori	t1,1
 	mtc0	t1,CP0_STATUS
 	sll	t0,a2,2
-	bgez	t0,2f
-	 sll	t0,a2,5
 	bgez	t0,1f
-	 lwc1	$f0, (THREAD_FPU + 0x00)(a0)
-	FPU_RESTORE_16ODD(a0)
+	 lw	ra,THREAD_REG31($28)
+	FPU_RESTORE($28, t0)
 1:
-	FPU_RESTORE_16EVEN(a0, t0)
-2:
-	CPU_RESTORE_NONSCRATCH(a0)
-	lw	t0,THREAD_KSP(a0)		# Restore status register
+	CPU_RESTORE_NONSCRATCH($28)
+	addiu	t0, $28, KERNEL_STACK_SIZE-32
 	sw	t0,kernelsp
 	jr	ra
-	 mtc0	a2,CP0_STATUS
+	 mtc0	a2,CP0_STATUS			# Restore status register
 	END(r2300_resume)
-
-
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S
--- v2.1.100/linux/arch/mips/kernel/r4k_fpu.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r4k_fpu.S	Fri May  8 00:13:24 1998
@@ -5,12 +5,12 @@
  * 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: r4k_fpu.S,v 1.3 1997/12/01 16:56:06 ralf Exp $
+ * $Id: r4k_fpu.S,v 1.4 1998/05/01 01:34:15 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
@@ -18,65 +18,63 @@
 #include <asm/offset.h>
 #include <asm/regdef.h>
 
+#define EX(a,b)							\
+9:	a,##b;							\
+	.section __ex_table,"a";				\
+	PTR	9b,bad_stack;					\
+	.previous
+
 	.set	noreorder
 	.set	mips3
 	/* Save floating point context */
 LEAF(r4k_save_fp_context)
 	mfc0	t1,CP0_STATUS
-	sll	t2,t1,2
-	bgez	t2,2f
 	 sll	t2,t1,5
 
-	cfc1	t1,fcr31
 	bgez	t2,1f
-	 nop
+	 cfc1	t1,fcr31
 	/* Store the 16 odd double precision registers */
-	sdc1	$f1,(SC_FPREGS+8)(a0)
-	sdc1	$f3,(SC_FPREGS+24)(a0)
-	sdc1	$f5,(SC_FPREGS+40)(a0)
-	sdc1	$f7,(SC_FPREGS+56)(a0)
-	sdc1	$f9,(SC_FPREGS+72)(a0)
-	sdc1	$f11,(SC_FPREGS+88)(a0)
-	sdc1	$f13,(SC_FPREGS+104)(a0)
-	sdc1	$f15,(SC_FPREGS+120)(a0)
-	sdc1	$f17,(SC_FPREGS+136)(a0)
-	sdc1	$f19,(SC_FPREGS+152)(a0)
-	sdc1	$f21,(SC_FPREGS+168)(a0)
-	sdc1	$f23,(SC_FPREGS+184)(a0)
-	sdc1	$f25,(SC_FPREGS+200)(a0)
-	sdc1	$f27,(SC_FPREGS+216)(a0)
-	sdc1	$f29,(SC_FPREGS+232)(a0)
-	sdc1	$f31,(SC_FPREGS+248)(a0)
+	EX(sdc1	$f1,(SC_FPREGS+8)(a0))
+	EX(sdc1	$f3,(SC_FPREGS+24)(a0))
+	EX(sdc1	$f5,(SC_FPREGS+40)(a0))
+	EX(sdc1	$f7,(SC_FPREGS+56)(a0))
+	EX(sdc1	$f9,(SC_FPREGS+72)(a0))
+	EX(sdc1	$f11,(SC_FPREGS+88)(a0))
+	EX(sdc1	$f13,(SC_FPREGS+104)(a0))
+	EX(sdc1	$f15,(SC_FPREGS+120)(a0))
+	EX(sdc1	$f17,(SC_FPREGS+136)(a0))
+	EX(sdc1	$f19,(SC_FPREGS+152)(a0))
+	EX(sdc1	$f21,(SC_FPREGS+168)(a0))
+	EX(sdc1	$f23,(SC_FPREGS+184)(a0))
+	EX(sdc1	$f25,(SC_FPREGS+200)(a0))
+	EX(sdc1	$f27,(SC_FPREGS+216)(a0))
+	EX(sdc1	$f29,(SC_FPREGS+232)(a0))
+	EX(sdc1	$f31,(SC_FPREGS+248)(a0))
 
 	/* Store the 16 even double precision registers */
 1:
-	sdc1	$f0,(SC_FPREGS+0)(a0)
-	sdc1	$f2,(SC_FPREGS+16)(a0)
-	sdc1	$f4,(SC_FPREGS+32)(a0)
-	sdc1	$f6,(SC_FPREGS+48)(a0)
-	sdc1	$f8,(SC_FPREGS+64)(a0)
-	sdc1	$f10,(SC_FPREGS+80)(a0)
-	sdc1	$f12,(SC_FPREGS+96)(a0)
-	sdc1	$f14,(SC_FPREGS+112)(a0)
-	sdc1	$f16,(SC_FPREGS+128)(a0)
-	sdc1	$f18,(SC_FPREGS+144)(a0)
-	sdc1	$f20,(SC_FPREGS+160)(a0)
-	sdc1	$f22,(SC_FPREGS+176)(a0)
-	sdc1	$f24,(SC_FPREGS+192)(a0)
-	sdc1	$f26,(SC_FPREGS+208)(a0)
-	sdc1	$f28,(SC_FPREGS+224)(a0)
-	sdc1	$f30,(SC_FPREGS+240)(a0)
-	sw	t1,SC_FPC_CSR(a0)
+	EX(sdc1	$f0,(SC_FPREGS+0)(a0))
+	EX(sdc1	$f2,(SC_FPREGS+16)(a0))
+	EX(sdc1	$f4,(SC_FPREGS+32)(a0))
+	EX(sdc1	$f6,(SC_FPREGS+48)(a0))
+	EX(sdc1	$f8,(SC_FPREGS+64)(a0))
+	EX(sdc1	$f10,(SC_FPREGS+80)(a0))
+	EX(sdc1	$f12,(SC_FPREGS+96)(a0))
+	EX(sdc1	$f14,(SC_FPREGS+112)(a0))
+	EX(sdc1	$f16,(SC_FPREGS+128)(a0))
+	EX(sdc1	$f18,(SC_FPREGS+144)(a0))
+	EX(sdc1	$f20,(SC_FPREGS+160)(a0))
+	EX(sdc1	$f22,(SC_FPREGS+176)(a0))
+	EX(sdc1	$f24,(SC_FPREGS+192)(a0))
+	EX(sdc1	$f26,(SC_FPREGS+208)(a0))
+	EX(sdc1	$f28,(SC_FPREGS+224)(a0))
+	EX(sdc1	$f30,(SC_FPREGS+240)(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
-2:
-	jr	ra
-	.set	nomacro
-	 nop
+	 EX(sw	t0,SC_FPC_EIR(a0))
 	.set	macro
 	END(r4k_save_fp_context)
 
@@ -90,56 +88,51 @@
  * stack frame which might have been changed by the user.
  */
 LEAF(r4k_restore_fp_context)
-	mfc0	t1,CP0_STATUS
-	sll	t0,t1,2
-	bgez	t0,2f
-	 sll	t0,t1,5
-
+	mfc0	t1, CP0_STATUS
+	sll	t0,t1,5
 	bgez	t0,1f
-	 lw	t0,SC_FPC_CSR(a0)
+	 EX(lw	t0,SC_FPC_CSR(a0))
+
 	/* Restore the 16 odd double precision registers only
 	 * when enabled in the cp0 status register.
 	 */
-	ldc1	$f1,(SC_FPREGS+8)(a0)
-	ldc1	$f3,(SC_FPREGS+24)(a0)
-	ldc1	$f5,(SC_FPREGS+40)(a0)
-	ldc1	$f7,(SC_FPREGS+56)(a0)
-	ldc1	$f9,(SC_FPREGS+72)(a0)
-	ldc1	$f11,(SC_FPREGS+88)(a0)
-	ldc1	$f13,(SC_FPREGS+104)(a0)
-	ldc1	$f15,(SC_FPREGS+120)(a0)
-	ldc1	$f17,(SC_FPREGS+136)(a0)
-	ldc1	$f19,(SC_FPREGS+152)(a0)
-	ldc1	$f21,(SC_FPREGS+168)(a0)
-	ldc1	$f23,(SC_FPREGS+184)(a0)
-	ldc1	$f25,(SC_FPREGS+200)(a0)
-	ldc1	$f27,(SC_FPREGS+216)(a0)
-	ldc1	$f29,(SC_FPREGS+232)(a0)
-	ldc1	$f31,(SC_FPREGS+248)(a0)
+	EX(ldc1	$f1,(SC_FPREGS+8)(a0))
+	EX(ldc1	$f3,(SC_FPREGS+24)(a0))
+	EX(ldc1	$f5,(SC_FPREGS+40)(a0))
+	EX(ldc1	$f7,(SC_FPREGS+56)(a0))
+	EX(ldc1	$f9,(SC_FPREGS+72)(a0))
+	EX(ldc1	$f11,(SC_FPREGS+88)(a0))
+	EX(ldc1	$f13,(SC_FPREGS+104)(a0))
+	EX(ldc1	$f15,(SC_FPREGS+120)(a0))
+	EX(ldc1	$f17,(SC_FPREGS+136)(a0))
+	EX(ldc1	$f19,(SC_FPREGS+152)(a0))
+	EX(ldc1	$f21,(SC_FPREGS+168)(a0))
+	EX(ldc1	$f23,(SC_FPREGS+184)(a0))
+	EX(ldc1	$f25,(SC_FPREGS+200)(a0))
+	EX(ldc1	$f27,(SC_FPREGS+216)(a0))
+	EX(ldc1	$f29,(SC_FPREGS+232)(a0))
+	EX(ldc1	$f31,(SC_FPREGS+248)(a0))
 
 	/*
 	 * Restore the 16 even double precision registers
 	 * when cp1 was enabled in the cp0 status register.
 	 */
-1:	ldc1	$f0,(SC_FPREGS+0)(a0)
-	ldc1	$f2,(SC_FPREGS+16)(a0)
-	ldc1	$f4,(SC_FPREGS+32)(a0)
-	ldc1	$f6,(SC_FPREGS+48)(a0)
-	ldc1	$f8,(SC_FPREGS+64)(a0)
-	ldc1	$f10,(SC_FPREGS+80)(a0)
-	ldc1	$f12,(SC_FPREGS+96)(a0)
-	ldc1	$f14,(SC_FPREGS+112)(a0)
-	ldc1	$f16,(SC_FPREGS+128)(a0)
-	ldc1	$f18,(SC_FPREGS+144)(a0)
-	ldc1	$f20,(SC_FPREGS+160)(a0)
-	ldc1	$f22,(SC_FPREGS+176)(a0)
-	ldc1	$f24,(SC_FPREGS+192)(a0)
-	ldc1	$f26,(SC_FPREGS+208)(a0)
-	ldc1	$f28,(SC_FPREGS+224)(a0)
-	ldc1	$f30,(SC_FPREGS+240)(a0)
+1:	EX(ldc1	$f0,(SC_FPREGS+0)(a0))
+	EX(ldc1	$f2,(SC_FPREGS+16)(a0))
+	EX(ldc1	$f4,(SC_FPREGS+32)(a0))
+	EX(ldc1	$f6,(SC_FPREGS+48)(a0))
+	EX(ldc1	$f8,(SC_FPREGS+64)(a0))
+	EX(ldc1	$f10,(SC_FPREGS+80)(a0))
+	EX(ldc1	$f12,(SC_FPREGS+96)(a0))
+	EX(ldc1	$f14,(SC_FPREGS+112)(a0))
+	EX(ldc1	$f16,(SC_FPREGS+128)(a0))
+	EX(ldc1	$f18,(SC_FPREGS+144)(a0))
+	EX(ldc1	$f20,(SC_FPREGS+160)(a0))
+	EX(ldc1	$f22,(SC_FPREGS+176)(a0))
+	EX(ldc1	$f24,(SC_FPREGS+192)(a0))
+	EX(ldc1	$f26,(SC_FPREGS+208)(a0))
+	EX(ldc1	$f28,(SC_FPREGS+224)(a0))
+	EX(ldc1	$f30,(SC_FPREGS+240)(a0))
 	jr	ra
 	 ctc1	t0,fcr31
-
-2:	jr	ra
-	 nop
 	END(r4k_restore_fp_context)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S
--- v2.1.100/linux/arch/mips/kernel/r4k_misc.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r4k_misc.S	Fri May  8 00:13:24 1998
@@ -6,7 +6,7 @@
  * 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 1998/05/01 01:34:17 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/current.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_scall.S linux/arch/mips/kernel/r4k_scall.S
--- v2.1.100/linux/arch/mips/kernel/r4k_scall.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r4k_scall.S	Wed Dec 31 16:00:00 1969
@@ -1,72 +0,0 @@
-/* $Id: r4k_scall.S,v 1.1.1.1 1997/06/01 03:16:43 ralf Exp $
- * r4k_scall.S: R4xx0 specific code to handle system calls.
- *
- * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
- *
- * Multi-arch abstraction and beautification:
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/fpregdef.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.set	noreorder
-	.set	mips3
-	.align	5
-NESTED(r4k_do_syscalls, 64, sp)
-	subu	sp, 64
-	sw	ra, 56(sp)
-	sll	a2, a2, PTRLOG
-	lw	t0, dst(a2)
-	move	t2, a1
-	jalr	t0
-	 lw	t0, PT_R29(a0)		# get old user stack pointer
-7:
-	lw	t1, 24(t0)		# parameter #7 from usp
-	sw	t1, 24(sp)
-6:
-	lw	t1, 20(t0)		# parameter #6 from usp
-	sw	t1, 20(sp)
-5:
-	lw	t1, 16(t0)		# parameter #5 from usp
-	sw	t1, 16(sp)
-4:
-	lw	a3, PT_R7(a0)		# 4 args
-3:
-	lw	a2, PT_R6(a0)		# 3 args
-2:
-	lw	a1, PT_R5(a0)		# 2 args
-1:
-	jalr	t2			# 1 args
-	 lw	a0, PT_R4(a0)
-
-	.set	reorder
-	lw	ra, 56(sp)
-	addiu	sp, 64
-	jr	ra
-0:
-	jalr	t2			# 0 args, just pass a0
-	 nop
-	lw	ra, 56(sp)
-	addiu	sp, 64
-	jr	ra
-	 nop
-	END(r4k_do_syscalls)
-
-		.rdata
-		.align	PTRLOG
-dst:		PTR	0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
-
-		.section	__ex_table,"a"
-		PTR	7b,bad_stack
-		PTR	6b,bad_stack
-		PTR	5b,bad_stack
-		.previous
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S
--- v2.1.100/linux/arch/mips/kernel/r4k_switch.S	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/kernel/r4k_switch.S	Fri May  8 00:13:24 1998
@@ -5,6 +5,8 @@
  *
  * Multi-cpu abstraction and macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: r4k_switch.S,v 1.2 1998/05/01 01:34:19 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
@@ -13,6 +15,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>
@@ -25,44 +28,139 @@
 	.set	mips3
 	.align	5
 	LEAF(r4xx0_resume)
-	GET_CURRENT(t0)
-	mfc0	t1, CP0_STATUS
-	nop
-	sw	t1, THREAD_STATUS(t0)
-	ori	t2, t1, 0x1f
-	xori	t2, t2, 0x1e
-	mtc0	t2, CP0_STATUS
-	CPU_SAVE_NONSCRATCH(t0)
-	sll	t2, t1, 2		# Save floating point state
-	bgez	t2, 2f
-	 sw	ra, THREAD_REG31(t0)
+	mfc0	t1, CP0_STATUS			# fp exception boundary
+	sll	t0, t1, 2
+	bgez	t0, 1f
+	 nop
+	cfc1	zero, fcr31
+1:	sw	t1, THREAD_STATUS($28)
+	CPU_SAVE_NONSCRATCH($28)
+	sw	ra, THREAD_REG31($28)
+
+	/*
+	 * The order of restoring the registers takes care of the race
+	 * updating $28, $29 and kernelsp without disabling ints.
+	 */
+	move	$28, a0
+	CPU_RESTORE_NONSCRATCH($28)
+	addiu	t0, $28, KERNEL_STACK_SIZE-32
+	sw	t0, kernelsp
+	lw	a3, TASK_MM($28)
+	lw	a2, THREAD_STATUS($28)
+	lw	a3, MM_CONTEXT(a3)
+	mtc0	a2, CP0_STATUS
+	andi	a3, a3, 0xff
+	jr	ra
+	 mtc0	a3, CP0_ENTRYHI
+	END(r4xx0_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(r4xx0_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
+	lw	t1, ST_OFF(a0)			# last thread looses fpu
+	and	t1, t3
+	sw	t1, ST_OFF(a0)
 	sll	t2, t1, 5
 	bgez	t2, 1f
-	 swc1	$f0, (THREAD_FPU + 0x00)(t0)
-	FPU_SAVE_16ODD(t0)
+	 sdc1	$f0, (THREAD_FPU + 0x00)(a0)
+	FPU_SAVE_16ODD(a0)
 1:
-	FPU_SAVE_16EVEN(t0, t1)		# clobbers t1
+	FPU_SAVE_16EVEN(a0, t1)			# clobbers t1
 2:
-	lw	a3, TASK_MM(a0)
-	lw	a2, THREAD_STATUS(a0)
-	lw	a3, MM_CONTEXT(a3)
-	ori	t1, a2, 1		# restore fpu, pipeline magic
-	andi	a3, a3, 0xff
-	xori	t1, t1, 1
-	mtc0	a3, CP0_ENTRYHI
-	mtc0	t1, CP0_STATUS
-	sll	t0, a2, 2
-	bgez	t0, 2f
-	 sll	t0, a2, 5
+
+	sll	t0, t0, 5			# load new fp state
 	bgez	t0, 1f
-	 lwc1	$f0, (THREAD_FPU + 0x00)(a0)
-	FPU_RESTORE_16ODD(a0)
+	 ldc1	$f0, (THREAD_FPU + 0x00)($28)
+	FPU_RESTORE_16ODD($28)
 1:
-	FPU_RESTORE_16EVEN(a0, t0)	# clobbers t0
-2:
-	CPU_RESTORE_NONSCRATCH(a0)
-	lw	t0, THREAD_KSP(a0)
-	sw	t0, kernelsp
+	.set	reorder
+	FPU_RESTORE_16EVEN($28, t0)		# clobbers t0
 	jr	ra
-	 mtc0	a2, CP0_STATUS
-	END(r4xx0_resume)
+	END(r4xx0_lazy_fpu_switch)
+
+/*
+ * Save a thread's fp context.
+ */
+	.set	noreorder
+LEAF(r4xx0_save_fp)
+	mfc0	t0, CP0_STATUS
+	sll	t1, t0, 5
+	bgez	t1, 1f				# 16 register mode?
+	 nop
+	FPU_SAVE_16ODD(a0)
+1:
+	FPU_SAVE_16EVEN(a0, t1)			# clobbers t1
+	jr	ra
+	 sdc1	$f0, (THREAD_FPU + 0x00)(a0)
+	END(r4xx0_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  0x00000600
+
+LEAF(r4xx0_init_fpu)
+	mfc0	t0, CP0_STATUS
+	li	t1, 0x20000000
+	or	t0, t1
+	mtc0	t0, CP0_STATUS
+	sll	t0, t0, 5
+
+	li	t1, FPU_DEFAULT
+	ctc1	t1, fcr31
+
+	bgez	t0, 1f			# 16 / 32 register mode?
+	 li	t0, -1
+
+	dmtc1	t0, $f1
+	dmtc1	t0, $f3
+	dmtc1	t0, $f5
+	dmtc1	t0, $f7
+	dmtc1	t0, $f9
+	dmtc1	t0, $f11
+	dmtc1	t0, $f13
+	dmtc1	t0, $f15
+	dmtc1	t0, $f17
+	dmtc1	t0, $f19
+	dmtc1	t0, $f21
+	dmtc1	t0, $f23
+	dmtc1	t0, $f25
+	dmtc1	t0, $f27
+	dmtc1	t0, $f29
+	dmtc1	t0, $f31
+
+1:	dmtc1	t0, $f0
+	dmtc1	t0, $f2
+	dmtc1	t0, $f4
+	dmtc1	t0, $f6
+	dmtc1	t0, $f8
+	dmtc1	t0, $f10
+	dmtc1	t0, $f12
+	dmtc1	t0, $f14
+	dmtc1	t0, $f16
+	dmtc1	t0, $f18
+	dmtc1	t0, $f20
+	dmtc1	t0, $f22
+	dmtc1	t0, $f24
+	dmtc1	t0, $f26
+	dmtc1	t0, $f28
+	jr	ra
+	 dmtc1	t0, $f30
+	END(r4xx0_init_fpu)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S
--- v2.1.100/linux/arch/mips/kernel/r6000_fpu.S	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/r6000_fpu.S	Fri May  8 00:13:24 1998
@@ -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.4 1998/05/01 01:34:20 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S
--- v2.1.100/linux/arch/mips/kernel/scall_o32.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/scall_o32.S	Fri May  8 00:13:24 1998
@@ -0,0 +1,177 @@
+/*
+ * arch/mips/kernel/scall_o32.S
+ *
+ * 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
+ *
+ * $Id: scall_o32.S,v 1.1 1998/05/01 01:34:21 ralf Exp $
+ */
+#include <asm/asm.h>
+#include <linux/errno.h>
+#include <asm/current.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/unistd.h>
+
+/* This duplicates the definition from <linux/sched.h> */
+#define PF_TRACESYS	0x00000020	/* tracing system calls */
+
+/* This duplicates the definition from <asm/signal.h> */
+#define SIGILL		4		/* Illegal instruction (ANSI).  */
+
+/* Highest syscall used of any syscall flavour */
+#define MAX_SYSCALL_NO	__NR_Linux + __NR_Linux_syscalls
+
+	.align  5
+NESTED(handle_sys, PT_SIZE, sp)
+	.set	noat
+	SAVE_SOME
+	STI
+	.set	at
+
+	lw	t1, PT_EPC(sp)		# skip syscall on return
+
+	sltiu	t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+	addiu	t1, 4			# skip to next instruction
+	beqz	t0, illegal_syscall
+	sw	t1, PT_EPC(sp)
+
+	/* XXX Put both in one cacheline, should save a bit. */
+	sll	t0, v0, 2
+	lw	t2, sys_call_table(t0)	# syscall routine
+	lbu	t3, sys_narg_table(v0)	# number of arguments
+	beqz	t2, illegal_syscall;
+
+	subu	t0, t3, 5		# 5 or more arguments?
+	bgez	t0, stackargs
+
+stack_done:
+	lw	t0, TASK_FLAGS($28)	# syscall tracing enabled?
+	andi	t0, PF_TRACESYS
+	bnez	t0, trace_a_syscall
+
+	jalr	t2			# Do The Real Thing (TM)
+
+	li	t0, -EMAXERRNO - 1	# error?
+	sltu	t0, t0, v0
+	sw	t0, PT_R7(sp)		# set error flag
+	beqz	t0, 1f
+
+	negu	v0			# error
+	sw	v0, PT_R0(sp)		# set flag for syscall restarting
+1:	sw	v0, PT_R2(sp)		# result
+
+EXPORT(o32_ret_from_sys_call)
+	lw	t0,bh_mask
+	lw	t1,bh_active		# unused delay slot
+	and	t0,t1
+	bnez	t0,o32_handle_bottom_half
+
+9:	lw	t0,PT_STATUS(sp)	# returning to kernel mode?
+	andi	t1, t0, 0x10
+	lw	t2, need_resched
+	beqz	t1, o32_return		# -> yes
+	bnez	t2, o32_reschedule
+	lw	v0, TASK_SIGPENDING($28)
+	move	a0, zero
+	beqz	v0, o32_return
+	move	a1, sp
+	SAVE_STATIC
+	jal	do_signal
+
+o32_return:
+	RESTORE_SOME
+	RESTORE_SP
+	.set	mips3
+	eret
+	.set	mips0
+
+o32_handle_bottom_half:
+	jal	do_bottom_half
+	b	9b
+o32_reschedule:
+	SAVE_STATIC
+	jal	schedule
+	b	o32_ret_from_sys_call
+
+/* ------------------------------------------------------------------------ */
+
+trace_a_syscall:
+	SAVE_STATIC
+	sw	t2,PT_R1(sp)
+	jal	syscall_trace
+	sw	t2,PT_R1(sp)
+
+	jalr	t2			# Do The Real Thing (TM)
+
+	li	t0, -EMAXERRNO - 1	# error?
+	sltu	t0, t0, v0
+	sw	t0, PT_R7(sp)		# set error flag
+	beqz	t0, 1f
+
+	negu	v0			# error
+	sw	v0, PT_R0(sp)		# set flag for syscall restarting
+1:	sw	v0, PT_R2(sp)		# result
+
+	jal	syscall_trace
+	j	ret_from_sys_call
+
+/* ------------------------------------------------------------------------ */
+
+	/*
+	 * More than four arguments.  Try to deal with it by copying the
+	 * stack arguments from the user stack to the kernel stack.
+	 * This Sucks (TM).
+	 */
+stackargs:
+	lw	t0, PT_R29(sp)		# get old user stack pointer
+	subu	t3, 4
+	sll	t1, t3, 2		# stack valid?
+
+	addu	t1, t0			# end address
+	or	t0, t1
+	bltz	t0, bad_stack		# -> sp is bad
+
+	lw	t0, PT_R29(sp)		# get old user stack pointer
+	la	t1, 3f			# copy 1 to 2 arguments
+	sll	t3, t3, 3
+	subu	t1, t3
+	jr	t1
+
+	/* Ok, copy the args from the luser stack to the kernel stack */
+1:	lw	t1, 20(t0)		# argument #6 from usp
+	sw	t1, 20(sp)
+2:	lw	t1, 16(t0)		# argument #5 from usp
+	sw	t1, 16(sp)
+
+3:	j	stack_done		# go back
+
+	.section __ex_table,"a"
+	PTR	1b,bad_stack
+	PTR	2b,bad_stack
+	.previous
+
+	/*
+	 * The stackpointer for a call with more than 4 arguments is bad.
+	 */
+bad_stack:
+	negu	v0				# error
+	sw	v0, PT_R0(sp)
+	sw	v0, PT_R2(sp)
+	li	t0, 1				# set error flag
+	sw	t0, PT_R7(sp)
+	j	ret_from_sys_call
+
+	/*
+	 * The system call does not exist in this kernel
+	 */
+illegal_syscall:
+	li	v0, ENOSYS			# error
+	sw	v0, PT_R2(sp)
+	li	t0, 1				# set error flag
+	sw	t0, PT_R7(sp)
+	j	ret_from_sys_call
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v2.1.100/linux/arch/mips/kernel/setup.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/setup.c	Fri May  8 00:13:24 1998
@@ -5,10 +5,11 @@
  *  Copyright (C) 1995, 1996  Ralf Baechle
  *  Copyright (C) 1996  Stoned Elipot
  *
- * $Id: setup.c,v 1.5 1997/12/06 08:55:42 ralf Exp $
+ * $Id: setup.c,v 1.9 1998/05/04 09:17:56 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/errno.h>
+#include <linux/hdreg.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
@@ -34,6 +35,7 @@
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
+#include <asm/ide.h>
 #include <asm/io.h>
 #include <asm/vector.h>
 #include <asm/stackframe.h>
@@ -86,6 +88,11 @@
 struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO;
 struct screen_info screen_info = DEFAULT_SCREEN_INFO;
 
+#ifdef CONFIG_BLK_DEV_IDE
+extern struct ide_ops no_ide_ops;
+struct ide_ops *ide_ops;
+#endif
+
 /*
  * setup informations
  *
@@ -170,25 +177,15 @@
 	atag = bi_TagFind(tag_vram_base);
 	memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size);
 
+	/* Save defaults for configuration dependand routines.  */
 	irq_setup = default_irq_setup;
 	fd_cacheflush = default_fd_cacheflush;
+#ifdef CONFIG_BLK_DEV_IDE
+	ide_ops = &no_ide_ops;
+#endif
 
 	switch(mips_machgroup)
 	{
-#ifdef CONFIG_MIPS_DECSTATION
-	case MACH_GROUP_DEC:
-		decstation_setup();
-		break;
-#endif
-#if defined(CONFIG_MIPS_ARC) 
-	/*
-	 * Perhaps arch/mips/deskstation should be renamed to arch/mips/arc.
-	 * For now CONFIG_MIPS_ARC means DeskStation. -Stoned.
-	 */
-	case MACH_GROUP_ARC:
-		deskstation_setup();
-		break;
-#endif
 #ifdef CONFIG_MIPS_JAZZ
 	case MACH_GROUP_JAZZ:
 		jazz_setup();
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
--- v2.1.100/linux/arch/mips/kernel/signal.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/signal.c	Fri May  8 00:13:24 1998
@@ -4,7 +4,9 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1994, 1995, 1996  Ralf Baechle
  *
- * $Id: signal.c,v 1.8 1997/12/01 16:26:34 ralf Exp $
+ * $Id: signal.c,v 1.12 1998/05/01 01:34:28 ralf Exp $
+ *
+ * XXX Handle lazy fp context switches correctly.
  */
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -23,82 +25,189 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 
-#define _S(nr) (1<<((nr)-1))
+#define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
                          int options, unsigned long *ru);
-asmlinkage int do_signal(unsigned long oldmask, struct pt_regs *regs);
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage void (*save_fp_context)(struct sigcontext *sc);
 extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
- * Unlike on Intel we pass a sigset_t *, not sigset_t.
  */
-asmlinkage int sys_sigsuspend(struct pt_regs *regs)
+asmlinkage inline int
+sys_sigsuspend(struct pt_regs regs)
 {
-	unsigned long mask;
-	sigset_t *uset, set;
+	sigset_t *uset, saveset, newset;
 
-	uset = (sigset_t *) regs->regs[4];
-	if (get_user(set, uset))
+	uset = (sigset_t *) regs.regs[4];
+	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
 
 	spin_lock_irq(&current->sigmask_lock);
-	mask = current->blocked;
-	current->blocked = set & _BLOCKABLE;
+	saveset = current->blocked;
+	current->blocked = newset;
 	spin_unlock_irq(&current->sigmask_lock);
 
-	regs->regs[2] = -EINTR;
+	regs.regs[2] = -EINTR;
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(mask, regs))
+		if (do_signal(&saveset, &regs))
 			return -EINTR;
 	}
-	return -EINTR;
 }
 
-asmlinkage int sys_sigreturn(struct pt_regs *regs)
+asmlinkage int
+sys_rt_sigsuspend(struct pt_regs regs)
 {
-	struct sigcontext *context;
-	unsigned long blocked;
-	long long reg;
-	int i;
+	sigset_t *uset, saveset, newset;
 
-	context = (struct sigcontext *)(long) regs->regs[29];
-	if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
-	    (regs->regs[29] & (SZREG - 1)))
-		goto badframe;
+	uset = (sigset_t *) regs.regs[4];
+	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
 
-	__get_user(blocked, &context->sc_sigset);
-	current->blocked = blocked & _BLOCKABLE;
-	__get_user(regs->cp0_epc, &context->sc_pc);
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	spin_unlock_irq(&current->sigmask_lock);
 
-	/*
-	 * Restore all integer registers.
-	 */
-	for(i = 31;i >= 0;i--) {
-		__get_user(reg, &context->sc_regs[i]);
-		regs->regs[i] = (int) reg;
+	regs.regs[2] = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(&saveset, &regs))
+			return -EINTR;
 	}
+}
+
+asmlinkage int 
+sys_sigaction(int sig, const struct sigaction *act,
+	      struct sigaction *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags))
+			return -EFAULT;
+
+		__copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
+		new_ka.ka_restorer = NULL;
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
+			return -EFAULT;
+		__copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
+		               sizeof(sigset_t));
+	}
+
+	return ret;
+}
+
+/*
+ * To do: this entire function should be accessed over a function pointer
+ * such that we can handle stack frames for different ABIs.
+ */
+
+asmlinkage void
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *context)
+{
+	long long reg;
+	int owned_fp;
+
+	__get_user(regs->cp0_epc, &context->sc_pc);
+
 	__get_user(reg, &context->sc_mdhi);
 	regs->hi = (int) reg;
 	__get_user(reg, &context->sc_mdlo);
 	regs->lo = (int) reg;
 
-	/*
-	 * FP depends on what FPU in what mode we have.  Best done in
-	 * Assembler ...
-	 */
-	restore_fp_context(context);
+#define restore_gp_reg(i) __get_user(reg, &context->sc_regs[i]); \
+			  regs->regs[i] = (int) reg;
+	restore_gp_reg( 1); restore_gp_reg( 2); restore_gp_reg( 3);
+	restore_gp_reg( 4); restore_gp_reg( 5); restore_gp_reg( 6);
+	restore_gp_reg( 7); restore_gp_reg( 8); restore_gp_reg( 9);
+	restore_gp_reg(10); restore_gp_reg(11); restore_gp_reg(12);
+	restore_gp_reg(13); restore_gp_reg(14); restore_gp_reg(15);
+	restore_gp_reg(16); restore_gp_reg(17); restore_gp_reg(18);
+	restore_gp_reg(19); restore_gp_reg(20); restore_gp_reg(21);
+	restore_gp_reg(22); restore_gp_reg(23); restore_gp_reg(24);
+	restore_gp_reg(25); restore_gp_reg(26); restore_gp_reg(27);
+	restore_gp_reg(28); restore_gp_reg(29); restore_gp_reg(30);
+	restore_gp_reg(31);
+#undef restore_gp_reg
+
+	/* FP depends on what FPU in what mode we have.  */
+	__get_user(owned_fp, &context->sc_ownedfp);
+#if 0
+	if (owned_fp) {
+		restore_fp_context(context);
+		last_task_used_math = current;
+	}
+#endif
+restore_fp_context(context);
+}
 
-	/*
-	 * Disable syscall checks
-	 */
-	regs->orig_reg2 = -1;
+/*
+ * The structure sc describes the stackframe on the userstack.  The frames
+ * are identical for normal and realtime signal stackframes with the
+ * exception of the additional struct ucontext for rt frames.
+ */
+struct sigframe {
+	unsigned long	ass[4];		/* argument save space for o32 */
+	unsigned int	code[4];	/* signal trampoline */
+	struct sigcontext scc;
+};
+
+struct rt_sigframe {
+	unsigned long	ass[4];
+	unsigned int	code[4];
+	struct sigcontext scc;
+	// struct ucontext uc;
+};
+
+asmlinkage int sys_sigreturn(struct pt_regs regs)
+{
+	struct sigcontext *context;
+	sigset_t blocked;
+
+	context = (struct sigcontext *)(long) regs.regs[29];
+	if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
+	    (regs.regs[29] & (SZREG - 1)))
+		goto badframe;
+
+#if 1
+	if (__get_user(blocked.sig[0], &context->sc_sigset[0]) ||
+	    __get_user(blocked.sig[1], &context->sc_sigset[1]) ||
+	    __get_user(blocked.sig[2], &context->sc_sigset[2]) ||
+	    __get_user(blocked.sig[3], &context->sc_sigset[3]))
+		goto badframe;
+#else
+	if (__copy_from_user(&blocked, &context->sc_sigset, sizeof(blocked)))
+		goto badframe;
+#endif
+
+	sigdelsetmask(&blocked, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = blocked;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	restore_sigcontext(&regs, context);
 
 	/*
 	 * Don't let your children do this ...
@@ -107,7 +216,7 @@
 		"move\t$29,%0\n\t"
 		"j\tret_from_sys_call"
 		:/* no outputs */
-		:"r" (regs));
+		:"r" (&regs));
 	/* Unreached */
 
 badframe:
@@ -116,103 +225,113 @@
 	unlock_kernel();
 }
 
+/* same as sys_sigreturn for now */
+asmlinkage int sys_rt_sigreturn(struct pt_regs regs)
+{
+	return -ENOSYS;
+}
+
+#define scc_offset ((size_t)&((struct sigframe *)0)->scc)
+
 /*
- * Set up a signal frame...
- *
- * This routine is somewhat complicated by the fact that if the kernel may be
- * entered by an exception other than a system call; e.g. a bus error or other
- * "bad" exception.  If this is the case, then *all* the context on the kernel
- * stack frame must be saved.
- *
- * For a large number of exceptions, the stack frame format is the same
- * as that which will be created when the process traps back to the kernel
- * when finished executing the signal handler.	In this case, nothing
- * must be done. This information is saved on the user stack and restored
- * when the signal handler is returned.
- *
- * The signal handler will be called with ra pointing to code1 (see below) and
- * one parameters in a0 (signum).
+ * Set up the return code ...
  *
- *     usp ->  [unused]                         ; first free word on stack
- *             arg save space                   ; 16/32 bytes arg. save space
- *	       code1   (addiu sp,#1-offset)	; pop stackframe
- *	       code2   (li v0,__NR_sigreturn)	; syscall number
- *	       code3   (syscall)		; do sigreturn(2)
- *     #1|     $0, at, v0, v1, a0, a1, a2, a3   ; All integer registers
- *       |     t0, t1, t2, t3, t4, t5, t6, t7   ; $0, k0 and k1 are placeholders
- *       |     s0, s1, s2, s3, s4, s5, s6, s7
- *       |     k0, k1, t8, t9, gp, sp, fp, ra;
- *       |     epc                              ; old program counter
- *       |     cause                            ; CP0 cause register
- *       |     oldmask
+ *         .set    noreorder
+ *         addiu   sp,0x20
+ *         li      v0,__NR_sigreturn
+ *         syscall
+ *         .set    reorder
  */
+static void inline
+setup_trampoline(unsigned int *code)
+{
+	__put_user(0x27bd0000 + scc_offset    , code + 0);
+	__put_user(0x24020000 + __NR_sigreturn, code + 1);
+	__put_user(0x0000000c                 , code + 2);
 
-struct sc {
-	unsigned long	ass[4];
-	unsigned int	code[4];
-	struct sigcontext scc;
-};
-#define scc_offset ((size_t)&((struct sc *)0)->scc)
+	/*
+	 * Flush caches so that the instructions will be correctly executed.
+	 */
+	flush_cache_sigtramp((unsigned long) code);
+}
+
+static void inline
+setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc, sigset_t *set)
+{
+	int owned_fp;
+
+	__put_user(regs->cp0_epc, &sc->sc_pc);
+	__put_user(regs->cp0_status, &sc->sc_status);	/* Status register */
+
+#define save_gp_reg(i) __put_user(regs->regs[(i)], &sc->sc_regs[(i)])
+	__put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
+	save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6);
+	save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10);
+	save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
+	save_gp_reg(15); save_gp_reg(16); save_gp_reg(17); save_gp_reg(18);
+	save_gp_reg(19); save_gp_reg(20); save_gp_reg(21); save_gp_reg(22);
+	save_gp_reg(23); save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
+	save_gp_reg(27); save_gp_reg(28); save_gp_reg(29); save_gp_reg(30);
+	save_gp_reg(31);
+#undef save_gp_reg
+
+	__put_user(regs->hi, &sc->sc_mdhi);
+	__put_user(regs->lo, &sc->sc_mdlo);
+	__put_user(regs->cp0_cause, &sc->sc_cause);
+
+	owned_fp = (current == last_task_used_math);
+	__put_user(owned_fp, &sc->sc_ownedfp);
+
+#if 0
+	if (current->used_math) {	/* fp is active.  */
+		set_cp0_status(ST0_CU1, ST0_CU1);
+		save_fp_context(sc);		/* cpu dependant */
+		last_task_used_math = NULL;
+		regs->cp0_status &= ~ST0_CU1;
+		current->used_math = 0;
+	}
+#endif
+set_cp0_status(ST0_CU1, ST0_CU1);
+save_fp_context(sc);		/* cpu dependant */
 
-static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
-                        int signr, unsigned long oldmask)
+	__put_user(set->sig[0], &sc->sc_sigset[0]);
+	__put_user(set->sig[1], &sc->sc_sigset[1]);
+	__put_user(set->sig[2], &sc->sc_sigset[2]);
+	__put_user(set->sig[3], &sc->sc_sigset[3]);
+}
+
+static void inline
+setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
+            int signr, sigset_t *oldmask)
 {
-	struct sc *frame;
+	struct sigframe *frame;
 	struct sigcontext *sc;
-	int i;
 
 	/* Align the stackframe to an adequate boundary for the architecture. */
-	frame = (struct sc *) (long) regs->regs[29];
+	frame = (struct sigframe *) (long) regs->regs[29];
 	frame--;
-	frame = (struct sc *)((unsigned long)frame & ALMASK);
+	frame = (struct sigframe *)((unsigned long)frame & ALMASK);
 
 	if (verify_area(VERIFY_WRITE, frame, sizeof (*frame)))
 		goto segv_and_exit;
 	sc = &frame->scc;
 
-	/*
-	 * Set up the return code ...
-	 *
-	 *         .set    noreorder
-	 *         addiu   sp,0x20
-	 *         li      v0,__NR_sigreturn
-	 *         syscall
-	 *         .set    reorder
-	 */
-	__put_user(0x27bd0000 + scc_offset, &frame->code[0]);
-	__put_user(0x24020000 + __NR_sigreturn, &frame->code[1]);
-	__put_user(0x0000000c, &frame->code[2]);
-
-	/*
-	 * Flush caches so that the instructions will be correctly executed.
-	 */
-	flush_cache_sigtramp((unsigned long) frame->code);
+	setup_trampoline(frame->code);
+	setup_sigcontext(regs, &frame->scc, oldmask);
 
-	/*
-	 * Set up the "normal" sigcontext
-	 */
-	__put_user(regs->cp0_epc, &sc->sc_pc);
-	__put_user(regs->cp0_status, &sc->sc_status);	/* Status register */
-	for(i = 31;i >= 0;i--)
-		__put_user(regs->regs[i], &sc->sc_regs[i]);
-	save_fp_context(sc);
-	__put_user(regs->hi, &sc->sc_mdhi);
-	__put_user(regs->lo, &sc->sc_mdlo);
-	__put_user(regs->cp0_cause, &sc->sc_cause);
-	__put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp);
-	__put_user(oldmask, &sc->sc_sigset);
-	__put_user(0, &sc->__pad0[0]);
-	__put_user(0, &sc->__pad0[1]);
-	__put_user(0, &sc->__pad0[2]);
-
-	regs->regs[4] = signr;				/* Arguments for handler */
-	regs->regs[5] = 0;				/* For now. */
-	regs->regs[6] = (long) frame;			/* Pointer to sigcontext */
-	regs->regs[29] = (unsigned long) frame;		/* Stack pointer */
-	regs->regs[31] = (unsigned long) frame->code;	/* Return address */
-	regs->cp0_epc = (unsigned long) sa->sa_handler;	/* "return" to the first handler */
-	regs->regs[25] = regs->cp0_epc;			/* PIC shit... */
-	return;
+	regs->regs[4] = signr;				/* arguments */
+        regs->regs[5] = 0;                              /* should be cause  */
+        regs->regs[6] = (long) frame;                   /* ptr to sigcontext */
+        regs->regs[29] = (unsigned long) frame;         /* Stack pointer */
+        regs->regs[31] = (unsigned long) frame->code;   /* Return address */
+        regs->cp0_epc = (unsigned long) ka->sa.sa_handler; /* handler address */
+        regs->regs[25] = regs->cp0_epc;                 /* PIC shit... */
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n",
+	       current->comm, current->pid, frame, regs->cp0_epc, frame->code);
+#endif
+        return;
 
 segv_and_exit:
 	lock_kernel();
@@ -220,96 +339,127 @@
 	unlock_kernel();
 }
 
-static inline void handle_signal(unsigned long signr, struct sigaction *sa,
-	unsigned long oldmask, struct pt_regs * regs)
+static void inline
+setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
+               int signr, sigset_t *oldmask, siginfo_t *info)
 {
-	setup_frame(sa, regs, signr, oldmask);
+	printk("Aiee: setup_tr_frame wants to be written");
+}
 
-	if (sa->sa_flags & SA_ONESHOT)
-		sa->sa_handler = NULL;
-	if (!(sa->sa_flags & SA_NOMASK)) {
+/* ------------------------------------------------------------------------- */
+
+static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
+	siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(ka, regs, sig, oldset, info);
+	else
+		setup_frame(ka, regs, sig, oldset);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sigmask_lock);
-		current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigaddset(&current->blocked,sig);
+		recalc_sigpending(current);
 		spin_unlock_irq(&current->sigmask_lock);
 	}
 }
 
-static inline void syscall_restart(unsigned long r0, unsigned long or2,
-				   unsigned long or7, struct pt_regs *regs,
-				   struct sigaction *sa)
+static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 {
-	switch(r0) {
+	switch(regs->regs[0]) {
 	case ERESTARTNOHAND:
-	no_system_call_restart:
-		regs->regs[0] = regs->regs[2] = EINTR;
+		regs->regs[2] = EINTR;
 		break;
 	case ERESTARTSYS:
-		if(!(sa->sa_flags & SA_RESTART))
-			goto no_system_call_restart;
+		if(!(ka->sa.sa_flags & SA_RESTART)) {
+			regs->regs[2] = EINTR;
+			break;
+		}
 	/* fallthrough */
-	case ERESTARTNOINTR:
-		regs->regs[0] = regs->regs[2] = or2;
-		regs->regs[7] = or7;
+	case ERESTARTNOINTR:		/* Userland will reload $v0.  */
 		regs->cp0_epc -= 8;
 	}
+
+	regs->regs[0] = 0;		/* Don't deal with this again.  */
 }
 
-extern int do_irix_signal(unsigned long oldmask, struct pt_regs *regs);
+extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs);
 
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- *
- * Note that we go through the signals twice: once to check the signals that
- * the kernel can handle, and then we build all the user-level signal handling
- * stack-frames in one go after that.
- */
-asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
+asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
 {
-	unsigned long mask = ~current->blocked;
-	unsigned long signr, r0 = regs->regs[0];
-	unsigned long r7 = regs->orig_reg7;
-	struct sigaction * sa;
+	struct k_sigaction *ka;
+	siginfo_t info;
 
 #ifdef CONFIG_BINFMT_IRIX
-	if(current->personality != PER_LINUX)
-		return do_irix_signal(oldmask, regs);
+	if (current->personality != PER_LINUX)           /* XXX */
+		return do_irix_signal(oldset, regs);
 #endif
-	while ((signr = current->signal & mask)) {
-		signr = ffz(~signr);
-		clear_bit(signr, &current->signal);
-		sa = current->sig->action + signr;
-		signr++;
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	for (;;) {
+		unsigned long signr;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		if (!signr)
+			break;
+
 		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+			/* Let the debugger run.  */
 			current->exit_code = signr;
 			current->state = TASK_STOPPED;
 			notify_parent(current, SIGCHLD);
 			schedule();
+
+			/* We're back.  Did the debugger cancel the sig?  */
 			if (!(signr = current->exit_code))
 				continue;
 			current->exit_code = 0;
+
+			/* The debugger continued.  Ignore SIGSTOP.  */
 			if (signr == SIGSTOP)
 				continue;
-			if (_S(signr) & current->blocked) {
-				spin_lock_irq(&current->sigmask_lock);
-				current->signal |= _S(signr);
-				spin_unlock_irq(&current->sigmask_lock);
+
+			/* Update the siginfo structure.  Is this good?  */
+			if (signr != info.si_signo) {
+				info.si_signo = signr;
+				info.si_errno = 0;
+				info.si_code = SI_USER;
+				info.si_pid = current->p_pptr->pid;
+				info.si_uid = current->p_pptr->uid;
+			}
+
+			/* If the (new) signal is now blocked, requeue it.  */
+			if (sigismember(&current->blocked, signr)) {
+				send_sig_info(signr, &info, current);
 				continue;
 			}
-			sa = current->sig->action + signr - 1;
 		}
-		if (sa->sa_handler == SIG_IGN) {
+
+		ka = &current->sig->action[signr-1];
+		if (ka->sa.sa_handler == SIG_IGN) {
 			if (signr != SIGCHLD)
 				continue;
-			/* check for SIGCHLD: it's special */
-			while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
 				/* nothing */;
 			continue;
 		}
-		if (sa->sa_handler == SIG_DFL) {
+
+		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr;
+
+			/* Init gets no signals it doesn't want.  */
 			if (current->pid == 1)
 				continue;
+
 			switch (signr) {
 			case SIGCONT: case SIGCHLD: case SIGWINCH:
 				continue;
@@ -317,72 +467,55 @@
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
 				if (is_orphaned_pgrp(current->pgrp))
 					continue;
+				/* FALLTHRU */
+
 			case SIGSTOP:
-				if (current->flags & PF_PTRACED)
-					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
-				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & 
-						SA_NOCLDSTOP))
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
 				schedule();
 				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
 			case SIGABRT: case SIGFPE: case SIGSEGV:
-			case SIGBUS:
 				lock_kernel();
-				if (current->binfmt && current->binfmt->core_dump) {
-					if (current->binfmt->core_dump(signr, regs))
-						signr |= 0x80;
-				}
+				if (current->binfmt
+				    && current->binfmt->core_dump
+				    && current->binfmt->core_dump(signr, regs))
+					exit_code |= 0x80;
 				unlock_kernel();
-				/* fall through */
-			default:
-				spin_lock_irq(&current->sigmask_lock);
-				current->signal |= _S(signr & 0x7f);
-				spin_unlock_irq(&current->sigmask_lock);
+				/* FALLTHRU */
 
+			default:
+				lock_kernel();
+				sigaddset(&current->signal, signr);
 				current->flags |= PF_SIGNALED;
-
-				lock_kernel(); /* 8-( */
-				do_exit(signr);
-				unlock_kernel();
+				do_exit(exit_code);
+				/* NOTREACHED */
 			}
 		}
-		/*
-		 * OK, we're invoking a handler
-		 */
-		if(r0)
-			syscall_restart(r0, regs->orig_reg2,
-					r7, regs, sa);
-		handle_signal(signr, sa, oldmask, regs);
+
+		if (regs->regs[0])
+			syscall_restart(regs, ka);
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, ka, &info, oldset, regs);
 		return 1;
 	}
+
 	/*
 	 * Who's code doesn't conform to the restartable syscall convention
 	 * dies here!!!  The li instruction, a single machine instruction,
 	 * must directly be followed by the syscall instruction.
 	 */
-	if (r0 &&
-	    (regs->regs[2] == ERESTARTNOHAND ||
-	     regs->regs[2] == ERESTARTSYS ||
-	     regs->regs[2] == ERESTARTNOINTR)) {
-		regs->regs[0] = regs->regs[2] = regs->orig_reg2;
-		regs->regs[7] = r7;
-		regs->cp0_epc -= 8;
+	if (regs->regs[0]) {
+		if (regs->regs[2] == ERESTARTNOHAND ||
+		    regs->regs[2] == ERESTARTSYS ||
+		    regs->regs[2] == ERESTARTNOINTR) {
+			regs->cp0_epc -= 8;
+		}
 	}
 	return 0;
-}
-
-/*
- * The signal(2) syscall is no longer available in the kernel
- * because GNU libc doesn't use it.  Maybe I'll add it back to the
- * kernel for the binary compatibility stuff.
- */
-asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
-{
-	return -ENOSYS;
 }
 
 /*
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- v2.1.100/linux/arch/mips/kernel/syscall.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/kernel/syscall.c	Fri May  8 00:13:24 1998
@@ -11,7 +11,7 @@
  *        Don't waste that much memory for empty entries in the syscall
  *        table.
  *
- * $Id: syscall.c,v 1.4 1997/09/18 07:57:30 root Exp $
+ * $Id: syscall.c,v 1.11 1998/05/01 01:34:30 ralf Exp $
  */
 #undef CONF_PRINT_SYSCALLS
 #undef CONF_DEBUG_IRIX
@@ -23,11 +23,14 @@
 #include <linux/smp_lock.h>
 #include <linux/mman.h>
 #include <linux/sched.h>
+#include <linux/file.h>
 #include <linux/utsname.h>
 #include <linux/unistd.h>
 #include <asm/branch.h>
+#include <asm/offset.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
+#include <asm/stackframe.h>
 #include <asm/uaccess.h>
 
 extern asmlinkage void syscall_trace(void);
@@ -37,7 +40,7 @@
 extern syscall_t sys_call_table[];
 extern unsigned char sys_narg_table[];
 
-asmlinkage int sys_pipe(struct pt_regs *regs)
+asmlinkage int sys_pipe(struct pt_regs regs)
 {
 	int fd[2];
 	int error, res;
@@ -48,7 +51,7 @@
 		res = error;
 		goto out;
 	}
-	regs->regs[3] = fd[1];
+	regs.regs[3] = fd[1];
 	res = fd[0];
 out:
 	unlock_kernel();
@@ -59,19 +62,22 @@
                                   int flags, int fd, off_t offset)
 {
 	struct file * file = NULL;
-	unsigned long res;
+	unsigned long error = -EFAULT;
 
 	lock_kernel();
 	if (!(flags & MAP_ANONYMOUS)) {
-		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
-			return -EBADF;
-	}
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-
-	res = do_mmap(file, addr, len, prot, flags, offset);
-
+		error = -EBADF;
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+        error = do_mmap(file, addr, len, prot, flags, offset);
+        if (file)
+                fput(file);
+out:
 	unlock_kernel();
-	return res;
+	return error;
 }
 
 asmlinkage int sys_idle(void)
@@ -105,28 +111,30 @@
 	return ret;
 }
 
-asmlinkage int sys_fork(struct pt_regs *regs)
+asmlinkage int sys_fork(struct pt_regs regs)
 {
 	int res;
 
+	save_static(&regs);
 	lock_kernel();
-	res = do_fork(SIGCHLD, regs->regs[29], regs);
+	res = do_fork(SIGCHLD, regs.regs[29], &regs);
 	unlock_kernel();
 	return res;
 }
 
-asmlinkage int sys_clone(struct pt_regs *regs)
+asmlinkage int sys_clone(struct pt_regs regs)
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
 	int res;
 
+	save_static(&regs);
 	lock_kernel();
-	clone_flags = regs->regs[4];
-	newsp = regs->regs[5];
+	clone_flags = regs.regs[4];
+	newsp = regs.regs[5];
 	if (!newsp)
-		newsp = regs->regs[29];
-	res = do_fork(clone_flags, newsp, regs);
+		newsp = regs.regs[29];
+	res = do_fork(clone_flags, newsp, &regs);
 	unlock_kernel();
 	return res;
 }
@@ -134,18 +142,18 @@
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(struct pt_regs *regs)
+asmlinkage int sys_execve(struct pt_regs regs)
 {
 	int error;
 	char * filename;
 
 	lock_kernel();
-	filename = getname((char *) (long)regs->regs[4]);
+	filename = getname((char *) (long)regs.regs[4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	error = do_execve(filename, (char **) (long)regs->regs[5],
-	                  (char **) (long)regs->regs[6], regs);
+	error = do_execve(filename, (char **) (long)regs.regs[5],
+	                  (char **) (long)regs.regs[6], &regs);
 	putname(filename);
 
 out:
@@ -193,11 +201,13 @@
 /*
  * Do the indirect syscall syscall.
  * Don't care about kernel locking; the actual syscall will do it.
+ *
+ * XXX This is borken.
  */
-asmlinkage int sys_syscall(struct pt_regs *regs)
+asmlinkage int sys_syscall(struct pt_regs regs)
 {
 	syscall_t syscall;
-	unsigned long syscallnr = regs->regs[4];
+	unsigned long syscallnr = regs.regs[4];
 	unsigned long a0, a1, a2, a3, a4, a5, a6;
 	int nargs, errno;
 
@@ -219,7 +229,7 @@
 	}
 
 	if(nargs > 3) {
-		unsigned long usp = regs->regs[29];
+		unsigned long usp = regs.regs[29];
 		unsigned long *sp = (unsigned long *) usp;
 		if(usp & 3) {
 			printk("unaligned usp -EFAULT\n");
@@ -252,9 +262,9 @@
 	} else {
 		a3 = a4 = a5 = a6 = 0;
 	}
-	a0 = regs->regs[5]; a1 = regs->regs[6]; a2 = regs->regs[7];
+	a0 = regs.regs[5]; a1 = regs.regs[6]; a2 = regs.regs[7];
 	if(nargs == 0)
-		a0 = (unsigned long) regs;
+		a0 = (unsigned long) &regs;
 	return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
 }
 
@@ -268,6 +278,9 @@
 	do_exit(SIGSEGV);
 }
 
+/*
+ * Build the string table for the builtin "poor man's strace".
+ */
 #ifdef CONF_PRINT_SYSCALLS
 #define SYS(fun, narg) #fun,
 static char *sfnames[] = {
@@ -281,146 +294,3 @@
 #include "irix5sys.h"
 };
 #endif
-
-/*
- * This isn't entirely correct with respect to kernel locking ...
- */
-void do_sys(struct pt_regs *regs)
-{
-	unsigned long syscallnr, usp;
-	syscall_t syscall;
-	int errno, narg;
-
-        /* Skip syscall instruction */
-	if (delay_slot(regs)) {
-		/*
-		 * By convention "li v0,<syscallno>" is always preceeding
-		 * the syscall instruction.  So if we're in a delay slot
-		 * userland is screwed up.
-		 */
-		force_sig(SIGILL, current);
-		return;
-	}
-	regs->cp0_epc += 4;
-
-	syscallnr = regs->regs[2];
-	if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
-		goto illegal_syscall;
-
-	syscall = sys_call_table[syscallnr];
-	if (syscall == NULL)
-		goto illegal_syscall;
-
-	narg = sys_narg_table[syscallnr];
-#ifdef CONF_PRINT_SYSCALLS
-	if(syscallnr >= 4000)
-		printk("do_sys(%s:%d): %s(%08lx,%08lx,%08lx,%08lx)<pc=%08lx>",
-		       current->comm, current->pid, sfnames[syscallnr - __NR_Linux],
-		       regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7],
-		       regs->cp0_epc);
-#endif
-#if defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX)
-	if(syscallnr < 2000 && syscallnr >= 1000) {
-		printk("irix_sys(%s:%d): %s(", current->comm,
-		       current->pid, irix_sys_names[syscallnr - 1000]);
-		if((narg < 4) && (narg != 0)) {
-			int i = 0;
-
-			while(i < (narg - 1)) {
-				printk("%08lx, ", regs->regs[i + 4]);
-				i++;
-			}
-			printk("%08lx) ", regs->regs[i + 4]);
-		} else if(narg == 0) {
-			printk("%08lx, %08lx, %08lx, %08lx) ",
-			       regs->regs[4], regs->regs[5], regs->regs[6],
-			       regs->regs[7]);
-		} else
-			printk("narg=%d) ", narg);
-	}
-#endif
-	if (narg > 4) {
-		/*
-		 * Verify that we can safely get the additional parameters
-		 * from the user stack.  Of course I could read the params
-		 * from unaligned addresses ...  Consider this a programming
-		 * course caliber .45.
-		 */
-		usp = regs->regs[29];
-		if (usp & 3) {
-			printk("unaligned usp\n");
-			force_sig(SIGSEGV, current);
-			regs->regs[2] = EFAULT;
-			regs->regs[7] = 1;
-			return;
-		}
-		if (!access_ok(VERIFY_READ, (void *) (usp + 16),
-		      (narg - 4) * sizeof(unsigned long))) {
-			regs->regs[2] = EFAULT;
-			regs->regs[7] = 1;
-			return;
-		}
-	}
-
-	if ((current->flags & PF_TRACESYS) == 0)
-	{
-		errno = do_syscalls(regs, syscall, narg);
-		if ((errno < 0 && errno > (-ENOIOCTLCMD - 1)) || current->errno) {
-			goto bad_syscall;
-		}
-		regs->regs[2] = errno;
-		regs->regs[7] = 0;
-	}
-	else
-	{
-		syscall_trace();
-
-		errno = do_syscalls(regs, syscall, narg);
-		if (errno < 0 || current->errno)
-		{
-			regs->regs[2] = -errno;
-			regs->regs[7] = 1;
-		}
-		else
-		{
-			regs->regs[2] = errno;
-			regs->regs[7] = 0;
-		}
-
-		syscall_trace();
-	}
-#if defined(CONF_PRINT_SYSCALLS) || \
-    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
-#if 0
-	printk(" returning: normal\n");
-#else
-	if(syscallnr >= 4000 && syscallnr < 5000)
-		printk(" returning: %08lx\n", (unsigned long) errno);
-#endif
-#endif
-	return;
-
-bad_syscall:
-	regs->regs[0] = regs->regs[2] = -errno;
-	regs->regs[7] = 1;
-#if defined(CONF_PRINT_SYSCALLS) || \
-    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
-#if 0
-	printk(" returning: bad_syscall\n");
-#else
-	if(syscallnr >= 4000 && syscallnr < 5000)
-		printk(" returning error: %d\n", errno);
-#endif
-#endif
-	return;
-illegal_syscall:
-
-	regs->regs[2] = ENOSYS;
-	regs->regs[7] = 1;
-#if defined(CONF_PRINT_SYSCALLS) || \
-    (defined(CONFIG_BINFMT_IRIX) && defined(CONF_DEBUG_IRIX))
-	if(syscallnr >= 1000 && syscallnr < 2000)
-		printk(" returning: illegal_syscall\n");
-#endif
-	return;
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- v2.1.100/linux/arch/mips/kernel/syscalls.h	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/kernel/syscalls.h	Fri May  8 00:13:24 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1995, 1996 by Ralf Baechle
  *
- * $Id: syscalls.h,v 1.6 1997/12/06 09:57:39 ralf Exp $
+ * $Id: syscalls.h,v 1.13 1998/05/01 01:34:34 ralf Exp $
  */
 
 /*
@@ -66,7 +66,7 @@
 SYS(sys_brk, 1)					/* 4045 */
 SYS(sys_setgid, 1)
 SYS(sys_getgid, 0)
-SYS(sys_signal, 2)
+SYS(sys_ni_syscall, 0)	/* was signal(2) */
 SYS(sys_geteuid, 0)
 SYS(sys_getegid, 0)				/* 4050 */
 SYS(sys_acct, 0)
@@ -211,3 +211,13 @@
 SYS(sys_setresgid, 3)				/* 4190 */
 SYS(sys_getresgid, 3)
 SYS(sys_prctl, 5)
+SYS(sys_rt_sigreturn, 0)
+SYS(sys_rt_sigaction, 4)
+SYS(sys_rt_sigprocmask, 4)			/* 4195 */
+SYS(sys_rt_sigpending, 2)
+SYS(sys_rt_sigtimedwait, 4)
+SYS(sys_rt_sigqueueinfo, 3)
+SYS(sys_rt_sigsuspend, 2)
+SYS(sys_pread, 4)				/* 4200 */
+SYS(sys_pwrite, 4)
+SYS(sys_lchown, 3)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.1.100/linux/arch/mips/kernel/sysirix.c	Thu May  7 22:51:47 1998
+++ linux/arch/mips/kernel/sysirix.c	Fri May  8 00:13:24 1998
@@ -1,7 +1,10 @@
-/* $Id: sysirix.c,v 1.6 1997/12/06 11:29:29 ralf Exp $
+/*
  * sysirix.c: IRIX system call emulation.
  *
  * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 1997 Miguel de Icaza
+ *
+ * $Id: sysirix.c,v 1.9 1998/05/01 01:34:35 ralf Exp $
  */
 
 #include <linux/kernel.h>
@@ -25,11 +28,15 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
+#include <asm/sgialib.h>
+#include <asm/inventory.h>
 
-/* 2,358 lines of complete and utter shit coming up... */
+/* 2,526 lines of complete and utter shit coming up... */
 
 /* The sysmp commands supported thus far. */
-#define MP_PGSIZE           14 /* Return system page size in v1. */
+#define MP_NPROCS       	1 /* # processor in complex */
+#define MP_NAPROCS      	2 /* # active processors in complex */
+#define MP_PGSIZE           	14 /* Return system page size in v1. */
 
 asmlinkage int irix_sysmp(struct pt_regs *regs)
 {
@@ -45,9 +52,13 @@
 	case MP_PGSIZE:
 		error = PAGE_SIZE;
 		break;
-
+	case MP_NPROCS:
+	case MP_NAPROCS:
+		error = 1;
+		error = NR_CPUS;
+		break;
 	default:
-		printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
+		printk("SYSMP[%s:%ld]: Unsupported opcode %d\n",
 		       current->comm, current->pid, (int)cmd);
 		error = -EINVAL;
 		break;
@@ -86,7 +97,7 @@
 	cmd = regs->regs[base + 4];
 	switch(cmd) {
 	case PR_MAXPROCS:
-		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n",
 		       current->comm, current->pid);
 		error = NR_TASKS;
 		break;
@@ -94,7 +105,7 @@
 	case PR_ISBLOCKED: {
 		struct task_struct *task;
 
-		printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_ISBLOCKED\n",
 		       current->comm, current->pid);
 		task = find_task_by_pid(regs->regs[base + 5]);
 		if(!task) {
@@ -109,7 +120,7 @@
 	case PR_SETSTACKSIZE: {
 		long value = regs->regs[base + 5];
 
-		printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_SETSTACKSIZE<%08lx>\n",
 		       current->comm, current->pid, (unsigned long) value);
 		if(value > RLIM_INFINITY)
 			value = RLIM_INFINITY;
@@ -129,25 +140,25 @@
 	}
 
 	case PR_GETSTACKSIZE:
-		printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_GETSTACKSIZE\n",
 		       current->comm, current->pid);
 		error = current->rlim[RLIMIT_STACK].rlim_cur;
 		break;
 
 	case PR_MAXPPROCS:
-		printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n",
 		       current->comm, current->pid);
 		error = 1;
 		break;
 
 	case PR_UNBLKONEXEC:
-		printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_UNBLKONEXEC\n",
 		       current->comm, current->pid);
 		error = -EINVAL;
 		break;
 
 	case PR_SETEXITSIG:
-		printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_SETEXITSIG\n",
 		       current->comm, current->pid);
 
 		/* We can probably play some game where we set the task
@@ -158,31 +169,31 @@
 		break;
 
 	case PR_RESIDENT:
-		printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n",
 		       current->comm, current->pid);
 		error = 0; /* Compatability indeed. */
 		break;
 
 	case PR_ATTACHADDR:
-		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDR\n",
 		       current->comm, current->pid);
 		error = -EINVAL;
 		break;
 
 	case PR_DETACHADDR:
-		printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_DETACHADDR\n",
 		       current->comm, current->pid);
 		error = -EINVAL;
 		break;
 
 	case PR_TERMCHILD:
-		printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_TERMCHILD\n",
 		       current->comm, current->pid);
 		error = -EINVAL;
 		break;
 
 	case PR_GETSHMASK:
-		printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_GETSHMASK\n",
 		       current->comm, current->pid);
 		error = -EINVAL; /* Until I have the sproc() stuff in. */
 		break;
@@ -192,24 +203,24 @@
 		break;
 
 	case PR_COREPID:
-		printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_COREPID\n",
 		       current->comm, current->pid);
 		error = -EINVAL;
 		break;
 
 	case PR_ATTACHADDRPERM:
-		printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDRPERM\n",
 		       current->comm, current->pid);
 		error = -EINVAL;
 		break;
 
 	case PR_PTHREADEXIT:
-		printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
+		printk("irix_prctl[%s:%ld]: Wants PR_PTHREADEXIT\n",
 		       current->comm, current->pid);
 		do_exit(regs->regs[base + 5]);
 
 	default:
-		printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",
+		printk("irix_prctl[%s:%ld]: Non-existant opcode %d\n",
 		       current->comm, current->pid, (int)cmd);
 		error = -EINVAL;
 		break;
@@ -225,15 +236,25 @@
 extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);
 extern void sys_sync(void);
 extern asmlinkage int sys_getsid(pid_t pid);
+extern asmlinkage long sys_write (unsigned int fd, const char *buf, unsigned long count);
+extern asmlinkage long sys_lseek (unsigned int fd, off_t offset, unsigned int origin);
 extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
 extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
 extern int getrusage(struct task_struct *p, int who, struct rusage *ru);
+extern char *prom_getenv(char *name);
+extern long prom_setenv(char *name, char *value);
 
 /* The syssgi commands supported thus far. */
 #define SGI_SYSID         1       /* Return unique per-machine identifier. */
+#define SGI_INVENT        5       /* Fetch inventory  */
+#   define SGI_INV_SIZEOF 1
+#   define SGI_INV_READ   2
 #define SGI_RDNAME        6       /* Return string name of a process. */
+#define SGI_SETNVRAM	  8	  /* Set PROM variable. */
+#define SGI_GETNVRAM	  9	  /* Get PROM variable. */
 #define SGI_SETPGID      21       /* Set process group id. */
 #define SGI_SYSCONF      22       /* POSIX sysconf garbage. */
+#define SGI_PATHCONF     24       /* POSIX sysconf garbage. */
 #define SGI_SETGROUPS    40       /* POSIX sysconf garbage. */
 #define SGI_GETGROUPS    41       /* POSIX sysconf garbage. */
 #define SGI_RUSAGE       56       /* BSD style rusage(). */
@@ -246,45 +267,81 @@
 
 asmlinkage int irix_syssgi(struct pt_regs *regs)
 {
-	unsigned long cmd;
-	int retval, base = 0;
+        unsigned long cmd;
+        int retval, base = 0;
 
-	lock_kernel();
-	if(regs->regs[2] == 1000)
-		base = 1;
-
-	cmd = regs->regs[base + 4];
-	switch(cmd) {
-	case SGI_SYSID: {
-		char *buf = (char *) regs->regs[base + 5];
-
-		/* XXX Use ethernet addr.... */
-		retval = clear_user(buf, 64);
-		break;
-	}
-
-	case SGI_RDNAME: {
-		int pid = (int) regs->regs[base + 5];
-		char *buf = (char *) regs->regs[base + 6];
-		struct task_struct *p;
-
-		retval = verify_area(VERIFY_WRITE, buf, 16);
-		if(retval)
-			break;
-		for_each_task(p) {
-			if(p->pid == pid)
-				goto found0;
-		}
-		retval = -ESRCH;
-
-	found0:
-		copy_to_user(buf, p->comm, 16);
-		retval = 0;
+        lock_kernel();
+        if(regs->regs[2] == 1000)
+                base = 1;
+
+        cmd = regs->regs[base + 4];
+        switch(cmd) {
+        case SGI_SYSID: {
+                char *buf = (char *) regs->regs[base + 5];
+
+                /* XXX Use ethernet addr.... */
+                retval = clear_user(buf, 64);
+                break;
+        }
+#if 0
+        case SGI_RDNAME: {
+                int pid = (int) regs->regs[base + 5];
+                char *buf = (char *) regs->regs[base + 6];
+                struct task_struct *p;
+
+                retval = verify_area(VERIFY_WRITE, buf, 16);
+                if(retval)
+                        break;
+                for_each_task(p) {
+                        if(p->pid == pid)
+                                goto found0;
+                }
+                retval = -ESRCH;
+
+        found0:
+                /* XXX Need to check sizes. */
+                copy_to_user(buf, p->comm, 16);
+                retval = 0;
+                break;
+        }
+
+        case SGI_GETNVRAM: {
+                char *name = (char *) regs->regs[base+5];
+                char *buf = (char *) regs->regs[base+6];
+                char *value;
+		return -EINVAL;	/* til I fix it */
+                retval = verify_area(VERIFY_WRITE, buf, 128);
+                if (retval)
+                        break;
+                value = prom_getenv(name);
+                if (!value) {
+                        retval = -EINVAL;
+                        break;
+                }
+                /* Do I strlen() for the length? */
+                copy_to_user(buf, value, 128);
+                retval = 0;
+                break;
+        }
+
+        case SGI_SETNVRAM: {
+                char *name = (char *) regs->regs[base+5];
+                char *value = (char *) regs->regs[base+6];
+		return -EINVAL;	/* til I fix it */
+                retval = prom_setenv(name, value);
+		/* XXX make sure retval conforms to syssgi(2) */
+		printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",
+		       current->comm, current->pid,
+		       name, value, retval);
+/*		if (retval == PROM_ENOENT)
+		  	retval = -ENOENT; */
+		break;				   
 	}
-
+#endif
+	
 	case SGI_SETPGID: {
 #ifdef DEBUG_PROCGRPS
-		printk("[%s:%d] setpgid(%d, %d) ",
+		printk("[%s:%ld] setpgid(%d, %d) ",
 		       current->comm, current->pid,
 		       (int) regs->regs[base + 5], (int)regs->regs[base + 6]);
 #endif
@@ -381,7 +438,7 @@
 
 	case SGI_GETSID:
 #ifdef DEBUG_PROCGRPS
-		printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
+		printk("[%s:%ld] getsid(%d) ", current->comm, current->pid,
 		       (int) regs->regs[base + 5]);
 #endif
 		retval = sys_getsid(regs->regs[base + 5]);
@@ -428,6 +485,24 @@
 		break;
 	}
 
+	case SGI_INVENT: {
+		int  arg1    = (int)    regs->regs [base + 5];
+		void *buffer = (void *) regs->regs [base + 6];
+		int  count   = (int)    regs->regs [base + 7];
+
+		switch (arg1){
+		case SGI_INV_SIZEOF:
+			retval = sizeof (inventory_t);
+			break;
+		case SGI_INV_READ:
+			retval = dump_inventory_to_user (buffer, count);
+			break;
+		default:
+			retval = -EINVAL;
+		}
+		break;
+	}
+	
 	default:
 		printk("irix_syssgi: Unsupported command %d\n", (int)cmd);
 		retval = -EINVAL;
@@ -563,7 +638,8 @@
 	return ret;
 }
 
-extern int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
+extern int do_setitimer(int which, struct itimerval *value,
+                        struct itimerval *ovalue);
 
 static inline void jiffiestotv(unsigned long jiffies, struct timeval *value)
 {
@@ -604,7 +680,7 @@
 		it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
 		it_new.it_value.tv_sec = seconds;
 		it_new.it_value.tv_usec = 0;
-		_setitimer(ITIMER_REAL, &it_new, &it_old);
+		do_setitimer(ITIMER_REAL, &it_new, &it_old);
 	}
 	oldalarm = it_old.it_value.tv_sec;
 	/* ehhh.. We can't return 0 if we have an alarm pending.. */
@@ -634,7 +710,7 @@
 	int ret;
 
 	lock_kernel();
-	printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
+	printk("[%s:%ld] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
 	       current->comm, current->pid,
 	       dev_name, dir_name, flags, type, data, datalen);
 	ret = sys_mount(dev_name, dir_name, type, flags, data);
@@ -654,8 +730,9 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
+	mm_segment_t old_fs;
 	struct statfs kbuf;
-	int error, old_fs, i;
+	int error, i;
 
 	/* We don't support this feature yet. */
 	if(fs_type) {
@@ -703,8 +780,9 @@
 	struct dentry *dentry;
 	struct inode *inode;
 	struct statfs kbuf;
+	mm_segment_t old_fs;
 	struct file *file;
-	int error, old_fs, i;
+	int error, i;
 
 	lock_kernel();
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
@@ -751,6 +829,7 @@
 	}
 	error = 0;
 
+	dput(dentry);
 out:
 	unlock_kernel();
 	return error;
@@ -765,7 +844,7 @@
 
 	lock_kernel();
 #ifdef DEBUG_PROCGRPS
-	printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
+	printk("[%s:%ld] setpgrp(%d) ", current->comm, current->pid, flags);
 #endif
 	if(!flags)
 		error = current->pgrp;
@@ -845,7 +924,7 @@
 asmlinkage unsigned long irix_gethostid(void)
 {
 	lock_kernel();
-	printk("[%s:%d]: irix_gethostid() called...\n",
+	printk("[%s:%ld]: irix_gethostid() called...\n",
 	       current->comm, current->pid);
 	unlock_kernel();
 	return -EINVAL;
@@ -854,7 +933,7 @@
 asmlinkage unsigned long irix_sethostid(unsigned long val)
 {
 	lock_kernel();
-	printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
+	printk("[%s:%ld]: irix_sethostid(%08lx) called...\n",
 	       current->comm, current->pid, val);
 	unlock_kernel();
 	return -EINVAL;
@@ -983,8 +1062,9 @@
 
 asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base)
 {
+	mm_segment_t old_fs;
 	loff_t junk;
-	int old_fs, error;
+	int error;
 
 	lock_kernel();
 	old_fs = get_fs(); set_fs(get_ds());
@@ -1026,6 +1106,8 @@
 	return retval;
 }
 
+#define IRIX_MAP_AUTOGROW 0x40
+
 asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
 				     int flags, int fd, off_t offset)
 {
@@ -1038,7 +1120,19 @@
 			retval = -EBADF;
 			goto out;
 		}
+		/* Ok, bad taste hack follows, try to think in something else when reading this */
+		if (flags & IRIX_MAP_AUTOGROW){
+			unsigned long old_pos;
+			long max_size = offset + len;
+			
+			if (max_size > file->f_dentry->d_inode->i_size){
+				old_pos = sys_lseek (fd, max_size - 1, 0);
+				sys_write (fd, "", 1);
+				sys_lseek (fd, old_pos, 0);
+			}
+		}
 	}
+	
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
 	retval = do_mmap(file, addr, len, prot, flags, offset);
@@ -1051,7 +1145,7 @@
 asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n",
 	       current->comm, current->pid, addr, len, behavior);
 	unlock_kernel();
 	return -EINVAL;
@@ -1060,7 +1154,7 @@
 asmlinkage int irix_pagelock(char *addr, int len, int op)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_pagelock(%p,%d,%d)\n",
 	       current->comm, current->pid, addr, len, op);
 	unlock_kernel();
 	return -EINVAL;
@@ -1069,7 +1163,7 @@
 asmlinkage int irix_quotactl(struct pt_regs *regs)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_quotactl()\n",
+	printk("[%s:%ld] Wheee.. irix_quotactl()\n",
 	       current->comm, current->pid);
 	unlock_kernel();
 	return -EINVAL;
@@ -1081,7 +1175,7 @@
 
 	lock_kernel();
 #ifdef DEBUG_PROCGRPS
-	printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
+	printk("[%s:%ld] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
 	       pid, pgrp);
 #endif
 	if(!pid)
@@ -1104,7 +1198,7 @@
 asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_systeminfo(%d,%p,%d)\n",
 	       current->comm, current->pid, cmd, buf, cnt);
 	unlock_kernel();
 	return -EINVAL;
@@ -1140,7 +1234,13 @@
 
 #undef DEBUG_XSTAT
 
-static inline int irix_xstat32_xlate(struct stat *kb, struct stat *ubuf)
+static inline u32
+linux_to_irix_dev_t (dev_t t)
+{
+	return MAJOR (t) << 18 | MINOR (t);
+}
+
+static inline int irix_xstat32_xlate(struct stat *kb, void *ubuf)
 {
 	struct xstat32 {
 		u32 st_dev, st_pad1[3], st_ino, st_mode, st_nlink, st_uid, st_gid;
@@ -1151,9 +1251,27 @@
 		u32 st_blksize, st_blocks;
 		char st_fstype[16];
 		u32 st_pad4[8];
-	} *ub = (struct xstat32 *) ubuf;
+	} ub;
 
-	return copy_to_user(ub, kb, sizeof(*ub)) ? -EFAULT : 0;
+	ub.st_dev     = linux_to_irix_dev_t (kb->st_dev);
+	ub.st_ino     = kb->st_ino;
+	ub.st_mode    = kb->st_mode;
+	ub.st_nlink   = kb->st_nlink;
+	ub.st_uid     = kb->st_uid;
+	ub.st_gid     = kb->st_gid;
+	ub.st_rdev    = linux_to_irix_dev_t (kb->st_rdev);
+	ub.st_size    = kb->st_size;
+	ub.st_atime0  = kb->st_atime;
+	ub.st_atime1  = 0;
+	ub.st_mtime0  = kb->st_mtime;
+	ub.st_mtime1  = 0;
+	ub.st_ctime0  = kb->st_ctime;
+	ub.st_ctime1  = 0;
+	ub.st_blksize = kb->st_blksize;
+	ub.st_blocks  = kb->st_blocks;
+	strcpy (ub.st_fstype, "efs");
+
+	return copy_to_user(ubuf, &ub, sizeof(ub)) ? -EFAULT : 0;
 }
 
 static inline void irix_xstat64_xlate(struct stat *sb)
@@ -1173,14 +1291,14 @@
 		s32 st_pad4[8];
 	} ks;
 
-	ks.st_dev = (u32) sb->st_dev;
+	ks.st_dev = linux_to_irix_dev_t (sb->st_dev);
 	ks.st_pad1[0] = ks.st_pad1[1] = ks.st_pad1[2] = 0;
 	ks.st_ino = (unsigned long long) sb->st_ino;
 	ks.st_mode = (u32) sb->st_mode;
 	ks.st_nlink = (u32) sb->st_nlink;
 	ks.st_uid = (s32) sb->st_uid;
 	ks.st_gid = (s32) sb->st_gid;
-	ks.st_rdev = (u32) sb->st_rdev;
+	ks.st_rdev = linux_to_irix_dev_t (sb->st_rdev);
 	ks.st_pad2[0] = ks.st_pad2[1] = 0;
 	ks.st_size = (long long) sb->st_size;
 	ks.st_pad3 = 0;
@@ -1208,13 +1326,13 @@
 
 	lock_kernel();
 #ifdef DEBUG_XSTAT
-	printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
+	printk("[%s:%ld] Wheee.. irix_xstat(%d,%s,%p) ",
 	       current->comm, current->pid, version, filename, statbuf);
 #endif
 	switch(version) {
 	case 2: {
 		struct stat kb;
-		int old_fs;
+		mm_segment_t old_fs;
 
 		old_fs = get_fs(); set_fs(get_ds());
 		retval = sys_newstat(filename, &kb);
@@ -1259,13 +1377,13 @@
 
 	lock_kernel();
 #ifdef DEBUG_XSTAT
-	printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
+	printk("[%s:%ld] Wheee.. irix_lxstat(%d,%s,%p) ",
 	       current->comm, current->pid, version, filename, statbuf);
 #endif
 	switch(version) {
 	case 2: {
 		struct stat kb;
-		int old_fs;
+		mm_segment_t old_fs;
 
 		old_fs = get_fs(); set_fs(get_ds());
 		error = sys_newlstat(filename, &kb);
@@ -1310,13 +1428,13 @@
 
 	lock_kernel();
 #ifdef DEBUG_XSTAT
-	printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
+	printk("[%s:%ld] Wheee.. irix_fxstat(%d,%d,%p) ",
 	       current->comm, current->pid, version, fd, statbuf);
 #endif
 	switch(version) {
 	case 2: {
 		struct stat kb;
-		int old_fs;
+		mm_segment_t old_fs;
 
 		old_fs = get_fs(); set_fs(get_ds());
 		error = sys_newfstat(fd, &kb);
@@ -1360,7 +1478,7 @@
 	int retval;
 
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
+	printk("[%s:%ld] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
 	       current->comm, current->pid, ver, filename, mode, (int) dev);
 	switch(ver) {
 	case 2:
@@ -1380,7 +1498,7 @@
 asmlinkage int irix_swapctl(int cmd, char *arg)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
+	printk("[%s:%ld] Wheee.. irix_swapctl(%d,%p)\n",
 	       current->comm, current->pid, cmd, arg);
 	unlock_kernel();
 	return -EINVAL;
@@ -1398,11 +1516,12 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
+	mm_segment_t old_fs;
 	struct statfs kbuf;
-	int error, old_fs, i;
+	int error, i;
 
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
+	printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
 	       current->comm, current->pid, fname, buf);
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
 	if(error)
@@ -1457,12 +1576,13 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
+	mm_segment_t old_fs;
 	struct statfs kbuf;
 	struct file *file;
-	int error, old_fs, i;
+	int error, i;
 
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
+	printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n",
 	       current->comm, current->pid, fd, buf);
 
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
@@ -1514,6 +1634,7 @@
 
 	error = 0;
 
+	dput(dentry);
 out:
 	unlock_kernel();
 	return error;
@@ -1571,11 +1692,11 @@
 		error = -EDQUOT;
 		if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
 			goto dput_and_out;
-		error = notify_change(inode, &newattrs);
+		error = notify_change(dentry, &newattrs);
 		if (error)
 			inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
 	} else
-		error = notify_change(inode, &newattrs);
+		error = notify_change(dentry, &newattrs);
 
 dput_and_out:
 	dput(dentry);
@@ -1612,7 +1733,7 @@
 asmlinkage int irix_priocntl(struct pt_regs *regs)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_priocntl()\n",
+	printk("[%s:%ld] Wheee.. irix_priocntl()\n",
 	       current->comm, current->pid);
 	unlock_kernel();
 	return -EINVAL;
@@ -1621,7 +1742,7 @@
 asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
 	       current->comm, current->pid, pid, sig, code, val);
 	unlock_kernel();
 	return -EINVAL;
@@ -1667,10 +1788,10 @@
 
 asmlinkage int irix_mmap64(struct pt_regs *regs)
 {
+	int len, prot, flags, fd, off1, off2, error, base = 0;
 	unsigned long addr, *sp;
-	int len, prot, flags, fd, off1, off2, base = 0;
-	int error;
-
+	struct file *file;
+	
 	lock_kernel();
 	if(regs->regs[2] == 1000)
 		base = 1;
@@ -1699,6 +1820,26 @@
 		error = -EINVAL;
 		goto out;
 	}
+
+	if(!(flags & MAP_ANONYMOUS)) {
+		if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+			error = -EBADF;
+			goto out;
+		}
+		
+		/* Ok, bad taste hack follows, try to think in something else when reading this */
+		if (flags & IRIX_MAP_AUTOGROW){
+			unsigned long old_pos;
+			long max_size = off2 + len;
+			
+			if (max_size > file->f_dentry->d_inode->i_size){
+				old_pos = sys_lseek (fd, max_size - 1, 0);
+				sys_write (fd, "", 1);
+				sys_lseek (fd, old_pos, 0);
+			}
+		}
+	}
+	
 	error = sys_mmap(addr, (size_t) len, prot, flags, fd, off2);
 
 out:
@@ -1709,7 +1850,7 @@
 asmlinkage int irix_dmi(struct pt_regs *regs)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_dmi()\n",
+	printk("[%s:%ld] Wheee.. irix_dmi()\n",
 	       current->comm, current->pid);
 	unlock_kernel();
 	return -EINVAL;
@@ -1719,7 +1860,7 @@
 			  int off1, int off2)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
 	       current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
 	unlock_kernel();
 	return -EINVAL;
@@ -1729,7 +1870,7 @@
 			   int off1, int off2)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
 	       current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
 	unlock_kernel();
 	return -EINVAL;
@@ -1740,7 +1881,7 @@
 				unsigned long arg4, unsigned long arg5)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
+	printk("[%s:%ld] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
 	       "%08lx,%08lx)\n",
 	       current->comm, current->pid, cmd, arg0, arg1, arg2,
 	       arg3, arg4, arg5);
@@ -1763,10 +1904,11 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
+	mm_segment_t old_fs;
 	struct statfs kbuf;
-	int error, old_fs, i;
+	int error, i;
 
-	printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
+	printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
 	       current->comm, current->pid, fname, buf);
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
 	if(error)
@@ -1820,12 +1962,13 @@
 {
 	struct dentry *dentry;
 	struct inode *inode;
+	mm_segment_t old_fs;
 	struct statfs kbuf;
 	struct file *file;
-	int error, old_fs, i;
+	int error, i;
 
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
+	printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n",
 	       current->comm, current->pid, fd, buf);
 
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
@@ -1877,6 +2020,7 @@
 
 	error = 0;
 
+	dput(dentry);
 out:
 	unlock_kernel();
 	return error;
@@ -1887,7 +2031,7 @@
 	int error;
 
 	lock_kernel();
-	printk("[%s:%d] irix_getmountid(%s, %p)\n",
+	printk("[%s:%ld] irix_getmountid(%s, %p)\n",
 	       current->comm, current->pid, fname, midbuf);
 	error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
 	if(error)
@@ -1914,7 +2058,7 @@
 			   unsigned long arg, unsigned long sp, int slen)
 {
 	lock_kernel();
-	printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
+	printk("[%s:%ld] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
 	       current->comm, current->pid, entry, mask, arg, sp, slen);
 	unlock_kernel();
 	return -EINVAL;
@@ -1987,7 +2131,7 @@
 
 	lock_kernel();
 #ifdef DEBUG_GETDENTS
-	printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm,
+	printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm,
 	       current->pid, fd, dirent, count, eob);
 #endif
 	error = -EBADF;
@@ -2219,41 +2363,41 @@
 	switch(op) {
 	case 1:
 		/* Reboot */
-		printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
+		printk("[%s:%ld] irix_uadmin: Wants to reboot...\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 2:
 		/* Shutdown */
-		printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
+		printk("[%s:%ld] irix_uadmin: Wants to shutdown...\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 4:
 		/* Remount-root */
-		printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
+		printk("[%s:%ld] irix_uadmin: Wants to remount root...\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 8:
 		/* Kill all tasks. */
-		printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
+		printk("[%s:%ld] irix_uadmin: Wants to kill all tasks...\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 256:
 		/* Set magic mushrooms... */
-		printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
+		printk("[%s:%ld] irix_uadmin: Wants to set magic mushroom[%d]...\n",
 		       current->comm, current->pid, (int) func);
 		retval = -EINVAL;
 		goto out;
 
 	default:
-		printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
+		printk("[%s:%ld] irix_uadmin: Unknown operation [%d]...\n",
 		       current->comm, current->pid, (int) op);
 		retval = -EINVAL;
 		goto out;
@@ -2277,20 +2421,20 @@
 
 	case 2:
 		/* ustat() */
-		printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
+		printk("[%s:%ld] irix_utssys: Wants to do ustat()\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 3:
 		/* fusers() */
-		printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
+		printk("[%s:%ld] irix_utssys: Wants to do fusers()\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	default:
-		printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
+		printk("[%s:%ld] irix_utssys: Wants to do unknown type[%d]\n",
 		       current->comm, current->pid, (int) type);
 		retval = -EINVAL;
 		goto out;
@@ -2306,16 +2450,20 @@
 extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd,
 				 unsigned long arg);
 
+#define IRIX_F_ALLOCSP 10
+
 asmlinkage int irix_fcntl(int fd, int cmd, int arg)
 {
 	int retval;
 
 	lock_kernel();
 #ifdef DEBUG_FCNTL
-	printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm,
+	printk("[%s:%ld] irix_fcntl(%d, %d, %d) ", current->comm,
 	       current->pid, fd, cmd, arg);
 #endif
-
+	if (cmd == IRIX_F_ALLOCSP){
+		return 0;
+	}
 	retval = sys_fcntl(fd, cmd, arg);
 #ifdef DEBUG_FCNTL
 	printk("%d\n", retval);
@@ -2331,26 +2479,26 @@
 	lock_kernel();
 	switch(cmd) {
 	case 1:
-		printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
+		printk("[%s:%ld] irix_ulimit: Wants to get file size limit.\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 2:
-		printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
+		printk("[%s:%ld] irix_ulimit: Wants to set file size limit.\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 3:
-		printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
+		printk("[%s:%ld] irix_ulimit: Wants to get brk limit.\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	case 4:
 #if 0
-		printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
+		printk("[%s:%ld] irix_ulimit: Wants to get fd limit.\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
@@ -2359,13 +2507,13 @@
 		goto out;
 
 	case 5:
-		printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
+		printk("[%s:%ld] irix_ulimit: Wants to get txt offset.\n",
 		       current->comm, current->pid);
 		retval = -EINVAL;
 		goto out;
 
 	default:
-		printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
+		printk("[%s:%ld] irix_ulimit: Unknown command [%d].\n",
 		       current->comm, current->pid, cmd);
 		retval = -EINVAL;
 		goto out;
@@ -2378,7 +2526,7 @@
 asmlinkage int irix_unimp(struct pt_regs *regs)
 {
 	lock_kernel();
-	printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
+	printk("irix_unimp [%s:%ld] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
 	       "a3=%08lx\n", current->comm, current->pid,
 	       (int) regs->regs[2], (int) regs->regs[3],
 	       regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
--- v2.1.100/linux/arch/mips/kernel/sysmips.c	Thu May  7 22:51:47 1998
+++ linux/arch/mips/kernel/sysmips.c	Fri May  8 00:13:24 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
- * $Id: sysmips.c,v 1.3 1997/07/18 06:26:02 ralf Exp $
+ * $Id: sysmips.c,v 1.7 1998/05/01 01:34:38 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/linkage.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v2.1.100/linux/arch/mips/kernel/time.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/kernel/time.c	Fri May  8 00:13:24 1998
@@ -6,7 +6,7 @@
  * This file contains the time handling details for PC-style clocks as
  * found in some MIPS systems.
  *
- * $Id: time.c,v 1.5 1997/11/12 12:12:12 ralf Exp $
+ * $Id: time.c,v 1.8 1998/05/01 01:34:39 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- v2.1.100/linux/arch/mips/kernel/traps.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/kernel/traps.c	Fri May  8 00:13:24 1998
@@ -8,11 +8,12 @@
  * Copyright 1994, 1995, 1996, 1997 by Ralf Baechle
  * Modified for R3000 by Paul M. Antoine, 1995, 1996
  *
- * $Id: traps.c,v 1.7 1997/12/01 16:33:28 ralf Exp $
+ * $Id: traps.c,v 1.10 1998/05/04 09:17:57 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
@@ -27,10 +28,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_SGI
-#include <asm/sgialib.h>
-#endif
-
 #undef CONF_DEBUG_EXCEPTIONS
 
 static inline void console_verbose(void)
@@ -105,7 +102,7 @@
 	/*
 	 * Dump the stack
 	 */
-	printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
+	printk("Process %s (pid: %ld, stackpage=%08lx)\nStack: ",
 		current->comm, current->pid, (unsigned long)current);
 	for(i=0;i<5;i++)
 		printk("%08x ", *sp++);
@@ -167,18 +164,9 @@
 
 void die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
-	/*
-	 * Just return if in user mode.
-	 * XXX
-	 */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-	if (!((regs)->cp0_status & 0x4))
-		return;
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
-	if (regs->cp0_status & ST0_KSU == KSU_USER)
+	if (user_mode(regs))	/* Just return if in user mode.  */
 		return;
-#endif
+
 	console_verbose();
 	printk("%s: %04lx\n", str, err & 0xffff);
 	show_regs(regs);
@@ -196,6 +184,7 @@
 void do_ibe(struct pt_regs *regs)
 {
 	lock_kernel();
+show_regs(regs); while(1);
 	ibe_board_handler(regs);
 	unlock_kernel();
 }
@@ -203,6 +192,7 @@
 void do_dbe(struct pt_regs *regs)
 {
 	lock_kernel();
+show_regs(regs); while(1);
 	dbe_board_handler(regs);
 	unlock_kernel();
 }
@@ -240,7 +230,10 @@
 }
 #endif
 
-void do_fpe(struct pt_regs *regs, unsigned int fcr31)
+/*
+ * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
+ */
+void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
 #ifdef CONFIG_MIPS_FPE_MODULE
 	if (fpe_handler != NULL) {
@@ -252,8 +245,23 @@
 #ifdef CONF_DEBUG_EXCEPTIONS
 	show_regs(regs);
 #endif
-	printk("Caught floating exception at epc == %08lx, fcr31 == %08x\n",
-	       regs->cp0_epc, fcr31);
+	if (fcr31 & 0x20000) {
+		/* Retry instruction with flush to zero ...  */
+		if (!(fcr31 & (1<<24))) {
+			printk("Setting flush to zero for %s.\n",
+			       current->comm);
+			fcr31 &= ~0x20000;
+			fcr31 |= (1<<24);
+			__asm__ __volatile__(
+				"ctc1\t%0,$31"
+				: /* No outputs */
+				: "r" (fcr31));
+			goto out;
+		}
+		printk("Unimplemented exception at 0x%08lx in %s.\n",
+		       regs->cp0_epc, current->comm);
+	}
+
 	if (compute_return_epc(regs))
 		goto out;
 	force_sig(SIGFPE, current);
@@ -337,7 +345,7 @@
 #ifdef CONF_DEBUG_EXCEPTIONS
 	show_regs(regs);
 #endif
-	printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
+	printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
 	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
 	if (compute_return_epc(regs))
 		goto out;
@@ -350,16 +358,29 @@
 {
 	unsigned int cpid;
 
-	lock_kernel();
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
-	if (cpid == 1)
-	{
-		regs->cp0_status |= ST0_CU1;
+	if (cpid != 1)
+		goto bad_cid;
+
+	regs->cp0_status |= ST0_CU1;
+	if (last_task_used_math == current)
 		goto out;
+
+	if (current->used_math) {		/* Using the FPU again.  */
+		r4xx0_lazy_fpu_switch(last_task_used_math);
+	} else {				/* First time FPU user.  */
+
+		r4xx0_init_fpu();
+		current->used_math = 1;
 	}
+	last_task_used_math = current;
+	return;
+
+bad_cid:
+	lock_kernel();
 	force_sig(SIGILL, current);
-out:
 	unlock_kernel();
+out:
 }
 
 void do_vcei(struct pt_regs *regs)
@@ -460,13 +481,6 @@
 	}
 }
 
-typedef asmlinkage int (*syscall_t)(void *a0,...);
-asmlinkage int (*do_syscalls)(struct pt_regs *regs, syscall_t fun, int narg);
-extern asmlinkage int r4k_do_syscalls(struct pt_regs *regs,
-				      syscall_t fun, int narg);
-extern asmlinkage int r2300_do_syscalls(struct pt_regs *regs,
-					syscall_t fun, int narg);
-
 asmlinkage void (*save_fp_context)(struct sigcontext *sc);
 extern asmlinkage void r4k_save_fp_context(struct sigcontext *sc);
 extern asmlinkage void r2300_save_fp_context(struct sigcontext *sc);
@@ -489,7 +503,6 @@
 	unsigned long i;
 
 	if(mips_machtype == MACH_MIPS_MAGNUM_4000 ||
-	   mips_machtype == MACH_DESKSTATION_RPC44 ||
 	   mips_machtype == MACH_SNI_RM200_PCI)
 		EISA_bus = 1;
 
@@ -560,7 +573,6 @@
 		memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
 		memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
 
-		do_syscalls = r4k_do_syscalls;
 		save_fp_context = r4k_save_fp_context;
 		restore_fp_context = r4k_restore_fp_context;
 		resume = r4xx0_resume;
@@ -607,7 +619,6 @@
 	case CPU_R3000:
 	case CPU_R3000A:
 		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
-		do_syscalls = r2300_do_syscalls;
 		save_fp_context = r2300_save_fp_context;
 		restore_fp_context = r2300_restore_fp_context;
 		resume = r2300_resume;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c
--- v2.1.100/linux/arch/mips/kernel/unaligned.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/kernel/unaligned.c	Fri May  8 00:13:24 1998
@@ -5,7 +5,9 @@
  * 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
+ *
+ * $Id: unaligned.c,v 1.3 1998/05/04 09:17:59 ralf Exp $
  *
  * This file contains exception handler for address error exception with the
  * special capability to execute faulting instructions in software.  The
@@ -34,13 +36,7 @@
  * sysmips(MIPS_FIXADE, x);
  * ...
  *
- * The parameter x is 0 for disabeling software emulation.  Set bit 0 for
- * enabeling software emulation and bit 1 for enabeling printing debug
- * messages into syslog to aid finding address errors in programs.
- *
- * The logging feature is an addition over RISC/os and IRIX where only the
- * values 0 and 1 are acceptable values for x.  I'll probably remove this
- * hack later on.
+ * The argument x is 0 for disabling software emulation, enabled otherwise.
  *
  * Below a little program to play around with this feature.
  *
@@ -69,12 +65,6 @@
  *         printf("\n");
  * }
  *
- * Until I've written the code to handle branch delay slots it may happen
- * that the kernel receives an ades/adel instruction from an insn in a
- * branch delay slot but is unable to handle this case.  The kernel knows
- * this fact and therefore will kill the process.  For most code you can
- * fix this temporarily by compiling with flags -fno-delayed-branch -Wa,-O0.
- *
  * Coprozessor loads are not supported; I think this case is unimportant
  * in the practice.
  *
@@ -88,19 +78,15 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
+#include <asm/asm.h>
 #include <asm/branch.h>
 #include <asm/byteorder.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
 
-#undef CONF_NO_UNALIGNED_KERNEL_ACCESS
-#undef CONF_LOG_UNALIGNED_ACCESSES
-
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
 
-typedef unsigned long register_t;
-
 /*
  * User code may only access USEG; kernel code may access the
  * entire address space.
@@ -110,10 +96,12 @@
 		goto sigbus;
 
 static inline void
-emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long pc)
+emulate_load_store_insn(struct pt_regs *regs,
+                        unsigned long addr,
+                        unsigned long pc)
 {
 	union mips_instruction insn;
-	register_t value;
+	unsigned long value, fixup;
 
 	regs->regs[0] = 0;
 	/*
@@ -358,99 +346,70 @@
 		 */
 	default:
 		/*
-		 * Pheeee...  We encountered an yet unknown instruction ...
+		 * Pheeee...  We encountered an yet unknown instruction or
+		 * cache coherence problem.  Die sucker, die ...
 		 */
-		force_sig(SIGILL, current);
+		goto sigill;
 	}
 	return;
 
 fault:
+	/* Did we have an exception handler installed? */
+	fixup = search_exception_table(regs->cp0_epc);
+	if (fixup) {
+		long new_epc;
+		new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
+		printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n",
+		       current->comm, regs->cp0_epc, new_epc);
+		regs->cp0_epc = new_epc;
+		return;
+	}
+
+	lock_kernel();
 	send_sig(SIGSEGV, current, 1);
+	unlock_kernel();
 	return;
 sigbus:
+	lock_kernel();
 	send_sig(SIGBUS, current, 1);
+	unlock_kernel();
+	return;
+sigill:
+	lock_kernel();
+	send_sig(SIGILL, current, 1);
+	unlock_kernel();
 	return;
 }
 
 unsigned long unaligned_instructions;
 
-static inline void
-fix_ade(struct pt_regs *regs, unsigned long pc)
+asmlinkage void do_ade(struct pt_regs *regs)
 {
+	unsigned long pc;
+
 	/*
 	 * Did we catch a fault trying to load an instruction?
+	 * This also catches attempts to activate MIPS16 code on
+	 * CPUs which don't support it.
 	 */
-	if (regs->cp0_badvaddr == pc) {
-		/*
-		 * Phee...  Either the code is severly messed up or the
-		 * process tried to activate some MIPS16 code.
-		 */
-		force_sig(SIGBUS, current);
-	}
+	if (regs->cp0_badvaddr == regs->cp0_epc)
+		goto sigbus;
+
+	pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
+	if (compute_return_epc(regs))
+		return;
+	if ((current->tss.mflags & MF_FIXADE) == 0)
+		goto sigbus;
 
-	/*
-	 * Ok, this wasn't a failed instruction load.  The CPU was capable of
-	 * reading the instruction and faulted after this.  So we don't need
-	 * to verify_area the address of the instrucion.  We still don't
-	 * know whether the address used was legal and therefore need to do
-	 * verify_area().  The CPU already did the checking for legal
-	 * instructions for us, so we don't need to do this.
-	 */
 	emulate_load_store_insn(regs, regs->cp0_badvaddr, pc);
 	unaligned_instructions++;
-}
-
-#define kernel_address(x) ((long)(x) < 0)
 
-asmlinkage void
-do_ade(struct pt_regs *regs)
-{
-	register_t pc = regs->cp0_epc;
-	register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr;
-	char adels;
+	return;
 
+sigbus:
 	lock_kernel();
-	adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >>
-                  CAUSEB_EXCCODE) == 4) ? 'l' : 's';
-
-#ifdef CONF_NO_UNALIGNED_KERNEL_ACCESS
-	/*
-	 * In an ideal world there are no unaligned accesses by the kernel.
-	 * So be a bit noisy ...
-	 */
-	if (kernel_address(badvaddr) && !user_mode(regs)) {
-		show_regs(regs);
-		panic("Caught adel%c exception in kernel mode accessing %08lx.",
-		      adels, badvaddr);
-	}
-#endif /* CONF_NO_UNALIGNED_KERNEL_ACCESS */
-
-#ifdef CONF_LOG_UNALIGNED_ACCESSES
-	if (current->tss.mflags & MF_LOGADE) {
-		register_t logpc = pc;
-		if (regs->cp0_cause & CAUSEF_BD)
-			logpc += 4;
-		printk(KERN_DEBUG
-		       "Caught adel%c in '%s' at 0x%08lx accessing 0x%08lx.\n",
-		       adels, current->comm, logpc, regs->cp0_badvaddr);
-	}
-#endif /* CONF_LOG_UNALIGNED_ACCESSES */
-
-	if (compute_return_epc(regs))
-		goto out;
-	if(current->tss.mflags & MF_FIXADE) {
-		pc += ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
-		fix_ade(regs, pc);
-		goto out;
-	}
-
-#ifdef CONF_DEBUG_EXCEPTIONS
-	show_regs(regs);
-#endif
-
 	force_sig(SIGBUS, current);
-
-out:
 	unlock_kernel();
+
 	return;
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/ld.script.big linux/arch/mips/ld.script.big
--- v2.1.100/linux/arch/mips/ld.script.big	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/ld.script.big	Fri May  8 00:13:24 1998
@@ -37,6 +37,15 @@
   } =0
   _etext = .;
   PROVIDE (etext = .);
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);	/* Align double page for init_task_union */
+  __init_end = .;
+
   .fini      : { *(.fini)    } =0
   .reginfo : { *(.reginfo) }
   /* Adjust the address for the data segment.  We want to adjust up to
@@ -74,6 +83,7 @@
   .sdata     : { *(.sdata) }
   _edata  =  .;
   PROVIDE (edata = .);
+
   __bss_start = .;
   _fbss = .;
   .bss       :
diff -u --recursive --new-file v2.1.100/linux/arch/mips/ld.script.little linux/arch/mips/ld.script.little
--- v2.1.100/linux/arch/mips/ld.script.little	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/ld.script.little	Fri May  8 00:13:24 1998
@@ -37,6 +37,15 @@
   } =0
   _etext = .;
   PROVIDE (etext = .);
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);	/* Align double page for init_task_union */
+  __init_end = .;
+
   .fini      : { *(.fini)    } =0
   .reginfo : { *(.reginfo) }
   /* Adjust the address for the data segment.  We want to adjust up to
@@ -74,6 +83,7 @@
   .sdata     : { *(.sdata) }
   _edata  =  .;
   PROVIDE (edata = .);
+
   __bss_start = .;
   _fbss = .;
   .bss       :
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- v2.1.100/linux/arch/mips/lib/Makefile	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/lib/Makefile	Fri May  8 00:13:24 1998
@@ -1,11 +1,7 @@
 #
 # Makefile for MIPS-specific library files..
 #
-# Many of these routines are just left over debugging trash of ancient
-# times when I just make my Tyne beep and so ...
-#
-# ...and for when I need to get the DECStation to use the boot prom to
-# do things... Paul M. Antoine.
+# $Id: Makefile,v 1.7 1998/05/04 09:18:03 ralf Exp $
 #
 
 .S.s:
@@ -14,13 +10,12 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS	= beep.o checksum.o copy_user.o csum.o dump_tlb.o memset.o memcpy.o \
-          strlen_user.o strncpy_user.o tags.o watch.o
+L_OBJS	= csum_partial.o csum_partial_copy.o dump_tlb.o ide-std.c ide-no.o \
+	  memset.o memcpy.o strlen_user.o strncpy_user.o tags.o watch.o
 
-ifdef CONFIG_DECSTATION
-L_OBJS += pmaxcon.o pmaxio.o
-else
+#
+# Debug console, works without other support from the kernel
+#
 L_OBJS += tinycon.o
-endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/checksum.c linux/arch/mips/lib/checksum.c
--- v2.1.100/linux/arch/mips/lib/checksum.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/lib/checksum.c	Wed Dec 31 16:00:00 1969
@@ -1,131 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		MIPS specific IP/TCP/UDP checksumming routines
- *
- * Authors:	Ralf Baechle, <ralf@gnu.ai.mit.edu>
- *		Lots of code moved from tcp.c and ip.c; see those files
- *		for more names.
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
- *
- * $Id: checksum.c,v 1.2 1997/07/29 18:37:35 ralf Exp $
- */
-#include <net/checksum.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-static inline unsigned short from32to16(unsigned long x)
-{
-	/* 32 bits --> 16 bits + carry */
-	x = (x & 0xffff) + (x >> 16);
-	/* 16 bits + carry --> 16 bits including carry */
-	x = (x & 0xffff) + (x >> 16);
-	return x;
-}
-
-static inline unsigned long do_csum(const unsigned char * buff, int len)
-{
-	int odd, count;
-	unsigned long result = 0;
-
-	if (len <= 0)
-		goto out;
-	odd = 1 & (unsigned long) buff;
-	if (odd) {
-		result = be16_to_cpu(*buff);
-		len--;
-		buff++;
-	}
-	count = len >> 1;		/* nr of 16-bit words.. */
-	if (count) {
-		if (2 & (unsigned long) buff) {
-			result += *(unsigned short *) buff;
-			count--;
-			len -= 2;
-			buff += 2;
-		}
-		count >>= 1;		/* nr of 32-bit words.. */
-		if (count) {
-		        unsigned long carry = 0;
-			do {
-				unsigned long w = *(unsigned long *) buff;
-				count--;
-				buff += 4;
-				result += carry;
-				result += w;
-				carry = (w > result);
-			} while (count);
-			result += carry;
-			result = (result & 0xffff) + (result >> 16);
-		}
-		if (len & 2) {
-			result += *(unsigned short *) buff;
-			buff += 2;
-		}
-	}
-	if (len & 1)
-		result += le16_to_cpu(*buff);
-	result = from32to16(result);
-	if (odd)
-		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
-out:
-	return result;
-}
-
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum)
-{
-	unsigned long result = do_csum(buff, len);
-
-	/* add in old sum, and carry.. */
-	result += sum;
-	if(sum > result)
-		result += 1;
-	return result;
-}
-
-/*
- * copy while checksumming, otherwise like csum_partial
- */
-unsigned int csum_partial_copy(const char *src, char *dst, 
-                               int len, unsigned int sum)
-{
-	/*
-	 * It's 2:30 am and I don't feel like doing it real ...
-	 * This is lots slower than the real thing (tm)
-	 */
-	sum = csum_partial(src, len, sum);
-	memcpy(dst, src, len);
-
-	return sum;
-}
-
-/*
- * Copy from userspace and compute checksum.  If we catch an exception
- * then zero the rest of the buffer.
- */
-unsigned int csum_partial_copy_from_user (const char *src, char *dst,
-                                          int len, unsigned int sum,
-                                          int *err_ptr)
-{
-        int *dst_err_ptr=NULL;
-	int missing;
-
-	missing = copy_from_user(dst, src, len);
-	if (missing) {
-		memset(dst + len - missing, 0, missing);
-		*err_ptr = -EFAULT;
-	}
-		
-	return csum_partial(dst, len, sum);
-}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/copy_user.S linux/arch/mips/lib/copy_user.S
--- v2.1.100/linux/arch/mips/lib/copy_user.S	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/lib/copy_user.S	Wed Dec 31 16:00:00 1969
@@ -1,201 +0,0 @@
-/*
- * arch/mips/lib/copy_user.S
- *
- * 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 by Ralf Baechle
- *
- * Less stupid user_copy implementation for 32 bit MIPS CPUs.
- *
- * $Id: copy_user.S,v 1.2 1997/08/11 04:26:12 ralf Exp $
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-
-#define BLOCK_SIZE	16
-
-#define EX(addr,handler)                        \
-		.section	__ex_table,"a"; \
-		PTR		addr, handler;  \
-		.previous
-#define UEX(addr,handler)                       \
-		EX(addr,handler);               \
-		EX(addr+4,handler)
-
-		.set		noreorder
-		.set		noat
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * Bad.  We can't fix the alignment for both address parts.
- * Align the source address and copy slowly ...
- */
-not_even_the_same_alignment:
-		LONG_SUBU	v1,zero,a1
-		andi		v1,3
-		sltu		t0,v0,v1
-		MOVN(v1,v0,t0)
-		beqz		v1,src_aligned
-		 LONG_ADDU	v1,a0
-1:		lb		$1,(a1)
-		EX(1b, fault)
-		LONG_ADDIU	a1,1
-2:		sb		$1,(a0)
-		EX(2b, fault)
-		LONG_ADDIU	a0,1
-		bne		a0,v1,1b
-		 LONG_SUBU	v0,1
-src_aligned:
-
-/*
- * Ok.  We've fixed the alignment of the copy src for this case.
- * Now let's copy in the usual BLOCK_SIZE byte blocks using unaligned
- * stores.
- * XXX Align the destination address.  This is better if the __copy_user
- *     encounters an access fault because we never have to deal with an
- *     only partially modified destination word.  This is required to
- *     keep the semantics of the result of copy_*_user().
- */
-		ori		v1,v0,BLOCK_SIZE-1
-		xori		v1,BLOCK_SIZE-1
-		beqz		v1,copy_left_over
-		 nop
-		LONG_SUBU	v0,v1
-		LONG_ADDU	v1,a0
-
-1:		lw		t0,(a1)		# Can cause tlb fault
-		EX(1b, fault)
-2:		lw		t1,4(a1)	# Can cause tlb fault
-		EX(2b, fault)
-2:		lw		t2,8(a1)	# Can cause tlb fault
-		EX(2b, fault)
-2:		lw		t3,12(a1)	# Can cause tlb fault
-		EX(2b, fault)
-2:		usw		t0,(a0)		# Can cause tlb faults
-		UEX(2b, fault)
-2:		usw		t1,4(a0)	# Can cause tlb faults
-		UEX(2b, fault_plus_4)
-2:		usw		t2,8(a0)	# Can cause tlb faults
-		UEX(2b, fault_plus_8)
-2:		usw		t3,12(a0)	# Can cause tlb faults
-		UEX(2b, fault_plus_12)
-		LONG_ADDIU	a0,BLOCK_SIZE
-		bne		a0,v1,1b
-		 LONG_ADDIU	a1,BLOCK_SIZE
-9:
-		b		copy_left_over	# < BLOCK_SIZE bytes left
-		 nop
-
-/* ---------------------------------------------------------------------- */
-
-not_w_aligned:
-/*
- * Ok, src or destination are not 4-byte aligned.
- * Try to fix that.  Do at least both addresses have the same alignment?
- */
-		xor		t0,a0,a1
-		andi		t0,3
-		bnez		t0,not_even_the_same_alignment
-		nop					# delay slot
-
-/*
- * Ok, we can fix the alignment for both operands and go back to the
- * fast path.  We have to copy at least one byte, on average 3 bytes
- * bytewise.
- */
-		LONG_SUBU	v1,zero,a0
-		andi		v1,3
-		sltu		t0,v0,v1
-		MOVN(v1,v0,t0)
-		beqz		v1,__copy_user
-		 LONG_ADDU	v1,a0
-1:		lb		$1,(a1)
-		EX(1b, fault)
-		LONG_ADDIU	a1,1
-2:		sb		$1,(a0)
-		EX(2b, fault)
-		LONG_ADDIU	a0,1
-		bne		a0,v1,1b
-		 LONG_SUBU	v0,1
-		b		align4
-		 nop
-
-/* ---------------------------------------------------------------------- */
-
-LEAF(__copy_user)
-		or		t1,a0,a1
-		andi		t1,3
-		bnez		t1,not_w_aligned	# not word alignment
-		 move		v0,a2
-
-align4:
-		ori		v1,v0,BLOCK_SIZE-1
-		xori		v1,BLOCK_SIZE-1
-		beqz		v1,copy_left_over
-		 nop
-		LONG_SUBU	v0,v1
-		LONG_ADDU	v1,a0
-
-1:		lw		t0,(a1)		# Can cause tlb fault
-		EX(1b, fault)
-2:		lw		t1,4(a1)	# Can cause tlb fault
-		EX(2b, fault)
-2:		lw		t2,8(a1)	# Can cause tlb fault
-		EX(2b, fault)
-2:		lw		t3,12(a1)	# Can cause tlb fault
-		EX(2b, fault)
-2:		sw		t0,(a0)		# Can cause tlb fault
-		EX(2b, fault)
-2:		sw		t1,4(a0)	# Can cause tlb fault
-		EX(2b, fault_plus_4)
-2:		sw		t2,8(a0)	# Can cause tlb fault
-		EX(2b, fault_plus_8)
-2:		sw		t3,12(a0)	# Can cause tlb fault
-		EX(2b, fault_plus_12)
-		LONG_ADDIU	a0,BLOCK_SIZE
-		bne		a0,v1,1b
-		 LONG_ADDIU	a1,BLOCK_SIZE
-9:
-
-/*
- * XXX Tune me ...
- */
-copy_left_over:
-		beqz		v0,3f
-		 nop
-1:		lb		$1,(a1)
-		EX(1b, fault)
-		LONG_ADDIU	a1,1
-2:		sb		$1,(a0)
-		EX(2b, fault)
-		LONG_SUBU	v0,1
-		bnez		v0,1b
-		 LONG_ADDIU	a0,1
-3:
-
-done:		jr		ra
-		 nop
-
-		END(__copy_user)
-		.set		at
-		.set		reorder
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * Access fault.  The number of not copied bytes is in v0.  We have to
- * correct the number of the not copied bytes in v0 in case of a access
- * fault in an unrolled loop, then return.
- */
-
-fault:			jr	ra
-fault_plus_4:		LONG_ADDIU	v0,4
-			jr	ra
-fault_plus_8:		LONG_ADDIU	v0,8
-			jr	ra
-fault_plus_12:		LONG_ADDIU	v0,12
-			jr	ra
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/csum_partial.S linux/arch/mips/lib/csum_partial.S
--- v2.1.100/linux/arch/mips/lib/csum_partial.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/csum_partial.S	Fri May  8 00:13:24 1998
@@ -0,0 +1,242 @@
+/*
+ * 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 Ralf Baechle
+ *
+ * $Id: csum_partial.S,v 1.1 1998/05/04 09:18:08 ralf Exp $
+ */
+#include <sys/asm.h>
+#include <sys/regdef.h>
+
+#define ADDC(sum,reg)			\
+	addu	sum, reg;		\
+	sltu	v1, sum, reg;		\
+	addu	sum, v1
+
+#define CSUM_BIGCHUNK(src, offset, sum, t0, t1, t2, t3) \
+	lw	t0, (offset + 0x00)(src); \
+	lw	t1, (offset + 0x04)(src); \
+	lw	t2, (offset + 0x08)(src); \
+	lw	t3, (offset + 0x0c)(src); \
+	ADDC(sum, t0);                    \
+	ADDC(sum, t1);                    \
+	ADDC(sum, t2);                    \
+	ADDC(sum, t3);                    \
+	lw	t0, (offset + 0x10)(src); \
+	lw	t1, (offset + 0x14)(src); \
+	lw	t2, (offset + 0x18)(src); \
+	lw	t3, (offset + 0x1c)(src); \
+	ADDC(sum, t0);                    \
+	ADDC(sum, t1);                    \
+	ADDC(sum, t2);                    \
+	ADDC(sum, t3);                    \
+
+/*
+ * a0: source address
+ * a1: length of the area to checksum
+ * a2: partial checksum
+ */
+
+#define src a0
+#define dest a1
+#define sum v0
+
+	.text
+	.set	noreorder
+
+/* unknown src alignment and < 8 bytes to go  */
+small_csumcpy:
+	move	a1, t2
+
+	andi	t0, a1, 4
+	beqz	t0, 1f
+	 andi	t0, a1, 2
+
+	/* Still a full word to go  */
+	ulw	t1, (src)
+	addiu	src, 4
+	ADDC(sum, t1)
+
+1:	move	t1, zero
+	beqz	t0, 1f
+	 andi	t0, a1, 1
+
+	/* Still a halfword to go  */
+	ulhu	t1, (src)
+	addiu	src, 2
+
+1:	beqz	t0, 1f
+	 sll	t1, t1, 16
+
+	lbu	t2, (src)
+	 nop
+
+#ifdef __MIPSEB__
+	sll	t2, t2, 8
+#endif
+	or	t1, t2
+
+1:	ADDC(sum, t1)
+
+	/* fold checksum */
+	sll	v1, sum, 16
+	addu	sum, v1
+	sltu	v1, sum, v1
+	srl	sum, sum, 16
+	addu	sum, v1
+
+	/* odd buffer alignment? */
+	beqz	t7, 1f
+	 nop
+	sll	v1, sum, 8
+	srl	sum, sum, 8
+	or	sum, v1
+	andi	sum, 0xffff
+1:
+	.set	reorder
+	/* Add the passed partial csum.  */
+	ADDC(sum, a2)
+	jr	ra
+	.set	noreorder
+
+/* ------------------------------------------------------------------------- */
+
+	.align	5
+LEAF(csum_partial)
+	move sum, zero
+	move t7, zero
+
+	sltiu	t8, a1, 0x8
+	bnez	t8, small_csumcpy		/* < 8 bytes to copy */
+	 move	t2, a1
+
+	beqz	a1, out
+	 andi	t7, src, 0x1			/* odd buffer? */
+
+hword_align:
+	beqz	t7, word_align
+	 andi	t8, src, 0x2
+
+	lbu	t0, (src)
+	subu	a1, a1, 0x1
+#ifdef __MIPSEL__
+	sll	t0, t0, 8
+#endif
+	ADDC(sum, t0)
+	addu	src, src, 0x1
+	andi	t8, src, 0x2
+
+word_align:
+	beqz	t8, dword_align
+	 sltiu	t8, a1, 56
+
+	lhu	t0, (src)
+	subu	a1, a1, 0x2
+	ADDC(sum, t0)
+	sltiu	t8, a1, 56
+	addu	src, src, 0x2
+
+dword_align:
+	bnez	t8, do_end_words
+	 move	t8, a1
+
+	andi	t8, src, 0x4
+	beqz	t8, qword_align
+	 andi	t8, src, 0x8
+
+	lw	t0, 0x00(src)
+	subu	a1, a1, 0x4
+	ADDC(sum, t0)
+	addu	src, src, 0x4
+	andi	t8, src, 0x8
+
+qword_align:
+	beqz	t8, oword_align
+	 andi	t8, src, 0x10
+
+	lw	t0, 0x00(src)
+	lw	t1, 0x04(src)
+	subu	a1, a1, 0x8
+	ADDC(sum, t0)
+	ADDC(sum, t1)
+	addu	src, src, 0x8
+	andi	t8, src, 0x10
+
+oword_align:
+	beqz	t8, begin_movement
+	 srl	t8, a1, 0x7
+
+	lw	t3, 0x08(src)
+	lw	t4, 0x0c(src)
+	lw	t0, 0x00(src)
+	lw	t1, 0x04(src)
+	ADDC(sum, t3)
+	ADDC(sum, t4)
+	ADDC(sum, t0)
+	ADDC(sum, t1)
+	subu	a1, a1, 0x10
+	addu	src, src, 0x10
+	srl	t8, a1, 0x7
+
+begin_movement:
+	beqz	t8, 1f
+	 andi	t2, a1, 0x40
+
+move_128bytes:
+	CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, 0x40, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, 0x60, sum, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	bnez	t8, move_128bytes
+	 addu	src, src, 0x80
+
+1:
+	beqz	t2, 1f
+	 andi	t2, a1, 0x20
+
+move_64bytes:
+	CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, 0x20, sum, t0, t1, t3, t4)
+	addu	src, src, 0x40
+
+1:
+	beqz	t2, do_end_words
+	 andi	t8, a1, 0x1c
+
+move_32bytes:
+	CSUM_BIGCHUNK(src, 0x00, sum, t0, t1, t3, t4)
+	andi	t8, a1, 0x1c
+	addu	src, src, 0x20
+
+do_end_words:
+	beqz	t8, maybe_end_cruft
+	 srl	t8, t8, 0x2
+
+end_words:
+	lw	t0, (src)
+	subu	t8, t8, 0x1
+	ADDC(sum, t0)
+	bnez	t8, end_words
+	 addu	src, src, 0x4
+
+maybe_end_cruft:
+	andi	t2, a1, 0x3
+
+small_memcpy:
+ j small_csumcpy; move a1, t2
+	beqz	t2, out
+	 move	a1, t2
+
+end_bytes:
+	lb	t0, (src)
+	subu	a1, a1, 0x1
+	bnez	a2, end_bytes
+	 addu	src, src, 0x1
+
+out:
+	jr	ra
+	 move	v0, sum
+	END(csum_partial)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/csum_partial_copy.S linux/arch/mips/lib/csum_partial_copy.S
--- v2.1.100/linux/arch/mips/lib/csum_partial_copy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/csum_partial_copy.S	Fri May  8 00:13:24 1998
@@ -0,0 +1,518 @@
+/*
+ * 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 Ralf Baechle
+ *
+ * $Id: csum_partial_copy.S,v 1.1 1998/05/04 09:18:11 ralf Exp $
+ *
+ * Unified implementation of csum_copy_partial and csum_copy_partial_from_user.
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+/*
+ * The fixup routine for csum_partial_copy_from_user depends on copying
+ * strictly in increasing order.  Gas expands ulw/usw macros in the wrong order
+ * for little endian machines, so we cannot depend on them.
+ */
+#ifdef __MIPSEB__
+#define ulwL	lwl
+#define ulwU	lwr
+#endif
+#ifdef __MIPSEL__
+#define ulwL	lwr
+#define ulwU	lwl
+#endif
+
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a"; 			\
+	PTR	9b, handler; 				\
+	.previous
+
+#define UEX(insn,reg,addr,handler)			\
+9:	insn ## L reg, addr;				\
+10:	insn ## U reg, 3 + addr;			\
+	.section __ex_table,"a"; 			\
+	PTR	9b, handler; 				\
+	PTR	10b, handler; 				\
+	.previous
+
+#define ADDC(sum,reg)					\
+	addu	sum, reg;				\
+	sltu	v1, sum, reg;				\
+	addu	sum, v1
+
+/* ascending order, destination aligned  */
+#define CSUM_BIGCHUNK(src, dst, offset, sum, t0, t1, t2, t3) \
+	EX(lw, t0, (offset + 0x00)(src), l_fixup);	\
+	EX(lw, t1, (offset + 0x04)(src), l_fixup);	\
+	EX(lw, t2, (offset + 0x08)(src), l_fixup);	\
+	EX(lw, t3, (offset + 0x0c)(src), l_fixup);	\
+	ADDC(sum, t0);					\
+	ADDC(sum, t1);					\
+	ADDC(sum, t2);					\
+	ADDC(sum, t3);					\
+	sw	t0, (offset + 0x00)(dst);		\
+	sw	t1, (offset + 0x04)(dst);		\
+	sw	t2, (offset + 0x08)(dst);		\
+	sw	t3, (offset + 0x0c)(dst);		\
+	EX(lw, t0, (offset + 0x10)(src), l_fixup);	\
+	EX(lw, t1, (offset + 0x14)(src), l_fixup);	\
+	EX(lw, t2, (offset + 0x18)(src), l_fixup);	\
+	EX(lw, t3, (offset + 0x1c)(src), l_fixup);	\
+	ADDC(sum, t0);					\
+	ADDC(sum, t1);					\
+	ADDC(sum, t2);					\
+	ADDC(sum, t3);					\
+	sw	t0, (offset + 0x10)(dst);		\
+	sw	t1, (offset + 0x14)(dst);		\
+	sw	t2, (offset + 0x18)(dst);		\
+	sw	t3, (offset + 0x1c)(dst)
+
+/* ascending order, destination unaligned  */
+#define UCSUM_BIGCHUNK(src, dst, offset, sum, t0, t1, t2, t3) \
+	EX(lw, t0, (offset + 0x00)(src), l_fixup);	\
+	EX(lw, t1, (offset + 0x04)(src), l_fixup);	\
+	EX(lw, t2, (offset + 0x08)(src), l_fixup);	\
+	EX(lw, t3, (offset + 0x0c)(src), l_fixup);	\
+	ADDC(sum, t0);					\
+	ADDC(sum, t1);					\
+	ADDC(sum, t2);					\
+	ADDC(sum, t3);					\
+	usw	t0, (offset + 0x00)(dst);		\
+	usw	t1, (offset + 0x04)(dst);		\
+	usw	t2, (offset + 0x08)(dst);		\
+	usw	t3, (offset + 0x0c)(dst);		\
+	EX(lw, t0, (offset + 0x00)(src), l_fixup);	\
+	EX(lw, t1, (offset + 0x04)(src), l_fixup);	\
+	EX(lw, t2, (offset + 0x08)(src), l_fixup);	\
+	EX(lw, t3, (offset + 0x0c)(src), l_fixup);	\
+	ADDC(sum, t0);					\
+	ADDC(sum, t1);					\
+	ADDC(sum, t2);					\
+	ADDC(sum, t3);					\
+	usw	t0, (offset + 0x10)(dst);		\
+	usw	t1, (offset + 0x14)(dst);		\
+	usw	t2, (offset + 0x18)(dst);		\
+	usw	t3, (offset + 0x1c)(dst)
+
+#
+# a0: source address
+# a1: destination address
+# a2: length of the area to checksum
+# a3: partial checksum
+#
+
+#define src a0
+#define dest a1
+#define sum v0
+
+	.text
+	.set	noreorder
+
+/* unknown src/dst alignment and < 8 bytes to go  */
+small_csumcpy:
+	move	a2, t2
+
+	andi	t0, a2, 4
+	beqz	t0, 1f
+	 andi	t0, a2, 2
+
+	/* Still a full word to go  */
+	UEX(ulw, t1, 0(src), l_fixup)
+	addiu	src, 4
+	usw	t1, 0(dest)
+	addiu	dest, 4
+	ADDC(sum, t1)
+
+1:	move	t1, zero
+	beqz	t0, 1f
+	 andi	t0, a2, 1
+
+	/* Still a halfword to go  */
+	ulhu	t1, (src)
+	addiu	src, 2
+	ush	t1, (dest)
+	addiu	dest, 2
+
+1:	beqz	t0, 1f
+	 sll	t1, t1, 16
+
+	lbu	t2, (src)
+	 nop
+	sb	t2, (dest)
+
+#ifdef __MIPSEB__
+	sll	t2, t2, 8
+#endif
+	or	t1, t2
+
+1:	ADDC(sum, t1)
+
+	/* fold checksum */
+	sll	v1, sum, 16
+	addu	sum, v1
+	sltu	v1, sum, v1
+	srl	sum, sum, 16
+	addu	sum, v1
+
+	/* odd buffer alignment? */
+	beqz	t7, 1f
+	 nop
+	sll	v1, sum, 8
+	srl	sum, sum, 8
+	or	sum, v1
+	andi	sum, 0xffff
+1:
+	.set	reorder
+	/* Add the passed partial csum.  */
+	ADDC(sum, a3)
+	jr	ra
+	.set	noreorder
+
+/* ------------------------------------------------------------------------- */
+
+	.align	5
+LEAF(csum_partial_copy_from_user)
+	addu	t5, src, a2			# end address for fixup
+EXPORT(csum_partial_copy)
+	move	sum, zero			# clear computed sum
+	move	t7, zero			# clear odd flag
+	xor	t0, dest, src
+	andi	t0, t0, 0x3
+	beqz	t0, can_align
+	 sltiu	t8, a2, 0x8
+
+	b	memcpy_u_src			# bad alignment
+	 move	t2, a2
+
+can_align:
+	bnez	t8, small_csumcpy		# < 8 bytes to copy
+	 move	t2, a2
+
+	beqz	a2, out
+	 andi	t7, src, 0x1			# odd buffer?
+
+hword_align:
+	beqz	t7, word_align
+	 andi	t8, src, 0x2
+
+	EX(lbu, t0, (src), l_fixup)
+	subu	a2, a2, 0x1
+	EX(sb, t0, (dest), l_fixup)
+#ifdef __MIPSEL__
+	sll	t0, t0, 8
+#endif
+	ADDC(sum, t0)
+	addu	src, src, 0x1
+	addu	dest, dest, 0x1
+	andi	t8, src, 0x2
+
+word_align:
+	beqz	t8, dword_align
+	 sltiu	t8, a2, 56
+
+	EX(lhu, t0, (src), l_fixup)
+	subu	a2, a2, 0x2
+	sh	t0, (dest)
+	ADDC(sum, t0)
+	sltiu	t8, a2, 56
+	addu	dest, dest, 0x2
+	addu	src, src, 0x2
+
+dword_align:
+	bnez	t8, do_end_words
+	 move	t8, a2
+
+	andi	t8, src, 0x4
+	beqz	t8, qword_align
+	 andi	t8, src, 0x8
+
+	EX(lw, t0, 0x00(src), l_fixup)
+	subu	a2, a2, 0x4
+	ADDC(sum, t0)
+	sw	t0, 0x00(dest)
+	addu	src, src, 0x4
+	addu	dest, dest, 0x4
+	andi	t8, src, 0x8
+
+qword_align:
+	beqz	t8, oword_align
+	 andi	t8, src, 0x10
+
+	EX(lw, t0, 0x00(src), l_fixup)
+	EX(lw, t1, 0x04(src), l_fixup)
+	subu	a2, a2, 0x8
+	ADDC(sum, t0)
+	ADDC(sum, t1)
+	sw	t0, 0x00(dest)
+	addu	src, src, 0x8
+	sw	t1, 0x04(dest)
+	andi	t8, src, 0x10
+	addu	dest, dest, 0x8
+
+oword_align:
+	beqz	t8, begin_movement
+	 srl	t8, a2, 0x7
+
+	EX(lw, t3, 0x08(src), l_fixup)		# assumes subblock ordering
+	EX(lw, t4, 0x0c(src), l_fixup)
+	EX(lw, t0, 0x00(src), l_fixup)
+	EX(lw, t1, 0x04(src), l_fixup)
+	ADDC(sum, t3)
+	ADDC(sum, t4)
+	ADDC(sum, t0)
+	ADDC(sum, t1)
+	sw	t3, 0x08(dest)
+	subu	a2, a2, 0x10
+	sw	t4, 0x0c(dest)
+	addu	src, src, 0x10
+	sw	t0, 0x00(dest)
+	srl	t8, a2, 0x7
+	addu	dest, dest, 0x10
+	sw	t1, -0x0c(dest)
+
+begin_movement:
+	beqz	t8, 0f
+	 andi	t2, a2, 0x40
+
+move_128bytes:
+	CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, dest, 0x40, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, dest, 0x60, sum, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	addu	src, src, 0x80
+	bnez	t8, move_128bytes
+	 addu	dest, dest, 0x80
+
+0:
+	beqz	t2, 1f
+	 andi	t2, a2, 0x20
+
+move_64bytes:
+	CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
+	CSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
+	addu	src, src, 0x40
+	addu	dest, dest, 0x40
+
+1:
+	beqz	t2, do_end_words
+	 andi	t8, a2, 0x1c
+
+move_32bytes:
+	CSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
+	andi	t8, a2, 0x1c
+	addu	src, src, 0x20
+	addu	dest, dest, 0x20
+
+do_end_words:
+	beqz	t8, maybe_end_cruft
+	 srl	t8, t8, 0x2
+
+end_words:
+	EX(lw, t0, (src), l_fixup)
+	subu	t8, t8, 0x1
+	ADDC(sum, t0)
+	sw	t0, (dest)
+	addu	src, src, 0x4
+	bnez	t8, end_words
+	 addu	dest, dest, 0x4
+
+maybe_end_cruft:
+	andi	t2, a2, 0x3
+
+small_memcpy:
+ j small_csumcpy; move a2, t2
+	beqz	t2, out
+	 move	a2, t2
+
+end_bytes:
+	EX(lb, t0, (src), l_fixup)
+	subu	a2, a2, 0x1
+	sb	t0, (dest)
+	addu	src, src, 0x1
+	bnez	a2, end_bytes
+	 addu	dest, dest, 0x1
+
+out:
+	jr	ra
+	 move	v0, sum
+
+/* ------------------------------------------------------------------------- */
+
+/* Bad, bad.  At least try to align the source  */
+
+memcpy_u_src:
+	bnez	t8, small_memcpy		# < 8 bytes?
+	 move	t2, a2
+
+	beqz	a2, out
+	 andi	t7, src, 0x1			# odd alignment?
+
+u_hword_align:
+	beqz	t7, u_word_align
+	 andi	t8, src, 0x2
+
+	EX(lbu, t0, (src), l_fixup)
+	subu	a2, a2, 0x1
+	sb	t0, (dest)
+#ifdef __MIPSEL__
+	sll	t0, t0, 8
+#endif
+	ADDC(sum, t0)
+	addu	src, src, 0x1
+	addu	dest, dest, 0x1
+	andi	t8, src, 0x2
+
+u_word_align:
+	beqz	t8, u_dword_align
+	 sltiu	t8, a2, 56
+
+	EX(lhu, t0, (src), l_fixup)
+	subu	a2, a2, 0x2
+	ush	t0, (dest)
+	ADDC(sum, t0)
+	sltiu	t8, a2, 56
+	addu	dest, dest, 0x2
+	addu	src, src, 0x2
+
+u_dword_align:
+	bnez	t8, u_do_end_words
+	 move	t8, a2
+
+	andi	t8, src, 0x4
+	beqz	t8, u_qword_align
+	 andi	t8, src, 0x8
+
+	EX(lw, t0, 0x00(src), l_fixup)
+	subu	a2, a2, 0x4
+	ADDC(sum, t0)
+	usw	t0, 0x00(dest)
+	addu	src, src, 0x4
+	addu	dest, dest, 0x4
+	andi	t8, src, 0x8
+
+u_qword_align:
+	beqz	t8, u_oword_align
+	 andi	t8, src, 0x10
+
+	EX(lw, t0, 0x00(src), l_fixup)
+	EX(lw, t1, 0x04(src), l_fixup)
+	subu	a2, a2, 0x8
+	ADDC(sum, t0)
+	ADDC(sum, t1)
+	usw	t0, 0x00(dest)
+	addu	src, src, 0x8
+	usw	t1, 0x04(dest)
+	andi	t8, src, 0x10
+	addu	dest, dest, 0x8
+
+u_oword_align:
+	beqz	t8, u_begin_movement
+	 srl	t8, a2, 0x7
+
+	EX(lw, t3, 0x08(src), l_fixup)
+	EX(lw, t4, 0x0c(src), l_fixup)
+	EX(lw, t0, 0x00(src), l_fixup)
+	EX(lw, t1, 0x04(src), l_fixup)
+	ADDC(sum, t3)
+	ADDC(sum, t4)
+	ADDC(sum, t0)
+	ADDC(sum, t1)
+	usw	t3, 0x08(dest)
+	subu	a2, a2, 0x10
+	usw	t4, 0x0c(dest)
+	addu	src, src, 0x10
+	usw	t0, 0x00(dest)
+	srl	t8, a2, 0x7
+	addu	dest, dest, 0x10
+	usw	t1, -0x0c(dest)
+
+u_begin_movement:
+	beqz	t8, 0f
+	 andi	t2, a2, 0x40
+
+u_move_128bytes:
+	UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
+	UCSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
+	UCSUM_BIGCHUNK(src, dest, 0x40, sum, t0, t1, t3, t4)
+	UCSUM_BIGCHUNK(src, dest, 0x60, sum, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	addu	src, src, 0x80
+	bnez	t8, u_move_128bytes
+	 addu	dest, dest, 0x80
+
+0:
+	beqz	t2, 1f
+	 andi	t2, a2, 0x20
+
+u_move_64bytes:
+	UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
+	UCSUM_BIGCHUNK(src, dest, 0x20, sum, t0, t1, t3, t4)
+	addu	src, src, 0x40
+	addu	dest, dest, 0x40
+
+1:
+	beqz	t2, u_do_end_words
+	 andi	t8, a2, 0x1c
+
+u_move_32bytes:
+	UCSUM_BIGCHUNK(src, dest, 0x00, sum, t0, t1, t3, t4)
+	andi	t8, a2, 0x1c
+	addu	src, src, 0x20
+	addu	dest, dest, 0x20
+
+u_do_end_words:
+	beqz	t8, u_maybe_end_cruft
+	 srl	t8, t8, 0x2
+
+u_end_words:
+	EX(lw, t0, 0x00(src), l_fixup)
+	subu	t8, t8, 0x1
+	ADDC(sum, t0)
+	usw	t0, 0x00(dest)
+	addu	src, src, 0x4
+	bnez	t8, u_end_words
+	 addu	dest, dest, 0x4
+
+u_maybe_end_cruft:
+	andi	t2, a2, 0x3
+
+u_cannot_optimize:
+ j small_csumcpy; move a2, t2
+	beqz	t2, out
+	 move	a2, t2
+
+u_end_bytes:
+	EX(lb, t0, (src), l_fixup)
+	subu	a2, a2, 0x1
+	sb	t0, (dest)
+	addu	src, src, 0x1
+	bnez	a2, u_end_bytes
+	 addu	dest, dest, 0x1
+
+	jr	ra
+	 move	v0, sum
+	END(csum_partial_copy_from_user)
+
+l_fixup:
+	beqz	t7, 1f				# odd buffer alignment?
+	 nop
+	sll	v1, sum, 8			# swap bytes
+	srl	sum, sum, 8
+	or	sum, v1
+	andi	sum, 0xffff
+1:	ADDC(sum, a3)				# Add csum argument.
+
+	lw	t0, THREAD_BUADDR($28)		# clear the rest of the buffer
+	 nop
+	subu	t1, t0, src			# where to start clearing
+	addu	a0, dest, t1
+	move	a1, zero			# zero fill
+	j	__bzero
+	 subu	a2, t5, t0			# a2 = bad - srcend bytes to go
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/dump_tlb.c linux/arch/mips/lib/dump_tlb.c
--- v2.1.100/linux/arch/mips/lib/dump_tlb.c	Sat Aug 16 09:51:07 1997
+++ linux/arch/mips/lib/dump_tlb.c	Fri May  8 00:13:24 1998
@@ -20,17 +20,6 @@
 	"u", "s", "k", "!"
 };
 
-static char *cache_map [] = {
-	"c/nc/wt/nwa,",
-	"c/nc/wt/wa, ",
-	"uncached,   ",
-	"c/nc/wb,    "
-	"unknown,    ",
-	"unknown,    ",
-	"unknown,    ",
-	"unknown,    "
-};
-
 void
 dump_tlb(int first, int last)
 {
@@ -69,9 +58,9 @@
 			c0 = (entrylo0 >> 3) & 7;
 			c1 = (entrylo1 >> 3) & 7;
 
-			printk("%s vpn2=%08x "
-			       "[pfn=%06x c=%d d=%d v=%d g=%d]"
-			       "[pfn=%06x c=%d d=%d v=%d g=%d]",
+			printk("%s vpn2=%08Lx "
+			       "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]"
+			       "[pfn=%06Lx c=%d d=%d v=%d g=%Ld]",
 			       region_map [r], (entryhi >> 13) & 0xffffffff,
 			       (entrylo0 >> 6) & 0xffffff, c0,
 			       (entrylo0 & 4) ? 1 : 0,
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c
--- v2.1.100/linux/arch/mips/lib/ide-no.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/ide-no.c	Fri May  8 00:13:24 1998
@@ -0,0 +1,73 @@
+/*
+ * arch/mips/kernel/ide-none.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.
+ *
+ * Stub IDE routines to keep Linux from crashing on machine which don't
+ * have IDE like the Indy.
+ *
+ * Copyright (C) 1998 by Ralf Baechle
+ *
+ * $Id: ide-no.c,v 1.1 1998/05/04 09:18:13 ralf Exp $
+ */
+#include <linux/hdreg.h>
+#include <linux/kernel.h>
+#include <asm/ptrace.h>
+#include <asm/ide.h>
+
+static int no_ide_default_irq(ide_ioreg_t base)
+{
+	return 0;
+}
+
+static ide_ioreg_t no_ide_default_io_base(int index)
+{
+	return 0;
+}
+
+static void no_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
+                                     int *irq)
+{
+}
+
+static int no_ide_request_irq(unsigned int irq,
+                                void (*handler)(int,void *, struct pt_regs *),
+                                unsigned long flags, const char *device,
+                                void *dev_id)
+{
+	panic("no_no_ide_request_irq called - shouldn't happen");
+}			
+
+static void no_ide_free_irq(unsigned int irq, void *dev_id)
+{
+	panic("no_ide_free_irq called - shouldn't happen");
+}
+
+static int no_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+	panic("no_ide_check_region called - shouldn't happen");
+}
+
+static void no_ide_request_region(ide_ioreg_t from, unsigned int extent,
+                                    const char *name)
+{
+	panic("no_ide_request_region called - shouldn't happen");
+}
+
+static void no_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+	panic("no_ide_release_region called - shouldn't happen");
+}
+
+struct ide_ops no_ide_ops = {
+	&no_ide_default_irq,
+	&no_ide_default_io_base,
+	&no_ide_init_hwif_ports,
+	&no_ide_request_irq,
+	&no_ide_free_irq,
+	&no_ide_check_region,
+	&no_ide_request_region,
+	&no_ide_release_region
+};
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c
--- v2.1.100/linux/arch/mips/lib/ide-std.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/ide-std.c	Fri May  8 00:13:24 1998
@@ -0,0 +1,91 @@
+/*
+ * include/asm-mips/types.h
+ *
+ * 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.
+ *
+ * IDE routines for typical pc-like standard configurations.
+ *
+ * Copyright (C) 1998 by Ralf Baechle
+ */
+#include <linux/hdreg.h>
+#include <asm/ptrace.h>
+#include <asm/ide.h>
+
+static int std_ide_default_irq(ide_ioreg_t base)
+{
+	switch (base) {
+		case 0x1f0: return 14;
+		case 0x170: return 15;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		default:
+			return 0;
+	}
+}
+
+static ide_ioreg_t std_ide_default_io_base(int index)
+{
+	switch (index) {
+		case 0:	return 0x1f0;
+		case 1:	return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		default:
+			return 0;
+	}
+}
+
+static void std_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
+                                     int *irq)
+{
+	ide_ioreg_t port = base;
+	int i = 8;
+
+	while (i--)
+		*p++ = port++;
+	*p++ = base + 0x206;
+	if (irq != NULL)
+		*irq = 0;
+}
+
+static int std_ide_request_irq(unsigned int irq,
+                                void (*handler)(int,void *, struct pt_regs *),
+                                unsigned long flags, const char *device,
+                                void *dev_id)
+{
+	return request_irq(irq, handler, flags, device, dev_id);
+}			
+
+static void std_ide_free_irq(unsigned int irq, void *dev_id)
+{
+	free_irq(irq, dev_id);
+}
+
+static int std_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+	return check_region(from, extent);
+}
+
+static void std_ide_request_region(ide_ioreg_t from, unsigned int extent,
+                                    const char *name)
+{
+	request_region(from, extent, name);
+}
+
+static void std_ide_release_region(ide_ioreg_t from, unsigned int extent)
+{
+	release_region(from, extent);
+}
+
+struct ide_ops std_ide_ops = {
+	&std_ide_default_irq,
+	&std_ide_default_io_base,
+	&std_ide_init_hwif_ports,
+	&std_ide_request_irq,
+	&std_ide_free_irq,
+	&std_ide_check_region,
+	&std_ide_request_region,
+	&std_ide_release_region
+};
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S
--- v2.1.100/linux/arch/mips/lib/memcpy.S	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/lib/memcpy.S	Fri May  8 00:13:24 1998
@@ -1,221 +1,701 @@
-/* memcpy.S: Mips optimized memcpy based upon SparcLinux code.
+/*
+ * 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 Linus Torvalds
- *  Copyright(C) 1996 David S. Miller
- *  Copyright(C) 1996 Eddie C. Dost
+ * $Id: memcpy.S,v 1.2 1998/05/04 09:18:16 ralf Exp $
  *
- * derived from:
- *	e-mail between David and Eddie.
+ * Unified implementation of memcpy, memmove and the __copy_user backend.
+ * For __rmemcpy and memmove an exception is always a kernel bug, therefore
+ * they're not protected.  In order to keep the exception fixup routine
+ * simple all memory accesses in __copy_user to src rsp. dst are stricly
+ * incremental.  The fixup routine depends on $at not being changed.
  */
-
 #include <asm/asm.h>
+#include <asm/offset.h>
 #include <asm/regdef.h>
 
-#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5) \
-	lw	t0, (offset + 0x18)(src); \
-	lw	t1, (offset + 0x1c)(src); \
-	sw	t0, (offset + 0x18)(dst); \
-	lw	t2, (offset + 0x10)(src); \
-	sw	t1, (offset + 0x1c)(dst); \
-	lw	t3, (offset + 0x14)(src); \
-	sw	t2, (offset + 0x10)(dst); \
-	lw	t4, (offset + 0x08)(src); \
-	sw	t3, (offset + 0x14)(dst); \
-	lw	t5, (offset + 0x0c)(src); \
-	sw	t4, (offset + 0x08)(dst); \
-	lw	t0, (offset + 0x00)(src); \
-	sw	t5, (offset + 0x0c)(dst); \
-	lw	t1, (offset + 0x04)(src); \
-	sw	t0, (offset + 0x00)(dst); \
-	sw	t1, (offset + 0x04)(dst); \
-
-	/* Alignment cases are:
-	 * 1) (src&0x3)=0x0 (dst&0x3)=0x0 	can optimize
-	 * 2) (src&0x3)=0x1 (dst&0x3)=0x1	can optimize
-	 * 3) (src&0x3)=0x2 (dst&0x3)=0x2	can optimize
-	 * 4) (src&0x3)=0x3 (dst&0x3)=0x3	can optimize
-	 * 5) anything else			cannot optimize
-	 */
-
-	/* I hate MIPS register names... AIEEE, it's a SPARC! */
-#define o0 a0
-#define o1 a1
-#define o2 a2
-#define o3 a3
-#define o4 t0
-#define o5 t1
-#define o6 sp
-#define o7 ra
-#define g0 zero
-#define g1 t2
-#define g2 t3
-#define g3 t4
-#define g4 t5
-#define g5 t6
-#define g6 t7
-#define g7 t8
+/*
+ * The fixup routine for copy_to_user depends on copying strictly in
+ * increasing order.  Gas expands the ulw/usw macros in the wrong order for
+ * little endian machines, so we cannot depend on them.
+ */
+#ifdef __MIPSEB__
+#define uswL	swl
+#define uswU	swr
+#define ulwL	lwl
+#define ulwU	lwr
+#endif
+#ifdef __MIPSEL__
+#define uswL	swr
+#define uswU	swl
+#define ulwL	lwr
+#define ulwU	lwl
+#endif
+
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a"; 			\
+	PTR	9b, handler; 				\
+	.previous
+
+#define UEX(insn,reg,addr,handler)			\
+9:	insn ## L reg, addr;				\
+10:	insn ## U reg, 3 + addr;			\
+	.section __ex_table,"a"; 			\
+	PTR	9b, handler; 				\
+	PTR	10b, handler; 				\
+	.previous
+
+/* ascending order, destination aligned  */
+#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \
+	EX(lw, t0, (offset + 0x00)(src), l_fixup); \
+	EX(lw, t1, (offset + 0x04)(src), l_fixup); \
+	EX(lw, t2, (offset + 0x08)(src), l_fixup); \
+	EX(lw, t3, (offset + 0x0c)(src), l_fixup); \
+	EX(sw, t0, (offset + 0x00)(dst), s_fixup); \
+	EX(sw, t1, (offset + 0x04)(dst), s_fixup); \
+	EX(sw, t2, (offset + 0x08)(dst), s_fixup); \
+	EX(sw, t3, (offset + 0x0c)(dst), s_fixup); \
+	EX(lw, t0, (offset + 0x10)(src), l_fixup); \
+	EX(lw, t1, (offset + 0x14)(src), l_fixup); \
+	EX(lw, t2, (offset + 0x18)(src), l_fixup); \
+	EX(lw, t3, (offset + 0x1c)(src), l_fixup); \
+	EX(sw, t0, (offset + 0x10)(dst), s_fixup); \
+	EX(sw, t1, (offset + 0x14)(dst), s_fixup); \
+	EX(sw, t2, (offset + 0x18)(dst), s_fixup); \
+	EX(sw, t3, (offset + 0x1c)(dst), s_fixup)
+
+/* ascending order, destination unaligned  */
+#define UMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \
+	EX(lw, t0, (offset + 0x00)(src), l_fixup); \
+	EX(lw, t1, (offset + 0x04)(src), l_fixup); \
+	EX(lw, t2, (offset + 0x08)(src), l_fixup); \
+	EX(lw, t3, (offset + 0x0c)(src), l_fixup); \
+	UEX(usw, t0, (offset + 0x00)(dst), s_fixup); \
+	UEX(usw, t1, (offset + 0x04)(dst), s_fixup); \
+	UEX(usw, t2, (offset + 0x08)(dst), s_fixup); \
+	UEX(usw, t3, (offset + 0x0c)(dst), s_fixup); \
+	EX(lw, t0, (offset + 0x10)(src), l_fixup); \
+	EX(lw, t1, (offset + 0x14)(src), l_fixup); \
+	EX(lw, t2, (offset + 0x18)(src), l_fixup); \
+	EX(lw, t3, (offset + 0x1c)(src), l_fixup); \
+	UEX(usw, t0, (offset + 0x10)(dst), s_fixup); \
+	UEX(usw, t1, (offset + 0x14)(dst), s_fixup); \
+	UEX(usw, t2, (offset + 0x18)(dst), s_fixup); \
+	UEX(usw, t3, (offset + 0x1c)(dst), s_fixup)
 
 	.text
 	.set	noreorder
 	.set	noat
 
-	.globl	bcopy
-	.globl	amemmove
-	.globl	memmove
-	.globl	memcpy
-	.align	2
-bcopy:
-	move	o3, o0
-	move	o0, o1
-	move	o1, o3
-
-amemmove:
-memmove:
-memcpy:			/* o0=dst o1=src o2=len */
-	xor	o4, o0, o1
-	andi	o4, o4, 0x3
-	move	g6, o0
-	beq	o4, g0, can_align
-	 sltiu	g7, o2, 0x8
+	.align	5
+LEAF(memcpy)					/* a0=dst a1=src a2=len */
+	move	v0, a0				/* return value */
+__memcpy:
+EXPORT(__copy_user)
+	xor	t0, a0, a1
+	andi	t0, t0, 0x3
+	move	t7, a0
+	beqz	t0, can_align
+	 sltiu	t8, a2, 0x8
 
-	b	cannot_optimize
-	 move	g1, o2
+	b	memcpy_u_src			# bad alignment
+	 move	t2, a2
 
 can_align:
-	bne	g7, g0, cannot_optimize
-	 move	g1, o2
+	bnez	t8, small_memcpy		# < 8 bytes to copy
+	 move	t2, a2
 
-	beq	o2, g0, out
-	 andi	g7, o1, 0x1
+	beqz	a2, out
+	 andi	t8, a1, 0x1
 
 hword_align:
-	beq	g7, g0, word_align
-	 andi	g7, o1, 0x2
+	beqz	t8, word_align
+	 andi	t8, a1, 0x2
 
-	lbu	o4, 0x00(o1)
-	subu	o2, o2, 0x1
-	sb	o4, 0x00(o0)
-	addu	o1, o1, 0x1
-	addu	o0, o0, 0x1
-	andi	g7, o1, 0x2
+	EX(lb, t0, (a1), l_fixup)
+	subu	a2, a2, 0x1
+	EX(sb, t0, (a0), s_fixup)
+	addu	a1, a1, 0x1
+	addu	a0, a0, 0x1
+	andi	t8, a1, 0x2
 
 word_align:
-	beq	g7, g0, dword_align
-	 sltiu	g7, o2, 56
+	beqz	t8, dword_align
+	 sltiu	t8, a2, 56
 	
-	lhu	o4, 0x00(o1)
-	subu	o2, o2, 0x2
-	sh	o4, 0x00(o0)
-	sltiu	g7, o2, 56
-	addu	o0, o0, 0x2
-	addu	o1, o1, 0x2
+	EX(lh, t0, (a1), l_fixup)
+	subu	a2, a2, 0x2
+	EX(sh, t0, (a0), s_fixup)
+	sltiu	t8, a2, 56
+	addu	a0, a0, 0x2
+	addu	a1, a1, 0x2
 
 dword_align:
-	bne	g7, g0, do_end_words
-	 move	g7, o2
+	bnez	t8, do_end_words
+	 move	t8, a2
 
-	andi	g7, o1, 0x4
-	beq	g7, zero, qword_align
-	 andi	g7, o1, 0x8
-
-	lw	o4, 0x00(o1)
-	subu	o2, o2, 0x4
-	sw	o4, 0x00(o0)
-	addu	o1, o1, 0x4
-	addu	o0, o0, 0x4
-	andi	g7, o1, 0x8
+	andi	t8, a1, 0x4
+	beqz	t8, qword_align
+	 andi	t8, a1, 0x8
+
+	EX(lw, t0, 0x00(a1), l_fixup)
+	subu	a2, a2, 0x4
+	EX(sw, t0, 0x00(a0), s_fixup)
+	addu	a1, a1, 0x4
+	addu	a0, a0, 0x4
+	andi	t8, a1, 0x8
 
 qword_align:
-	beq	g7, g0, oword_align
-	 andi	g7, o1, 0x10
+	beqz	t8, oword_align
+	 andi	t8, a1, 0x10
 
-	lw	o4, 0x00(o1)
-	lw	o5, 0x04(o1)
-	subu	o2, o2, 0x8
-	sw	o4, 0x00(o0)
-	addu	o1, o1, 0x8
-	sw	o5, 0x04(o0)
-	andi	g7, o1, 0x10
-	addu	o0, o0, 0x8
+	EX(lw, t0, 0x00(a1), l_fixup)
+	EX(lw, t1, 0x04(a1), l_fixup)
+	subu	a2, a2, 0x8
+	EX(sw, t0, 0x00(a0), s_fixup)
+	EX(sw, t1, 0x04(a0), s_fixup)
+	addu	a1, a1, 0x8
+	andi	t8, a1, 0x10
+	addu	a0, a0, 0x8
 
 oword_align:
-	beq	g7, g0, begin_movement
-	 srl	g7, o2, 0x7
+	beqz	t8, begin_movement
+	 srl	t8, a2, 0x7
 
-	lw	g2, 0x08(o1)
-	lw	g3, 0x0c(o1)
-	lw	o4, 0x00(o1)
-	lw	o5, 0x04(o1)
-	sw	g2, 0x08(o0)
-	subu	o2, o2, 0x10
-	sw	g3, 0x0c(o0)
-	addu	o1, o1, 0x10
-	sw	o4, 0x00(o0)
-	srl	g7, o2, 0x7
-	addu	o0, o0, 0x10
-	sw	o5, -0x0c(o0)
+	EX(lw, t3, 0x00(a1), l_fixup)
+	EX(lw, t4, 0x04(a1), l_fixup)
+	EX(lw, t0, 0x08(a1), l_fixup)
+	EX(lw, t1, 0x0c(a1), l_fixup)
+	EX(sw, t3, 0x00(a0), s_fixup)
+	EX(sw, t4, 0x04(a0), s_fixup)
+	EX(sw, t0, 0x08(a0), s_fixup)
+	EX(sw, t1, 0x0c(a0), s_fixup)
+	subu	a2, a2, 0x10
+	addu	a1, a1, 0x10
+	srl	t8, a2, 0x7
+	addu	a0, a0, 0x10
 
 begin_movement:
-	beq	g7, g0, 0f
-	 andi	g1, o2, 0x40
+	beqz	t8, 0f
+	 andi	t2, a2, 0x40
 
 move_128bytes:
-	MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x40, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x60, o4, o5, g2, g3, g4, g5)
-	subu	g7, g7, 0x01
-	addu	o1, o1, 0x80
-	bne	g7, g0, move_128bytes
-	 addu	o0, o0, 0x80
+	MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	MOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4)
+	MOVE_BIGCHUNK(a1, a0, 0x40, t0, t1, t3, t4)
+	MOVE_BIGCHUNK(a1, a0, 0x60, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	addu	a1, a1, 0x80
+	bnez	t8, move_128bytes
+	 addu	a0, a0, 0x80
 
 0:
-	beq	g1, g0, 1f
-	 andi	g1, o2, 0x20
+	beqz	t2, 1f
+	 andi	t2, a2, 0x20
 
 move_64bytes:
-	MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5)
-	MOVE_BIGCHUNK(o1, o0, 0x20, o4, o5, g2, g3, g4, g5)
-	addu	o1, o1, 0x40
-	addu	o0, o0, 0x40
+	MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	MOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4)
+	addu	a1, a1, 0x40
+	addu	a0, a0, 0x40
 
 1:
-	beq	g1, g0, do_end_words
-	 andi	g7, o2, 0x1c
+	beqz	t2, do_end_words
+	 andi	t8, a2, 0x1c
 
 move_32bytes:
-	MOVE_BIGCHUNK(o1, o0, 0x00, o4, o5, g2, g3, g4, g5)
-	andi	g7, o2, 0x1c
-	addu	o1, o1, 0x20
-	addu	o0, o0, 0x20
+	MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	andi	t8, a2, 0x1c
+	addu	a1, a1, 0x20
+	addu	a0, a0, 0x20
 
 do_end_words:
-	beq	g7, g0, maybe_end_cruft
-	 srl	g7, g7, 0x2
+	beqz	t8, maybe_end_cruft
+	 srl	t8, t8, 0x2
 
 end_words:
-	lw	o4, 0x00(o1)
-	subu	g7, g7, 0x1
-	sw	o4, 0x00(o0)
-	addu	o1, o1, 0x4
-	bne	g7, g0, end_words
-	 addu	o0, o0, 0x4
+	EX(lw, t0, (a1), l_fixup)
+	subu	t8, t8, 0x1
+	EX(sw, t0, (a0), s_fixup)
+	addu	a1, a1, 0x4
+	bnez	t8, end_words
+	 addu	a0, a0, 0x4
 
 maybe_end_cruft:
-	andi	g1, o2, 0x3
+	andi	t2, a2, 0x3
 
-cannot_optimize:
-	beq	g1, g0, out
-	 move	o2, g1
+small_memcpy:
+	beqz	t2, out
+	 move	a2, t2
 
 end_bytes:
-	lbu	o4, 0x00(o1)
-	subu	o2, o2, 0x1
-	sb	o4, 0x00(o0)
-	addu	o1, o1, 0x1
-	bne	o2, g0, end_bytes
-	 addu	o0, o0, 0x1
-
-out:
-	jr	o7
-	 move	v0, g6
+	EX(lb, t0, (a1), l_fixup)
+	subu	a2, a2, 0x1
+	EX(sb, t0, (a0), s_fixup)
+	addu	a1, a1, 0x1
+	bnez	a2, end_bytes
+	 addu	a0, a0, 0x1
+
+out:	jr	ra
+	 move	a2, zero
+
+/* ------------------------------------------------------------------------- */
+
+/* Bad, bad.  At least try to align the source  */
+
+memcpy_u_src:
+	bnez	t8, small_memcpy		# < 8 bytes?
+	 move	t2, a2
+
+	addiu	t0, a1, 7			# t0: how much to align
+	ori	t0, 7
+	xori	t0, 7
+	subu	t0, a1
+
+	UEX(ulw, t1, 0(a1), l_fixup)		# dword alignment
+	UEX(ulw, t2, 4(a1), l_fixup)
+	UEX(usw, t1, 0(a0), s_fixup)
+	UEX(usw, t2, 4(a0), s_fixup)
+
+	addu	a1, t0				# src
+	addu	a0, t0				# dst
+	subu	a2, t0				# len
+
+	sltiu	t8, a2, 56
+	bnez	t8, u_do_end_words
+	 andi	t8, a2, 0x3c
+
+	andi	t8, a1, 8			# now qword aligned?
+
+u_qword_align:
+	beqz	t8, u_oword_align
+	 andi	t8, a1, 0x10
+
+	EX(lw, t0, 0x00(a1), l_fixup)
+	EX(lw, t1, 0x04(a1), l_fixup)
+	subu	a2, a2, 0x8
+	UEX(usw, t0, 0x00(a0), s_fixup)
+	UEX(usw, t1, 0x04(a0), s_fixup)
+	addu	a1, a1, 0x8
+	andi	t8, a1, 0x10
+	addu	a0, a0, 0x8
+
+u_oword_align:
+	beqz	t8, u_begin_movement
+	 srl	t8, a2, 0x7
+
+	EX(lw, t3, 0x08(a1), l_fixup)
+	EX(lw, t4, 0x0c(a1), l_fixup)
+	EX(lw, t0, 0x00(a1), l_fixup)
+	EX(lw, t1, 0x04(a1), l_fixup)
+	UEX(usw, t3, 0x08(a0), s_fixup)
+	UEX(usw, t4, 0x0c(a0), s_fixup)
+	UEX(usw, t0, 0x00(a0), s_fixup)
+	UEX(usw, t1, 0x04(a0), s_fixup)
+	subu	a2, a2, 0x10
+	addu	a1, a1, 0x10
+	srl	t8, a2, 0x7
+	addu	a0, a0, 0x10
+
+u_begin_movement:
+	beqz	t8, 0f
+	 andi	t2, a2, 0x40
+
+u_move_128bytes:
+	UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	UMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4)
+	UMOVE_BIGCHUNK(a1, a0, 0x40, t0, t1, t3, t4)
+	UMOVE_BIGCHUNK(a1, a0, 0x60, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	addu	a1, a1, 0x80
+	bnez	t8, u_move_128bytes
+	 addu	a0, a0, 0x80
+
+0:
+	beqz	t2, 1f
+	 andi	t2, a2, 0x20
+
+u_move_64bytes:
+	UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	UMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4)
+	addu	a1, a1, 0x40
+	addu	a0, a0, 0x40
+
+1:
+	beqz	t2, u_do_end_words
+	 andi	t8, a2, 0x1c
+
+u_move_32bytes:
+	UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	andi	t8, a2, 0x1c
+	addu	a1, a1, 0x20
+	addu	a0, a0, 0x20
+
+u_do_end_words:
+	beqz	t8, u_maybe_end_cruft
+	 srl	t8, t8, 0x2
+
+u_end_words:
+	EX(lw, t0, 0x00(a1), l_fixup)
+	subu	t8, t8, 0x1
+	UEX(usw, t0, 0x00(a0), s_fixup)
+	addu	a1, a1, 0x4
+	bnez	t8, u_end_words
+	 addu	a0, a0, 0x4
+
+u_maybe_end_cruft:
+	andi	t2, a2, 0x3
+
+u_cannot_optimize:
+	beqz	t2, out
+	 move	a2, t2
+
+u_end_bytes:
+	EX(lb, t0, (a1), l_fixup)
+	subu	a2, a2, 0x1
+	EX(sb, t0, (a0), s_fixup)
+	addu	a1, a1, 0x1
+	bnez	a2, u_end_bytes
+	 addu	a0, a0, 0x1
+
+	jr	ra
+	 move	a2, zero
+	END(memcpy)
+
+/* descending order, destination aligned  */
+#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \
+	lw	t0, (offset + 0x10)(src); \
+	lw	t1, (offset + 0x14)(src); \
+	lw	t2, (offset + 0x18)(src); \
+	lw	t3, (offset + 0x1c)(src); \
+	sw	t0, (offset + 0x10)(dst); \
+	sw	t1, (offset + 0x14)(dst); \
+	sw	t2, (offset + 0x18)(dst); \
+	sw	t3, (offset + 0x1c)(dst); \
+	lw	t0, (offset + 0x00)(src); \
+	lw	t1, (offset + 0x04)(src); \
+	lw	t2, (offset + 0x08)(src); \
+	lw	t3, (offset + 0x0c)(src); \
+	sw	t0, (offset + 0x00)(dst); \
+	sw	t1, (offset + 0x04)(dst); \
+	sw	t2, (offset + 0x08)(dst); \
+	sw	t3, (offset + 0x0c)(dst)
+
+/* descending order, destination ununaligned  */
+#define RUMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \
+	lw	t0, (offset + 0x10)(src); \
+	lw	t1, (offset + 0x14)(src); \
+	lw	t2, (offset + 0x18)(src); \
+	lw	t3, (offset + 0x1c)(src); \
+	usw	t0, (offset + 0x10)(dst); \
+	usw	t1, (offset + 0x14)(dst); \
+	usw	t2, (offset + 0x18)(dst); \
+	usw	t3, (offset + 0x1c)(dst); \
+	lw	t0, (offset + 0x00)(src); \
+	lw	t1, (offset + 0x04)(src); \
+	lw	t2, (offset + 0x08)(src); \
+	lw	t3, (offset + 0x0c)(src); \
+	usw	t0, (offset + 0x00)(dst); \
+	usw	t1, (offset + 0x04)(dst); \
+	usw	t2, (offset + 0x08)(dst); \
+	usw	t3, (offset + 0x0c)(dst)
+
+	.align	5
+LEAF(memmove)
+	sltu	t0, a0, a1			# dst < src -> memcpy
+	bnez	t0, memcpy
+	 addu	v0, a0, a2
+	sltu	t0, v0, a1			# dst + len < src -> non-
+	bnez	t0, __memcpy			# overlapping, can use memcpy
+	 move	v0, a0				/* return value */
+	END(memmove)
+
+LEAF(__rmemcpy)					/* a0=dst a1=src a2=len */
+	addu	a0, a2				# dst = dst + len
+	addu	a1, a2				# src = src + len
+
+	xor	t0, a0, a1
+	andi	t0, t0, 0x3
+	move	t7, a0
+	beqz	t0, r_can_align
+	 sltiu	t8, a2, 0x8
+
+	b	r_memcpy_u_src			# bad alignment
+	 move	t2, a2
+
+r_can_align:
+	bnez	t8, r_small_memcpy		# < 8 bytes to copy
+	 move	t2, a2
+
+	beqz	a2, r_out
+	 andi	t8, a1, 0x1
+
+r_hword_align:
+	beqz	t8, r_word_align
+	 andi	t8, a1, 0x2
+
+	lb	t0, -1(a1)
+	subu	a2, a2, 0x1
+	sb	t0, -1(a0)
+	subu	a1, a1, 0x1
+	subu	a0, a0, 0x1
+	andi	t8, a1, 0x2
+
+r_word_align:
+	beqz	t8, r_dword_align
+	 sltiu	t8, a2, 56
+	
+	lh	t0, -2(a1)
+	subu	a2, a2, 0x2
+	sh	t0, -2(a0)
+	sltiu	t8, a2, 56
+	subu	a0, a0, 0x2
+	subu	a1, a1, 0x2
+
+r_dword_align:
+	bnez	t8, r_do_end_words
+	 move	t8, a2
+
+	andi	t8, a1, 0x4
+	beqz	t8, r_qword_align
+	 andi	t8, a1, 0x8
+
+	lw	t0, -4(a1)
+	subu	a2, a2, 0x4
+	sw	t0, -4(a0)
+	subu	a1, a1, 0x4
+	subu	a0, a0, 0x4
+	andi	t8, a1, 0x8
+
+r_qword_align:
+	beqz	t8, r_oword_align
+	 andi	t8, a1, 0x10
+
+	subu	a1, a1, 0x8
+	lw	t0, 0x04(a1)
+	lw	t1, 0x00(a1)
+	subu	a0, a0, 0x8
+	sw	t0, 0x04(a0)
+	sw	t1, 0x00(a0)
+	subu	a2, a2, 0x8
+
+	andi	t8, a1, 0x10
+
+r_oword_align:
+	beqz	t8, r_begin_movement
+	 srl	t8, a2, 0x7
+
+	subu	a1, a1, 0x10
+	lw	t3, 0x08(a1)			# assumes subblock ordering
+	lw	t4, 0x0c(a1)
+	lw	t0, 0x00(a1)
+	lw	t1, 0x04(a1)
+	subu	a0, a0, 0x10
+	sw	t3, 0x08(a0)
+	sw	t4, 0x0c(a0)
+	sw	t0, 0x00(a0)
+	sw	t1, 0x04(a0)
+	subu	a2, a2, 0x10
+	srl	t8, a2, 0x7
+
+r_begin_movement:
+	beqz	t8, 0f
+	 andi	t2, a2, 0x40
+
+r_move_128bytes:
+	RMOVE_BIGCHUNK(a1, a0, -0x80, t0, t1, t3, t4)
+	RMOVE_BIGCHUNK(a1, a0, -0x60, t0, t1, t3, t4)
+	RMOVE_BIGCHUNK(a1, a0, -0x40, t0, t1, t3, t4)
+	RMOVE_BIGCHUNK(a1, a0, -0x20, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	subu	a1, a1, 0x80
+	bnez	t8, r_move_128bytes
+	 subu	a0, a0, 0x80
+
+0:
+	beqz	t2, 1f
+	 andi	t2, a2, 0x20
+
+r_move_64bytes:
+	subu	a1, a1, 0x40
+	subu	a0, a0, 0x40
+	RMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4)
+	RMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+
+1:
+	beqz	t2, r_do_end_words
+	 andi	t8, a2, 0x1c
+
+r_move_32bytes:
+	subu	a1, a1, 0x20
+	subu	a0, a0, 0x20
+	RMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	andi	t8, a2, 0x1c
+
+r_do_end_words:
+	beqz	t8, r_maybe_end_cruft
+	 srl	t8, t8, 0x2
+
+r_end_words:
+	lw	t0, -4(a1)
+	subu	t8, t8, 0x1
+	sw	t0, -4(a0)
+	subu	a1, a1, 0x4
+	bnez	t8, r_end_words
+	 subu	a0, a0, 0x4
+
+r_maybe_end_cruft:
+	andi	t2, a2, 0x3
+
+r_small_memcpy:
+	beqz	t2, r_out
+	 move	a2, t2
+
+r_end_bytes:
+	lb	t0, -1(a1)
+	subu	a2, a2, 0x1
+	sb	t0, -1(a0)
+	subu	a1, a1, 0x1
+	bnez	a2, r_end_bytes
+	 subu	a0, a0, 0x1
+
+r_out:
+	jr	ra
+	 move	a2, zero
+
+/* ------------------------------------------------------------------------- */
+
+/* Bad, bad.  At least try to align the source  */
+
+r_memcpy_u_src:
+	bnez	t8, r_small_memcpy		# < 8 bytes?
+	 move	t2, a2
+
+	andi	t0, a1, 7			# t0: how much to align
+
+	ulw	t1, -8(a1)			# dword alignment
+	ulw	t2, -4(a1)
+	usw	t1, -8(a0)
+	usw	t2, -4(a0)
+
+	subu	a1, t0				# src
+	subu	a0, t0				# dst
+	subu	a2, t0				# len
+
+	sltiu	t8, a2, 56
+	bnez	t8, ru_do_end_words
+	 andi	t8, a2, 0x3c
+
+	andi	t8, a1, 8			# now qword aligned?
+
+ru_qword_align:
+	beqz	t8, ru_oword_align
+	 andi	t8, a1, 0x10
+
+	subu	a1, a1, 0x8
+	lw	t0, 0x00(a1)
+	lw	t1, 0x04(a1)
+	subu	a0, a0, 0x8
+	usw	t0, 0x00(a0)
+	usw	t1, 0x04(a0)
+	subu	a2, a2, 0x8
+
+	andi	t8, a1, 0x10
+
+ru_oword_align:
+	beqz	t8, ru_begin_movement
+	 srl	t8, a2, 0x7
+
+	subu	a1, a1, 0x10
+	lw	t3, 0x08(a1)			# assumes subblock ordering
+	lw	t4, 0x0c(a1)
+	lw	t0, 0x00(a1)
+	lw	t1, 0x04(a1)
+	subu	a0, a0, 0x10
+	usw	t3, 0x08(a0)
+	usw	t4, 0x0c(a0)
+	usw	t0, 0x00(a0)
+	usw	t1, 0x04(a0)
+	subu	a2, a2, 0x10
+
+	srl	t8, a2, 0x7
+
+ru_begin_movement:
+	beqz	t8, 0f
+	 andi	t2, a2, 0x40
+
+ru_move_128bytes:
+	RUMOVE_BIGCHUNK(a1, a0, -0x80, t0, t1, t3, t4)
+	RUMOVE_BIGCHUNK(a1, a0, -0x60, t0, t1, t3, t4)
+	RUMOVE_BIGCHUNK(a1, a0, -0x40, t0, t1, t3, t4)
+	RUMOVE_BIGCHUNK(a1, a0, -0x20, t0, t1, t3, t4)
+	subu	t8, t8, 0x01
+	subu	a1, a1, 0x80
+	bnez	t8, ru_move_128bytes
+	 subu	a0, a0, 0x80
+
+0:
+	beqz	t2, 1f
+	 andi	t2, a2, 0x20
+
+ru_move_64bytes:
+	subu	a1, a1, 0x40
+	subu	a0, a0, 0x40
+	RUMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4)
+	RUMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+
+1:
+	beqz	t2, ru_do_end_words
+	 andi	t8, a2, 0x1c
+
+ru_move_32bytes:
+	subu	a1, a1, 0x20
+	subu	a0, a0, 0x20
+	RUMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4)
+	andi	t8, a2, 0x1c
+
+ru_do_end_words:
+	beqz	t8, ru_maybe_end_cruft
+	 srl	t8, t8, 0x2
+
+ru_end_words:
+	lw	t0, -4(a1)
+	usw	t0, -4(a0)
+	subu	t8, t8, 0x1
+	subu	a1, a1, 0x4
+	bnez	t8, ru_end_words
+	 subu	a0, a0, 0x4
+
+ru_maybe_end_cruft:
+	andi	t2, a2, 0x3
+
+ru_cannot_optimize:
+	beqz	t2, r_out
+	 move	a2, t2
+
+ru_end_bytes:
+	lb	t0, -1(a1)
+	subu	a2, a2, 0x1
+	sb	t0, -1(a0)
+	subu	a1, a1, 0x1
+	bnez	a2, ru_end_bytes
+	 subu	a0, a0, 0x1
+
+	jr	ra
+	 move	a2, zero
+	END(__rmemcpy)
+
+l_fixup:					# clear the rest of the buffer
+	lw	t0, THREAD_BUADDR($28)
+	 nop
+	subu	a2, AT, t0			# a2 bytes to go
+	addu	a0, t0				# compute start address in a1
+	subu	a0, a1
+	j	__bzero
+	 move	a1, zero
+
+s_fixup:
+	jr	ra
+	 nop
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S
--- v2.1.100/linux/arch/mips/lib/memset.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/lib/memset.S	Fri May  8 00:13:24 1998
@@ -0,0 +1,141 @@
+/*
+ * include/asm-mips/types.h
+ *
+ * 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
+ *
+ * $Id: memset.S,v 1.1 1998/05/04 09:18:18 ralf Exp $
+ */
+#include <asm/asm.h>
+#include <asm/offset.h>
+#include <asm/regdef.h>
+
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a"; 			\
+	PTR	9b, handler; 				\
+	.previous
+
+#define F_FILL64(dst, offset, val, fixup)		\
+	EX(sw, val, (offset + 0x00)(dst), fixup);	\
+	EX(sw, val, (offset + 0x04)(dst), fixup);	\
+	EX(sw, val, (offset + 0x08)(dst), fixup);	\
+	EX(sw, val, (offset + 0x0c)(dst), fixup);	\
+	EX(sw, val, (offset + 0x10)(dst), fixup);	\
+	EX(sw, val, (offset + 0x14)(dst), fixup);	\
+	EX(sw, val, (offset + 0x18)(dst), fixup);	\
+	EX(sw, val, (offset + 0x1c)(dst), fixup);	\
+	EX(sw, val, (offset + 0x20)(dst), fixup);	\
+	EX(sw, val, (offset + 0x24)(dst), fixup);	\
+	EX(sw, val, (offset + 0x28)(dst), fixup);	\
+	EX(sw, val, (offset + 0x2c)(dst), fixup);	\
+	EX(sw, val, (offset + 0x30)(dst), fixup);	\
+	EX(sw, val, (offset + 0x34)(dst), fixup);	\
+	EX(sw, val, (offset + 0x38)(dst), fixup);	\
+	EX(sw, val, (offset + 0x3c)(dst), fixup)
+
+/*
+ * memset(void *s, int c, size_t n)
+ *
+ * a0: start of area to clear
+ * a1: char to fill with
+ * a2: size of area to clear
+ */
+	.set	noreorder
+	.align	5
+LEAF(memset)
+	beqz	a1, 1f
+	 move	v0, a0				/* result */
+
+	andi	a1, 0xff			/* spread fillword */
+	sll	t1, a1, 8
+	or	a1, t1
+	sll	t1, a1, 16
+	or	a1, t1
+1:
+
+EXPORT(__bzero)
+	sltiu	t0, a2, 4			/* very small region? */
+	bnez	t0, small_memset
+	 andi	t0, a0, 3			/* aligned? */
+
+	beqz	t0, 1f
+	 subu	t0, 4				/* alignment in bytes */
+
+#ifdef __MIPSEB__
+	EX(swl, a1, (a0), first_fixup)		/* make word aligned */
+#endif
+#ifdef __MIPSEL__
+	EX(swr, a1, (a0), first_fixup)		/* make word aligned */
+#endif
+	subu	a0, t0				/* word align ptr */
+	addu	a2, t0				/* correct size */
+
+1:	ori	t1, a2, 0x3f			/* # of full blocks */
+	xori	t1, 0x3f
+	beqz	t1, memset_partial		/* no block to fill */
+	 andi	t0, a2, 0x3c
+
+	addu	t1, a0				/* end address */
+	.set	reorder
+1:	addiu	a0, 64
+	F_FILL64(a0, -64, a1, fwd_fixup)
+	bne	t1, a0, 1b
+	.set	noreorder
+
+memset_partial:
+	la	t1, 2f				/* where to start */
+	subu	t1, t0
+	jr	t1
+	 addu	a0, t0				/* dest ptr */
+
+	F_FILL64(a0, -64, a1, partial_fixup)	/* ... but first do wrds ... */
+2:	andi	a2, 3				/* 0 <= n <= 3 to go */
+
+	beqz	a2, 1f
+	 addu	a0, a2				/* What's left */
+#ifdef __MIPSEB__
+	EX(swr, a1, -1(a0), last_fixup)
+#endif
+#ifdef __MIPSEL__
+	EX(swl, a1, -1(a0), last_fixup)
+#endif
+1:	jr	ra
+	 move	a2, zero
+
+small_memset:
+	beqz	a2, 2f
+	 addu	t1, a0, a2
+
+1:	addiu	a0, 1				/* fill bytewise */
+	bne	t1, a0, 1b
+	 sb	a1, -1(a0)
+
+2:	jr	ra				/* done */
+	 move	a2, zero
+	END(memset)
+
+first_fixup:
+	jr	ra
+	 nop
+
+fwd_fixup:
+	lw	t0, THREAD_BUADDR($28)
+	andi	a2, 0x3f
+	addu	a2, t1
+	jr	ra
+	 subu	a2, t0
+
+partial_fixup:
+	lw	t0, THREAD_BUADDR($28)
+	andi	a2, 3
+	addu	a2, t1
+	jr	ra
+	 subu	a2, t0
+
+last_fixup:
+	jr	ra
+	 andi	v1, a2, 3
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/pmaxcon.c linux/arch/mips/lib/pmaxcon.c
--- v2.1.100/linux/arch/mips/lib/pmaxcon.c	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/lib/pmaxcon.c	Wed Dec 31 16:00:00 1969
@@ -1,150 +0,0 @@
-/* ----------------------------------------------------------------------
- * console.c
- *
- * Copyright (C) 1994 by Waldorf Electronic,
- * written by Ralf Baechle and Andreas Busse
- * Copyright (C) 1995 Paul M. Antoine (PMAX)
- *
- * 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.
- * ---------------------------------------------------------------------- */
-/*
- * FIXME: This file is hacked to be hardwired for the Personal DECStation
- *        Only thought of as a debugging console output
- */
-
-#include <linux/tty.h>
-#include <asm/bootinfo.h>
-
-static unsigned int size_x;
-static unsigned int size_y;
-static unsigned short cursor_x;
-static unsigned short cursor_y;
-static volatile unsigned short *vram_addr;
-static int console_needs_init = 1;
-
-extern struct bootinfo boot_info;
-extern struct screen_info screen_info;
-
-/*
- * Here is the base address of the prom calls
- */
-unsigned long pmax_rex_base = 0;
-
-/* ----------------------------------------------------------------------
- * init_console()
- * ---------------------------------------------------------------------- */
-
-void init_console(void)
-{
-  size_x = 80;
-  size_y = 50;
-  cursor_x = 0;
-  cursor_y = 0;
-
-  vram_addr = (unsigned short *)0xe10b8000;
-  
-  console_needs_init = 0;
-}
-
-void
-set_size_x(unsigned int x)
-{
-  size_x = x;
-}
-
-void
-set_size_y(unsigned int y)
-{
-  size_y = y;
-}
-
-void
-set_vram(unsigned short *vram)
-{
-  vram_addr = vram;
-}
-
-/*
- * FIXME: Temporary hack - changed its name to avoid conflict in
- *	  drivers/char/vga.c that shouldn't be there <sigh>  PMA
- */
-void
-set_pmax_cursor(unsigned int x, unsigned int y)
-{
-  cursor_x = x;
-  cursor_y = y;
-}
-
-void
-print_char(unsigned int x, unsigned int y, unsigned char c)
-{
-  volatile unsigned short *caddr;
-
-/*  caddr = vram_addr + (y * size_x) + x;
-  *caddr = (*caddr & 0xff00) | 0x0f00 | (unsigned short) c;
-*/
-  pmax_putch(c);
-}
-
-static void
-scroll(void)
-{
-  volatile unsigned short *caddr;
-  register int i;
-/*
-  caddr = vram_addr;
-  for(i=0; i<size_x * (size_y-1); i++)
-    *(caddr++) = *(caddr + size_x);
-
-   blank last line 
-  
-  caddr = vram_addr + (size_x * (size_y-1));
-  for(i=0; i<size_x; i++)
-    *(caddr++) = (*caddr & 0xff00) | (unsigned short) ' ';
-*/
-  pmax_putch('\n');
-}
-
-void print_string(const unsigned char *str)
-{
-  unsigned char c;
-
-  if (console_needs_init)
-    init_console();
-/*
-  while((c = *str++))
-    switch(c)
-      {
-      case '\n':
-	cursor_x = 0;
-	cursor_y++;
-	if(cursor_y == size_y)
-	  {
-	    scroll();
-	    cursor_y = size_y - 1;
-	  }
-	break;
-
-      default:
-	print_char(cursor_x, cursor_y, c);
-	cursor_x++;
-	if(cursor_x == size_x)
-	  {
-	    cursor_x = 0;
-	    cursor_y++;
-	    if(cursor_y == size_y)
-	      {
-		scroll();
-		cursor_y = size_y - 1;
-	      }
-	  }
-	break;
-      }
-*/
-  pmax_printf(str);
-
-}
-
-/* end of file */
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/pmaxio.S linux/arch/mips/lib/pmaxio.S
--- v2.1.100/linux/arch/mips/lib/pmaxio.S	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/lib/pmaxio.S	Wed Dec 31 16:00:00 1969
@@ -1,40 +0,0 @@
-#include <asm/regdef.h>
-#include <asm/decstation.h>
-
-		.text
-		.set	reorder
-/*
- * pmax_printf - call the PROM printf() function
- */
-		.globl	pmax_printf
-pmax_printf:
-		lw	v0,pmax_rex_base
-		lw	v0,REX_PRINTF(v0)
-		j	v0
-
-/*
- * pmax_getchar - call the PROM getchar() function
- */
-		.globl	pmax_getch
-pmax_getch:
-		lw	v0,pmax_rex_base
-		lw	v0,REX_GETCHAR(v0)
-		j	v0
-
-/*
- * pmax_putchar - call the PROM putchar() function
- */
-		.globl	pmax_putch
-pmax_putch:
-		lw	v0,pmax_rex_base
-		lw	v0,REX_PUTCHAR(v0)
-		j	v0
-
-/*
- * pmax_halt - call the PROM halt() function
- */
-		.globl	pmax_halt
-pmax_halt:
-		lw	v0,pmax_rex_base
-		lw	v0,REX_HALT(v0)
-		j	v0
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S
--- v2.1.100/linux/arch/mips/lib/strlen_user.S	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/lib/strlen_user.S	Fri May  8 00:13:24 1998
@@ -5,29 +5,44 @@
  * 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
+ *
+ * $Id: strlen_user.S,v 1.2 1998/05/04 09:18:20 ralf Exp $
  */
 #include <asm/asm.h>
+#include <asm/offset.h>
 #include <asm/regdef.h>
 #include <asm/sgidefs.h>
 
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a";			\
+	PTR	9b, handler;				\
+	.previous
+
 /*
  * Return the size of a string (including the ending 0)
  *
  * Return 0 for error
  */
-LEAF(__strlen_user)
-		move		v0,zero
-1:		lb		t0,(a0)
-		LONG_ADDIU	v0,1
-		LONG_ADDIU	a0,1
-		bnez		t0,1b
-		jr		ra
-		END(__strlen_user)
+LEAF(__strlen_user_nocheck_asm)
+	lw	v0, THREAD_CURDS($28)			# pointer ok?
+	subu	v0, zero, v0
+	and	v0, a0
+	nor	v0, zero, v0
+	beqz	v0, fault
+EXPORT(__strlen_user_asm)
+	move		v0, a0
+1:	EX(lb, t0, (v0), fault)
+	LONG_ADDIU	v0, 1
+	bnez		t0, 1b
+	LONG_SUBU	v0, a0
+	jr		ra
+	END(__strlen_user_nocheck_asm)
 
-		.section	__ex_table,"a"
-		PTR		1b,fault
-		.previous
+	.section	__ex_table,"a"
+	PTR		1b, fault
+	.previous
 
-fault:		move		v0,zero
-		jr		ra
+fault:	move		v0, zero
+	jr		ra
diff -u --recursive --new-file v2.1.100/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S
--- v2.1.100/linux/arch/mips/lib/strncpy_user.S	Thu Jun 26 12:33:37 1997
+++ linux/arch/mips/lib/strncpy_user.S	Fri May  8 00:13:24 1998
@@ -6,12 +6,20 @@
  * for more details.
  *
  * Copyright (c) 1996 by Ralf Baechle
+ *
+ * $Id: strncpy_user.S,v 1.2 1998/05/04 09:18:22 ralf Exp $
  */
 #include <linux/errno.h>
-
 #include <asm/asm.h>
+#include <asm/offset.h>
 #include <asm/regdef.h>
 
+#define EX(insn,reg,addr,handler)			\
+9:	insn	reg, addr;				\
+	.section __ex_table,"a";			\
+	PTR	9b, handler;				\
+	.previous
+
 /*
  * Returns: -EFAULT if exception before terminator, N if the entire
  * buffer filled, else strlen.
@@ -19,30 +27,37 @@
 
 /*
  * Ugly special case have to check: we might get passed a user space
- * pointer which wraps into the kernel space ...
+ * pointer which wraps into the kernel space.  We don't deal with that.  If
+ * it happens at most some bytes of the exceptions handlers will be copied.
  */
 
-LEAF(__strncpy_from_user)
-		move		v0,zero
-		move		v1,a1
-		.set		noreorder
-1:		lbu		t0,(v1)
-		LONG_ADDIU	v1,1
-		beqz		t0,2f
-		sb		t0,(a0)		# delay slot
-		LONG_ADDIU	v0,1
-		bne		v0,a2,1b
-		LONG_ADDIU	a0,1		# delay slot
-		.set		reorder
-2:		LONG_ADDU	t0,a1,v0
-		xor		t0,a1
-		bltz		t0,fault
-		jr		ra		# return n
-		END(__strncpy_from_user)
-
-fault:		li		v0,-EFAULT
-		jr		ra
-
-		.section	__ex_table,"a"
-		PTR		1b,fault
-		.previous
+LEAF(__strncpy_from_user_asm)
+	lw	v0, THREAD_CURDS($28)		# pointer ok?
+	subu	v0, zero, v0
+	and	v0, a1
+	nor	v0, zero, v0
+	beqz	v0, fault
+EXPORT(__strncpy_from_user_nocheck_asm)
+	move		v0,zero
+	move		v1,a1
+	.set		noreorder
+1:	EX(lbu,	 t0, (v1), fault)
+	LONG_ADDIU	v1,1
+	beqz		t0,2f
+	 sb		t0,(a0)
+	LONG_ADDIU	v0,1
+	bne		v0,a2,1b
+	 LONG_ADDIU	a0,1
+	.set		reorder
+2:	LONG_ADDU	t0,a1,v0
+	xor		t0,a1
+	bltz		t0,fault
+	jr		ra			# return n
+	END(__strncpy_from_user_asm)
+
+fault:	li		v0,-EFAULT
+	jr		ra
+
+	.section	__ex_table,"a"
+	PTR		1b,fault
+	.previous
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c
--- v2.1.100/linux/arch/mips/mm/andes.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/mm/andes.c	Fri May  8 00:13:24 1998
@@ -1,13 +1,14 @@
-/* $Id: andes.c,v 1.2 1997/12/02 05:51:07 ralf Exp $
+/*
  * andes.c: MMU and cache operations for the R10000 (ANDES).
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: andes.c,v 1.5 1998/05/04 09:18:26 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -85,7 +86,12 @@
         /* XXX */
 }
 
-void ld_mmu_andes(void)
+static int andes_user_mode(struct pt_regs *regs)
+{
+	return (regs->cp0_status & ST0_KSU) == KSU_USER;
+}
+
+__initfunc(void ld_mmu_andes(void))
 {
 	flush_cache_all = andes_flush_cache_all;
 	flush_cache_mm = andes_flush_cache_mm;
@@ -100,6 +106,8 @@
 	flush_tlb_page = andes_flush_tlb_page;
     
         add_wired_entry = andes_add_wired_entry;
+
+	user_mode = andes_user_mode;
 
 	load_pgd = andes_load_pgd;
 	pgd_init = andes_pgd_init;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c
--- v2.1.100/linux/arch/mips/mm/fault.c	Sat Aug 16 09:51:07 1997
+++ linux/arch/mips/mm/fault.c	Fri May  8 00:13:24 1998
@@ -16,6 +16,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
+#include <asm/hardirq.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/system.h>
@@ -43,6 +44,8 @@
 	struct mm_struct *mm = tsk->mm;
 	unsigned long fixup;
 
+	if (local_irq_count[smp_processor_id()] != 0)
+		die_if_kernel("page fault from irq handler", regs, writeaccess);
 	lock_kernel();
 #if 0
 	printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
@@ -85,7 +88,7 @@
 	if (user_mode(regs)) {
 		tsk->tss.cp0_badvaddr = address;
 		tsk->tss.error_code = writeaccess;
-#if 1
+#if 0
 		printk("do_page_fault() #2: sending SIGSEGV to %s for illegal %s\n"
 		       "%08lx (epc == %08lx, ra == %08lx)\n",
 		       tsk->comm,
@@ -94,9 +97,6 @@
 		       (unsigned long) regs->cp0_epc,
 		       (unsigned long) regs->regs[31]);
 #endif
-
-		current->tss.cp0_badvaddr = address;
-		current->tss.error_code = writeaccess;
 		force_sig(SIGSEGV, tsk);
 		goto out;
 	}
@@ -105,6 +105,8 @@
 	fixup = search_exception_table(regs->cp0_epc);
 	if (fixup) {
 		long new_epc;
+
+		tsk->tss.cp0_baduaddr = address;
 		new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
 		printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n",
 		       tsk->comm, regs->cp0_epc, new_epc);
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v2.1.100/linux/arch/mips/mm/init.c	Thu Jul 31 13:09:17 1997
+++ linux/arch/mips/mm/init.c	Fri May  8 00:13:24 1998
@@ -1,10 +1,14 @@
 /*
- *  arch/mips/mm/init.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) 1991, 1992, 1993, 1994  Linus Torvalds
- *  Ported to MIPS by Ralf Baechle
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle
+ *
+ * $Id: init.c,v 1.14 1998/05/01 01:34:53 ralf Exp $
  */
 #include <linux/config.h>
+#include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/head.h>
@@ -113,58 +117,12 @@
 	return (pte_t *)page;
 }
 
-static inline void
-__zeropage(unsigned long page)
-{
-	unsigned long dummy1, dummy2;
-
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
-        /*
-         * Use 64bit code even for Linux/MIPS 32bit on R4000
-         */
-	__asm__ __volatile__(
-		".set\tnoreorder\n"
-		".set\tnoat\n\t"
-		".set\tmips3\n"
-		"1:\tsd\t$0,(%0)\n\t"
-		"subu\t%1,1\n\t"
-		"bnez\t%1,1b\n\t"
-		"addiu\t%0,8\n\t"
-		".set\tmips0\n\t"
-		".set\tat\n"
-		".set\treorder"
-		:"=r" (dummy1),
-		 "=r" (dummy2)
-		:"0" (page),
-		 "1" (PAGE_SIZE/8));
-#else /* (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) */
-	__asm__ __volatile__(
-		".set\tnoreorder\n"
-		"1:\tsw\t$0,(%0)\n\t"
-		"subu\t%1,1\n\t"
-		"bnez\t%1,1b\n\t"
-		"addiu\t%0,4\n\t"
-		".set\treorder"
-		:"=r" (dummy1),
-		 "=r" (dummy2)
-		:"0" (page),
-		 "1" (PAGE_SIZE/4));
-#endif
-}
-
-static inline void
-zeropage(unsigned long page)
-{
-	flush_page_to_ram(page);
-	__zeropage(page);
-}
-
 pte_t __bad_page(void)
 {
 	extern char empty_bad_page[PAGE_SIZE];
 	unsigned long page = (unsigned long)empty_bad_page;
 
-	zeropage(page);
+	clear_page(page);
 	return pte_mkdirty(mk_pte(page, PAGE_SHARED));
 }
 
@@ -198,13 +156,13 @@
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
 
-unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
+__initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_mem))
 {
 	pgd_init((unsigned long)swapper_pg_dir);
 	return free_area_init(start_mem, end_mem);
 }
 
-void mem_init(unsigned long start_mem, unsigned long end_mem)
+__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
 {
 	int codepages = 0;
 	int datapages = 0;
@@ -221,7 +179,7 @@
 	high_memory = (void *)end_mem;
 
 	/* clear the zero-page */
-	memset(empty_zero_page, 0, PAGE_SIZE);
+	clear_page((unsigned long)empty_zero_page);
 
 	/* mark usable pages in the mem_map[] */
 	start_mem = PAGE_ALIGN(start_mem);
@@ -229,27 +187,11 @@
 	for(tmp = MAP_NR(start_mem);tmp < max_mapnr;tmp++)
 		clear_bit(PG_reserved, &mem_map[tmp].flags);
 
-	/*
-	 * For rPC44 and RM200 we've reserved some memory too much.  Free
-	 * the memory from PAGE_SIZE to PAGE_OFFSET + 0xa0000 again.  We
-	 * don't free the lowest page where the exception handlers will
-	 * reside.
-	 */
-	if (mips_machgroup ==  MACH_GROUP_ARC &&
-	    mips_machtype == MACH_DESKSTATION_RPC44)
-		for(tmp = MAP_NR(PAGE_OFFSET + PAGE_SIZE);
-		    tmp < MAP_NR(PAGE_OFFSET + 0xa000); tmp++)
-			clear_bit(PG_reserved, &mem_map[tmp].flags);
-
 
 #ifdef CONFIG_SGI
 	prom_fixup_mem_map(start_mem, (unsigned long)high_memory);
 #endif
 
-#ifdef CONFIG_DESKSTATION_TYNE
-	deskstation_tyne_dma_init();
-#endif
-
 	for (tmp = PAGE_OFFSET; tmp < end_mem; tmp += PAGE_SIZE) {
 		/*
 		 * This is only for PC-style DMA.  The onboard DMA
@@ -284,9 +226,20 @@
 	return;
 }
 
+extern char __init_begin, __init_end;
+
 void free_initmem(void)
 {
-	/* To be written */
+	unsigned long addr;
+        
+	addr = (unsigned long)(&__init_begin);
+	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+		mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+		free_page(addr);
+	}
+	printk("Freeing unused kernel memory: %dk freed\n",
+	       (&__init_end - &__init_begin) >> 10);
 }
 
 void si_meminfo(struct sysinfo *val)
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c
--- v2.1.100/linux/arch/mips/mm/loadmmu.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/mm/loadmmu.c	Fri May  8 00:13:24 1998
@@ -3,9 +3,9 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: loadmmu.c,v 1.4 1997/12/02 05:51:07 ralf Exp $
+ * $Id: loadmmu.c,v 1.6 1998/05/01 01:34:54 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -30,8 +30,8 @@
 void (*flush_page_to_ram)(unsigned long page);
 
 /* DMA cache operations. */
-void (*flush_cache_pre_dma_out)(unsigned long start, unsigned long size);
-void (*flush_cache_post_dma_in)(unsigned long start, unsigned long size);
+void (*dma_cache_wback_inv)(unsigned long start, unsigned long size);
+void (*dma_cache_inv)(unsigned long start, unsigned long size);
 
 /* TLB operations. */
 void (*flush_tlb_all)(void);
@@ -51,6 +51,8 @@
 void (*add_wired_entry)(unsigned long entrylo0, unsigned long entrylo1,
 			unsigned long entryhi, unsigned long pagemask);
 
+int (*user_mode)(struct pt_regs *);
+
 asmlinkage void (*resume)(void *tsk);
 
 extern void ld_mmu_r2300(void);
@@ -59,7 +61,7 @@
 extern void ld_mmu_tfp(void);
 extern void ld_mmu_andes(void);
 
-void loadmmu(void)
+__initfunc(void loadmmu(void))
 {
 	switch(mips_cputype) {
 	case CPU_R2000:
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c
--- v2.1.100/linux/arch/mips/mm/r2300.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/mm/r2300.c	Fri May  8 00:13:24 1998
@@ -3,9 +3,9 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r2300.c,v 1.3 1997/12/02 05:51:08 ralf Exp $
+ * $Id: r2300.c,v 1.5 1998/05/01 01:34:55 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -253,7 +253,12 @@
 	 */
 }
 
-void ld_mmu_r2300(void)
+static int r2300_user_mode(struct pt_regs *regs)
+{
+	return !(regs->cp0_status & 0x4);
+}
+
+__initfunc(void ld_mmu_r2300(void))
 {
 	clear_page = r2300_clear_page;
 	copy_page = r2300_copy_page;
@@ -278,5 +283,6 @@
     
         add_wired_entry = r2300_add_wired_entry;
 
+	user_mode = r2300_user_mode;
 	flush_tlb_all();
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c
--- v2.1.100/linux/arch/mips/mm/r4xx0.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/mm/r4xx0.c	Fri May  8 00:13:24 1998
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r4xx0.c,v 1.11 1997/12/02 06:33:53 ralf Exp $
+ * $Id: r4xx0.c,v 1.11 1998/05/04 09:18:31 ralf Exp $
  *
  * To do:
  *
@@ -11,13 +11,13 @@
  *  - many of the bug workarounds are not efficient at all, but at
  *    least they are functional ...
  */
-#include <linux/config.h>
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/autoconf.h>
 
+#include <asm/bcache.h>
+#include <asm/io.h>
 #include <asm/sgi.h>
 #include <asm/sgimc.h>
 #include <asm/page.h>
@@ -45,6 +45,18 @@
 #undef DEBUG_CACHE
 
 /*
+ * Dummy cache handling routines for machines without boardcaches
+ */
+static void no_sc_noop(void) {}
+
+static struct bcache_ops no_sc_ops = {
+	(void *)no_sc_noop, (void *)no_sc_noop,
+	(void *)no_sc_noop, (void *)no_sc_noop
+};
+
+struct bcache_ops *bcops = &no_sc_ops;
+
+/*
  * On processors with QED R4600 style two set assosicative cache
  * this is the bit which selects the way in the cache for the
  * indexed cachops.
@@ -53,9 +65,19 @@
 #define dcache_waybit (dcache_size >> 1)
 
 /*
- * Zero an entire page.  We have three flavours of the routine available.
- * One for CPU with 16byte, with 32byte cachelines plus a special version
- * with nops which handles the buggy R4600 v1.x.
+ * Zero an entire page.  Basically a simple unrolled loop should do the
+ * job but we want more performance by saving memory bus bandwidth.  We
+ * have five flavours of the routine available for:
+ *
+ * - 16byte cachelines and no second level cache
+ * - 32byte cachelines second level cache
+ * - a version which handles the buggy R4600 v1.x
+ * - a version which handles the buggy R4600 v2.0
+ * - Finally a last version without fancy cache games for the SC and MC
+ *   versions of R4000 and R4400.  Cache instructions are quite expensive
+ *   and I guess using them for both the primary and the second level cache
+ *   wouldn't be worth the effort.
+ *   This needs to be verified by benchmarking.
  */
 
 static void r4k_clear_page_d16(unsigned long page)
@@ -219,6 +241,32 @@
 	restore_flags(flags);
 }
 
+static void r4k_clear_page(unsigned long page)
+{
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%2\n"
+		"1:\tsd\t$0,(%0)\n\t"
+		"sd\t$0,8(%0)\n\t"
+		"sd\t$0,16(%0)\n\t"
+		"sd\t$0,24(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"sd\t$0,-32(%0)\n\t"
+		"sd\t$0,-24(%0)\n\t"
+		"sd\t$0,-16(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sd\t$0,-8(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (page)
+		:"0" (page),
+		 "I" (PAGE_SIZE)
+		:"$1","memory");
+}
+
 
 /*
  * This is still inefficient.  We only can do better if we know the
@@ -477,6 +525,60 @@
 	restore_flags(flags);
 }
 
+static void r4k_copy_page(unsigned long to, unsigned long from)
+{
+	unsigned long dummy1, dummy2;
+	unsigned long reg1, reg2, reg3, reg4;
+
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		".set\tmips3\n\t"
+		"daddiu\t$1,%0,%8\n"
+		"1:\tlw\t%2,(%1)\n\t"
+		"lw\t%3,4(%1)\n\t"
+		"lw\t%4,8(%1)\n\t"
+		"lw\t%5,12(%1)\n\t"
+		"sw\t%2,(%0)\n\t"
+		"sw\t%3,4(%0)\n\t"
+		"sw\t%4,8(%0)\n\t"
+		"sw\t%5,12(%0)\n\t"
+		"lw\t%2,16(%1)\n\t"
+		"lw\t%3,20(%1)\n\t"
+		"lw\t%4,24(%1)\n\t"
+		"lw\t%5,28(%1)\n\t"
+		"sw\t%2,16(%0)\n\t"
+		"sw\t%3,20(%0)\n\t"
+		"sw\t%4,24(%0)\n\t"
+		"sw\t%5,28(%0)\n\t"
+		"daddiu\t%0,64\n\t"
+		"daddiu\t%1,64\n\t"
+		"lw\t%2,-32(%1)\n\t"
+		"lw\t%3,-28(%1)\n\t"
+		"lw\t%4,-24(%1)\n\t"
+		"lw\t%5,-20(%1)\n\t"
+		"sw\t%2,-32(%0)\n\t"
+		"sw\t%3,-28(%0)\n\t"
+		"sw\t%4,-24(%0)\n\t"
+		"sw\t%5,-20(%0)\n\t"
+		"lw\t%2,-16(%1)\n\t"
+		"lw\t%3,-12(%1)\n\t"
+		"lw\t%4,-8(%1)\n\t"
+		"lw\t%5,-4(%1)\n\t"
+		"sw\t%2,-16(%0)\n\t"
+		"sw\t%3,-12(%0)\n\t"
+		"sw\t%4,-8(%0)\n\t"
+		"bne\t$1,%0,1b\n\t"
+		"sw\t%5,-4(%0)\n\t"
+		".set\tmips0\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		:"=r" (dummy1), "=r" (dummy2),
+		 "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
+		:"0" (to), "1" (from),
+		 "I" (PAGE_SIZE));
+}
+
 /*
  * If you think for one second that this stuff coming up is a lot
  * of bulky code eating too many kernel cache lines.  Think _again_.
@@ -1892,144 +1994,111 @@
  * in .pdf format.)
  */
 static void
-r4k_flush_cache_pre_dma_out_pc(unsigned long addr, unsigned long size)
+r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size)
 {
 	unsigned long end, a;
-	unsigned int cmode, flags;
-
-	cmode = read_32bit_cp0_register(CP0_CONFIG) & CONFIG_CM_CMASK;
-	if (cmode == CONFIG_CM_CACHABLE_WA ||
-	    cmode == CONFIG_CM_CACHABLE_NO_WA) {
-		/* primary dcache is writethrough, therefore memory
-		   is already consistent with the caches.  */
-		return;
-	}
+	unsigned int flags;
 
 	if (size >= dcache_size) {
 		flush_cache_all();
-		return;
-	}
-
-	/* Workaround for R4600 bug.  See comment above. */
-	save_and_cli(flags);
-	*(volatile unsigned long *)KSEG1;
+	} else {
+		/* Workaround for R4600 bug.  See comment above. */
+		save_and_cli(flags);
+		*(volatile unsigned long *)KSEG1;
 
-	a = addr & ~(dc_lsize - 1);
-	end = (addr + size) & ~(dc_lsize - 1);
-	while (1) {
-		flush_dcache_line(a); /* Hit_Writeback_Inv_D */
-		if (a == end) break;
-		a += dc_lsize;
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size) & ~(dc_lsize - 1);
+		while (1) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			if (a == end) break;
+			a += dc_lsize;
+		}
+		restore_flags(flags);
 	}
-	restore_flags(flags);
+	bcops->bc_wback_inv(addr, size);
 }
 
 static void
-r4k_flush_cache_pre_dma_out_sc(unsigned long addr, unsigned long size)
+r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size)
 {
-	unsigned long end;
-	unsigned long a;
+	unsigned long end, a;
+	unsigned int flags;
 
 	if (size >= scache_size) {
 		flush_cache_all();
-		return;
+	} else {
+		save_and_cli(flags);
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size) & ~(dc_lsize - 1);
+		while (1) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			if (a == end) break;
+			a += dc_lsize;
+		}
+		restore_flags(flags);
 	}
 
 	a = addr & ~(sc_lsize - 1);
 	end = (addr + size) & ~(sc_lsize - 1);
 	while (1) {
-		flush_scache_line(addr); /* Hit_Writeback_Inv_SD */
-		if (addr == end) break;
-		addr += sc_lsize;
+		flush_scache_line(a);	/* Hit_Writeback_Inv_SD */
+		if (a == end) break;
+		a += sc_lsize;
 	}
-	r4k_flush_cache_pre_dma_out_pc(addr, size);
 }
 
 static void
-r4k_flush_cache_post_dma_in_pc(unsigned long addr, unsigned long size)
+r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size)
 {
-	unsigned long end;
-	unsigned long a;
+	unsigned long end, a;
+	unsigned int flags;
 
 	if (size >= dcache_size) {
 		flush_cache_all();
-		return;
-	}
-
-	/* Workaround for R4600 bug.  See comment above. */
-	*(volatile unsigned long *)KSEG1;
+	} else {
+		/* Workaround for R4600 bug.  See comment above. */
+		save_and_cli(flags);
+		*(volatile unsigned long *)KSEG1;
 
-	a = addr & ~(dc_lsize - 1);
-	end = (addr + size) & ~(dc_lsize - 1);
-	while (1) {
-		invalidate_dcache_line(a); /* Hit_Invalidate_D */
-		if (a == end) break;
-		a += dc_lsize;
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size) & ~(dc_lsize - 1);
+		while (1) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			if (a == end) break;
+			a += dc_lsize;
+		}
+		restore_flags(flags);
 	}
+
+	bcops->bc_inv(addr, size);
 }
 
 static void
-r4k_flush_cache_post_dma_in_sc(unsigned long addr, unsigned long size)
+r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size)
 {
-	unsigned long end;
-	unsigned long a;
+	unsigned long end, a;
+	unsigned int flags;
 
 	if (size >= scache_size) {
 		flush_cache_all();
-		return;
+	} else {
+		save_and_cli(flags);
+		a = addr & ~(dc_lsize - 1);
+		end = (addr + size) & ~(dc_lsize - 1);
+		while (1) {
+			flush_dcache_line(a); /* Hit_Writeback_Inv_D */
+			if (a == end) break;
+			a += dc_lsize;
+		}
+		restore_flags(flags);
 	}
 
 	a = addr & ~(sc_lsize - 1);
 	end = (addr + size) & ~(sc_lsize - 1);
 	while (1) {
-		invalidate_scache_line(addr); /* Hit_Invalidate_SD */
-		if (addr == end) break;
-		addr += sc_lsize;
-	}
-	r4k_flush_cache_pre_dma_out_pc(addr, size);
-}
-
-static void r4k_flush_page_to_ram_d32i32_r4600(unsigned long page)
-{
-	page &= PAGE_MASK;
-	if((page >= KSEG0 && page < KSEG1) || (page >= KSEG2)) {
-		unsigned long flags;
-
-#ifdef DEBUG_CACHE
-		printk("r4600_cram[%08lx]", page);
-#endif
-		save_and_cli(flags);
-		blast_dcache32_page(page);
-#ifdef CONFIG_SGI
-		{
-			unsigned long tmp1, tmp2;
-
-			__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			li	%0, 0x1
-			dsll	%0, 31
-			or	%0, %0, %2
-			lui	%1, 0x9000
-			dsll32	%1, 0
-			or	%0, %0, %1
-			daddu	%1, %0, 0x0fe0
-			li	%2, 0x80
-			mtc0	%2, $12
-			nop; nop; nop; nop;
-1:			sw	$0, 0(%0)
-			bltu	%0, %1, 1b
-			daddu	%0, 32
-			mtc0	$0, $12
-			nop; nop; nop; nop;
-			.set mips0
-			.set reorder"
-			: "=&r" (tmp1), "=&r" (tmp2),
-			  "=&r" (page)
-			: "2" (page & 0x0007f000));
-		}
-#endif /* CONFIG_SGI */
-		restore_flags(flags);
+		flush_scache_line(a); /* Hit_Writeback_Inv_SD */
+		if (a == end) break;
+		a += sc_lsize;
 	}
 }
 
@@ -2394,173 +2463,31 @@
 }
 
 /* Detect and size the various r4k caches. */
-static void probe_icache(unsigned long config)
+__initfunc(static void probe_icache(unsigned long config))
 {
-	unsigned long tmp;
-
-	tmp = (config >> 9) & 7;
-	icache_size = (1 << (12 + tmp));
-	if((config >> 5) & 1)
-		ic_lsize = 32;
-	else
-		ic_lsize = 16;
+	icache_size = 1 << (12 + ((config >> 6) & 7));
+	ic_lsize = 16 << ((config >> 4) & 1);
 
-	printk("Primary ICACHE %dK (linesize %d bytes)\n",
-	       (int)(icache_size >> 10), (int)ic_lsize);
+	printk("Primary instruction cache %dkb, linesize %d bytes)\n",
+	       icache_size >> 10, ic_lsize);
 }
 
-static void probe_dcache(unsigned long config)
+__initfunc(static void probe_dcache(unsigned long config))
 {
-	unsigned long tmp;
+	dcache_size = 1 << (12 + ((config >> 6) & 7));
+	dc_lsize = 16 << ((config >> 4) & 1);
 
-	tmp = (config >> 6) & 7;
-	dcache_size = (1 << (12 + tmp));
-	if((config >> 4) & 1)
-		dc_lsize = 32;
-	else
-		dc_lsize = 16;
-
-	printk("Primary DCACHE %dK (linesize %d bytes)\n",
-	       (int)(dcache_size >> 10), (int)dc_lsize);
+	printk("Primary data cache %dkb, linesize %d bytes)\n",
+	       dcache_size >> 10, dc_lsize);
 }
 
-static int probe_scache_eeprom(unsigned long config)
-{
-#ifdef CONFIG_SGI
-	volatile unsigned int *cpu_control;
-	unsigned short cmd = 0xc220;
-	unsigned long data = 0;
-	int i, n;
-
-#ifdef __MIPSEB__
-	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
-#else
-	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
-#endif
-#define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
-#define ASSERT(bit) (*(cpu_control) |= (bit))
-#define DELAY  for(n = 0; n < 100000; n++) __asm__ __volatile__("")
-	DEASSERT(SGIMC_EEPROM_PRE);
-	DEASSERT(SGIMC_EEPROM_SDATAO);
-	DEASSERT(SGIMC_EEPROM_SECLOCK);
-	DEASSERT(SGIMC_EEPROM_PRE);
-	DELAY;
-	ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
-	for(i = 0; i < 11; i++) {
-		if(cmd & (1<<15))
-			ASSERT(SGIMC_EEPROM_SDATAO);
-		else
-			DEASSERT(SGIMC_EEPROM_SDATAO);
-		DEASSERT(SGIMC_EEPROM_SECLOCK);
-		ASSERT(SGIMC_EEPROM_SECLOCK);
-		cmd <<= 1;
-	}
-	DEASSERT(SGIMC_EEPROM_SDATAO);
-	for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
-		unsigned int tmp;
-
-		DEASSERT(SGIMC_EEPROM_SECLOCK);
-		DELAY;
-		ASSERT(SGIMC_EEPROM_SECLOCK);
-		DELAY;
-		data <<= 1;
-		tmp = *cpu_control;
-		if(tmp & SGIMC_EEPROM_SDATAI)
-			data |= 1;
-	}
-	DEASSERT(SGIMC_EEPROM_SECLOCK);
-	DEASSERT(SGIMC_EEPROM_CSEL);
-	ASSERT(SGIMC_EEPROM_PRE);
-	ASSERT(SGIMC_EEPROM_SECLOCK);
-	data <<= PAGE_SHIFT;
-	printk("R4600/R5000 SCACHE size %dK ", (int) (data >> 10));
-	switch(mips_cputype) {
-	case CPU_R4600:
-	case CPU_R4640:
-		sc_lsize = 32;
-		break;
-
-	default:
-		sc_lsize = 128;
-		break;
-	}
-	printk("linesize %d bytes\n", sc_lsize);
-	scache_size = data;
-	if(data) {
-		unsigned long addr, tmp1, tmp2;
-
-		/* Enable r4600/r5000 cache.  But flush it first. */
-		for(addr = KSEG0; addr < (KSEG0 + dcache_size);
-		    addr += dc_lsize)
-			flush_dcache_line_indexed(addr);
-		for(addr = KSEG0; addr < (KSEG0 + icache_size);
-		    addr += ic_lsize)
-			flush_icache_line_indexed(addr);
-		for(addr = KSEG0; addr < (KSEG0 + scache_size);
-		    addr += sc_lsize)
-			flush_scache_line_indexed(addr);
-
-		/* R5000 scache enable is in CP0 config, on R4600 variants
-		 * the scache is enable by the memory mapped cache controller.
-		 */
-		if(mips_cputype == CPU_R5000) {
-			unsigned long config;
-
-			config = read_32bit_cp0_register(CP0_CONFIG);
-			config |= 0x1000;
-			write_32bit_cp0_register(CP0_CONFIG, config);
-		} else {
-			/* This is really cool... */
-			printk("Enabling R4600 SCACHE\n");
-			__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			mfc0	%2, $12
-			nop; nop; nop; nop;
-			li	%1, 0x80
-			mtc0	%1, $12
-			nop; nop; nop; nop;
-			li	%0, 0x1
-			dsll	%0, 31
-			lui	%1, 0x9000
-			dsll32	%1, 0
-			or	%0, %1, %0
-			sb	$0, 0(%0)
-			mtc0	$0, $12
-			nop; nop; nop; nop;
-			mtc0	%2, $12
-			nop; nop; nop; nop;
-			.set mips0
-			.set reorder
-		        " : "=r" (tmp1), "=r" (tmp2), "=r" (addr));
-		}
-
-		return 1;
-	} else {
-		if(mips_cputype == CPU_R5000)
-			return -1;
-		else
-			return 0;
-	}
-#else
-	/*
-	 * XXX For now we don't panic and assume that existing chipset
-	 * controlled caches are setup correnctly and are completly
-	 * transparent.  Works fine for those MIPS machines I know.
-	 * Morituri the salutant ...
-	 */
-	return 0;
-
-	panic("Cannot probe SCACHE on this machine.");
-#endif
-}
 
 /* If you even _breathe_ on this function, look at the gcc output
  * and make sure it does not pop things on and off the stack for
  * the cache sizing loop that executes in KSEG1 space or else
  * you will crash and burn badly.  You have been warned.
  */
-static int probe_scache(unsigned long config)
+__initfunc(static int probe_scache(unsigned long config))
 {
 	extern unsigned long stext;
 	unsigned long flags, addr, begin, end, pow2;
@@ -2644,7 +2571,7 @@
 	return 1;
 }
 
-static void setup_noscache_funcs(void)
+__initfunc(static void setup_noscache_funcs(void))
 {
 	unsigned int prid;
 
@@ -2677,18 +2604,16 @@
 		flush_page_to_ram = r4k_flush_page_to_ram_d32i32;
 		break;
 	}
-	flush_cache_pre_dma_out = r4k_flush_cache_pre_dma_out_pc;
-	flush_cache_post_dma_in = r4k_flush_cache_post_dma_in_pc;
+	dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc;
+	dma_cache_inv = r4k_dma_cache_inv_pc;
 }
 
-static void setup_scache_funcs(void)
+__initfunc(static void setup_scache_funcs(void))
 {
 	switch(sc_lsize) {
 	case 16:
 		switch(dc_lsize) {
 		case 16:
-			clear_page = r4k_clear_page_d16;
-			copy_page = r4k_copy_page_d16;
 			flush_cache_all = r4k_flush_cache_all_s16d16i16;
 			flush_cache_mm = r4k_flush_cache_mm_s16d16i16;
 			flush_cache_range = r4k_flush_cache_range_s16d16i16;
@@ -2696,8 +2621,6 @@
 			flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16;
 			break;
 		case 32:
-			clear_page = r4k_clear_page_d32;
-			copy_page = r4k_copy_page_d32;
 			flush_cache_all = r4k_flush_cache_all_s16d32i32;
 			flush_cache_mm = r4k_flush_cache_mm_s16d32i32;
 			flush_cache_range = r4k_flush_cache_range_s16d32i32;
@@ -2709,8 +2632,6 @@
 	case 32:
 		switch(dc_lsize) {
 		case 16:
-			clear_page = r4k_clear_page_d16;
-			copy_page = r4k_copy_page_d16;
 			flush_cache_all = r4k_flush_cache_all_s32d16i16;
 			flush_cache_mm = r4k_flush_cache_mm_s32d16i16;
 			flush_cache_range = r4k_flush_cache_range_s32d16i16;
@@ -2718,8 +2639,6 @@
 			flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16;
 			break;
 		case 32:
-			clear_page = r4k_clear_page_d32;
-			copy_page = r4k_copy_page_d32;
 			flush_cache_all = r4k_flush_cache_all_s32d32i32;
 			flush_cache_mm = r4k_flush_cache_mm_s32d32i32;
 			flush_cache_range = r4k_flush_cache_range_s32d32i32;
@@ -2730,8 +2649,6 @@
 	case 64:
 		switch(dc_lsize) {
 		case 16:
-			clear_page = r4k_clear_page_d16;
-			copy_page = r4k_copy_page_d16;
 			flush_cache_all = r4k_flush_cache_all_s64d16i16;
 			flush_cache_mm = r4k_flush_cache_mm_s64d16i16;
 			flush_cache_range = r4k_flush_cache_range_s64d16i16;
@@ -2739,8 +2656,6 @@
 			flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16;
 			break;
 		case 32:
-			clear_page = r4k_clear_page_d32;
-			copy_page = r4k_copy_page_d32;
 			flush_cache_all = r4k_flush_cache_all_s64d32i32;
 			flush_cache_mm = r4k_flush_cache_mm_s64d32i32;
 			flush_cache_range = r4k_flush_cache_range_s64d32i32;
@@ -2751,8 +2666,6 @@
 	case 128:
 		switch(dc_lsize) {
 		case 16:
-			clear_page = r4k_clear_page_d16;
-			copy_page = r4k_copy_page_d16;
 			flush_cache_all = r4k_flush_cache_all_s128d16i16;
 			flush_cache_mm = r4k_flush_cache_mm_s128d16i16;
 			flush_cache_range = r4k_flush_cache_range_s128d16i16;
@@ -2760,8 +2673,6 @@
 			flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16;
 			break;
 		case 32:
-			clear_page = r4k_clear_page_d32;
-			copy_page = r4k_copy_page_d32;
 			flush_cache_all = r4k_flush_cache_all_s128d32i32;
 			flush_cache_mm = r4k_flush_cache_mm_s128d32i32;
 			flush_cache_range = r4k_flush_cache_range_s128d32i32;
@@ -2771,77 +2682,57 @@
 		};
 		break;
 	}
-
-	/* XXX Do these for Indy style caches also.  No need for now ... */
-	flush_cache_pre_dma_out = r4k_flush_cache_pre_dma_out_sc;
-	flush_cache_post_dma_in = r4k_flush_cache_post_dma_in_sc;
+	clear_page = r4k_clear_page;
+	copy_page = r4k_copy_page;
+	dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc;
+	dma_cache_inv = r4k_dma_cache_inv_sc;
 }
 
 typedef int (*probe_func_t)(unsigned long);
-static probe_func_t probe_scache_kseg1;
 
-void ld_mmu_r4xx0(void)
+__initfunc(static inline void setup_scache(unsigned int config))
 {
-	unsigned long cfg = read_32bit_cp0_register(CP0_CONFIG);
+	probe_func_t probe_scache_kseg1;
 	int sc_present = 0;
 
+	/* Maybe the cpu knows about a l2 cache? */
+	probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
+	sc_present = probe_scache_kseg1(config);
+
+	if (sc_present) {
+		setup_scache_funcs();
+		return;
+	}
+
+	setup_noscache_funcs();
+}
+
+static int r4k_user_mode(struct pt_regs *regs)
+{
+	return (regs->cp0_status & ST0_KSU) == KSU_USER;
+}
+
+
+__initfunc(void ld_mmu_r4xx0(void))
+{
+	unsigned long config = read_32bit_cp0_register(CP0_CONFIG);
+
 	printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID));
 
 	set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_CACHABLE_NONCOHERENT);
-//set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_CACHABLE_WA);
-//set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_CACHABLE_NO_WA);
 
-	probe_icache(cfg);
-	probe_dcache(cfg);
+	probe_icache(config);
+	probe_dcache(config);
+	setup_scache(config);
 
 	switch(mips_cputype) {
-	case CPU_R4000PC:
-	case CPU_R4000SC:
-	case CPU_R4000MC:
-	case CPU_R4400PC:
-	case CPU_R4400SC:
-	case CPU_R4400MC:
-		probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache));
-		sc_present = probe_scache_kseg1(cfg);
-		break;
-
-	case CPU_R4600:
-	case CPU_R4640:
+	case CPU_R4600:			/* QED style two way caches? */
 	case CPU_R4700:
-	case CPU_R5000:	/* XXX: We don't handle the true R5000 SCACHE */
+	case CPU_R5000:
 	case CPU_NEVADA:
-		probe_scache_kseg1 = (probe_func_t)
-			(KSEG1ADDR(&probe_scache_eeprom));
-		sc_present = probe_scache_eeprom(cfg);
-
-		/* Try using tags if eeprom gives us bogus data. */
-		if(sc_present == -1) {
-			probe_scache_kseg1 =
-				(probe_func_t) (KSEG1ADDR(&probe_scache));
-			sc_present = probe_scache_kseg1(cfg);
-		}
-		break;
-	};
-
-	if(sc_present == 1
-	   && (mips_cputype == CPU_R4000SC
-               || mips_cputype == CPU_R4000MC
-               || mips_cputype == CPU_R4400SC
-               || mips_cputype == CPU_R4400MC)) {
-		/* Has a true secondary cache. */
-		setup_scache_funcs();
-	} else {
-		/* Lacks true secondary cache. */
-		setup_noscache_funcs();
-		if((mips_cputype != CPU_R5000)) { /* XXX */
-			flush_cache_page =
-				r4k_flush_cache_page_d32i32_r4600;
-			flush_page_to_ram =
-				r4k_flush_page_to_ram_d32i32_r4600;
-		}
+		flush_cache_page = r4k_flush_cache_page_d32i32_r4600;
 	}
 
-	/* XXX Handle true second level cache w/ split I/D */
 	flush_cache_sigtramp = r4k_flush_cache_sigtramp;
 	if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) {
 		flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp;
@@ -2859,6 +2750,8 @@
 	show_regs = r4k_show_regs;
     
         add_wired_entry = r4k_add_wired_entry;
+
+	user_mode = r4k_user_mode;
 
 	flush_cache_all();
 	write_32bit_cp0_register(CP0_WIRED, 0);
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/r6000.c linux/arch/mips/mm/r6000.c
--- v2.1.100/linux/arch/mips/mm/r6000.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/mm/r6000.c	Fri May  8 00:13:24 1998
@@ -1,9 +1,9 @@
-/* $Id: r6000.c,v 1.2 1997/12/02 05:51:08 ralf Exp $
+/* $Id: r6000.c,v 1.4 1998/05/01 01:35:06 ralf Exp $
  * r6000.c: MMU and cache routines for the R6000 processors.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -162,7 +162,12 @@
         /* XXX */
 }
 
-void ld_mmu_r6000(void)
+static int r6000_user_mode(struct pt_regs *regs)
+{
+	return !(regs->cp0_status & 0x4);
+}
+
+__initfunc(void ld_mmu_r6000(void))
 {
 	flush_cache_all = r6000_flush_cache_all;
 	flush_cache_mm = r6000_flush_cache_mm;
@@ -183,6 +188,8 @@
 	show_regs = r6000_show_regs;
     
         add_wired_entry = r6000_add_wired_entry;
+
+	user_mode = r6000_user_mode;
 
 	flush_cache_all();
 	flush_tlb_all();
diff -u --recursive --new-file v2.1.100/linux/arch/mips/mm/tfp.c linux/arch/mips/mm/tfp.c
--- v2.1.100/linux/arch/mips/mm/tfp.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/mm/tfp.c	Fri May  8 00:13:24 1998
@@ -1,9 +1,10 @@
-/* $Id: tfp.c,v 1.2 1997/12/02 05:51:09 ralf Exp $
+/*
  * tfp.c: MMU and cache routines specific to the r8000 (TFP).
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -85,7 +86,12 @@
         /* XXX */
 }
 
-void ld_mmu_tfp(void)
+static int tfp_user_mode(struct pt_regs *regs)
+{
+	return (regs->cp0_status & ST0_KSU) == KSU_USER;
+}
+
+__initfunc(void ld_mmu_tfp(void))
 {
 	flush_cache_all = tfp_flush_cache_all;
 	flush_cache_mm = tfp_flush_cache_mm;
@@ -101,10 +107,11 @@
 
         add_wired_entry = tfp_add_wired_entry;
 
+	user_mode = tfp_user_mode;
+
 	load_pgd = tfp_load_pgd;
 	pgd_init = tfp_pgd_init;
     
 	flush_cache_all();
 	flush_tlb_all();
 }
-
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile
--- v2.1.100/linux/arch/mips/sgi/kernel/Makefile	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/Makefile	Fri May  8 00:13:25 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+# $Id: Makefile,v 1.2 1998/05/01 01:35:13 ralf Exp $
 # Makefile for the SGI specific kernel interface routines
 # under Linux.
 #
@@ -13,8 +13,8 @@
 .S.o:
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
-OBJS  = indy_mc.o indy_hpc.o indy_int.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 system.o indy_timer.o \
+	indyIRQ.o reset.o setup.o time.o
 
 all: sgikern.a
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S
--- v2.1.100/linux/arch/mips/sgi/kernel/indyIRQ.S	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/indyIRQ.S	Fri May  8 00:13:25 1998
@@ -1,4 +1,4 @@
-/* $Id: indyIRQ.S,v 1.2 1997/09/20 19:20:14 root Exp $
+/* $Id: indyIRQ.S,v 1.3 1998/05/01 01:35:14 ralf Exp $
  * indyIRQ.S: Interrupt exception dispatch code for FullHouse and
  *            Guiness.
  *
@@ -68,7 +68,6 @@
 
 	/* Wheee, a timer interrupt. */
 	move	a0, sp
-	addiu	t0, s7, 1
 	jal	indy_timer_interrupt
 	 nop				# delay slot
 
@@ -117,7 +116,6 @@
 	 */
 	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
 	beq	a0, zero, 1f
-	 addiu	t0, s7, 1
 
 	/* Must be one of the 8254 timers... */
 	move	a0, sp
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c
--- v2.1.100/linux/arch/mips/sgi/kernel/indy_hpc.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/indy_hpc.c	Fri May  8 00:13:25 1998
@@ -1,8 +1,11 @@
-/* $Id: indy_hpc.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * indy_hpc.c: Routines for generic manipulation of the HPC controllers.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: indy_hpc.c,v 1.2 1998/05/01 01:35:14 ralf Exp $
  */
+#include <linux/init.h>
 
 #include <asm/addrspace.h>
 #include <asm/ptrace.h>
@@ -38,7 +41,7 @@
 	hpc3mregs->write2 = write2;
 }
 
-void sgihpc_init(void)
+__initfunc(void sgihpc_init(void))
 {
 	unsigned long sid, crev, brev;
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c
--- v2.1.100/linux/arch/mips/sgi/kernel/indy_int.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/indy_int.c	Fri May  8 00:13:25 1998
@@ -4,10 +4,10 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: indy_int.c,v 1.4 1997/09/20 19:20:15 root Exp $
+ * $Id: indy_int.c,v 1.6 1998/05/01 01:35:15 ralf Exp $
  */
 #include <linux/config.h>
-
+#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
@@ -55,6 +55,7 @@
 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;
 
@@ -230,7 +231,7 @@
 		if (!action) 
 			continue;
 		len += sprintf(buf+len, "%2d: %8d %c %s",
-			num, kstat.interrupts[num],
+			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
@@ -245,7 +246,7 @@
 		if (!action) 
 			continue;
 		len += sprintf(buf+len, "%2d: %8d %c %s",
-			num, kstat.interrupts[num],
+			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
@@ -274,7 +275,7 @@
 
 	cpu = smp_processor_id();
 	irq_enter(cpu, irq);
-	kstat.interrupts[irq]++;
+	kstat.irqs[0][irq]++;
 
 	printk("Got irq %d, press a key.", irq);
 	prom_getchar();
@@ -416,7 +417,7 @@
 	printk("Trying to free free IRQ%d\n",irq);
 }
 
-void init_IRQ(void)
+__initfunc(void init_IRQ(void))
 {
 	irq_setup();
 }
@@ -440,7 +441,7 @@
 	}
 
 	irq_enter(cpu, irq);
-	kstat.interrupts[irq + 16]++;
+	kstat.irqs[0][irq + 16]++;
 	action->handler(irq, action->dev_id, regs);
 	irq_exit(cpu, irq);
 }
@@ -464,7 +465,7 @@
 		action = local_irq_action[irq];
 	}
 	irq_enter(cpu, irq);
-	kstat.interrupts[irq + 24]++;
+	kstat.irqs[0][irq + 24]++;
 	action->handler(irq, action->dev_id, regs);
 	irq_exit(cpu, irq);
 }
@@ -475,7 +476,7 @@
 	int irq = 6;
 
 	irq_enter(cpu, irq);
-	kstat.interrupts[irq]++;
+	kstat.irqs[0][irq]++;
 	printk("Got a bus error IRQ, shouldn't happen yet\n");
 	show_regs(regs);
 	printk("Spinning...\n");
@@ -494,7 +495,7 @@
 	return 0;
 }
 
-void sgint_init(void)
+__initfunc(void sgint_init(void))
 {
 	int i;
 #ifdef CONFIG_REMOTE_DEBUG
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c
--- v2.1.100/linux/arch/mips/sgi/kernel/indy_mc.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/indy_mc.c	Fri May  8 00:13:25 1998
@@ -1,8 +1,12 @@
-/* $Id: indy_mc.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * indy_mc.c: Routines for manipulating the INDY memory controller.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: indy_mc.c,v 1.3 1998/05/04 09:18:37 ralf Exp $
  */
+#include <linux/init.h>
+#include <linux/kernel.h>
 
 #include <asm/addrspace.h>
 #include <asm/ptrace.h>
@@ -43,7 +47,7 @@
 	};
 }
 
-void sgimc_init(void)
+__initfunc(void sgimc_init(void))
 {
 	unsigned long tmpreg;
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c
--- v2.1.100/linux/arch/mips/sgi/kernel/indy_sc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sgi/kernel/indy_sc.c	Fri May  8 00:13:25 1998
@@ -0,0 +1,227 @@
+/*
+ * indy_sc.c: Indy cache managment functions.
+ *
+ * Copyright (C) 1997 Ralf Baechle (ralf@gnu.org),
+ * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com).
+ *
+ * $Id: indy_sc.c,v 1.4 1998/05/04 09:12:57 ralf Exp $
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/autoconf.h>
+
+#include <asm/bcache.h>
+#include <asm/sgi.h>
+#include <asm/sgimc.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/sgialib.h>
+#include <asm/mmu_context.h>
+
+/* Secondary cache size in bytes, if present.  */
+static unsigned long scache_size;
+
+#undef DEBUG_CACHE
+
+#define SC_SIZE 0x00080000
+#define SC_LINE 32
+#define CI_MASK (SC_SIZE - SC_LINE)
+#define SC_ROUND(n) ((n) + SC_LINE - 1)
+#define SC_INDEX(n) ((n) & CI_MASK)
+
+static inline void indy_sc_wipe(unsigned long first, unsigned long last)
+{
+	__asm__ __volatile__("
+		.set	noreorder
+		.set	mips3
+		.set	noat
+		li	$1, 0x80	# Go 64 bit
+		mtc0	$1, $12
+
+		dli	$1, 0x9000000080000000
+		or	%0, $1		# first line to flush
+		or	%1, $1		# last line to flush
+		.set	at
+
+1:		sw	$0, 0(%0)
+		bne	%0, %1, 1b
+		daddu	%0, 32
+
+		mtc0	$0, $12		# Back to 32 bit
+		nop; nop; nop; nop;
+		.set mips0
+		.set reorder"
+		: "=r" (first), "=r" (last)
+		: "0" (first), "1" (last)
+		: "$1");
+}
+
+static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size)
+{
+	unsigned long first_line, last_line;
+	unsigned int flags;
+
+#ifdef DEBUG_CACHE
+	printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
+#endif
+	/* Which lines to flush?  */
+	first_line = SC_INDEX(addr);
+	last_line = SC_INDEX(SC_ROUND(addr + size));
+
+	__save_and_cli(flags);
+	if (first_line <= last_line) {
+		indy_sc_wipe(first_line, last_line);
+		goto out;
+	}
+
+	/* 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);
+out:
+	__restore_flags(flags);
+}
+
+static void indy_sc_enable(void)
+{
+	unsigned long addr, tmp1, tmp2;
+
+	/* This is really cool... */
+#ifdef DEBUG_CACHE
+	printk("Enabling R4600 SCACHE\n");
+#endif
+	__asm__ __volatile__("
+		.set noreorder
+		.set mips3
+		mfc0	%2, $12
+		nop; nop; nop; nop;
+		li	%1, 0x80
+		mtc0	%1, $12
+		nop; nop; nop; nop;
+		li	%0, 0x1
+		dsll	%0, 31
+		lui	%1, 0x9000
+		dsll32	%1, 0
+		or	%0, %1, %0
+		sb	$0, 0(%0)
+		mtc0	$0, $12
+		nop; nop; nop; nop;
+		mtc0	%2, $12
+		nop; nop; nop; nop;
+		.set mips0
+		.set reorder"
+		: "=r" (tmp1), "=r" (tmp2), "=r" (addr));
+}
+
+static void indy_sc_disable(void)
+{
+	unsigned long tmp1, tmp2, tmp3;
+
+#ifdef DEBUG_CACHE
+	printk("Disabling R4600 SCACHE\n");
+#endif
+	__asm__ __volatile__("
+		.set noreorder
+		.set mips3
+		li	%0, 0x1
+		dsll	%0, 31
+		lui	%1, 0x9000
+		dsll32	%1, 0
+		or	%0, %1, %0
+		mfc0	%2, $12
+		nop; nop; nop; nop;
+		li	%1, 0x80
+		mtc0	%1, $12
+		nop; nop; nop; nop;
+		sh	$0, 0(%0)
+		mtc0	$0, $12
+		nop; nop; nop; nop;
+		mtc0	%2, $12
+		nop; nop; nop; nop;
+		.set mips2
+		.set reorder
+        " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+}
+
+__initfunc(static inline int indy_sc_probe(void))
+{
+	volatile unsigned int *cpu_control;
+	unsigned short cmd = 0xc220;
+	unsigned long data = 0;
+	int i, n;
+
+#ifdef __MIPSEB__
+	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034);
+#else
+	cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030);
+#endif
+#define DEASSERT(bit) (*(cpu_control) &= (~(bit)))
+#define ASSERT(bit) (*(cpu_control) |= (bit))
+#define DELAY  for(n = 0; n < 100000; n++) __asm__ __volatile__("")
+	DEASSERT(SGIMC_EEPROM_PRE);
+	DEASSERT(SGIMC_EEPROM_SDATAO);
+	DEASSERT(SGIMC_EEPROM_SECLOCK);
+	DEASSERT(SGIMC_EEPROM_PRE);
+	DELAY;
+	ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK);
+	for(i = 0; i < 11; i++) {
+		if(cmd & (1<<15))
+			ASSERT(SGIMC_EEPROM_SDATAO);
+		else
+			DEASSERT(SGIMC_EEPROM_SDATAO);
+		DEASSERT(SGIMC_EEPROM_SECLOCK);
+		ASSERT(SGIMC_EEPROM_SECLOCK);
+		cmd <<= 1;
+	}
+	DEASSERT(SGIMC_EEPROM_SDATAO);
+	for(i = 0; i < (sizeof(unsigned short) * 8); i++) {
+		unsigned int tmp;
+
+		DEASSERT(SGIMC_EEPROM_SECLOCK);
+		DELAY;
+		ASSERT(SGIMC_EEPROM_SECLOCK);
+		DELAY;
+		data <<= 1;
+		tmp = *cpu_control;
+		if(tmp & SGIMC_EEPROM_SDATAI)
+			data |= 1;
+	}
+	DEASSERT(SGIMC_EEPROM_SECLOCK);
+	DEASSERT(SGIMC_EEPROM_CSEL);
+	ASSERT(SGIMC_EEPROM_PRE);
+	ASSERT(SGIMC_EEPROM_SECLOCK);
+
+	data <<= PAGE_SHIFT;
+	if (data == 0)
+		return 0;
+
+	scache_size = data;
+
+	printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n",
+	       scache_size >> 10);
+
+	return 1;
+}
+
+/* XXX Check with wje if the Indy caches can differenciate between
+   writeback + invalidate and just invalidate.  */
+struct bcache_ops indy_sc_ops = {
+	indy_sc_enable,
+	indy_sc_disable,
+	indy_sc_wback_invalidate,
+	indy_sc_wback_invalidate
+};
+
+__initfunc(void indy_sc_init(void))
+{
+	if (indy_sc_probe()) {
+		indy_sc_enable();
+		bcops = &indy_sc_ops;
+	}
+}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c
--- v2.1.100/linux/arch/mips/sgi/kernel/indy_timer.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/indy_timer.c	Fri May  8 00:13:25 1998
@@ -3,10 +3,10 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: indy_timer.c,v 1.3 1997/08/11 04:37:09 ralf Exp $
+ * $Id: indy_timer.c,v 1.5 1998/05/01 01:35:17 ralf Exp $
  */
-
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
@@ -98,15 +98,25 @@
 }
 
 static long last_rtc_update = 0;
+unsigned long missed_heart_beats = 0;
 
 void indy_timer_interrupt(struct pt_regs *regs)
 {
+	unsigned long count;
 	int irq = 7;
 
 	/* Ack timer and compute new compare. */
-	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+	count = read_32bit_cp0_register(CP0_COUNT);
+	/* This has races.  */
+	if ((count - r4k_cur) >= r4k_offset) {
+		/* If this happens to often we'll need to compensate.  */
+		missed_heart_beats++;
+		r4k_cur = count + r4k_offset;
+	}
+        else
+            r4k_cur += r4k_offset;
 	ack_r4ktimer(r4k_cur);
-	kstat.interrupts[irq]++;
+	kstat.irqs[0][irq]++;
 	do_timer(regs);
 
 	/* We update the Dallas time of day approx. every 11 minutes,
@@ -123,8 +133,8 @@
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 }
 
-static inline unsigned long dosample(volatile unsigned char *tcwp,
-				     volatile unsigned char *tc2p)
+static unsigned long dosample(volatile unsigned char *tcwp,
+                              volatile unsigned char *tc2p)
 {
 	unsigned long ct0, ct1;
 	unsigned char msb, lsb;
@@ -138,16 +148,12 @@
 	ct0 = read_32bit_cp0_register(CP0_COUNT);
 
 	/* Latch and spin until top byte of counter2 is zero */
-	*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
-	ct1 = read_32bit_cp0_register(CP0_COUNT);
-	lsb = *tc2p;
-	msb = *tc2p;
-	while(msb) {
+	do {
 		*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
-		ct1 = read_32bit_cp0_register(CP0_COUNT);
 		lsb = *tc2p;
 		msb = *tc2p;
-	}
+		ct1 = read_32bit_cp0_register(CP0_COUNT);
+	} while(msb);
 
 	/* Stop the counter. */
 	*tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST);
@@ -189,7 +195,7 @@
 	  )*60 + sec; /* finally seconds */
 }
 
-unsigned long get_indy_time(void)
+__initfunc(static unsigned long get_indy_time(void))
 {
 	struct indy_clock *clock = INDY_CLOCK_REGS;
 	unsigned int year, mon, day, hour, min, sec;
@@ -234,7 +240,7 @@
 
 #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
 
-void indy_timer_init(void)
+__initfunc(void indy_timer_init(void))
 {
 	struct sgi_ioc_timers *p;
 	volatile unsigned char *tcwp, *tc2p;
@@ -254,11 +260,9 @@
 	tc2p = &p->tcnt2;
 
 	printk("calculating r4koff... ");
-	r4k_offset = dosample(tcwp, tc2p);  /* First sample. */
-	dosample(tcwp, tc2p);               /* Eat one... */
-	r4k_offset += dosample(tcwp, tc2p); /* Second sample. */
-	r4k_offset = (r4k_offset >> 1);     /* Get average. */
-	r4k_offset = HZ * r4k_offset;       /* Multiply by HZ */
+	dosample(tcwp, tc2p);			/* First sample. */
+	dosample(tcwp, tc2p);			/* Eat one.	*/
+	r4k_offset = dosample(tcwp, tc2p);	/* Second sample. */
 
 	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
 
@@ -278,7 +282,7 @@
 	int irq = 4;
 
 	irq_enter(cpu, irq);
-	kstat.interrupts[irq]++;
+	kstat.irqs[0][irq]++;
 	printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
 	prom_getchar();
 	prom_imode();
@@ -303,4 +307,3 @@
 	time_esterror = MAXPHASE;
 	sti();
 }
-
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c
--- v2.1.100/linux/arch/mips/sgi/kernel/reset.c	Thu Jun 26 12:33:38 1997
+++ linux/arch/mips/sgi/kernel/reset.c	Fri May  8 00:13:25 1998
@@ -1,25 +1,31 @@
 /*
- *  linux/arch/mips/sgi/kernel/process.c
- *
  *  Reset a SGI.
+ *
+ * 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
+ *
+ * $Id: reset.c,v 1.3 1998/05/01 01:35:18 ralf Exp $
  */
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/reboot.h>
+#include <asm/sgialib.h>
 
 /* XXX How to pass the reboot command to the firmware??? */
 void sgi_machine_restart(char *command)
 {
-        for(;;)
-                prom_imode();
+	prom_reboot();
 }
 
 void sgi_machine_halt(void)
 {
-	/* XXX */
+	prom_imode();
 }
 
 void sgi_machine_power_off(void)
 {
-	/* XXX */
+	prom_powerdown();
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c
--- v2.1.100/linux/arch/mips/sgi/kernel/setup.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/setup.c	Fri May  8 00:13:25 1998
@@ -3,12 +3,14 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: setup.c,v 1.5 1997/09/13 02:19:18 ralf Exp $
+ * $Id: setup.c,v 1.5 1998/05/01 01:35:19 ralf Exp $
  */
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
 #include <asm/addrspace.h>
+#include <asm/bcache.h>
 #include <asm/keyboard.h>
 #include <asm/reboot.h>
 #include <asm/vector.h>
@@ -49,7 +51,7 @@
 	return sgi_kh->command;
 }
 
-static void sgi_keyboard_setup(void)
+__initfunc(static void sgi_keyboard_setup(void))
 {
 	kbd_read_input = sgi_read_input;
 	kbd_write_output = sgi_write_output;
@@ -57,12 +59,12 @@
 	kbd_read_status = sgi_read_status;
 }
 
-static void sgi_irq_setup(void)
+__initfunc(static void sgi_irq_setup(void))
 {
 	sgint_init();
 }
 
-void sgi_setup(void)
+__initfunc(void sgi_setup(void))
 {
 	char *ctype;
 
@@ -82,6 +84,9 @@
 
 	/* Init INDY memory controller. */
 	sgimc_init();
+
+	/* Now enable boardcaches, if any. */
+	indy_sc_init();
 
 	/* ARCS console environment variable is set to "g?" for
 	 * graphics console, it is set to "d" for the first serial
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c
--- v2.1.100/linux/arch/mips/sgi/kernel/system.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/system.c	Fri May  8 00:13:25 1998
@@ -3,8 +3,9 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: system.c,v 1.3 1997/09/13 02:19:18 ralf Exp $
+ * $Id: system.c,v 1.4 1998/05/01 01:35:19 ralf Exp $
  */
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -56,7 +57,7 @@
 
 #define NUM_CPUS 9 /* for now */
 
-static enum sgi_mach string_to_mach(char *s)
+__initfunc(static enum sgi_mach string_to_mach(char *s))
 {
 	int i;
 
@@ -71,7 +72,7 @@
 	return (enum sgi_mach) 0;
 }
 
-static int string_to_cpu(char *s)
+__initfunc(static int string_to_cpu(char *s))
 {
 	int i;
 
@@ -90,7 +91,7 @@
  * We' call this early before loadmmu().  If we do the other way around
  * the firmware will crash and burn.
  */
-void sgi_sysinit(void)
+__initfunc(void sgi_sysinit(void))
 {
 	pcomponent *p, *toplev, *cpup = 0;
 	int cputype = -1;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c
--- v2.1.100/linux/arch/mips/sgi/kernel/time.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/kernel/time.c	Fri May  8 00:13:25 1998
@@ -1,13 +1,14 @@
-/* $Id: time.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/* $Id: time.c,v 1.2 1998/05/01 01:35:20 ralf Exp $
  * time.c: Generic SGI time_init() code, this will dispatch to the
  *         appropriate per-architecture time/counter init code.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
+#include <linux/init.h>
 
 extern void indy_timer_init(void);
 
-void time_init(void)
+__initfunc(void time_init(void))
 {
 	/* XXX assume INDY for now XXX */
 	indy_timer_init();
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/Makefile linux/arch/mips/sgi/prom/Makefile
--- v2.1.100/linux/arch/mips/sgi/prom/Makefile	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/Makefile	Fri May  8 00:13:25 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+# $Id: Makefile,v 1.2 1998/05/01 01:35:22 ralf Exp $
 # Makefile for the SGI arcs prom monitor library routines
 # under Linux.
 #
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/cmdline.c linux/arch/mips/sgi/prom/cmdline.c
--- v2.1.100/linux/arch/mips/sgi/prom/cmdline.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/cmdline.c	Fri May  8 00:13:25 1998
@@ -1,9 +1,11 @@
-/* $Id: cmdline.c,v 1.2 1997/12/02 05:51:09 ralf Exp $
+/*
  * 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/05/01 01:35:22 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 
@@ -14,7 +16,7 @@
 
 extern char arcs_cmdline[CL_SIZE];
 
-char *prom_getcmdline(void)
+__initfunc(char *prom_getcmdline(void))
 {
 	return &(arcs_cmdline[0]);
 }
@@ -29,7 +31,7 @@
 };
 #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
 
-void prom_init_cmdline(void)
+__initfunc(void prom_init_cmdline(void))
 {
 	char *cp;
 	int actr, i;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/console.c linux/arch/mips/sgi/prom/console.c
--- v2.1.100/linux/arch/mips/sgi/prom/console.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/console.c	Fri May  8 00:13:25 1998
@@ -1,12 +1,14 @@
-/* $Id: console.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * console.c: SGI arcs console code.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
+ *
+ * $Id: console.c,v 1.2 1998/05/01 01:35:23 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <asm/sgialib.h>
 
-void prom_putchar(char c)
+__initfunc(void prom_putchar(char c))
 {
 	long cnt;
 	char it = c;
@@ -14,7 +16,7 @@
 	romvec->write(1, &it, 1, &cnt);
 }
 
-char prom_getchar(void)
+__initfunc(char prom_getchar(void))
 {
 	long cnt;
 	char c;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/env.c linux/arch/mips/sgi/prom/env.c
--- v2.1.100/linux/arch/mips/sgi/prom/env.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/env.c	Fri May  8 00:13:25 1998
@@ -1,20 +1,22 @@
-/* $Id: env.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * env.c: ARCS environment variable routines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: env.c,v 1.2 1998/05/01 01:35:24 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 
 #include <asm/sgialib.h>
 
-char *prom_getenv(char *name)
+__initfunc(char *prom_getenv(char *name))
 {
 	return romvec->get_evar(name);
 }
 
-long prom_setenv(char *name, char *value)
+__initfunc(long prom_setenv(char *name, char *value))
 {
 	return romvec->set_evar(name, value);
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/file.c linux/arch/mips/sgi/prom/file.c
--- v2.1.100/linux/arch/mips/sgi/prom/file.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/file.c	Fri May  8 00:13:25 1998
@@ -1,58 +1,59 @@
-/* $Id: file.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * file.c: ARCS firmware interface to files.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: file.c,v 1.2 1998/05/01 01:35:24 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <asm/sgialib.h>
 
-long prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num,
-		     unsigned long *cnt)
+__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);
 }
 
-long prom_open(char *name, enum linux_omode md, unsigned long *fd)
+__initfunc(long prom_open(char *name, enum linux_omode md, unsigned long *fd))
 {
 	return romvec->open(name, md, fd);
 }
 
-long prom_close(unsigned long fd)
+__initfunc(long prom_close(unsigned long fd))
 {
 	return romvec->close(fd);
 }
 
-long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)
+__initfunc(long prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
 {
 	return romvec->read(fd, buf, num, cnt);
 }
 
-long prom_getrstatus(unsigned long fd)
+__initfunc(long prom_getrstatus(unsigned long fd))
 {
 	return romvec->get_rstatus(fd);
 }
 
-long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt)
+__initfunc(long prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt))
 {
 	return romvec->write(fd, buf, num, cnt);
 }
 
-long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm)
+__initfunc(long prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm))
 {
 	return romvec->seek(fd, off, sm);
 }
 
-long prom_mount(char *name, enum linux_mountops op)
+__initfunc(long prom_mount(char *name, enum linux_mountops op))
 {
 	return romvec->mount(name, op);
 }
 
-long prom_getfinfo(unsigned long fd, struct linux_finfo *buf)
+__initfunc(long prom_getfinfo(unsigned long fd, struct linux_finfo *buf))
 {
 	return romvec->get_finfo(fd, buf);
 }
 
-long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk)
+__initfunc(long prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk))
 {
 	return romvec->set_finfo(fd, flags, msk);
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/init.c linux/arch/mips/sgi/prom/init.c
--- v2.1.100/linux/arch/mips/sgi/prom/init.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/init.c	Fri May  8 00:13:25 1998
@@ -1,9 +1,11 @@
-/* $Id: init.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * init.c: PROM library initialisation code.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: init.c,v 1.2 1998/05/01 01:35:25 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 
 #include <asm/sgialib.h>
@@ -19,7 +21,7 @@
 
 extern void prom_testtree(void);
 
-int prom_init(int argc, char **argv, char **envp)
+__initfunc(int prom_init(int argc, char **argv, char **envp))
 {
 	struct linux_promblock *pb;
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/memory.c linux/arch/mips/sgi/prom/memory.c
--- v2.1.100/linux/arch/mips/sgi/prom/memory.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/memory.c	Fri May  8 00:13:25 1998
@@ -1,10 +1,12 @@
-/* $Id: memory.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * 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/05/01 01:35:25 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/sched.h>
@@ -18,7 +20,7 @@
 
 /* #define DEBUG */
 
-struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr)
+__initfunc(struct linux_mdesc *prom_getmdesc(struct linux_mdesc *curr))
 {
 	return romvec->get_mdesc(curr);
 }
@@ -38,12 +40,12 @@
 
 static struct prom_pmemblock prom_pblocks[PROM_MAX_PMEMBLOCKS];
 
-struct prom_pmemblock *prom_getpblock_array(void)
+__initfunc(struct prom_pmemblock *prom_getpblock_array(void))
 {
 	return &prom_pblocks[0];
 }
 
-static void prom_setup_memupper(void)
+__initfunc(static void prom_setup_memupper(void))
 {
 	struct prom_pmemblock *p, *highest;
 
@@ -60,7 +62,7 @@
 #endif
 }
 
-void prom_meminit(void)
+__initfunc(void prom_meminit(void))
 {
 	struct linux_mdesc *p;
 	int totram;
@@ -104,7 +106,7 @@
 }
 
 /* Called from mem_init() to fixup the mem_map page settings. */
-void prom_fixup_mem_map(unsigned long start, unsigned long end)
+__initfunc(void prom_fixup_mem_map(unsigned long start, unsigned long end))
 {
 	struct prom_pmemblock *p;
 	int i, nents;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/misc.c linux/arch/mips/sgi/prom/misc.c
--- v2.1.100/linux/arch/mips/sgi/prom/misc.c	Thu Jun 26 12:33:38 1997
+++ linux/arch/mips/sgi/prom/misc.c	Fri May  8 00:13:25 1998
@@ -2,10 +2,14 @@
  * misc.c: Miscellaneous ARCS PROM routines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: misc.c,v 1.2 1998/05/01 01:35:26 ralf Exp $
  */
 #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>
@@ -15,91 +19,59 @@
 extern void *sgiwd93_host;
 extern void reset_wd33c93(void *instance);
 
-static inline void shutoff_r4600_cache(void)
-{
-	unsigned long tmp1, tmp2, tmp3;
-
-	if(mips_cputype != CPU_R4600 &&
-	   mips_cputype != CPU_R4640 &&
-	   mips_cputype != CPU_R4700)
-		return;
-	printk("Disabling R4600 SCACHE\n");
-	__asm__ __volatile__("
-	.set noreorder
-	.set mips3
-	li	%0, 0x1
-	dsll	%0, 31
-	lui	%1, 0x9000
-	dsll32	%1, 0
-	or	%0, %1, %0
-	mfc0	%2, $12
-	nop; nop; nop; nop;
-	li	%1, 0x80
-	mtc0	%1, $12
-	nop; nop; nop; nop;
-	sh	$0, 0(%0)
-	mtc0	$0, $12
-	nop; nop; nop; nop;
-	mtc0	%2, $12
-	nop; nop; nop; nop;
-	.set mips2
-	.set reorder
-        " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
-}
-
 void prom_halt(void)
 {
-	shutoff_r4600_cache();
+	bcops->bc_disable();
 	initialize_kbd();
+	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
 #endif
-	cli();
 	romvec->halt();
 }
 
 void prom_powerdown(void)
 {
-	shutoff_r4600_cache();
+	bcops->bc_disable();
 	initialize_kbd();
+	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
 #endif
-	cli();
 	romvec->pdown();
 }
 
 /* XXX is this a soft reset basically? XXX */
 void prom_restart(void)
 {
-	shutoff_r4600_cache();
+	bcops->bc_disable();
 	initialize_kbd();
+	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
 #endif
-	cli();
 	romvec->restart();
 }
 
 void prom_reboot(void)
 {
-	shutoff_r4600_cache();
+	bcops->bc_disable();
 	initialize_kbd();
+	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
 #endif
-	cli();
 	romvec->reboot();
 }
 
 void prom_imode(void)
 {
-	shutoff_r4600_cache();
+	bcops->bc_disable();
 	initialize_kbd();
+	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
 #endif
-	cli();
 	romvec->imode();
 }
 
@@ -113,7 +85,7 @@
 	return romvec->get_sysid();
 }
 
-void prom_cacheflush(void)
+__initfunc(void prom_cacheflush(void))
 {
 	romvec->cache_flush();
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/printf.c linux/arch/mips/sgi/prom/printf.c
--- v2.1.100/linux/arch/mips/sgi/prom/printf.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/printf.c	Fri May  8 00:13:25 1998
@@ -1,18 +1,19 @@
-/* $Id: printf.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * 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/05/01 01:35:27 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 
 #include <asm/sgialib.h>
 
 static char ppbuf[1024];
 
-void
-prom_printf(char *fmt, ...)
+__initfunc(void prom_printf(char *fmt, ...))
 {
 	va_list args;
 	char ch, *bptr;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/salone.c linux/arch/mips/sgi/prom/salone.c
--- v2.1.100/linux/arch/mips/sgi/prom/salone.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/salone.c	Fri May  8 00:13:25 1998
@@ -1,24 +1,25 @@
-/* $Id: salone.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * 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/05/01 01:35:27 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <asm/sgialib.h>
 
-long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr)
+__initfunc(long prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr))
 {
 	return romvec->load(name, end, pc, eaddr);
 }
 
-long prom_invoke(unsigned long pc, unsigned long sp, long argc,
-		 char **argv, char **envp)
+__initfunc(long prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp))
 {
 	return romvec->invoke(pc, sp, argc, argv, envp);
 }
 
-long prom_exec(char *name, long argc, char **argv, char **envp)
+__initfunc(long prom_exec(char *name, long argc, char **argv, char **envp))
 {
 	return romvec->exec(name, argc, argv, envp);
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/tags.c linux/arch/mips/sgi/prom/tags.c
--- v2.1.100/linux/arch/mips/sgi/prom/tags.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/tags.c	Fri May  8 00:13:25 1998
@@ -1,10 +1,12 @@
-/* $Id: tags.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * 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/05/01 01:35:28 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 
@@ -43,7 +45,7 @@
 	/* XXX COLOSTOMY BAG!!!! XXX */
 };
 
-void prom_setup_archtags(void)
+__initfunc(void prom_setup_archtags(void))
 {
 	tag_def *tdp = &taglist_sgi_indy[0];
 	tag *tp;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/time.c linux/arch/mips/sgi/prom/time.c
--- v2.1.100/linux/arch/mips/sgi/prom/time.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/time.c	Fri May  8 00:13:25 1998
@@ -1,17 +1,19 @@
-/* $Id: time.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * 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/05/01 01:35:29 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <asm/sgialib.h>
 
-struct linux_tinfo *prom_gettinfo(void)
+__initfunc(struct linux_tinfo *prom_gettinfo(void))
 {
 	return romvec->get_tinfo();
 }
 
-unsigned long prom_getrtime(void)
+__initfunc(unsigned long prom_getrtime(void))
 {
 	return romvec->get_rtime();
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sgi/prom/tree.c linux/arch/mips/sgi/prom/tree.c
--- v2.1.100/linux/arch/mips/sgi/prom/tree.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sgi/prom/tree.c	Fri May  8 00:13:25 1998
@@ -1,48 +1,50 @@
-/* $Id: tree.c,v 1.1.1.1 1997/06/01 03:16:40 ralf Exp $
+/*
  * tree.c: PROM component device tree code.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: tree.c,v 1.2 1998/05/01 01:35:30 ralf Exp $
  */
-
+#include <linux/init.h>
 #include <asm/sgialib.h>
 
 #define DEBUG_PROM_TREE
 
-pcomponent *prom_getsibling(pcomponent *this)
+__initfunc(pcomponent *prom_getsibling(pcomponent *this))
 {
 	if(this == PROM_NULL_COMPONENT)
 		return PROM_NULL_COMPONENT;
 	return romvec->next_component(this);
 }
 
-pcomponent *prom_getchild(pcomponent *this)
+__initfunc(pcomponent *prom_getchild(pcomponent *this))
 {
 	return romvec->child_component(this);
 }
 
-pcomponent *prom_getparent(pcomponent *child)
+__initfunc(pcomponent *prom_getparent(pcomponent *child))
 {
 	if(child == PROM_NULL_COMPONENT)
 		return PROM_NULL_COMPONENT;
 	return romvec->parent_component(child);
 }
 
-long prom_getcdata(void *buffer, pcomponent *this)
+__initfunc(long prom_getcdata(void *buffer, pcomponent *this))
 {
 	return romvec->component_data(buffer, this);
 }
 
-pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data)
+__initfunc(pcomponent *prom_childadd(pcomponent *this, pcomponent *tmp, void *data))
 {
 	return romvec->child_add(this, tmp, data);
 }
 
-long prom_delcomponent(pcomponent *this)
+__initfunc(long prom_delcomponent(pcomponent *this))
 {
 	return romvec->comp_del(this);
 }
 
-pcomponent *prom_componentbypath(char *path)
+__initfunc(pcomponent *prom_componentbypath(char *path))
 {
 	return romvec->component_by_path(path);
 }
@@ -72,7 +74,7 @@
 	"input", "output"
 };
 
-static void dump_component(pcomponent *p)
+__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],
@@ -81,7 +83,7 @@
 		    p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname);
 }
 
-static void traverse(pcomponent *p, int op)
+__initfunc(static void traverse(pcomponent *p, int op))
 {
 	dump_component(p);
 	if(prom_getchild(p))
@@ -90,7 +92,7 @@
 		traverse(prom_getsibling(p), 1);
 }
 
-void prom_testtree(void)
+__initfunc(void prom_testtree(void))
 {
 	pcomponent *p;
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile
--- v2.1.100/linux/arch/mips/sni/Makefile	Thu Jun 26 12:33:38 1997
+++ linux/arch/mips/sni/Makefile	Fri May  8 00:13:25 1998
@@ -5,6 +5,8 @@
 # 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 1998/05/01 01:35:32 ralf Exp $
+#
 
 .S.s:
 	$(CPP) $(CFLAGS) $< -o $*.s
@@ -13,7 +15,7 @@
 
 all: sni.o
 O_TARGET := sni.o
-O_OBJS	 := hw-access.o int-handler.o io.o pci.o reset.o setup.o
+O_OBJS	 := hw-access.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o
 
 int-handler.o: int-handler.S
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/hw-access.c linux/arch/mips/sni/hw-access.c
--- v2.1.100/linux/arch/mips/sni/hw-access.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sni/hw-access.c	Fri May  8 00:13:25 1998
@@ -5,11 +5,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  *
- * $Id: hw-access.c,v 1.3 1997/07/29 17:46:46 ralf Exp $
+ * $Id: hw-access.c,v 1.4 1998/05/01 01:35:32 ralf Exp $
  */
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <linux/kbdcntrlr.h>
 #include <linux/kernel.h>
 #include <linux/linkage.h>
@@ -182,7 +183,7 @@
 	return inb(KBD_STATUS_REG);
 }
 
-void sni_rm200_keyboard_setup(void)
+__initfunc(void sni_rm200_keyboard_setup(void))
 {
 	kbd_read_input = sni_read_input;
 	kbd_write_output = sni_write_output;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S
--- v2.1.100/linux/arch/mips/sni/int-handler.S	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sni/int-handler.S	Fri May  8 00:13:25 1998
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1994 - 1997 by Ralf Baechle
  *
- * $Id: int-handler.S,v 1.3 1997/12/01 16:39:24 ralf Exp $
+ * $Id: int-handler.S,v 1.3 1998/05/01 01:35:33 ralf Exp $
  */
 #include <asm/asm.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c
--- v2.1.100/linux/arch/mips/sni/io.c	Thu Jun 26 12:33:38 1997
+++ linux/arch/mips/sni/io.c	Fri May  8 00:13:25 1998
@@ -4,6 +4,8 @@
  * for more details.
  *
  * Low level I/O functions for SNI.
+ *
+ * $Id: io.c,v 1.2 1998/05/01 01:35:34 ralf Exp $
  */
 #include <linux/string.h>
 #include <asm/mipsconfig.h>
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c
--- v2.1.100/linux/arch/mips/sni/pci.c	Mon Apr  6 17:40:59 1998
+++ linux/arch/mips/sni/pci.c	Fri May  8 00:13:25 1998
@@ -4,9 +4,11 @@
  * for more details.
  *
  * SNI specific PCI support for RM200/RM300.
+ *
+ * $Id: pci.c,v 1.4 1998/05/01 01:35:34 ralf Exp $
  */
 #include <linux/config.h>
-#include <linux/init.h>
+#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
@@ -15,13 +17,14 @@
 
 #ifdef CONFIG_PCI
 
-extern inline u32 mkaddr(unsigned char bus, unsigned char dev_fn,
-                         unsigned char where)
-{
-	return ((bus    & 0xff) << 0x10) |
-	       ((dev_fn & 0xff) << 0x08) |
-	       (where  & 0xfc);
-}
+#define mkaddr(bus, dev_fn, where)                                           \
+do {                                                                         \
+	if (bus == 0 && dev_fn >= PCI_DEVFN(8, 0))                           \
+		return -1;                                                   \
+	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = ((bus    & 0xff) << 0x10) |  \
+	                                        ((dev_fn & 0xff) << 0x08) |  \
+	                                        (where  & 0xfc);             \
+} while(0);
 
 static unsigned long sni_rm200_pcibios_fixup (unsigned long memory_start,
                                               unsigned long memory_end)
@@ -31,6 +34,9 @@
 	 * 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);
+
 	return memory_start;
 }
 
@@ -45,7 +51,7 @@
 {
 	u32 res;
 
-	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	mkaddr(bus, dev_fn, where);
 	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
 	res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff;
 	*val = res;
@@ -62,7 +68,7 @@
 
 	if (where & 1)
 		return PCIBIOS_BAD_REGISTER_NUMBER;
-	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	mkaddr(bus, dev_fn, where);
 	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
 	res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff;
 	*val = res;
@@ -77,9 +83,9 @@
 {
 	u32 res;
 
-	if (where & 3)
+		if (where & 3)
 		return PCIBIOS_BAD_REGISTER_NUMBER;
-	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	mkaddr(bus, dev_fn, where);
 	res = *(volatile u32 *)PCIMT_CONFIG_DATA;
 	res = le32_to_cpu(res);
 	*val = res;
@@ -92,7 +98,9 @@
                                                 unsigned char where,
                                                 unsigned char val)
 {
-	/* To do */
+	mkaddr(bus, dev_fn, where);
+	*(volatile u8 *)(PCIMT_CONFIG_DATA + (where & 3)) = val;
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -101,7 +109,11 @@
                                                 unsigned char where,
                                                 unsigned short val)
 {
-	/* To do */
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	mkaddr(bus, dev_fn, where);
+	*(volatile u16 *)(PCIMT_CONFIG_DATA + (where & 3)) = le16_to_cpu(val);
+
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -112,7 +124,7 @@
 {
 	if (where & 3)
 		return PCIBIOS_BAD_REGISTER_NUMBER;
-	*(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where);
+	mkaddr(bus, dev_fn, where);
 	*(volatile u32 *)PCIMT_CONFIG_DATA = le32_to_cpu(val);
 
 	return PCIBIOS_SUCCESSFUL;
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/pcimt_scache.c linux/arch/mips/sni/pcimt_scache.c
--- v2.1.100/linux/arch/mips/sni/pcimt_scache.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/sni/pcimt_scache.c	Fri May  8 00:13:25 1998
@@ -0,0 +1,34 @@
+/*
+ * 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.1 1998/03/04 08:47:29 ralf Exp $
+ */
+#include <linux/init.h>
+#include <asm/bcache.h>
+#include <asm/sni.h>
+
+__initfunc(void sni_pcimt_sc_init(void))
+{
+	unsigned int cacheconf, 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");
+		return;
+	}
+	if ((cacheconf & 7) >= 6) {
+		printk("Invalid second level cache size detected\n");
+		return;
+	}
+	
+	sc_size = 128 << (cacheconf & 7);
+	printk("%dkb second level cache detected.\n", sc_size);
+}
diff -u --recursive --new-file v2.1.100/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c
--- v2.1.100/linux/arch/mips/sni/setup.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/sni/setup.c	Fri May  8 00:13:25 1998
@@ -1,5 +1,5 @@
 /*
- * Setup pointers to hardware dependand routines.
+ * Setup pointers to hardware dependant 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
@@ -7,17 +7,21 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: setup.c,v 1.5 1997/12/01 16:19:12 ralf Exp $
+ * $Id: setup.c,v 1.5 1998/05/04 09:18:42 ralf Exp $
  */
 #include <asm/ptrace.h>
+#include <linux/config.h>
+#include <linux/hdreg.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/pci.h>
+#include <asm/bcache.h>
 #include <asm/bootinfo.h>
 #include <asm/keyboard.h>
+#include <asm/ide.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
@@ -45,6 +49,8 @@
 extern void sni_machine_halt(void);
 extern void sni_machine_power_off(void);
 
+extern struct ide_ops std_ide_ops;
+
 __initfunc(static void sni_irq_setup(void))
 {
 	set_except_vector(0, sni_rm200_pci_handle_int);
@@ -94,32 +100,8 @@
 	asic = (csmsr & 0x08) ? asic : !asic;
 	p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1");
 	printk("%s.\n", boardtype);
-
-	cacheconf = *(volatile unsigned int *)PCIMT_CACHECONF;
-	switch(cacheconf & 7) {
-	case 0:
-		printk("Secondary cache disabled\n");
-		break;
-	case 1:
-		printk("256kb secondary cache\n");
-		break;
-	case 2:
-		printk("512kb secondary cache\n");
-		break;
-	case 3:
-		printk("1mb secondary cache\n");
-		break;
-	case 4:
-		printk("2mb secondary cache\n");
-		break;
-	case 5:
-		printk("4mb secondary cache\n");
-		break;
-	default:
-		panic("invalid secondary cache size\n");
-	}
 }
-	
+
 __initfunc(void sni_rm200_pci_setup(void))
 {
 	tag *atag;
@@ -149,6 +131,7 @@
 	}
 
 	sni_pcimt_detect();
+	sni_pcimt_sc_init();
 
 	irq_setup = sni_irq_setup;
 	fd_cacheflush = sni_fd_cacheflush;	// Will go away
@@ -183,4 +166,7 @@
 	 */
 	request_region(0xcfc,0x04,"PCI config data");
 	pci_ops = &sni_pci_ops;
+#ifdef CONFIG_BLK_DEV_IDE
+	ide_ops = &std_ide_ops;
+#endif
 }
diff -u --recursive --new-file v2.1.100/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile
--- v2.1.100/linux/arch/mips/tools/Makefile	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/tools/Makefile	Fri May  8 00:13:25 1998
@@ -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.3 1998/05/01 01:35:37 ralf Exp $
 #
 TARGET	:= $(TOPDIR)/include/asm-$(ARCH)/offset.h
 
diff -u --recursive --new-file v2.1.100/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c
--- v2.1.100/linux/arch/mips/tools/offset.c	Wed Dec 10 10:31:10 1997
+++ linux/arch/mips/tools/offset.c	Fri May  8 00:13:25 1998
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 David S. Miller
  * Made portable by Ralf Baechle
  *
- * $Id: offset.c,v 1.3 1997/07/29 18:57:11 ralf Exp $
+ * $Id: offset.c,v 1.6 1998/05/04 09:18:45 ralf Exp $
  */
 
 #include <linux/types.h>
@@ -65,8 +65,6 @@
 	offset("#define PT_R31    ", struct pt_regs, regs[31]);
 	offset("#define PT_LO     ", struct pt_regs, lo);
 	offset("#define PT_HI     ", struct pt_regs, hi);
-	offset("#define PT_OR2    ", struct pt_regs, orig_reg2);
-	offset("#define PT_OR7    ", struct pt_regs, orig_reg7);
 	offset("#define PT_EPC    ", struct pt_regs, cp0_epc);
 	offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
 	offset("#define PT_STATUS ", struct pt_regs, cp0_status);
@@ -81,9 +79,8 @@
 	offset("#define TASK_STATE         ", struct task_struct, state);
 	offset("#define TASK_COUNTER       ", struct task_struct, counter);
 	offset("#define TASK_PRIORITY      ", struct task_struct, priority);
-	offset("#define TASK_SIGNAL        ", struct task_struct, signal);
-	offset("#define TASK_BLOCKED       ", struct task_struct, blocked);
 	offset("#define TASK_FLAGS         ", struct task_struct, flags);
+	offset("#define TASK_SIGPENDING    ", struct task_struct, sigpending);
 	offset("#define TASK_MM            ", struct task_struct, mm);
 	linefeed;
 }
@@ -99,16 +96,15 @@
 	offset("#define THREAD_REG21   ", struct task_struct, tss.reg21);
 	offset("#define THREAD_REG22   ", struct task_struct, tss.reg22);
 	offset("#define THREAD_REG23   ", struct task_struct, tss.reg23);
-	offset("#define THREAD_REG28   ", struct task_struct, tss.reg28);
 	offset("#define THREAD_REG29   ", struct task_struct, tss.reg29);
 	offset("#define THREAD_REG30   ", struct task_struct, tss.reg30);
 	offset("#define THREAD_REG31   ", struct task_struct, tss.reg31);
 	offset("#define THREAD_STATUS  ", struct task_struct, tss.cp0_status);
 	offset("#define THREAD_FPU     ", struct task_struct, tss.fpu);
 	offset("#define THREAD_BVADDR  ", struct task_struct, tss.cp0_badvaddr);
+	offset("#define THREAD_BUADDR  ", struct task_struct, tss.cp0_baduaddr);
 	offset("#define THREAD_ECODE   ", struct task_struct, tss.error_code);
 	offset("#define THREAD_TRAPNO  ", struct task_struct, tss.trap_no);
-	offset("#define THREAD_KSP     ", struct task_struct, tss.ksp);
 	offset("#define THREAD_PGDIR   ", struct task_struct, tss.pg_dir);
 	offset("#define THREAD_MFLAGS  ", struct task_struct, tss.mflags);
 	offset("#define THREAD_CURDS   ", struct task_struct, tss.current_ds);
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- v2.1.100/linux/arch/ppc/8xx_io/commproc.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/8xx_io/commproc.c	Fri May  8 00:18:13 1998
@@ -85,7 +85,6 @@
 	*/
 	dp_alloc_base = CPM_DATAONLY_BASE;
 	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
-
 	/* Set the host page for allocation.
 	*/
 	host_buffer = host_page_addr;	/* Host virtual page address */
@@ -104,7 +103,6 @@
 	    (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
 		((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
 	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr = 0;
-
 	/* Set our interrupt handler with the core CPU.
 	*/
 	if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0)
@@ -113,7 +111,6 @@
 	/* Install our own error handler.
 	*/
 	cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL);
-
 	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
 }
 
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.1.100/linux/arch/ppc/8xx_io/enet.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/8xx_io/enet.c	Fri May  8 00:18:13 1998
@@ -30,10 +30,8 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <linux/init.h>
-#include <asm/bitops.h>
-
+#include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -41,8 +39,9 @@
 #include <asm/8xx_immap.h>
 #include <asm/pgtable.h>
 #include <asm/mbx.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
 #include "commproc.h"
-#include <linux/delay.h>
 
 /*
  *				Theory of Operation
@@ -151,762 +150,766 @@
 
 /* GET THIS FROM THE VPD!!!!
 */
-static	ushort	my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+/*static	ushort	my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };*/
 
-/* Initialize the CPM Ethernet on SCC1.  If EPPC-Bug loaded us, or performed
- * some other network I/O, a whole bunch of this has already been set up.
- * It is no big deal if we do it again, we just have to disable the
- * transmit and receive to make sure we don't catch the CPM with some
- * inconsistent control information.
- */
-__initfunc(int cpm_enet_init(void))
+static int
+cpm_enet_open(struct device *dev)
 {
-	struct device *dev;
-	struct cpm_enet_private *cep;
-	int i, j;
-	unsigned char	*eap;
-	unsigned long	mem_addr;
-	pte_t		*pte;
-	volatile	cbd_t		*bdp;
-	volatile	cpm8xx_t	*cp;
-	volatile	scc_t		*sccp;
-	volatile	scc_enet_t	*ep;
-	volatile	immap_t		*immap;
 
-	cp = cpmp;	/* Get pointer to Communication Processor */
+	/* I should reset the ring buffers here, but I don't yet know
+	 * a simple way to do that.
+	 */
 
-	immap = (immap_t *)MBX_IMAP_ADDR;	/* and to internal registers */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
 
-	/* Allocate some private information.
-	*/
-	cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
-	memset(cep, 0, sizeof(*cep));
+	return 0;					/* Always succeed */
+}
 
-	/* Create an Ethernet device instance.
-	*/
-	dev = init_etherdev(0, 0);
+static int
+cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+	volatile cbd_t	*bdp;
+	unsigned long flags;
 
-	/* Get pointer to SCC1 area in parameter RAM.
-	*/
-	ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_SCC1]);
+	/* Transmitter timeout, serious problems. */
+	if (dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 20)
+			return 1;
+		printk("%s: transmit timed out.\n", dev->name);
+		cep->stats.tx_errors++;
+#ifndef final_version
+		{
+			int	i;
+			cbd_t	*bdp;
+			printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n",
+				   cep->cur_tx, cep->tx_full ? " (full)" : "",
+				   cep->cur_rx);
+			bdp = cep->tx_bd_base;
+			for (i = 0 ; i < TX_RING_SIZE; i++)
+				printk("%04x %04x %08x\n",
+					bdp->cbd_sc,
+					bdp->cbd_datlen,
+					bdp->cbd_bufaddr);
+			bdp = cep->rx_bd_base;
+			for (i = 0 ; i < RX_RING_SIZE; i++)
+				printk("%04x %04x %08x\n",
+					bdp->cbd_sc,
+					bdp->cbd_datlen,
+					bdp->cbd_bufaddr);
+		}
+#endif
 
-	/* And another to the SCC register area.
-	*/
-	sccp = (volatile scc_t *)(&cp->cp_scc[0]);
-	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */
+		dev->tbusy=0;
+		dev->trans_start = jiffies;
 
-	/* Disable receive and transmit in case EPPC-Bug started it.
-	*/
-	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+		return 0;
+	}
 
-	/* Cookbook style from the MPC860 manual.....
-	 * Not all of this is necessary if EPPC-Bug has initialized
-	 * the network.
+	/* 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("%s: Transmitter access conflict.\n", dev->name);
+		return 1;
+	}
+
+	if (test_and_set_bit(0, (void*)&cep->lock) != 0) {
+		printk("%s: tx queue lock!.\n", dev->name);
+		/* don't clear dev->tbusy flag. */
+		return 1;
+	}
+
+	/* Fill in a Tx ring entry */
+	bdp = cep->cur_tx;
+
+#ifndef final_version
+	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since dev->tbusy should be set.
+		 */
+		printk("%s: tx queue full!.\n", dev->name);
+		cep->lock = 0;
+		return 1;
+	}
+#endif
+
+	/* Clear all of the status flags.
 	 */
+	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
 
-	/* Configure port A pins for Txd and Rxd.
+	/* If the frame is short, tell CPM to pad it.
 	*/
-	immap->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
-	immap->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
-	immap->im_ioport.iop_paodr &= ~PA_ENET_TXD;
+	if (skb->len <= ETH_ZLEN)
+		bdp->cbd_sc |= BD_ENET_TX_PAD;
+	else
+		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
 
-	/* Configure port C pins to enable CLSN and RENA.
+	/* Set buffer length and buffer pointer.
 	*/
-	immap->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
-	immap->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
-	immap->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
+	bdp->cbd_datlen = skb->len;
+	bdp->cbd_bufaddr = __pa(skb->data);
 
-	/* Configure port A for TCLK and RCLK.
+	/* Save skb pointer.
 	*/
-	immap->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
-	immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
-
-	/* Configure Serial Interface clock routing.
-	 * First, clear all SCC1 bits to zero, then set the ones we want.
-	 */
-	cp->cp_sicr &= ~SICR_ENET_MASK;
-	cp->cp_sicr |= SICR_ENET_CLKRT;
+	cep->tx_skbuff[cep->skb_cur] = skb;
 
-	/* Manual says set SDDR, but I can't find anything with that
-	 * name.  I think it is a misprint, and should be SDCR.  This
-	 * has already been set by the communication processor initialization.
+	cep->stats.tx_bytes += skb->len;
+	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
+	
+	/* Push the data cache so the CPM does not get stale memory
+	 * data.
 	 */
+	/*flush_dcache_range(skb->data, skb->data + skb->len);*/
 
-	/* Allocate space for the buffer descriptors in the DP ram.
-	 * These are relative offsets in the DP ram address space.
-	 * Initialize base addresses for the buffer descriptors.
+	/* Send it on its way.  Tell CPM its ready, interrupt when done,
+	 * its the last BD of the frame, and to put the CRC on the end.
 	 */
-	i = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
-	ep->sen_genscc.scc_rbase = i;
-	cep->rx_bd_base = (cbd_t *)&cp->cp_dpmem[i];
-
-	i = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
-	ep->sen_genscc.scc_tbase = i;
-	cep->tx_bd_base = (cbd_t *)&cp->cp_dpmem[i];
-
-	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
-	cep->cur_rx = cep->rx_bd_base;
+	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
 
-	/* Issue init Rx BD command for SCC1.
-	 * Manual says to perform an Init Rx parameters here.  We have
-	 * to perform both Rx and Tx because the SCC may have been
-	 * already running.
-	 * In addition, we have to do it later because we don't yet have
-	 * all of the BD control/status set properly.
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_RX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
-	 */
+	dev->trans_start = jiffies;
 
-	/* Initialize function code registers for big-endian.
+	/* If this was the last BD in the ring, start at the beginning again.
 	*/
-	ep->sen_genscc.scc_rfcr = SCC_EB;
-	ep->sen_genscc.scc_tfcr = SCC_EB;
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = cep->tx_bd_base;
+	else
+		bdp++;
 
-	/* Set maximum bytes per receive buffer.
-	 * This appears to be an Ethernet frame size, not the buffer
-	 * fragment size.  It must be a multiple of four.
-	 */
-	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
+	save_flags(flags);
+	cli();
+	cep->lock = 0;
+	if (bdp->cbd_sc & BD_ENET_TX_READY)
+		cep->tx_full = 1;
+	else
+		dev->tbusy=0;
+	restore_flags(flags);
 
-	/* Set CRC preset and mask.
-	*/
-	ep->sen_cpres = 0xffffffff;
-	ep->sen_cmask = 0xdebb20e3;
+	cep->cur_tx = (cbd_t *)bdp;
 
-	ep->sen_crcec = 0;	/* CRC Error counter */
-	ep->sen_alec = 0;	/* alignment error counter */
-	ep->sen_disfc = 0;	/* discard frame counter */
+	return 0;
+}
 
-	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
-	ep->sen_retlim = 15;	/* Retry limit threshold */
+/* The interrupt handler.
+ * This is called from the CPM handler, not the MPC core interrupt.
+ */
+static void
+cpm_enet_interrupt(void *dev_id)
+{
+	struct	device *dev = dev_id;
+	struct	cpm_enet_private *cep;
+	volatile cbd_t	*bdp;
+	ushort	int_events;
+	int	must_restart;
 
-	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
-	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+	cep = (struct cpm_enet_private *)dev->priv;
+	if (dev->interrupt)
+		printk("%s: Re-entering the interrupt handler.\n", dev->name);
 
-	ep->sen_maxd1 = PKT_MAXBUF_SIZE;	/* maximum DMA1 length */
-	ep->sen_maxd2 = PKT_MAXBUF_SIZE;	/* maximum DMA2 length */
+	dev->interrupt = 1;
 
-	/* Clear hash tables.
+	/* Get the interrupt events that caused us to be here.
 	*/
-	ep->sen_gaddr1 = 0;
-	ep->sen_gaddr2 = 0;
-	ep->sen_gaddr3 = 0;
-	ep->sen_gaddr4 = 0;
-	ep->sen_iaddr1 = 0;
-	ep->sen_iaddr2 = 0;
-	ep->sen_iaddr3 = 0;
-	ep->sen_iaddr4 = 0;
+	int_events = cep->sccp->scc_scce;
+	must_restart = 0;
 
-	/* Set Ethernet station address.  This must come from the
-	 * Vital Product Data (VPD) EEPROM.....as soon as I get the
-	 * I2C interface working.....
-	 *
-	 * Since we performed a diskless boot, the Ethernet controller
-	 * has been initialized and we copy the address out into our
-	 * own structure.
-	 */
-#ifdef notdef
-	ep->sen_paddrh = my_enet_addr[0];
-	ep->sen_paddrm = my_enet_addr[1];
-	ep->sen_paddrl = my_enet_addr[2];
-#else
-	eap = (unsigned char *)&(ep->sen_paddrh);
-	for (i=5; i>=0; i--)
-		dev->dev_addr[i] = *eap++;
-#endif
-
-	ep->sen_pper = 0;	/* 'cause the book says so */
-	ep->sen_taddrl = 0;	/* temp address (LSB) */
-	ep->sen_taddrm = 0;
-	ep->sen_taddrh = 0;	/* temp address (MSB) */
+	/* Handle receive event in its own function.
+	*/
+	if (int_events & SCCE_ENET_RXF)
+		cpm_enet_rx(dev_id);
 
-	/* Now allocate the host memory pages and initialize the
-	 * buffer descriptors.
+	/* Check for a transmit error.  The manual is a little unclear
+	 * about this, so the debug code until I get it figured out.  It
+	 * appears that if TXE is set, then TXB is not set.  However,
+	 * if carrier sense is lost during frame transmission, the TXE
+	 * bit is set, "and continues the buffer transmission normally."
+	 * I don't know if "normally" implies TXB is set when the buffer
+	 * descriptor is closed.....trial and error :-).
 	 */
-	bdp = cep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
+	if (int_events & SCCE_ENET_TXE) {
 
-		/* Initialize the BD for every fragment in the page.
+		/* Transmission errors.
 		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
-	}
+		bdp = cep->dirty_tx;
+#ifndef final_version
+		printk("CPM ENET xmit error %x\n", bdp->cbd_sc);
+		if (bdp->cbd_sc & BD_ENET_TX_READY)
+			printk("HEY! Enet xmit interrupt and TX_READY.\n");
+#endif
+		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
+			cep->stats.tx_heartbeat_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
+			cep->stats.tx_window_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
+			cep->stats.tx_aborted_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
+			cep->stats.tx_fifo_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
+			cep->stats.tx_carrier_errors++;
 
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
+		cep->stats.tx_errors++;
 
-	bdp = cep->rx_bd_base;
-	for (i=0; i<CPM_ENET_RX_PAGES; i++) {
+		/* No heartbeat or Lost carrier are not really bad errors.
+		 * The others require a restart transmit command.
+		 */
+		if (bdp->cbd_sc &
+		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN))
+			must_restart = 1;
+	}
 
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
+	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	*/
+	if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
+		cep->stats.tx_packets++;
+		bdp = cep->dirty_tx;
+#ifndef final_version
+		if (bdp->cbd_sc & BD_ENET_TX_READY)
+			printk("HEY! Enet xmit interrupt and TX_READY.\n");
+#endif
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+			cep->stats.collisions++;
 
-		/* Make it uncached.
+		/* Free the sk buffer associated with this last transmit.
 		*/
-		pte = va_to_pte(&init_task, mem_addr);
-		pte_val(*pte) |= _PAGE_NO_CACHE;
-		flush_tlb_page(current->mm->mmap, mem_addr);
+		dev_kfree_skb(cep->tx_skbuff[cep->skb_dirty]/*, FREE_WRITE*/);
+		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
-		/* Initialize the BD for every fragment in the page.
+		/* Update pointer to next buffer descriptor to be transmitted.
 		*/
-		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += CPM_ENET_RX_FRSIZE;
+		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+			bdp = cep->tx_bd_base;
+		else
 			bdp++;
+
+		/* I don't know if we can be held off from processing these
+		 * interrupts for more than one frame time.  I really hope
+		 * not.  In such a case, we would now want to check the
+		 * currently available BD (cur_tx) and determine if any
+		 * buffers between the dirty_tx and cur_tx have also been
+		 * sent.  We would want to process anything in between that
+		 * does not have BD_ENET_TX_READY set.
+		 */
+
+		/* Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (cep->tx_full && dev->tbusy) {
+			cep->tx_full = 0;
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
 		}
+
+		cep->dirty_tx = (cbd_t *)bdp;
 	}
 
-	/* Set the last buffer to wrap.
-	*/
-	bdp--;
-	bdp->cbd_sc |= BD_SC_WRAP;
+	if (must_restart) {
+		volatile cpm8xx_t *cp;
 
-	/* Let's re-initialize the channel now.  We have to do it later
-	 * than the manual describes because we have just now finished
-	 * the BD initialization.
+		/* Some transmit errors cause the transmitter to shut
+		 * down.  We now issue a restart transmit.  Since the
+		 * errors close the BD and update the pointers, the restart
+		 * _should_ pick up without having to reset any of our
+		 * pointers either.
+		 */
+		cp = cpmp;
+		cp->cp_cpcr =
+		    mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_RESTART_TX) | CPM_CR_FLG;
+		while (cp->cp_cpcr & CPM_CR_FLG);
+	}
+
+	/* Check for receive busy, i.e. packets coming but no place to
+	 * put them.  This "can't happen" because the receive interrupt
+	 * is tossing previous frames.
 	 */
-	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
-	while (cp->cp_cpcr & CPM_CR_FLG);
+	if (int_events & SCCE_ENET_BSY) {
+		cep->stats.rx_dropped++;
+		printk("CPM ENET: BSY can't happen.\n");
+	}
 
-	cep->skb_cur = cep->skb_dirty = 0;
+	/* Write the SCC event register with the events we have handled
+	 * to clear them.  Maybe we should do this sooner?
+	 */
+	cep->sccp->scc_scce = int_events;
 
-	sccp->scc_scce = 0xffff;	/* Clear any pending events */
+	dev->interrupt = 0;
 
-	/* Enable interrupts for transmit error, complete frame
-	 * received, and any transmit buffer we have also set the
-	 * interrupt flag.
-	 */
-	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
+	return;
+}
 
-	/* Install our interrupt handler.
-	*/
-	cpm_install_handler(CPMVEC_SCC1, cpm_enet_interrupt, dev);
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+cpm_enet_rx(struct device *dev)
+{
+	struct	cpm_enet_private *cep;
+	volatile cbd_t	*bdp;
+	struct	sk_buff *skb;
+	ushort	pkt_len;
 
-	/* Set GSMR_H to enable all normal operating modes.
-	 * Set GSMR_L to enable Ethernet to MC68160.
+	cep = (struct cpm_enet_private *)dev->priv;
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
 	 */
-	sccp->scc_gsmrh = 0;
-	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
+	bdp = cep->cur_rx;
 
-	/* Set sync/delimiters.
+for (;;) {
+	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+		break;
+		
+#ifndef final_version
+	/* Since we have allocated space to hold a complete frame, both
+	 * the first and last indicators should be set.
+	 */
+	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
+		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
+			printk("CPM ENET: rcv is not first+last\n");
+#endif
+
+	/* Frame too long or too short.
 	*/
-	sccp->scc_dsr = 0xd555;
+	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+		cep->stats.rx_length_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		cep->stats.rx_frame_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		cep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
+		cep->stats.rx_crc_errors++;
 
-	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
-	 * start frame search 22 bit times after RENA.
+	/* Report late collisions as a frame error.
+	 * On this error, the BD is closed, but we don't know what we
+	 * have in the buffer.  So, just drop this frame on the floor.
 	 */
-	sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_BRO | SCC_PMSR_NIB22);
+	if (bdp->cbd_sc & BD_ENET_RX_CL) {
+		cep->stats.rx_frame_errors++;
+	}
+	else {
 
-	/* It is now OK to enable the Ethernet transmitter.
-	*/
-	immap->im_ioport.iop_pcpar |= PC_ENET_TENA;
-	immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
+		/* Process the incoming frame.
+		*/
+		cep->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		cep->stats.rx_bytes += pkt_len;
 
-	dev->base_addr = (unsigned long)ep;
-	dev->priv = cep;
-	dev->name = "CPM_ENET";
+		/* This does 16 byte alignment, much more than we need.
+		*/
+		skb = dev_alloc_skb(pkt_len);
 
-	/* The CPM Ethernet specific entries in the device structure. */
-	dev->open = cpm_enet_open;
-	dev->hard_start_xmit = cpm_enet_start_xmit;
-	dev->stop = cpm_enet_close;
-	dev->get_stats = cpm_enet_get_stats;
-	dev->set_multicast_list = set_multicast_list;
+		if (skb == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			cep->stats.rx_dropped++;
+		}
+		else {
+			skb->dev = dev;
+			skb_put(skb,pkt_len);	/* Make room */
+			eth_copy_and_sum(skb,
+				(unsigned char *)__va(bdp->cbd_bufaddr),
+				pkt_len, 0);
+			skb->protocol=eth_type_trans(skb,dev);
+			netif_rx(skb);
+		}
+	}
 
-	/* And last, enable the transmit and receive processing.
+	/* Clear the status flags for this buffer.
 	*/
-	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
 
-	printk("CPM ENET Version 0.1, ");
-	for (i=0; i<5; i++)
-		printk("%02x:", dev->dev_addr[i]);
-	printk("%02x\n", dev->dev_addr[5]);
+	/* Mark the buffer empty.
+	*/
+	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+	/* Update BD pointer to next entry.
+	*/
+	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+		bdp = cep->rx_bd_base;
+	else
+		bdp++;
+
+   }
+	cep->cur_rx = (cbd_t *)bdp;
 
 	return 0;
 }
 
 static int
-cpm_enet_open(struct device *dev)
+cpm_enet_close(struct device *dev)
 {
+	/* Don't know what to do yet.
+	*/
 
-	/* I should reset the ring buffers here, but I don't yet know
-	 * a simple way to do that.
-	 */
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	return 0;					/* Always succeed */
+	return 0;
 }
 
-static int
-cpm_enet_start_xmit(struct sk_buff *skb, struct device *dev)
+static struct net_device_stats *cpm_enet_get_stats(struct device *dev)
 {
 	struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
-	volatile cbd_t	*bdp;
-	unsigned long flags;
 
-	/* Transmitter timeout, serious problems. */
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 20)
-			return 1;
-		printk("%s: transmit timed out.\n", dev->name);
-		cep->stats.tx_errors++;
-#ifndef final_version
-		{
-			int	i;
-			cbd_t	*bdp;
-			printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n",
-				   cep->cur_tx, cep->tx_full ? " (full)" : "",
-				   cep->cur_rx);
-			bdp = cep->tx_bd_base;
-			for (i = 0 ; i < TX_RING_SIZE; i++)
-				printk("%04x %04x %08x\n",
-					bdp->cbd_sc,
-					bdp->cbd_datlen,
-					bdp->cbd_bufaddr);
-			bdp = cep->rx_bd_base;
-			for (i = 0 ; i < RX_RING_SIZE; i++)
-				printk("%04x %04x %08x\n",
-					bdp->cbd_sc,
-					bdp->cbd_datlen,
-					bdp->cbd_bufaddr);
-		}
-#endif
-
-		dev->tbusy=0;
-		dev->trans_start = jiffies;
-
-		return 0;
-	}
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		printk("%s: Transmitter access conflict.\n", dev->name);
-		return 1;
-	}
-
-	if (test_and_set_bit(0, (void*)&cep->lock) != 0) {
-		printk("%s: tx queue lock!.\n", dev->name);
-		/* don't clear dev->tbusy flag. */
-		return 1;
-	}
-
-	/* Fill in a Tx ring entry */
-	bdp = cep->cur_tx;
-
-#ifndef final_version
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
-		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since dev->tbusy should be set.
-		 */
-		printk("%s: tx queue full!.\n", dev->name);
-		cep->lock = 0;
-		return 1;
-	}
-#endif
-
-	/* Clear all of the status flags.
-	 */
-	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+	return &cep->stats;
+}
 
-	/* If the frame is short, tell CPM to pad it.
-	*/
-	if (skb->len <= ETH_ZLEN)
-		bdp->cbd_sc |= BD_ENET_TX_PAD;
-	else
-		bdp->cbd_sc &= ~BD_ENET_TX_PAD;
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
 
-	/* Set buffer length and buffer pointer.
-	*/
-	bdp->cbd_datlen = skb->len;
-	bdp->cbd_bufaddr = __pa(skb->data);
+static void set_multicast_list(struct device *dev)
+{
+	struct	cpm_enet_private *cep;
+	struct	dev_mc_list *dmi;
+	u_char	*mcptr, *tdptr;
+	volatile scc_enet_t *ep;
+	int	i, j;
+	cep = (struct cpm_enet_private *)dev->priv;
 
-	/* Save skb pointer.
+	/* Get pointer to SCC1 area in parameter RAM.
 	*/
-	cep->tx_skbuff[cep->skb_cur] = skb;
+	ep = (scc_enet_t *)dev->base_addr;
 
-	cep->stats.tx_bytes += skb->len;
-	cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK;
-	
-	/* Push the data cache so the CPM does not get stale memory
-	 * data.
-	 */
-	/*flush_dcache_range(skb->data, skb->data + skb->len);*/
+	if (dev->flags&IFF_PROMISC) {
+	  
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		cep->sccp->scc_pmsr |= SCC_PMSR_PRO;
+	} else {
 
-	/* Send it on its way.  Tell CPM its ready, interrupt when done,
-	 * its the last BD of the frame, and to put the CRC on the end.
-	 */
-	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+		cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO;
 
-	dev->trans_start = jiffies;
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			ep->sen_gaddr1 = 0xffff;
+			ep->sen_gaddr2 = 0xffff;
+			ep->sen_gaddr3 = 0xffff;
+			ep->sen_gaddr4 = 0xffff;
+		}
+		else {
+			/* Clear filter and add the addresses in the list.
+			*/
+			ep->sen_gaddr1 = 0;
+			ep->sen_gaddr2 = 0;
+			ep->sen_gaddr3 = 0;
+			ep->sen_gaddr4 = 0;
 
-	/* If this was the last BD in the ring, start at the beginning again.
-	*/
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-		bdp = cep->tx_bd_base;
-	else
-		bdp++;
+			dmi = dev->mc_list;
 
-	save_flags(flags);
-	cli();
-	cep->lock = 0;
-	if (bdp->cbd_sc & BD_ENET_TX_READY)
-		cep->tx_full = 1;
-	else
-		dev->tbusy=0;
-	restore_flags(flags);
+			for (i=0; i<dev->mc_count; i++) {
+				
+				/* Only support group multicast for now.
+				*/
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
 
-	cep->cur_tx = (cbd_t *)bdp;
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u_char *)dmi->dmi_addr + 5;
+				tdptr = (u_char *)&ep->sen_taddrh;
+				for (j=0; j<6; j++)
+					*tdptr++ = *mcptr--;
 
-	return 0;
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG;
+				/* this delay is necessary here -- Cort */
+				udelay(10);
+				while (cpmp->cp_cpcr & CPM_CR_FLG);
+			}
+		}
+	}
 }
 
-/* The interrupt handler.
- * This is called from the CPM handler, not the MPC core interrupt.
+/* Initialize the CPM Ethernet on SCC1.  If EPPC-Bug loaded us, or performed
+ * some other network I/O, a whole bunch of this has already been set up.
+ * It is no big deal if we do it again, we just have to disable the
+ * transmit and receive to make sure we don't catch the CPM with some
+ * inconsistent control information.
  */
-static void
-cpm_enet_interrupt(void *dev_id)
+__initfunc(int cpm_enet_init(void))
 {
-	struct	device *dev = dev_id;
-	struct	cpm_enet_private *cep;
-	volatile cbd_t	*bdp;
-	ushort	int_events;
-	int	must_restart;
+	struct device *dev;
+	struct cpm_enet_private *cep;
+	int i, j;
+	unsigned char	*eap;
+	unsigned long	mem_addr;
+	pte_t		*pte;
+	volatile	cbd_t		*bdp;
+	volatile	cpm8xx_t	*cp;
+	volatile	scc_t		*sccp;
+	volatile	scc_enet_t	*ep;
+	volatile	immap_t		*immap;
 
-	cep = (struct cpm_enet_private *)dev->priv;
-	if (dev->interrupt)
-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
+	cp = cpmp;	/* Get pointer to Communication Processor */
 
-	dev->interrupt = 1;
+	immap = (immap_t *)MBX_IMAP_ADDR;	/* and to internal registers */
 
-	/* Get the interrupt events that caused us to be here.
+	/* Allocate some private information.
 	*/
-	int_events = cep->sccp->scc_scce;
-	must_restart = 0;
+	cep = (struct cpm_enet_private *)kmalloc(sizeof(*cep), GFP_KERNEL);
+	/*memset(cep, 0, sizeof(*cep));*/
+	__clear_user(cep,sizeof(*cep));
 
-	/* Handle receive event in its own function.
+	/* Create an Ethernet device instance.
 	*/
-	if (int_events & SCCE_ENET_RXF)
-		cpm_enet_rx(dev_id);
+	dev = init_etherdev(0, 0);
 
-	/* Check for a transmit error.  The manual is a little unclear
-	 * about this, so the debug code until I get it figured out.  It
-	 * appears that if TXE is set, then TXB is not set.  However,
-	 * if carrier sense is lost during frame transmission, the TXE
-	 * bit is set, "and continues the buffer transmission normally."
-	 * I don't know if "normally" implies TXB is set when the buffer
-	 * descriptor is closed.....trial and error :-).
-	 */
-	if (int_events & SCCE_ENET_TXE) {
+	/* Get pointer to SCC1 area in parameter RAM.
+	*/
+	ep = (scc_enet_t *)(&cp->cp_dparam[PROFF_SCC1]);
 
-		/* Transmission errors.
-		*/
-		bdp = cep->dirty_tx;
-#ifndef final_version
-		printk("CPM ENET xmit error %x\n", bdp->cbd_sc);
-		if (bdp->cbd_sc & BD_ENET_TX_READY)
-			printk("HEY! Enet xmit interrupt and TX_READY.\n");
-#endif
-		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
-			cep->stats.tx_heartbeat_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
-			cep->stats.tx_window_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
-			cep->stats.tx_aborted_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
-			cep->stats.tx_fifo_errors++;
-		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
-			cep->stats.tx_carrier_errors++;
+	/* And another to the SCC register area.
+	*/
+	sccp = (volatile scc_t *)(&cp->cp_scc[0]);
+	cep->sccp = (scc_t *)sccp;		/* Keep the pointer handy */
 
-		cep->stats.tx_errors++;
+	/* Disable receive and transmit in case EPPC-Bug started it.
+	*/
+	sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 
-		/* No heartbeat or Lost carrier are not really bad errors.
-		 * The others require a restart transmit command.
-		 */
-		if (bdp->cbd_sc &
-		    (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN))
-			must_restart = 1;
-	}
+	/* Cookbook style from the MPC860 manual.....
+	 * Not all of this is necessary if EPPC-Bug has initialized
+	 * the network.
+	 */
 
-	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	/* Configure port A pins for Txd and Rxd.
 	*/
-	if (int_events & (SCCE_ENET_TXE | SCCE_ENET_TXB)) {
-		cep->stats.tx_packets++;
-		bdp = cep->dirty_tx;
-#ifndef final_version
-		if (bdp->cbd_sc & BD_ENET_TX_READY)
-			printk("HEY! Enet xmit interrupt and TX_READY.\n");
-#endif
-		/* Deferred means some collisions occurred during transmit,
-		 * but we eventually sent the packet OK.
-		 */
-		if (bdp->cbd_sc & BD_ENET_TX_DEF)
-			cep->stats.collisions++;
+	immap->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD);
+	immap->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
+	immap->im_ioport.iop_paodr &= ~PA_ENET_TXD;
 
-		/* Free the sk buffer associated with this last transmit.
-		*/
-		dev_kfree_skb(cep->tx_skbuff[cep->skb_dirty]/*, FREE_WRITE*/);
-		cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK;
+	/* Configure port C pins to enable CLSN and RENA.
+	*/
+	immap->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+	immap->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
+	immap->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA);
 
-		/* Update pointer to next buffer descriptor to be transmitted.
-		*/
-		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
-			bdp = cep->tx_bd_base;
-		else
-			bdp++;
+	/* Configure port A for TCLK and RCLK.
+	*/
+	immap->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK);
+	immap->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
 
-		/* I don't know if we can be held off from processing these
-		 * interrupts for more than one frame time.  I really hope
-		 * not.  In such a case, we would now want to check the
-		 * currently available BD (cur_tx) and determine if any
-		 * buffers between the dirty_tx and cur_tx have also been
-		 * sent.  We would want to process anything in between that
-		 * does not have BD_ENET_TX_READY set.
-		 */
+	/* Configure Serial Interface clock routing.
+	 * First, clear all SCC1 bits to zero, then set the ones we want.
+	 */
+	cp->cp_sicr &= ~SICR_ENET_MASK;
+	cp->cp_sicr |= SICR_ENET_CLKRT;
 
-		/* Since we have freed up a buffer, the ring is no longer
-		 * full.
-		 */
-		if (cep->tx_full && dev->tbusy) {
-			cep->tx_full = 0;
-			dev->tbusy = 0;
-			mark_bh(NET_BH);
-		}
+	/* Manual says set SDDR, but I can't find anything with that
+	 * name.  I think it is a misprint, and should be SDCR.  This
+	 * has already been set by the communication processor initialization.
+	 */
 
-		cep->dirty_tx = (cbd_t *)bdp;
-	}
+	/* Allocate space for the buffer descriptors in the DP ram.
+	 * These are relative offsets in the DP ram address space.
+	 * Initialize base addresses for the buffer descriptors.
+	 */
+	i = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
+	ep->sen_genscc.scc_rbase = i;
+	cep->rx_bd_base = (cbd_t *)&cp->cp_dpmem[i];
 
-	if (must_restart) {
-		volatile cpm8xx_t *cp;
+	i = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
+	ep->sen_genscc.scc_tbase = i;
+	cep->tx_bd_base = (cbd_t *)&cp->cp_dpmem[i];
 
-		/* Some transmit errors cause the transmitter to shut
-		 * down.  We now issue a restart transmit.  Since the
-		 * errors close the BD and update the pointers, the restart
-		 * _should_ pick up without having to reset any of our
-		 * pointers either.
-		 */
-		cp = cpmp;
-		cp->cp_cpcr =
-		    mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_RESTART_TX) | CPM_CR_FLG;
-		while (cp->cp_cpcr & CPM_CR_FLG);
-	}
+	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
+	cep->cur_rx = cep->rx_bd_base;
 
-	/* Check for receive busy, i.e. packets coming but no place to
-	 * put them.  This "can't happen" because the receive interrupt
-	 * is tossing previous frames.
+	/* Issue init Rx BD command for SCC1.
+	 * Manual says to perform an Init Rx parameters here.  We have
+	 * to perform both Rx and Tx because the SCC may have been
+	 * already running.
+	 * In addition, we have to do it later because we don't yet have
+	 * all of the BD control/status set properly.
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_RX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
 	 */
-	if (int_events & SCCE_ENET_BSY) {
-		cep->stats.rx_dropped++;
-		printk("CPM ENET: BSY can't happen.\n");
-	}
 
-	/* Write the SCC event register with the events we have handled
-	 * to clear them.  Maybe we should do this sooner?
+	/* Initialize function code registers for big-endian.
+	*/
+	ep->sen_genscc.scc_rfcr = SCC_EB;
+	ep->sen_genscc.scc_tfcr = SCC_EB;
+
+	/* Set maximum bytes per receive buffer.
+	 * This appears to be an Ethernet frame size, not the buffer
+	 * fragment size.  It must be a multiple of four.
 	 */
-	cep->sccp->scc_scce = int_events;
+	ep->sen_genscc.scc_mrblr = PKT_MAXBLR_SIZE;
 
-	dev->interrupt = 0;
+	/* Set CRC preset and mask.
+	*/
+	ep->sen_cpres = 0xffffffff;
+	ep->sen_cmask = 0xdebb20e3;
 
-	return;
-}
+	ep->sen_crcec = 0;	/* CRC Error counter */
+	ep->sen_alec = 0;	/* alignment error counter */
+	ep->sen_disfc = 0;	/* discard frame counter */
 
-/* During a receive, the cur_rx points to the current incoming buffer.
- * When we update through the ring, if the next incoming buffer has
- * not been given to the system, we just set the empty indicator,
- * effectively tossing the packet.
- */
-static int
-cpm_enet_rx(struct device *dev)
-{
-	struct	cpm_enet_private *cep;
-	volatile cbd_t	*bdp;
-	struct	sk_buff *skb;
-	ushort	pkt_len;
+	ep->sen_pads = 0x8888;	/* Tx short frame pad character */
+	ep->sen_retlim = 15;	/* Retry limit threshold */
 
-	cep = (struct cpm_enet_private *)dev->priv;
+	ep->sen_maxflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
+	ep->sen_minflr = PKT_MINBUF_SIZE;  /* minimum frame length register */
+
+	ep->sen_maxd1 = PKT_MAXBUF_SIZE;	/* maximum DMA1 length */
+	ep->sen_maxd2 = PKT_MAXBUF_SIZE;	/* maximum DMA2 length */
 
-	/* First, grab all of the stats for the incoming packet.
-	 * These get messed up if we get called due to a busy condition.
-	 */
-	bdp = cep->cur_rx;
+	/* Clear hash tables.
+	*/
+	ep->sen_gaddr1 = 0;
+	ep->sen_gaddr2 = 0;
+	ep->sen_gaddr3 = 0;
+	ep->sen_gaddr4 = 0;
+	ep->sen_iaddr1 = 0;
+	ep->sen_iaddr2 = 0;
+	ep->sen_iaddr3 = 0;
+	ep->sen_iaddr4 = 0;
 
-for (;;) {
-	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
-		break;
-		
-#ifndef final_version
-	/* Since we have allocated space to hold a complete frame, both
-	 * the first and last indicators should be set.
+	/* Set Ethernet station address.  This must come from the
+	 * Vital Product Data (VPD) EEPROM.....as soon as I get the
+	 * I2C interface working.....
+	 *
+	 * Since we performed a diskless boot, the Ethernet controller
+	 * has been initialized and we copy the address out into our
+	 * own structure.
 	 */
-	if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) !=
-		(BD_ENET_RX_FIRST | BD_ENET_RX_LAST))
-			printk("CPM ENET: rcv is not first+last\n");
+#ifdef notdef
+	ep->sen_paddrh = my_enet_addr[0];
+	ep->sen_paddrm = my_enet_addr[1];
+	ep->sen_paddrl = my_enet_addr[2];
+#else
+	eap = (unsigned char *)&(ep->sen_paddrh);
+	for (i=5; i>=0; i--)
+		dev->dev_addr[i] = *eap++;
 #endif
 
-	/* Frame too long or too short.
-	*/
-	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
-		cep->stats.rx_length_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
-		cep->stats.rx_frame_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
-		cep->stats.rx_crc_errors++;
-	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
-		cep->stats.rx_crc_errors++;
+	ep->sen_pper = 0;	/* 'cause the book says so */
+	ep->sen_taddrl = 0;	/* temp address (LSB) */
+	ep->sen_taddrm = 0;
+	ep->sen_taddrh = 0;	/* temp address (MSB) */
 
-	/* Report late collisions as a frame error.
-	 * On this error, the BD is closed, but we don't know what we
-	 * have in the buffer.  So, just drop this frame on the floor.
+	/* Now allocate the host memory pages and initialize the
+	 * buffer descriptors.
 	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
-		cep->stats.rx_frame_errors++;
-	}
-	else {
-
-		/* Process the incoming frame.
-		*/
-		cep->stats.rx_packets++;
-		pkt_len = bdp->cbd_datlen;
-		cep->stats.rx_bytes += pkt_len;
+	bdp = cep->tx_bd_base;
+	for (i=0; i<TX_RING_SIZE; i++) {
 
-		/* This does 16 byte alignment, much more than we need.
+		/* Initialize the BD for every fragment in the page.
 		*/
-		skb = dev_alloc_skb(pkt_len);
-
-		if (skb == NULL) {
-			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-			cep->stats.rx_dropped++;
-		}
-		else {
-			skb->dev = dev;
-			skb_put(skb,pkt_len);	/* Make room */
-			eth_copy_and_sum(skb,
-				(unsigned char *)__va(bdp->cbd_bufaddr),
-				pkt_len, 0);
-			skb->protocol=eth_type_trans(skb,dev);
-			netif_rx(skb);
-		}
+		bdp->cbd_sc = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
 	}
 
-	/* Clear the status flags for this buffer.
+	/* Set the last buffer to wrap.
 	*/
-	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
 
-	/* Mark the buffer empty.
-	*/
-	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+	bdp = cep->rx_bd_base;
+	for (i=0; i<CPM_ENET_RX_PAGES; i++) {
 
-	/* Update BD pointer to next entry.
-	*/
-	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
-		bdp = cep->rx_bd_base;
-	else
-		bdp++;
+		/* Allocate a page.
+		*/
+		mem_addr = __get_free_page(GFP_KERNEL);
 
-   }
-	cep->cur_rx = (cbd_t *)bdp;
+		/* Make it uncached.
+		*/
+		pte = va_to_pte(&init_task, mem_addr);
+		pte_val(*pte) |= _PAGE_NO_CACHE;
+		flush_tlb_page(current->mm->mmap, mem_addr);
 
-	return 0;
-}
+		/* Initialize the BD for every fragment in the page.
+		*/
+		for (j=0; j<CPM_ENET_RX_FRPPG; j++) {
+			bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR;
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			mem_addr += CPM_ENET_RX_FRSIZE;
+			bdp++;
+		}
+	}
 
-static int
-cpm_enet_close(struct device *dev)
-{
-	/* Don't know what to do yet.
+	/* Set the last buffer to wrap.
 	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
 
-	return 0;
-}
+	/* Let's re-initialize the channel now.  We have to do it later
+	 * than the manual describes because we have just now finished
+	 * the BD initialization.
+	 */
+	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	while (cp->cp_cpcr & CPM_CR_FLG);
 
-static struct net_device_stats *cpm_enet_get_stats(struct device *dev)
-{
-	struct cpm_enet_private *cep = (struct cpm_enet_private *)dev->priv;
+	cep->skb_cur = cep->skb_dirty = 0;
 
-	return &cep->stats;
-}
+	sccp->scc_scce = 0xffff;	/* Clear any pending events */
 
-/* Set or clear the multicast filter for this adaptor.
- * Skeleton taken from sunlance driver.
- * The CPM Ethernet implementation allows Multicast as well as individual
- * MAC address filtering.  Some of the drivers check to make sure it is
- * a group multicast address, and discard those that are not.  I guess I
- * will do the same for now, but just remove the test if you want
- * individual filtering as well (do the upper net layers want or support
- * this kind of feature?).
- */
+	/* Enable interrupts for transmit error, complete frame
+	 * received, and any transmit buffer we have also set the
+	 * interrupt flag.
+	 */
+	sccp->scc_sccm = (SCCE_ENET_TXE | SCCE_ENET_RXF | SCCE_ENET_TXB);
 
-static void set_multicast_list(struct device *dev)
-{
-	struct	cpm_enet_private *cep;
-	struct	dev_mc_list *dmi;
-	u_char	*mcptr, *tdptr;
-	volatile scc_enet_t *ep;
-	int	i, j;
+	/* Install our interrupt handler.
+	*/
+	cpm_install_handler(CPMVEC_SCC1, cpm_enet_interrupt, dev);
 
-	cep = (struct cpm_enet_private *)dev->priv;
+	/* Set GSMR_H to enable all normal operating modes.
+	 * Set GSMR_L to enable Ethernet to MC68160.
+	 */
+	sccp->scc_gsmrh = 0;
+	sccp->scc_gsmrl = (SCC_GSMRL_TCI | SCC_GSMRL_TPL_48 | SCC_GSMRL_TPP_10 | SCC_GSMRL_MODE_ENET);
 
-	/* Get pointer to SCC1 area in parameter RAM.
+	/* Set sync/delimiters.
 	*/
-	ep = (scc_enet_t *)dev->base_addr;
+	sccp->scc_dsr = 0xd555;
 
-	if (dev->flags&IFF_PROMISC) {
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
-		cep->sccp->scc_pmsr |= SCC_PMSR_PRO;
-	} else {
+	/* Set processing mode.  Use Ethernet CRC, catch broadcast, and
+	 * start frame search 22 bit times after RENA.
+	 */
+	sccp->scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_BRO | SCC_PMSR_NIB22);
 
-		cep->sccp->scc_pmsr &= ~SCC_PMSR_PRO;
+	/* It is now OK to enable the Ethernet transmitter.
+	*/
+	immap->im_ioport.iop_pcpar |= PC_ENET_TENA;
+	immap->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
 
-		if (dev->flags & IFF_ALLMULTI) {
-			/* Catch all multicast addresses, so set the
-			 * filter to all 1's.
-			 */
-			ep->sen_gaddr1 = 0xffff;
-			ep->sen_gaddr2 = 0xffff;
-			ep->sen_gaddr3 = 0xffff;
-			ep->sen_gaddr4 = 0xffff;
-		}
-		else {
-			/* Clear filter and add the addresses in the list.
-			*/
-			ep->sen_gaddr1 = 0;
-			ep->sen_gaddr2 = 0;
-			ep->sen_gaddr3 = 0;
-			ep->sen_gaddr4 = 0;
+	dev->base_addr = (unsigned long)ep;
+	dev->priv = cep;
+	dev->name = "CPM_ENET";
 
-			dmi = dev->mc_list;
+	/* The CPM Ethernet specific entries in the device structure. */
+	dev->open = cpm_enet_open;
+	dev->hard_start_xmit = cpm_enet_start_xmit;
+	dev->stop = cpm_enet_close;
+	dev->get_stats = cpm_enet_get_stats;
+	dev->set_multicast_list = set_multicast_list;
 
-			for (i=0; i<dev->mc_count; i++) {
-				
-				/* Only support group multicast for now.
-				*/
-				if (!(dmi->dmi_addr[0] & 1))
-					continue;
+	/* And last, enable the transmit and receive processing.
+	*/
+	sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 
-				/* The address in dmi_addr is LSB first,
-				 * and taddr is MSB first.  We have to
-				 * copy bytes MSB first from dmi_addr.
-				 */
-				mcptr = (u_char *)dmi->dmi_addr + 5;
-				tdptr = (u_char *)&ep->sen_taddrh;
-				for (j=0; j<6; j++)
-					*tdptr++ = *mcptr--;
+	printk("CPM ENET Version 0.1, ");
+	for (i=0; i<5; i++)
+		printk("%02x:", dev->dev_addr[i]);
+	printk("%02x\n", dev->dev_addr[5]);
 
-				/* Ask CPM to run CRC and set bit in
-				 * filter mask.
-				 */
-				cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG;
-				while (cpmp->cp_cpcr & CPM_CR_FLG);
-			}
-		}
-	}
+	return 0;
 }
+
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.1.100/linux/arch/ppc/8xx_io/uart.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/8xx_io/uart.c	Fri May  8 00:18:13 1998
@@ -59,6 +59,7 @@
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
+static int serial_console_setup(struct console *co, char *options);
 
 /*
  * Serial driver configuration section.  Here are the various options:
@@ -277,7 +278,7 @@
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, *cp;
-	int	ignored = 0;
+	/*int	ignored = 0;*/
 	int	i;
 	ushort	status;
 	struct	async_icount *icount;
@@ -594,10 +595,10 @@
 	tty_hangup(tty);
 }
 
-static void rs_8xx_timer(void)
+/*static void rs_8xx_timer(void)
 {
 	printk("rs_8xx_timer\n");
-}
+}*/
 
 
 static int startup(ser_info_t *info)
@@ -1607,7 +1608,7 @@
 {
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 	unsigned long orig_jiffies, char_time;
-	int lsr;
+	/*int lsr;*/
 	volatile cbd_t *bdp;
 	
 	if (serial_paranoia_check(info, tty->device, "rs_wait_until_sent"))
@@ -1645,7 +1646,7 @@
 		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
 #endif
 		current->state = TASK_INTERRUPTIBLE;
-/*		current->counter = 0;	/* make us low-priority */
+/*		current->counter = 0;	 make us low-priority */
 		current->timeout = jiffies + char_time;
 		schedule();
 		if (signal_pending(current))
@@ -2030,6 +2031,185 @@
  	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
 }
 
+
+/*
+ * The serial console driver used during boot.  Note that these names
+ * clash with those found in "serial.c", so we currently can't support
+ * the 16xxx uarts and these at the same time.  I will fix this to become
+ * an indirect function call from tty_io.c (or something).
+ */
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+/*
+ * 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 *c, const char *s,
+				unsigned count)
+{
+	struct		serial_state	*ser;
+	ser_info_t			*info;
+	unsigned			i;
+	volatile	cbd_t		*bdp, *bdbase;
+	volatile	smc_uart_t	*up;
+	volatile	u_char		*cp;
+
+	ser = rs_table + c->index;
+
+	/* If the port has been initialized for general use, we have
+	 * to use the buffer descriptors allocated there.  Otherwise,
+	 * we simply use the single buffer allocated.
+	 */
+	if ((info = (ser_info_t *)ser->info) != NULL) {
+		bdp = info->tx_cur;
+		bdbase = info->tx_bd_base;
+	}
+	else {
+		/* Pointer to UART in parameter ram.
+		*/
+		up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
+
+		/* Get the address of the host memory buffer.
+		 */
+		bdp = bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+	}
+
+	/*
+	 * We need to gracefully shut down the transmitter, disable
+	 * interrupts, then send our bytes out.
+	 */
+
+	/*
+	 * Now, do each character.  This is not as bad as it looks
+	 * since this is a holding FIFO and not a transmitting FIFO.
+	 * We could add the complexity of filling the entire transmit
+	 * buffer, but we would just wait longer between accesses......
+	 */
+	for (i = 0; i < count; i++, s++) {
+		/* Wait for transmitter fifo to empty.
+		 * Ready indicates output is ready, and xmt is doing
+		 * that, not that it is ready for us to send.
+		 */
+		while (bdp->cbd_sc & BD_SC_READY);
+		/* Send the character out. */
+		cp = __va(bdp->cbd_bufaddr);
+		*cp = *s;
+		
+		bdp->cbd_datlen = 1;
+		bdp->cbd_sc |= BD_SC_READY;
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = bdbase;
+		else
+			bdp++;
+
+		/* if a LF, also do CR... */
+		if (*s == 10) {
+			while (bdp->cbd_sc & BD_SC_READY);
+			cp = __va(bdp->cbd_bufaddr);
+			*cp = 13;
+			bdp->cbd_datlen = 1;
+			bdp->cbd_sc |= BD_SC_READY;
+
+			if (bdp->cbd_sc & BD_SC_WRAP) {
+				bdp = bdbase;
+			}
+			else {
+				bdp++;
+			}
+		}
+	}
+
+	/*
+	 * Finally, Wait for transmitter & holding register to empty
+	 *  and restore the IER
+	 */
+	while (bdp->cbd_sc & BD_SC_READY);
+
+	if (info)
+		info->tx_cur = (cbd_t *)bdp;
+}
+
+/*
+ * Receive character from the serial port.  This only works well
+ * before the port is initialize for real use.
+ */
+static int serial_console_wait_key(struct console *co)
+{
+	struct serial_state		*ser;
+	u_char				c, *cp;
+	ser_info_t			*info;
+	volatile	cbd_t		*bdp;
+	volatile	smc_uart_t	*up;
+
+	ser = rs_table + co->index;
+
+	/* Pointer to UART in parameter ram.
+	*/
+	up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
+
+	/* Get the address of the host memory buffer.
+	 * If the port has been initialized for general use, we must
+	 * use information from the port structure.
+	 */
+	if ((info = (ser_info_t *)ser->info))
+		bdp = info->rx_cur;
+	else
+		bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+	/*
+	 * We need to gracefully shut down the receiver, disable
+	 * interrupts, then read the input.
+	 */
+	while (bdp->cbd_sc & BD_SC_EMPTY);	/* Wait for a character */
+	cp = __va(bdp->cbd_bufaddr);
+
+	if (info) {
+		if (bdp->cbd_sc & BD_SC_WRAP) {
+			bdp = info->rx_bd_base;
+		}
+		else {
+			bdp++;
+		}
+		info->rx_cur = (cbd_t *)bdp;
+	}
+
+	c = *cp;
+	return((int)c);
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
+}
+
+
+static struct console sercons = {
+	"ttyS",
+	serial_console_write,
+	NULL,
+	serial_console_device,
+	serial_console_wait_key,
+	NULL,
+	serial_console_setup,
+	CON_PRINTBUFFER,
+	CONFIG_SERIAL_CONSOLE_PORT,
+	0,
+	NULL
+};
+
+/*
+ *	Register console.
+ */
+__initfunc (long console_8xx_init(long kmem_start, long kmem_end))
+{
+	register_console(&sercons);
+	return kmem_start;
+}
+
+#endif
+
 /*
  * The serial driver boot-time initialization code!
  */
@@ -2055,7 +2235,8 @@
 
 	/* Initialize the tty_driver structure */
 	
-	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	/*memset(&serial_driver, 0, sizeof(struct tty_driver));*/
+	__clear_user(&serial_driver,sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
 	serial_driver.driver_name = "serial";
 	serial_driver.name = "ttyS";
@@ -2147,7 +2328,8 @@
 #endif
 		info = kmalloc(sizeof(ser_info_t), GFP_KERNEL);
 		if (info) {
-			memset(info, 0, sizeof(ser_info_t));
+			/*memset(info, 0, sizeof(ser_info_t));*/
+			__clear_user(info,sizeof(ser_info_t));
 			info->magic = SERIAL_MAGIC;
 			info->flags = state->flags;
 			info->tqueue.routine = do_softint;
@@ -2267,159 +2449,6 @@
 	return 0;
 }
 
-/*
- * The serial console driver used during boot.  Note that these names
- * clash with those found in "serial.c", so we currently can't support
- * the 16xxx uarts and these at the same time.  I will fix this to become
- * an indirect function call from tty_io.c (or something).
- */
-
-#ifdef CONFIG_SERIAL_CONSOLE
-
-/*
- * 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 *c, const char *s,
-				unsigned count)
-{
-	struct		serial_state	*ser;
-	ser_info_t			*info;
-	unsigned			i;
-	volatile	cbd_t		*bdp, *bdbase;
-	volatile	smc_uart_t	*up;
-	volatile	u_char		*cp;
-
-	ser = rs_table + c->index;
-
-	/* If the port has been initialized for general use, we have
-	 * to use the buffer descriptors allocated there.  Otherwise,
-	 * we simply use the single buffer allocated.
-	 */
-	if ((info = (ser_info_t *)ser->info) != NULL) {
-		bdp = info->tx_cur;
-		bdbase = info->tx_bd_base;
-	}
-	else {
-		/* Pointer to UART in parameter ram.
-		*/
-		up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
-
-		/* Get the address of the host memory buffer.
-		 */
-		bdp = bdbase = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
-	}
-
-	/*
-	 * We need to gracefully shut down the transmitter, disable
-	 * interrupts, then send our bytes out.
-	 */
-
-	/*
-	 * Now, do each character.  This is not as bad as it looks
-	 * since this is a holding FIFO and not a transmitting FIFO.
-	 * We could add the complexity of filling the entire transmit
-	 * buffer, but we would just wait longer between accesses......
-	 */
-	for (i = 0; i < count; i++, s++) {
-
-		/* Wait for transmitter fifo to empty.
-		 * Ready indicates output is ready, and xmt is doing
-		 * that, not that it is ready for us to send.
-		 */
-		while (bdp->cbd_sc & BD_SC_READY);
-
-		/* Send the character out. */
-		cp = __va(bdp->cbd_bufaddr);
-		*cp = *s;
-		bdp->cbd_datlen = 1;
-		bdp->cbd_sc |= BD_SC_READY;
-
-		if (bdp->cbd_sc & BD_SC_WRAP)
-			bdp = bdbase;
-		else
-			bdp++;
-
-		/* if a LF, also do CR... */
-		if (*s == 10) {
-			while (bdp->cbd_sc & BD_SC_READY);
-			cp = __va(bdp->cbd_bufaddr);
-			*cp = 13;
-			bdp->cbd_datlen = 1;
-			bdp->cbd_sc |= BD_SC_READY;
-
-			if (bdp->cbd_sc & BD_SC_WRAP) {
-				bdp = bdbase;
-			}
-			else {
-				bdp++;
-			}
-		}
-	}
-
-	/*
-	 * Finally, Wait for transmitter & holding register to empty
-	 *  and restore the IER
-	 */
-	while (bdp->cbd_sc & BD_SC_READY);
-
-	if (info)
-		info->tx_cur = (cbd_t *)bdp;
-}
-
-/*
- * Receive character from the serial port.  This only works well
- * before the port is initialize for real use.
- */
-static int serial_console_wait_key(struct console *co)
-{
-	struct serial_state		*ser;
-	u_char				c, *cp;
-	ser_info_t			*info;
-	volatile	cbd_t		*bdp;
-	volatile	smc_uart_t	*up;
-
-	ser = rs_table + co->index;
-
-	/* Pointer to UART in parameter ram.
-	*/
-	up = (smc_uart_t *)&cpmp->cp_dparam[ser->port];
-
-	/* Get the address of the host memory buffer.
-	 * If the port has been initialized for general use, we must
-	 * use information from the port structure.
-	 */
-	if ((info = ser->info))
-		bdp = info->rx_cur;
-	else
-		bdp = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
-
-	/*
-	 * We need to gracefully shut down the receiver, disable
-	 * interrupts, then read the input.
-	 */
-	while (bdp->cbd_sc & BD_SC_EMPTY);	/* Wait for a character */
-	cp = __va(bdp->cbd_bufaddr);
-
-	if (info) {
-		if (bdp->cbd_sc & BD_SC_WRAP) {
-			bdp = info->rx_bd_base;
-		}
-		else {
-			bdp++;
-		}
-		info->rx_cur = (cbd_t *)bdp;
-	}
-
-	c = *cp;
-	return((int)c);
-}
-
-static kdev_t serial_console_device(struct console *c)
-{
-	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
-}
-
 /* This must always be called before the rs_8xx_init() function, otherwise
  * it blows away the port control information.
 */
@@ -2431,7 +2460,6 @@
 	volatile	cpm8xx_t	*cp;
 	volatile	smc_t		*sp;
 	volatile	smc_uart_t	*up;
-
 	co->cflag = CREAD|CLOCAL|B9600|CS8;
 
 	ser = rs_table + co->index;
@@ -2441,7 +2469,6 @@
 	/* Right now, assume we are using SMCs.
 	*/
 	sp = &cp->cp_smc[ser->smc_scc_num];
-
 	/* When we get here, the CPM has been reset, so we need
 	 * to configure the port.
 	 * We need to allocate a transmit and receive buffer descriptor
@@ -2486,8 +2513,12 @@
 	/* Send the CPM an initialize command.
 	*/
 	cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+	/*
+	 * delay for a bit - this is necessary on my board!
+	 *  -- Cort
+	 */
+	printk("");
 	while (cp->cp_cpcr & CPM_CR_FLG);
-
 	/* Set UART mode, 8 bit, no parity, one stop.
 	 * Enable receive and transmit.
 	 */
@@ -2496,35 +2527,10 @@
 	/* Set up the baud rate generator.
 	*/
 	mbx_cpm_setbrg(ser->smc_scc_num, 9600);
- 
+
 	/* And finally, enable Rx and Tx.
 	*/
 	sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
 
 	return 0;
 }
-
-static struct console sercons = {
-	"ttyS",
-	serial_console_write,
-	NULL,
-	serial_console_device,
-	serial_console_wait_key,
-	NULL,
-	serial_console_setup,
-	CON_PRINTBUFFER,
-	CONFIG_SERIAL_CONSOLE_PORT,
-	0,
-	NULL
-};
-
-/*
- *	Register console.
- */
-__initfunc (long console_8xx_init(long kmem_start, long kmem_end))
-{
-	register_console(&sercons);
-	return kmem_start;
-}
-
-#endif
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.1.100/linux/arch/ppc/Makefile	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/Makefile	Fri May  8 00:09:20 1998
@@ -95,6 +95,8 @@
 	@$(MAKEBOOT) clean
 	@$(MAKECHRPBOOT) clean
 
+archmrproper:
+
 archdep:
 	$(MAKEBOOT) fastdep
 	$(MAKECHRPBOOT) fastdep
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.1.100/linux/arch/ppc/boot/Makefile	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/boot/Makefile	Fri May  8 00:18:13 1998
@@ -69,9 +69,25 @@
 		--add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.initrd.tmp $@
 	rm zvmlinux.initrd.tmp
-
-else
-zvmlinux.initrd:
+endif
+ifeq ($(CONFIG_MBX),y)
+zvmlinux.initrd: zvmlinux
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=initrd=ramdisk.image.gz \
+		--add-section=image=../coffboot/vmlinux.gz \
+		zvmlinux.initrd.tmp zvmlinux.initrd
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \
+		-DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \
+		-DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \
+		-DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \
+		-DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=initrd=ramdisk.image.gz \
+		--add-section=image=../coffboot/vmlinux.gz \
+		zvmlinux.initrd.tmp $@
+	rm zvmlinux.initrd.tmp
 endif
 
 zImage: zvmlinux mkprep
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.1.100/linux/arch/ppc/boot/head.S	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/boot/head.S	Fri May  8 00:18:13 1998
@@ -43,6 +43,28 @@
 	ori	r4,r4,MSR_EE
 	andc	r3,r3,r4
 	mtmsr	r3
+/* check if we need to relocate ourselves to the link addr or were we
+   loaded there to begin with -- Cort */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	mflr	r3
+	subi	r3,r3,4		/* we get the nip, not the ip of the branch */
+	mr	r8,r3
+	cmp	0,r3,r4
+	bne	1010f
+/* compute size of whole image in words.  this should be moved to
+ * start_ldr() -- Cort
+ */
+	lis	r4,start@h
+	ori	r4,r4,start@l
+	lis	r5,end@h
+	ori	r5,r5,end@l
+	addi	r5,r5,3		/* round up */
+	sub	r5,r5,r4
+	srwi	r5,r5,2
+	mr	r7,r5
+	b	start_ldr
+1010:
 /* Copy relocation code down to location 0x0100 (where we hope it's safe!) */
 	mflr	r3
 	addi	r5,r3,start_ldr-start_
@@ -115,13 +137,18 @@
 	andc	r1,r1,r2
 /* Run loader */
 #ifdef CONFIG_MBX
+        mr      r21, r11
         bl      serial_init             /* Init MBX serial port */
-#define ILAP_ADDRESS    0xfa000020
-        lis     r8, ILAP_ADDRESS@h
-        lwz     r8, ILAP_ADDRESS@l(r8)
+        mr      r11, r21
+	lis	r8,start@h
+	ori	r8,r8,start@l
 	li	r9,end@h
 	ori	r9,r9,end@l
 	sub	r7,r8,r9
+	srwi	r7,r7,2
+#define ILAP_ADDRESS    0xfa000020
+        lis     r8, ILAP_ADDRESS@h
+        lwz     r8, ILAP_ADDRESS@l(r8)
         addis   r8, r8, 1               /* Add 64K */
 #endif	
 	mr	r3,r8			/* Load point */
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.1.100/linux/arch/ppc/boot/misc.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/boot/misc.c	Fri May  8 00:18:13 1998
@@ -11,22 +11,34 @@
 #include "asm/residual.h"
 #include <elf.h>
 #include <linux/config.h>
+#include <asm/page.h>
 #ifdef CONFIG_MBX
 #include <asm/mbx.h>
 bd_t	hold_board_info;
 #endif
 
-/* this is where the INITRD gets moved to for safe keeping */
-#define INITRD_DESTINATION /*0x00f00000*/ 0x01800000
-#ifdef CONFIG_8xx
-char *avail_ram = (char *) 0x00200000;
-char *end_avail = (char *) 0x00400000;
-#else /* CONFIG_8xx */
-/* this will do for now - Cort */
-char *avail_ram = (char *) 0x00800000; /* start with 8M */
-/* assume 15M max since this is where we copy the initrd to -- Cort */
-char *end_avail = (char *) INITRD_DESTINATION; 
-#endif /* CONFIG_8xx */
+/*
+ * MBX: loads at:      	0x00200000
+ *      board data at: 	end of ram
+ * PREP:
+ *  powerstack 1:
+ *      network load at:   configurable - should set to link addr-0x400
+ *                         exec. addr set to link addr
+ *            such as load: 0x005ffc00 exec 0x00600000
+ *      hd/floppy/tape load at:
+ *  powerstack 2:
+ *      loads at:       0x00400000
+ *  IBM 830 (carolina):
+ *      loads at:	???
+ *
+ * Please send me load/board info and such data for hardware not
+ * listed here so I can keep track since things are getting tricky
+ * with the different load addrs with different firmware.  This will
+ * help to avoid breaking the load/boot process.
+ * -- Cort
+ */
+char *avail_ram;
+char *end_avail;
 
 char cmd_line[256];
 RESIDUAL hold_residual;
@@ -313,24 +325,35 @@
 	orig_y = 24;
 	
 	
-#ifndef CONFIG_8xx
+#ifndef CONFIG_MBX
 	vga_init(0xC0000000);
 	/* copy the residual data */
 	if (residual)
 		memcpy(&hold_residual,residual,sizeof(RESIDUAL));
-#endif /* CONFIG_8xx */
-#ifdef CONFIG_MBX	
+#else /* CONFIG_MBX */
 	/* copy board data */
 	if (residual)
 		_bcopy((char *)residual, (char *)&hold_board_info,
 		       sizeof(hold_board_info));
-#endif /* CONFIG_8xx */
+#endif /* CONFIG_MBX */
+	
+	/* MBX/prep put the board/residual data at the end of memory */
+	if ( residual )
+		end_avail = (char *)PAGE_ALIGN((unsigned long)residual);
+	/* prep netboot looses the residual */
+	else
+		end_avail = (char *)0x00800000;
 	
 
 	puts("loaded at:     "); puthex(load_addr);
 	puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
-	puts("relocated to:  "); puthex((unsigned long)&start);
-	puts(" "); puthex((unsigned long)((unsigned long)&start + (4*num_words))); puts("\n");
+	if ( (unsigned long)load_addr != (unsigned long)&start )
+	{
+		puts("relocated to:  "); puthex((unsigned long)&start);
+		puts(" ");
+		puthex((unsigned long)((unsigned long)&start + (4*num_words)));
+		puts("\n");
+	}
 
 	if ( residual )
 	{
@@ -357,6 +380,8 @@
 		puts("\n");
 	}
 
+	/* we have to subtract 0x10000 here to correct for objdump including the
+	   size of the elf header which we strip -- Cort */
 	zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET);
 	zimage_size = ZIMAGE_SIZE;
 	puts("zimage at:     "); puthex((unsigned long)zimage_start);
@@ -367,20 +392,45 @@
 	else
 		initrd_start = 0;
 	initrd_end = INITRD_SIZE + initrd_start;
-  
+
+	/*
+	 * setup avail_ram - this is the first part of ram usable
+	 * by the uncompress code. -- Cort
+	 */
+	avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
+	if ( (load_addr+(num_words*4)) > (unsigned long) avail_ram )
+		avail_ram = (char *)(load_addr+(num_words*4));
+	if ( ((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram )
+		avail_ram = (char *)((unsigned long)&start+(num_words*4));
+	
 	/* relocate initrd */
 	if ( initrd_start )
 	{
 		puts("initrd at:     "); puthex(initrd_start);
 		puts(" "); puthex(initrd_end); puts("\n");
-		
-		memcpy ((void *)INITRD_DESTINATION,(void *)initrd_start,
+		/*
+		 * Memory is really tight on the MBX (we can assume 4M)
+		 * so put the initrd at the TOP of ram, and set end_avail
+		 * to right after that.
+		 *
+		 * I should do something like this for prep, too and keep
+		 * a variable end_of_DRAM to keep track of what we think the
+		 * max ram is.
+		 * -- Cort
+		 */
+		memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
+			(void *)initrd_start,
 			INITRD_SIZE );
-		initrd_end = INITRD_DESTINATION + INITRD_SIZE;
-		initrd_start = INITRD_DESTINATION;
-		puts("Moved initrd to:  "); puthex(initrd_start);
+		initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE);
+		initrd_end = initrd_start + INITRD_SIZE;
+		end_avail = (char *)initrd_start;
+		puts("relocated to:  "); puthex(initrd_start);
 		puts(" "); puthex(initrd_end); puts("\n");
 	}
+	
+	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
+	puthex((unsigned long)end_avail); puts("\n");
+	
 #ifndef CONFIG_MBX
 	CRT_tstc();  /* Forces keyboard to be initialized */
 #endif	
@@ -417,13 +467,14 @@
        
 	puts("Uncompressing Linux...");
 
-	/* these _bcopy() calls are here so I can add breakpoints to the boot for mbx -- Cort */
-	/*_bcopy( (char *)0x100,(char *)&sanity, 0x2000-0x100);*/
 	gunzip(0, 0x400000, zimage_start, &zimage_size);
-	/*_bcopy( (char *)&sanity,(char *)0x100,0x2000-0x100);*/
 	puts("done.\n");
 	puts("Now booting the kernel\n");
+#ifndef CONFIG_MBX	
 	return (unsigned long)&hold_residual;
+#else
+	return (unsigned long)&hold_board_info;
+#endif	
 }
 
 void puthex(unsigned long val)
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/chrp_defconfig linux/arch/ppc/chrp_defconfig
--- v2.1.100/linux/arch/ppc/chrp_defconfig	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/chrp_defconfig	Fri May  8 00:18:13 1998
@@ -226,7 +226,6 @@
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
-CONFIG_CDROM=y
 
 #
 # Filesystems
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.1.100/linux/arch/ppc/common_defconfig	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/common_defconfig	Fri May  8 00:18:13 1998
@@ -219,7 +219,6 @@
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
-CONFIG_CDROM=y
 
 #
 # Filesystems
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.1.100/linux/arch/ppc/config.in	Sat May  2 14:19:52 1998
+++ linux/arch/ppc/config.in	Fri May  8 00:18:13 1998
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.47 1998/04/10 10:19:04 geert Exp $
+# $Id: config.in,v 1.53 1998/05/02 12:06:12 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -28,6 +28,10 @@
 	 MBX		CONFIG_MBX" PReP
 endmenu
 
+if [ "$CONFIG_MBX" = "y" ];then
+  define_bool CONFIG_SERIAL_CONSOLE y
+fi
+
 if [ "$CONFIG_ALL_PPC" != "y" ]; then
   define_bool CONFIG_MACH_SPECIFIC y
 fi
@@ -84,8 +88,6 @@
   else
     define_bool CONFIG_PMAC_CONSOLE y
   fi
-  define_bool CONFIG_MAC_KEYBOARD y
-  define_bool CONFIG_MAC_FLOPPY	y
 else
 # if compiling specifically for prep or chrp, or supporting all arch's
   if [ "$CONFIG_ABSTRACT_CONSOLE" = "y" ]; then
@@ -95,9 +97,10 @@
   else
     bool 'Support for PowerMac console' CONFIG_PMAC_CONSOLE
   fi
-  bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD
-  bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
 fi
+bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD
+bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
+bool 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'Support for PowerMac mouse (EXPERIMENTAL)' CONFIG_MACMOUSE
 fi
@@ -122,7 +125,7 @@
 
 source drivers/pnp/Config.in
 source drivers/block/Config.in
-source drivers.new/Config.in
+#source drivers.new/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
@@ -179,11 +182,12 @@
 
 source drivers/char/Config.in
 
-mainmenu_option next_comment
-comment 'Sound'
-
-tristate 'Sound card support' CONFIG_SOUND
-if [ "$CONFIG_SOUND" != "n" ]; then
-  source drivers/sound/Config.in
-fi
-endmenu
+#mainmenu_option next_comment
+#comment 'Sound'
+#
+#tristate 'Sound card support' CONFIG_SOUND
+#if [ "$CONFIG_SOUND" != "n" ]; then
+#  source drivers/sound/Config.in
+#fi
+#
+#endmenu
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.1.100/linux/arch/ppc/defconfig	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/defconfig	Fri May  8 00:18:13 1998
@@ -1,42 +1,54 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 
 #
 # Platform support
 #
 CONFIG_PPC=y
-# CONFIG_6xx is not set
-CONFIG_8xx=y
-# CONFIG_PMAC is not set
+CONFIG_6xx=y
+# CONFIG_8xx is not set
+CONFIG_PMAC=y
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
 # CONFIG_ALL_PPC is not set
-CONFIG_MBX=y
+# CONFIG_APUS is not set
+# CONFIG_MBX is not set
 CONFIG_MACH_SPECIFIC=y
 
 #
 # General setup
 #
-# CONFIG_EXPERIMENTAL is not set
-# CONFIG_MODULES is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
 CONFIG_PCI=y
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
 # CONFIG_BINFMT_JAVA is not set
 # CONFIG_PARPORT is not set
-# CONFIG_PMAC_CONSOLE is not set
-# CONFIG_MAC_KEYBOARD is not set
-# CONFIG_MAC_FLOPPY is not set
-# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_ABSTRACT_CONSOLE is not set
+CONFIG_PMAC_CONSOLE=y
+CONFIG_MAC_KEYBOARD=y
+CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
+CONFIG_MACMOUSE=y
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_KGDB is not set
 # CONFIG_XMON is not set
-CONFIG_VGA_CONSOLE=y
+CONFIG_CONTROL_VIDEO=y
+CONFIG_PLATINUM_VIDEO=y
+CONFIG_VALKYRIE_VIDEO=y
+CONFIG_ATY_VIDEO=y
+CONFIG_IMSTT_VIDEO=y
+CONFIG_CHIPS_VIDEO=y
 
 #
 # Plug and Play support
@@ -47,8 +59,25 @@
 # Floppy, IDE, and other block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-# CONFIG_BLK_DEV_HD_ONLY is not set
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_IDEPCI is not set
+# CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
@@ -60,41 +89,112 @@
 # CONFIG_BLK_DEV_HD is not set
 
 #
-# NEW devices (io_request, all ALPHA and dangerous)
-#
-# CONFIG_IO_REQUEST is not set
-
-#
 # Networking options
 #
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
-# CONFIG_NET_ALIAS is not set
+CONFIG_NET_ALIAS=y
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_PNP is not set
 # CONFIG_IP_ACCT is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_IP_ALIAS=y
 # CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_RARP is not set
+
+#
+# (it is safe to leave these untouched)
+#
+CONFIG_INET_RARP=y
 CONFIG_IP_NOSR=y
-# CONFIG_SKB_LARGE is not set
+CONFIG_SKB_LARGE=y
+# CONFIG_IPV6 is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_ATALK=m
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_PROFILE is not set
 
 #
 # SCSI support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+CONFIG_SCSI_AIC7XXX=m
+# CONFIG_OVERRIDE_CMDS is not set
+CONFIG_AIC7XXX_PROC_STATS=y
+CONFIG_AIC7XXX_RESET_DELAY=15
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 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_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP 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_SCSI_DEBUG is not set
+CONFIG_SCSI_MESH=y
+CONFIG_SCSI_MESH_SYNC_RATE=5
+CONFIG_SCSI_MAC53C94=y
 
 #
 # Network device support
@@ -104,22 +204,42 @@
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_NET_ETHERNET=y
+CONFIG_MACE=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+CONFIG_NET_EISA=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_DE4X5=m
+CONFIG_DEC_ELCP=m
+# CONFIG_DGRS is not set
+# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_TLAN is not set
+# CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_DLCI is not set
-# CONFIG_PPP is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
+CONFIG_PPP=m
+
+#
+# CCP compressors for PPP are only built as modules.
+#
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
 # CONFIG_TR is not set
-# CONFIG_WAN_DRIVERS is not set
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
+# CONFIG_SHAPER is not set
 
 #
 # Amateur Radio support
@@ -135,7 +255,6 @@
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
-# CONFIG_CDROM is not set
 
 #
 # Filesystems
@@ -143,15 +262,15 @@
 # CONFIG_QUOTA is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_EXT2_FS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_PROC_FS is not set
+CONFIG_VFAT_FS=m
+CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
+CONFIG_NFSD=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_CODA_FS is not set
@@ -160,28 +279,62 @@
 # CONFIG_NTFS_FS is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
+CONFIG_HFS_FS=m
 # CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
 # CONFIG_UFS_FS is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_NLS is not set
+# CONFIG_ADFS_FS is not set
+CONFIG_DEVPTS_FS=y
+CONFIG_MAC_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# 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 is not set
+# 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
 
 #
 # Character devices
 #
-# CONFIG_VT is not set
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+# CONFIG_SOFTCURSOR is not set
+# CONFIG_SERIAL is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_MOUSE is not set
+# CONFIG_UMISC is not set
 # CONFIG_QIC02_TAPE is not set
 # CONFIG_APM 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_NVRAM=y
 # CONFIG_JOYSTICK is not set
 # CONFIG_MISC_RADIO is not set
 
@@ -189,8 +342,3 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.1.100/linux/arch/ppc/kernel/Makefile	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/kernel/Makefile	Fri May  8 00:18:14 1998
@@ -15,7 +15,11 @@
 
 
 O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
-	  bitops.o ppc_htab.o setup.o ptrace.o align.o
+	  bitops.o setup.o ptrace.o align.o
+
+ifndef CONFIG_8xx
+O_OBJS += ppc_htab.o
+endif
 
 ifdef CONFIG_PCI
 O_OBJS += pci.o
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.1.100/linux/arch/ppc/kernel/chrp_setup.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/kernel/chrp_setup.c	Fri May  8 00:18:14 1998
@@ -85,7 +85,7 @@
 {
 }
 
-void chrp_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+__initfunc(void chrp_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq))
 {
 	int i;
 
@@ -221,7 +221,7 @@
 
 	ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
 	
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 	/* initrd_start and size are setup by boot/head.S and kernel/head.S */
 	if ( initrd_start )
 	{
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- v2.1.100/linux/arch/ppc/kernel/chrp_time.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/kernel/chrp_time.c	Fri May  8 00:18:14 1998
@@ -18,6 +18,7 @@
 #include <linux/timex.h>
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
+#include <linux/init.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -30,7 +31,7 @@
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
 
-void chrp_time_init(void)
+__initfunc(void chrp_time_init(void))
 {
 	struct device_node *rtcs;
 	int base;
@@ -150,7 +151,7 @@
 }
 
 
-void chrp_calibrate_decr(void)
+__initfunc(void chrp_calibrate_decr(void))
 {
 	struct device_node *cpu;
 	int freq, *fp, divisor;
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/find_name.c linux/arch/ppc/kernel/find_name.c
--- v2.1.100/linux/arch/ppc/kernel/find_name.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/kernel/find_name.c	Fri May  8 00:18:14 1998
@@ -1,16 +1,16 @@
 #include <stdio.h>
 #include <asm/page.h>
 #include <sys/mman.h>
+#include <strings.h>
 /*
  * Finds a given address in the System.map and prints it out
  * with its neighbors.  -- Cort
  */
 
-void main(int argc, char **argv)
+int main(int argc, char **argv)
 {
 	unsigned long addr, cmp, i;
 	FILE *f;
-	char *ptr;
 	char s[256], last[256];
 	
 	if ( argc < 2 )
@@ -21,7 +21,7 @@
 
 	for ( i = 1 ; argv[i] ; i++ )
 	{
-		sscanf( argv[i], "%0x", &addr );
+		sscanf( argv[i], "%0lx", &addr );
 		/* adjust if addr is relative to kernelbase */
 		if ( addr < PAGE_OFFSET )
 			addr += PAGE_OFFSET;
@@ -35,7 +35,7 @@
 		while ( !feof(f) )
 		{
 			fgets(s, 255 , f);
-			sscanf( s, "%0x", &cmp );
+			sscanf( s, "%0lx", &cmp );
 			if ( addr < cmp )
 				break;
 			strcpy( last, s);
@@ -44,4 +44,5 @@
 		printf( "%s", last);
 	}		
 	fclose(f);
+	return 0;
 }
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.1.100/linux/arch/ppc/kernel/head.S	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/head.S	Fri May  8 00:18:14 1998
@@ -325,7 +325,7 @@
 	ori	r8, r8, MD_SVALID	/* Make it valid */
 	mtspr	MD_TWC, r8
 	lis	r8, 0xfa000000@h	/* Create paddr for TLB */
-	ori	r8, r8, MI_BOOTINIT
+	ori	r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
 	mtspr	MD_RPN, r8
 #endif
 
@@ -338,19 +338,17 @@
 	mtspr	DC_CST, r8
 	lis	r8, IDC_ENABLE@h
 	mtspr	IC_CST, r8
-#ifdef notdef
+#if 0
 	mtspr	DC_CST, r8
 #else
 	/* I still have a bug somewhere because the Ethernet driver
 	 * does not want to work with copyback enabled.  For now,
 	 * at least enable write through.
 	 */
-#if 0	
 	lis	r8, DC_SFWT@h
 	mtspr	DC_CST, r8
 	lis	r8, IDC_ENABLE@h
 	mtspr	DC_CST, r8
-#endif	
 #endif
 
 /* We now have the lower 8 Meg mapped into TLB entries, and the caches
@@ -689,11 +687,11 @@
 	STD_EXCEPTION(0x1000, SoftEmu, SoftwareEmulation)
 #endif
 
-#ifndef CONFIG_8xx
 /*
  * Handle TLB miss for DATA Load operation on 603/603e
  */
 	. = 0x1100
+#ifndef CONFIG_8xx
 DataLoadTLBMiss:
 #ifdef NO_RELOAD_HTAB
 /*
@@ -1558,11 +1556,12 @@
 	bl	set_mbx_memory
 #endif
 	bl	MMU_init
-
 /*
  * Go back to running unmapped so we can load up new values
  * for SDR1 (hash table pointer) and the segment registers
  * and change to using our exception vectors.
+ * On the 8xx, all we have to do is invalidate the TLB to clear
+ * the old 8M byte TLB mappings and load the page table base register.
  */
 #ifndef CONFIG_8xx
 	lis	r6,_SDR1@ha
@@ -1586,7 +1585,6 @@
 	rfi
 /* Load up the kernel context */
 2:
-
 	SYNC			/* Force all PTE updates to finish */
 	tlbia			/* Clear all TLB entries */
 #ifndef CONFIG_8xx
@@ -1610,7 +1608,6 @@
 	LOAD_BAT(2,32,r3,r4,r5)
 	LOAD_BAT(3,48,r3,r4,r5)
 #endif /* CONFIG_8xx */
-	
 /* Set up for using our exception vectors */
 	/* ptr to phys current tss */
 	tophys(r4,r2,r4)
@@ -1618,7 +1615,6 @@
 	mtspr	SPRG3,r4
 	li	r3,0
 	mtspr	SPRG2,r3	/* 0 => r1 has kernel sp */
-
 /* Now turn on the MMU for real! */
 	li	r4,MSR_KERNEL
 	lis	r3,start_kernel@h
@@ -1893,11 +1889,12 @@
  * page directory loaded into the MMU base register, and set the
  * ASID compare register with the new "context".
  */
-	mtspr	M_CASID, r5		/* Update context */
-	lwz	r5,MM-TSS(r4)		/* Get virtual address of mm */
-	lwz	r5,PGD(r5)		/* get new->mm->pgd */	
-	tophys(r5, r5, 0)		/* convert to phys addr */
-	mtspr	M_TWB, r5		/* Update MMU base address */
+        lwz     r3,MM-TSS(r4)           /* Get virtual address of mm */
+        lwz     r3,PGD(r3)              /* get new->mm->pgd */
+        addis   r3,r3,-KERNELBASE@h     /* convert to phys addr */
+        mtspr   M_TWB, r3               /* Update MMU base address */
+        mtspr   M_CASID, r5             /* Update context */
+        tlbia
 #endif
 	SYNC
 
@@ -2262,18 +2259,6 @@
 	rfi			/* return to caller */
 #endif /* CONFIG_8xx */
 
-#ifdef CONFIG_8xx
-/* This is called during an exec when new page tables are created.
- * It maps to the SET_PAGE_DIR macro.  I guess I should make it an
- * inline function.
- */
-_GLOBAL(set_page_dir)
-	addis	r3,r3,-KERNELBASE@h	/* convert to phys addr */
-	mtspr	M_TWB, r3		/* Update MMU base address */
-	blr
-#endif
-	
-		
 #ifdef __SMP__
 /*
  * Secondary processor begins executing here.
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.1.100/linux/arch/ppc/kernel/idle.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/kernel/idle.c	Fri May  8 00:18:14 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: idle.c,v 1.35 1998/04/07 20:24:23 cort Exp $
+ * $Id: idle.c,v 1.37 1998/04/26 06:59:12 cort Exp $
  *
  * Idle daemon for PowerPC.  Idle daemon will handle any action
  * that needs to be taken when the system becomes idle.
@@ -319,19 +319,18 @@
 	case 6:			/* 603e */
 	case 7:			/* 603ev */
 	case 8:			/* 750 */
-		break;
+		save_flags(msr);
+		cli();
+		if (!need_resched) {
+			asm("mfspr %0,1008" : "=r" (hid0) :);
+			hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
+			hid0 |= powersave_mode | HID0_DPM;
+			asm("mtspr 1008,%0" : : "r" (hid0));
+			msr |= MSR_POW;
+		}
+		restore_flags(msr);
 	default:
 		return;
 	}
 	
-	save_flags(msr);
-	cli();
-	if (!need_resched) {
-		asm("mfspr %0,1008" : "=r" (hid0) :);
-		hid0 &= ~(HID0_NAP | HID0_SLEEP | HID0_DOZE);
-		hid0 |= powersave_mode | HID0_DPM;
-		asm("mtspr 1008,%0" : : "r" (hid0));
-		msr |= MSR_POW;
-	}
-	restore_flags(msr);
 }
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.1.100/linux/arch/ppc/kernel/irq.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/irq.c	Fri May  8 00:18:14 1998
@@ -327,6 +327,9 @@
 			else
 				len += sprintf(buf+len, "  OpenPIC ");
 			break;
+		case _MACH_mbx:
+			len += sprintf(buf+len, "   MPC8xx ");
+			break;
 		}
 
 		len += sprintf(buf+len, "   %s",action->name);
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.1.100/linux/arch/ppc/kernel/mbx_setup.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/mbx_setup.c	Fri May  8 00:18:14 1998
@@ -72,53 +72,19 @@
 #endif
 }
 
-int
-mbx_get_cpuinfo(char *buffer)
-{
-	int	pvr = _get_PVR();
-	int	len;
-	char	*model;
-	bd_t	*bp;
-	extern	RESIDUAL res;
-  
-	/* I know the MPC860 is 0x50.  I don't have the book handy
-	 * to check the others.
-	 */
-	if ((pvr>>16) == 0x50)
-		model = "MPC860";
-	else
-		model = "unknown";
-
-#ifdef __SMP__
-#define CD(X)		(cpu_data[n].X)  
-#else
-#define CD(X) (X)
-#define CPUN 0
-#endif
-	bp = (bd_t *)&res;
-
-	len = sprintf(buffer,"processor\t: %d\n"
-		      "cpu\t\t: %s\n"
-		      "revision\t: %d.%d\n"
-		      "clock\t\t: %d MHz\n"
-		      "bus clock\t: %d MHz\n",
-		      CPUN,
-		      model,
-		      MAJOR(pvr), MINOR(pvr),
-		      bp->bi_intfreq / 1000000,
-		      bp->bi_busfreq / 1000000
-		);
-  
-	return len;
-}
-
 __initfunc(void
 mbx_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
 	int	cpm_page;
-
+	extern char cmd_line[];
+	
 	cpm_page = *memory_start_p;
 	*memory_start_p += PAGE_SIZE;
+	
+	sprintf(cmd_line,
+"%s root=/dev/nfs nfsroot=/sys/mbxroot",
+		cmd_line);
+	printk("Boot arguments: %s\n", cmd_line);
 
 	/* Reset the Communication Processor Module.
 	*/
@@ -128,7 +94,7 @@
 	ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
 #endif
 	
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 #if 0
 	ROOT_DEV = to_kdev_t(0x0200); /* floppy */  
 	rd_prompt = 1;
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.1.100/linux/arch/ppc/kernel/misc.S	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/kernel/misc.S	Fri May  8 00:18:14 1998
@@ -436,8 +436,8 @@
 	.long sys_time
 	.long sys_mknod
 	.long sys_chmod		/* 15 */
-	.long sys_chown
-	.long /*sys_break*/ sys_ni_syscall
+	.long sys_lchown
+	.long sys_ni_syscall
 	.long sys_stat
 	.long sys_lseek
 	.long sys_getpid	/* 20 */
@@ -590,9 +590,19 @@
 	.long sys_poll
 	.long sys_nfsservctl
 	.long sys_setresgid	
-	.long sys_getresgid	/* 170 */
+	.long sys_getresgid		/* 170 */
 	.long sys_prctl
+	.long sys_rt_sigreturn
+	.long sys_rt_sigaction
+	.long sys_rt_sigprocmask	
+	.long sys_rt_sigpending		/* 175 */
+	.long sys_rt_sigtimedwait
+	.long sys_rt_sigqueueinfo
+	.long sys_rt_sigsuspend
+	.long sys_pread
+	.long sys_pwrite		/* 180 */
+	.long sys_chown
+	.long sys_getcwd
 	.long sys_xstat
 	.long sys_xmknod
-	.space (NR_syscalls-173)*4
-
+	.space (NR_syscalls-185)*4
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c
--- v2.1.100/linux/arch/ppc/kernel/openpic.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/kernel/openpic.c	Fri May  8 00:18:14 1998
@@ -264,7 +264,7 @@
     openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
 
     if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
-		    "OpenPIC cascade", NULL))
+		    "82c59 cascade", NULL))
 	printk("Unable to get OpenPIC IRQ 0 for cascade\n");
     openpic_set_priority(0, 0);
     openpic_disable_8259_pass_through();
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.1.100/linux/arch/ppc/kernel/pci.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/pci.c	Fri May  8 00:18:14 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: pci.c,v 1.24 1998/02/19 21:29:49 cort Exp $
+ * $Id: pci.c,v 1.27 1998/04/24 02:46:47 cort Exp $
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
@@ -88,6 +88,19 @@
 extern int prep_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
 					   unsigned char offset, unsigned int val);
 
+extern int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+					 unsigned char offset, unsigned char *val);
+extern int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+					 unsigned char offset, unsigned short *val);
+extern int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+					  unsigned char offset, unsigned int *val);
+extern int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+					  unsigned char offset, unsigned char val);
+extern int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+					  unsigned char offset, unsigned short val);
+extern int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+					   unsigned char offset, unsigned int val);
+
 int pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
 			     unsigned char offset, unsigned char *val)
 {
@@ -124,15 +137,14 @@
 	return 1;
 }
 
-__initfunc(unsigned long
-	   pcibios_init(unsigned long mem_start,unsigned long mem_end))
+__initfunc(void pcibios_init(void))
 {
-	return mem_start;
 }
 
 __initfunc(void
 	   setup_pci_ptrs(void))
 {
+#ifndef CONFIG_MBX  
 	switch (_machine) {
 	case _MACH_prep:
 		ptr_pcibios_read_config_byte = prep_pcibios_read_config_byte;
@@ -158,12 +170,20 @@
 		ptr_pcibios_write_config_word = chrp_pcibios_write_config_word;
 		ptr_pcibios_write_config_dword = chrp_pcibios_write_config_dword;
 		break;
+	default:
+		printk("setup_pci_ptrs(): unknown machine type!\n");
 	}
+#else  /* CONFIG_MBX */	
+	ptr_pcibios_read_config_byte = mbx_pcibios_read_config_byte;
+	ptr_pcibios_read_config_word = mbx_pcibios_read_config_word;
+	ptr_pcibios_read_config_dword = mbx_pcibios_read_config_dword;
+	ptr_pcibios_write_config_byte = mbx_pcibios_write_config_byte;
+	ptr_pcibios_write_config_word = mbx_pcibios_write_config_word;
+	ptr_pcibios_write_config_dword = mbx_pcibios_write_config_dword;
+#endif /* CONFIG_MBX */	
 }
 
-__initfunc(unsigned long
-	   pcibios_fixup(unsigned long mem_start, unsigned long mem_end))
-
+__initfunc(void pcibios_fixup(void))
 {
 	extern route_pci_interrupts(void);
 	struct pci_dev *dev;
@@ -223,7 +243,6 @@
 		}
 		break;
 	}
-	return mem_start;
 }
 
 __initfunc(char *pcibios_setup(char *str))
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.1.100/linux/arch/ppc/kernel/pmac_pci.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/kernel/pmac_pci.c	Fri May  8 00:18:14 1998
@@ -39,114 +39,7 @@
 #define BANDIT_MAGIC	0x50
 #define BANDIT_COHERENT	0x40
 
-/*
- * For a bandit bridge, turn on cache coherency if necessary.
- * N.B. we can't use pcibios_*_config_* here because bridges[]
- * is not initialized yet.
- */
-static void init_bandit(struct bridge_data *bp)
-{
-	unsigned int vendev, magic;
-	int rev;
-
-	/* read the word at offset 0 in config space for device 11 */
-	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
-	udelay(2);
-	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
-	if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) {
-		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
-		return;
-	}
-
-	/* read the revision id */
-	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
-	udelay(2);
-	rev = in_8(bp->cfg_data);
-	if (rev != BANDIT_REVID)
-		printk(KERN_WARNING "Unknown revision %d for bandit at %p\n",
-		       rev, bp->io_base);
-
-	/* read the word at offset 0x50 */
-	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
-	udelay(2);
-	magic = in_le32((volatile unsigned int *)bp->cfg_data);
-	if ((magic & BANDIT_COHERENT) != 0)
-		return;
-	magic |= BANDIT_COHERENT;
-	udelay(2);
-	out_le32((volatile unsigned int *)bp->cfg_data, magic);
-	printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n",
-	       bp->io_base);
-}
-
-unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end)
-{
-	int bus;
-	struct bridge_data *bridge;
-
-	bridge_list = 0;
-	max_bus = 0;
-	add_bridges(find_devices("bandit"), &mem_start);
-	add_bridges(find_devices("chaos"), &mem_start);
-	bridges = (struct bridge_data **) mem_start;
-	mem_start += (max_bus + 1) * sizeof(struct bridge_data *);
-	memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *));
-	for (bridge = bridge_list; bridge != NULL; bridge = bridge->next)
-		for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus)
-			bridges[bus] = bridge;
-
-	return mem_start;
-}
-
-static void add_bridges(struct device_node *dev, unsigned long *mem_ptr)
-{
-	int *bus_range;
-	int len;
-	struct bridge_data *bp;
-	struct reg_property *addr;
-
-	for (; dev != NULL; dev = dev->next) {
-		addr = (struct reg_property *) get_property(dev, "reg", &len);
-		if (addr == NULL || len < sizeof(*addr)) {
-			printk(KERN_WARNING "Can't use %s: no address\n",
-			       dev->full_name);
-			continue;
-		}
-		bus_range = (int *) get_property(dev, "bus-range", &len);
-		if (bus_range == NULL || len < 2 * sizeof(int)) {
-			printk(KERN_WARNING "Can't get bus-range for %s\n",
-			       dev->full_name);
-			continue;
-		}
-		if (bus_range[1] == bus_range[0])
-			printk(KERN_INFO "PCI bus %d", bus_range[0]);
-		else
-			printk(KERN_INFO "PCI buses %d..%d", bus_range[0],
-			       bus_range[1]);
-		printk(" controlled by %s at %x\n", dev->name, addr->address);
-		bp = (struct bridge_data *) *mem_ptr;
-		*mem_ptr += sizeof(struct bridge_data);
-		bp->cfg_addr = (volatile unsigned int *)
-			ioremap(addr->address + 0x800000, 0x1000);
-		bp->cfg_data = (volatile unsigned char *)
-			ioremap(addr->address + 0xc00000, 0x1000);
-		bp->io_base = (void *) ioremap(addr->address, 0x10000);
-#ifdef CONFIG_PMAC
-		if (isa_io_base == 0)
-			isa_io_base = (unsigned long) bp->io_base;
-#endif
-		bp->bus_number = bus_range[0];
-		bp->max_bus = bus_range[1];
-		bp->next = bridge_list;
-		bp->node = dev;
-		bridge_list = bp;
-		if (bp->max_bus > max_bus)
-			max_bus = bp->max_bus;
-
-		if (strcmp(dev->name, "bandit") == 0)
-			init_bandit(bp);
-	}
-}
+__pmac
 
 void *pci_io_base(unsigned int bus)
 {
@@ -303,3 +196,113 @@
 	out_le32((volatile unsigned int *)bp->cfg_data, val);
 	return PCIBIOS_SUCCESSFUL;
 }
+
+/*
+ * For a bandit bridge, turn on cache coherency if necessary.
+ * N.B. we can't use pcibios_*_config_* here because bridges[]
+ * is not initialized yet.
+ */
+__initfunc(static void init_bandit(struct bridge_data *bp))
+{
+	unsigned int vendev, magic;
+	int rev;
+
+	/* read the word at offset 0 in config space for device 11 */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
+	udelay(2);
+	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
+	if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) {
+		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
+		return;
+	}
+
+	/* read the revision id */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
+	udelay(2);
+	rev = in_8(bp->cfg_data);
+	if (rev != BANDIT_REVID)
+		printk(KERN_WARNING "Unknown revision %d for bandit at %p\n",
+		       rev, bp->io_base);
+
+	/* read the word at offset 0x50 */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
+	udelay(2);
+	magic = in_le32((volatile unsigned int *)bp->cfg_data);
+	if ((magic & BANDIT_COHERENT) != 0)
+		return;
+	magic |= BANDIT_COHERENT;
+	udelay(2);
+	out_le32((volatile unsigned int *)bp->cfg_data, magic);
+	printk(KERN_INFO "Cache coherency enabled for bandit/PSX at %p\n",
+	       bp->io_base);
+}
+
+__initfunc(unsigned long pmac_find_bridges(unsigned long mem_start, unsigned long mem_end))
+{
+	int bus;
+	struct bridge_data *bridge;
+
+	bridge_list = 0;
+	max_bus = 0;
+	add_bridges(find_devices("bandit"), &mem_start);
+	add_bridges(find_devices("chaos"), &mem_start);
+	bridges = (struct bridge_data **) mem_start;
+	mem_start += (max_bus + 1) * sizeof(struct bridge_data *);
+	memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *));
+	for (bridge = bridge_list; bridge != NULL; bridge = bridge->next)
+		for (bus = bridge->bus_number; bus <= bridge->max_bus; ++bus)
+			bridges[bus] = bridge;
+
+	return mem_start;
+}
+
+__initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_ptr))
+{
+	int *bus_range;
+	int len;
+	struct bridge_data *bp;
+	struct reg_property *addr;
+
+	for (; dev != NULL; dev = dev->next) {
+		addr = (struct reg_property *) get_property(dev, "reg", &len);
+		if (addr == NULL || len < sizeof(*addr)) {
+			printk(KERN_WARNING "Can't use %s: no address\n",
+			       dev->full_name);
+			continue;
+		}
+		bus_range = (int *) get_property(dev, "bus-range", &len);
+		if (bus_range == NULL || len < 2 * sizeof(int)) {
+			printk(KERN_WARNING "Can't get bus-range for %s\n",
+			       dev->full_name);
+			continue;
+		}
+		if (bus_range[1] == bus_range[0])
+			printk(KERN_INFO "PCI bus %d", bus_range[0]);
+		else
+			printk(KERN_INFO "PCI buses %d..%d", bus_range[0],
+			       bus_range[1]);
+		printk(" controlled by %s at %x\n", dev->name, addr->address);
+		bp = (struct bridge_data *) *mem_ptr;
+		*mem_ptr += sizeof(struct bridge_data);
+		bp->cfg_addr = (volatile unsigned int *)
+			ioremap(addr->address + 0x800000, 0x1000);
+		bp->cfg_data = (volatile unsigned char *)
+			ioremap(addr->address + 0xc00000, 0x1000);
+		bp->io_base = (void *) ioremap(addr->address, 0x10000);
+#ifdef CONFIG_PMAC
+		if (isa_io_base == 0)
+			isa_io_base = (unsigned long) bp->io_base;
+#endif
+		bp->bus_number = bus_range[0];
+		bp->max_bus = bus_range[1];
+		bp->next = bridge_list;
+		bp->node = dev;
+		bridge_list = bp;
+		if (bp->max_bus > max_bus)
+			max_bus = bp->max_bus;
+
+		if (strcmp(dev->name, "bandit") == 0)
+			init_bandit(bp);
+	}
+}
+
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.1.100/linux/arch/ppc/kernel/pmac_setup.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/pmac_setup.c	Fri May  8 00:18:14 1998
@@ -22,6 +22,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -47,6 +48,8 @@
 #include <asm/ide.h>
 #include <asm/pci-bridge.h>
 #include <asm/adb.h>
+#include <asm/cuda.h>
+#include <asm/pmu.h>
 #include <asm/mediabay.h>
 #include <asm/ohare.h>
 #include <asm/mediabay.h>
@@ -58,10 +61,44 @@
 
 #define DEFAULT_ROOT_DEVICE 0x0801	/* sda1 - slightly silly choice */
 
+extern void zs_kgdb_hook(int tty_num);
 static void ohare_init(void);
 
-void
-pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p)
+__pmac
+
+int
+pmac_get_cpuinfo(char *buffer)
+{
+	int len;
+	/* should find motherboard type here as well */
+	len = sprintf(buffer,"machine\t\t: PowerMac\n");
+	return len;
+}
+
+#ifdef CONFIG_SCSI
+/* Find the device number for the disk (if any) at target tgt
+   on host adaptor host.
+   XXX this really really should be in drivers/scsi/sd.c. */
+#include <linux/blkdev.h>
+#include "../../../drivers/scsi/scsi.h"
+#include "../../../drivers/scsi/sd.h"
+#include "../../../drivers/scsi/hosts.h"
+
+kdev_t sd_find_target(void *host, int tgt)
+{
+    Scsi_Disk *dp;
+    int i;
+
+    for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
+        if (dp->device != NULL && dp->device->host == host
+            && dp->device->id == tgt)
+            return MKDEV(SCSI_DISK_MAJOR, i << 4);
+    return 0;
+}
+#endif
+
+__initfunc(void
+pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
 {
 	struct device_node *cpu;
 	int *fp;
@@ -94,6 +131,13 @@
 
 	ohare_init();
 
+#ifdef CONFIG_KGDB
+	zs_kgdb_hook(0);
+#endif
+
+	find_via_cuda();
+	find_via_pmu();
+
 #ifdef CONFIG_FB
 	/* Frame buffer device based console */
 	conswitchp = &fb_con;
@@ -102,7 +146,7 @@
 
 static volatile u32 *feature_addr;
 
-static void ohare_init(void)
+__initfunc(static void ohare_init(void))
 {
 	struct device_node *np;
 
@@ -134,28 +178,20 @@
 int boot_part;
 kdev_t boot_dev;
 
-unsigned long
-powermac_init(unsigned long mem_start, unsigned long mem_end)
+__initfunc(void powermac_init(void))
 {
-#ifdef CONFIG_KGDB
-	extern void zs_kgdb_hook(int tty_num);
-	zs_kgdb_hook(0);
-#endif
 	adb_init();
 	pmac_nvram_init();
 	if (_machine == _MACH_Pmac) {
-		pmac_read_rtc_time();
 		media_bay_init();
 	}
 #ifdef CONFIG_PMAC_CONSOLE
 	pmac_find_display();
 #endif
-
-	return mem_start;
 }
 
-void
-note_scsi_host(struct device_node *node, void *host)
+__initfunc(void
+note_scsi_host(struct device_node *node, void *host))
 {
 	int l;
 	char *p;
@@ -183,29 +219,7 @@
 	}
 }
 
-#ifdef CONFIG_SCSI
-/* Find the device number for the disk (if any) at target tgt
-   on host adaptor host.
-   XXX this really really should be in drivers/scsi/sd.c. */
-#include <linux/blkdev.h>
-#include "../../../drivers/scsi/scsi.h"
-#include "../../../drivers/scsi/sd.h"
-#include "../../../drivers/scsi/hosts.h"
-
-kdev_t sd_find_target(void *host, int tgt)
-{
-    Scsi_Disk *dp;
-    int i;
-
-    for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
-        if (dp->device != NULL && dp->device->host == host
-            && dp->device->id == tgt)
-            return MKDEV(SCSI_DISK_MAJOR, i << 4);
-    return 0;
-}
-#endif
-
-void find_boot_device(void)
+__initfunc(void find_boot_device(void))
 {
 	kdev_t dev;
 
@@ -223,7 +237,7 @@
 	/* XXX should cope with booting from IDE also */
 }
 
-void note_bootable_part(kdev_t dev, int part)
+__initfunc(void note_bootable_part(kdev_t dev, int part))
 {
 	static int found_boot = 0;
 
@@ -243,7 +257,7 @@
 ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
 int pmac_ide_irq[MAX_HWIFS];
 
-void pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+__initfunc(void pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq))
 {
 	int i;
 
@@ -268,7 +282,7 @@
 	}
 }
 
-void pmac_ide_probe(void)
+__initfunc(void pmac_ide_probe(void))
 {
 	struct device_node *np;
 	int i;
@@ -325,11 +339,3 @@
 }
 #endif /* CONFIG_BLK_DEV_IDE */
 
-int
-pmac_get_cpuinfo(char *buffer)
-{
-	int len;
-	/* should find motherboard type here as well */
-	len = sprintf(buffer,"machine\t\t: PowerMac\n");
-	return len;
-}
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_support.c linux/arch/ppc/kernel/pmac_support.c
--- v2.1.100/linux/arch/ppc/kernel/pmac_support.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/pmac_support.c	Fri May  8 00:18:15 1998
@@ -5,6 +5,7 @@
 #include <linux/stddef.h>
 #include <linux/reboot.h>
 #include <linux/nvram.h>
+#include <asm/init.h>
 #include <asm/ptrace.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
@@ -22,6 +23,9 @@
 static int nvram_mult;
 
 #define NVRAM_SIZE	0x2000	/* 8kB of non-volatile RAM */
+
+
+__pmac
 
 void pmac_nvram_init(void)
 {
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- v2.1.100/linux/arch/ppc/kernel/pmac_time.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/pmac_time.c	Fri May  8 00:18:15 1998
@@ -13,6 +13,7 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 #include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/pmu.h>
@@ -47,11 +48,49 @@
 /* Bits in IFR and IER */
 #define T1_INT		0x40		/* Timer 1 interrupt */
 
+__pmac
+
+unsigned long pmac_get_rtc_time(void)
+{
+	struct adb_request req;
+
+	/* Get the time from the RTC */
+	switch (adb_hardware) {
+	case ADB_VIACUDA:
+		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+		if (req.reply_len != 7)
+			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return (req.reply[3] << 24) + (req.reply[4] << 16)
+			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
+	case ADB_VIAPMU:
+		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 5)
+			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return (req.reply[1] << 24) + (req.reply[2] << 16)
+			+ (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET;
+	default:
+		return 0;
+	}
+}
+
+int pmac_set_rtc_time(unsigned long nowtime)
+{
+	return 0;
+}
+
 /*
  * Calibrate the decrementer register using VIA timer 1.
  * This is used both on powermacs and CHRP machines.
  */
-int via_calibrate_decr(void)
+__initfunc(int via_calibrate_decr(void))
 {
 	struct device_node *vias;
 	volatile unsigned char *via;
@@ -100,7 +139,7 @@
  * This was taken from the pmac time_init() when merging the prep/pmac
  * time functions.
  */
-void pmac_calibrate_decr(void)
+__initfunc(void pmac_calibrate_decr(void))
 {
 	struct device_node *cpu;
 	int freq, *fp, divisor;
@@ -127,51 +166,3 @@
 	count_period_den = freq / 1000000;
 }
 
-unsigned long
-pmac_get_rtc_time(void)
-{
-	struct adb_request req;
-
-	/* Get the time from the RTC */
-	switch (adb_hardware) {
-	case ADB_VIACUDA:
-		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
-			return 0;
-		while (!req.complete)
-			cuda_poll();
-		if (req.reply_len != 7)
-			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		return (req.reply[3] << 24) + (req.reply[4] << 16)
-			+ (req.reply[5] << 8) + req.reply[6] - RTC_OFFSET;
-	case ADB_VIAPMU:
-		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
-			return 0;
-		while (!req.complete)
-			pmu_poll();
-		if (req.reply_len != 5)
-			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		return (req.reply[1] << 24) + (req.reply[2] << 16)
-			+ (req.reply[3] << 8) + req.reply[4] - RTC_OFFSET;
-	default:
-		return 0;
-	}
-}
-
-int pmac_set_rtc_time(unsigned long nowtime)
-{
-	return 0;
-}
-
-/*
- * We can't do this in time_init, because via_cuda_init hasn't
- * been called at that stage.
- */
-void
-pmac_read_rtc_time(void)
-{
-	xtime.tv_sec = pmac_get_rtc_time();
-	xtime.tv_usec = 0;
-	last_rtc_update = xtime.tv_sec;
-}
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.1.100/linux/arch/ppc/kernel/ppc_htab.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/kernel/ppc_htab.c	Fri May  8 00:18:15 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: ppc_htab.c,v 1.17 1998/03/14 07:52:49 cort Exp $
+ * $Id: ppc_htab.c,v 1.18 1998/04/24 12:29:39 davem Exp $
  *
  * PowerPC hash table management proc entry.  Will show information
  * about the current hash table and will allow changes to it.
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.1.100/linux/arch/ppc/kernel/prep_setup.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/prep_setup.c	Fri May  8 00:18:21 1998
@@ -62,7 +62,7 @@
 extern int rd_image_start;	/* starting block # of image */
 #endif
 
-void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+__initfunc(void prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
 {
 	ide_ioreg_t port = base;
 	int i = 8;
@@ -188,7 +188,7 @@
 		break;
 	}
 	
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 	/* initrd_start and size are setup by boot/head.S and kernel/head.S */
 	if ( initrd_start )
 	{
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
--- v2.1.100/linux/arch/ppc/kernel/prep_time.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/prep_time.c	Fri May  8 00:18:23 1998
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/kernel_stat.h>
+#include <linux/init.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -173,67 +174,3 @@
 		year += 100;
 	return mktime(year, mon, day, hour, min, sec);
 }
-
-#if 0
-void time_init(void)
-{
-	void (*irq_handler)(int, void *,struct pt_regs *);
-	
-	xtime.tv_sec = prep_get_rtc_time();
-	xtime.tv_usec = 0;
-	
-	prep_calibrate_decr();
-	
-	/* If we have the CPU hardware time counters, use them */
-	irq_handler = timer_interrupt;
-	if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0)
-		panic("Could not allocate timer IRQ!");
-}
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
-{
-	prep_calibrate_decr_handler(irq,dev,regs);
-	do_timer(regs);
-
-	/* update the hw clock if:
-	 * the time is marked out of sync (TIME_ERROR)
-	 * or ~11 minutes have expired since the last update -- Cort
-	 * If we have an externally synchronized Linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes. prep_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 )
-	/*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 (prep_set_rtc_time(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-
-
-#ifdef CONFIG_HEARTBEAT
-	/* use hard disk LED as a heartbeat instead -- much more useful
-	   for debugging -- Cort */
-	switch(kstat_irqs(0) % 101)
-	{
-	/* act like an actual heart beat -- ie thump-thump-pause... */
-	case 0:
-	case 20:
-		outb(1,IBM_HDD_LED);
-		break;
-	case 7:
-	case 27:
-		outb(0,IBM_HDD_LED);
-		break;
-	case 100:
-		break;
-	}
-#endif
-}
-#endif
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.1.100/linux/arch/ppc/kernel/prom.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/prom.c	Fri May  8 00:18:23 1998
@@ -122,6 +122,8 @@
 
 #define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
 
+__pmac
+
 static void
 prom_exit()
 {
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.1.100/linux/arch/ppc/kernel/ptrace.c	Thu May  7 22:51:47 1998
+++ linux/arch/ppc/kernel/ptrace.c	Fri May  8 00:18:23 1998
@@ -430,11 +430,11 @@
 			}
 			if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
 #ifndef __SMP__
-				if (child->tss.regs->msr & MSR_FP )
-					smp_giveup_fpu(child);
-#else	
 				if (last_task_used_math == child)
 					giveup_fpu();
+#else	
+				if (child->tss.regs->msr & MSR_FP )
+					smp_giveup_fpu(child);
 #endif				
 				((long *)child->tss.fpr)[addr - PT_FPR0] = data;
 				ret = 0;
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.1.100/linux/arch/ppc/kernel/setup.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/setup.c	Fri May  8 00:18:23 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: setup.c,v 1.68 1998/04/07 08:20:33 geert Exp $
+ * $Id: setup.c,v 1.77 1998/05/04 07:24:38 geert Exp $
  * Common prep/pmac/chrp boot and setup code.
  */
 
@@ -73,11 +73,11 @@
 /*
  * I really need to add multiple-console support... -- Cort
  */
-int pmac_display_supported(char *name)
+__initfunc(int pmac_display_supported(char *name))
 {
 	return 0;
 }
-void pmac_find_display(void)
+__initfunc(void pmac_find_display(void))
 {
 }
 #endif
@@ -103,6 +103,7 @@
 /* cmd is ignored for now... */
 void machine_restart(char *cmd)
 {
+#ifndef CONFIG_MBX
 	struct adb_request req;
 	unsigned long flags;
 	unsigned long i = 10000;
@@ -176,10 +177,15 @@
 		for(;;);
 		break;
 	}
+#else /* CONFIG_MBX */
+	extern void MBX_gorom(void);
+	MBX_gorom();
+#endif /* CONFIG_MBX */
 }
 
 void machine_power_off(void)
 {
+#ifndef CONFIG_MBX	
 	struct adb_request req;
 #if 0	
 	int err;
@@ -222,8 +228,10 @@
 #endif
 #endif
 	}
-	for (;;)
-		;
+	for (;;);
+#else /* CONFIG_MBX */
+	machine_restart(NULL);
+#endif /* CONFIG_MBX */
 }
 
 void machine_halt(void)
@@ -244,6 +252,7 @@
 #ifdef CONFIG_BLK_DEV_IDE
 void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
+#ifndef CONFIG_MBX
 	switch (_machine) {
 	case _MACH_Pmac:
 		pmac_ide_init_hwif_ports(p,base,irq);
@@ -255,11 +264,13 @@
 		prep_ide_init_hwif_ports(p,base,irq);
 		break;
 	}
+#endif
 }
 #endif
 
 unsigned long cpu_temp(void)
 {
+#if 0	
 	unsigned long i, temp, thrm1, dir;
 	int sanity;
 	
@@ -318,8 +329,9 @@
 	}
 	asm("mtspr 1020, %0\n\t"
 	    "mtspr 1022, %0\n\t" ::"r" (0) );
+#endif
 #endif	
-	return temp;
+	return 0;
 }
 
 int get_cpuinfo(char *buffer)
@@ -390,13 +402,18 @@
 		case 10:
 			len += sprintf(len+buffer, "604ev5 (MachV)\n");
 			break;
+		case 50:
+			len += sprintf(len+buffer, "821\n");
+		case 80:
+			len += sprintf(len+buffer, "860\n");
+			break;
 		default:
 			len += sprintf(len+buffer, "unknown (%lu)\n",
 				       GET_PVR>>16);
 			break;
 		}
-
-
+		
+#ifndef CONFIG_MBX
 		/*
 		 * Assume here that all clock rates are the same in a
 		 * smp system.  -- Cort
@@ -426,7 +443,20 @@
 				       res.VitalProductData.ProcessorHz);
 			else
 				len += sprintf(len+buffer, "???\n");
-		}				
+		}
+#else /* CONFIG_MBX */
+		{
+			bd_t	*bp;
+			extern	RESIDUAL res;
+			
+			bp = (bd_t *)&res;
+			
+			len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
+				      "bus clock\t: %dMHz\n",
+				      bp->bi_intfreq /*/ 1000000*/,
+				      bp->bi_busfreq /*/ 1000000*/);
+		}
+#endif /* CONFIG_MBX */		
 		
 		len += sprintf(len+buffer, "revision\t: %ld.%ld\n",
 			       (GET_PVR & 0xff00) >> 8, GET_PVR & 0xff);
@@ -460,6 +490,7 @@
 			            ((zeropage_calls)?zeropage_calls:1));
 	}
 
+#ifndef CONFIG_MBX
 	switch (_machine)
 	{
 	case _MACH_Pmac:
@@ -477,6 +508,7 @@
 		break;
 #endif
 	}
+#endif /* ndef CONFIG_MBX */	
 	return len;
 }
 
@@ -488,8 +520,8 @@
 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
 		 unsigned long r6, unsigned long r7))
 {
-	extern setup_pci_ptrs(void);
-#ifndef CONFIG_MBX8xx
+	extern void setup_pci_ptrs(void);
+#ifndef CONFIG_MBX
 
 #ifdef CONFIG_APUS
 	if ( r3 == 0x61707573 )
@@ -513,7 +545,7 @@
 
 		return 0;
 	}
-#endif
+#endif /* CONFIG_APUS */
 
 #ifndef CONFIG_MACH_SPECIFIC
 	/* prep boot loader tells us if we're prep or not */
@@ -621,14 +653,14 @@
 		}
 		else /* assume motorola if no residual (netboot?) */
 			_prep_type = _PREP_Motorola;
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 		/* take care of initrd if we have one */
 		if ( r4 )
 		{
 			initrd_start = r4 + KERNELBASE;
 			initrd_end = r5 + KERNELBASE;
 		}
-#endif /* CONFIG_BLK_DEV_RAM */
+#endif /* CONFIG_BLK_DEV_INITRD */
 		/* take care of cmd line */
 		if ( r6 )
 		{
@@ -637,14 +669,14 @@
 		}
 		break;
 	case _MACH_chrp:
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 		/* take care of initrd if we have one */
 		if ( r3 )
 		{
 			initrd_start = r3 + KERNELBASE;
 			initrd_end = r3+ r4 + KERNELBASE;
 		}
-#endif /* CONFIG_BLK_DEV_RAM */
+#endif /* CONFIG_BLK_DEV_INITRD */
 #if !defined(CONFIG_MACH_SPECIFIC)
 		isa_io_base = CHRP_ISA_IO_BASE;
 		isa_mem_base = CHRP_ISA_MEM_BASE;
@@ -657,22 +689,21 @@
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
-#else /* CONFIG_MBX8xx */
-	extern setup_pci_ptrs(void);
+#else /* CONFIG_MBX */
 
 	if ( r3 )
 		memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
 
 	setup_pci_ptrs();
 
-#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
 	/* take care of initrd if we have one */
 	if ( r4 )
 	{
 		initrd_start = r4 + KERNELBASE;
 		initrd_end = r5 + KERNELBASE;
 	}
-#endif /* CONFIG_BLK_DEV_RAM */
+#endif /* CONFIG_BLK_DEV_INITRD */
 	/* take care of cmd line */
 	if ( r6 )
 	{
@@ -682,7 +713,6 @@
 	}
 
 #endif /* CONFIG_MBX */
-	
 	return 0;
 }
 
@@ -693,6 +723,7 @@
 	extern void chrp_setup_arch(unsigned long *, unsigned long *);
 	extern void prep_setup_arch(unsigned long *, unsigned long *);
 	extern void apus_setup_arch(char **, unsigned long *, unsigned long *);
+	extern void mbx_setup_arch(unsigned long *, unsigned long *);
 	extern int panic_timeout;
 	extern char _etext[], _edata[];
 	extern char *klimit;
@@ -718,7 +749,9 @@
 
 	*memory_start_p = find_available_memory();
 	*memory_end_p = (unsigned long) end_of_DRAM;
-
+#ifdef CONFIG_MBX
+	mbx_setup_arch(memory_start_p,memory_end_p);
+#else /* CONFIG_MBX */	
 	switch (_machine) {
 	case _MACH_Pmac:
 		pmac_setup_arch(memory_start_p, memory_end_p);
@@ -738,4 +771,5 @@
 	default:
 		printk("Unknown machine %d in setup_arch()\n", _machine);
 	}
+#endif /* CONFIG_MBX */	
 }
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.1.100/linux/arch/ppc/kernel/signal.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/signal.c	Fri May  8 00:18:23 1998
@@ -118,6 +118,14 @@
 	}
 }
 
+
+asmlinkage int sys_rt_sigreturn(unsigned long __unused)
+{
+	printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n",
+	       current->comm,current->pid);
+	do_exit(SIGSEGV);
+}
+
 int 
 sys_sigaction(int sig, const struct old_sigaction *act,
 	      struct old_sigaction *oact)
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.1.100/linux/arch/ppc/kernel/smp.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/smp.c	Fri May  8 00:18:23 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: smp.c,v 1.22 1998/04/10 01:53:34 cort Exp $
+ * $Id: smp.c,v 1.24 1998/04/27 09:02:37 cort Exp $
  *
  * Smp support for ppc.
  *
@@ -7,7 +7,6 @@
  * deal of code from the sparc and intel versions.
  */
 
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/tasks.h>
@@ -18,6 +17,7 @@
 #include <linux/delay.h>
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
+#include <linux/init.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -53,7 +53,123 @@
 
 extern int cpu_idle(void *unused);
 
-void smp_boot_cpus(void)
+void smp_local_timer_interrupt(struct pt_regs * regs)
+{
+	int cpu = smp_processor_id();
+	extern void update_one_process(struct task_struct *,unsigned long,
+				       unsigned long,unsigned long,int);
+
+	if (!--prof_counter[cpu]) {
+		int user=0,system=0;
+		struct task_struct * p = current;
+
+		/*
+		 * After doing the above, we need to make like
+		 * a normal interrupt - otherwise timer interrupts
+		 * ignore the global interrupt lock, which is the
+		 * WrongThing (tm) to do.
+		 */
+
+		if (user_mode(regs))
+			user=1;
+		else
+			system=1;
+
+		if (p->pid) {
+			update_one_process(p, 1, user, system, cpu);
+
+			p->counter -= 1;
+			if (p->counter < 0) {
+				p->counter = 0;
+				need_resched = 1;
+			}
+			if (p->priority < DEF_PRIORITY) {
+				kstat.cpu_nice += user;
+				kstat.per_cpu_nice[cpu] += user;
+			} else {
+				kstat.cpu_user += user;
+				kstat.per_cpu_user[cpu] += user;
+			}
+
+			kstat.cpu_system += system;
+			kstat.per_cpu_system[cpu] += system;
+
+		}
+		prof_counter[cpu]=prof_multiplier[cpu];
+	}
+}
+
+/*
+ * Dirty hack to get smp message passing working.
+ * Right now it only works for stop cpu's but will be setup
+ * later for more general message passing.
+ *
+ * As it is now, if we're sending two message as the same time
+ * we have race conditions.  I avoided doing locks here since
+ * all that works right now is the stop cpu message.
+ *
+ *  -- Cort
+ */
+int smp_message[NR_CPUS];
+void smp_message_recv(void)
+{
+	int msg = smp_message[smp_processor_id()];
+	
+	printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);
+	
+	/* make sure msg is for us */
+	if ( msg == -1 ) return;
+printk("recv after msg check\n");	
+	switch( msg )
+	{
+	case MSG_STOP_CPU:
+		__cli();
+		while (1) ;
+		break;
+	case 0xf0f0: /* syncing time bases - just return */
+		break;
+	default:
+		printk("SMP %d: smp_message_recv(): unknown msg %d\n",
+		       smp_processor_id(), msg);
+		break;
+	}
+	/* reset message */
+	smp_message[smp_processor_id()] = -1;
+}
+
+spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
+void smp_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	printk("SMP %d: sending smp message\n", current->processor);
+
+	spin_lock(&mesg_pass_lock);
+	if ( _machine != _MACH_Pmac )
+		return;
+
+#define OTHER (~smp_processor_id() & 1)
+	
+	switch( target )
+	{
+	case MSG_ALL:
+		smp_message[smp_processor_id()] = msg;
+		/* fall through */
+	case MSG_ALL_BUT_SELF:
+		smp_message[OTHER] = msg;
+		break;
+	default:
+		smp_message[target] = msg;
+		break;
+	}
+	/* interrupt secondary processor */
+	/**(volatile unsigned long *)(0xf80000c0) = 0xffffffff;
+	eieio();*/
+	*(volatile unsigned long *)(0xf80000c0) = 0;
+	/* interrupt primary */
+	/**(volatile unsigned long *)(0xf3019000);*/
+	spin_unlock(&mesg_pass_lock);	
+}
+
+__initfunc(void smp_boot_cpus(void))
 {
 	extern unsigned long secondary_entry[];
 	extern struct task_struct *current_set[NR_CPUS];
@@ -118,10 +234,10 @@
 		__cpu_logical_map[i] = 1;
 		printk("Processor 1 found.\n");
 
-#if 0 /* this sync's the decr's */
+#if 0 /* this sync's the decr's, but we don't want this now -- Cort */
 		set_dec(decrementer_count);
 #endif
-		/* interrupt secondary to sync the time bases */
+		/* interrupt secondary to start decr's again */
 		smp_message_pass(1,0xf0f0, 0, 0);
 		/* interrupt secondary to begin executing code */
 		/**(volatile unsigned long *)(0xf80000c0) = 0L;
@@ -132,7 +248,7 @@
 	}
 }
 
-void smp_commence(void)
+__initfunc(void smp_commence(void))
 {
 	printk("SMP %d: smp_commence()\n",current->processor);
 	/*
@@ -144,19 +260,19 @@
 }
 
 /* intel needs this */
-void initialize_secondary(void)
+__initfunc(void initialize_secondary(void))
 {
 }
 
 /* Activate a secondary processor. */
-int start_secondary(void *unused)
+__initfunc(int start_secondary(void *unused))
 {
 	printk("SMP %d: start_secondary()\n",current->processor);
 	smp_callin();
 	return cpu_idle(NULL);
 }
 
-void smp_callin(void)
+__initfunc(void smp_callin(void))
 {
 	printk("SMP %d: smp_callin()\n",current->processor);
         smp_store_cpu_info(1);
@@ -174,128 +290,12 @@
 	__sti();
 }
 
-void smp_setup(char *str, int *ints)
+__initfunc(void smp_setup(char *str, int *ints))
 {
 	printk("SMP %d: smp_setup()\n",current->processor);
 }
 
-void smp_local_timer_interrupt(struct pt_regs * regs)
-{
-	int cpu = smp_processor_id();
-	extern void update_one_process(struct task_struct *,unsigned long,
-				       unsigned long,unsigned long,int);
-
-	if (!--prof_counter[cpu]) {
-		int user=0,system=0;
-		struct task_struct * p = current;
-
-		/*
-		 * After doing the above, we need to make like
-		 * a normal interrupt - otherwise timer interrupts
-		 * ignore the global interrupt lock, which is the
-		 * WrongThing (tm) to do.
-		 */
-
-		if (user_mode(regs))
-			user=1;
-		else
-			system=1;
-
-		if (p->pid) {
-			update_one_process(p, 1, user, system, cpu);
-
-			p->counter -= 1;
-			if (p->counter < 0) {
-				p->counter = 0;
-				need_resched = 1;
-			}
-			if (p->priority < DEF_PRIORITY) {
-				kstat.cpu_nice += user;
-				kstat.per_cpu_nice[cpu] += user;
-			} else {
-				kstat.cpu_user += user;
-				kstat.per_cpu_user[cpu] += user;
-			}
-
-			kstat.cpu_system += system;
-			kstat.per_cpu_system[cpu] += system;
-
-		}
-		prof_counter[cpu]=prof_multiplier[cpu];
-	}
-}
-
-/*
- * Dirty hack to get smp message passing working.
- * Right now it only works for stop cpu's but will be setup
- * later for more general message passing.
- *
- * As it is now, if we're sending two message as the same time
- * we have race conditions.  I avoided doing locks here since
- * all that works right now is the stop cpu message.
- *
- *  -- Cort
- */
-int smp_message[NR_CPUS];
-void smp_message_recv(void)
-{
-	int msg = smp_message[smp_processor_id()];
-	
-	printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);
-	
-	/* make sure msg is for us */
-	if ( msg == -1 ) return;
-printk("recv after msg check\n");	
-	switch( msg )
-	{
-	case MSG_STOP_CPU:
-		__cli();
-		while (1) ;
-		break;
-	case 0xf0f0: /* syncing time bases - just return */
-		break;
-	default:
-		printk("SMP %d: smp_message_recv(): unknown msg %d\n",
-		       smp_processor_id(), msg);
-		break;
-	}
-	/* reset message */
-	smp_message[smp_processor_id()] = -1;
-}
-
-spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
-void smp_message_pass(int target, int msg, unsigned long data, int wait)
-{
-	printk("SMP %d: sending smp message\n", current->processor);
-
-	spin_lock(&mesg_pass_lock);
-	if ( _machine != _MACH_Pmac )
-		return;
-
-#define OTHER (~smp_processor_id() & 1)
-	
-	switch( target )
-	{
-	case MSG_ALL:
-		smp_message[smp_processor_id()] = msg;
-		/* fall through */
-	case MSG_ALL_BUT_SELF:
-		smp_message[OTHER] = msg;
-		break;
-	default:
-		smp_message[target] = msg;
-		break;
-	}
-	/* interrupt secondary processor */
-	/**(volatile unsigned long *)(0xf80000c0) = 0xffffffff;
-	eieio();*/
-	*(volatile unsigned long *)(0xf80000c0) = 0;
-	/* interrupt primary */
-	/**(volatile unsigned long *)(0xf3019000);*/
-	spin_unlock(&mesg_pass_lock);	
-}
-
-int setup_profiling_timer(unsigned int multiplier)
+__initfunc(int setup_profiling_timer(unsigned int multiplier))
 {
 	return 0;
 }
@@ -307,4 +307,3 @@
         c->loops_per_sec = loops_per_sec;
         c->pvr = _get_PVR();
 }
-
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.1.100/linux/arch/ppc/kernel/softemu8xx.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/kernel/softemu8xx.c	Fri May  8 00:18:23 1998
@@ -63,34 +63,57 @@
 	ea = (uint *)(regs->gpr[idxreg] + disp);
 	ip = (uint *)&current->tss.fpr[flreg];
 
-	if (inst == LFD) {
+	switch ( inst )
+	{
+	case LFD:
 		if (copy_from_user(ip, ea, sizeof(double)))
 			retval = EFAULT;
-	}
-	else if (inst == LFDU) {
-
+		break;
+		
+	case LFDU:
 		if (copy_from_user(ip, ea, sizeof(double)))
 			retval = EFAULT;
 		else
 			regs->gpr[idxreg] = (uint)ea;
-	}
-	else if (inst == STFD) {
-
+		break;
+	case STFD:
 		if (copy_to_user(ea, ip, sizeof(double)))
 			retval = EFAULT;
-	}
-	else if (inst == STFDU) {
+		break;
 
+	case STFDU:
 		if (copy_to_user(ea, ip, sizeof(double)))
 			retval = EFAULT;
 		else
 			regs->gpr[idxreg] = (uint)ea;
-	}
-	else {
+		break;
+	default:
 		retval = 1;
+		printk("Bad emulation %s/%d\n"
+		       " NIP: %08x instruction: %08x opcode: %x "
+		       "A: %x B: %x C: %x code: %x rc: %x\n",
+		       current->comm,current->pid,
+		       regs->nip,
+		       instword,inst,
+		       (instword>>16)&0x1f,
+		       (instword>>11)&0x1f,
+		       (instword>>6)&0x1f,
+		       (instword>>1)&0x1f,
+		       instword&1);
+		{
+			int pa;
+			print_8xx_pte(current->mm,regs->nip);
+			pa = get_8xx_pte(current->mm,regs->nip) & PAGE_MASK;
+			pa |= (regs->nip & ~PAGE_MASK);
+			pa = __va(pa);
+			printk("Kernel VA for NIP %x ", pa);
+			print_8xx_pte(current->mm,pa);
+		}
+		
 	}
 
 	if (retval == 0)
 		regs->nip += 4;
 	return(retval);
 }
+
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.1.100/linux/arch/ppc/kernel/time.c	Sat Apr 25 18:13:10 1998
+++ linux/arch/ppc/kernel/time.c	Fri May  8 00:18:23 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: time.c,v 1.28 1998/04/07 18:49:49 cort Exp $
+ * $Id: time.c,v 1.32 1998/04/24 12:29:38 davem Exp $
  * Common time routines among all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -31,6 +31,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/time.h>
+#include <linux/init.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -76,7 +77,6 @@
 	 * this hack should leave for a better solution -- Cort */
 	unsigned dcache_locked = unlock_dcache();
 	
-if ( smp_processor_id() ) printk("SMP 1: timer intr\n");	
 	hardirq_enter(cpu);
 	
 	while ((dval = get_dec()) < 0) {
@@ -116,6 +116,7 @@
 */
 void timebase_interrupt(int irq, void * dev, struct pt_regs * regs)
 {
+	printk("timebase_interrupt()\n");
 }
 
 /* The RTC on the MPC8xx is an internal register.
@@ -168,8 +169,7 @@
 }
 
 
-void
-time_init(void)
+__initfunc(void time_init(void))
 {
 #ifndef CONFIG_MBX
 	if ((_get_PVR() >> 16) == 1) {
@@ -181,8 +181,7 @@
 
 	switch (_machine) {
 	case _MACH_Pmac:
-		/* can't call pmac_get_rtc_time() yet,
-		   because via-cuda isn't initialized yet. */
+		xtime.tv_sec = pmac_get_rtc_time();
 		if ( (_get_PVR() >> 16) != 1 && (!smp_processor_id()) )
 			pmac_calibrate_decr();
 		if ( !smp_processor_id() )
@@ -212,8 +211,7 @@
 #endif
 	}
 	xtime.tv_usec = 0;
-	set_dec(decrementer_count);
-#else
+#else /* CONFIG_MBX */
 	mbx_calibrate_decr();
 	set_rtc_time = mbx_set_rtc_time;
 
@@ -249,7 +247,7 @@
 	xtime.tv_usec = 0;
 
 #endif /* CONFIG_MBX */
-	
+	set_dec(decrementer_count);
 	/* mark the rtc/on-chip timer as in sync
 	 * so we don't update right away
 	 */
@@ -265,7 +263,7 @@
  */
 int calibrate_done = 0;
 volatile int *done_ptr = &calibrate_done;
-void prep_calibrate_decr(void)
+__initfunc(void prep_calibrate_decr(void))
 {
 	unsigned long flags;
 
@@ -308,7 +306,7 @@
 	free_irq( 0, NULL);
 }
 
-void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs)
+__initfunc(void prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs * regs))
 {
 	unsigned long freq, divisor;
 	static unsigned long t1 = 0, t2 = 0;
@@ -337,8 +335,9 @@
  * sixteen, or external oscillator divided by four.  Currently, we only
  * support the MBX, which is system clock divided by sixteen.
  */
-void mbx_calibrate_decr(void)
+__initfunc(void mbx_calibrate_decr(void))
 {
+	bd_t	*binfo = (bd_t *)&res;
 	int freq, fp, divisor;
 
 	if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
@@ -348,7 +347,7 @@
 	 * as MHz.  The value 'fp' is the number of decrementer ticks
 	 * per second.
 	 */
-	/*fp = (mbx_board_info.bi_intfreq * 1000000) / 16;*/
+	fp = (binfo->bi_intfreq * 1000000) / 16;
 	freq = fp*60;	/* try to make freq/1e6 an integer */
         divisor = 60;
         printk("time_init: decrementer frequency = %d/%d\n", freq, divisor);
@@ -432,3 +431,6 @@
 	/* Days are what is left over (+1) from all that. */
 	tm->tm_mday = day + 1;
 }
+
+
+
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.1.100/linux/arch/ppc/kernel/traps.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/kernel/traps.c	Fri May  8 00:18:23 1998
@@ -28,6 +28,7 @@
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
 #include <linux/config.h>
+#include <linux/init.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -69,11 +70,6 @@
  */
 
 void
-trap_init(void)
-{
-}
-
-void
 _exception(int signr, struct pt_regs *regs)
 {
 	if (!user_mode(regs))
@@ -93,6 +89,11 @@
 {
 	if ( !user_mode(regs) )
 	{
+#ifdef CONFIG_MBX
+		/* the mbx pci read routines can cause machine checks -- Cort */
+		bad_page_fault(regs,regs->dar);
+		return;
+#endif /* CONFIG_MBX */
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
 		if (debugger_fault_handler) {
 			debugger_fault_handler(regs);
@@ -230,32 +231,28 @@
 }
 
 #ifdef CONFIG_8xx
-
 void
 SoftwareEmulation(struct pt_regs *regs)
 {
 	int	errcode;
 	extern int	Soft_emulate_8xx (struct pt_regs *regs);
+	extern void print_8xx_pte(struct mm_struct *, unsigned long);	
 
-	if (user_mode(regs)) {
-#if 0
-		printk("(user mode)\n");
-		_exception(SIGTRAP, regs);
-#else
-		if (errcode = Soft_emulate_8xx(regs)) {
-printk("Software Emulation 0x%x: 0x%x ",
-			regs->nip, *((uint *)regs->nip));
-print_8xx_pte(current->mm, regs->nip);
+	if (user_mode(regs))
+	{
+		if ((errcode = Soft_emulate_8xx(regs))) {
+printk("Software Emulation %s/%d NIP: %lx *NIP: 0x%x code: %x",
+       current->comm,current->pid,
+       regs->nip, *((uint *)regs->nip), errcode);
+/*print_8xx_pte(current->mm, regs->nip);*/
 			if (errcode == EFAULT)
 				_exception(SIGBUS, regs);
 			else
 				_exception(SIGILL, regs);
 		}
-#endif
 	}
 	else {
-		printk("(kernel mode)\n");
-		panic("Kernel Mode Software Emulation");
+		panic("Kernel Mode Software FPU Emulation");
 	}
 }
 #endif
@@ -265,4 +262,8 @@
 {
 	printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n",
 	       regs->nip, regs->msr, regs->trap);
+}
+
+__initfunc(void trap_init(void))
+{
 }
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- v2.1.100/linux/arch/ppc/lib/string.S	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/lib/string.S	Fri May  8 00:18:23 1998
@@ -274,6 +274,8 @@
 	.long	17b,99b
 .text
 
+#undef CLEAR_USE_DCBZ 1
+#undef CLEAR_NO_CACHE 1
 	.globl	__clear_user
 __clear_user:
 	addi	r6,r3,-4
@@ -281,17 +283,34 @@
 	li	r5,0
 	cmplwi	0,r4,4
 	blt	7f
+	/* clear a single word */
 11:	stwu	r5,4(r6)
 	beqlr
+#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
+	/* 
+	 * no reason to turn off the cache for a single word 
+	 * or a few bytes -- Cort 
+	 */
+	mfspr	r7,HID0
+	ori	r8,r7,HID0_DLOCK
+	mtspr	HID0,r8
+#endif /* CLEAR_NO_CACHE */
+	/* clear word sized chunks */
 	andi.	r0,r6,3
 	add	r4,r0,r4
 	subf	r6,r0,r6
-	rlwinm	r0,r4,32-2,2,31
+	/*rlwinm	r0,r4,32-2,2,31*/
+	srwi	r0,r4,2
 	mtctr	r0
 	bdz	6f
 1:	stwu	r5,4(r6)
 	bdnz	1b
 6:	andi.	r4,r4,3
+#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
+	/* restore the original state of HID0 in case cache was off -- Cort */
+	mtspr	HID0,r7
+#endif /* CLEAR_NO_CACHE */	
+	/* clear byte sized chunks */
 7:	cmpwi	0,r4,0
 	beqlr
 	mtctr	r4
@@ -305,6 +324,9 @@
 	.align	2
 	.long	11b,99b
 	.long	1b,99b
+#ifdef CLEAR_USE_DCBZ
+	/*.long	66b,99b*/
+#endif		
 	.long	8b,99b
 .text
 
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/mbx_defconfig linux/arch/ppc/mbx_defconfig
--- v2.1.100/linux/arch/ppc/mbx_defconfig	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/mbx_defconfig	Fri May  8 00:18:23 1998
@@ -12,7 +12,9 @@
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
 # CONFIG_ALL_PPC is not set
+# CONFIG_APUS is not set
 CONFIG_MBX=y
+CONFIG_SERIAL_CONSOLE=y
 CONFIG_MACH_SPECIFIC=y
 
 #
@@ -34,7 +36,9 @@
 # CONFIG_PMAC_CONSOLE is not set
 # CONFIG_MAC_KEYBOARD is not set
 # CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
 # CONFIG_PROC_DEVICETREE is not set
+# CONFIG_KGDB is not set
 # CONFIG_XMON is not set
 CONFIG_VGA_CONSOLE=y
 
@@ -52,19 +56,13 @@
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
-# NEW devices (io_request, all ALPHA and dangerous)
-#
-# CONFIG_IO_REQUEST is not set
-
-#
 # Networking options
 #
 # CONFIG_PACKET is not set
@@ -142,13 +140,13 @@
 #
 # CONFIG_QUOTA is not set
 # CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
-# CONFIG_PROC_FS is not set
+CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
@@ -171,8 +169,7 @@
 # Character devices
 #
 # CONFIG_VT is not set
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_MOUSE is not set
@@ -189,8 +186,3 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.1.100/linux/arch/ppc/mm/fault.c	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/mm/fault.c	Fri May  8 00:18:23 1998
@@ -62,13 +62,13 @@
 	struct vm_area_struct * vma;
 	struct mm_struct *mm = current->mm;
 
-	/*printk("address: %08lx code: %08lx %s%s%s%s%s%s\n",
-	       address,error_code,
+	/*printk("address: %08lx nip:%08lx code: %08lx %s%s%s%s%s%s\n",
+	       address,regs->nip,error_code,
 	       (error_code&0x40000000)?"604 tlb&htab miss ":"",
 	       (error_code&0x20000000)?"603 tlbmiss ":"",
 	       (error_code&0x02000000)?"write ":"",
 	       (error_code&0x08000000)?"prot ":"",
-	       (error_code&0x95700000)?"I/O ":"",
+	       (error_code&0x80000000)?"I/O ":"",
 	       (regs->trap == 0x400)?"instr":"data"
 	       );*/
 	       
@@ -161,32 +161,6 @@
 bad_page_fault(struct pt_regs *regs, unsigned long address)
 {
 	unsigned long fixup;
-#if 0	
-	extern unsigned long video_mem_base;
-	extern unsigned long video_mem_term;
-	
-	/*
-	 * Remap video IO areas for buggy X servers.
-	 * The S3 server wants direct access to video memory
-	 * at 0x8000 0000 and 0xc000 0000 on prep systems, but
-	 * we don't allow that AND we remap the io areas so it's not
-	 * even there!
-	 * So, for this task only give a virtual=physical mapping of the
-	 * video mem.
-	 * -- Cort
-	 */
-	if ( is_prep && user_mode(regs) )
-	{
-			printk("%s/%d: fault on %x\n",
-			       current->comm,current->pid,address);
-			printk("mapping: %x -> %x\n",
-			       address&PAGE_MASK, address&PAGE_MASK);
-			map_page(current,address&PAGE_MASK,address&PAGE_MASK,
-				 _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE|_PAGE_NO_CACHE|_PAGE_WRITETHRU);
-			return;
-	}
-#endif	
-	
 	if (user_mode(regs)) {
 		force_sig(SIGSEGV, current);
 		return;
@@ -209,6 +183,7 @@
 	      regs->nip,regs->link,address,current->comm,current->pid);
 }
 
+#ifdef CONFIG_8xx
 /*
  * I need a va to pte function for the MPC8xx so I can set the cache
  * attributes on individual pages used by the Communication Processor
@@ -286,6 +261,17 @@
                         if (pte) {
                                 printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
                                         (long)pgd, (long)pte, (long)pte_val(*pte));
+#define pp ((long)pte_val(*pte))				
+				printk(" RPN: %05x PP: %x SPS: %x SH: %x "
+				       "CI: %x v: %x\n",
+				       pp>>12,    /* rpn */
+				       (pp>>10)&3, /* pp */
+				       (pp>>3)&1, /* small */
+				       (pp>>2)&1, /* shared */
+				       (pp>>1)&1, /* cache inhibit */
+				       pp&1       /* valid */
+				       );
+#undef pp				
                         }
                         else {
                                 printk("no pte\n");
@@ -320,6 +306,7 @@
         }
         return(retval);
 }
+#endif /* CONFIG_8xx */
 
 #if 0
 /*
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.1.100/linux/arch/ppc/mm/init.c	Thu May  7 22:51:47 1998
+++ linux/arch/ppc/mm/init.c	Fri May  8 00:18:23 1998
@@ -1,5 +1,5 @@
 /*
- *  arch/ppc/mm/init.c
+ *  $Id: init.c,v 1.94 1998/05/06 02:07:36 paulus Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -33,30 +33,25 @@
 #include <linux/swap.h>
 #include <linux/stddef.h>
 #include <linux/vmalloc.h>
+#include <linux/init.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>		/* for initrd_* */
+#endif
+
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 #include <asm/residual.h>
-#ifdef CONFIG_BLK_DEV_INITRD
-#include <linux/blk.h>		/* for initrd_* */
-#endif
+#include <asm/uaccess.h>
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
 #endif
 #ifdef CONFIG_MBX
 #include <asm/mbx.h>
 #endif
-
-#ifndef CONFIG_8xx
-unsigned long _SDR1;
-PTE *Hash, *Hash_end;
-unsigned long Hash_size, Hash_mask;
-#endif /* CONFIG_8xx */
-
-/* ifdef APUS specific stuff until the merge is completed. -jskov */
-#ifdef CONFIG_APUS
+#ifdef CONFIG_APUS /* ifdef APUS specific stuff until the merge is completed. -jskov */
 #include <asm/setup.h>
 #include <asm/amigahw.h>
 #endif
@@ -69,67 +64,60 @@
 extern char _start[], _end[];
 extern char etext[], _stext[];
 extern char __init_begin, __init_end;
+extern char __prep_begin, __prep_end;
+extern char __pmac_begin, __pmac_end;
+extern char __openfirmware_begin, __openfirmware_end;
 extern RESIDUAL res;
 char *klimit = _end;
 struct device_node *memory_node;
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
+unsigned long avail_start;
 #ifndef __SMP__
 struct pgtable_cache_struct quicklists;
 #endif
 
-#ifndef CONFIG_8xx
-static void hash_init(void);
-#endif /* CONFIG_8xx */
-static void mapin_ram(void);
+void MMU_init(void);
 static void *MMU_get_page(void);
+unsigned long *prep_find_end_of_memory(void);
+unsigned long *pmac_find_end_of_memory(void);
+extern unsigned long *find_end_of_memory(void);
+static void mapin_ram(void);
 void map_page(struct task_struct *, unsigned long va,
 		     unsigned long pa, int flags);
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
-extern unsigned long *find_end_of_memory(void);
 
 extern struct task_struct *current_set[NR_CPUS];
 
+#ifndef CONFIG_8xx
+unsigned long _SDR1;
+PTE *Hash, *Hash_end;
+unsigned long Hash_size, Hash_mask;
+static void hash_init(void);
+union ubat {			/* BAT register values to be loaded */
+	BAT	bat;
+	P601_BAT bat_601;
+	u32	word[2];
+} BATS[4][2];			/* 4 pairs of IBAT, DBAT */
+
+struct batrange {		/* stores address ranges mapped by BATs */
+	unsigned long start;
+	unsigned long limit;
+	unsigned long phys;
+} bat_addrs[4];
+#endif /* CONFIG_8xx */
 #ifdef CONFIG_MBX
-/* This is a big hack that may not yet work correctly.
- * The MBX8xx boards have a single DIMM socket for additional memory.
- * Although it appears you can set magical locations in the serial
- * EEPROM to get EPPC-Bug to configure this memory, there are no tools
- * (i.e. commands) to make this easy.  If you screw up, you will most
- * likely end up with a board that will not boot until you find a
- * way to program the EEPROM correctly.  I decided to simply program
- * the memory controller here to add the additional memory.
- * The reason this may not work correctly is that depending upon the
- * on-board and DIMM memory size, there may be holes in the physical
- * address space.  This is the case for me, I have a 4 MB local memory
- * and a 32 MB DIMM.
- * The DIMM is 64 bits wide, and we see it as two banks of 32 bit
- * memory.  The holes are caused by the requirement to map the
- * memory on a natural alignment, that is a 16 MB bank must begin on
- * a 16 MB boundary.  The DIMM_SIZE below represents the size of the
- * bank, which is the total size divided by two.
- * Although I may not have all of this working, the intention is to
- * mark all of the page maps in the "hole" as reserved, and adjust
- * num_physpages accordingly.  In the current implementation, this
- * seems to work, but there are some assumptions about contiguous
- * memory.  The correct solution is to modify the memory allocators
- * to know about holes, but that will have to wait for another day.
- *
- * define DIMM_8xx to enable this feature.
- * define DIMM_SIZE to reflect the bank size (DIMM size divided by two).
- */
-/*#define DIMM_8xx      1 */
-#define DIMM_SIZE       (16 * 1024 * 1024)
+void set_mbx_memory(void);
 #endif /* CONFIG_MBX */
 
 /*
  * this tells the system to map all of ram with the segregs
  * (i.e. page tables) instead of the bats.
+ * -- Cort
  */
 #undef MAP_RAM_WITH_SEGREGS 1
-
-/* optimization for 603 to load the tlb directly from the linux table */
+/* optimization for 603 to load the tlb directly from the linux table -- Cort */
 #define NO_RELOAD_HTAB 1 /* change in kernel/head.S too! */
 
 void __bad_pte(pmd_t *pmd)
@@ -177,7 +165,8 @@
 
 pte_t * __bad_pagetable(void)
 {
-	memset((void *)empty_bad_page_table, 0, PAGE_SIZE);
+	/*memset((void *)empty_bad_page_table, 0, PAGE_SIZE);*/
+	__clear_user((void *)empty_bad_page_table, PAGE_SIZE);
 	return (pte_t *) empty_bad_page_table;
 }
 
@@ -185,10 +174,355 @@
 
 pte_t __bad_page(void)
 {
-	memset((void *)empty_bad_page, 0, PAGE_SIZE);
+	/*memset((void *)empty_bad_page, 0, PAGE_SIZE);*/
+	__clear_user((void *)empty_bad_page, PAGE_SIZE);
 	return pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED));
 }
 
+void show_mem(void)
+{
+	int i,free = 0,total = 0,reserved = 0;
+	int shared = 0, cached = 0;
+	struct task_struct *p;
+
+	printk("Mem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+	i = max_mapnr;
+	while (i-- > 0) {
+		total++;
+		if (PageReserved(mem_map+i))
+			reserved++;
+		else if (PageSwapCache(mem_map+i))
+			cached++;
+		else if (!atomic_read(&mem_map[i].count))
+			free++;
+		else
+			shared += atomic_read(&mem_map[i].count) - 1;
+	}
+	printk("%d pages of RAM\n",total);
+	printk("%d free pages\n",free);
+	printk("%d reserved pages\n",reserved);
+	printk("%d pages shared\n",shared);
+	printk("%d pages swap cached\n",cached);
+	printk("%d pages in page table cache\n",(int)pgtable_cache_size);
+	show_buffers();
+#ifdef CONFIG_NET
+	show_net_buffers();
+#endif
+	printk("%-8s %3s %3s %8s %8s %8s %9s %8s", "Process", "Pid", "Cnt",
+	       "Ctx", "Ctx<<4", "Last Sys", "pc", "task");
+#ifdef __SMP__
+	printk(" %3s", "CPU");
+#endif /* __SMP__ */
+	printk("\n");
+	for_each_task(p)
+	{	
+		printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ",
+		       p->comm,p->pid,
+		       p->mm->count,p->mm->context,
+		       p->mm->context<<4, p->tss.last_syscall,
+		       user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip,
+		       (ulong)p);
+		{
+			int iscur = 0;
+#ifdef __SMP__
+			printk("%3d ", p->processor);
+			if ( (p->processor != NO_PROC_ID) &&
+			     (p == current_set[p->processor]) )
+			
+#else		
+			if ( p == current )
+#endif /* __SMP__ */
+			{
+				iscur = 1;
+				printk("current");
+			}
+			if ( p == last_task_used_math )
+			{
+				if ( iscur )
+					printk(",");
+				printk("last math");
+			}			
+			printk("\n");
+		}
+	}
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+	int i;
+
+	i = max_mapnr;
+	val->totalram = 0;
+	val->sharedram = 0;
+	val->freeram = nr_free_pages << PAGE_SHIFT;
+	val->bufferram = buffermem;
+	while (i-- > 0)  {
+		if (PageReserved(mem_map+i))
+			continue;
+		val->totalram++;
+		if (!atomic_read(&mem_map[i].count))
+			continue;
+		val->sharedram += atomic_read(&mem_map[i].count) - 1;
+	}
+	val->totalram <<= PAGE_SHIFT;
+	val->sharedram <<= PAGE_SHIFT;
+	return;
+}
+
+void *
+ioremap(unsigned long addr, unsigned long size)
+{
+	return __ioremap(addr, size, _PAGE_NO_CACHE);
+}
+
+void *
+__ioremap(unsigned long addr, unsigned long size, unsigned long flags)
+{
+	unsigned long p, v, i;
+
+	/*
+	 * Choose an address to map it to.
+	 * Once the vmalloc system is running, we use it.
+	 * Before then, we map addresses >= ioremap_base
+	 * virt == phys; for addresses below this we use
+	 * space going down from ioremap_base (ioremap_bot
+	 * records where we're up to).
+	 *
+	 * We should also look out for a frame buffer and
+	 * map it with a free BAT register, if there is one.
+	 */
+	p = addr & PAGE_MASK;
+	size = PAGE_ALIGN(addr + size) - p;
+	if (size == 0)
+		return NULL;
+
+	if (mem_init_done) {
+		struct vm_struct *area;
+		area = get_vm_area(size);
+		if (area == 0)
+			return NULL;
+		v = VMALLOC_VMADDR(area->addr);
+	} else {
+		if (p >= ioremap_base)
+			v = p;
+		else
+			v = (ioremap_bot -= size);
+	}
+
+	flags |= pgprot_val(PAGE_KERNEL);
+	if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU))
+		flags |= _PAGE_GUARDED;
+	for (i = 0; i < size; i += PAGE_SIZE)
+		map_page(&init_task, v+i, p+i, flags);
+
+	return (void *) (v + (addr & ~PAGE_MASK));
+}
+
+void iounmap(void *addr)
+{
+	/* XXX todo */
+}
+
+unsigned long iopa(unsigned long addr)
+{
+	unsigned long idx;
+	pmd_t *pd;
+	pte_t *pg;
+#ifndef CONFIG_8xx
+	int b;
+#endif
+	idx = addr & ~PAGE_MASK;
+	addr = addr & PAGE_MASK;
+
+#ifndef CONFIG_8xx
+	/* Check the BATs */
+	for (b = 0; b < 4; ++b)
+		if (addr >= bat_addrs[b].start && addr <= bat_addrs[b].limit)
+#ifndef CONFIG_APUS
+			return bat_addrs[b].phys | idx;
+#else
+			/* Do a more precise remapping of virtual address */
+			/* --Carsten */
+			return (bat_addrs[b].phys - bat_addrs[b].start + addr) | idx;
+#endif /* CONFIG_APUS */
+#endif /* CONFIG_8xx */
+	/* Do we have a page table? */
+	if (init_task.mm->pgd == NULL)
+		return 0;
+
+	/* Use upper 10 bits of addr to index the first level map */
+	pd = (pmd_t *) (init_task.mm->pgd + (addr >> PGDIR_SHIFT));
+	if (pmd_none(*pd))
+		return 0;
+
+	/* Use middle 10 bits of addr to index the second-level map */
+	pg = pte_offset(pd, addr);
+	return (pte_val(*pg) & PAGE_MASK) | idx;
+}
+
+void
+map_page(struct task_struct *tsk, unsigned long va,
+	 unsigned long pa, int flags)
+{
+	pmd_t *pd;
+	pte_t *pg;
+#ifndef CONFIG_8xx
+	int b;
+#endif
+	if (tsk->mm->pgd == NULL) {
+		/* Allocate upper level page map */
+		tsk->mm->pgd = (pgd_t *) MMU_get_page();
+	}
+	/* Use upper 10 bits of VA to index the first level map */
+	pd = (pmd_t *) (tsk->mm->pgd + (va >> PGDIR_SHIFT));
+	if (pmd_none(*pd)) {
+#ifndef CONFIG_8xx
+		/*
+		 * Need to allocate second-level table, but first
+		 * check whether this address is already mapped by
+		 * the BATs; if so, don't bother allocating the page.
+		 */
+		for (b = 0; b < 4; ++b) {
+			if (va >= bat_addrs[b].start
+			    && va <= bat_addrs[b].limit) {
+				/* XXX should check the phys address matches */
+				return;
+			}
+		}
+#endif /* CONFIG_8xx */
+		pg = (pte_t *) MMU_get_page();
+		pmd_val(*pd) = (unsigned long) pg;
+	}
+	/* Use middle 10 bits of VA to index the second-level map */
+	pg = pte_offset(pd, va);
+	set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
+#ifndef CONFIG_8xx
+	flush_hash_page(0, va);
+#endif	
+}
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *
+ * since the hardware hash table functions as an extension of the
+ * tlb as far as the linux tables are concerned, flush it too.
+ *    -- Cort
+ */
+
+/*
+ * Flush all tlb/hash table entries (except perhaps for those
+ * mapping RAM starting at PAGE_OFFSET, since they never change).
+ */
+void
+local_flush_tlb_all(void)
+{
+#ifndef CONFIG_8xx
+	__clear_user(Hash, Hash_size);
+	/*memset(Hash, 0, Hash_size);*/
+	_tlbia();
+#else
+	asm volatile ("tlbia" : : );
+#endif
+}
+
+/*
+ * Flush all the (user) entries for the address space described
+ * by mm.  We can't rely on mm->mmap describing all the entries
+ * that might be in the hash table.
+ */
+void
+local_flush_tlb_mm(struct mm_struct *mm)
+{
+#ifndef CONFIG_8xx
+	mm->context = NO_CONTEXT;
+	if (mm == current->mm)
+		activate_context(current);
+#else
+	asm volatile ("tlbia" : : );
+#endif
+}
+
+void
+local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+#ifndef CONFIG_8xx
+	if (vmaddr < TASK_SIZE)
+		flush_hash_page(vma->vm_mm->context, vmaddr);
+	else
+		flush_hash_page(0, vmaddr);
+#else
+	asm volatile ("tlbia" : : );
+#endif
+}
+
+
+/*
+ * for each page addr in the range, call MMU_invalidate_page()
+ * if the range is very large and the hash table is small it might be
+ * faster to do a search of the hash table and just invalidate pages
+ * that are in the range but that's for study later.
+ * -- Cort
+ */
+void
+local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+#ifndef CONFIG_8xx
+	start &= PAGE_MASK;
+
+	if (end - start > 20 * PAGE_SIZE)
+	{
+		flush_tlb_mm(mm);
+		return;
+	}
+
+	for (; start < end && start < TASK_SIZE; start += PAGE_SIZE)
+	{
+		flush_hash_page(mm->context, start);
+	}
+#else
+	asm volatile ("tlbia" : : );
+#endif
+}
+
+/*
+ * The context counter has overflowed.
+ * We set mm->context to NO_CONTEXT for all mm's in the system.
+ * We assume we can get to all mm's by looking as tsk->mm for
+ * all tasks in the system.
+ */
+void
+mmu_context_overflow(void)
+{
+#ifndef CONFIG_8xx
+	struct task_struct *tsk;
+
+	printk(KERN_DEBUG "mmu_context_overflow\n");
+	read_lock(&tasklist_lock);
+ 	for_each_task(tsk) {
+		if (tsk->mm)
+			tsk->mm->context = NO_CONTEXT;
+	}
+	read_unlock(&tasklist_lock);
+	flush_hash_segments(0x10, 0xffffff);
+	next_mmu_context = 0;
+	/* make sure current always has a context */
+	current->mm->context = MUNGE_CONTEXT(++next_mmu_context);
+	set_context(current->mm->context);
+#else
+	/* We set the value to -1 because it is pre-incremented before
+	 * before use.
+	 */
+	next_mmu_context = -1;
+#endif
+}
+
 /*
  * The following stuff defines a data structure for representing
  * areas of memory as an array of (address, length) pairs, and
@@ -211,8 +545,8 @@
 /*
  * Scan a region for a piece of a given size with the required alignment.
  */
-void *
-find_mem_piece(unsigned size, unsigned align)
+__initfunc(void *
+find_mem_piece(unsigned size, unsigned align))
 {
 	int i;
 	unsigned a, e;
@@ -235,9 +569,9 @@
 /*
  * Remove some memory from an array of pieces
  */
-static void
+__initfunc(static void
 remove_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size,
-		 int must_exist)
+		 int must_exist))
 {
 	int i, j;
 	unsigned end, rs, re;
@@ -291,8 +625,7 @@
 	}
 }
 
-static void
-print_mem_pieces(struct mem_pieces *mp)
+__initfunc(static void print_mem_pieces(struct mem_pieces *mp))
 {
 	int i;
 
@@ -311,8 +644,7 @@
 static void coalesce_mem_pieces(struct mem_pieces *);
 static void append_mem_piece(struct mem_pieces *, unsigned, unsigned);
 
-static void
-sort_mem_pieces(struct mem_pieces *mp)
+__initfunc(static void sort_mem_pieces(struct mem_pieces *mp))
 {
 	unsigned long a, s;
 	int i, j;
@@ -330,8 +662,7 @@
 	}
 }
 
-static void
-coalesce_mem_pieces(struct mem_pieces *mp)
+__initfunc(static void coalesce_mem_pieces(struct mem_pieces *mp))
 {
 	unsigned long a, e;
 	int i, j, d;
@@ -353,8 +684,8 @@
 /*
  * Add some memory to an array of pieces
  */
-static void
-append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size)
+__initfunc(static void
+	   append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size))
 {
 	struct reg_property *rp;
 
@@ -369,8 +700,7 @@
  * Read in a property describing some pieces of memory.
  */
 
-static void
-get_mem_prop(char *name, struct mem_pieces *mp)
+__initfunc(static void get_mem_prop(char *name, struct mem_pieces *mp))
 {
 	struct reg_property *rp;
 	int s;
@@ -389,423 +719,16 @@
 	coalesce_mem_pieces(mp);
 }
 
-/*
- * On systems with Open Firmware, collect information about
- * physical RAM and which pieces are already in use.
- * At this point, we have (at least) the first 8MB mapped with a BAT.
- * Our text, data, bss use something over 1MB, starting at 0.
- * Open Firmware may be using 1MB at the 4MB point.
- */
-unsigned long *pmac_find_end_of_memory(void)
-{
-	unsigned long a, total;
-	unsigned long kstart, ksize;
-	int i;
-
-	memory_node = find_devices("memory");
-	if (memory_node == NULL) {
-		printk(KERN_ERR "can't find memory node\n");
-		abort();
-	}
-
-	/*
-	 * Find out where physical memory is, and check that it
-	 * starts at 0 and is contiguous.  It seems that RAM is
-	 * always physically contiguous on Power Macintoshes,
-	 * because MacOS can't cope if it isn't.
-	 *
-	 * Supporting discontiguous physical memory isn't hard,
-	 * it just makes the virtual <-> physical mapping functions
-	 * more complicated (or else you end up wasting space
-	 * in mem_map).
-	 */
-	get_mem_prop("reg", &phys_mem);
-	if (phys_mem.n_regions == 0)
-		panic("No RAM??");
-	a = phys_mem.regions[0].address;
-	if (a != 0)
-		panic("RAM doesn't start at physical address 0");
-	total = phys_mem.regions[0].size;
-	if (phys_mem.n_regions > 1) {
-		printk("RAM starting at 0x%x is not contiguous\n",
-		       phys_mem.regions[1].address);
-		printk("Using RAM from 0 to 0x%lx\n", total-1);
-		phys_mem.n_regions = 1;
-	}
-
-	/* record which bits the prom is using */
-	get_mem_prop("available", &phys_avail);
-	prom_mem = phys_mem;
-	for (i = 0; i < phys_avail.n_regions; ++i)
-		remove_mem_piece(&prom_mem, phys_avail.regions[i].address,
-				 phys_avail.regions[i].size, 1);
-
-	/*
-	 * phys_avail records memory we can use now.
-	 * prom_mem records memory allocated by the prom that we
-	 * don't want to use now, but we'll reclaim later.
-	 * Make sure the kernel text/data/bss is in neither.
-	 */
-	kstart = __pa(_stext);	/* should be 0 */
-	ksize = PAGE_ALIGN(klimit - _stext);
-	remove_mem_piece(&phys_avail, kstart, ksize, 0);
-	remove_mem_piece(&prom_mem, kstart, ksize, 0);
-	remove_mem_piece(&phys_avail, 0, 0x4000, 0);
-	remove_mem_piece(&prom_mem, 0, 0x4000, 0);
-
-	return __va(total);
-}
-#endif /* CONFIG_8xx */
-
-#ifdef CONFIG_APUS
-#define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long *apus_find_end_of_memory(void)
-{
-	unsigned long kstart, ksize;
-
-	/* Add the chunk that ADOS does not see. Removed again below. */
-	m68k_memory[0].size += HARDWARE_MAPPED_SIZE;
-
-	append_mem_piece(&phys_mem, m68k_memory[0].addr, m68k_memory[0].size);
-
-	phys_avail = phys_mem;
-	kstart = __pa(_stext);
-	ksize = PAGE_ALIGN(klimit - _stext);
-	remove_mem_piece(&phys_avail, kstart, ksize, 1);
-
-	/* Remove the upper HARDWARE_MAPPED_SIZE bytes where the address
-	 * range 0xfff00000-0xfffx0000 is mapped to.
-	 * We do it this way to ensure that the memory registered in the
-	 * system has a power-of-two size.
-	 */
-	remove_mem_piece(&phys_avail, 
-			 (m68k_memory[0].addr + m68k_memory[0].size 
-			  - HARDWARE_MAPPED_SIZE),
-			 HARDWARE_MAPPED_SIZE, 1);
-
-	/* FIXME:APUS: Only handles one block of memory! Problem is
-	 * that the VTOP/PTOV code in head.S would be a mess if it had
-	 * to handle more than one block.
-	 */
-	return __va(m68k_memory[0].addr + m68k_memory[0].size);
-}
-#endif
-
-/*
- * Find some memory for setup_arch to return.
- * We use the last chunk of available memory as the area
- * that setup_arch returns, making sure that there are at
- * least 32 pages unused before this for MMU_get_page to use.
- */
-unsigned long avail_start;
-
-unsigned long find_available_memory(void)
-{
-	int i;
-	unsigned long a, free;
-	unsigned long start, end;
-
-	free = 0;
-	if (_machine == _MACH_mbx) {
-		/* Return the first, not the last region, because we
-                 * may not yet have properly initialized the additonal
-                 * memory DIMM.
-                 */
-                a = PAGE_ALIGN(phys_avail.regions[0].address);
-                avail_start = (unsigned long) __va(a);
-                return avail_start;
-        }
-	
-	for (i = 0; i < phys_avail.n_regions - 1; ++i) {
-		start = phys_avail.regions[i].address;
-		end = start + phys_avail.regions[i].size;
-		free += (end & PAGE_MASK) - PAGE_ALIGN(start);
-	}
-	a = PAGE_ALIGN(phys_avail.regions[i].address);
-	if (free < 32 * PAGE_SIZE)
-		a += 32 * PAGE_SIZE - free;
-	avail_start = (unsigned long) __va(a);
-	return avail_start;
-}
-
-void show_mem(void)
-{
-	int i,free = 0,total = 0,reserved = 0;
-	int shared = 0, cached = 0;
-	struct task_struct *p;
-
-	printk("Mem-info:\n");
-	show_free_areas();
-	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	i = max_mapnr;
-	while (i-- > 0) {
-		total++;
-		if (PageReserved(mem_map+i))
-			reserved++;
-		else if (PageSwapCache(mem_map+i))
-			cached++;
-		else if (!atomic_read(&mem_map[i].count))
-			free++;
-		else
-			shared += atomic_read(&mem_map[i].count) - 1;
-	}
-	printk("%d pages of RAM\n",total);
-	printk("%d free pages\n",free);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	printk("%d pages swap cached\n",cached);
-	printk("%d pages in page table cache\n",(int)pgtable_cache_size);
-	show_buffers();
-#ifdef CONFIG_NET
-	show_net_buffers();
-#endif
-	printk("%-8s %3s %3s %8s %8s %8s %9s %8s", "Process", "Pid", "Cnt",
-	       "Ctx", "Ctx<<4", "Last Sys", "pc", "task");
-#ifdef __SMP__
-	printk(" %3s", "CPU");
-#endif /* __SMP__ */
-	printk("\n");
-	for_each_task(p)
-	{	
-		printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ",
-		       p->comm,p->pid,
-		       p->mm->count,p->mm->context,
-		       p->mm->context<<4, p->tss.last_syscall,
-		       user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip,
-		       (ulong)p);
-		{
-			int iscur = 0;
-#ifdef __SMP__
-			printk("%3d ", p->processor);
-			if ( (p->processor != NO_PROC_ID) &&
-			     (p == current_set[p->processor]) )
-			
-#else		
-			if ( p == current )
-#endif /* __SMP__ */
-			{
-				iscur = 1;
-				printk("current");
-			}
-			if ( p == last_task_used_math )
-			{
-				if ( iscur )
-					printk(",");
-				printk("last math");
-			}			
-			printk("\n");
-		}
-	}
-}
-
-extern unsigned long free_area_init(unsigned long, unsigned long);
-
-/*
- * paging_init() sets up the page tables - in fact we've already done this.
- */
-unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
-{
-	/*
-	 * Grab some memory for bad_page and bad_pagetable to use.
-	 */
-	empty_bad_page = PAGE_ALIGN(start_mem);
-	empty_bad_page_table = empty_bad_page + PAGE_SIZE;
-	start_mem = empty_bad_page + 2 * PAGE_SIZE;
-
-	/* note: free_area_init uses its second argument
-	   to size the mem_map array. */
-	start_mem = free_area_init(start_mem, end_mem);
-	return start_mem;
-}
-
-void mem_init(unsigned long start_mem, unsigned long end_mem)
-{
-	unsigned long addr;
-	int i;
-	unsigned long a, lim;
-	int codepages = 0;
-	int datapages = 0;
-	int initpages = 0;
-	extern unsigned int rtas_data, rtas_size;
-
-	end_mem &= PAGE_MASK;
-	high_memory = (void *) end_mem;
-	max_mapnr = MAP_NR(high_memory);
-	num_physpages = max_mapnr;	/* RAM is assumed contiguous */
-
-	/* mark usable pages in the mem_map[] */
-	start_mem = PAGE_ALIGN(start_mem);
-
-#ifndef CONFIG_8xx
-	remove_mem_piece(&phys_avail, __pa(avail_start),
-			 start_mem - avail_start, 1);
-
-	for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE)
-		set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
-
-	for (i = 0; i < phys_avail.n_regions; ++i) {
-		a = (unsigned long) __va(phys_avail.regions[i].address);
-		lim = a + phys_avail.regions[i].size;
-		a = PAGE_ALIGN(a);
-		for (; a < lim; a += PAGE_SIZE)
-			clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
-	}
-	phys_avail.n_regions = 0;
-
-	/* free the prom's memory - no-op on prep */
-	for (i = 0; i < prom_mem.n_regions; ++i) {
-		a = (unsigned long) __va(prom_mem.regions[i].address);
-		lim = a + prom_mem.regions[i].size;
-		a = PAGE_ALIGN(a);
-		for (; a < lim; a += PAGE_SIZE)
-			clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
-	}
-	prom_trashed = 1;
-#else /* CONFIG_8xx */
-	/* When we get here, all of the page maps have been set up and
-         * Linux thinks we have contiguous memory.  Since the MBX can
-         * have memory holes, we need to compensate for that here.
-         * The memory holes are currently pages marked reserved (all
-         * pages right now are marked reserved).
-         * All of the memory allocated by the kernel up to this point
-         * had to come from region 0.
-         */
-
-        /* First, unreserve all memory from the page following start_mem
-         * to the end of region 0.
-         */
-        for (addr = start_mem + PAGE_SIZE ;
-              addr < (ulong) __va(phys_mem.regions[0].size);
-                addr += PAGE_SIZE) {
-                        clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
-        }
-
-        /* Now add any additional regions to the system.
-        */
-        for (i = 1; i < phys_avail.n_regions; ++i) {
-                a = (unsigned long) __va(phys_avail.regions[i].address);
-                lim = a + phys_avail.regions[i].size;
-                a = PAGE_ALIGN(a);
-                for (; a < lim; a += PAGE_SIZE)
-                        clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
-        }
-        phys_avail.n_regions = 0;       /* Nothing available, kernel owns */
-        /* Count up the size of the holes.  We look for the space
-         * between the end of one region and the start of the next.
-         */
-        lim = 0;
-        for (i = 0; i < phys_mem.n_regions-1; ++i) {
-                a = (unsigned long) phys_mem.regions[i].address;
-                a += phys_mem.regions[i].size;
-                lim += phys_mem.regions[i+1].address - a;
-        }
-
-        /* It appears that num_physpages is only used for quota checking,
-         * when pages are locked down.  We subtract the size of the holes
-         * from it now.
-         */
-        num_physpages -= lim/PAGE_SIZE;
-#endif /* CONFIG_8xx */
-	
-	for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
-		if (PageReserved(mem_map + MAP_NR(addr))) {
-			if (addr < (ulong) etext)
-				codepages++;
-			else if (addr >= (unsigned long)&__init_begin
-				 && addr < (unsigned long)&__init_end)
-                                initpages++;
-                        else if (addr < (ulong) start_mem)
-				datapages++;
-			continue;
-		}
-		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (!initrd_start ||
-		    addr < (initrd_start & PAGE_MASK) || addr >= initrd_end)
-#endif /* CONFIG_BLK_DEV_INITRD */
-#ifndef CONFIG_8xx		  
-			if ( !rtas_data ||
-			     addr < (rtas_data & PAGE_MASK) ||
-			     addr >= (rtas_data+rtas_size))
 #endif /* CONFIG_8xx */
-				free_page(addr);
-	}
-
-        printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08x,%08lx]\n",
-	       (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
-	       codepages << (PAGE_SHIFT-10),
-	       datapages << (PAGE_SHIFT-10), 
-	       initpages << (PAGE_SHIFT-10),
-	       PAGE_OFFSET, end_mem);
-	mem_init_done = 1;
-}
-
-/*
- * Unfortunately, we can't put initialization functions in their
- * own section and free that at this point, because gas gets some
- * relocations wrong if we do. :-(  But this code is here for when
- * gas gets fixed.
- */
-void free_initmem(void)
-{
-	unsigned long a;
-	unsigned long num_freed_pages = 0;
-
-	a = (unsigned long)(&__init_begin);
-	for (; a < (unsigned long)(&__init_end); a += PAGE_SIZE) {
-		clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
-		atomic_set(&mem_map[MAP_NR(a)].count, 1);
-		free_page(a);
-		num_freed_pages++;
-	}
-
-	printk ("Freeing unused kernel memory: %ldk freed\n",
-		(num_freed_pages * PAGE_SIZE) >> 10);
-}
-
-void si_meminfo(struct sysinfo *val)
-{
-	int i;
-
-	i = max_mapnr;
-	val->totalram = 0;
-	val->sharedram = 0;
-	val->freeram = nr_free_pages << PAGE_SHIFT;
-	val->bufferram = buffermem;
-	while (i-- > 0)  {
-		if (PageReserved(mem_map+i))
-			continue;
-		val->totalram++;
-		if (!atomic_read(&mem_map[i].count))
-			continue;
-		val->sharedram += atomic_read(&mem_map[i].count) - 1;
-	}
-	val->totalram <<= PAGE_SHIFT;
-	val->sharedram <<= PAGE_SHIFT;
-	return;
-}
 
 #ifndef CONFIG_8xx
-union ubat {			/* BAT register values to be loaded */
-	BAT	bat;
-	P601_BAT bat_601;
-	u32	word[2];
-} BATS[4][2];			/* 4 pairs of IBAT, DBAT */
-
-struct batrange {		/* stores address ranges mapped by BATs */
-	unsigned long start;
-	unsigned long limit;
-	unsigned long phys;
-} bat_addrs[4];
-
 /*
  * Set up one of the I/D BAT (block address translation) register pairs.
  * The parameters are not checked; in particular size must be a power
  * of 2 between 128k and 256M.
  */
-void
-setbat(int index, unsigned long virt, unsigned long phys,
-       unsigned int size, int flags)
+__initfunc(void setbat(int index, unsigned long virt, unsigned long phys,
+       unsigned int size, int flags))
 {
 	unsigned int bl;
 	int wimgxpp;
@@ -853,37 +776,6 @@
 #define RAM_PAGE (_PAGE_RW)
 #endif
 
-/*
- * This finds the amount of physical ram and does necessary
- * setup for prep.  This is pretty architecture specific so
- * this will likely stay seperate from the pmac.
- * -- Cort
- */
-unsigned long *prep_find_end_of_memory(void)
-{
-	unsigned long kstart, ksize;
-	unsigned long total;
-	total = res.TotalMemory;
-
-	if (total == 0 )
-	{
-		/*
-		 * I need a way to probe the amount of memory if the residual
-		 * data doesn't contain it. -- Cort
-		 */
-		printk("Ramsize from residual data was 0 -- Probing for value\n");
-		total = 0x02000000;
-		printk("Ramsize default to be %ldM\n", total>>20);
-	}
-	append_mem_piece(&phys_mem, 0, total);
-	phys_avail = phys_mem;
-	kstart = __pa(_stext);	/* should be 0 */
-	ksize = PAGE_ALIGN(klimit - _stext);
-	remove_mem_piece(&phys_avail, kstart, ksize, 0);
-	remove_mem_piece(&phys_avail, 0, 0x4000, 0);
-
-	return (__va(total));
-}
 #endif /* CONFIG_8xx */
 
 /*
@@ -891,7 +783,7 @@
  */
 #define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
 
-static void mapin_ram()
+__initfunc(static void mapin_ram(void))
 {
 	int i;
 	unsigned long v, p, s, f;
@@ -957,87 +849,64 @@
 	}	    
 }
 
-#ifndef CONFIG_8xx
-/*
- * Initialize the hash table and patch the instructions in head.S.
- */
-static void hash_init(void)
+__initfunc(static void *MMU_get_page(void))
 {
-	int Hash_bits;
-	unsigned long h, ramsize;
+	void *p;
 
-	extern unsigned int hash_page_patch_A[], hash_page_patch_B[],
-		hash_page_patch_C[], hash_page_patch_D[];
+	if (mem_init_done) {
+		p = (void *) __get_free_page(GFP_KERNEL);
+		if (p == 0)
+			panic("couldn't get a page in MMU_get_page");
+	} else {
+		p = find_mem_piece(PAGE_SIZE, PAGE_SIZE);
+	}
+	/*memset(p, 0, PAGE_SIZE);*/
+	__clear_user(p, PAGE_SIZE);
+	return p;
+}
 
-	/*
-	 * Allow 64k of hash table for every 16MB of memory,
-	 * up to a maximum of 2MB.
-	 */
-	ramsize = (ulong)end_of_DRAM - KERNELBASE;
-	for (h = 64<<10; h < ramsize / 256 && h < 2<<20; h *= 2)
-		;
-	Hash_size = h;
-	Hash_mask = (h >> 6) - 1;
-	
-#ifdef NO_RELOAD_HTAB
-	/* shrink the htab since we don't use it on 603's -- Cort */
-	switch (_get_PVR()>>16) {
-	case 3: /* 603 */
-	case 6: /* 603e */
-	case 7: /* 603ev */
-		Hash_size = 0;
-		Hash_mask = 0;
-		break;
-	default:
-	        /* on 601/4 let things be */
-		break;
- 	}
-#endif /* NO_RELOAD_HTAB */
-	
-	/* Find some memory for the hash table. */
-	if ( Hash_size )
-		Hash = find_mem_piece(Hash_size, Hash_size);
-	else
-		Hash = 0;
+__initfunc(void free_initmem(void))
+{
+	unsigned long a;
+	unsigned long num_freed_pages = 0, num_prep_pages = 0,
+		num_pmac_pages = 0;
 
-	printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
-	       ramsize >> 20, Hash_size >> 10, Hash);
-	if ( Hash_size )
-	{
-		memset(Hash, 0, Hash_size);
-		Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+#define FREESEC(START,END,CNT) do { \
+	a = (unsigned long)(&START); \
+	for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
+	  	clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags); \
+		atomic_set(&mem_map[MAP_NR(a)].count, 1); \
+		free_page(a); \
+		CNT++; \
+	} \
+} while (0)
 
-		/*
-		 * Patch up the instructions in head.S:hash_page
-		 */
-		Hash_bits = ffz(~Hash_size) - 6;
-		hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
-			| (__pa(Hash) >> 16);
-		hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0)
-			| ((26 - Hash_bits) << 6);
-		if (Hash_bits > 16)
-			Hash_bits = 16;
-		hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0)
-			| ((26 - Hash_bits) << 6);
-		hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff)
-			| (Hash_mask >> 10);
-		hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff)
-			| (Hash_mask >> 10);
-		hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff)
-			| (Hash_mask >> 10);
-		/*
-		 * Ensure that the locations we've patched have been written
-		 * out from the data cache and invalidated in the instruction
-		 * cache, on those machines with split caches.
-		 */
-		flush_icache_range((unsigned long) hash_page_patch_A,
-				   (unsigned long) (hash_page_patch_D + 1));
+	FREESEC(__init_begin,__init_end,num_freed_pages);
+	switch (_machine)
+	{
+	case _MACH_Pmac:
+	case _MACH_chrp:
+		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		break;
+	case _MACH_prep:
+		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
+		FREESEC(__openfirmware_begin,__openfirmware_end,num_pmac_pages);
+		break;
+	case _MACH_mbx:
+		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
+		FREESEC(__openfirmware_begin,__openfirmware_end,num_pmac_pages);
+		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		break;
 	}
-	else
-		Hash_end = 0;
-
+	
+	printk ("Freeing unused kernel memory: %ldk init",
+		(num_freed_pages * PAGE_SIZE) >> 10);
+	if ( num_prep_pages )
+		printk(" %ldk prep",(num_prep_pages*PAGE_SIZE)>>10);
+	if ( num_pmac_pages )
+		printk(" %ldk pmac",(num_pmac_pages*PAGE_SIZE)>>10);
+	printk("\n");
 }
-#endif /* CONFIG_8xx */
 
 /*
  * Do very early mm setup such as finding the size of memory
@@ -1046,8 +915,7 @@
  * still be merged.
  * -- Cort
  */
-void
-MMU_init(void)
+__initfunc(void MMU_init(void))
 {
 #ifndef CONFIG_8xx
 	if (have_of)
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig
--- v2.1.100/linux/arch/ppc/pmac_defconfig	Thu Apr 23 20:21:29 1998
+++ linux/arch/ppc/pmac_defconfig	Fri May  8 00:18:23 1998
@@ -6,13 +6,15 @@
 # Platform support
 #
 CONFIG_PPC=y
-CONFIG_NATIVE=y
-CONFIG_PPC6XX=y
-# CONFIG_PPC8XX is not set
-CONFIG_MACH_SPECIFIC=y
+CONFIG_6xx=y
+# CONFIG_8xx is not set
 CONFIG_PMAC=y
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
+# CONFIG_ALL_PPC is not set
+# CONFIG_APUS is not set
+# CONFIG_MBX is not set
+CONFIG_MACH_SPECIFIC=y
 
 #
 # General setup
@@ -20,7 +22,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
-CONFIG_KERNELD=y
+CONFIG_KMOD=y
 CONFIG_PCI=y
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
@@ -31,12 +33,15 @@
 CONFIG_KERNEL_ELF=y
 CONFIG_BINFMT_MISC=m
 # CONFIG_BINFMT_JAVA is not set
+# CONFIG_PARPORT is not set
 # CONFIG_ABSTRACT_CONSOLE is not set
 CONFIG_PMAC_CONSOLE=y
 CONFIG_MAC_KEYBOARD=y
 CONFIG_MAC_FLOPPY=y
+CONFIG_MAC_SERIAL=y
 CONFIG_MACMOUSE=y
 CONFIG_PROC_DEVICETREE=y
+# CONFIG_KGDB is not set
 # CONFIG_XMON is not set
 CONFIG_CONTROL_VIDEO=y
 CONFIG_PLATINUM_VIDEO=y
@@ -73,22 +78,17 @@
 #
 # Additional Block Devices
 #
-CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=m
+CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
-# NEW devices (io_request, all ALPHA and dangerous)
-#
-# CONFIG_IO_REQUEST is not set
-
-#
 # Networking options
 #
 # CONFIG_PACKET is not set
@@ -102,7 +102,6 @@
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
 # CONFIG_IP_ACCT is not set
-# CONFIG_IP_MASQUERADE is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -122,11 +121,12 @@
 #  
 #
 # CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_ATALK=m
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
+# CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
@@ -146,7 +146,7 @@
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SG is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -163,9 +163,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=m
-# CONFIG_AIC7XXX_TAGGED_QUEUEING is not set
 # CONFIG_OVERRIDE_CMDS is not set
-# CONFIG_AIC7XXX_PAGE_ENABLE is not set
 CONFIG_AIC7XXX_PROC_STATS=y
 CONFIG_AIC7XXX_RESET_DELAY=15
 # CONFIG_SCSI_ADVANSYS is not set
@@ -182,7 +180,6 @@
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
-# CONFIG_SCSI_PPA is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
@@ -194,8 +191,9 @@
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_DEBUG is not set
 CONFIG_SCSI_MESH=y
-CONFIG_SCSI_MESH_SYNC_RATE=10
+CONFIG_SCSI_MESH_SYNC_RATE=5
 CONFIG_SCSI_MAC53C94=y
 
 #
@@ -223,13 +221,16 @@
 CONFIG_DEC_ELCP=m
 # CONFIG_DGRS is not set
 # CONFIG_EEXPRESS_PRO100 is not set
-# CONFIG_TLAN is not set
 # CONFIG_ES3210 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_TLAN is not set
 # CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
 # CONFIG_DLCI is not set
-# CONFIG_PLIP is not set
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
 CONFIG_PPP=m
 
 #
@@ -254,7 +255,6 @@
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
-CONFIG_CDROM=y
 
 #
 # Filesystems
@@ -284,13 +284,14 @@
 CONFIG_AUTOFS_FS=y
 # CONFIG_UFS_FS is not set
 # CONFIG_ADFS_FS is not set
+CONFIG_DEVPTS_FS=y
 CONFIG_MAC_PARTITION=y
 CONFIG_NLS=y
 
 #
 # Native Language Support
 #
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -323,11 +324,9 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_SOFTCURSOR is not set
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_PRINTER is not set
 # CONFIG_MOUSE is not set
 # CONFIG_UMISC is not set
 # CONFIG_QIC02_TAPE is not set
@@ -343,8 +342,3 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig
--- v2.1.100/linux/arch/ppc/prep_defconfig	Sat May  2 14:19:52 1998
+++ linux/arch/ppc/prep_defconfig	Fri May  8 00:18:23 1998
@@ -23,7 +23,6 @@
 CONFIG_MODVERSIONS=y
 CONFIG_KERNELD=y
 CONFIG_PCI=y
-# CONFIG_PCI_QUIRKS is not set
 # CONFIG_PCI_OPTIMIZE is not set
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
@@ -221,7 +220,6 @@
 # CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
 #
 # CONFIG_CD_NO_IDESCSI is not set
-CONFIG_CDROM=y
 
 #
 # Filesystems
diff -u --recursive --new-file v2.1.100/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds
--- v2.1.100/linux/arch/ppc/vmlinux.lds	Thu Sep  4 12:54:48 1997
+++ linux/arch/ppc/vmlinux.lds	Fri May  8 00:18:23 1998
@@ -71,6 +71,27 @@
   . = ALIGN(4096);
   __init_end = .;
 
+  . = ALIGN(4096);
+  __pmac_begin = .;
+  .text.pmac : { *(.text.pmac) }
+  .data.pmac : { *(.data.pmac) }
+  . = ALIGN(4096);
+  __pmac_end = .;
+
+  . = ALIGN(4096);
+  __prep_begin = .;
+  .text.prep : { *(.text.prep) }
+  .data.prep : { *(.data.prep) }
+  . = ALIGN(4096);
+  __prep_end = .;
+
+  . = ALIGN(4096);
+  __openfirmware_begin = .;
+  .text.openfirmware : { *(.text.openfirmware) }
+  .data.openfirmware : { *(.data.openfirmware) }
+  . = ALIGN(4096);
+  __openfirmware_end = .;
+
   __bss_start = .;
   .bss       :
   {
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/Makefile linux/arch/sparc/Makefile
--- v2.1.100/linux/arch/sparc/Makefile	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/Makefile	Fri May  8 00:09:20 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.34 1998/04/06 16:09:34 jj Exp $
+# $Id: Makefile,v 1.35 1998/04/18 03:40:53 davem Exp $
 # sparc/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -45,6 +45,8 @@
 
 archclean:
 	-$(MAKE) -C arch/sparc/boot archclean
+
+archmrproper:
 	-$(MAKE) -C arch/sparc/math-emu cleansymlinks
 
 archdep:
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.1.100/linux/arch/sparc/config.in	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/config.in	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.54 1998/03/27 06:59:39 davem Exp $
+# $Id: config.in,v 1.55 1998/04/12 06:20:22 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.1.100/linux/arch/sparc/defconfig	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/defconfig	Fri May  8 00:11:28 1998
@@ -138,16 +138,14 @@
 #  
 #
 CONFIG_IPX=m
-
-#
-# IPX options
-#
 # CONFIG_IPX_INTERN is not set
+# CONFIG_SPX is not set
 CONFIG_ATALK=m
 CONFIG_X25=m
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
+# CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
@@ -155,11 +153,12 @@
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_CSZ=m
+CONFIG_NET_SCH_PRIO=y
 CONFIG_NET_SCH_RED=m
 CONFIG_NET_SCH_SFQ=m
+# CONFIG_NET_SCH_TEQL is not set
 CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_PFIFO=y
-CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_QOS is not set
 # CONFIG_NET_PROFILE is not set
 
 #
@@ -226,7 +225,6 @@
 CONFIG_HAPPYMEAL=m
 CONFIG_SUNQE=m
 CONFIG_MYRI_SBUS=m
-CONFIG_CDROM=y
 
 #
 # Filesystems
@@ -268,6 +266,7 @@
 CONFIG_SMD_DISKLABEL=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_ADFS_FS is not set
+CONFIG_DEVPTS_FS=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.1.100/linux/arch/sparc/kernel/head.S	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/head.S	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.90 1998/03/24 18:12:05 jj Exp $
+/* $Id: head.S,v 1.91 1998/04/24 13:40:48 jj Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -403,7 +403,7 @@
 	BAD_TRAP(0xfc) BAD_TRAP(0xfd) BAD_TRAP(0xfe) BAD_TRAP(0xff)
 
 #endif
-	.align 4096
+	.align PAGE_SIZE
 
 /* This was the only reasonable way I could think of to properly align
  * these page-table data structures.
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.1.100/linux/arch/sparc/kernel/sun4d_irq.c	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/sun4d_irq.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/*  $Id: sun4d_irq.c,v 1.12 1998/03/19 15:36:36 jj Exp $
+/*  $Id: sun4d_irq.c,v 1.13 1998/04/15 14:58:33 jj Exp $
  *  arch/sparc/kernel/sun4d_irq.c:
  *			SS1000/SC2000 interrupt handling.
  *
@@ -495,7 +495,7 @@
 #endif
 }
 
-__initfunc(unsigned long sun4d_init_sbi_irq(unsigned long memory_start))
+__initfunc(void sun4d_init_sbi_irq(void))
 {
 	struct linux_sbus *sbus;
 	unsigned mask;
@@ -503,9 +503,7 @@
 	nsbi = 0;
 	for_each_sbus(sbus)
 		nsbi++;
-	memory_start = ((memory_start + 7) & ~7);
-	sbus_actions = (struct sbus_action *)memory_start;
-	memory_start += (nsbi * 8 * 4 * sizeof(struct sbus_action));
+	sbus_actions = (struct sbus_action *)kmalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
 	memset (sbus_actions, 0, (nsbi * 8 * 4 * sizeof(struct sbus_action)));
 	for_each_sbus(sbus) {
 #ifdef __SMP__	
@@ -521,7 +519,6 @@
 			release_sbi(sbus->devid, mask);
 		}
 	}
-	return memory_start;
 }
 
 __initfunc(void sun4d_init_IRQ(void))
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.1.100/linux/arch/sparc/kernel/systbls.S	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/systbls.S	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.71 1998/03/24 06:25:06 ecd Exp $
+/* $Id: systbls.S,v 1.72 1998/04/14 13:49:46 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -63,7 +63,7 @@
 	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
 	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
 	.long C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_readv)
+	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_getcwd), C_LABEL(sys_readv)
 	.long C_LABEL(sys_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown)
 	.long C_LABEL(sys_fchmod), C_LABEL(sys_nis_syscall), C_LABEL(sys_setreuid)
 	.long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate)
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/math-emu/fnegs.c linux/arch/sparc/math-emu/fnegs.c
--- v2.1.100/linux/arch/sparc/math-emu/fnegs.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/math-emu/fnegs.c	Fri May  8 00:11:28 1998
@@ -4,4 +4,3 @@
 	rd[0] = rs2[0] ^ 0x80000000UL;
 	return 1;
 }
-                
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v2.1.100/linux/arch/sparc/mm/fault.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/mm/fault.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.93 1998/03/25 10:43:16 jj Exp $
+/* $Id: fault.c,v 1.94 1998/05/01 16:00:27 jj Exp $
  * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -248,9 +248,11 @@
 			extern const unsigned __csum_partial_copy_start[];
 			extern const unsigned __csum_partial_copy_end[];
 
+#ifdef DEBUG_EXCEPTIONS
 			printk("Exception: PC<%08lx> faddr<%08lx>\n", regs->pc, address);
 			printk("EX_TABLE: insn<%08lx> fixup<%08x> g2<%08lx>\n",
 				regs->pc, fixup, g2);
+#endif
 			if ((regs->pc >= (unsigned long)__memset_start &&
 			     regs->pc < (unsigned long)__memset_end) ||
 			    (regs->pc >= (unsigned long)__csum_partial_copy_start &&
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c
--- v2.1.100/linux/arch/sparc/mm/io-unit.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/mm/io-unit.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.10 1998/03/03 12:31:14 jj Exp $
+/* $Id: io-unit.c,v 1.11 1998/04/13 07:26:37 davem Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -23,22 +23,17 @@
 #define IOD(x) do { } while (0)
 #endif
 
-#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
-
 #define IOPERM        (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID)
 #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
 
-__initfunc(unsigned long
-iounit_init(int sbi_node, int io_node, unsigned long memory_start,
-	    unsigned long memory_end, struct linux_sbus *sbus))
+__initfunc(void
+iounit_init(int sbi_node, int io_node, struct linux_sbus *sbus))
 {
 	iopte_t *xpt, *xptend;
 	struct iounit_struct *iounit;
 	struct linux_prom_registers iommu_promregs[PROMREG_MAX];
 	
-	memory_start = LONG_ALIGN(memory_start);
-	iounit = (struct iounit_struct *)memory_start;
-	memory_start = LONG_ALIGN(memory_start + sizeof(struct iounit_struct));
+	iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
 	
 	memset(iounit, 0, sizeof(*iounit));
 	iounit->limit[0] = IOUNIT_BMAP1_START;
@@ -62,8 +57,6 @@
 	for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
 	     xpt < xptend;)
 	     	*xpt++ = 0;
-	     	
-	return memory_start;
 }
 
 /* One has to hold iounit->lock to call this */
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.1.100/linux/arch/sparc/mm/iommu.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/mm/iommu.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.7 1998/02/22 10:32:26 ecd Exp $
+/* $Id: iommu.c,v 1.9 1998/04/15 14:58:37 jj Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -10,6 +10,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/mm.h>
 #include <linux/malloc.h>
 #include <asm/pgtable.h>
 #include <asm/sbus.h>
@@ -26,14 +27,12 @@
 extern void viking_flush_page(unsigned long page);
 extern void viking_mxcc_flush_page(unsigned long page);
 
-#define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
-
 #define IOPERM        (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID)
 #define MKIOPTE(phys) (((((phys)>>4) & IOPTE_PAGE) | IOPERM) & ~IOPTE_WAZ)
 
-static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu,
-						  unsigned long kern_end)
+static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu)
 {
+	unsigned long kern_end = (unsigned long) high_memory;
 	unsigned long first = page_offset;
 	unsigned long last = kern_end;
 	iopte_t *iopte = iommu->page_table;
@@ -45,18 +44,17 @@
 	}
 }
 
-__initfunc(unsigned long
-iommu_init(int iommund, unsigned long memory_start,
-	   unsigned long memory_end, struct linux_sbus *sbus))
+__initfunc(void
+iommu_init(int iommund, struct linux_sbus *sbus))
 {
 	unsigned int impl, vers, ptsize;
 	unsigned long tmp;
 	struct iommu_struct *iommu;
 	struct linux_prom_registers iommu_promregs[PROMREG_MAX];
+	int i, j, k, l, m;
+	struct iommu_alloc { unsigned long addr; int next; } *ia;
 
-	memory_start = LONG_ALIGN(memory_start);
-	iommu = (struct iommu_struct *) memory_start;
-	memory_start += sizeof(struct iommu_struct);
+	iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
 	prom_getproperty(iommund, "reg", (void *) iommu_promregs,
 			 sizeof(iommu_promregs));
 	iommu->regs = (struct iommu_regs *)
@@ -98,16 +96,68 @@
 	ptsize = iommu->end - iommu->start + 1;
 	ptsize = (ptsize >> PAGE_SHIFT) * sizeof(iopte_t);
 
-	/* Stupid alignment constraints give me a headache. */
-	memory_start = PAGE_ALIGN(memory_start);
-	memory_start = (((memory_start) + (ptsize - 1)) & ~(ptsize - 1));
-	iommu->lowest = iommu->page_table = (iopte_t *) memory_start;
-	memory_start += ptsize;
+	/* Stupid alignment constraints give me a headache. 
+	   We want to get very large aligned memory area, larger than
+	   maximum what get_free_pages gives us (128K): we need
+	   256K or 512K or 1M or 2M aligned to its size. */
+	ia = (struct iommu_alloc *) kmalloc (sizeof(struct iommu_alloc) * 128, GFP_ATOMIC);
+	for (i = 0; i < 128; i++) {
+		ia[i].addr = 0;
+		ia[i].next = -1;
+	}
+	k = 0;
+	for (i = 0; i < 128; i++) {
+		ia[i].addr = __get_free_pages(GFP_DMA, 5);
+		if (ia[i].addr <= ia[k].addr) {
+			if (i) {
+				ia[i].next = k;
+				k = i;
+			}			
+		} else {
+			for (m = k, l = ia[k].next; l != -1; m = l, l = ia[l].next)
+				if (ia[i].addr <= ia[l].addr) {
+					ia[i].next = l;
+					ia[m].next = i;
+				}
+			if (l == -1)
+				ia[m].next = i;
+		}
+		for (m = -1, j = 0, l = k; l != -1; l = ia[l].next) {
+			if (!(ia[l].addr & (ptsize - 1))) {
+				tmp = ia[l].addr;
+				m = l;
+				j = 128 * 1024;
+			} else if (m != -1) {
+				if (ia[l].addr != tmp + j)
+					m = -1;
+				else {
+					j += 128 * 1024;
+					if (j == ptsize) {
+						break;
+					}
+				}
+			}
+		}
+		if (l != -1)
+			break;
+	}
+	if (i == 128) {
+		prom_printf("Could not allocate iopte of size 0x%08x\n", ptsize);
+		prom_halt();
+	}
+	for (l = m, j = 0; j < ptsize; j += 128 * 1024, l = ia[l].next)
+		ia[l].addr = 0;
+	for (l = k; l != -1; l = ia[l].next)
+		if (ia[l].addr)
+			free_pages(ia[l].addr, 5);
+	kfree (ia);
+	iommu->lowest = iommu->page_table = (iopte_t *)tmp;
+	
 
 	/* Initialize new table. */
 	flush_cache_all();
 	memset(iommu->page_table, 0, ptsize);
-	iommu_map_dvma_pages_for_iommu(iommu, memory_end);
+	iommu_map_dvma_pages_for_iommu(iommu);
 	if(viking_mxcc_present) {
 		unsigned long start = (unsigned long) iommu->page_table;
 		unsigned long end = (start + ptsize);
@@ -130,7 +180,6 @@
 	sbus->iommu = iommu;
 	printk("IOMMU: impl %d vers %d page table at %p of size %d bytes\n",
 	       impl, vers, iommu->page_table, ptsize);
-	return memory_start;
 }
 
 static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct linux_sbus *sbus)
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.1.100/linux/arch/sparc/mm/srmmu.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/mm/srmmu.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.170 1998/03/09 14:04:01 jj Exp $
+/* $Id: srmmu.c,v 1.171 1998/04/24 15:03:35 jj Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -512,7 +512,7 @@
 		pgd_cache_size--;
 	}
 	spin_unlock(&pgd_spinlock);
-	return (pte_t *)ret;
+	return (pgd_t *)ret;
 }
 
 static inline pgd_t *srmmu_get_pgd_slow(void)
diff -u --recursive --new-file v2.1.100/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.1.100/linux/arch/sparc/mm/sun4c.c	Sat May  2 14:19:52 1998
+++ linux/arch/sparc/mm/sun4c.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.163 1998/03/11 04:08:21 tdyas Exp $
+/* $Id: sun4c.c,v 1.164 1998/05/02 12:06:19 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.1.100/linux/arch/sparc64/Makefile	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/Makefile	Fri May  8 00:09:20 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.25 1998/04/06 16:10:31 jj Exp $
+# $Id: Makefile,v 1.26 1998/04/18 03:40:54 davem Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -56,6 +56,8 @@
 
 archclean:
 	rm -f $(TOPDIR)/vmlinux.aout
+
+archmrproper:
 
 archdep:
 
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.1.100/linux/arch/sparc64/config.in	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/config.in	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.44 1998/04/06 16:10:35 jj Exp $
+# $Id: config.in,v 1.46 1998/05/05 17:17:21 jj Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -46,6 +46,7 @@
 	define_bool CONFIG_SUN_IO y
 	define_bool CONFIG_PCI y
 	source drivers/sbus/char/Config.in
+	source drivers/sbus/audio/Config.in
 fi
 
 tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.100/linux/arch/sparc64/defconfig	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/defconfig	Fri May  8 00:11:28 1998
@@ -55,6 +55,13 @@
 CONFIG_OBP_FLASH=m
 # CONFIG_SUN_BPP is not set
 # CONFIG_SUN_VIDEOPIX is not set
+
+#
+# Linux/SPARC audio subsystem (EXPERIMENTAL)
+#
+# CONFIG_SPARCAUDIO is not set
+# CONFIG_SPARCAUDIO_AMD7930 is not set
+# CONFIG_SPARCAUDIO_CS4231 is not set
 CONFIG_SUN_OPENPROMFS=m
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
@@ -132,16 +139,14 @@
 #  
 #
 CONFIG_IPX=m
-
-#
-# IPX options
-#
 # CONFIG_IPX_INTERN is not set
+# CONFIG_SPX is not set
 CONFIG_ATALK=m
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
+# CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
@@ -149,11 +154,12 @@
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=y
 CONFIG_NET_SCH_CSZ=y
+CONFIG_NET_SCH_PRIO=y
 CONFIG_NET_SCH_RED=y
 CONFIG_NET_SCH_SFQ=y
+# CONFIG_NET_SCH_TEQL is not set
 CONFIG_NET_SCH_TBF=y
-CONFIG_NET_SCH_PFIFO=y
-CONFIG_NET_SCH_PRIO=y
+# CONFIG_NET_QOS is not set
 # CONFIG_NET_PROFILE is not set
 
 #
@@ -269,6 +275,7 @@
 CONFIG_SMD_DISKLABEL=y
 CONFIG_SOLARIS_X86_PARTITION=y
 # CONFIG_ADFS_FS is not set
+CONFIG_DEVPTS_FS=y
 # CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.1.100/linux/arch/sparc64/kernel/ebus.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/kernel/ebus.c	Fri May  8 00:11:28 1998
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.23 1998/03/29 16:27:24 ecd Exp $
+/* $Id: ebus.c,v 1.26 1998/04/21 06:34:02 ecd Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/malloc.h>
 #include <linux/string.h>
 
 #include <asm/system.h>
@@ -30,7 +31,7 @@
 
 extern void prom_ebus_ranges_init(struct linux_ebus *);
 extern void prom_ebus_intmap_init(struct linux_ebus *);
-extern unsigned long pci_console_init(unsigned long memory_start);
+extern void pci_console_init(void);
 
 #ifdef CONFIG_SUN_OPENPROMIO
 extern int openprom_init(void);
@@ -48,19 +49,9 @@
 extern int envctrl_init(void);
 #endif
 
-extern unsigned int psycho_irq_build(struct linux_pbm_info *pbm,
-				     unsigned int full_ino);
-
-static inline unsigned long
-ebus_alloc(unsigned long *memory_start, size_t size)
+static inline unsigned long ebus_alloc(size_t size)
 {
-	unsigned long mem;
-
-	*memory_start = (*memory_start + 7) & ~(7);
-	mem = *memory_start;
-	*memory_start += size;
-	memset((void *)mem, 0, size);
-	return mem;
+	return (unsigned long)kmalloc(size, GFP_ATOMIC);
 }
 
 __initfunc(void ebus_intmap_match(struct linux_ebus *ebus,
@@ -117,11 +108,27 @@
 	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
 	if ((len == -1) || (len == 0)) {
 		dev->num_irqs = 0;
+		/*
+		 * Oh, well, some PROMs don't export interrupts
+		 * property to children of EBus devices...
+		 *
+		 * Be smart about PS/2 keyboard and mouse.
+		 */
+		if (!strcmp(dev->parent->prom_name, "8042")) {
+			if (!strcmp(dev->prom_name, "kb_ps2")) {
+				dev->num_irqs = 1;
+				dev->irqs[0] = dev->parent->irqs[0];
+			} else {
+				dev->num_irqs = 1;
+				dev->irqs[0] = dev->parent->irqs[1];
+			}
+		}
 	} else {
 		dev->num_irqs = len / sizeof(irqs[0]);
 		for (i = 0; i < dev->num_irqs; i++) {
 			ebus_intmap_match(dev->bus, preg, &irqs[i]);
-			dev->irqs[i] = psycho_irq_build(dev->bus->parent, irqs[i]);
+			dev->irqs[i] = psycho_irq_build(dev->bus->parent,
+							dev->bus->self, irqs[i]);
 		}
 	}
 
@@ -139,9 +146,7 @@
 #endif
 }
 
-__initfunc(unsigned long fill_ebus_device(int node,
-					  struct linux_ebus_device *dev,
-					  unsigned long memory_start))
+__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
 {
 	struct linux_prom_registers regs[PROMREG_MAX];
 	struct linux_ebus_child *child;
@@ -176,7 +181,8 @@
 		dev->num_irqs = len / sizeof(irqs[0]);
 		for (i = 0; i < dev->num_irqs; i++) {
 			ebus_intmap_match(dev->bus, &regs[0], &irqs[i]);
-			dev->irqs[i] = psycho_irq_build(dev->bus->parent, irqs[i]);
+			dev->irqs[i] = psycho_irq_build(dev->bus->parent,
+							dev->bus->self, irqs[i]);
 		}
 	}
 
@@ -194,7 +200,7 @@
 #endif
 	if ((node = prom_getchild(node))) {
 		dev->children = (struct linux_ebus_child *)
-			ebus_alloc(&memory_start, sizeof(struct linux_ebus_child));
+			ebus_alloc(sizeof(struct linux_ebus_child));
 
 		child = dev->children;
 		child->next = 0;
@@ -204,7 +210,7 @@
 
 		while ((node = prom_getsibling(node))) {
 			child->next = (struct linux_ebus_child *)
-				ebus_alloc(&memory_start, sizeof(struct linux_ebus_child));
+				ebus_alloc(sizeof(struct linux_ebus_child));
 
 			child = child->next;
 			child->next = 0;
@@ -213,15 +219,12 @@
 			fill_ebus_child(node, &regs[0], child);
 		}
 	}
-
-	return memory_start;
 }
 
 extern void sun4u_start_timers(void);
 extern void clock_probe(void);
 
-__initfunc(unsigned long ebus_init(unsigned long memory_start,
-				   unsigned long memory_end))
+__initfunc(void ebus_init(void))
 {
 	struct linux_prom_pci_registers regs[PROMREG_MAX];
 	struct linux_pbm_info *pbm;
@@ -237,7 +240,7 @@
 	int num_ebus = 0;
 
 	if (!pci_present())
-		return memory_start;
+		return;
 
 	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
 	if (!pdev) {
@@ -245,14 +248,14 @@
 #ifdef PROM_DEBUG
 		dprintf("ebus: No EBus's found.\n");
 #endif
-		return memory_start;
+		return;
 	}
 
 	cookie = pdev->sysdata;
 	ebusnd = cookie->prom_node;
 
 	ebus_chain = ebus = (struct linux_ebus *)
-			ebus_alloc(&memory_start, sizeof(struct linux_ebus));
+			ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = 0;
 
 	while (ebusnd) {
@@ -323,24 +326,23 @@
 			goto next_ebus;
 
 		ebus->devices = (struct linux_ebus_device *)
-				ebus_alloc(&memory_start,
-					   sizeof(struct linux_ebus_device));
+				ebus_alloc(sizeof(struct linux_ebus_device));
 
 		dev = ebus->devices;
 		dev->next = 0;
 		dev->children = 0;
 		dev->bus = ebus;
-		memory_start = fill_ebus_device(nd, dev, memory_start);
+		fill_ebus_device(nd, dev);
 
 		while ((nd = prom_getsibling(nd))) {
 			dev->next = (struct linux_ebus_device *)
-				ebus_alloc(&memory_start, sizeof(struct linux_ebus_device));
+				ebus_alloc(sizeof(struct linux_ebus_device));
 
 			dev = dev->next;
 			dev->next = 0;
 			dev->children = 0;
 			dev->bus = ebus;
-			memory_start = fill_ebus_device(nd, dev, memory_start);
+			fill_ebus_device(nd, dev);
 		}
 
 	next_ebus:
@@ -353,13 +355,13 @@
 		ebusnd = cookie->prom_node;
 
 		ebus->next = (struct linux_ebus *)
-			ebus_alloc(&memory_start, sizeof(struct linux_ebus));
+			ebus_alloc(sizeof(struct linux_ebus));
 		ebus = ebus->next;
 		ebus->next = 0;
 		++num_ebus;
 	}
 
-	memory_start = pci_console_init(memory_start);
+	pci_console_init();
 
 #ifdef CONFIG_SUN_OPENPROMIO
 	openprom_init();
@@ -381,5 +383,4 @@
 #endif
 	sun4u_start_timers();
 	clock_probe();
-	return memory_start;
 }
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- v2.1.100/linux/arch/sparc64/kernel/entry.S	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/kernel/entry.S	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.76 1998/01/05 17:00:13 jj Exp $
+/* $Id: entry.S,v 1.78 1998/05/01 20:36:24 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -58,8 +58,7 @@
 	 mov		1, %o2
 	.align		32
 sparc64_dtlb_refbit_catch:
-	srlx		%g5, 9, %g4
-	and		%g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+	and		%g5, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
 	cmp		%g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
 	be,a,pt		%xcc, 2f
 	 mov		1, %g4
@@ -85,8 +84,7 @@
 	 clr		%l6
 	.align		32
 sparc64_itlb_refbit_catch:
-	srlx		%g5, 9, %g4
-	and		%g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
+	and		%g5, ((_PAGE_PRESENT | _PAGE_READ) >> 9), %g4
 	cmp		%g4, ((_PAGE_PRESENT | _PAGE_READ) >> 9)
 	be,a,pt		%xcc, 3f
 	 mov		1, %g4
@@ -666,7 +664,7 @@
 		ba,pt		%xcc, rtrap
 		 clr		%l6
 
-	/* This is how fork() was meant to be done, 12 instruction entry.
+	/* This is how fork() was meant to be done, 8 instruction entry.
 	 *
 	 * I questioned the following code briefly, let me clear things
 	 * up so you must not reason on it like I did.
@@ -695,7 +693,8 @@
 sys_fork:
 sys_vfork:	mov		SIGCHLD, %o0
 		clr		%o1
-sys_clone:	mov		%o7, %l5
+sys_clone:	flushw
+		mov		%o7, %l5
 		add		%sp, STACK_BIAS + REGWIN_SZ, %o2
 		movrz		%o1, %fp, %o1
 		call		do_fork
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.1.100/linux/arch/sparc64/kernel/ioctl32.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/kernel/ioctl32.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.35 1998/04/10 02:01:46 davem Exp $
+/* $Id: ioctl32.c,v 1.37 1998/05/06 05:34:13 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -28,6 +28,8 @@
 #include <linux/if_ppp.h>
 #include <linux/mtio.h>
 #include <linux/cdrom.h>
+#include <linux/loop.h>
+#include <linux/auto_fs.h>
 
 #include <scsi/scsi.h>
 /* Ugly hack. */
@@ -66,6 +68,22 @@
 	return err;
 }
  
+static int rw_long(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	if(get_user(val, (u32 *)A(arg)))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 *)A(arg)))
+		return -EFAULT;
+	return err;
+}
+ 
 struct timeval32 {
 	int tv_sec;
 	int tv_usec;
@@ -1059,6 +1077,57 @@
 	return 0;
 }
 
+struct loop_info32 {
+	int			lo_number;      /* ioctl r/o */
+	__kernel_dev_t32	lo_device;      /* ioctl r/o */
+	unsigned int		lo_inode;       /* ioctl r/o */
+	__kernel_dev_t32	lo_rdevice;     /* ioctl r/o */
+	int			lo_offset;
+	int			lo_encrypt_type;
+	int			lo_encrypt_key_size;    /* ioctl w/o */
+	int			lo_flags;       /* ioctl r/o */
+	char			lo_name[LO_NAME_SIZE];
+	unsigned char		lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+	unsigned int		lo_init[2];
+	char			reserved[4];
+};
+
+static int loop_status(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct loop_info l;
+	int err = 0;
+
+	switch(cmd) {
+	case LOOP_SET_STATUS:
+		if ((get_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) ||
+		     __get_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) ||
+		     __get_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) ||
+		     __get_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) ||
+		     __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)A(arg))->lo_offset,
+					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset)))
+			return -EFAULT;
+		set_fs (KERNEL_DS);
+		err = sys_ioctl (fd, cmd, (unsigned long)&l);
+		set_fs (old_fs);
+		break;
+	case LOOP_GET_STATUS:
+		set_fs (KERNEL_DS);
+		err = sys_ioctl (fd, cmd, (unsigned long)&l);
+		set_fs (old_fs);
+		if (!err && 
+		    (put_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) ||
+		     __put_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) ||
+		     __put_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) ||
+		     __put_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) ||
+		     __copy_to_user((char *)&((struct loop_info32 *)A(arg))->lo_offset,
+					   (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset)))
+			err = -EFAULT;
+		break;
+	}
+	return err;
+}
+
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
 {
 	struct file * filp;
@@ -1185,6 +1254,15 @@
 	case CDROMREADALL:
 		error = cdrom_ioctl_trans(fd, cmd, arg);
 		goto out;
+		
+	case LOOP_SET_STATUS:
+	case LOOP_GET_STATUS:
+		error = loop_status(fd, cmd, arg);
+		goto out;
+
+	case AUTOFS_IOC_SETTIMEOUT:
+		error = rw_long(fd, cmd, arg);
+		goto out;
 
 	/* List here exlicitly which ioctl's are known to have
 	 * compatable types passed or none at all...
@@ -1455,6 +1533,17 @@
 	case CDROM_DRIVE_STATUS:
 	case CDROM_DISC_STATUS:
 	case CDROM_CHANGER_NSLOTS:
+	
+	/* Big L */
+	case LOOP_SET_FD:
+	case LOOP_CLR_FD:
+
+	/* AUTOFS */
+	case AUTOFS_IOC_READY:
+	case AUTOFS_IOC_FAIL:
+	case AUTOFS_IOC_CATATONIC:
+	case AUTOFS_IOC_PROTOVER:
+	case AUTOFS_IOC_EXPIRE:
 
 		error = sys_ioctl (fd, cmd, (unsigned long)arg);
 		goto out;
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.1.100/linux/arch/sparc64/kernel/irq.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/kernel/irq.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.52 1998/03/19 00:22:54 ecd Exp $
+/* $Id: irq.c,v 1.53 1998/04/20 07:14:58 ecd Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -36,6 +36,7 @@
 
 /* Internal flag, should not be visible elsewhere at all. */
 #define SA_IMAP_MASKED		0x100
+#define SA_DMA_SYNC		0x200
 
 #ifdef __SMP__
 void distribute_irqs(void);
@@ -543,6 +544,8 @@
 #ifdef CONFIG_PCI
 		if(PCI_IRQ_P(irq)) {
 			pci_irq_frobnicate(&cpu_irq, &ivindex_fixup, &imap, &iclr, irq);
+			if (irq & PCI_IRQ_DMA_SYNC)
+				irqflags |= SA_DMA_SYNC;
 		} else
 #endif
 		if(irqflags & SA_DCOOKIE) {
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.1.100/linux/arch/sparc64/kernel/process.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/kernel/process.c	Fri May  8 00:11:29 1998
@@ -1,9 +1,9 @@
-/*  $Id: process.c,v 1.52 1998/03/29 12:57:53 ecd Exp $
+/*  $Id: process.c,v 1.54 1998/04/28 08:23:28 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
- *  Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
- *  Copyright (C) 1997, 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *  Copyright (C) 1996       Eddie C. Dost   (ecd@skynet.be)
+ *  Copyright (C) 1997, 1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
  */
 
 /*
@@ -43,6 +43,45 @@
 
 #ifndef __SMP__
 
+extern int pgt_cache_water[2];
+
+static inline void ultra_check_pgt_cache(void)
+{
+        struct page *page, *page2;
+
+        if(pgtable_cache_size > pgt_cache_water[0]) {
+                do {
+                        if(pmd_quicklist)
+                                free_pmd_slow(get_pmd_fast());
+                        if(pte_quicklist)
+                                free_pte_slow(get_pte_fast());
+                } while(pgtable_cache_size > pgt_cache_water[1]);
+        }
+        if (pgd_cache_size > pgt_cache_water[0] / 4) {
+                for (page2 = NULL, page = (struct page *)pgd_quicklist; page;) {
+                        if ((unsigned long)page->pprev_hash == 3) {
+                                if (page2)
+                                        page2->next_hash = page->next_hash;
+                                else
+                                        (struct page *)pgd_quicklist = page->next_hash;
+                                page->next_hash = NULL;
+                                page->pprev_hash = NULL;
+                                pgd_cache_size -= 2;
+                                free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+                                if (page2)
+                                        page = page2->next_hash;
+                                else
+                                        page = (struct page *)pgd_quicklist;
+                                if (pgd_cache_size <= pgt_cache_water[1] / 4)
+                                        break;
+                                continue;
+                        }
+                        page2 = page;
+                        page = page->next_hash;
+                }
+        }
+}
+
 /*
  * the idle loop on a Sparc... ;)
  */
@@ -55,7 +94,7 @@
 	current->priority = -100;
 	current->counter = -100;
 	for (;;) {
-		check_pgt_cache();
+		ultra_check_pgt_cache();
 		run_task_queue(&tq_scheduler);
 		schedule();
 	}
@@ -422,7 +461,7 @@
 		get_mmu_context(current);
 		spin_unlock(&scheduler_lock);
 	}
-	current->tss.ctx = current->mm->context & 0x1fff;
+	current->tss.ctx = current->mm->context & 0x3ff;
 	spitfire_set_secondary_context (current->tss.ctx);
 	__asm__ __volatile__("flush %g6");
 }
@@ -584,7 +623,7 @@
 		p->tss.kregs->u_regs[UREG_FP] = sp;
 		p->tss.flags &= ~SPARC_FLAG_KTHREAD;
 		p->tss.current_ds = USER_DS;
-		p->tss.ctx = (p->mm->context & 0x1fff);
+		p->tss.ctx = (p->mm->context & 0x3ff);
 		if (sp != regs->u_regs[UREG_FP]) {
 			unsigned long csp;
 
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c
--- v2.1.100/linux/arch/sparc64/kernel/psycho.c	Thu May  7 22:51:47 1998
+++ linux/arch/sparc64/kernel/psycho.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.50 1998/04/10 12:29:47 ecd Exp $
+/* $Id: psycho.c,v 1.54 1998/05/01 19:16:32 ecd Exp $
  * psycho.c: Ultra/AX U2P PCI controller support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -9,6 +9,8 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
 
 #include <asm/ebus.h>
 #include <asm/sbus.h> /* for sanity check... */
@@ -17,6 +19,7 @@
 #undef FIXUP_REGS_DEBUG
 #undef FIXUP_IRQ_DEBUG
 #undef FIXUP_VMA_DEBUG
+#undef PCI_COOKIE_DEBUG
 
 #ifdef PROM_DEBUG
 #define dprintf	prom_printf
@@ -94,19 +97,12 @@
  */
 static int pci_probe_enable = 0;
 
-static inline unsigned long long_align(unsigned long addr)
+__initfunc(static void psycho_iommu_init(struct linux_psycho *psycho, int tsbsize))
 {
-	return ((addr + (sizeof(unsigned long) - 1)) &
-		~(sizeof(unsigned long) - 1));
-}
-
-__initfunc(static unsigned long psycho_iommu_init(struct linux_psycho *psycho,
-						  int tsbsize,
-						  unsigned long memory_start))
-{
-	unsigned long tsbbase = PAGE_ALIGN(memory_start);
+	unsigned long tsbbase;
 	unsigned long control, i;
 	unsigned long *iopte;
+	unsigned long order;
 
 	/*
 	 * Invalidate TLB Entries.
@@ -120,9 +116,12 @@
 	control &= ~(IOMMU_CTRL_DENAB);
 	psycho->psycho_regs->iommu_control = control;
 
-	memory_start = (tsbbase + ((tsbsize * 1024) * 8));
+	for(order = 0;; order++) {
+		if((PAGE_SIZE << order) >= ((tsbsize * 1024) * 8))
+			break;
+	}
+	tsbbase = __get_free_pages(GFP_DMA, order);
 	iopte = (unsigned long *)tsbbase;
-
 	for(i = 0; i < (tsbsize * 1024); i++) {
 		*iopte = (IOPTE_VALID | IOPTE_64K |
 			  IOPTE_CACHE | IOPTE_WRITE);
@@ -154,8 +153,6 @@
 		break;
 	}
 	psycho->psycho_regs->iommu_control = control;
-
-	return memory_start;
 }
 
 extern void prom_pbm_ranges_init(int node, struct linux_pbm_info *pbm);
@@ -164,7 +161,7 @@
 /*
  * Poor man's PCI...
  */
-__initfunc(unsigned long sabre_init(int pnode, unsigned long memory_start))
+__initfunc(void sabre_init(int pnode))
 {
 	struct linux_prom64_registers pr_regs[2];
 	struct linux_psycho *sabre;
@@ -175,8 +172,7 @@
 	u32 portid;
 	int bus;
 
-	sabre = (struct linux_psycho *)memory_start;
-	memory_start = long_align(memory_start + sizeof(struct linux_psycho));
+	sabre = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
 
 	portid = prom_getintdefault(pnode, "upa-portid", 0xff);
 
@@ -262,7 +258,7 @@
 			prom_halt();
 	}
 
-	memory_start = psycho_iommu_init(sabre, tsbsize, memory_start);
+	psycho_iommu_init(sabre, tsbsize);
 	pci_dvma_offset = vdma[0];
 
 	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
@@ -338,11 +334,15 @@
 		if (!node)
 			break;
 	}
+}
 
-	return memory_start;
+static __inline__ int
+apb_present(struct linux_psycho *psycho)
+{
+	return psycho->pci_bus ? 1 : 0;
 }
 
-__initfunc(unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void pcibios_init(void))
 {
 	struct linux_prom64_registers pr_regs[3];
 	struct linux_psycho *psycho;
@@ -355,7 +355,6 @@
 	dprintf("PCI: Probing for controllers.\n");
 #endif
 
-	memory_start = long_align(memory_start);
 	node = prom_getchild(prom_root_node);
 	while((node = prom_searchsiblings(node, "pci")) != 0) {
 		struct linux_psycho *search;
@@ -365,11 +364,11 @@
 
 		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
 		if ((err > 0) && !strncmp(namebuf, "SUNW,sabre", err)) {
-			memory_start = sabre_init(node, memory_start);
+			sabre_init(node);
 			goto next_pci;
 		}
 
-		psycho = (struct linux_psycho *)memory_start;
+		psycho = kmalloc(sizeof(struct linux_psycho), GFP_ATOMIC);
 
 		portid = prom_getintdefault(node, "upa-portid", 0xff);
 		for(search = psycho_root; search; search = search->next) {
@@ -385,9 +384,6 @@
 			}
 		}
 
-		memory_start = long_align(memory_start +
-					  sizeof(struct linux_psycho));
-
 		memset(psycho, 0, sizeof(*psycho));
 
 		psycho->next = psycho_root;
@@ -452,7 +448,7 @@
 			psycho->pci_config_space);
 #endif
 
-		memory_start = psycho_iommu_init(psycho, 32, memory_start);
+		psycho_iommu_init(psycho, 32);
 		pci_dvma_offset = 0x80000000UL;
 
 		is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
@@ -504,14 +500,11 @@
 		prom_halt();
 	}
 
-	psycho_index_map = (struct linux_psycho **)long_align(memory_start);
-	memory_start = long_align(memory_start + linux_num_psycho
-					       * sizeof(struct linux_psycho *));
+	psycho_index_map = kmalloc(sizeof(struct linux_psycho *) * linux_num_psycho,
+				   GFP_ATOMIC);
 
 	for (psycho = psycho_root; psycho; psycho = psycho->next)
 		psycho_index_map[psycho->index] = psycho;
-
-	return memory_start;
 }
 
 int pcibios_present(void)
@@ -577,40 +570,14 @@
 	}
 }
 
-static unsigned long *pci_alloc_arena = NULL;
-
-static inline void pci_init_alloc_init(unsigned long *mstart)
-{
-	pci_alloc_arena = mstart;
-}
-
-static inline void pci_init_alloc_fini(void)
-{
-	pci_alloc_arena = NULL;
-}
-
-__initfunc(static void *pci_init_alloc(int size))
-{
-	unsigned long start = long_align(*pci_alloc_arena);
-	void *mp = (void *)start;
-
-	if(!pci_alloc_arena) {
-		prom_printf("pci_init_alloc: pci_vma arena not init'd\n");
-		prom_halt();
-	}
-	start += size;
-	*pci_alloc_arena = start;
-	return mp;
-}
-
 static inline struct pci_vma *pci_vma_alloc(void)
 {
-	return pci_init_alloc(sizeof(struct pci_vma));
+	return kmalloc(sizeof(struct pci_vma), GFP_ATOMIC);
 }
 
 static inline struct pcidev_cookie *pci_devcookie_alloc(void)
 {
-	return pci_init_alloc(sizeof(struct pcidev_cookie));
+	return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
 }
 
 
@@ -694,6 +661,14 @@
 	unsigned short stmp;
 	unsigned int itmp;
 
+	for(pdev = pci_devices; pdev; pdev = pdev->next) {
+		if(pdev->vendor == PCI_VENDOR_ID_SUN &&
+		   pdev->device == PCI_DEVICE_ID_SUN_SABRE) {
+			/* Increase latency timer on top level bridge. */
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8);
+			break;
+		}
+	}
 	for (pdev = sabre->pci_bus->devices; pdev; pdev = pdev->sibling) {
 		if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 		    pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
@@ -732,12 +707,14 @@
 			pci_write_config_byte(pdev, APB_PIO_TARGET_LATENCY_TIMER, 0);
 			pci_write_config_byte(pdev, APB_DMA_TARGET_RETRY_LIMIT, 0x80);
 			pci_write_config_byte(pdev, APB_DMA_TARGET_LATENCY_TIMER, 0);
+
+			/* Increase primary latency timer. */
+			pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xf8);
 		}
 	}
 }
 
-__initfunc(static void sabre_probe(struct linux_psycho *sabre,
-				   unsigned long *mstart))
+__initfunc(static void sabre_probe(struct linux_psycho *sabre))
 {
 	struct pci_bus *pbus = sabre->pci_bus;
 	static unsigned char busno = 0;
@@ -745,7 +722,7 @@
 	pbus->number = pbus->secondary = busno;
 	pbus->sysdata = sabre;
 
-	pbus->subordinate = pci_scan_bus(pbus, mstart);
+	pbus->subordinate = pci_scan_bus(pbus);
 	busno = pbus->subordinate + 1;
 
 	for(pbus = pbus->children; pbus; pbus = pbus->next) {
@@ -759,8 +736,7 @@
 }
 
 
-__initfunc(static void pbm_probe(struct linux_pbm_info *pbm,
-				 unsigned long *mstart))
+__initfunc(static void pbm_probe(struct linux_pbm_info *pbm))
 {
 	static struct pci_bus *pchain = NULL;
 	struct pci_bus *pbus = &pbm->pci_bus;
@@ -777,7 +753,7 @@
 
 	pbm_fixup_busno(pbm, busno);
 
-	pbus->subordinate = pci_scan_bus(pbus, mstart);
+	pbus->subordinate = pci_scan_bus(pbus);
 
 	/*
 	 * Set the maximum subordinate bus of this pbm.
@@ -842,6 +818,10 @@
 	pcp->pbm = pbm;
 	pcp->prom_node = node;
 	pdev->sysdata = pcp;
+#ifdef PCI_COOKIE_DEBUG
+	dprintf("pdev_cookie_fillin: pdev [%02x.%02x]: pbm %p, node %x\n",
+		pdev->bus->number, pdev->devfn, pbm, node);
+#endif
 }
 
 __initfunc(static void fill_in_pbm_cookies(struct pci_bus *pbus,
@@ -851,6 +831,11 @@
 
 	pbus->sysdata = pbm;
 
+#ifdef PCI_COOKIE_DEBUG
+	dprintf("fill_in_pbm_cookies: pbus [%02x]: pbm %p\n",
+		pbus->number, pbm);
+#endif
+
 	for(pdev = pbus->devices; pdev; pdev = pdev->sibling)
 		pdev_cookie_fillin(pbm, pdev);
 
@@ -973,7 +958,7 @@
 {
 	struct pci_vma *vp;
 
-	if (pbm->parent->pci_bus) {
+	if (apb_present(pbm->parent)) {
 		/*
 		 * Disallow anything that is not in our IO/MEM map on SIMBA.
 		 */
@@ -984,12 +969,8 @@
 
 		for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
 			struct pcidev_cookie *pcp = pdev->sysdata;
-			if (!pcp) {
-				prom_printf("record_assignments: "
-					"no pcidev_cookie for pdev %02x\n",
-					pdev->devfn);
-				prom_halt();
-			}
+			if (!pcp)
+				continue;
 			if (pcp->pbm == pbm)
 				break;
 		}
@@ -1448,9 +1429,12 @@
 }
 
 /* Exported for EBUS probing layer. */
-__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm, unsigned int full_ino))
+__initfunc(unsigned int psycho_irq_build(struct linux_pbm_info *pbm,
+					 struct pci_dev *pdev,
+					 unsigned int full_ino))
 {
 	unsigned long imap_off, ign, ino;
+	int need_dma_sync = 0;
 
 	ign = (full_ino & PSYCHO_IMAP_IGN) >> 6;
 	ino = (full_ino & PSYCHO_IMAP_INO);
@@ -1540,7 +1524,11 @@
 	}
 	imap_off -= imap_offset(imap_a_slot0);
 
-	return pci_irq_encode(imap_off, pbm->parent->index, ign, ino);
+	if (apb_present(pbm->parent) && (pdev->bus->number != pbm->pci_first_busno)) {
+		need_dma_sync = 1;
+	}
+
+	return pci_irq_encode(imap_off, pbm->parent->index, ign, ino, need_dma_sync);
 }
 
 __initfunc(static int pbm_intmap_match(struct linux_pbm_info *pbm,
@@ -1618,7 +1606,7 @@
 
 	/* See if we find a matching interrupt-map entry. */
 	if (pbm_intmap_match(pbm, pdev, preg, &prom_irq)) {
-		pdev->irq = psycho_irq_build(pbm,
+		pdev->irq = psycho_irq_build(pbm, pdev,
 					     (pbm->parent->upa_portid << 6)
 					     | prom_irq);
 #ifdef FIXUP_IRQ_DEBUG
@@ -1627,14 +1615,14 @@
 #endif
 	/* See if fully specified already (ie. for onboard devices like hme) */
 	} else if(((prom_irq & PSYCHO_IMAP_IGN) >> 6) == pbm->parent->upa_portid) {
-		pdev->irq = psycho_irq_build(pbm, prom_irq);
+		pdev->irq = psycho_irq_build(pbm, pdev, prom_irq);
 #ifdef FIXUP_IRQ_DEBUG
 		dprintf("fully specified prom_irq[%x] pdev->irq[%x]",
 		        prom_irq, pdev->irq);
 #endif
 	/* See if onboard device interrupt (i.e. bit 5 set) */
 	} else if((prom_irq & PSYCHO_IMAP_INO) & 0x20) {
-		pdev->irq = psycho_irq_build(pbm,
+		pdev->irq = psycho_irq_build(pbm, pdev,
 					     (pbm->parent->upa_portid << 6)
 					     | prom_irq);
 #ifdef FIXUP_IRQ_DEBUG
@@ -1669,7 +1657,7 @@
 		}
 		slot = (slot << 2);
 
-		pdev->irq = psycho_irq_build(pbm,
+		pdev->irq = psycho_irq_build(pbm, pdev,
 					     (((portid << 6) & PSYCHO_IMAP_IGN)
 					     | (bus | slot | line)));
 
@@ -1818,7 +1806,7 @@
 		fixup_addr_irq(&psycho->pbm_B);
 }
 
-__initfunc(unsigned long pcibios_fixup(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void pcibios_fixup(void))
 {
 	struct linux_psycho *psycho;
 
@@ -1838,26 +1826,24 @@
 
 	for (psycho = psycho_root; psycho; psycho = psycho->next) {
 		/* Probe bus on builtin PCI. */
-		if (psycho->pci_bus)
-			sabre_probe(psycho, &memory_start);
+		if (apb_present(psycho))
+			sabre_probe(psycho);
 		else {
 			/* Probe busses under PBM B. */
-			pbm_probe(&psycho->pbm_B, &memory_start);
+			pbm_probe(&psycho->pbm_B);
 
 			/* Probe busses under PBM A. */
-			pbm_probe(&psycho->pbm_A, &memory_start);
+			pbm_probe(&psycho->pbm_A);
 		}
 	}
 
-	pci_init_alloc_init(&memory_start);
-
 	/* Walk all PCI devices found.  For each device, and
 	 * PCI bridge which is not one of the PSYCHO PBM's, fill in the
 	 * sysdata with a pointer to the PBM (for pci_bus's) or
 	 * a pci_dev cookie (PBM+PROM_NODE, for pci_dev's).
 	 */
 	for (psycho = psycho_root; psycho; psycho = psycho->next) {
-		if (psycho->pci_bus)
+		if (apb_present(psycho))
 			sabre_cookie_fillin(psycho);
 
 		fill_in_pbm_cookies(&psycho->pbm_A.pci_bus,
@@ -1873,9 +1859,7 @@
 		psycho_final_fixup(psycho);
 	}
 
-	pci_init_alloc_fini();
-
-	return ebus_init(memory_start, memory_end);
+	return ebus_init();
 }
 
 /* "PCI: The emerging standard..." 8-( */
@@ -2257,7 +2241,7 @@
 {
 	struct linux_pbm_info *pbm = bus2pbm[bus];
 
-	if (pbm && pbm->parent && pbm->parent->pci_bus)
+	if (pbm && pbm->parent && apb_present(pbm->parent))
 		return sabre_read_config_byte(pbm, bus, devfn, where, value);
 	return pbm_read_config_byte(pbm, bus, devfn, where, value);
 }
@@ -2267,7 +2251,7 @@
 {
 	struct linux_pbm_info *pbm = bus2pbm[bus];
 
-	if (pbm && pbm->parent && pbm->parent->pci_bus)
+	if (pbm && pbm->parent && apb_present(pbm->parent))
 		return sabre_read_config_word(pbm, bus, devfn, where, value);
 	return pbm_read_config_word(pbm, bus, devfn, where, value);
 }
@@ -2277,7 +2261,7 @@
 {
 	struct linux_pbm_info *pbm = bus2pbm[bus];
 
-	if (pbm && pbm->parent && pbm->parent->pci_bus)
+	if (pbm && pbm->parent && apb_present(pbm->parent))
 		return sabre_read_config_dword(pbm, bus, devfn, where, value);
 	return pbm_read_config_dword(pbm, bus, devfn, where, value);
 }
@@ -2287,7 +2271,7 @@
 {
 	struct linux_pbm_info *pbm = bus2pbm[bus];
 
-	if (pbm && pbm->parent && pbm->parent->pci_bus)
+	if (pbm && pbm->parent && apb_present(pbm->parent))
 		return sabre_write_config_byte(pbm, bus, devfn, where, value);
 	return pbm_write_config_byte(pbm, bus, devfn, where, value);
 }
@@ -2297,7 +2281,7 @@
 {
 	struct linux_pbm_info *pbm = bus2pbm[bus];
 
-	if (pbm && pbm->parent && pbm->parent->pci_bus)
+	if (pbm && pbm->parent && apb_present(pbm->parent))
 		return sabre_write_config_word(pbm, bus, devfn, where, value);
 	return pbm_write_config_word(bus2pbm[bus], bus, devfn, where, value);
 }
@@ -2307,7 +2291,7 @@
 {
 	struct linux_pbm_info *pbm = bus2pbm[bus];
 
-	if (pbm && pbm->parent && pbm->parent->pci_bus)
+	if (pbm && pbm->parent && apb_present(pbm->parent))
 		return sabre_write_config_dword(pbm, bus, devfn, where, value);
 	return pbm_write_config_dword(bus2pbm[bus], bus, devfn, where, value);
 }
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- v2.1.100/linux/arch/sparc64/kernel/ptrace.c	Thu May  7 22:51:47 1998
+++ linux/arch/sparc64/kernel/ptrace.c	Fri May  8 00:11:29 1998
@@ -19,6 +19,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
+#include <asm/asi.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -72,6 +73,41 @@
 	return pgtable;
 }
 
+/* We must bypass the L1-cache to avoid alias issues.  -DaveM */
+static __inline__ unsigned long read_user_long(unsigned long kvaddr)
+{
+	unsigned long ret;
+
+	__asm__ __volatile__("ldxa [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
+	return ret;
+}
+
+static __inline__ unsigned int read_user_int(unsigned long kvaddr)
+{
+	unsigned int ret;
+
+	__asm__ __volatile__("lduwa [%1] %2, %0"
+			     : "=r" (ret)
+			     : "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
+	return ret;
+}
+
+static __inline__ void write_user_long(unsigned long kvaddr, unsigned long val)
+{
+	__asm__ __volatile__("stxa %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
+}
+
+static __inline__ void write_user_int(unsigned long kvaddr, unsigned int val)
+{
+	__asm__ __volatile__("stwa %0, [%1] %2"
+			     : /* no outputs */
+			     : "r" (val), "r" (__pa(kvaddr)), "i" (ASI_PHYS_USE_EC));
+}
+
 static inline unsigned long get_long(struct task_struct * tsk,
 	struct vm_area_struct * vma, unsigned long addr)
 {
@@ -84,7 +120,7 @@
 	if (MAP_NR(page) >= max_mapnr)
 		return 0;
 	page += addr & ~PAGE_MASK;
-	retval = *(unsigned long *) page;
+	retval = read_user_long(page);
 	flush_page_to_ram(page);
 	return retval;
 }
@@ -103,14 +139,12 @@
 		unsigned long pgaddr;
 
 		pgaddr = page + (addr & ~PAGE_MASK);
-		*(unsigned long *) (pgaddr) = data;
+		write_user_long(pgaddr, data);
 
 		__asm__ __volatile__("
 		membar	#StoreStore
 		flush	%0
 "		: : "r" (pgaddr & ~7) : "memory");
-
-		flush_page_to_ram(page);
 	}
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
@@ -131,7 +165,7 @@
 	if (MAP_NR(page) >= max_mapnr)
 		return 0;
 	page += addr & ~PAGE_MASK;
-	retval = *(unsigned int *) page;
+	retval = read_user_int(page);
 	flush_page_to_ram(page);
 	return retval;
 }
@@ -150,14 +184,12 @@
 		unsigned long pgaddr;
 
 		pgaddr = page + (addr & ~PAGE_MASK);
-		*(unsigned int *) (pgaddr) = data;
+		write_user_int(pgaddr, data);
 
 		__asm__ __volatile__("
 		membar	#StoreStore
 		flush	%0
 "		: : "r" (pgaddr & ~7) : "memory");
-
-		flush_page_to_ram(page);
 	}
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
@@ -890,7 +922,7 @@
 			vma = find_extend_vma(child, src);
 			if (!vma) {
 				pt_error_return(regs, EIO);
-				goto out;
+				goto flush_and_out;
 			}
 			pgtable = get_page (child, vma, src, 0);
 			if (src & ~PAGE_MASK) {
@@ -904,13 +936,13 @@
 				if (copy_to_user (dest, ((char *)page) + (src & ~PAGE_MASK), curlen)) {
 					flush_page_to_ram(page);
 					pt_error_return(regs, EFAULT);
-					goto out;
+					goto flush_and_out;
 				}
 				flush_page_to_ram(page);
 			} else {
 				if (clear_user (dest, curlen)) {
 					pt_error_return(regs, EFAULT);
-					goto out;
+					goto flush_and_out;
 				}
 			}
 			src += curlen;
@@ -918,7 +950,7 @@
 			len -= curlen;
 		}
 		pt_succ_return(regs, 0);
-		goto out;
+		goto flush_and_out;
 	}
 
 	case PTRACE_WRITETEXT:
@@ -934,7 +966,7 @@
 			vma = find_extend_vma(child, dest);
 			if (!vma) {
 				pt_error_return(regs, EIO);
-				goto out;
+				goto flush_and_out;
 			}
 			pgtable = get_page (child, vma, dest, 1);
 			if (dest & ~PAGE_MASK) {
@@ -951,7 +983,7 @@
 					set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 					flush_tlb_page(vma, dest);
 					pt_error_return(regs, EFAULT);
-					goto out;
+					goto flush_and_out;
 				}
 				flush_page_to_ram(page);
 				set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -962,7 +994,7 @@
 			len -= curlen;
 		}
 		pt_succ_return(regs, 0);
-		goto out;
+		goto flush_and_out;
 	}
 
 	case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
@@ -1040,6 +1072,12 @@
 	default:
 		pt_error_return(regs, EIO);
 		goto out;
+	}
+flush_and_out:
+	{
+		unsigned long va;
+		for(va =  0; va < (PAGE_SIZE << 1); va += 32)
+			spitfire_put_dcache_tag(va, 0x0);
 	}
 out:
 	unlock_kernel();
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.1.100/linux/arch/sparc64/kernel/smp.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/kernel/smp.c	Fri May  8 00:11:29 1998
@@ -85,7 +85,6 @@
 {
 	cpu_data[id].udelay_val			= loops_per_sec;
 	cpu_data[id].irq_count			= 0;
-	cpu_data[id].last_tlbversion_seen	= tlb_context_cache & CTX_VERSION_MASK;
 	cpu_data[id].pgcache_size		= 0;
 	cpu_data[id].pgd_cache			= NULL;
 	cpu_data[id].pmd_cache			= NULL;
@@ -368,16 +367,28 @@
 	__flush_tlb_all();
 }
 
+/* We know that the window frames of the user have been flushed
+ * to the stack before we get here because all callers of us
+ * are flush_tlb_*() routines, and these run after flush_cache_*()
+ * which performs the flushw.
+ */
 static void smp_cross_call_avoidance(struct mm_struct *mm)
 {
+	u32 ctx;
+
 	spin_lock(&scheduler_lock);
-	get_new_mmu_context(mm, &tlb_context_cache);
+	get_new_mmu_context(mm);
 	mm->cpu_vm_mask = (1UL << smp_processor_id());
-	if(segment_eq(current->tss.current_ds,USER_DS)) {
-		u32 ctx = mm->context & 0x1fff;
-
-		current->tss.ctx = ctx;
-		spitfire_set_secondary_context(ctx);
+	current->tss.ctx = ctx = mm->context & 0x3ff;
+	spitfire_set_secondary_context(ctx);
+	__asm__ __volatile__("flush %g6");
+	spitfire_flush_dtlb_secondary_context();
+	spitfire_flush_itlb_secondary_context();
+	__asm__ __volatile__("flush %g6");
+	if(!segment_eq(current->tss.current_ds,USER_DS)) {
+		/* Rarely happens. */
+		current->tss.ctx = 0;
+		spitfire_set_secondary_context(0);
 		__asm__ __volatile__("flush %g6");
 	}
 	spin_unlock(&scheduler_lock);
@@ -385,7 +396,7 @@
 
 void smp_flush_tlb_mm(struct mm_struct *mm)
 {
-	u32 ctx = mm->context & 0x1fff;
+	u32 ctx = mm->context & 0x3ff;
 
 	if(mm == current->mm && mm->count == 1) {
 		if(mm->cpu_vm_mask == (1UL << smp_processor_id()))
@@ -401,7 +412,7 @@
 void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
 			 unsigned long end)
 {
-	u32 ctx = mm->context & 0x1fff;
+	u32 ctx = mm->context & 0x3ff;
 
 	if(mm == current->mm && mm->count == 1) {
 		if(mm->cpu_vm_mask == (1UL << smp_processor_id()))
@@ -416,7 +427,7 @@
 
 void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page)
 {
-	u32 ctx = mm->context & 0x1fff;
+	u32 ctx = mm->context & 0x3ff;
 
 	if(mm == current->mm && mm->count == 1) {
 		if(mm->cpu_vm_mask == (1UL << smp_processor_id()))
@@ -424,7 +435,7 @@
 		return smp_cross_call_avoidance(mm);
 	}
 #if 0 /* XXX Disabled until further notice... */
-	else if(mm != current->mm && mm->count == 1) {
+	else if(mm->count == 1) {
 		/* Try to handle two special cases to avoid cross calls
 		 * in common scenerios where we are swapping process
 		 * pages out.
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.1.100/linux/arch/sparc64/kernel/sparc64_ksyms.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.33 1998/04/06 16:09:40 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.36 1998/04/16 07:07:19 ecd Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -113,10 +113,10 @@
 #else
 EXPORT_SYMBOL(local_irq_count);
 #endif
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL_PRIVATE(_lock_kernel);
 EXPORT_SYMBOL_PRIVATE(_unlock_kernel);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
 
 EXPORT_SYMBOL_PRIVATE(flushw_user);
 
@@ -140,6 +140,12 @@
 EXPORT_SYMBOL(pci_dvma_offset);
 EXPORT_SYMBOL(pci_dvma_mask);
 EXPORT_SYMBOL(empty_zero_page);
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
 #endif
 
 /* Solaris/SunOS binary compatibility */
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.1.100/linux/arch/sparc64/kernel/sys_sparc32.c	Thu May  7 22:51:47 1998
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.77 1998/03/29 10:10:50 davem Exp $
+/* $Id: sys_sparc32.c,v 1.83 1998/05/04 05:35:39 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -60,7 +60,7 @@
  
 extern char * getname_quicklist;
 extern int getname_quickcount;
-extern struct semaphore getname_quicklock;
+extern spinlock_t getname_quicklock;
 
 /* Tuning: increase locality by reusing same pages again...
  * if getname_quicklist becomes too long on low memory machines, either a limit
@@ -70,15 +70,15 @@
 static inline char * get_page(void)
 {
 	char * res;
-	down(&getname_quicklock);
+	spin_lock(&getname_quicklock);
 	res = getname_quicklist;
 	if (res) {
 		getname_quicklist = *(char**)res;
 		getname_quickcount--;
 	}
-	else
+	spin_unlock(&getname_quicklock);
+	if (!res)
 		res = (char*)__get_free_page(GFP_KERNEL);
-	up(&getname_quicklock);
 	return res;
 }
 
@@ -845,9 +845,6 @@
 
 	ret = do_readv_writev32(VERIFY_WRITE, file,
 				(struct iovec32 *)A(vector), count);
-	if (ret > 0)
-		current->io_usage += ret;
-
 out:
 	fput(file);
 bad_file:
@@ -872,9 +869,6 @@
 	ret = do_readv_writev32(VERIFY_READ, file,
 				(struct iovec32 *)A(vector), count);
 	up(&file->f_dentry->d_inode->i_sem);
-	if (ret > 0)
-		current->io_usage += ret;
-
 out:
 	fput(file);
 bad_file:
@@ -1148,6 +1142,7 @@
 		put_user(sec, &tvp->tv_sec);
 		put_user(usec, &tvp->tv_usec);
 	}
+	current->timeout = 0;
 
 	if (ret < 0)
 		goto out;
@@ -2556,14 +2551,16 @@
 			return 0;
 		p -= len; pos = p;
 		while (len) {
-			char *pag;
+			char *pag = (char *) page[pos/PAGE_SIZE];
 			int offset, bytes_to_copy;
 
 			offset = pos % PAGE_SIZE;
-			if (!(pag = (char *) page[pos/PAGE_SIZE]) &&
-			    !(pag = (char *) page[pos/PAGE_SIZE] =
-			      (unsigned long *) get_free_page(GFP_USER)))
-				return 0;
+			if(!pag) {
+				pag = (char *) page[pos/PAGE_SIZE] = get_user_page(pos);
+				if(!pag)
+					return 0;
+				clear_page(pag);
+			}
 			bytes_to_copy = PAGE_SIZE - offset;
 			if (bytes_to_copy > len)
 				bytes_to_copy = len;
@@ -2703,119 +2700,274 @@
 	s32 usecount;
 };
 
-extern asmlinkage int sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, size_t *ret);
+/* Query various bits about modules.  */
+
+extern long get_mod_name(const char *user_name, char **buf);
+extern void put_mod_name(char *buf);
+extern struct module *find_module(const char *name);
+extern struct module kernel_module;
+
+static int
+qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	struct module *mod;
+	size_t nmod, space, len;
+
+	nmod = space = 0;
+
+	for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {
+		len = strlen(mod->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, mod->name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
 
-asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 retv)
+	if (put_user(nmod, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((mod = mod->next) != &kernel_module)
+		space += strlen(mod->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
 {
-	char *buff;
-	mm_segment_t old_fs = get_fs();
-	size_t val;
-	int ret, i, j;
-	unsigned long *p;
-	char *usernam = NULL;
-	int bufsiz = bufsize;
-	struct module_info mi;
-	
-	switch (which) {
-	case 0:	return sys_query_module ((const char *)A(name_user), which, (char *)A(buf), (size_t)bufsize, (size_t *)A(retv));
-	case QM_SYMBOLS:
-		bufsiz <<= 1;
-	case QM_MODULES:
-	case QM_REFS:
-	case QM_DEPS:
-		if (name_user) {
-			usernam = getname32 (name_user);
-			ret = PTR_ERR(usernam);
-			if (IS_ERR(usernam))
-				return ret;
-		}
-		buff = kmalloc (bufsiz, GFP_KERNEL);
-		if (!buff) {
-			if (name_user) putname32 (usernam);
-			return -ENOMEM;
+	size_t i, space, len;
+
+	if (mod == &kernel_module)
+		return -EINVAL;
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (i = 0; i < mod->ndeps; ++i) {
+		const char *dep_name = mod->deps[i].dep->name;
+
+		len = strlen(dep_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, dep_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while (++i < mod->ndeps)
+		space += strlen(mod->deps[i].dep->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t nrefs, space, len;
+	struct module_ref *ref;
+
+	if (mod == &kernel_module)
+		return -EINVAL;
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
+		const char *ref_name = ref->ref->name;
+
+		len = strlen(ref_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, ref_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nrefs, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((ref = ref->next_ref) != NULL)
+		space += strlen(ref->ref->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+	struct module_symbol *s;
+	char *strings;
+	unsigned *vals;
+
+	if ((mod->flags & (MOD_RUNNING | MOD_DELETED)) != MOD_RUNNING)
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = mod->nsyms * 2*sizeof(u32);
+
+	i = len = 0;
+	s = mod->syms;
+
+	if (space > bufsize)
+		goto calc_space_needed;
+
+	if (!access_ok(VERIFY_WRITE, buf, space))
+		return -EFAULT;
+
+	bufsize -= space;
+	vals = (unsigned *)buf;
+	strings = buf+space;
+
+	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
+		len = strlen(s->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+
+		if (copy_to_user(strings, s->name, len)
+		    || __put_user(s->value, vals+0)
+		    || __put_user(space, vals+1))
+			return -EFAULT;
+
+		strings += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (; i < mod->nsyms; ++i, ++s)
+		space += strlen(s->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	int error = 0;
+
+	if (mod == &kernel_module)
+		return -EINVAL;
+
+	if (sizeof(struct module_info32) <= bufsize) {
+		struct module_info32 info;
+		info.addr = (unsigned long)mod;
+		info.size = mod->size;
+		info.flags = mod->flags;
+		info.usecount = (mod_member_present(mod, can_unload)
+				 && mod->can_unload ? -1 : mod->usecount);
+
+		if (copy_to_user(buf, &info, sizeof(struct module_info32)))
+			return -EFAULT;
+	} else
+		error = -ENOSPC;
+
+	if (put_user(sizeof(struct module_info32), ret))
+		return -EFAULT;
+
+	return error;
+}
+
+asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 ret)
+{
+	struct module *mod;
+	int err;
+
+	lock_kernel();
+	if (name_user == 0)
+		mod = &kernel_module;
+	else {
+		long namelen;
+		char *name;
+
+		if ((namelen = get_mod_name((char *)A(name_user), &name)) < 0) {
+			err = namelen;
+			goto out;
 		}
-qmsym_toshort:
-		set_fs (KERNEL_DS);
-		ret = sys_query_module (usernam, which, buff, bufsiz, &val);
-		set_fs (old_fs);
-		if (which != QM_SYMBOLS) {
-			if (ret == -ENOSPC || !ret) {
-				if (put_user (val, (__kernel_size_t32 *)A(retv)))
-					ret = -EFAULT;
-			}
-			if (!ret) {
-				if (copy_to_user ((char *)A(buf), buff, bufsize))
-					ret = -EFAULT;
-			}
-		} else {
-			if (ret == -ENOSPC) {
-				if (put_user (2 * val, (__kernel_size_t32 *)A(retv)))
-					ret = -EFAULT;
-			}
-			p = (unsigned long *)buff;
-			if (!ret) {
-				if (put_user (val, (__kernel_size_t32 *)A(retv)))
-					ret = -EFAULT;
-			}
-			if (!ret) {
-				j = val * 8;
-				for (i = 0; i < val; i++, p += 2) {
-					if (bufsize < (2 * sizeof (u32))) {
-						bufsiz = 0;
-						goto qmsym_toshort;
-					}
-					if (put_user (p[0], (u32 *)A(buf)) ||
-				    	    __put_user (p[1] - j, (((u32 *)A(buf))+1))) {
-						ret = -EFAULT;
-						break;
-					}
-					bufsize -= (2 * sizeof (u32));
-					buf += (2 * sizeof (u32));
-				}
-			}
-			if (!ret && val) {
-				char *strings = buff + ((unsigned long *)buff)[1];
-				j = *(p - 1) - ((unsigned long *)buff)[1];
-				j = j + strlen (strings + j) + 1;
-				if (bufsize < j) {
-					bufsiz = 0;
-					goto qmsym_toshort;
-				}
-				if (copy_to_user ((char *)A(buf), strings, j))
-					ret = -EFAULT;
-			}
+		err = -ENOENT;
+		if (namelen == 0)
+			mod = &kernel_module;
+		else if ((mod = find_module(name)) == NULL) {
+			put_mod_name(name);
+			goto out;
 		}
-		kfree (buff);
-		if (name_user) putname32 (usernam);
-		return ret;
+		put_mod_name(name);
+	}
+
+	switch (which)
+	{
+	case 0:
+		err = 0;
+		break;
+	case QM_MODULES:
+		err = qm_modules((char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		break;
+	case QM_DEPS:
+		err = qm_deps(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		break;
+	case QM_REFS:
+		err = qm_refs(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		break;
+	case QM_SYMBOLS:
+		err = qm_symbols(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		break;
 	case QM_INFO:
-		if (name_user) {
-			usernam = getname32 (name_user);
-			ret = PTR_ERR(usernam);
-			if (IS_ERR(usernam))
-				return ret;
-		}
-		set_fs (KERNEL_DS);
-		ret = sys_query_module (usernam, which, (char *)&mi, sizeof (mi), &val);
-		set_fs (old_fs);
-		if (!ret) {
-			if (put_user (sizeof (struct module_info32), (__kernel_size_t32 *)A(retv)))
-				ret = -EFAULT;
-			else if (bufsize < sizeof (struct module_info32))
-				ret = -ENOSPC;
-		}
-		if (!ret) {
-			if (put_user (mi.addr, &(((struct module_info32 *)A(buf))->addr)) ||
-			    __put_user (mi.size, &(((struct module_info32 *)A(buf))->size)) ||
-			    __put_user (mi.flags, &(((struct module_info32 *)A(buf))->flags)) ||
-			    __put_user (mi.usecount, &(((struct module_info32 *)A(buf))->usecount)))
-				ret = -EFAULT;
-		}
-		if (name_user) putname32 (usernam);
-		return ret;
+		err = qm_info(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		break;
 	default:
-		return -EINVAL;
+		err = -EINVAL;
+		break;
 	}
+out:
+	unlock_kernel();
+	return err;
 }
 
 struct kernel_sym32 {
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.1.100/linux/arch/sparc64/kernel/systbls.S	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/kernel/systbls.S	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.41 1998/03/24 05:57:57 ecd Exp $
+/* $Id: systbls.S,v 1.42 1998/04/14 13:49:52 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -40,11 +40,11 @@
 /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
 	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
 /*110*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-	.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_nis_syscall
+	.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/	.word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
 	.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
 /*130*/	.word sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
-	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall
+	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_nis_syscall
 /*140*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
 	.word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
 /*150*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
@@ -99,11 +99,11 @@
 /*100*/	.word sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
 	.word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
 /*110*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg
-	.word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_nis_syscall
+	.word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd
 /*120*/	.word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
 	.word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
 /*130*/	.word sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown
-	.word sys_socketpair, sys_mkdir, sys_rmdir, sys_nis_syscall, sys_nis_syscall
+	.word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall
 /*140*/	.word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
 	.word sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/	.word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S
--- v2.1.100/linux/arch/sparc64/lib/VIScopy.S	Thu Sep  4 12:54:48 1997
+++ linux/arch/sparc64/lib/VIScopy.S	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: VIScopy.S,v 1.14 1997/08/22 15:54:53 jj Exp $
+/* $Id: VIScopy.S,v 1.15 1998/04/26 07:21:54 davem Exp $
  * VIScopy.S: High speed copy operations utilizing the UltraSparc
  *            Visual Instruction Set.
  *
@@ -978,7 +978,16 @@
 VIScopyfixup_reto2:
 		mov		%o2, %o0
 VIScopyfixup_ret:
-		retl
+		/* If this is copy_from_user(), zero out the rest of the
+		 * kernel buffer.
+		 */
+		andcc		asi_src, 0x1, %g0
+		bne		1f
+		 mov		%o0, %o4
+		/* XXX Here, somehow get original kernel pointer (was in %o0)
+		 * XXX and bzero() all remaining bytes in kernel buffer.
+		 */
+1:		retl
 		 wr		%g0, 0, %fprs
 VIScopyfixup1:	subcc		%g2, 18, %g2
 		bgeu,a,pt	%icc, VIScopyfixup1
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.1.100/linux/arch/sparc64/mm/init.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/mm/init.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.71 1998/03/27 07:00:08 davem Exp $
+/*  $Id: init.c,v 1.81 1998/05/04 05:35:43 jj Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -8,6 +8,8 @@
 #include <linux/config.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
 #include <linux/blk.h>
 #include <linux/swap.h>
 #include <linux/swapctl.h>
@@ -52,11 +54,6 @@
 	__bfill64((void *)pmdp, &two_null_pte_table);
 }
 
-static __inline__ void __init_pgd(pgd_t *pgdp)
-{
-	__bfill64((void *)pgdp, &two_null_pmd_table);
-}
-
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -125,6 +122,9 @@
 	printk("%d pages shared\n",shared);
 	printk("%d pages swap cached\n",cached);
 	printk("%ld pages in page table cache\n",pgtable_cache_size);
+#ifndef __SMP__
+	printk("%ld entries in page dir cache\n",pgd_cache_size);
+#endif	
 	show_buffers();
 #ifdef CONFIG_NET
 	show_net_buffers();
@@ -135,27 +135,47 @@
 
 /* This keeps track of pages used in sparc_alloc_dvma() invocations. */
 /* NOTE: All of these are inited to 0 in bss, don't need to make data segment bigger */
-static unsigned long dvma_map_pages[0x10000000 >> 16];
+#define DVMAIO_SIZE 0x2000000
+static unsigned long dvma_map_pages[DVMAIO_SIZE >> 16];
 static unsigned long dvma_pages_current_offset;
 static int dvma_pages_current_index;
+static unsigned long dvmaiobase = 0;
+static unsigned long dvmaiosz __initdata = 0;
 
 /* #define E3000_DEBUG */
 
-__initfunc(unsigned long iommu_init(int iommu_node, unsigned long memory_start,
-				    unsigned long memory_end, struct linux_sbus *sbus))
+__initfunc(void dvmaio_init(void))
+{
+	int i;
+	
+	if (!dvmaiobase) {
+		for (i = 0; sp_banks[i].num_bytes != 0; i++)
+			if (sp_banks[i].base_addr + sp_banks[i].num_bytes > dvmaiobase)
+				dvmaiobase = sp_banks[i].base_addr + sp_banks[i].num_bytes;
+		dvmaiobase = (dvmaiobase + DVMAIO_SIZE + 0x400000 - 1) & ~(0x400000 - 1);
+		for (i = 0; i < 6; i++)
+			if (dvmaiobase <= ((1024 * 64 * 1024) << i))
+				break;
+		dvmaiobase = ((1024 * 64 * 1024) << i) - DVMAIO_SIZE;
+		dvmaiosz = i;
+	}
+}
+
+__initfunc(void iommu_init(int iommu_node, struct linux_sbus *sbus))
 {
 	struct iommu_struct *iommu;
 	struct sysio_regs *sregs;
 	struct linux_prom64_registers rprop;
 	unsigned long impl, vers;
 	unsigned long control, tsbbase;
+	unsigned long tsbbases[32];
 	unsigned long *iopte;
-	u32 rlow, rhigh;
-	int err, i;
-
+	int err, i, j;
+	
+	dvmaio_init();
 #ifdef E3000_DEBUG
-	prom_printf("\niommu_init: [%x:%016lx:%016lx:%p] ",
-		    iommu_node, memory_start, memory_end, sbus);
+	prom_printf("\niommu_init: [%x:%p] ",
+		    iommu_node, sbus);
 #endif
 	err = prom_getproperty(iommu_node, "reg", (char *)&rprop,
 			       sizeof(rprop));
@@ -163,14 +183,8 @@
 		prom_printf("iommu_init: Cannot map SYSIO control registers.\n");
 		prom_halt();
 	}
-	rlow  = (rprop.phys_addr & 0xffffffff);
-	rhigh = (rprop.phys_addr >> 32);
-#ifdef E3000_DEBUG
-	prom_printf("rlow[%08x] rhigh[%08x] ", rlow, rhigh);
-#endif
-	sregs = (struct sysio_regs *) sparc_alloc_io(rlow, (void *)0,
-						     sizeof(struct sysio_regs),
-						     "SYSIO Regs", rhigh, 0x0);
+	sregs = (struct sysio_regs *) __va(rprop.phys_addr);
+
 #ifdef E3000_DEBUG
 	prom_printf("sregs[%p]\n");
 #endif
@@ -179,9 +193,7 @@
 		prom_halt();
 	}
 
-	memory_start = (memory_start + 7) & ~7;
-	iommu = (struct iommu_struct *) memory_start;
-	memory_start += sizeof(struct iommu_struct);
+	iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC);
 
 #ifdef E3000_DEBUG
 	prom_printf("iommu_init: iommu[%p] ", iommu);
@@ -203,26 +215,54 @@
 	       (unsigned int) impl, (unsigned int)vers, (unsigned long) sregs);
 	
 	control &= ~(IOMMU_CTRL_TSBSZ);
-	control |= (IOMMU_TSBSZ_64K | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
+	control |= ((IOMMU_TSBSZ_2K * dvmaiosz) | IOMMU_CTRL_TBWSZ | IOMMU_CTRL_ENAB);
 
 	/* Use only 64k pages, things are layed out in the 32-bit SBUS
 	 * address space like this:
 	 *
-	 * 0x00000000	----------------------------------------
-	 *		| Direct physical mappings for most    |
-	 *              | DVMA to paddr's within this range    |
-	 * 0xf0000000   ----------------------------------------
-	 * 		| For mappings requested via           |
-	 *              | sparc_alloc_dvma()		       |
-	 * 0xffffffff	----------------------------------------
-	 */
-	tsbbase = PAGE_ALIGN(memory_start);
-	memory_start = (tsbbase + ((64 * 1024) * 8));
+	 * 0x00000000	  ----------------------------------------
+	 *		  | Direct physical mappings for most    |
+	 *                | DVMA to paddr's within this range    |
+	 * dvmaiobase     ----------------------------------------
+	 * 		  | For mappings requested via           |
+	 *                | sparc_alloc_dvma()		         |
+	 * dvmaiobase+32M ----------------------------------------
+	 *
+	 * NOTE: we need to order 2 contiguous order 5, that's the largest
+	 *       chunk page_alloc will give us.   -JJ */
+	tsbbase = 0;
+	if (dvmaiosz == 6) {
+		memset (tsbbases, 0, sizeof(tsbbases));
+		for (i = 0; i < 32; i++) {
+			tsbbases[i] = __get_free_pages(GFP_DMA, 5);
+			for (j = 0; j < i; j++)
+				if (tsbbases[j] == tsbbases[i] + 32768*sizeof(iopte_t)) {
+					tsbbase = tsbbases[i];
+					break;
+				} else if (tsbbases[i] == tsbbases[j] + 32768*sizeof(iopte_t)) {
+					tsbbase = tsbbases[j];
+					break;
+				}
+			if (tsbbase) {
+				tsbbases[i] = 0;
+				tsbbases[j] = 0;
+				break;
+			}
+		}
+		for (i = 0; i < 32; i++)
+			if (tsbbases[i])
+				free_pages(tsbbases[i], 5);
+	} else
+		tsbbase = __get_free_pages(GFP_DMA, dvmaiosz);
+	if (!tsbbase) {
+		prom_printf("Strange. Could not allocate 512K of contiguous RAM.\n");
+		prom_halt();
+	}
 	iommu->page_table = (iopte_t *) tsbbase;
 	iopte = (unsigned long *) tsbbase;
 
 	/* Setup aliased mappings... */
-	for(i = 0; i < (65536 - 4096); i++) {
+	for(i = 0; i < (dvmaiobase >> 16); i++) {
 		*iopte  = (IOPTE_VALID | IOPTE_64K | IOPTE_STBUF |
 			   IOPTE_CACHE | IOPTE_WRITE);
 		*iopte |= (i << 16);
@@ -230,7 +270,7 @@
 	}
 
 	/* Clear all sparc_alloc_dvma() maps. */
-	for( ; i < 65536; i++)
+	for( ; i < ((dvmaiobase + DVMAIO_SIZE) >> 16); i++)
 		*iopte++ = 0;
 
 #ifdef E3000_DEBUG
@@ -252,23 +292,19 @@
 #endif
 	printk("IOMMU: Streaming Buffer IMPL[%x] REV[%x] ",
 	       (unsigned int)impl, (unsigned int)vers);
-	printk("FlushFLAG[%p,%016lx] ... ",
-	       (iommu->sbuf_flushflag_va = (unsigned int *)memory_start),
-	       (iommu->sbuf_flushflag_pa = __pa(memory_start)));
+	iommu->sbuf_flushflag_va = kmalloc(sizeof(unsigned long), GFP_DMA);
+	printk("FlushFLAG[%016lx] ... ", (iommu->sbuf_flushflag_pa = __pa(iommu->sbuf_flushflag_va)));
 	*(iommu->sbuf_flushflag_va) = 0;
-	memory_start += sizeof(unsigned long); /* yes, unsigned long, for alignment */
 
 	sregs->sbuf_control = (control | SYSIO_SBUFCTRL_SB_EN);
 
 #ifdef E3000_DEBUG
-	prom_printf("done, returning %016lx\n", memory_start);
+	prom_printf("done, returning\n");
 #endif
 	printk("ENABLED\n");
 
 	/* Finally enable DVMA arbitration for all devices, just in case. */
 	sregs->sbus_control |= SYSIO_SBCNTRL_AEN;
-
-	return memory_start;
 }
 
 void mmu_map_dma_area(unsigned long addr, int len, __u32 *dvma_addr,
@@ -300,7 +336,7 @@
 		}
 
 		/* Stick it in the IOMMU. */
-		i = (65536 - 4096) + i;
+		i = (dvmaiobase >> 16) + i;
 		for_each_sbus(sbus) {
 			struct iommu_struct *iommu = sbus->iommu;
 			unsigned long flags;
@@ -314,7 +350,7 @@
 	}
 
 	/* Get this out of the way. */
-	*dvma_addr = (__u32) ((0xf0000000) +
+	*dvma_addr = (__u32) ((dvmaiobase) +
 			      (dvma_pages_current_index << 16) +
 			      (dvma_pages_current_offset));
 
@@ -345,13 +381,17 @@
 {
 	__u32 sbus_addr = (__u32) __pa(vaddr);
 
-	if((sbus_addr < 0xf0000000) &&
-	   ((sbus_addr + len) < 0xf0000000))
+#ifndef DEBUG_IOMMU
+	return sbus_addr;
+#else
+	if((sbus_addr < dvmaiobase) &&
+	   ((sbus_addr + len) < dvmaiobase))
 		return sbus_addr;
 
 	/* "can't happen"... GFP_DMA assures this. */
 	panic("Very high scsi_one mappings should never happen.");
         return (__u32)0;
+#endif        
 }
 
 void mmu_release_scsi_one(u32 vaddr, unsigned long len, struct linux_sbus *sbus)
@@ -385,13 +425,17 @@
 {
 	while(sz >= 0) {
 		__u32 page = (__u32) __pa(((unsigned long) sg[sz].addr));
-		if((page < 0xf0000000) &&
-		   (page + sg[sz].len) < 0xf0000000) {
+#ifndef DEBUG_IOMMU
+		sg[sz].dvma_addr = page;
+#else		
+		if((page < dvmaiobase) &&
+		   (page + sg[sz].len) < dvmaiobase) {
 			sg[sz].dvma_addr = page;
 		} else {
 			/* "can't happen"... GFP_DMA assures this. */
 			panic("scsi_sgl high mappings should never happen.");
 		}
+#endif
 		sz--;
 	}
 }
@@ -485,10 +529,42 @@
 	}
 }
 
+static int prom_ditlb_set = 0;
 int prom_itlb_ent, prom_dtlb_ent;
 unsigned long prom_itlb_tag, prom_itlb_data;
 unsigned long prom_dtlb_tag, prom_dtlb_data;
 
+void prom_world(int enter)
+{
+	if (!prom_ditlb_set) return;
+	if (enter) {
+		/* Install PROM world. */
+		__asm__ __volatile__("stxa %0, [%1] %2"
+					: : "r" (prom_dtlb_tag), "r" (TLB_TAG_ACCESS),
+					"i" (ASI_DMMU));
+		membar("#Sync");
+		spitfire_put_dtlb_data(62, prom_dtlb_data);
+		membar("#Sync");
+		__asm__ __volatile__("stxa %0, [%1] %2"
+					: : "r" (prom_itlb_tag), "r" (TLB_TAG_ACCESS),
+					"i" (ASI_IMMU));
+		membar("#Sync");
+		spitfire_put_itlb_data(62, prom_itlb_data);
+		membar("#Sync");
+	} else {
+		__asm__ __volatile__("stxa %%g0, [%0] %1"
+					: : "r" (TLB_TAG_ACCESS), "i" (ASI_DMMU));
+		membar("#Sync");
+		spitfire_put_dtlb_data(62, 0x0UL);
+		membar("#Sync");
+		__asm__ __volatile__("stxa %%g0, [%0] %1"
+					: : "r" (TLB_TAG_ACCESS), "i" (ASI_IMMU));
+		membar("#Sync");
+		spitfire_put_itlb_data(62, 0x0UL);
+		membar("#Sync");
+	}
+}
+
 void inherit_locked_prom_mappings(int save_p)
 {
 	int i;
@@ -500,8 +576,7 @@
 	 * translations property.  The only ones that matter are
 	 * the locked PROM tlb entries, so we impose the following
 	 * irrecovable rule on the PROM, it is allowed 1 locked
-	 * entry in the ITLB and 1 in the DTLB.  We move those
-	 * (if necessary) up into tlb entry 62.
+	 * entry in the ITLB and 1 in the DTLB.
 	 *
 	 * Supposedly the upper 16GB of the address space is
 	 * reserved for OBP, BUT I WISH THIS WAS DOCUMENTED
@@ -510,7 +585,7 @@
 	 * systems to coordinate mmu mappings is also COMPLETELY
 	 * UNDOCUMENTED!!!!!! Thanks S(t)un!
 	 */
-	for(i = 0; i < 62; i++) {
+	for(i = 0; i < 63; i++) {
 		unsigned long data;
 
 		data = spitfire_get_dtlb_data(i);
@@ -528,13 +603,6 @@
 			spitfire_put_dtlb_data(i, 0x0UL);
 			membar("#Sync");
 
-			/* Re-install it. */
-			__asm__ __volatile__("stxa %0, [%1] %2"
-					     : : "r" (tag), "r" (TLB_TAG_ACCESS),
-					         "i" (ASI_DMMU));
-			membar("#Sync");
-			spitfire_put_dtlb_data(62, data);
-			membar("#Sync");
 			dtlb_seen = 1;
 			if(itlb_seen)
 				break;
@@ -566,6 +634,8 @@
 				break;
 		}
 	}
+	if (save_p)
+		prom_ditlb_set = 1;
 }
 
 /* Give PROM back his world, done during reboots... */
@@ -628,37 +698,67 @@
 			     : : "r" (pstate));
 }
 
-/* We are always protected by scheduler_lock under SMP. */
-void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx)
-{
-	unsigned int new_ctx = *ctx;
+unsigned long mmu_context_bmap[1UL << (CTX_VERSION_SHIFT - 6)];
 
-	if((new_ctx & ~(CTX_VERSION_MASK)) == 0) {
-		new_ctx += CTX_FIRST_VERSION;
-		if(new_ctx == 1)
-			new_ctx = CTX_FIRST_VERSION;
-		*ctx = new_ctx;
-		DO_LOCAL_FLUSH(smp_processor_id());
+/* We are always protected by scheduler_lock under SMP.
+ * Caller does TLB context flushing on local CPU if necessary.
+ */
+void get_new_mmu_context(struct mm_struct *mm)
+{
+	unsigned long ctx = (tlb_context_cache + 1) & ~(CTX_VERSION_MASK);
+	unsigned long new_ctx;
+	
+	if (mm->context != NO_CONTEXT && !((mm->context ^ tlb_context_cache) & CTX_VERSION_MASK))
+		clear_bit(mm->context & ~(CTX_VERSION_MASK), mmu_context_bmap);
+	new_ctx = find_next_zero_bit(mmu_context_bmap, 1UL << CTX_VERSION_SHIFT, ctx);
+	if (new_ctx >= (1UL << CTX_VERSION_SHIFT)) {
+		new_ctx = find_next_zero_bit(mmu_context_bmap, ctx, 1);
+		if (new_ctx >= ctx) {
+			new_ctx = (tlb_context_cache & CTX_VERSION_MASK) + CTX_FIRST_VERSION;
+			mmu_context_bmap[0] = 3;
+			memset(mmu_context_bmap + sizeof(long), 0, sizeof(mmu_context_bmap) - sizeof(long));
+			goto out;
+		}
 	}
+	set_bit(new_ctx, mmu_context_bmap);
+	new_ctx |= (tlb_context_cache & CTX_VERSION_MASK);
+out:	tlb_context_cache = new_ctx;
 	mm->context = new_ctx;
-	mm->cpu_vm_mask = 0;	/* Callers sets it properly. */
-	(*ctx)++;
+	mm->cpu_vm_mask = 0;
 }
 
-#ifndef __SMP__
-struct pgtable_cache_struct pgt_quicklists;
+#ifdef __SMP__
+spinlock_t user_page_lock = SPIN_LOCK_UNLOCKED;
 #endif
+struct upcache user_page_cache[2] __attribute__((aligned(32)));
 
-pgd_t *get_pgd_slow(void)
-{
-	pgd_t *pgd;
-
-	pgd = (pgd_t *) __get_free_page(GFP_KERNEL);
-	if(pgd)
-		__init_pgd(pgd);
-	return pgd;
+unsigned long get_user_page_slow(int which)
+{
+	unsigned long chunk;
+	struct upcache *up = &user_page_cache[!which];
+	struct page *p;
+
+	do { chunk = __get_free_pages(GFP_KERNEL, 1); } while(chunk==0);
+	p = mem_map + MAP_NR(chunk);
+	atomic_set(&p->count, 1);
+	atomic_set(&(p+1)->count, 1);
+	p->age = (p+1)->age = PAGE_INITIAL_AGE;
+	spin_lock(&user_page_lock);
+	if(up->count < USER_PAGE_WATER) {
+		struct page *new = p + !which;
+		new->next = up->list;
+		up->list = new;
+		up->count++;
+	} else
+		free_pages((chunk+(PAGE_SIZE*(!which))), 0);
+	spin_unlock(&user_page_lock);
+	return page_address(p + which);
 }
 
+#ifndef __SMP__
+struct pgtable_cache_struct pgt_quicklists;
+#endif
+
 pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
 {
 	pmd_t *pmd;
@@ -747,7 +847,7 @@
 	pte_clear(ptep);
 }
 
-#if NOTUSED
+#ifdef NOTUSED
 void sparc_ultra_dump_itlb(void)
 {
         int slot;
@@ -796,6 +896,7 @@
 	unsigned long flags;
 	unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
 	
+	set_bit(0, mmu_context_bmap);
 	/* We assume physical memory starts at some 4mb multiple,
 	 * if this were not true we wouldn't boot up to this point
 	 * anyways.
@@ -889,6 +990,7 @@
 	unsigned long tmp = 0, paddr, endaddr;
 	unsigned long end = __pa(end_mem);
 
+	dvmaio_init();
 	for (paddr = __pa(start_mem); paddr < end; ) {
 		for (; sp_banks[tmp].num_bytes != 0; tmp++)
 			if (sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes > paddr)
@@ -911,7 +1013,7 @@
 		endaddr = sp_banks[tmp].base_addr + sp_banks[tmp].num_bytes;
 		while (paddr < endaddr) {
 			mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<<PG_reserved);
-			if (paddr >= 0xf0000000)
+			if (paddr >= dvmaiobase)
 				mem_map[paddr>>PAGE_SHIFT].flags &= ~(1<<PG_DMA);
 			paddr += PAGE_SIZE;
 		}
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- v2.1.100/linux/arch/sparc64/mm/ultra.S	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/mm/ultra.S	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.20 1997/10/03 20:42:46 davem Exp $
+/* $Id: ultra.S,v 1.21 1998/04/28 08:23:30 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -12,7 +12,7 @@
 	.text
 	.align		32
 	.globl		__flush_tlb_mm, __flush_tlb_range, __flush_tlb_page
-__flush_tlb_mm:		/* %o0 == (mm->context & 0x1fff) */
+__flush_tlb_mm:		/* %o0 == (mm->context & 0x3ff) */
 	mov		SECONDARY_CONTEXT, %g7
 9:	ldxa		[%g7] ASI_DMMU, %g2
 	cmp		%g2, %o0
@@ -33,7 +33,7 @@
 	retl
 	 wrpr		%g1, 0, %pstate
 	nop
-__flush_tlb_range:	/* %o0 == (mm->context & 0x1fff), %o1 == start, %o2 == end */
+__flush_tlb_range:	/* %o0 == (mm->context & 0x3ff), %o1 == start, %o2 == end */
 	sethi		%hi(8192 - 1), %g5
 	or		%g5, %lo(8192 - 1), %g5
 	andn		%o1, %g5, %o1
@@ -72,7 +72,7 @@
 	 nop
 
 	.align		32
-__flush_tlb_page:	/* %o0 == (mm->context & 0x1fff), %o1 == page & PAGE_MASK */
+__flush_tlb_page:	/* %o0 == (mm->context & 0x3ff), %o1 == page & PAGE_MASK */
 	mov		SECONDARY_CONTEXT, %g7
 	ldxa		[%g7] ASI_DMMU, %g2
 	cmp		%g2, %o0
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/prom/p1275.c linux/arch/sparc64/prom/p1275.c
--- v2.1.100/linux/arch/sparc64/prom/p1275.c	Sat Aug 16 09:51:09 1997
+++ linux/arch/sparc64/prom/p1275.c	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: p1275.c,v 1.12 1997/07/26 18:39:01 davem Exp $
+/* $Id: p1275.c,v 1.13 1998/04/24 15:45:35 jj Exp $
  * p1275.c: Sun IEEE 1275 PROM low level interface routines
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -24,6 +24,8 @@
 	char prom_buffer [3000];
 } p1275buf;
 
+extern void prom_world(int);
+
 void prom_cif_interface (void)
 {
 	__asm__ __volatile__ ("
@@ -115,7 +117,11 @@
 	}
 	va_end(list);
 
+	prom_world(1);
+	
 	prom_cif_interface();
+	
+	prom_world(0);
 
 	attrs = fmt >> 8;
 	va_start(list, fmt);
diff -u --recursive --new-file v2.1.100/linux/arch/sparc64/solaris/signal.h linux/arch/sparc64/solaris/signal.h
--- v2.1.100/linux/arch/sparc64/solaris/signal.h	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/solaris/signal.h	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: signal.h,v 1.2 1997/09/03 12:29:21 jj Exp $
+/* $Id: signal.h,v 1.3 1998/04/12 06:20:33 davem Exp $
  * signal.h: Signal emulation for Solaris
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -106,4 +106,3 @@
 #define SOLARIS_POLL_ERR        4
 #define SOLARIS_POLL_PRI        5
 #define SOLARIS_POLL_HUP        6
-    
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/Config.in linux/drivers/acorn/block/Config.in
--- v2.1.100/linux/drivers/acorn/block/Config.in	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/block/Config.in	Fri May  8 00:42:38 1998
@@ -2,9 +2,8 @@
 # Block device driver configuration
 #
 mainmenu_option next_comment
-comment 'Acorn-Specific floppy, IDE, and other block devices'
+comment 'Acorn-specific block devices'
 
-tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD
 bool '   Support expansion card IDE interfaces' CONFIG_BLK_DEV_IDE_CARDS
 if [ "$CONFIG_BLK_DEV_IDE_CARDS" = "y" ]; then
   dep_tristate '    ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE $CONFIG_BLK_DEV_IDE
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/fd1772dma.S linux/drivers/acorn/block/fd1772dma.S
--- v2.1.100/linux/drivers/acorn/block/fd1772dma.S	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/block/fd1772dma.S	Fri May  8 00:42:38 1998
@@ -0,0 +1,100 @@
+#include <asm/hardware.h>
+
+@ Code for DMA with the 1772 fdc
+.text
+
+
+  .global _fdc1772_dataaddr
+_fdc1772_fiqdata:
+@ Number of bytes left to DMA
+  .global _fdc1772_bytestogo
+_fdc1772_bytestogo:
+  .word 0
+@ Place to put/get data from in DMA
+  .global _fdc1772_dataaddr
+_fdc1772_dataaddr:
+  .word 0
+  
+  .global _fdc1772_fdc_int_done
+_fdc1772_fdc_int_done:
+  .word 0
+  .global _fdc1772_comendstatus
+_fdc1772_comendstatus:
+  .word 0
+
+@ We hang this off DMA channel 1
+    .global _fdc1772_comendhandler
+_fdc1772_comendhandler:
+  mov      r8,#IOC_BASE
+  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
+  tst      r9,#2
+  subeqs   pc,r14,#4        @ should I leave a space here
+  orr      r9,r8,#0x10000   @ FDC base
+  adr      r8,_fdc1772_fdc_int_done
+  ldrb     r10,[r9,#0]  @ FDC status
+  mov      r9,#1        @ Got a FIQ flag
+  stmia    r8,{r9,r10}
+  subs     pc,r14,#4
+
+
+    .global _fdc1772_dma_read
+_fdc1772_dma_read:
+  mov      r8,#IOC_BASE
+  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
+  tst      r9,#1
+  beq      _fdc1772_dma_read_notours
+  orr      r8,r8,#0x10000   @ FDC base
+  ldrb     r10,[r8,#0xc]   @ Read from FDC data reg (also clears interrupt)
+  ldmia    r11,{r8,r9}
+  subs     r8,r8,#1        @ One less byte to go
+  @ If there was somewhere for this data to go then store it and update pointers
+  strplb   r10,[r9],#1     @ Store the data and increment the pointer
+  stmplia  r11,{r8,r9}     @ Update count/pointers
+  @ Handle any other interrupts if there are any
+_fdc1772_dma_read_notours:
+  @ Cant branch because this code has been copied down to the FIQ vector
+  ldr pc,[pc,#-4]
+  .word _fdc1772_comendhandler
+  .global _fdc1772_dma_read_end
+_fdc1772_dma_read_end:
+
+    .global _fdc1772_dma_write
+_fdc1772_dma_write:
+  mov      r8,#IOC_BASE
+  ldrb     r9,[r8,#0x34]    @ IOC FIQ status
+  tst      r9,#1
+  beq      _fdc1772_dma_write_notours
+  orr      r8,r8,#0x10000   @ FDC base
+  ldmia    r11,{r9,r10}
+  subs     r9,r9,#1        @ One less byte to go
+  @ If there really is some data then get it, store it and update count
+  ldrplb   r12,[r10],#1
+  strplb   r12,[r8,#0xc]   @ write it to FDC data reg
+  stmplia  r11,{r9,r10}    @ Update count and pointer - should clear interrupt
+  @ Handle any other interrupts
+_fdc1772_dma_write_notours:
+  @ Cant branch because this code has been copied down to the FIQ vector
+  ldr pc,[pc,#-4]
+  .word _fdc1772_comendhandler
+
+  .global _fdc1772_dma_write_end
+_fdc1772_dma_write_end:
+  
+
+@ Setup the FIQ R11 to point to the data and store the count, address
+@ for this dma
+@ R0=count
+@ R1=address
+  .global _fdc1772_setupdma
+_fdc1772_setupdma:
+	@ The big job is flipping in and out of FIQ mode
+	adr	r2,_fdc1772_fiqdata	@ This is what we really came here for
+  stmia  r2,{r0,r1}
+	mov	r3, pc
+	teqp	pc,#0x0c000001	@ Disable FIQs, IRQs and switch to FIQ mode
+	mov	r0,r0      	@ NOP
+	mov r11,r2
+	teqp	r3,#0		@ Normal mode
+	mov	r0,r0		@ NOP
+  mov pc,r14
+
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/ide-rapide.c linux/drivers/acorn/block/ide-rapide.c
--- v2.1.100/linux/drivers/acorn/block/ide-rapide.c	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/block/ide-rapide.c	Fri May  8 00:42:38 1998
@@ -1,10 +1,11 @@
 /*
- * linux/arch/arm/drivers/block/ide-ics.c
+ * linux/arch/arm/drivers/block/ide-rapide.c
  *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1998 Russell King.
  *
  * Changelog:
  *  08-06-1996	RMK	Created
+ *  13-04-1998	RMK	Added manufacturer and product IDs
  */
 
 #include <linux/module.h>
@@ -16,38 +17,39 @@
 #include "../../block/ide.h"
 
 static const card_ids rapide_cids[] = {
+	{ MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 },
 	{ 0xffff, 0xffff }
 };
 
 static struct expansion_card *ec[MAX_ECARDS];
 static int result[MAX_ECARDS];
 
-static inline int rapide_register (struct expansion_card *ec)
+static inline int rapide_register(struct expansion_card *ec)
 {
 	unsigned long port = ecard_address (ec, ECARD_MEMC, 0);
 
-	return ide_register_port (port, port + 0x206, 4, ec->irq);
+	return ide_register_port(port, port + 0x206, 4, ec->irq);
 }
 
-int rapide_init (void)
+int rapide_init(void)
 {
 	int i;
 
 	for (i = 0; i < MAX_ECARDS; i++)
 		ec[i] = NULL;
 
-	ecard_startfind ();
+	ecard_startfind();
 
 	for (i = 0; ; i++) {
-		if ((ec[i] = ecard_find (0, rapide_cids)) == NULL)
+		if ((ec[i] = ecard_find(0, rapide_cids)) == NULL)
 			break;
 
-		ecard_claim (ec[i]);
-		result[i] = rapide_register (ec[i]);
+		ecard_claim(ec[i]);
+		result[i] = rapide_register(ec[i]);
 	}
 	for (i = 0; i < MAX_ECARDS; i++)
 		if (ec[i] && result[i] < 0) {
-			ecard_release (ec[i]);
+			ecard_release(ec[i]);
 			ec[i] = NULL;
 	}
 	return 0;
@@ -67,10 +69,10 @@
 	for (i = 0; i < MAX_ECARDS; i++)
 		if (ec[i]) {
 			unsigned long port;
-			port = ecard_address (ec[i], ECARD_MEMC, 0);
+			port = ecard_address(ec[i], ECARD_MEMC, 0);
 
-			ide_unregister_port (port, ec[i]->irq, 16);
-			ecard_release (ec[i]);
+			ide_unregister_port(port, ec[i]->irq, 16);
+			ecard_release(ec[i]);
 			ec[i] = NULL;
 		}
 }
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/block/mfm.S linux/drivers/acorn/block/mfm.S
--- v2.1.100/linux/drivers/acorn/block/mfm.S	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/block/mfm.S	Fri May  8 00:42:38 1998
@@ -0,0 +1,163 @@
+@ Read/Write DMA code for the ST506/MFM hard drive controllers on the A400
+@   motherboard on ST506 podules.
+@ (c) David Alan Gilbert (gilbertd@cs.man.ac.uk) 1996
+
+#include <asm/assembler.h>
+ 
+_hdc63463_irqdata:
+@ Controller base address
+  .global _hdc63463_baseaddress
+_hdc63463_baseaddress:
+  .word 0
+
+  .global _hdc63463_irqpolladdress
+_hdc63463_irqpolladdress:
+  .word 0
+ 
+  .global _hdc63463_irqpollmask
+_hdc63463_irqpollmask:
+  .word 0
+
+@ where to read/write data  from the kernel data space
+  .global _hdc63463_dataptr
+_hdc63463_dataptr:
+  .word 0
+
+@ Number of bytes left to transfer
+  .global _hdc63463_dataleft
+_hdc63463_dataleft:
+  .word 0
+
+@ -------------------------------------------------------------------------
+@ hdc63463_writedma: DMA from host to controller
+@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
+@                      r3=data ptr, r4=data left, r5,r6=temporary
+  .global _hdc63463_writedma
+_hdc63463_writedma:
+  stmfd sp!,{r4-r7}
+  adr r5,_hdc63463_irqdata
+  ldmia r5,{r0,r1,r2,r3,r4}
+
+
+writedma_again:
+
+  @ test number of remaining bytes to transfer
+  cmp r4,#0
+  beq writedma_end
+  bmi writedma_end
+
+  @ Check the hdc is interrupting
+  ldrb r5,[r1,#0]
+  tst r5,r2
+  beq writedma_end
+
+  @ Transfer a block of upto 256 bytes
+  cmp r4,#256
+  movlt r7,r4
+  movge r7,#256
+
+  @ Check the hdc is still busy and command has not ended and no errors
+  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
+  @ think we should continue DMA until it drops busy - perhaps this was
+  @ the main problem with corrected errors causing a hang
+  @tst r5,#0x3c00        @ Test for things which should be off
+  @bne writedma_end
+  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
+  cmp r5,#0x8000
+  bne writedma_end 
+
+  @ Bytes remaining at end
+  sub r4,r4,r7
+
+  @ HDC Write register location
+  add r0,r0,#32+8
+
+writedma_loop:
+  @ OK - pretty sure we should be doing this
+
+  ldr r5,[r3],#4          @ Get a word to be written
+  @ get bottom half to be sent first
+  mov r6,r5,lsl#16        @ Separate the first 2 bytes
+  orr r2,r6,r6,lsr #16    @ Duplicate them in the bottom half of the word
+  @ now the top half
+  mov r6,r5,lsr#16        @ Get 2nd 2 bytes
+  orr r6,r6,r6,lsl#16     @ Duplicate
+  @str r6,[r0]       @ to hdc
+  stmia r0,{r2,r6}
+  subs r7,r7,#4           @ Dec. number of bytes left
+  bne writedma_loop
+
+  @ If we were too slow we had better go through again - DAG - took out with new interrupt routine
+  @ sub r0,r0,#32+8
+  @ adr r2,_hdc63463_irqdata
+  @ ldr r2,[r2,#8]
+  @ b writedma_again
+
+writedma_end:
+  adr r5,_hdc63463_irqdata+12
+  stmia r5,{r3,r4}
+  ldmfd sp!,{r4-r7}
+  RETINSTR(mov,pc,lr)
+
+@ -------------------------------------------------------------------------
+@ hdc63463_readdma: DMA from controller to host
+@  internal reg usage: r0=hdc base address, r1=irq poll address, r2=poll mask
+@                      r3=data ptr, r4=data left, r5,r6=temporary
+  .global _hdc63463_readdma
+_hdc63463_readdma:
+  stmfd sp!,{r4-r7}
+  adr r5,_hdc63463_irqdata
+  ldmia r5,{r0,r1,r2,r3,r4}
+
+readdma_again:
+  @ test number of remaining bytes to transfer
+  cmp r4,#0
+  beq readdma_end
+  bmi readdma_end
+
+  @ Check the hdc is interrupting
+  ldrb r5,[r1,#0]
+  tst r5,r2
+  beq readdma_end
+
+  @ Check the hdc is still busy and command has not ended and no errors
+  ldr r5,[r0,#32]     @ Status reg - 16 bit - its the top few bits which are status
+  @ think we should continue DMA until it drops busy - perhaps this was
+  @ the main problem with corrected errors causing a hang
+  @tst r5,#0x3c00      @ Test for things which should be off
+  @bne readdma_end
+  and r5,r5,#0x8000        @ This is test for things which should be on: Busy
+  cmp r5,#0x8000
+  bne readdma_end 
+
+  @ Transfer a block of upto 256 bytes
+  cmp r4,#256
+  movlt r7,r4
+  movge r7,#256
+
+  @ Bytes remaining at end
+  sub r4,r4,r7
+
+  @ Set a pointer to the data register in the HDC
+  add r0,r0,#8
+readdma_loop:
+  @ OK - pretty sure we should be doing this
+  ldmia r0,{r5,r6}
+  mov r5,r5,lsl#16
+  mov r6,r6,lsl#16
+  orr r6,r6,r5,lsr #16
+  str r6,[r3],#4
+  subs r7,r7,#4        @ Decrement bytes to go
+  bne readdma_loop
+
+  @ Try reading multiple blocks - if this was fast enough then I dont think
+  @ this should help - NO taken out DAG - new interrupt handler has
+  @ non-consecutive memory blocks
+  @ sub r0,r0,#8
+  @ b readdma_again
+
+readdma_end:
+  adr r5,_hdc63463_irqdata+12
+  stmia r5,{r3,r4}
+  ldmfd sp!,{r4-r7}
+  RETINSTR(mov,pc,lr)
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/Config.in linux/drivers/acorn/char/Config.in
--- v2.1.100/linux/drivers/acorn/char/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/Config.in	Fri May  8 00:42:38 1998
@@ -0,0 +1,4 @@
+if [ "$CONFIG_SERIAL" != "n" ]; then
+  tristate '   Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
+  tristate '   Dual serial port support' CONFIG_DUALSP_SERIAL
+fi
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile
--- v2.1.100/linux/drivers/acorn/char/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/Makefile	Fri May  8 00:42:38 1998
@@ -0,0 +1,32 @@
+#
+# Makefile for the kernel character device drivers.
+#
+# 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 inherited from the
+# parent makes..
+#
+
+L_TARGET := acorn-char.a
+M_OBJS   :=
+L_OBJS   :=
+
+ifeq ($(CONFIG_ATOMWIDE_SERIAL),y)
+  L_OBJS += serial-atomwide.o
+else
+  ifeq ($(CONFIG_ATOMWIDE_SERIAL),m)
+    M_OBJS += serial-atomwide.o
+  endif
+endif
+
+ifeq ($(CONFIG_DUALSP_SERIAL),y)
+  L_OBJS += serial-dualsp.o
+else
+  ifeq ($(CONFIG_DUALSP_SERIAL),m)
+    M_OBJS += serial-dualsp.o
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/serial-atomwide.c linux/drivers/acorn/char/serial-atomwide.c
--- v2.1.100/linux/drivers/acorn/char/serial-atomwide.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/serial-atomwide.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/arm/drivers/char/serial-atomwide.c
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  02-05-1996	RMK	Created
+ *  07-05-1996	RMK	Altered for greater number of cards.
+ *  30-07-1996	RMK	Now uses generic card code.
+ */
+
+#define MY_CARD_LIST { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL }
+#define MY_NUMPORTS 3
+#define MY_BAUD_BASE (7372800 / 16)
+#define MY_INIT atomwide_serial_init
+#define MY_BASE_ADDRESS(ec) \
+	ecard_address ((ec), ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2)
+#define MY_PORT_ADDRESS(port,cardaddr) \
+	((cardaddr) + 0x200 - (port) * 0x100)
+#include "serial-card.c"
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/serial-card.c linux/drivers/acorn/char/serial-card.c
--- v2.1.100/linux/drivers/acorn/char/serial-card.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/serial-card.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,106 @@
+/*
+ * linux/arch/arm/drivers/char/serial-module.c
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * A generic handler of serial expansion cards that use 16550s or
+ * the like.
+ *
+ * Definitions:
+ *  MY_PRODS		Product numbers to identify this card by
+ *  MY_MANUS		Manufacturer numbers to identify this card by
+ *  MY_NUMPORTS		Number of ports per card
+ *  MY_BAUD_BASE	Baud base for the card
+ *  MY_INIT		Initialisation routine name
+ *  MY_BASE_ADDRESS(ec)	Return base address for ports
+ *  MY_PORT_ADDRESS
+ *	(port,cardaddr)	Return address for port using base address
+ *			from above.
+ *
+ * Changelog:
+ *  30-07-1996	RMK	Created
+ *  22-04-1998	RMK	Removed old register_pre_init_serial
+ */
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/errno.h>
+#include <asm/ecard.h>
+
+#ifndef NUM_SERIALS
+#define NUM_SERIALS	MY_NUMPORTS * MAX_ECARDS
+#endif
+
+#ifdef MODULE
+static int __serial_ports[NUM_SERIALS];
+static int __serial_pcount;
+static struct expansion_card *expcard[MAX_ECARDS];
+#define ADD_ECARD(ec,card) expcard[(card)] = (ec)
+#define ADD_PORT(port) __serial_ports[__serial_pcount++] = (port)
+#undef MY_INIT
+#define MY_INIT init_module
+#else
+#define ADD_ECARD(ec,card)
+#define ADD_PORT(port)
+#endif
+
+static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } };
+
+static inline int serial_register_onedev (unsigned long port, int irq)
+{
+    struct serial_struct req;
+
+    req.baud_base = MY_BAUD_BASE;
+    req.irq = irq;
+    req.port = port;
+
+    return register_serial(&req);
+}
+
+int MY_INIT (void)
+{
+    int card = 0;
+
+    ecard_startfind ();
+
+    do {
+	struct expansion_card *ec;
+	unsigned long cardaddr;
+	int port;
+
+	ec = ecard_find (0, serial_cids);
+	if (!ec)
+	    break;
+
+	cardaddr = MY_BASE_ADDRESS(ec);
+
+	for (port = 0; port < MY_NUMPORTS; port ++) {
+	    int line;
+
+	    line = serial_register_onedev (MY_PORT_ADDRESS(port, cardaddr), ec->irq);
+	    if (line < 0)
+		break;
+	    ADD_PORT(line);
+	}
+
+	if (port) {
+	    ecard_claim (ec);
+	    ADD_ECARD(ec, card);
+	} else
+	    break;
+    } while (++card < MAX_ECARDS);
+    return card ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+void cleanup_module (void)
+{
+    int i;
+
+    for (i = 0; i < __serial_pcount; i++)
+	unregister_serial (__serial_ports[i]);
+
+    for (i = 0; i < MAX_ECARDS; i++)
+	if (expcard[i])
+	    ecard_release (expcard[i]);
+}
+#endif
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/char/serial-dualsp.c linux/drivers/acorn/char/serial-dualsp.c
--- v2.1.100/linux/drivers/acorn/char/serial-dualsp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/serial-dualsp.c	Fri May  8 00:42:38 1998
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/arm/drivers/char/serial-dualsp.c
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  30-07-1996	RMK	Created
+ */
+#define MY_CARD_LIST { MANU_SERPORT, PROD_SERPORT_DSPORT }
+#define MY_NUMPORTS 2
+#define MY_BAUD_BASE (3686400 / 16)
+#define MY_INIT dualsp_serial_init
+#define MY_BASE_ADDRESS(ec) \
+	ecard_address (ec, ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2)
+#define MY_PORT_ADDRESS(port,cardaddress) \
+	((cardaddress) + (port) * 8)
+#include "serial-card.c"
+
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.1.100/linux/drivers/acorn/net/ether3.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/net/ether3.c	Fri May  8 00:42:38 1998
@@ -340,6 +340,23 @@
 	outw(priv->regs.command | CMD_RXON, REG_COMMAND);
 }
 
+static inline int
+ether3_probe_bus_8(struct device *dev, int val)
+{
+	outb(val & 255, REG_RECVPTR);
+	outb(val >> 8, REG_RECVPTR + 1);
+
+	return inb(REG_RECVPTR) == (val & 255) && inb(REG_RECVPTR + 1) == (val >> 8);
+}
+
+static inline int
+ether3_probe_bus_16(struct device *dev, int val)
+{
+	outw(val, REG_RECVPTR);
+
+	return inw(REG_RECVPTR) == val;
+}
+
 /*
  * This is the real probe routine.
  */
@@ -373,15 +390,14 @@
 	/* Test using Receive Pointer (16-bit register) to find out
 	 * how the ether3 is connected to the bus...
 	 */
-	outb(0, REG_RECVPTR);
-	outb(1, REG_RECVPTR + 1);
-
-	if (inb(REG_RECVPTR + 1) == 1) {
-		if (inb(REG_RECVPTR) == 0)
-			bus_type = BUS_8;
-		else if (inw(REG_RECVPTR) == 0x101)
-			bus_type = BUS_16;
-	}
+	if (ether3_probe_bus_8(dev, 0x100) &&
+	    ether3_probe_bus_8(dev, 0x201))
+		bus_type = BUS_8;
+
+	if (bus_type == BUS_UNKNOWN &&
+	    ether3_probe_bus_16(dev, 0x101) &&
+	    ether3_probe_bus_16(dev, 0x201))
+		bus_type = BUS_16;
 
 	switch (bus_type) {
 	case BUS_UNKNOWN:
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.1.100/linux/drivers/acorn/net/etherh.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/net/etherh.c	Fri May  8 00:42:38 1998
@@ -4,12 +4,15 @@
  * NS8390 ANT etherh specific driver
  *  For Acorn machines
  *
+ * Thanks to I-Cubed for information on their cards.
+ *
  * By Russell King.
  *
  * Changelog:
- *  08-Dec-1996	RMK	1.00	Created
+ *  08-12-1996	RMK	1.00	Created
  *		RMK	1.03	Added support for EtherLan500 cards
- *  23-Nov-1997	RMK	1.04	Added media autodetection
+ *  23-11-1997	RMK	1.04	Added media autodetection
+ *  16-04-1998	RMK	1.05	Improved media autodetection
  *
  * Insmod Module Parameters
  * ------------------------
@@ -54,7 +57,7 @@
 	{ 0xffff, 0xffff }
 };
 
-static char *version = "etherh [500/600/600A] ethernet driver (c) 1997 R.M.King v1.04\n";
+static char *version = "etherh [500/600/600A] ethernet driver (c) 1998 R.M.King v1.05\n";
 
 #define ETHERH500_DATAPORT	0x200	/* MEMC */
 #define ETHERH500_NS8390	0x000	/* MEMC */
@@ -66,6 +69,7 @@
 
 #define ETHERH_CP_IE		1
 #define ETHERH_CP_IF		2
+#define ETHERH_CP_HEARTBEAT	2
 
 #define ETHERH_TX_START_PAGE	1
 #define ETHERH_STOP_PAGE	0x7f
@@ -77,7 +81,7 @@
  * This is an ascii string...
  */
 static int
-etherh_addr (char *addr, struct expansion_card *ec)
+etherh_addr(char *addr, struct expansion_card *ec)
 {
 	struct in_chunk_dir cd;
 	char *s;
@@ -95,19 +99,80 @@
 	return ENODEV;
 }
 
+static void
+etherh_setif(struct device *dev)
+{
+	unsigned long addr;
+	unsigned long flags;
+
+	save_flags_cli(flags);
+
+	/* set the interface type */
+	switch (dev->mem_end) {
+	case PROD_I3_ETHERLAN600:
+	case PROD_I3_ETHERLAN600A:
+		addr = dev->base_addr + EN0_RCNTHI;
+
+		if (ei_status.interface_num)	/* 10b2 */
+			outb((inb(addr) & 0xf8) | 1, addr);
+		else				/* 10bT */
+			outb((inb(addr) & 0xf8), addr);
+		break;
+
+	case PROD_I3_ETHERLAN500:
+		addr = dev->rmem_start;
+
+		if (ei_status.interface_num)	/* 10b2 */
+			outb(inb(addr) & ~ETHERH_CP_IF, addr);
+		else				/* 10bT */
+			outb(inb(addr) | ETHERH_CP_IF, addr);
+		break;
+
+	default:
+		break;
+	}
+
+	restore_flags(flags);
+}
+
+static int
+etherh_getifstat(struct device *dev)
+{
+	int stat;
+
+	switch (dev->mem_end) {
+	case PROD_I3_ETHERLAN600:
+	case PROD_I3_ETHERLAN600A:
+		if (ei_status.interface_num)	/* 10b2 */
+			stat = 1;
+		else				/* 10bT */
+			stat = inb(dev->base_addr+EN0_RCNTHI) & 4;
+		break;
+
+	case PROD_I3_ETHERLAN500:
+		if (ei_status.interface_num)	/* 10b2 */
+			stat = 1;
+		else				/* 10bT */
+			stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT;
+		break;
+
+	default:
+		stat = 0;
+		break;
+	}
+
+	return stat != 0;
+}
+
 /*
  * Reset the 8390 (hard reset)
  */
 static void
-etherh_reset (struct device *dev)
+etherh_reset(struct device *dev)
 {
-	unsigned int addr = dev->base_addr;
-	int crb;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
 
-	if (dev->mem_end == PROD_I3_ETHERLAN600 || dev->mem_end == PROD_I3_ETHERLAN600A) {
-		crb = inb (addr + EN0_RCNTHI) & 0xf8;
-		outb (ei_status.interface_num ? crb | 1: crb, addr+EN0_RCNTHI);
-	}
+	etherh_setif(dev);
 }
 
 /*
@@ -262,9 +327,6 @@
 static int
 etherh_open(struct device *dev)
 {
-	unsigned int addr = dev->base_addr;
-	int crb;
-
 	MOD_INC_USE_COUNT;
 
 	if (request_irq(dev->irq, ei_interrupt, 0, "etherh", dev)) {
@@ -272,12 +334,8 @@
 		return -EAGAIN;
 	}
 
-	if (dev->mem_end == PROD_I3_ETHERLAN600 || dev->mem_end == PROD_I3_ETHERLAN600A) {
-		crb = inb (addr + EN0_RCNTHI) & 0xf8;
-		outb (ei_status.interface_num ? crb | 1: crb, addr+EN0_RCNTHI);
-	}
-
-	ei_open (dev);
+	etherh_reset(dev);
+	ei_open(dev);
 	return 0;
 }
 
@@ -302,7 +360,8 @@
 {
 	static int version_printed;
 	unsigned int addr, i, reg0, tmp;
-	char *dev_type;
+	const char *dev_type;
+	const char *if_type;
 
 	addr = dev->base_addr;
 
@@ -352,11 +411,10 @@
 		dev->name, dev_type, dev->base_addr, dev->irq);
 
 	for (i = 0; i < 6; i++)
-		printk (i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]);
+		printk (i == 5 ? "%2.2x " : "%2.2x:", dev->dev_addr[i]);
 
 	ei_status.name = "etherh";
 	ei_status.word16 = 1;
-	ei_status.interface_num = dev->if_port & 1;
 	ei_status.tx_start_page = ETHERH_TX_START_PAGE;
 	ei_status.rx_start_page = ei_status.tx_start_page + TX_PAGES;
 	ei_status.stop_page = ETHERH_STOP_PAGE;
@@ -367,20 +425,36 @@
 	dev->open = etherh_open;
 	dev->stop = etherh_close;
 
+	/* select 10bT */
+	ei_status.interface_num = 0;
+	if_type = "10BaseT";
+	etherh_setif(dev);
+	udelay(1000);
+	if (!etherh_getifstat(dev)) {
+		if_type = "10Base2";
+		ei_status.interface_num = 1;
+		etherh_setif(dev);
+	}
+	if (!etherh_getifstat(dev))
+		if_type = "UNKNOWN";
+
+	printk("%s\n", if_type);
+
+	etherh_reset(dev);
 	NS8390_init (dev, 0);
 	return 0;
 }
 
-static void etherh_irq_enable (ecard_t *ec, int irqnr)
+static void etherh_irq_enable(ecard_t *ec, int irqnr)
 {
 	unsigned int ctrl_addr = (unsigned int)ec->irq_data;
-	outb (inb (ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
+	outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
 }
 
-static void etherh_irq_disable (ecard_t *ec, int irqnr)
+static void etherh_irq_disable(ecard_t *ec, int irqnr)
 {
 	unsigned int ctrl_addr = (unsigned int)ec->irq_data;
-	outb (inb (ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
+	outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
 }
 
 static expansioncard_ops_t etherh_ops = {
@@ -401,6 +475,7 @@
 	case PROD_I3_ETHERLAN500:
 		dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390;
 		dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
+		dev->rmem_start = (unsigned long)
 		ec->irq_data   = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
 				  + ETHERH500_CTRLPORT;
 		break;
@@ -446,7 +521,6 @@
 
 static int io[MAX_ETHERH_CARDS];
 static int irq[MAX_ETHERH_CARDS];
-static int xcvr[MAX_ETHERH_CARDS] = { 1, 1 };
 static char ethernames[MAX_ETHERH_CARDS][9];
 static struct device *my_ethers[MAX_ETHERH_CARDS];
 static struct expansion_card *ec[MAX_ETHERH_CARDS];
@@ -490,7 +564,6 @@
 
 		dev->init = etherh_probe1;
 		dev->name = ethernames[i];
-		dev->if_port = xcvr[i];
 
 		my_ethers[i] = dev;
 
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/Config.in linux/drivers/acorn/scsi/Config.in
--- v2.1.100/linux/drivers/acorn/scsi/Config.in	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/Config.in	Fri May  8 00:42:39 1998
@@ -8,6 +8,7 @@
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   dep_tristate 'CumanaSCSI II support (Experimental)' CONFIG_SCSI_CUMANA_2 $CONFIG_SCSI
+  dep_tristate 'EESOX support (Experimental)' CONFIG_SCSI_EESOXSCSI $CONFIG_SCSI
   dep_tristate 'PowerTec support (Experimental)' CONFIG_SCSI_POWERTECSCSI $CONFIG_SCSI
 
   comment 'The following drives are not fully supported'
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/Makefile linux/drivers/acorn/scsi/Makefile
--- v2.1.100/linux/drivers/acorn/scsi/Makefile	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/Makefile	Fri May  8 00:42:39 1998
@@ -72,6 +72,18 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_EESOXSCSI),y)
+  L_OBJS += eesox.o
+  CONFIG_QUEUE_BUILTIN=y
+  CONFIG_FAS216_BUILTIN=y
+else
+  ifeq ($(CONFIG_SCSI_EESOXSCSI),m)
+    M_OBJS += eesox.o
+    CONFIG_QUEUE_MODULE=y
+    CONFIG_FAS216_MODULE=y
+  endif
+endif
+
 ifeq ($(CONFIG_QUEUE_BUILTIN),y)
   LX_OBJS += queue.o msgqueue.o
 else
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c
--- v2.1.100/linux/drivers/acorn/scsi/acornscsi.c	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/acornscsi.c	Fri May  8 00:42:39 1998
@@ -2726,7 +2726,7 @@
 
     p = string;
     
-    p += sprintf (string, "%s at port %X irq %d v%d.%d.%d"
+    p += sprintf (string, "%s at port %lX irq %d v%d.%d.%d"
 #ifdef CONFIG_SCSI_ACORNSCSI_SYNC
     " SYNC"
 #endif
@@ -2784,12 +2784,12 @@
 			host->dma.io_port, host->scsi.irq);
 #endif
 
-    p += sprintf (p,	"Statistics:\n",
-			"Queued commands: %-10d    Issued commands: %-10d\n"
-			"Done commands  : %-10d    Reads          : %-10d\n"
-			"Writes         : %-10d    Others         : %-10d\n"
-			"Disconnects    : %-10d    Aborts         : %-10d\n"
-			"Resets         : %-10d\n\nLast phases:",
+    p += sprintf (p,	"Statistics:\n"
+			"Queued commands: %-10u    Issued commands: %-10u\n"
+			"Done commands  : %-10u    Reads          : %-10u\n"
+			"Writes         : %-10u    Others         : %-10u\n"
+			"Disconnects    : %-10u    Aborts         : %-10u\n"
+			"Resets         : %-10u\n\nLast phases:",
 			host->stats.queues,		host->stats.removes,
 			host->stats.fins,		host->stats.reads,
 			host->stats.writes,		host->stats.miscs,
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c
--- v2.1.100/linux/drivers/acorn/scsi/cumana_1.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/cumana_1.c	Fri May  8 00:42:39 1998
@@ -34,6 +34,11 @@
 
 /*
  * $Log: cumana_1.c,v $
+ * Revision 1.3  1998/05/03 20:45:32  alan
+ * ARM SCSI update. This adds the eesox driver and massively updates the
+ * Cumana driver. The folks who bought cumana arent anal retentive all
+ * docs are secret weenies so now there are docs ..
+ *
  * Revision 1.2  1998/03/08 05:49:46  davem
  * Merge to 2.1.89
  *
@@ -134,7 +139,7 @@
 	    printk("scsi%d: please jumper the board for a free IRQ.\n", instance->host_no);
 	}
 
-	printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
+	printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
 	if (instance->irq == IRQ_NONE)
 	    printk ("s disabled");
 	else
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c
--- v2.1.100/linux/drivers/acorn/scsi/cumana_2.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/cumana_2.c	Fri May  8 00:42:39 1998
@@ -1,15 +1,13 @@
 /*
  * linux/arch/arm/drivers/scsi/cumana_2.c
  *
- * Copyright (C) 1997,1998 Russell King
- *
- * This driver is based on experimentation.  Hence, it may have made
- * assumptions about the particular card that I have available, and
- * may not be reliable!
+ * Copyright (C) 1997-1998 Russell King
  *
  * Changelog:
  *  30-08-1997	RMK	0.0.0	Created, READONLY version
  *  22-01-1998	RMK	0.0.1	Updated to 2.1.80
+ *  15-04-1998	RMK	0.0.1	Only do PIO if FAS216 will allow it.
+ *  02-05-1998	RMK	0.0.2	Updated & added DMA support
  */
 
 #include <linux/module.h>
@@ -23,352 +21,556 @@
 #include <linux/stat.h>
 
 #include <asm/delay.h>
+#include <asm/dma.h>
+#include <asm/ecard.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/ecard.h>
+#include <asm/pgtable.h>
 
 #include "../../scsi/sd.h"
 #include "../../scsi/hosts.h"
 #include "cumana_2.h"
-#include "fas216.h"
-
-/* Hmm - this should go somewhere else */
-#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
 
 /* Configuration */
-#define XTALFREQ		40
-#define INT_POLARITY		CTRL_INT_HIGH
+#define CUMANASCSI2_XTALFREQ		40
+#define CUMANASCSI2_ASYNC_PERIOD	200
+#define CUMANASCSI2_SYNC_DEPTH		8
 
 /*
  * List of devices that the driver will recognise
  */
-#define CUMANASCSI2_LIST	{ MANU_CUMANA, PROD_CUMANA_SCSI_2 }
+#define CUMANASCSI2_LIST		{ MANU_CUMANA, PROD_CUMANA_SCSI_2 }
+
+#define CUMANASCSI2_STATUS		(0)
+#define STATUS_INT			(1 << 0)
+#define STATUS_DRQ			(1 << 1)
+#define STATUS_LATCHED			(1 << 3)
+
+#define CUMANASCSI2_ALATCH		(5)
+#define ALATCH_ENA_INT			(3)
+#define ALATCH_DIS_INT			(2)
+#define ALATCH_ENA_TERM			(5)
+#define ALATCH_DIS_TERM			(4)
+#define ALATCH_ENA_BIT32		(11)
+#define ALATCH_DIS_BIT32		(10)
+#define ALATCH_ENA_DMA			(13)
+#define ALATCH_DIS_DMA			(12)
+#define ALATCH_DMA_OUT			(15)
+#define ALATCH_DMA_IN			(14)
+
+#define CUMANASCSI2_PSEUDODMA		(0x80)
+
+#define CUMANASCSI2_FAS216_OFFSET	(0xc0)
+#define CUMANASCSI2_FAS216_SHIFT	0
 
 /*
  * Version
  */
 #define VER_MAJOR	0
 #define VER_MINOR	0
-#define VER_PATCH	1
+#define VER_PATCH	2
 
 static struct expansion_card *ecs[MAX_ECARDS];
 
+/*
+ * Use term=0,1,0,0,0 to turn terminators on/off
+ */
+int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
+
 static struct proc_dir_entry proc_scsi_cumanascsi_2 = {
 	PROC_SCSI_QLOGICFAS, 6, "cumanascs2",
 	S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
-/*
- * Function: void cumanascsi_2_intr (int irq, void *dev_id, struct pt_regs *regs)
- * Purpose : handle interrupts from Cumana SCSI 2 card
- * Params  : irq - interrupt number
- *	     dev_id - user-defined (Scsi_Host structure)
- *	     regs - processor registers at interrupt
+/* Prototype: void cumanascsi_2_irqenable(ec, irqnr)
+ * Purpose  : Enable interrupts on Cumana SCSI 2 card
+ * Params   : ec    - expansion card structure
+ *          : irqnr - interrupt number
  */
-static void cumanascsi_2_intr (int irq, void *dev_id, struct pt_regs *regs)
+static void
+cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr)
 {
-    struct Scsi_Host *instance = (struct Scsi_Host *)dev_id;
+	unsigned int port = (unsigned int)ec->irq_data;
+	outb(ALATCH_ENA_INT, port);
+}
 
-    fas216_intr (instance);
+/* Prototype: void cumanascsi_2_irqdisable(ec, irqnr)
+ * Purpose  : Disable interrupts on Cumana SCSI 2 card
+ * Params   : ec    - expansion card structure
+ *          : irqnr - interrupt number
+ */
+static void
+cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr)
+{
+	unsigned int port = (unsigned int)ec->irq_data;
+	outb(ALATCH_DIS_INT, port);
 }
 
-/*
- * Function: int cumanascsi_2_dma_setup (instance, SCpnt, direction)
- * Purpose : initialises DMA/PIO
- * Params  : instance  - host
- *	     SCpnt     - command
- *	     direction - DMA on to/off of card
- * Returns : 0 if we should not set CMD_WITHDMA for transfer info command
- */
-static fasdmatype_t cumanascsi_2_dma_setup (struct Scsi_Host *instance, Scsi_Pointer *SCp, fasdmadir_t direction)
-{
-    /*
-     * We don't do DMA
-     */
-    return fasdma_pseudo;
+static const expansioncard_ops_t cumanascsi_2_ops = {
+	cumanascsi_2_irqenable,
+	cumanascsi_2_irqdisable,
+	NULL,
+	NULL
+};
+
+/* Prototype: void cumanascsi_2_terminator_ctl(host, on_off)
+ * Purpose  : Turn the Cumana SCSI 2 terminators on or off
+ * Params   : host   - card to turn on/off
+ *          : on_off - !0 to turn on, 0 to turn off
+ */
+static void
+cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off)
+{
+	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+
+	if (on_off) {
+		info->terms = 1;
+		outb (ALATCH_ENA_TERM, info->alatch);
+	} else {
+		info->terms = 0;
+		outb (ALATCH_DIS_TERM, info->alatch);
+	}
 }
 
-/*
- * Function: int cumanascsi_2_dma_pseudo (instance, SCpnt, direction, transfer)
- * Purpose : handles pseudo DMA
- * Params  : instance  - host
- *	     SCpnt     - command
- *	     direction - DMA on to/off of card
- *	     transfer  - minimum number of bytes we expect to transfer
- * Returns : bytes transfered
+/* Prototype: void cumanascsi_2_intr(irq, *dev_id, *regs)
+ * Purpose  : handle interrupts from Cumana SCSI 2 card
+ * Params   : irq    - interrupt number
+ *	      dev_id - user-defined (Scsi_Host structure)
+ *	      regs   - processor registers at interrupt
  */
-static int
-cumanascsi_2_dma_pseudo (struct Scsi_Host *instance, Scsi_Pointer *SCp,
-			 fasdmadir_t direction, int transfer)
+static void
+cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-    CumanaScsi2_Info *info = (CumanaScsi2_Info *)instance->hostdata;
-    unsigned int length;
-    unsigned char *addr;
+	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
 
-    length = SCp->this_residual;
-    addr = SCp->ptr;
+	fas216_intr(host);
+}
 
-    if (direction == DMA_OUT)
-#if 0
-	while (length > 1) {
-	    unsigned long word;
+static void
+cumanascsi_2_invalidate(char *addr, long len, fasdmadir_t direction)
+{
+	unsigned int page;
 
+	if (direction == DMA_OUT) {
+		for (page = (unsigned int) addr; len > 0;
+		     page += PAGE_SIZE, len -= PAGE_SIZE)
+			flush_page_to_ram(page);
+	} else
+		flush_cache_range(current->mm, (unsigned long)addr,
+				  (unsigned long)addr + len);
+}
 
-	    if (inb (REG_STAT(&info->info)) & STAT_INT)
-		goto end;
+/* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type)
+ * Purpose  : initialises DMA/PIO
+ * Params   : host      - host
+ *	      SCpnt     - command
+ *	      direction - DMA on to/off of card
+ *	      min_type  - minimum DMA support that we must have for this transfer
+ * Returns  : type of transfer to be performed
+ */
+static fasdmatype_t
+cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
+		       fasdmadir_t direction, fasdmatype_t min_type)
+{
+	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	int dmach = host->dma_channel;
 
-	    if (!(inb (info->cstatus) & CSTATUS_DRQ))
-		continue;
+	outb(ALATCH_DIS_DMA, info->alatch);
 
-	    word = *addr | (*addr + 1) << 8;
-	    outw (info->dmaarea);
-	    addr += 2;
-	    length -= 2;
+	if (dmach != NO_DMA &&
+	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
+		int buf;
+
+		for (buf = 1; buf <= SCp->buffers_residual &&
+			      buf < NR_SG; buf++) {
+			info->dmasg[buf].address = __virt_to_bus(
+				(unsigned long)SCp->buffer[buf].address);
+			info->dmasg[buf].length = SCp->buffer[buf].length;
+
+			cumanascsi_2_invalidate(SCp->buffer[buf].address,
+						SCp->buffer[buf].length,
+						direction);
+		}
+
+		info->dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr);
+		info->dmasg[0].length = SCp->this_residual;
+		cumanascsi_2_invalidate(SCp->ptr,
+					SCp->this_residual, direction);
+
+		disable_dma(dmach);
+		set_dma_sg(dmach, info->dmasg, buf);
+		if (direction == DMA_OUT) {
+			outb(ALATCH_DMA_OUT, info->alatch);
+			set_dma_mode(dmach, DMA_MODE_WRITE);
+		} else {
+			outb(ALATCH_DMA_IN, info->alatch);
+			set_dma_mode(dmach, DMA_MODE_READ);
+		}
+		enable_dma(dmach);
+		outb(ALATCH_ENA_DMA, info->alatch);
+		outb(ALATCH_DIS_BIT32, info->alatch);
+		return fasdma_real_all;
 	}
-#else
-	printk ("PSEUDO_OUT???\n");
-#endif
-    else {
-	if (transfer && (transfer & 255)) {
-	    while (length >= 256) {
-		if (inb (REG_STAT(&info->info)) & STAT_INT)
-		    goto end;
-	    
-		if (!(inb (info->cstatus) & CSTATUS_DRQ))
-		    continue;
 
-		insw (info->dmaarea, addr, 256 >> 1);
-		addr += 256;
-		length -= 256;
-	    }
-	}
+	/*
+	 * If we're not doing DMA,
+	 *  we'll do pseudo DMA
+	 */
+	return fasdma_pio;
+}
+
+/*
+ * Prototype: void cumanascsi_2_dma_pseudo(host, SCpnt, direction, transfer)
+ * Purpose  : handles pseudo DMA
+ * Params   : host      - host
+ *	      SCpnt     - command
+ *	      direction - DMA on to/off of card
+ *	      transfer  - minimum number of bytes we expect to transfer
+ */
+static void
+cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
+			fasdmadir_t direction, int transfer)
+{
+	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	unsigned int length;
+	unsigned char *addr;
+
+	length = SCp->this_residual;
+	addr = SCp->ptr;
 
-	while (length > 0) {
-	    unsigned long word;
+	if (direction == DMA_OUT)
+#if 0
+		while (length > 1) {
+			unsigned long word;
+			unsigned int status = inb(info->status);
+
+			if (status & STATUS_INT)
+				goto end;
+
+			if (!(status & STATUS_DRQ))
+				continue;
+
+			word = *addr | (*addr + 1) << 8;
+			outw (info->dmaarea);
+			addr += 2;
+			length -= 2;
+		}
+#else
+		printk ("PSEUDO_OUT???\n");
+#endif
+	else {
+		if (transfer && (transfer & 255)) {
+			while (length >= 256) {
+				unsigned int status = inb(info->status);
 
-	    if (inb (REG_STAT(&info->info)) & STAT_INT)
-		goto end;
+				if (status & STATUS_INT)
+					goto end;
 	    
-	    if (!(inb (info->cstatus) & CSTATUS_DRQ))
-		continue;
+				if (!(status & STATUS_DRQ))
+					continue;
 
-	    word = inw (info->dmaarea);
-	    *addr++ = word;
-	    if (--length > 0) {
-		*addr++ = word >> 8;
-		length --;
-	    }
+				insw(info->dmaarea, addr, 256 >> 1);
+				addr += 256;
+				length -= 256;
+			}
+		}
+
+		while (length > 0) {
+			unsigned long word;
+			unsigned int status = inb(info->status);
+
+			if (status & STATUS_INT)
+				goto end;
+
+			if (!(status & STATUS_DRQ))
+				continue;
+
+			word = inw (info->dmaarea);
+			*addr++ = word;
+			if (--length > 0) {
+				*addr++ = word >> 8;
+				length --;
+			}
+		}
 	}
-    }
 
 end:
-    return SCp->this_residual - length;
 }
 
-/*
- * Function: int cumanascsi_2_dma_stop (instance, SCpnt)
- * Purpose : stops DMA/PIO
- * Params  : instance  - host
- *	     SCpnt     - command
- */
-static void cumanascsi_2_dma_stop (struct Scsi_Host *instance, Scsi_Pointer *SCp)
-{
-    /*
-     * no DMA to stop
-     */
+/* Prototype: int cumanascsi_2_dma_stop(host, SCpnt)
+ * Purpose  : stops DMA/PIO
+ * Params   : host  - host
+ *	      SCpnt - command
+ */
+static void
+cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
+{
+	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	if (host->dma_channel != NO_DMA) {
+		outb(ALATCH_DIS_DMA, info->alatch);
+		disable_dma(host->dma_channel);
+	}
 }
 
-/*
- * Function: int cumanascsi_2_detect (Scsi_Host_Template * tpnt)
- * Purpose : initialises Cumana SCSI 2 driver
- * Params  : tpnt - template for this SCSI adapter
- * Returns : >0 if host found, 0 otherwise.
- */
-int cumanascsi_2_detect (Scsi_Host_Template *tpnt)
-{
-    static const card_ids cumanascsi_2_cids[] = { CUMANASCSI2_LIST, { 0xffff, 0xffff} };
-    int count = 0;
-    struct Scsi_Host *instance;
+/* Prototype: int cumanascsi_2_detect(Scsi_Host_Template * tpnt)
+ * Purpose  : initialises Cumana SCSI 2 driver
+ * Params   : tpnt - template for this SCSI adapter
+ * Returns  : >0 if host found, 0 otherwise.
+ */
+int
+cumanascsi_2_detect(Scsi_Host_Template *tpnt)
+{
+	static const card_ids cumanascsi_2_cids[] =
+			{ CUMANASCSI2_LIST, { 0xffff, 0xffff} };
+	int count = 0;
+	struct Scsi_Host *host;
   
-    tpnt->proc_dir = &proc_scsi_cumanascsi_2;
-    memset (ecs, 0, sizeof (ecs));
+	tpnt->proc_dir = &proc_scsi_cumanascsi_2;
+	memset(ecs, 0, sizeof (ecs));
 
-    ecard_startfind ();
+	ecard_startfind();
 
-    while (1) {
-    	CumanaScsi2_Info *info;
+	while (1) {
+	    	CumanaScsi2_Info *info;
 
-	ecs[count] = ecard_find (0, cumanascsi_2_cids);
-	if (!ecs[count])
-	    break;
+		ecs[count] = ecard_find(0, cumanascsi_2_cids);
+		if (!ecs[count])
+			break;
+
+		ecard_claim(ecs[count]);
+
+		host = scsi_register(tpnt, sizeof (CumanaScsi2_Info));
+		if (!host) {
+			ecard_release(ecs[count]);
+			break;
+		}
+
+		host->io_port = ecard_address(ecs[count], ECARD_MEMC, 0);
+		host->irq = ecs[count]->irq;
+		host->dma_channel = ecs[count]->dma;
+		info = (CumanaScsi2_Info *)host->hostdata;
+
+		info->terms			= term[count] ? 1 : 0;
+		cumanascsi_2_terminator_ctl(host, info->terms);
+
+		info->info.scsi.io_port		= host->io_port + CUMANASCSI2_FAS216_OFFSET;
+		info->info.scsi.io_shift	= CUMANASCSI2_FAS216_SHIFT;
+		info->info.scsi.irq		= host->irq;
+		info->info.ifcfg.clockrate	= CUMANASCSI2_XTALFREQ;
+		info->info.ifcfg.select_timeout	= 255;
+		info->info.ifcfg.asyncperiod	= CUMANASCSI2_ASYNC_PERIOD;
+		info->info.ifcfg.sync_max_depth	= CUMANASCSI2_SYNC_DEPTH;
+		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+		info->info.dma.setup		= cumanascsi_2_dma_setup;
+		info->info.dma.pseudo		= cumanascsi_2_dma_pseudo;
+		info->info.dma.stop		= cumanascsi_2_dma_stop;
+		info->dmaarea			= host->io_port + CUMANASCSI2_PSEUDODMA;
+		info->status			= host->io_port + CUMANASCSI2_STATUS;
+		info->alatch			= host->io_port + CUMANASCSI2_ALATCH;
+
+		ecs[count]->irqaddr	= (unsigned char *)ioaddr(info->status);
+		ecs[count]->irqmask	= STATUS_INT;
+		ecs[count]->irq_data	= (void *)info->alatch;
+		ecs[count]->ops		= (expansioncard_ops_t *)&cumanascsi_2_ops;
+
+		request_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
+			       16 << CUMANASCSI2_FAS216_SHIFT, "cumanascsi2-fas");
+
+		if (host->irq != NO_IRQ &&
+		    request_irq(host->irq, cumanascsi_2_intr,
+				SA_INTERRUPT, "cumanascsi2", host)) {
+			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
+			       host->host_no, host->irq);
+			host->irq = NO_IRQ;
+			info->info.scsi.irq = NO_IRQ;
+		}
+
+		if (host->dma_channel != NO_DMA &&
+		    request_dma(host->dma_channel, "cumanascsi2")) {
+			printk("scsi%d: DMA%d not free, DMA disabled\n",
+			       host->host_no, host->dma_channel);
+			host->dma_channel = NO_DMA;
+		}
 
-	ecard_claim (ecs[count]);
-
-	instance = scsi_register (tpnt, sizeof (CumanaScsi2_Info));
-	if (!instance) {
-	    ecard_release (ecs[count]);
-	    break;
+		fas216_init(host);
+		++count;
 	}
+	return count;
+}
 
-	instance->io_port = ecard_address (ecs[count], ECARD_MEMC, 0);
-	instance->irq = ecs[count]->irq;
-
-	ecs[count]->irqaddr = (unsigned char *)BUS_ADDR(instance->io_port);
-	ecs[count]->irqmask = CSTATUS_IRQ;
+/* Prototype: int cumanascsi_2_release(struct Scsi_Host * host)
+ * Purpose  : releases all resources used by this adapter
+ * Params   : host - driver host structure to return info for.
+ */
+int cumanascsi_2_release(struct Scsi_Host *host)
+{
+	int i;
 
-	request_region (instance->io_port      ,  1, "cumanascsi2-stat");
-	request_region (instance->io_port + 128, 64, "cumanascsi2-dma");
-	request_region (instance->io_port + 192, 16, "cumanascsi2-fas");
-	if (request_irq (instance->irq, cumanascsi_2_intr, SA_INTERRUPT, "cumanascsi2", instance)) {
-	    printk ("scsi%d: IRQ%d not free, interrupts disabled\n",
-		      instance->host_no, instance->irq);
-	}
+	fas216_release(host);
 
-	info = (CumanaScsi2_Info *)instance->hostdata;
-	info->info.scsi.io_port	= instance->io_port + 192;
-	info->info.scsi.irq	= instance->irq;
-	info->info.ifcfg.clockrate = XTALFREQ;
-	info->info.ifcfg.select_timeout = 255;
-	info->info.dma.setup	= cumanascsi_2_dma_setup;
-	info->info.dma.pseudo	= cumanascsi_2_dma_pseudo;
-	info->info.dma.stop	= cumanascsi_2_dma_stop;
-	info->dmaarea		= instance->io_port + 128;
-	info->cstatus		= instance->io_port;
-
-	fas216_init (instance);
-	++count;
-    }
-    return count;
+	if (host->irq != NO_IRQ)
+		free_irq(host->irq, host);
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	release_region(host->io_port + CUMANASCSI2_FAS216_OFFSET,
+		       16 << CUMANASCSI2_FAS216_SHIFT);
+
+	for (i = 0; i < MAX_ECARDS; i++)
+		if (ecs[i] && host->io_port == ecard_address (ecs[i], ECARD_MEMC, 0))
+			ecard_release (ecs[i]);
+	return 0;
 }
 
-/*
- * Function: int cumanascsi_2_release (struct Scsi_Host * host)
- * Purpose : releases all resources used by this adapter
- * Params  : host - driver host structure to return info for.
- * Returns : nothing
- */
-int cumanascsi_2_release (struct Scsi_Host *instance)
-{
-    int i;
-
-    fas216_release (instance);
-
-    if (instance->irq != 255)
-	free_irq (instance->irq, instance);
-    release_region (instance->io_port, 1);
-    release_region (instance->io_port + 128, 32);
-    release_region (instance->io_port + 192, 16);
-
-    for (i = 0; i < MAX_ECARDS; i++)
-	if (ecs[i] && instance->io_port == ecard_address (ecs[i], ECARD_MEMC, 0))
-		ecard_release (ecs[i]);
-    return 0;
+/* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host)
+ * Purpose  : returns a descriptive string about this interface,
+ * Params   : host - driver host structure to return info for.
+ * Returns  : pointer to a static buffer containing null terminated string.
+ */
+const char *cumanascsi_2_info(struct Scsi_Host *host)
+{
+	CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
+	static char string[100], *p;
+
+	p = string;
+	p += sprintf(string, "%s at port %lX ",
+		     host->hostt->name, host->io_port);
+
+	if (host->irq != NO_IRQ)
+		p += sprintf(p, "irq %d ", host->irq);
+	else
+		p += sprintf(p, "NO IRQ ");
+
+	if (host->dma_channel != NO_DMA)
+		p += sprintf(p, "dma %d ", host->dma_channel);
+	else
+		p += sprintf(p, "NO DMA ");
+
+	p += sprintf(p, "v%d.%d.%d scsi %s",
+		     VER_MAJOR, VER_MINOR, VER_PATCH,
+		     info->info.scsi.type);
+
+	p += sprintf(p, " terminators %s",
+		     info->terms ? "on" : "off");
+
+	return string;
 }
 
-/*
- * Function: const char *cumanascsi_2_info (struct Scsi_Host * host)
- * Purpose : returns a descriptive string about this interface,
- * Params  : host - driver host structure to return info for.
- * Returns : pointer to a static buffer containing null terminated string.
- */
-const char *cumanascsi_2_info (struct Scsi_Host *host)
-{
-    CumanaScsi2_Info *info = (CumanaScsi2_Info *)host->hostdata;
-    static char string[100], *p;
-
-    p = string;
-    p += sprintf (string, "%s at port %X irq %d v%d.%d.%d scsi %s",
-		  host->hostt->name, host->io_port, host->irq,
-		  VER_MAJOR, VER_MINOR, VER_PATCH,
-		  info->info.scsi.type);
+/* Prototype: int cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
+ * Purpose  : Set a driver specific function
+ * Params   : host   - host to setup
+ *          : buffer - buffer containing string describing operation
+ *          : length - length of string
+ * Returns  : -EINVAL, or 0
+ */
+static int
+cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	int ret = length;
 
-    return string;
+	if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) {
+		buffer += 11;
+		length -= 11;
+
+		if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
+			if (buffer[5] == '1')
+				cumanascsi_2_terminator_ctl(host, 1);
+			else if (buffer[5] == '0')
+				cumanascsi_2_terminator_ctl(host, 0);
+			else
+				ret = -EINVAL;
+		} else
+			ret = -EINVAL;
+	} else
+		ret = -EINVAL;
+
+	return ret;
 }
 
-/*
- * Function: int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
+/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset,
  *					 int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- *	     the /proc filesystem.
- * Params  : buffer - a buffer to write information to
- *	     start  - a pointer into this buffer set by this routine to the start
- *		      of the required information.
- *	     offset - offset into information that we have read upto.
- *	     length - length of buffer
- *	     host_no - host number to return information for
- *	     inout  - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
+ * Purpose  : Return information about the driver to a user process accessing
+ *	      the /proc filesystem.
+ * Params   : buffer - a buffer to write information to
+ *	      start  - a pointer into this buffer set by this routine to the start
+ *		       of the required information.
+ *	      offset - offset into information that we have read upto.
+ *	      length - length of buffer
+ *	      host_no - host number to return information for
+ *	      inout  - 0 for reading, 1 for writing.
+ * Returns  : length of data written to buffer.
  */
 int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
 			    int length, int host_no, int inout)
 {
-    int pos, begin;
-    struct Scsi_Host *host = scsi_hostlist;
-    CumanaScsi2_Info *info;
-    Scsi_Device *scd;
-
-    while (host) {
-	if (host->host_no == host_no)
-	    break;
-	host = host->next;
-    }
-    if (!host)
-	return 0;
+	int pos, begin;
+	struct Scsi_Host *host = scsi_hostlist;
+	CumanaScsi2_Info *info;
+	Scsi_Device *scd;
+
+	while (host) {
+		if (host->host_no == host_no)
+			break;
+		host = host->next;
+	}
+	if (!host)
+		return 0;
 
-    info = (CumanaScsi2_Info *)host->hostdata;
-    if (inout == 1)
-      return -EINVAL;
+	if (inout == 1)
+		return cumanascsi_2_set_proc_info(host, buffer, length);
 
-    begin = 0;
-    pos = sprintf (buffer,
+	info = (CumanaScsi2_Info *)host->hostdata;
+
+	begin = 0;
+	pos = sprintf(buffer,
 			"Cumana SCSI II driver version %d.%d.%d\n",
 			VER_MAJOR, VER_MINOR, VER_PATCH);
-    pos += sprintf (buffer + pos,
-			"Address: %08X          IRQ : %d\n"
-			"FAS    : %s\n\n"
+	pos += sprintf(buffer + pos,
+			"Address: %08lX    IRQ : %d     DMA : %d\n"
+			"FAS    : %-10s  TERM: %-3s\n\n"
 			"Statistics:\n",
-			host->io_port, host->irq, info->info.scsi.type);
+			host->io_port, host->irq, host->dma_channel,
+			info->info.scsi.type, info->terms ? "on" : "off");
 
-    pos += sprintf (buffer+pos,
-			"Queued commands: %-10ld   Issued commands: %-10ld\n"
-			"Done commands  : %-10ld   Reads          : %-10ld\n"
-			"Writes         : %-10ld   Others         : %-10ld\n"
-			"Disconnects    : %-10ld   Aborts         : %-10ld\n"
-			"Resets         : %-10ld\n",
-			 info->info.stats.queues,      info->info.stats.removes,
-			 info->info.stats.fins,        info->info.stats.reads,
-			 info->info.stats.writes,      info->info.stats.miscs,
-			 info->info.stats.disconnects, info->info.stats.aborts,
-			 info->info.stats.resets);
-
-    pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none");
-
-    for (scd = host->host_queue; scd; scd = scd->next) {
-	int len;
-
-	proc_print_scsidevice (scd, buffer, &len, pos);
-	pos += len;
-	pos += sprintf (buffer+pos, "Extensions: ");
-	if (scd->tagged_supported)
-	    pos += sprintf (buffer+pos, "TAG %sabled [%d] ",
-			    scd->tagged_queue ? "en" : "dis",
-			    scd->current_tag);
-	pos += sprintf (buffer+pos, "\n");
-
-	if (pos + begin < offset) {
-	    begin += pos;
-	    pos = 0;
+	pos += sprintf(buffer+pos,
+			"Queued commands: %-10u   Issued commands: %-10u\n"
+			"Done commands  : %-10u   Reads          : %-10u\n"
+			"Writes         : %-10u   Others         : %-10u\n"
+			"Disconnects    : %-10u   Aborts         : %-10u\n"
+			"Resets         : %-10u\n",
+			info->info.stats.queues,      info->info.stats.removes,
+			info->info.stats.fins,        info->info.stats.reads,
+			info->info.stats.writes,      info->info.stats.miscs,
+			info->info.stats.disconnects, info->info.stats.aborts,
+			info->info.stats.resets);
+
+	pos += sprintf(buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none");
+
+	for (scd = host->host_queue; scd; scd = scd->next) {
+		int len;
+
+		proc_print_scsidevice(scd, buffer, &len, pos);
+		pos += len;
+		pos += sprintf(buffer+pos, "Extensions: ");
+		if (scd->tagged_supported)
+			pos += sprintf(buffer+pos, "TAG %sabled [%d] ",
+				       scd->tagged_queue ? "en" : "dis",
+				       scd->current_tag);
+		pos += sprintf(buffer+pos, "\n");
+
+		if (pos + begin < offset) {
+			begin += pos;
+			pos = 0;
+		}
+		if (pos + begin > offset + length)
+			break;
 	}
-	if (pos + begin > offset + length)
-	    break;
-    }
-
-    *start = buffer + (offset - begin);
-    pos -= offset - begin;
-    if (pos > length)
-	pos = length;
 
-    return pos;
+	*start = buffer + (offset - begin);
+	pos -= offset - begin;
+	if (pos > length)
+		pos = length;
+
+	return pos;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/cumana_2.h linux/drivers/acorn/scsi/cumana_2.h
--- v2.1.100/linux/drivers/acorn/scsi/cumana_2.h	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/cumana_2.h	Fri May  8 00:42:39 1998
@@ -1,7 +1,7 @@
 /*
  * Cumana SCSI II driver
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1998 Russell King
  */
 #ifndef CUMANA_2_H
 #define CUMANA_2_H
@@ -57,12 +57,19 @@
 
 #ifndef HOSTS_C
 
+#include <asm/dma.h>
+
+#define NR_SG	256
+
 typedef struct {
-    FAS216_Info info;
+	FAS216_Info info;
 
-    /* other info... */
-    unsigned int	cstatus;	/* card status register	*/
-    unsigned int	dmaarea;	/* Pseudo DMA area	*/
+	/* other info... */
+	unsigned int	status;		/* card status register	*/
+	unsigned int	alatch;		/* Control register	*/
+	unsigned int	terms;		/* Terminator state	*/
+	unsigned int	dmaarea;	/* Pseudo DMA area	*/
+	dmasg_t		dmasg[NR_SG];	/* Scatter DMA list	*/
 } CumanaScsi2_Info;
 
 #define CSTATUS_IRQ	(1 << 0)
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c
--- v2.1.100/linux/drivers/acorn/scsi/eesox.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/scsi/eesox.c	Fri May  8 00:42:39 1998
@@ -0,0 +1,582 @@
+/*
+ * linux/arch/arm/drivers/scsi/eesox.c
+ *
+ * Copyright (C) 1997-1998 Russell King
+ *
+ * This driver is based on experimentation.  Hence, it may have made
+ * assumptions about the particular card that I have available, and
+ * may not be reliable!
+ *
+ * Changelog:
+ *  01-10-1997	RMK	Created, READONLY version
+ *  15-02-1998	RMK	READ/WRITE version
+ *			added DMA support and hardware definitions
+ *  14-03-1998	RMK	Updated DMA support
+ *			Added terminator control
+ *  15-04-1998	RMK	Only do PIO if FAS216 will allow it.
+ */
+
+#include <linux/module.h>
+#include <linux/blk.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/unistd.h>
+#include <linux/stat.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/ecard.h>
+#include <asm/pgtable.h>
+
+#include "../../scsi/sd.h"
+#include "../../scsi/hosts.h"
+#include "eesox.h"
+
+#define NO_IRQ	255
+#define NO_DMA	255
+
+/* Configuration */
+#define EESOX_XTALFREQ		40
+#define EESOX_ASYNC_PERIOD	200
+#define EESOX_SYNC_DEPTH	7
+
+/*
+ * List of devices that the driver will recognise
+ */
+#define EESOXSCSI_LIST	{ MANU_EESOX, PROD_EESOX_SCSI2 }
+
+#define EESOX_FAS216_OFFSET	0xc00
+#define EESOX_FAS216_SHIFT	3
+
+#define EESOX_STATUS		0xa00
+#define EESOX_STAT_INTR		0x01
+#define EESOX_STAT_DMA		0x02
+
+#define EESOX_CONTROL		0xa00
+#define EESOX_INTR_ENABLE	0x04
+#define EESOX_TERM_ENABLE	0x02
+#define EESOX_RESET		0x01
+
+#define EESOX_DMA_OFFSET	0xe00
+
+/*
+ * Version
+ */
+#define VER_MAJOR	0
+#define VER_MINOR	0
+#define VER_PATCH	2
+
+static struct expansion_card *ecs[MAX_ECARDS];
+
+/*
+ * Use term=0,1,0,0,0 to turn terminators on/off
+ */
+int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
+
+static struct proc_dir_entry proc_scsi_eesox = {
+	PROC_SCSI_QLOGICISP, 5, "eesox",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+/* Prototype: void eesoxscsi_irqenable(ec, irqnr)
+ * Purpose  : Enable interrupts on EESOX SCSI card
+ * Params   : ec    - expansion card structure
+ *          : irqnr - interrupt number
+ */
+static void
+eesoxscsi_irqenable(struct expansion_card *ec, int irqnr)
+{
+	struct control *control = (struct control *)ec->irq_data;
+
+	control->control |= EESOX_INTR_ENABLE;
+
+	outb(control->control, control->io_port);
+}
+
+/* Prototype: void eesoxscsi_irqdisable(ec, irqnr)
+ * Purpose  : Disable interrupts on EESOX SCSI card
+ * Params   : ec    - expansion card structure
+ *          : irqnr - interrupt number
+ */
+static void
+eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr)
+{
+	struct control *control = (struct control *)ec->irq_data;
+
+	control->control &= ~EESOX_INTR_ENABLE;
+
+	outb(control->control, control->io_port);
+}
+
+static const expansioncard_ops_t eesoxscsi_ops = {
+	eesoxscsi_irqenable,
+	eesoxscsi_irqdisable,
+	NULL,
+	NULL
+};
+
+/* Prototype: void eesoxscsi_terminator_ctl(*host, on_off)
+ * Purpose  : Turn the EESOX SCSI terminators on or off
+ * Params   : host   - card to turn on/off
+ *          : on_off - !0 to turn on, 0 to turn off
+ */
+static void
+eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
+{
+	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	unsigned long flags;
+
+	save_flags_cli(flags);
+	if (on_off)
+		info->control.control |= EESOX_TERM_ENABLE;
+	else
+		info->control.control &= ~EESOX_TERM_ENABLE;
+	restore_flags(flags);
+
+	outb(info->control.control, info->control.io_port);
+}
+
+/* Prototype: void eesoxscsi_intr(irq, *dev_id, *regs)
+ * Purpose  : handle interrupts from EESOX SCSI card
+ * Params   : irq    - interrupt number
+ *	      dev_id - user-defined (Scsi_Host structure)
+ *	      regs   - processor registers at interrupt
+ */
+static void
+eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
+
+	fas216_intr(host);
+}
+
+static void
+eesoxscsi_invalidate(char *addr, long len, fasdmadir_t direction)
+{
+	unsigned int page;
+
+	if (direction == DMA_OUT) {
+		for(page = (unsigned int) addr; len > 0;
+		     page += PAGE_SIZE, len -= PAGE_SIZE)
+			flush_page_to_ram(page);
+	} else
+		flush_cache_range(current->mm, (unsigned long)addr,
+				  (unsigned long)addr + len);
+}
+
+/* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type)
+ * Purpose  : initialises DMA/PIO
+ * Params   : host      - host
+ *	      SCpnt     - command
+ *	      direction - DMA on to/off of card
+ *	      min_type  - minimum DMA support that we must have for this transfer
+ * Returns  : type of transfer to be performed
+ */
+static fasdmatype_t
+eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
+		       fasdmadir_t direction, fasdmatype_t min_type)
+{
+	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	int dmach = host->dma_channel;
+
+	if (dmach != NO_DMA &&
+	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
+		int buf;
+
+		for(buf = 1; buf <= SCp->buffers_residual &&
+			     buf < NR_SG; buf++) {
+			info->dmasg[buf].address = __virt_to_bus(
+				(unsigned long)SCp->buffer[buf].address);
+			info->dmasg[buf].length = SCp->buffer[buf].length;
+
+			eesoxscsi_invalidate(SCp->buffer[buf].address,
+						SCp->buffer[buf].length,
+						direction);
+		}
+
+		info->dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr);
+		info->dmasg[0].length = SCp->this_residual;
+		eesoxscsi_invalidate(SCp->ptr,
+					SCp->this_residual, direction);
+
+		disable_dma(dmach);
+		set_dma_sg(dmach, info->dmasg, buf);
+		set_dma_mode(dmach,
+			     direction == DMA_OUT ? DMA_MODE_WRITE :
+						    DMA_MODE_READ);
+		enable_dma(dmach);
+		return fasdma_real_all;
+	}
+	/*
+	 * We don't do DMA, we only do slow PIO
+	 *
+	 * Some day, we will do Pseudo DMA
+	 */
+	return fasdma_pseudo;
+}
+
+static void
+eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
+		     fasdmadir_t dir, int transfer_size)
+{
+	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	unsigned int status;
+	unsigned int length = SCp->this_residual;
+	union {
+		unsigned char *c;
+		unsigned short *s;
+		unsigned long *l;
+	} buffer;
+
+	buffer.c = SCp->ptr;
+
+	status = inb(host->io_port + EESOX_STATUS);
+	if (dir == DMA_IN) {
+		while (length > 8) {
+			if (status & EESOX_STAT_DMA) {
+				unsigned long l1, l2;
+
+				l1 = inw(info->dmaarea);
+				l1 |= inw(info->dmaarea) << 16;
+				l2 = inw(info->dmaarea);
+				l2 |= inw(info->dmaarea) << 16;
+				*buffer.l++ = l1;
+				*buffer.l++ = l2;
+				length -= 8;
+			} else if (status & EESOX_STAT_INTR)
+				goto end;
+			status = inb(host->io_port + EESOX_STATUS);
+		}
+
+		while (length > 1) {
+			if (status & EESOX_STAT_DMA) {
+				*buffer.s++ = inw(info->dmaarea);
+				length -= 2;
+			} else if (status & EESOX_STAT_INTR)
+				goto end;
+			status = inb(host->io_port + EESOX_STATUS);
+		}
+
+		while (length > 0) {
+			if (status & EESOX_STAT_DMA) {
+				*buffer.c++ = inw(info->dmaarea);
+				length -= 1;
+			} else if (status & EESOX_STAT_INTR)
+				goto end;
+			status = inb(host->io_port + EESOX_STATUS);
+		}
+	} else {
+		while (length > 8) {
+			if (status & EESOX_STAT_DMA) {
+				unsigned long l1, l2;
+
+				l1 = *buffer.l++;
+				l2 = *buffer.l++;
+
+				outw(l1, info->dmaarea);
+				outw(l1 >> 16, info->dmaarea);
+				outw(l2, info->dmaarea);
+				outw(l2 >> 16, info->dmaarea);
+				length -= 8;
+			} else if (status & EESOX_STAT_INTR)
+				goto end;
+			status = inb(host->io_port + EESOX_STATUS);
+		}
+
+		while (length > 1) {
+			if (status & EESOX_STAT_DMA) {
+				outw(*buffer.s++, info->dmaarea);
+				length -= 2;
+			} else if (status & EESOX_STAT_INTR)
+				goto end;
+			status = inb(host->io_port + EESOX_STATUS);
+		}
+
+		while (length > 0) {
+			if (status & EESOX_STAT_DMA) {
+				outw(*buffer.c++, info->dmaarea);
+				length -= 1;
+			} else if (status & EESOX_STAT_INTR)
+				goto end;
+			status = inb(host->io_port + EESOX_STATUS);
+		}
+	}
+end:
+}
+
+/* Prototype: int eesoxscsi_dma_stop(host, SCpnt)
+ * Purpose  : stops DMA/PIO
+ * Params   : host  - host
+ *	      SCpnt - command
+ */
+static void
+eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
+{
+	if (host->dma_channel != NO_DMA)
+		disable_dma(host->dma_channel);
+}
+
+/* Prototype: int eesoxscsi_detect(Scsi_Host_Template * tpnt)
+ * Purpose  : initialises EESOX SCSI driver
+ * Params   : tpnt - template for this SCSI adapter
+ * Returns  : >0 if host found, 0 otherwise.
+ */
+int
+eesoxscsi_detect(Scsi_Host_Template *tpnt)
+{
+	static const card_ids eesoxscsi_cids[] =
+			{ EESOXSCSI_LIST, { 0xffff, 0xffff} };
+	int count = 0;
+	struct Scsi_Host *host;
+  
+	tpnt->proc_dir = &proc_scsi_eesox;
+	memset(ecs, 0, sizeof (ecs));
+
+	ecard_startfind();
+
+	while(1) {
+	    	EESOXScsi_Info *info;
+
+		ecs[count] = ecard_find(0, eesoxscsi_cids);
+		if (!ecs[count])
+			break;
+
+		ecard_claim(ecs[count]);
+
+		host = scsi_register(tpnt, sizeof (EESOXScsi_Info));
+		if (!host) {
+			ecard_release(ecs[count]);
+			break;
+		}
+
+		host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST);
+		host->irq = ecs[count]->irq;
+		host->dma_channel = ecs[count]->dma;
+		info = (EESOXScsi_Info *)host->hostdata;
+
+		info->control.io_port = host->io_port + EESOX_CONTROL;
+		info->control.control = term[count] ? EESOX_TERM_ENABLE : 0;
+		outb(info->control.control, info->control.io_port);
+
+		ecs[count]->irqaddr = (unsigned char *)
+			    ioaddr(host->io_port + EESOX_STATUS);
+		ecs[count]->irqmask = EESOX_STAT_INTR;
+		ecs[count]->irq_data = &info->control;
+		ecs[count]->ops = (expansioncard_ops_t *)&eesoxscsi_ops;
+
+		info->info.scsi.io_port		= host->io_port + EESOX_FAS216_OFFSET;
+		info->info.scsi.io_shift	= EESOX_FAS216_SHIFT;
+		info->info.scsi.irq		= host->irq;
+		info->info.ifcfg.clockrate	= EESOX_XTALFREQ;
+		info->info.ifcfg.select_timeout	= 255;
+		info->info.ifcfg.asyncperiod	= EESOX_ASYNC_PERIOD;
+		info->info.ifcfg.sync_max_depth	= EESOX_SYNC_DEPTH;
+		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+		info->info.dma.setup		= eesoxscsi_dma_setup;
+		info->info.dma.pseudo		= eesoxscsi_dma_pseudo;
+		info->info.dma.stop		= eesoxscsi_dma_stop;
+		info->dmaarea			= host->io_port + EESOX_DMA_OFFSET;
+
+		request_region(host->io_port + EESOX_FAS216_OFFSET,
+				16 << EESOX_FAS216_SHIFT, "eesox2-fas");
+
+		if (request_irq(host->irq, eesoxscsi_intr,
+				SA_INTERRUPT, "eesox", host)) {
+			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
+			       host->host_no, host->irq);
+			host->irq = NO_IRQ;
+		}
+
+		if (request_dma(host->dma_channel, "eesox")) {
+			printk("scsi%d: DMA%d not free, DMA disabled\n",
+			       host->host_no, host->dma_channel);
+			host->dma_channel = NO_DMA;
+		}
+
+		fas216_init(host);
+		++count;
+	}
+	return count;
+}
+
+/* Prototype: int eesoxscsi_release(struct Scsi_Host * host)
+ * Purpose  : releases all resources used by this adapter
+ * Params   : host - driver host structure to return info for.
+ */
+int eesoxscsi_release(struct Scsi_Host *host)
+{
+	int i;
+
+	fas216_release(host);
+
+	if (host->irq != NO_IRQ)
+		free_irq(host->irq, host);
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	release_region(host->io_port + EESOX_FAS216_OFFSET, 16 << EESOX_FAS216_SHIFT);
+
+	for (i = 0; i < MAX_ECARDS; i++)
+		if (ecs[i] &&
+		    host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST))
+			ecard_release(ecs[i]);
+	return 0;
+}
+
+/* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host)
+ * Purpose  : returns a descriptive string about this interface,
+ * Params   : host - driver host structure to return info for.
+ * Returns  : pointer to a static buffer containing null terminated string.
+ */
+const char *eesoxscsi_info(struct Scsi_Host *host)
+{
+	EESOXScsi_Info *info = (EESOXScsi_Info *)host->hostdata;
+	static char string[100], *p;
+
+	p = string;
+	p += sprintf(string, "%s at port %lX ",
+		     host->hostt->name, host->io_port);
+
+	if (host->irq != NO_IRQ)
+		p += sprintf(p, "irq %d ", host->irq);
+	else
+		p += sprintf(p, "NO IRQ ");
+
+	if (host->dma_channel != NO_DMA)
+		p += sprintf(p, "dma %d ", host->dma_channel);
+	else
+		p += sprintf(p, "NO DMA ");
+
+	p += sprintf(p, "v%d.%d.%d scsi %s", VER_MAJOR, VER_MINOR, VER_PATCH,
+		  info->info.scsi.type);
+
+	p += sprintf(p, " terminators %s",
+		  info->control.control & EESOX_TERM_ENABLE ? "on" : "off");
+
+	return string;
+}
+
+/* Prototype: int eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
+ * Purpose  : Set a driver specific function
+ * Params   : host   - host to setup
+ *          : buffer - buffer containing string describing operation
+ *          : length - length of string
+ * Returns  : -EINVAL, or 0
+ */
+static int
+eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	int ret = length;
+
+	if (length >= 9 && strncmp(buffer, "EESOXSCSI", 9) == 0) {
+		buffer += 9;
+		length -= 9;
+
+		if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
+			if (buffer[5] == '1')
+				eesoxscsi_terminator_ctl(host, 1);
+			else if (buffer[5] == '0')
+				eesoxscsi_terminator_ctl(host, 0);
+			else
+				ret = -EINVAL;
+		} else
+			ret = -EINVAL;
+	} else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
+ *				      int length, int host_no, int inout)
+ * Purpose  : Return information about the driver to a user process accessing
+ *	      the /proc filesystem.
+ * Params   : buffer - a buffer to write information to
+ *	      start  - a pointer into this buffer set by this routine to the start
+ *		       of the required information.
+ *	      offset - offset into information that we have read upto.
+ *	      length - length of buffer
+ *	      host_no - host number to return information for
+ *	      inout  - 0 for reading, 1 for writing.
+ * Returns  : length of data written to buffer.
+ */
+int eesoxscsi_proc_info(char *buffer, char **start, off_t offset,
+			    int length, int host_no, int inout)
+{
+	int pos, begin;
+	struct Scsi_Host *host = scsi_hostlist;
+	EESOXScsi_Info *info;
+	Scsi_Device *scd;
+
+	while (host) {
+		if (host->host_no == host_no)
+			break;
+		host = host->next;
+	}
+	if (!host)
+		return 0;
+
+	if (inout == 1)
+		return eesoxscsi_set_proc_info(host, buffer, length);
+
+	info = (EESOXScsi_Info *)host->hostdata;
+
+	begin = 0;
+	pos = sprintf(buffer,
+			"EESOX SCSI driver version %d.%d.%d\n",
+			VER_MAJOR, VER_MINOR, VER_PATCH);
+	pos += sprintf(buffer + pos,
+			"Address: %08lX    IRQ : %d     DMA : %d\n"
+			"FAS    : %-10s  TERM: %-3s\n\n"
+			"Statistics:\n",
+			host->io_port, host->irq, host->dma_channel,
+			info->info.scsi.type, info->control.control & EESOX_TERM_ENABLE ? "on" : "off");
+
+	pos += sprintf(buffer+pos,
+			"Queued commands: %-10u   Issued commands: %-10u\n"
+			"Done commands  : %-10u   Reads          : %-10u\n"
+			"Writes         : %-10u   Others         : %-10u\n"
+			"Disconnects    : %-10u   Aborts         : %-10u\n"
+			"Resets         : %-10u\n",
+			info->info.stats.queues,      info->info.stats.removes,
+			info->info.stats.fins,        info->info.stats.reads,
+			info->info.stats.writes,      info->info.stats.miscs,
+			info->info.stats.disconnects, info->info.stats.aborts,
+			info->info.stats.resets);
+
+	pos += sprintf (buffer+pos, "\nAttached devices:%s\n", host->host_queue ? "" : " none");
+
+	for (scd = host->host_queue; scd; scd = scd->next) {
+		int len;
+
+		proc_print_scsidevice (scd, buffer, &len, pos);
+		pos += len;
+		pos += sprintf (buffer+pos, "Extensions: ");
+		if (scd->tagged_supported)
+			pos += sprintf (buffer+pos, "TAG %sabled [%d] ",
+					scd->tagged_queue ? "en" : "dis",
+					scd->current_tag);
+		pos += sprintf (buffer+pos, "\n");
+
+		if (pos + begin < offset) {
+			begin += pos;
+			pos = 0;
+		}
+	}
+	*start = buffer + (offset - begin);
+	pos -= offset - begin;
+	if (pos > length)
+		pos = length;
+
+	return pos;
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = EESOXSCSI;
+
+#include "../../scsi/scsi_module.c"
+#endif
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/eesox.h linux/drivers/acorn/scsi/eesox.h
--- v2.1.100/linux/drivers/acorn/scsi/eesox.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/scsi/eesox.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,81 @@
+/*
+ * EESOX SCSI driver
+ *
+ * Copyright (C) 1997-1998 Russell King
+ */
+#ifndef EESOXSCSI_H
+#define EESOXSCSI_H
+
+extern int eesoxscsi_detect (Scsi_Host_Template *);
+extern int eesoxscsi_release (struct Scsi_Host *);
+extern const char *eesoxscsi_info (struct Scsi_Host *);
+extern int eesoxscsi_proc_info (char *buffer, char **start, off_t offset,
+					int length, int hostno, int inout);
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#ifndef CAN_QUEUE
+/*
+ * Default queue size
+ */
+#define CAN_QUEUE	1
+#endif
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN	1
+#endif
+
+#ifndef SCSI_ID
+/*
+ * Default SCSI host ID
+ */
+#define SCSI_ID		7
+#endif
+
+#include <scsi/scsicam.h>
+
+#include "fas216.h"
+
+#define EESOXSCSI {							\
+proc_info:	eesoxscsi_proc_info,					\
+name:		"EESOX SCSI",						\
+detect:		eesoxscsi_detect,	/* detect		*/	\
+release:	eesoxscsi_release,	/* release		*/	\
+info:		eesoxscsi_info,		/* info			*/	\
+command:	fas216_command,		/* command		*/	\
+queuecommand:	fas216_queue_command,	/* queuecommand		*/	\
+abort:		fas216_abort,		/* abort		*/	\
+reset:		fas216_reset,		/* reset		*/	\
+bios_param:	scsicam_bios_param,	/* biosparam		*/	\
+can_queue:	CAN_QUEUE,		/* can queue		*/	\
+this_id:	SCSI_ID,		/* scsi host id		*/	\
+sg_tablesize:	SG_ALL,			/* sg_tablesize		*/	\
+cmd_per_lun:	CAN_QUEUE,		/* cmd per lun		*/	\
+use_clustering:	DISABLE_CLUSTERING					\
+	}
+
+#ifndef HOSTS_C
+
+#include <asm/dma.h>
+
+#define NR_SG	256
+
+struct control {
+	unsigned int	io_port;
+	unsigned int	control;
+};
+
+typedef struct {
+	FAS216_Info info;
+
+	struct control control;
+
+	unsigned int	dmaarea;	/* Pseudo DMA area	*/
+	dmasg_t		dmasg[NR_SG];	/* Scatter DMA list	*/
+} EESOXScsi_Info;
+
+#endif /* HOSTS_C */
+
+#endif /* EESOXSCSI_H */
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c
--- v2.1.100/linux/drivers/acorn/scsi/fas216.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/fas216.c	Fri May  8 00:42:39 1998
@@ -3,8 +3,9 @@
  *
  * Copyright (C) 1997 Russell King
  *
- * Based in information in qlogicfas.c by Tom Zerucha, Michael Griffith, and
- * other sources.
+ * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and
+ * other sources, including:
+ *   the AMD Am53CF94 data sheet
  *
  * This is a generic driver.  To use it, have a look at cumana_2.c.  You
  * should define your own structure that overlays FAS216_Info, eg:
@@ -18,6 +19,13 @@
  *  14-09-1997	RMK	Started disconnect support
  *  08-02-1998	RMK	Corrected real DMA support
  *  15-02-1998	RMK	Started sync xfer support
+ *  06-04-1998	RMK	Tightened conditions for printing incomplete
+ *			transfers
+ *  02-05-1998	RMK	Added extra checks in fas216_reset
+ *
+ * Todo:
+ *  - tighten up the MESSAGE_REJECT support.
+ *  - allow individual devices to enable sync xfers.
  */
 
 #include <linux/module.h>
@@ -31,6 +39,7 @@
 #include <linux/stat.h>
 
 #include <asm/delay.h>
+#include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/ecard.h>
@@ -43,7 +52,34 @@
 
 #define VER_MAJOR	0
 #define VER_MINOR	0
-#define VER_PATCH	2
+#define VER_PATCH	3
+
+#define SCSI2_TAG
+
+/* NOTE: SCSI2 Synchronous transfers *require* DMA according to
+ *  the data sheet.  This restriction is crazy, especially when
+ *  you only want to send 16 bytes!  What were the guys who
+ *  designed this chip on at that time?  Did they read the SCSI2
+ *  spec at all?  The following sections are taken from the SCSI2
+ *  standard (s2r10) concerning this:
+ *
+ * > IMPLEMENTORS NOTES:
+ * >   (1)  Re-negotiation at every selection is not recommended, since a
+ * >   significant performance impact is likely.
+ *
+ * >  The implied synchronous agreement shall remain in effect until a BUS DEVICE
+ * >  RESET message is received, until a hard reset condition occurs, or until one
+ * >  of the two SCSI devices elects to modify the agreement.  The default data
+ * >  transfer mode is asynchronous data transfer mode.  The default data transfer
+ * >  mode is entered at power on, after a BUS DEVICE RESET message, or after a hard
+ * >  reset condition.
+ *
+ *  In total, this means that once you have elected to use synchronous
+ *  transfers, you must always use DMA.
+ *
+ *  I was thinking that this was a good chip until I found this restriction ;(
+ */
+#define SCSI2_SYNC
 
 #undef NO_DISCONNECTS
 #undef DEBUG_CONNECT
@@ -51,9 +87,95 @@
 #undef DEBUG_FUNCTIONDONE
 #undef DEBUG_MESSAGES
 
-static char *fas216_bus_phase (int stat)
+#undef CHECK_STRUCTURE
+
+static struct { int stat, ssr, isr, ph; } list[8];
+static int ptr;
+
+static void fas216_dumpstate(FAS216_Info *info)
+{
+	printk("FAS216 registers:\n");
+	printk("    CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X"
+	       " INST=%02X IS=%02X CFIS=%02X",
+		inb(REG_CTCL(info)), inb(REG_CTCM(info)),
+		inb(REG_CMD(info)),  inb(REG_STAT(info)),
+		inb(REG_INST(info)), inb(REG_IS(info)),
+		inb(REG_CFIS(info)));
+	printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n",
+		inb(REG_CNTL1(info)), inb(REG_CNTL2(info)),
+		inb(REG_CNTL3(info)), inb(REG_CTCH(info)));
+}
+
+static void fas216_dumpinfo(FAS216_Info *info)
+{
+	static int used = 0;
+	int i;
+
+	if (used++)
+		return;
+
+	printk("FAS216_Info = \n");
+	printk("  { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
+		info->magic_start, info->host, info->SCpnt,
+		info->origSCpnt);
+	printk("    scsi={ io_port=%X io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
+		info->scsi.io_port, info->scsi.io_shift, info->scsi.irq,
+		info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
+		info->scsi.cfg[3]);
+	printk("           type=%p phase=%X reconnected = { target=%d lun=%d tag=%d }\n",
+		info->scsi.type, info->scsi.phase,
+		info->scsi.reconnected.target,
+		info->scsi.reconnected.lun, info->scsi.reconnected.tag);
+	printk("           SCp = { ptr=%p this_residual=%X buffer=%p buffers_residual=%X }\n",
+		info->scsi.SCp.ptr, info->scsi.SCp.this_residual,
+		info->scsi.SCp.buffer, info->scsi.SCp.buffers_residual);
+	printk("      msgs async_stp=%X last_message=%X disconnectable=%d aborting=%d }\n",
+		info->scsi.async_stp, info->scsi.last_message,
+		info->scsi.disconnectable, info->scsi.aborting);
+	printk("    stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X disconnects=%X aborts=%X resets=%X }\n",
+		info->stats.queues, info->stats.removes, info->stats.fins,
+		info->stats.reads, info->stats.writes, info->stats.miscs,
+		info->stats.disconnects, info->stats.aborts, info->stats.resets);
+	printk("    ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n",
+		info->ifcfg.clockrate, info->ifcfg.select_timeout,
+		info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth);
+	for (i = 0; i < 8; i++) {
+		printk("    busyluns[%d]=%X dev[%d]={ disconnect_ok=%d stp=%X sof=%X negstate=%X }\n",
+			i, info->busyluns[i], i,
+			info->device[i].disconnect_ok, info->device[i].stp,
+			info->device[i].sof, info->device[i].negstate);
+	}
+	printk("    dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n",
+		info->dma.transfer_type, info->dma.setup,
+		info->dma.pseudo, info->dma.stop);
+	printk("    internal_done=%X magic_end=%lX\n",
+		info->internal_done, info->magic_end);
+}
+
+#ifdef CHECK_STRUCTURE
+static void fas216_checkmagic(FAS216_Info *info, const char *func)
+{
+	int corruption = 0;
+	if (info->magic_start != MAGIC) {
+		printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n");
+		corruption++;
+	}
+	if (info->magic_end != MAGIC) {
+		printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n");
+		corruption++;
+	}
+	if (corruption) {
+		fas216_dumpinfo(info);
+		panic("scsi memory space corrupted in %s", func);
+	}
+}
+#else
+#define fas216_checkmagic(info,func)
+#endif
+
+static const char *fas216_bus_phase(int stat)
 {
-	static char *phases[] = {
+	static const char *phases[] = {
 		"DATA OUT", "DATA IN",
 		"COMMAND", "STATUS",
 		"MISC OUT", "MISC IN",
@@ -63,7 +185,26 @@
 	return phases[stat & STAT_BUSMASK];
 }
 
-static char fas216_target (FAS216_Info *info)
+static const char *fas216_drv_phase(FAS216_Info *info)
+{
+	switch (info->scsi.phase) {
+	case PHASE_IDLE:	return "idle";
+	case PHASE_SELECTION:	return "selection";
+	case PHASE_MESSAGESENT:	return "message sent";
+	case PHASE_RECONNECTED:	return "reconnected";
+	case PHASE_DATAOUT:	return "data out";
+	case PHASE_DATAIN:	return "data in";
+	case PHASE_MSGOUT:	return "message out";
+	case PHASE_MSGIN:	return "message in";
+	case PHASE_AFTERMSGOUT:	return "after message out";
+	case PHASE_STATUS:	return "status";
+	case PHASE_DISCONNECT:	return "disconnect";
+	case PHASE_DONE:	return "done";
+	default:		return "???";
+	}
+}
+
+static char fas216_target(FAS216_Info *info)
 {
 	if (info->SCpnt)
 		return '0' + info->SCpnt->target;
@@ -71,15 +212,41 @@
 		return 'H';
 }
 
-static void fas216_done (FAS216_Info *info, unsigned int result);
+static void add_debug_list(int stat, int ssr, int isr, int ph)
+{
+	list[ptr].stat = stat;
+	list[ptr].ssr = ssr;
+	list[ptr].isr = isr;
+	list[ptr].ph = ph;
+
+	ptr = (ptr + 1) & 7;
+}
+
+static void print_debug_list(void)
+{
+	int i;
+
+	i = ptr;
+
+	printk(KERN_ERR "SCSI state trail: ");
+	do {
+		printk("%02X:%02X:%02X:%02X ",
+			list[i].stat, list[i].ssr,
+			list[i].isr, list[i].ph);
+		i = (i + 1) & 7;
+	} while (i != ptr);
+	printk("\n");
+}
+
+static void fas216_done(FAS216_Info *info, unsigned int result);
 
-/* Function: int fas216_clockrate (unsigned int clock)
+/* Function: int fas216_clockrate(unsigned int clock)
  * Purpose : calculate correct value to be written into clock conversion
  *	     factor register.
  * Params  : clock - clock speed in MHz
  * Returns : CLKF_ value
  */
-static int fas216_clockrate (int clock)
+static int fas216_clockrate(int clock)
 {
 	if (clock <= 10 || clock > 40) {
 		printk(KERN_CRIT
@@ -102,6 +269,8 @@
 {
 	int value = (info->ifcfg.clockrate * ns) / 1000;
 
+	fas216_checkmagic(info, "fas216_syncperiod");
+
 	if (value < 4)
 		value = 4;
 	else if (value > 35)
@@ -110,16 +279,21 @@
 	return value & 31;
 }
 
-/* Function: void fas216_updateptrs (FAS216_Info *info, int bytes_transferred)
+/* Function: void fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
  * Purpose : update data pointers after transfer suspended/paused
  * Params  : info              - interface's local pointer to update
  *           bytes_transferred - number of bytes transferred
  */
 static void
-fas216_updateptrs (FAS216_Info *info, int bytes_transferred)
+fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
 {
-	unsigned char *ptr = info->scsi.SCp.ptr;
-	unsigned int residual = info->scsi.SCp.this_residual;
+	unsigned char *ptr;
+	unsigned int residual;
+
+	fas216_checkmagic(info, "fas216_updateptrs");
+
+	ptr = info->scsi.SCp.ptr;
+	residual = info->scsi.SCp.this_residual;
 
 	info->SCpnt->request_bufflen -= bytes_transferred;
 
@@ -144,50 +318,61 @@
 	info->scsi.SCp.this_residual = residual;
 }
 
-/* Function: void fas216_pio (FAS216_Info *info, fasdmadir_t direction)
+/* Function: void fas216_pio(FAS216_Info *info, fasdmadir_t direction)
  * Purpose : transfer data off of/on to card using programmed IO
  * Params  : info      - interface to transfer data to/from
  *           direction - direction to transfer data (DMA_OUT/DMA_IN)
  * Notes   : this is incredibly slow
  */
 static void
-fas216_pio (FAS216_Info *info, fasdmadir_t direction)
+fas216_pio(FAS216_Info *info, fasdmadir_t direction)
 {
-	unsigned int length = info->scsi.SCp.this_residual;
-	char *ptr = info->scsi.SCp.ptr;
+	unsigned int residual;
+	char *ptr;
+	int correction;
+
+	fas216_checkmagic(info, "fas216_pio");
+
+	residual = info->scsi.SCp.this_residual;
+	ptr = info->scsi.SCp.ptr;
 
 	if (direction == DMA_OUT) {
-	    	while (length > 0) {
+	    	while (residual > 0) {
 			if ((inb(REG_CFIS(info)) & CFIS_CF) < 8) {
 				outb(*ptr++, REG_FF(info));
-				length -= 1;
+				residual -= 1;
 			} else if (inb(REG_STAT(info)) & STAT_INT)
 				break;
 		}
+		correction = inb(REG_CFIS(info)) & CFIS_CF;
 	} else {
-	    	while (length > 0) {
+	    	while (residual > 0) {
 			if ((inb(REG_CFIS(info)) & CFIS_CF) != 0) {
 				*ptr++ = inb(REG_FF(info));
-				length -= 1;
+				residual -= 1;
 			} else if (inb(REG_STAT(info)) & STAT_INT)
 				break;
 		}
+		correction = 0;
 	}
 
-	if (length == 0) {
+	ptr -= correction;
+	residual += correction;
+
+	if (residual == 0) {
 		if (info->scsi.SCp.buffers_residual) {
 			info->scsi.SCp.buffer++;
 			info->scsi.SCp.buffers_residual--;
 			ptr = (unsigned char *)info->scsi.SCp.buffer->address;
-			length = info->scsi.SCp.buffer->length;
+			residual = info->scsi.SCp.buffer->length;
 		} else {
 			ptr = NULL;
-			length = 0;
+			residual = 0;
 		}
 	}
 
 	info->scsi.SCp.ptr = ptr;
-	info->scsi.SCp.this_residual = length;
+	info->scsi.SCp.this_residual = residual;
 }
 
 /* Function: void fas216_starttransfer(FAS216_Info *info,
@@ -197,77 +382,81 @@
  *           direction - transfer direction (DMA_OUT/DMA_IN)
  */
 static void
-fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction)
+fas216_starttransfer(FAS216_Info *info, fasdmadir_t direction, int flush_fifo)
 {
 	fasdmatype_t dmatype;
 
+	fas216_checkmagic(info, "fas216_starttransfer");
+
 	info->scsi.phase = (direction == DMA_OUT) ?
 				PHASE_DATAOUT : PHASE_DATAIN;
 
-	if (info->dma.transfer_type == fasdma_real_block ||
-	    info->dma.transfer_type == fasdma_real_all) {
+	if (info->dma.transfer_type != fasdma_none &&
+	    info->dma.transfer_type != fasdma_pio) {
 		unsigned long total, residual;
 
-		if (info->dma.transfer_type == fasdma_real_block)
-			total = info->scsi.SCp.this_residual;
-		else
+		if (info->dma.transfer_type == fasdma_real_all)
 			total = info->SCpnt->request_bufflen;
+		else
+			total = info->scsi.SCp.this_residual;
 
 		residual = (inb(REG_CFIS(info)) & CFIS_CF) +
 			    inb(REG_CTCL(info)) +
 			    (inb(REG_CTCM(info)) << 8) +
 			    (inb(REG_CTCH(info)) << 16);
-		fas216_updateptrs (info, total - residual);
-		info->dma.transfer_type = fasdma_none;
+		fas216_updateptrs(info, total - residual);
 	}
+	info->dma.transfer_type = fasdma_none;
 
 	if (!info->scsi.SCp.ptr) {
-		printk ("scsi%d.%c: null buffer passed to "
+		printk("scsi%d.%c: null buffer passed to "
 			"fas216_starttransfer\n", info->host->host_no,
-			fas216_target (info));
+			fas216_target(info));
 		return;
 	}
 
-	dmatype = fasdma_none;
+	/* flush FIFO */
+	if (flush_fifo)
+		outb(CMD_FLUSHFIFO, REG_CMD(info));
+
+	/*
+	 * Default to PIO mode or DMA mode if we have a synchronous
+	 * transfer agreement.
+	 */
+	if (info->device[info->SCpnt->target].sof && info->dma.setup)
+		dmatype = fasdma_real_all;
+	else
+		dmatype = fasdma_pio;
+
 	if (info->dma.setup)
 		dmatype = info->dma.setup(info->host, &info->scsi.SCp,
-					  direction);
-
+					  direction, dmatype);
 	info->dma.transfer_type = dmatype;
 
 	switch (dmatype) {
-	case fasdma_none:
+	case fasdma_pio:
+		outb(0, REG_SOF(info));
+		outb(info->scsi.async_stp, REG_STP(info));
 		outb(info->scsi.SCp.this_residual, REG_STCL(info));
 		outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
 		outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
-		outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info));
 		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		fas216_pio (info, direction);
+		fas216_pio(info, direction);
 		break;
 
-	case fasdma_pseudo: {
-		int transferred;
-
+	case fasdma_pseudo:
 		outb(info->scsi.SCp.this_residual, REG_STCL(info));
 		outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
 		outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
-		outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info));
 		outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
-
-		transferred =
-			info->dma.pseudo(info->host, &info->scsi.SCp,
-					 direction, info->SCpnt->transfersize);
-
-		fas216_updateptrs (info, transferred);
-		}
+		info->dma.pseudo(info->host, &info->scsi.SCp,
+				 direction, info->SCpnt->transfersize);
 		break;
 
 	case fasdma_real_block:
 		outb(info->scsi.SCp.this_residual, REG_STCL(info));
 		outb(info->scsi.SCp.this_residual >> 8, REG_STCM(info));
 		outb(info->scsi.SCp.this_residual >> 16, REG_STCH(info));
-		outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info));
-
 		outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
 		break;
 
@@ -275,58 +464,66 @@
 		outb(info->SCpnt->request_bufflen, REG_STCL(info));
 		outb(info->SCpnt->request_bufflen >> 8, REG_STCM(info));
 		outb(info->SCpnt->request_bufflen >> 16, REG_STCH(info));
-		outb(CMD_NOP | CMD_WITHDMA, REG_CMD(info));
-
 		outb(CMD_TRANSFERINFO | CMD_WITHDMA, REG_CMD(info));
 		break;
+
+	default:
+		printk(KERN_ERR "scsi%d.%d: invalid FAS216 DMA type\n",
+		       info->host->host_no, fas216_target(info));
+		break;
 	}
 }
 
-/* Function: void fas216_stoptransfer (FAS216_Info *info)
+/* Function: void fas216_stoptransfer(FAS216_Info *info)
  * Purpose : Stop a DMA transfer onto / off of the card
  * Params  : info      - interface from which device disconnected from
  */
 static void
-fas216_stoptransfer (FAS216_Info *info)
+fas216_stoptransfer(FAS216_Info *info)
 {
-	if (info->dma.transfer_type == fasdma_real_block ||
-	    info->dma.transfer_type == fasdma_real_all) {
+	fas216_checkmagic(info, "fas216_stoptransfer");
+
+	if (info->dma.transfer_type != fasdma_none &&
+	    info->dma.transfer_type != fasdma_pio) {
 		unsigned long total, residual;
 
-		if (info->dma.stop)
-			info->dma.stop (info->host, &info->scsi.SCp);
+		if ((info->dma.transfer_type == fasdma_real_all ||
+		     info->dma.transfer_type == fasdma_real_block) &&
+		    info->dma.stop)
+			info->dma.stop(info->host, &info->scsi.SCp);
 
-		if (info->dma.transfer_type == fasdma_real_block)
-			total = info->scsi.SCp.this_residual;
-		else
+		if (info->dma.transfer_type == fasdma_real_all)
 			total = info->SCpnt->request_bufflen;
+		else
+			total = info->scsi.SCp.this_residual;
 
 		residual = (inb(REG_CFIS(info)) & CFIS_CF) +
 			    inb(REG_CTCL(info)) +
 			    (inb(REG_CTCM(info)) << 8) +
 			    (inb(REG_CTCH(info)) << 16);
-		fas216_updateptrs (info, total - residual);
-
+		fas216_updateptrs(info, total - residual);
 		info->dma.transfer_type = fasdma_none;
 	}
 }
 
-/* Function: void fas216_disconnected_intr (FAS216_Info *info)
+/* Function: void fas216_disconnected_intr(FAS216_Info *info)
  * Purpose : handle device disconnection
  * Params  : info - interface from which device disconnected from
  */
 static void
-fas216_disconnect_intr (FAS216_Info *info)
+fas216_disconnect_intr(FAS216_Info *info)
 {
+	fas216_checkmagic(info, "fas216_disconnected_intr");
+
 #ifdef DEBUG_CONNECT
 	printk("scsi%d.%c: disconnect phase=%02X\n", info->host->host_no,
-		fas216_target (info), info->scsi.phase);
+		fas216_target(info), info->scsi.phase);
 #endif
-	msgqueue_flush (&info->scsi.msgs);
+	msgqueue_flush(&info->scsi.msgs);
 
 	switch (info->scsi.phase) {
 	case PHASE_SELECTION:			/* while selecting - no target		*/
-		fas216_done (info, DID_NO_CONNECT);
+		fas216_done(info, DID_NO_CONNECT);
 		break;
 
 	case PHASE_DISCONNECT:			/* message in - disconnecting		*/
@@ -338,33 +535,36 @@
 		break;
 
 	case PHASE_DONE:			/* at end of command - complete		*/
-		fas216_done (info, DID_OK);
+		fas216_done(info, DID_OK);
 		break;
 
 	case PHASE_AFTERMSGOUT:			/* message out - possible ABORT message	*/
 		if (info->scsi.last_message == ABORT) {
 			info->scsi.aborting = 0;
-			fas216_done (info, DID_ABORT);
+			fas216_done(info, DID_ABORT);
 			break;
 		}
 
 	default:				/* huh?					*/
-		printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %d\n",
-			info->host->host_no, fas216_target (info), info->scsi.phase);
+		printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n",
+			info->host->host_no, fas216_target(info), fas216_drv_phase(info));
+		print_debug_list();
 		fas216_stoptransfer(info);
-		fas216_done (info, DID_ERROR);
+		fas216_done(info, DID_ERROR);
 		break;
 	}
 }
 
-/* Function: void fas216_reselected_intr (FAS216_Info *info)
+/* Function: void fas216_reselected_intr(FAS216_Info *info)
  * Purpose : Start reconnection of a device
  * Params  : info - interface which was reselected
  */
 static void
-fas216_reselected_intr (FAS216_Info *info)
+fas216_reselected_intr(FAS216_Info *info)
 {
-    unsigned char target, identify_msg, ok;
+	unsigned char target, identify_msg, ok;
+
+	fas216_checkmagic(info, "fas216_reselected_intr");
 
 	if (info->scsi.phase == PHASE_SELECTION && info->SCpnt) {
 		Scsi_Cmnd *SCpnt = info->SCpnt;
@@ -378,555 +578,733 @@
 
 #ifdef DEBUG_CONNECT
 	printk("scsi%d.%c: reconnect phase=%02X\n", info->host->host_no,
-		fas216_target (info), info->scsi.phase);
+		fas216_target(info), info->scsi.phase);
 #endif
 
-    msgqueue_flush (&info->scsi.msgs);
-
-    if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) {
-	printk (KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
-		info->host->host_no);
-	outb(CMD_SETATN, REG_CMD(info));
-	msgqueue_addmsg (&info->scsi.msgs, 1, MESSAGE_REJECT);
-	info->scsi.phase = PHASE_MSGOUT;
-	outb(CMD_MSGACCEPTED, REG_CMD(info));
-	return;
-    }
+	msgqueue_flush(&info->scsi.msgs);
 
-    target = inb(REG_FF(info));
-    identify_msg = inb(REG_FF(info));
+	if ((inb(REG_CFIS(info)) & CFIS_CF) != 2) {
+		printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n",
+			info->host->host_no);
+		outb(CMD_SETATN, REG_CMD(info));
+		msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
+		info->scsi.phase = PHASE_MSGOUT;
+		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		return;
+	}
 
-    ok = 1;
-    if (!(target & (1 << info->host->this_id))) {
-	printk (KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no);
-	ok = 0;
-    }
+	target = inb(REG_FF(info));
+	identify_msg = inb(REG_FF(info));
 
-    if (!(identify_msg & 0x80)) {
-	printk (KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n",
-		info->host->host_no, identify_msg);
-	ok = 0;
-    }
+	ok = 1;
+	if (!(target & (1 << info->host->this_id))) {
+		printk(KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no);
+		ok = 0;
+	}
 
-    if (!ok) {
-	/*
-	 * Something went wrong - abort the command on
-	 * the target.  Should this be INITIATOR_ERROR ?
-	 */
-	outb(CMD_SETATN, REG_CMD(info));
-	msgqueue_addmsg (&info->scsi.msgs, 1, ABORT);
-	info->scsi.phase = PHASE_MSGOUT;
-	outb(CMD_MSGACCEPTED, REG_CMD(info));
-	return;
-    }
+	if (!(identify_msg & 0x80)) {
+		printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n",
+			info->host->host_no, identify_msg);
+		ok = 0;
+	}
 
-    target &= ~(1 << info->host->this_id);
-    switch (target) {
-    case   1:  target = 0; break;
-    case   2:  target = 1; break;
-    case   4:  target = 2; break;
-    case   8:  target = 3; break;
-    case  16:  target = 4; break;
-    case  32:  target = 5; break;
-    case  64:  target = 6; break;
-    case 128:  target = 7; break;
-    default:   target = info->host->this_id; break;
-    }
-
-    identify_msg &= 7;
-    info->scsi.reconnected.target = target;
-    info->scsi.reconnected.lun    = identify_msg;
-    info->scsi.reconnected.tag    = 0;
-
-    ok = 0;
-    if (info->scsi.disconnectable && info->SCpnt &&
-	  info->SCpnt->target == target && info->SCpnt->lun == identify_msg)
-	ok = 1;
+	if (!ok) {
+		/*
+		 * Something went wrong - abort the command on
+		 * the target.  Should this be INITIATOR_ERROR ?
+		 */
+		outb(CMD_SETATN, REG_CMD(info));
+		msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
+		info->scsi.phase = PHASE_MSGOUT;
+		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		return;
+	}
 
-    if (!ok && queue_probetgtlun (&info->queues.disconnected, target, identify_msg))
-	ok = 1;
+	target &= ~(1 << info->host->this_id);
+	switch (target) {
+	case   1:  target = 0; break;
+	case   2:  target = 1; break;
+	case   4:  target = 2; break;
+	case   8:  target = 3; break;
+	case  16:  target = 4; break;
+	case  32:  target = 5; break;
+	case  64:  target = 6; break;
+	case 128:  target = 7; break;
+	default:   target = info->host->this_id; break;
+	}
+
+	identify_msg &= 7;
+	info->scsi.reconnected.target = target;
+	info->scsi.reconnected.lun    = identify_msg;
+	info->scsi.reconnected.tag    = 0;
 
-    if (ok) {
-	info->scsi.phase = PHASE_RECONNECTED;
-	outb(target, REG_SDID(info));
-    } else {
-	/*
-	 * Our command structure not found - abort the command on the target
-	 * Should this be INITIATOR_ERROR ?
-	 */
-	outb(CMD_SETATN, REG_CMD(info));
-	msgqueue_addmsg (&info->scsi.msgs, 1, ABORT);
-	info->scsi.phase = PHASE_MSGOUT;
-    }
-    outb(CMD_MSGACCEPTED, REG_CMD(info));
+	ok = 0;
+	if (info->scsi.disconnectable && info->SCpnt &&
+	    info->SCpnt->target == target && info->SCpnt->lun == identify_msg)
+		ok = 1;
+
+	if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg))
+		ok = 1;
+
+	if (ok) {
+		info->scsi.phase = PHASE_RECONNECTED;
+		outb(target, REG_SDID(info));
+	} else {
+		/*
+		 * Our command structure not found - abort the command on the target
+		 * Should this be INITIATOR_ERROR ?
+		 */
+		outb(CMD_SETATN, REG_CMD(info));
+		msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
+		info->scsi.phase = PHASE_MSGOUT;
+	}
+	outb(CMD_MSGACCEPTED, REG_CMD(info));
 }
 
-/* Function: void fas216_finish_reconnect (FAS216_Info *info)
+/* Function: void fas216_finish_reconnect(FAS216_Info *info)
  * Purpose : finish reconnection sequence for device
  * Params  : info - interface which caused function done interrupt
  */
 static void
-fas216_finish_reconnect (FAS216_Info *info)
+fas216_finish_reconnect(FAS216_Info *info)
 {
+	fas216_checkmagic(info, "fas216_reconnect");
+
 #ifdef DEBUG_CONNECT
-printk ("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n",
-	info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag,
-	info->scsi.reconnected.target, info->scsi.reconnected.lun,
-	info->scsi.reconnected.tag);
+	printk("Connected: %1X %1X %02X, reconnected: %1X %1X %02X\n",
+		info->SCpnt->target, info->SCpnt->lun, info->SCpnt->tag,
+		info->scsi.reconnected.target, info->scsi.reconnected.lun,
+		info->scsi.reconnected.tag);
 #endif
 
-    if (info->scsi.disconnectable && info->SCpnt) {
-	info->scsi.disconnectable = 0;
-	if (info->SCpnt->target == info->scsi.reconnected.target &&
-	    info->SCpnt->lun    == info->scsi.reconnected.lun &&
-	    info->SCpnt->tag    == info->scsi.reconnected.tag) {
+	if (info->scsi.disconnectable && info->SCpnt) {
+		info->scsi.disconnectable = 0;
+		if (info->SCpnt->target == info->scsi.reconnected.target &&
+		    info->SCpnt->lun    == info->scsi.reconnected.lun &&
+		    info->SCpnt->tag    == info->scsi.reconnected.tag) {
 #ifdef DEBUG_CONNECT
-	    printk ("scsi%d.%c: reconnected",
-		    info->host->host_no, fas216_target (info));
+			printk("scsi%d.%c: reconnected",
+				info->host->host_no, fas216_target(info));
 #endif
-	} else {
-	    queue_add_cmd_tail (&info->queues.disconnected, info->SCpnt);
+		} else {
+			queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
 #ifdef DEBUG_CONNECT
-	    printk ("scsi%d.%c: had to move command to disconnected queue\n",
-			info->host->host_no, fas216_target (info));
+			printk("scsi%d.%c: had to move command to disconnected queue\n",
+				info->host->host_no, fas216_target(info));
 #endif
-	    info->SCpnt = NULL;
+			info->SCpnt = NULL;
+		}
 	}
-    }
-    if (!info->SCpnt) {
-	info->SCpnt = queue_remove_tgtluntag (&info->queues.disconnected,
-				info->scsi.reconnected.target,
-				info->scsi.reconnected.lun,
-				info->scsi.reconnected.tag);
+	if (!info->SCpnt) {
+		info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected,
+					info->scsi.reconnected.target,
+					info->scsi.reconnected.lun,
+					info->scsi.reconnected.tag);
 #ifdef DEBUG_CONNECT
-	printk ("scsi%d.%c: had to get command",
-		info->host->host_no, fas216_target (info));
+		printk("scsi%d.%c: had to get command",
+			info->host->host_no, fas216_target(info));
 #endif
-    }
-    if (!info->SCpnt) {
-	outb(CMD_SETATN, REG_CMD(info));
-	msgqueue_addmsg (&info->scsi.msgs, 1, ABORT);
-	info->scsi.phase = PHASE_MSGOUT;
-	info->scsi.aborting = 1;
-    } else {
-	/*
-	 * Restore data pointer from SAVED data pointer
-	 */
-	info->scsi.SCp = info->SCpnt->SCp;
+	}
+	if (!info->SCpnt) {
+		outb(CMD_SETATN, REG_CMD(info));
+		msgqueue_addmsg(&info->scsi.msgs, 1, ABORT);
+		info->scsi.phase = PHASE_MSGOUT;
+		info->scsi.aborting = 1;
+	} else {
+		/*
+		 * Restore data pointer from SAVED data pointer
+		 */
+		info->scsi.SCp = info->SCpnt->SCp;
 #ifdef DEBUG_CONNECT
-	printk (", data pointers: [%p, %X]",
-		info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
+		printk(", data pointers: [%p, %X]",
+			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
 #endif
-    }
+	}
 #ifdef DEBUG_CONNECT
-    printk ("\n");
+	printk("\n");
 #endif
 }
 
-/* Function: void fas216_message (FAS216_Info *info)
+/* Function: void fas216_message(FAS216_Info *info)
  * Purpose : handle a function done interrupt from FAS216 chip
  * Params  : info - interface which caused function done interrupt
  */
-static void fas216_message (FAS216_Info *info)
+static void fas216_message(FAS216_Info *info)
 {
-    unsigned char message[16];
-    unsigned int msglen = 1;
+	unsigned char message[16];
+	unsigned int msglen = 1;
+
+	fas216_checkmagic(info, "fas216_message");
+
+	message[0] = inb(REG_FF(info));
 
-    message[0] = inb(REG_FF(info));
+	if (message[0] == EXTENDED_MESSAGE) {
+		int tout;
+		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		for (tout = 1000000; tout; tout--)
+			if (inb(REG_STAT(info)) & STAT_INT)
+				break;
+		inb(REG_INST(info));
+		outb(CMD_TRANSFERINFO, REG_CMD(info));
+		for (tout = 1000000; tout; tout--)
+			if (inb(REG_STAT(info)) & STAT_INT)
+				break;
+		inb(REG_INST(info));
 
-    if (message[0] == EXTENDED_MESSAGE) {
-	message[1] = inb(REG_FF(info));
+		message[1] = inb(REG_FF(info));
 
-	for (msglen = 2; msglen < message[1]; msglen++)
-	    message[msglen] = inb(REG_FF(info));
-    }
+		for (msglen = 2; msglen < message[1] + 2; msglen++) {
+			outb(CMD_MSGACCEPTED, REG_CMD(info));
+			for (tout = 1000000; tout; tout--)
+				if (inb(REG_STAT(info)) & STAT_INT)
+					break;
+			inb(REG_INST(info));
+			outb(CMD_TRANSFERINFO, REG_CMD(info));
+			for (tout = 1000000; tout; tout--)
+				if (inb(REG_STAT(info)) & STAT_INT)
+					break;
+			inb(REG_INST(info));
+
+			message[msglen] = inb(REG_FF(info));
+		}
+	}
 
 #ifdef DEBUG_MESSAGES
-    {
-	int i;
+	{
+		int i;
+
+		printk("scsi%d.%c: message in: ",
+			info->host->host_no, fas216_target(info));
+		for (i = 0; i < msglen; i++)
+			printk("%02X ", message[i]);
+		printk("\n");
+	}
+#endif
+	if (info->scsi.phase == PHASE_RECONNECTED) {
+		if (message[0] == SIMPLE_QUEUE_TAG)
+			info->scsi.reconnected.tag = message[1];
+		fas216_finish_reconnect(info);
+		info->scsi.phase = PHASE_MSGIN;
+	}
 
-	printk ("scsi%d.%c: message in: ",
-		info->host->host_no, fas216_target (info));
-	for (i = 0; i < msglen; i++)
-	    printk ("%02X ", message[i]);
-	printk ("\n");
-    }
-#endif
-    if (info->scsi.phase == PHASE_RECONNECTED) {
-	if (message[0] == SIMPLE_QUEUE_TAG)
-	    info->scsi.reconnected.tag = message[1];
-	fas216_finish_reconnect (info);
-	info->scsi.phase = PHASE_MSGIN;
-    }	
-
-    switch (message[0]) {
-    case COMMAND_COMPLETE:
-	printk ("fas216: command complete with no status in MESSAGE_IN?\n");
-	break;
+	switch (message[0]) {
+	case COMMAND_COMPLETE:
+		printk("fas216: command complete with no status in MESSAGE_IN?\n");
+		break;
 
-    case SAVE_POINTERS:
-	/*
-	 * Save current data pointer to SAVED data pointer
-	 */
-	info->SCpnt->SCp = info->scsi.SCp;
+	case SAVE_POINTERS:
+		/*
+		 * Save current data pointer to SAVED data pointer
+		 */
+		info->SCpnt->SCp = info->scsi.SCp;
 #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
-	printk ("scsi%d.%c: save data pointers: [%p, %X]\n",
-		info->host->host_no, fas216_target (info),
-		info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
+		printk("scsi%d.%c: save data pointers: [%p, %X]\n",
+			info->host->host_no, fas216_target(info),
+			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
 #endif
-	break;
+		break;
 
-    case RESTORE_POINTERS:
-	/*
-	 * Restore current data pointer from SAVED data pointer
-	 */
-	info->scsi.SCp = info->SCpnt->SCp;
+	case RESTORE_POINTERS:
+		/*
+		 * Restore current data pointer from SAVED data pointer
+		 */
+		info->scsi.SCp = info->SCpnt->SCp;
 #if defined (DEBUG_MESSAGES) || defined (DEBUG_CONNECT)
-	printk ("scsi%d.%c: restore data pointers: [%p, %X]\n",
-		info->host->host_no, fas216_target (info),
-		info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
+		printk("scsi%d.%c: restore data pointers: [%p, %X]\n",
+			info->host->host_no, fas216_target(info),
+			info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
 #endif
-	break;
+		break;
+
+	case DISCONNECT:
+		info->scsi.phase = PHASE_DISCONNECT;
+		break;
+
+	case MESSAGE_REJECT:
+		printk("scsi%d.%c: reject, last message %04X\n",
+			info->host->host_no, fas216_target(info),
+			info->scsi.last_message);
+		break;
+
+	case SIMPLE_QUEUE_TAG:
+		/* handled above */
+		printk("scsi%d.%c: reconnect queue tag %02X\n",
+			info->host->host_no, fas216_target(info),
+			message[1]);
+		break;
+
+	case EXTENDED_MESSAGE:
+		switch (message[2]) {
+		case EXTENDED_SDTR:	/* Sync transfer negociation request/reply */
+			switch (info->device[info->SCpnt->target].negstate) {
+			case syncneg_invalid:
+				msgqueue_flush(&info->scsi.msgs);
+				outb(CMD_SETATN, REG_CMD(info));
+				msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
+				info->scsi.phase = PHASE_MSGOUT;
+				break;
 
-    case DISCONNECT:
-	info->scsi.phase = PHASE_DISCONNECT;
-	break;
-
-    case MESSAGE_REJECT:
-	printk ("scsi%d.%c: reject, last message %04X\n",
-		info->host->host_no, fas216_target (info),
-		info->scsi.last_message);
-	break;
-
-    case SIMPLE_QUEUE_TAG:
-	/* handled above */
-	printk ("scsi%d.%c: reconnect queue tag %02X\n",
-		info->host->host_no, fas216_target (info),
-		message[1]);
-	break;
-
-    case EXTENDED_MESSAGE:
-	switch (message[2]) {
-	case EXTENDED_SDTR:	/* Sync transfer negociation request/reply */
+			default:
+				if (message[4] > info->ifcfg.sync_max_depth)
+					message[4] = info->ifcfg.sync_max_depth;
+				if (message[3] < 1000 / info->ifcfg.clockrate)
+					message[3] = 1000 / info->ifcfg.clockrate;
+
+				outb(CMD_SETATN, REG_CMD(info));
+				msgqueue_addmsg(&info->scsi.msgs, 5,
+						EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
+						message[3], message[4]);
+				info->scsi.phase = PHASE_MSGOUT;
+			case syncneg_sent:
+				info->device[info->SCpnt->target].negstate = syncneg_complete;
+				info->device[info->SCpnt->target].sof = message[4];
+				info->device[info->SCpnt->target].stp =
+					fas216_syncperiod(info, message[3] * 4);
+				printk(KERN_NOTICE "scsi%d.%c: using synchronous transfer, offset %d, %d ns\n",
+					info->host->host_no, fas216_target(info), message[4], message[3] * 4);
+				outb(info->device[info->SCpnt->target].sof, REG_SOF(info));
+				outb(info->device[info->SCpnt->target].stp, REG_STP(info));
+				break;
+			}
+			break;
+
+		case EXTENDED_WDTR:	/* Wide transfer negociation request/reply */
+			/* We don't do wide transfers - reject message */
+		default:
+			printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n",
+				info->host->host_no, fas216_target(info),
+				message[2]);
+			msgqueue_flush(&info->scsi.msgs);
+			outb(CMD_SETATN, REG_CMD(info));
+			msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
+			info->scsi.phase = PHASE_MSGOUT;
+			break;
+		}
+		break;
 
-	case EXTENDED_WDTR:	/* Wide transfer negociation request/reply */
-		/* We don't do wide transfers - reject message */
 	default:
-		printk("scsi%d.%c: unrecognised extended message %02X, rejecting\n",
-			info->host->host_no, fas216_target (info),
-			message[2]);
-		msgqueue_flush (&info->scsi.msgs);
+		printk("scsi%d.%c: unrecognised message %02X, rejecting\n",
+			info->host->host_no, fas216_target(info),
+			message[0]);
+		msgqueue_flush(&info->scsi.msgs);
 		outb(CMD_SETATN, REG_CMD(info));
-		msgqueue_addmsg (&info->scsi.msgs, 1, MESSAGE_REJECT);
+		msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT);
 		info->scsi.phase = PHASE_MSGOUT;
 		break;
 	}
-	break;
+	outb(CMD_MSGACCEPTED, REG_CMD(info));
+}
 
-    default:
-	printk ("scsi%d.%c: unrecognised message %02X, rejecting\n",
-		info->host->host_no, fas216_target (info),
-		message[0]);
-	msgqueue_flush (&info->scsi.msgs);
-	outb(CMD_SETATN, REG_CMD(info));
-	msgqueue_addmsg (&info->scsi.msgs, 1, MESSAGE_REJECT);
-	info->scsi.phase = PHASE_MSGOUT;
-	break;
-    }
-    outb(CMD_MSGACCEPTED, REG_CMD(info));
+/* Function: void fas216_send_command(FAS216_Info *info)
+ * Purpose : send a command to a target after all message bytes have been sent
+ * Params  : info - interface which caused bus service
+ */
+static void fas216_send_command(FAS216_Info *info)
+{
+	int i;
+
+	fas216_checkmagic(info, "fas216_send_command");
+
+	outb(CMD_NOP|CMD_WITHDMA, REG_CMD(info));
+	outb(CMD_FLUSHFIFO, REG_CMD(info));
+
+	/* load command */
+	for (i = 0; i < info->SCpnt->cmd_len; i++)
+		outb(info->SCpnt->cmnd[i], REG_FF(info));
+
+	outb(CMD_TRANSFERINFO, REG_CMD(info));
 }
 
-/* Function: void fas216_busservice_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr)
- * Purpose : handle a bus service interrupt from FAS216 chip
- * Params  : info - interface which caused bus service interrupt
- *           stat - Status register contents
- *           ssr  - SCSI Status register contents
+/* Function: int fas216_busservice_selection(FAS216_Info *info, unsigned int stat)
+ * Purpose : handle bus service in selection phase
+ * Params  : info - interface which caused bus service
+ * Returns : 0 if unable to service this interrupt
  */
-static void fas216_busservice_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr)
+static int fas216_busservice_selection(FAS216_Info *info, unsigned int stat)
 {
-    int i;
-#ifdef DEBUG_BUSSERVICE
-    printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n",
-	   info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
-#endif
-    switch (ssr & IS_BITS) {
-    case IS_COMPLETE:			/* last action completed		*/
-	outb(CMD_NOP, REG_CMD(info));
+	fas216_checkmagic(info, "fas216_busservice_selection");
 
-	switch (info->scsi.phase) {
-	case PHASE_SELECTION:		/* while selecting - selected target	*/
-	    switch (stat & STAT_BUSMASK) {
-	    case STAT_DATAOUT:	/* data out phase			*/
-		fas216_starttransfer (info, DMA_OUT);
-		break;
+	switch (stat & STAT_BUSMASK) {
+	case STAT_DATAOUT:	/* data out phase			*/
+		fas216_starttransfer(info, DMA_OUT, 1);
+		return 1;
 
-	    case STAT_DATAIN:		/* data in phase			*/
-		fas216_starttransfer (info, DMA_IN);
-		break;
+	case STAT_DATAIN:		/* data in phase		*/
+		fas216_starttransfer(info, DMA_IN, 0);
+		return 1;
 
-	    case STAT_STATUS:		/* status phase				*/
+	case STAT_STATUS:		/* status phase			*/
 		info->scsi.phase = PHASE_STATUS;
 		outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
-		break;
+		return 1;
 
-	    case STAT_MESGIN:		/* message in phase			*/
+	case STAT_MESGIN:		/* message in phase		*/
 		info->scsi.phase = PHASE_MSGIN;
 		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		break;
+		return 1;
 
-	    default:			/* other				*/
-		printk ("scsi%d.%c: bus phase %s after connect?\n",
-			info->host->host_no, fas216_target (info),
-			fas216_bus_phase (stat));
-		break;
-	    }
-	    break;
+	case STAT_MESGOUT:{		/* message out phase		*/
+		char *msg;
+		int start = 1, msglen;
 
-	case PHASE_DATAIN:		/* while transfering data in		*/
-	    switch (stat & STAT_BUSMASK) {
-	    case STAT_DATAIN:		/* continue data in phase		*/
-		fas216_starttransfer (info, DMA_IN);
-		break;
+		/* load message bytes, but don't forget to miss the first
+		 * byte!
+		 */
+		while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) {
+			int i;
 
-	    case STAT_STATUS:
-		fas216_stoptransfer(info);
-		info->scsi.phase = PHASE_STATUS;
-		outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
-		break;
+			for (i = start; i < msglen; i++)
+				outb(msg[i], REG_FF(info));
+			start = 0;
+		}
+		outb(CMD_TRANSFERINFO, REG_CMD(info));
+		info->scsi.phase = PHASE_MESSAGESENT;
+		return 1;
+	}
+	default:
+		return 0;
+	}
+}
 
-	    case STAT_MESGIN:		/* message in phase			*/
-		fas216_stoptransfer(info);
+/* Function: int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat)
+ * Purpose : handle bus service after the IDENTIFY message has been sent
+ * Params  : info - interface which caused bus service
+ * Returns : 0 if unable to service this interrupt
+ */
+static int fas216_busservice_messagesent(FAS216_Info *info, unsigned int stat)
+{
+	fas216_checkmagic(info, "fas216_busservice_messagesent");
+
+	switch (stat & STAT_BUSMASK) {
+	case STAT_MESGIN:		/* message in phase		*/
 		info->scsi.phase = PHASE_MSGIN;
+		outb(CMD_FLUSHFIFO, REG_CMD(info));
 		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		break;
+		return 1;
 
-	    default:
-		printk ("scsi%d.%c: bus phase %s after data in?\n",
-			info->host->host_no, fas216_target (info),
-			fas216_bus_phase (stat));
-	    }
-	    break;
-
-	case PHASE_DATAOUT:		/* while transfering data out		*/
-	    switch (stat & STAT_BUSMASK) {
-	    case STAT_DATAOUT:
-		fas216_starttransfer (info, DMA_OUT);
-		break;
+	case STAT_COMMAND:		/* command phase		*/
+		fas216_send_command(info);
+		return 1;
+
+	default:
+		return 0;
+	}
+}
 
-	    case STAT_STATUS:
+/* Function: int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat)
+ * Purpose : handle bus service in a data in/out phase.
+ * Params  : info - interface which caused bus service
+ * Returns : 0 if unable to service this interrupt
+ * Note    : We do not allow the device to change the data direction!
+ */
+static int fas216_busservice_dataphase(FAS216_Info *info, unsigned int stat)
+{
+	fas216_checkmagic(info, "fas216_busservice_dataphase");
+
+	switch (stat & STAT_BUSMASK) {
+	case STAT_DATAIN:		/* continue data in phase	*/
+		if (info->scsi.phase == PHASE_DATAIN) {
+			fas216_starttransfer(info, DMA_IN, 0);
+			return 1;
+		} else
+			return 0;
+
+	case STAT_DATAOUT:		/* continue data out phase	*/
+		if (info->scsi.phase == PHASE_DATAOUT) {
+			fas216_starttransfer(info, DMA_OUT, 0);
+			return 1;
+		} else
+			return 0;
+
+	case STAT_STATUS:		/* status in phase		*/
 		fas216_stoptransfer(info);
 		info->scsi.phase = PHASE_STATUS;
-		outb(CMD_FLUSHFIFO, REG_CMD(info));
 		outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
-		break;
+		return 1;
 
-	    case STAT_MESGIN:		/* message in phase			*/
+	case STAT_MESGIN:		/* message in phase		*/
 		fas216_stoptransfer(info);
 		info->scsi.phase = PHASE_MSGIN;
-		outb(CMD_FLUSHFIFO, REG_CMD(info));
 		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		break;
+		return 1;
+
+	default:
+		return 0;
+	}
+}
+
+/* Function: int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat)
+ * Purpose : handle bus service in after a reconnection
+ * Params  : info - interface which caused bus service
+ * Returns : 0 if unable to service this interrupt
+ * Note    : We do not allow the device to change the data direction!
+ */
+static int fas216_busservice_reconnected(FAS216_Info *info, unsigned int stat)
+{
+	fas216_checkmagic(info, "fas216_busservice_reconnected");
 
-	    default:
-		printk ("scsi%d.%c: bus phase %s after data out?\n",
-			info->host->host_no, fas216_target (info),
-			fas216_bus_phase (stat));
-	    }
-	    break;
-
-	case PHASE_RECONNECTED:		/* newly reconnected device		*/
-	    /*
-	     * Command reconnected - if MESGIN, get message - it may be
-	     * the tag.  If not, get command out of the disconnected queue
-	     */
-	    switch (stat & STAT_BUSMASK) {
-	    case STAT_MESGIN:
+	switch (stat & STAT_BUSMASK) {
+	case STAT_MESGIN:
 		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		break;
+		return 1;
 
-	    case STAT_STATUS:
-		fas216_finish_reconnect (info);
+	case STAT_STATUS:
+		fas216_finish_reconnect(info);
 		info->scsi.phase = PHASE_STATUS;
 		outb(CMD_INITCMDCOMPLETE, REG_CMD(info));
-		break;
+		return 1;
 
-	    case STAT_DATAOUT:		/* data out phase			*/
-		fas216_finish_reconnect (info);
-		fas216_starttransfer (info, DMA_OUT);
-		break;
-
-	    case STAT_DATAIN:		/* data in phase			*/
-		fas216_finish_reconnect (info);
-		fas216_starttransfer (info, DMA_IN);
-		break;
-
-	    default:
-		printk ("scsi%d.%c: bus phase %s after reconnect?\n",
-			info->host->host_no, fas216_target (info),
-			fas216_bus_phase (stat));
-	    }
-	    break;
-
-	case PHASE_MSGIN:
-	    switch (stat & STAT_BUSMASK) {
-	    case STAT_MESGIN:
-		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		break;
+	case STAT_DATAOUT:		/* data out phase		*/
+		fas216_finish_reconnect(info);
+		fas216_starttransfer(info, DMA_OUT, 1);
+		return 1;
+
+	case STAT_DATAIN:		/* data in phase		*/
+		fas216_finish_reconnect(info);
+		fas216_starttransfer(info, DMA_IN, 0);
+		return 1;
+
+	default:
+		return 0;
+	}
+}
 
-	    default:
-		printk ("scsi%d.%c: bus phase %s after message in?\n",
-			info->host->host_no, fas216_target (info),
-			fas216_bus_phase (stat));
-	    }
-	    break;
-
-	case PHASE_MSGOUT:
-	    if ((stat & STAT_BUSMASK) != STAT_MESGOUT) {
-		printk ("scsi%d.%c: didn't manage MESSAGE OUT phase\n",
-			info->host->host_no, fas216_target (info));
-	    } else {
-		unsigned int msglen;
+/* Function: int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat)
+ * Purpose : handle bus service to send a message
+ * Params  : info - interface which caused bus service
+ * Returns : 0 if unable to service this interrupt
+ * Note    : We do not allow the device to change the data direction!
+ */
+static int fas216_busservice_messageout(FAS216_Info *info, unsigned int stat)
+{
+	fas216_checkmagic(info, "fas216_busservice_messageout");
 
-		msglen = msgqueue_msglength (&info->scsi.msgs);
+	if ((stat & STAT_BUSMASK) != STAT_MESGOUT) {
+		printk("scsi%d.%c: didn't manage MESSAGE OUT phase\n",
+		       info->host->host_no, fas216_target(info));
+		return 0;
+	} else {
+		unsigned int msglen = msgqueue_msglength(&info->scsi.msgs);
 
 		outb(CMD_FLUSHFIFO, REG_CMD(info));
 
 		if (msglen == 0)
-		    outb(NOP, REG_FF(info));
+			outb(NOP, REG_FF(info));
 		else {
-		    char *msg;
+			char *msg;
 
-		    while ((msg = msgqueue_getnextmsg (&info->scsi.msgs, &msglen)) != NULL) {
-			for (i = 0; i < msglen; i++)
-			    outb(msg[i], REG_FF(info));
-		    }
+			while ((msg = msgqueue_getnextmsg(&info->scsi.msgs, &msglen)) != NULL) {
+				int i;
+
+				for (i = 0; i < msglen; i++)
+					outb(msg[i], REG_FF(info));
+			}
 		}
 		outb(CMD_TRANSFERINFO, REG_CMD(info));
 		info->scsi.phase = PHASE_AFTERMSGOUT;
-	    }
-	    break;
+		return 1;
+	}
+}
 
-	case PHASE_AFTERMSGOUT:
-	    switch (stat & STAT_BUSMASK) {
-	    case STAT_MESGIN:
-		info->scsi.phase = PHASE_MSGIN;
-		outb(CMD_TRANSFERINFO, REG_CMD(info));
-		break;
+/* Function: void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
+ * Purpose : handle a bus service interrupt from FAS216 chip
+ * Params  : info - interface which caused bus service interrupt
+ *           stat - Status register contents
+ *           ssr  - SCSI Status register contents
+ */
+static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
+{
+	fas216_checkmagic(info, "fas216_busservice_intr");
+
+#ifdef DEBUG_BUSSERVICE
+	printk("scsi%d.%c: bus service: stat=%02X ssr=%02X phase=%02X\n",
+		info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
+#endif
+	switch (ssr & IS_BITS) {
+	case IS_MSGBYTESENT:		/* select with ATN and stop steps completed	*/
+	case IS_COMPLETE:			/* last action completed		*/
+		outb(CMD_NOP, REG_CMD(info));
 
-	    default:
-		printk ("scsi%d.%c: bus phase %s after message out\n",
-			info->host->host_no, fas216_target (info),
-			fas216_bus_phase (stat));
-	    }
-	    break;
-
-	case PHASE_DISCONNECT:
-	    printk ("scsi%d.%c: disconnect message received, but bus service %s?\n",
-		    info->host->host_no, fas216_target (info),
-		    fas216_bus_phase (stat));
-	    outb(CMD_SETATN, REG_CMD(info));
-	    msgqueue_addmsg (&info->scsi.msgs, 1, ABORT);
-	    info->scsi.phase = PHASE_MSGOUT;
-	    info->scsi.aborting = 1;
-	    outb(CMD_TRANSFERINFO, REG_CMD(info));
-	    break;
+		switch (info->scsi.phase) {
+		case PHASE_SELECTION:		/* while selecting - selected target	*/
+			if (!fas216_busservice_selection(info, stat))
+				printk("scsi%d.%c: bus phase %s after connect?\n",
+					info->host->host_no, fas216_target(info),
+					fas216_bus_phase(stat));
+			break;
+
+		case PHASE_MESSAGESENT:
+			if (!fas216_busservice_messagesent(info, stat))
+				printk("scsi%d.%c: bus phase %s after message sent?\n",
+					info->host->host_no, fas216_target(info),
+					fas216_bus_phase(stat));
+			break;
+
+		case PHASE_DATAIN:		/* while transfering data in		*/
+		case PHASE_DATAOUT:		/* while transfering data out		*/
+			if (!fas216_busservice_dataphase(info, stat))
+				printk("scsi%d.%c: bus phase %s after %s?\n",
+					info->host->host_no, fas216_target(info),
+					fas216_bus_phase(stat), fas216_drv_phase(info));
+			break;
+
+		case PHASE_RECONNECTED:		/* newly reconnected device		*/
+			/*
+			 * Command reconnected - if MESGIN, get message - it may be
+			 * the tag.  If not, get command out of the disconnected queue
+			 */
+			if (!fas216_busservice_reconnected(info, stat))
+				printk("scsi%d.%c: bus phase %s after reconnect?\n",
+					info->host->host_no, fas216_target(info),
+					fas216_bus_phase(stat));
+			break;
+
+		case PHASE_MSGIN:
+		case PHASE_AFTERMSGOUT:
+			switch (stat & STAT_BUSMASK) {
+			case STAT_MESGIN:
+				info->scsi.phase = PHASE_MSGIN;
+				outb(CMD_TRANSFERINFO, REG_CMD(info));
+				break;
+
+			case STAT_COMMAND:	/* command phase			*/
+				fas216_send_command(info);
+				info->scsi.phase = PHASE_SELECTION;
+				break;
+
+			default:
+				printk("scsi%d.%c: bus phase %s after %s?\n",
+					info->host->host_no, fas216_target(info),
+					fas216_bus_phase(stat),
+					fas216_drv_phase(info));
+			}
+			break;
+
+		case PHASE_MSGOUT:
+			if (!fas216_busservice_messageout(info, stat))
+				printk("scsi%d.%c: bus phase %s instead of message out?\n",
+					info->host->host_no, fas216_target(info),
+					fas216_bus_phase(stat));
+			break;
+
+		case PHASE_DISCONNECT:
+			printk("scsi%d.%c: disconnect message received, but bus service %s?\n",
+				info->host->host_no, fas216_target(info),
+				fas216_bus_phase(stat));
+			outb(CMD_SETATN, REG_CMD(info));
+			msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR);
+			info->scsi.phase = PHASE_MSGOUT;
+			info->scsi.aborting = 1;
+			outb(CMD_TRANSFERINFO, REG_CMD(info));
+			break;
+
+		default:
+			printk("scsi%d.%c: internal phase %s for bus service?"
+				"  What do I do with this?\n",
+				info->host->host_no, fas216_target(info),
+				fas216_drv_phase(info));
+		}
+		break;
 
 	default:
-	    printk ("scsi%d.%c: internal phase %d for bus service?"
-		    "  What do I do with this?\n",
-		    info->host->host_no, fas216_target (info),
-		    info->scsi.phase);
+		printk("scsi%d.%c: bus service at step %d?\n",
+			info->host->host_no, fas216_target(info),
+			ssr & IS_BITS);
 	}
-	break;
-
-    default:
-	printk ("scsi%d.%c: bus service at step %d?\n",
-		info->host->host_no, fas216_target (info),
-		ssr & IS_BITS);
-    }
 }
 
-/* Function: void fas216_funcdone_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr)
+/* Function: void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
  * Purpose : handle a function done interrupt from FAS216 chip
  * Params  : info - interface which caused function done interrupt
  *           stat - Status register contents
  *           ssr  - SCSI Status register contents
  */
-static void fas216_funcdone_intr (FAS216_Info *info, unsigned int stat, unsigned int ssr)
+static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr)
 {
-    int status, message;
+	int status, message;
+
+	fas216_checkmagic(info, "fas216_funcdone_intr");
+
 #ifdef DEBUG_FUNCTIONDONE
-    printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n",
-	   info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
+	printk("scsi%d.%c: function done: stat=%X ssr=%X phase=%02X\n",
+		info->host->host_no, fas216_target(info), stat, ssr, info->scsi.phase);
 #endif
-    switch (info->scsi.phase) {
-    case PHASE_STATUS:			/* status phase - read status and msg	*/
-	status = inb(REG_FF(info));
-	message = inb(REG_FF(info));
-	info->scsi.SCp.Message = message;
-	info->scsi.SCp.Status = status;
-	info->scsi.phase = PHASE_DONE;
-	outb(CMD_MSGACCEPTED, REG_CMD(info));
-	break;
+	switch (info->scsi.phase) {
+	case PHASE_STATUS:			/* status phase - read status and msg	*/
+		status = inb(REG_FF(info));
+		message = inb(REG_FF(info));
+		info->scsi.SCp.Message = message;
+		info->scsi.SCp.Status = status;
+		info->scsi.phase = PHASE_DONE;
+		outb(CMD_MSGACCEPTED, REG_CMD(info));
+		break;
 
-    case PHASE_IDLE:			/* reselected?				*/
-    case PHASE_MSGIN:			/* message in phase			*/
-    case PHASE_RECONNECTED:		/* reconnected command			*/
-	if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
-	    fas216_message (info);
-	    break;
-	}
+	case PHASE_IDLE:			/* reselected?				*/
+	case PHASE_MSGIN:			/* message in phase			*/
+	case PHASE_RECONNECTED:			/* reconnected command			*/
+		if ((stat & STAT_BUSMASK) == STAT_MESGIN) {
+			fas216_message(info);
+			break;
+		}
 
-    default:
-	printk ("scsi%d.%c: internal phase %d for function done?"
-		"  What do I do with this?\n",
-		info->host->host_no, fas216_target (info),
-		info->scsi.phase);
-    }
+	default:
+		printk("scsi%d.%c: internal phase %s for function done?"
+			"  What do I do with this?\n",
+			info->host->host_no, fas216_target(info),
+			fas216_drv_phase(info));
+	}
 }
 
-/* Function: void fas216_intr (struct Scsi_Host *instance)
+/* Function: void fas216_intr(struct Scsi_Host *instance)
  * Purpose : handle interrupts from the interface to progress a command
  * Params  : instance - interface to service
  */
-void fas216_intr (struct Scsi_Host *instance)
+void fas216_intr(struct Scsi_Host *instance)
 {
-    FAS216_Info *info = (FAS216_Info *)instance->hostdata;
-    unsigned char isr, ssr, stat;
+	FAS216_Info *info = (FAS216_Info *)instance->hostdata;
+	unsigned char isr, ssr, stat;
+
+	fas216_checkmagic(info, "fas216_intr");
 
-    stat = inb(REG_STAT(info));
-    ssr = inb(REG_IS(info));
-    isr = inb(REG_INST(info));
-
-    if (isr & INST_BUSRESET)
-	printk ("scsi%d.H: fas216: bus reset detected\n", instance->host_no);
-    else if (isr & INST_ILLEGALCMD)
-	printk (KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no);
-    else if (isr & INST_DISCONNECT)
-	fas216_disconnect_intr (info);
-    else if (isr & INST_RESELECTED)		/* reselected			*/
-	fas216_reselected_intr (info);
-    else if (isr & INST_BUSSERVICE)		/* bus service request		*/
-	fas216_busservice_intr (info, stat, ssr);
-    else if (isr & INST_FUNCDONE)		/* function done		*/
-	fas216_funcdone_intr (info, stat, ssr);
-    else
-    	printk ("scsi%d.%c: unknown interrupt received:"
-		" phase %d isr %02X ssr %02X stat %02X\n",
-		instance->host_no, fas216_target (info),
-		info->scsi.phase, isr, ssr, stat);
+	stat = inb(REG_STAT(info));
+	ssr = inb(REG_IS(info));
+	isr = inb(REG_INST(info));
+
+	add_debug_list(stat, ssr, isr, info->scsi.phase);
+
+	if (stat & STAT_INT) {
+		if (isr & INST_BUSRESET)
+			printk("scsi%d.H: fas216: bus reset detected\n", instance->host_no);
+		else if (isr & INST_ILLEGALCMD)
+			printk(KERN_CRIT "scsi%d.H: illegal command given\n", instance->host_no);
+		else if (isr & INST_DISCONNECT)
+			fas216_disconnect_intr(info);
+		else if (isr & INST_RESELECTED)		/* reselected			*/
+			fas216_reselected_intr(info);
+		else if (isr & INST_BUSSERVICE)		/* bus service request		*/
+			fas216_busservice_intr(info, stat, ssr);
+		else if (isr & INST_FUNCDONE)		/* function done		*/
+			fas216_funcdone_intr(info, stat, ssr);
+		else
+		    	printk("scsi%d.%c: unknown interrupt received:"
+				" phase %s isr %02X ssr %02X stat %02X\n",
+				instance->host_no, fas216_target(info),
+				fas216_drv_phase(info), isr, ssr, stat);
+	}
 }
 
-/* Function: void fas216_kick (FAS216_Info *info)
+/* Function: void fas216_kick(FAS216_Info *info)
  * Purpose : kick a command to the interface - interface should be idle
  * Params  : info - our host interface to kick
  * Notes   : Interrupts are always disabled!
  */
-static void fas216_kick (FAS216_Info *info)
+static void fas216_kick(FAS216_Info *info)
 {
 	Scsi_Cmnd *SCpnt;
 	int i, msglen, from_queue = 0;
 
+	fas216_checkmagic(info, "fas216_kick");
+
 	if (info->origSCpnt) {
 		SCpnt = info->origSCpnt;
 		info->origSCpnt = NULL;
@@ -943,11 +1321,11 @@
 		return;
 
 	if (info->scsi.disconnectable && info->SCpnt) {
-		queue_add_cmd_tail (&info->queues.disconnected, info->SCpnt);
+		queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt);
 		info->scsi.disconnectable = 0;
 		info->SCpnt = NULL;
 		printk("scsi%d.%c: moved command to disconnected queue\n",
-			info->host->host_no, fas216_target (info));
+			info->host->host_no, fas216_target(info));
 	}
 
 	/*
@@ -1004,7 +1382,7 @@
 	}
 
 	/* build outgoing message bytes */
-	msgqueue_flush (&info->scsi.msgs);
+	msgqueue_flush(&info->scsi.msgs);
 	if (info->device[SCpnt->target].disconnect_ok)
 		msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(1, SCpnt->lun));
 	else
@@ -1015,7 +1393,8 @@
 		msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag);
 
 	/* add synchronous negociation */
-	if (info->device[SCpnt->target].negstate == syncneg_start) {
+	if (SCpnt->cmnd[0] == REQUEST_SENSE &&
+	    info->device[SCpnt->target].negstate == syncneg_start) {
 		info->device[SCpnt->target].negstate = syncneg_sent;
 		msgqueue_addmsg(&info->scsi.msgs, 5,
 				EXTENDED_MESSAGE, 3, EXTENDED_SDTR,
@@ -1040,9 +1419,12 @@
 	outb(info->device[SCpnt->target].sof, REG_SOF(info));
 	outb(info->device[SCpnt->target].stp, REG_STP(info));
 
-	msglen = msgqueue_msglength (&info->scsi.msgs);
+	msglen = msgqueue_msglength(&info->scsi.msgs);
 
 	if (msglen == 1 || msglen == 3) {
+		/*
+		 * We have an easy message length to send...
+		 */
 		char *msg;
 
 		/* load message bytes */
@@ -1060,6 +1442,22 @@
 		else
 			outb(CMD_SELECTATN3, REG_CMD(info));
 	} else {
+		/*
+		 * We have an unusual number of message bytes to send.
+		 *  Load first byte into fifo, and issue SELECT with ATN and
+		 *  stop steps.
+		 * Note: we only peek at t his message - we need the rest
+		 * later on!
+		 */
+		int thismsg;
+		char *msg = msgqueue_peeknextmsg(&info->scsi.msgs, &thismsg);
+
+		if (!msg || thismsg < 1)
+			printk(KERN_CRIT "scsi%d.%c: no message to send, but %d bytes\n",
+				info->host->host_no, fas216_target(info), msglen);
+		else
+			outb(msg[0], REG_FF(info));
+
 		outb(CMD_SELECTATNSTOP, REG_CMD(info));
 	}
 
@@ -1070,79 +1468,95 @@
 	/* should now get either DISCONNECT or (FUNCTION DONE with BUS SERVICE) intr */
 }
 
-/* Function: void fas216_done (FAS216_Info *info, unsigned int result)
+/* Function: void fas216_done(FAS216_Info *info, unsigned int result)
  * Purpose : complete processing for command
  * Params  : info   - interface that completed
  *	     result - driver byte of result
  */
-static void fas216_done (FAS216_Info *info, unsigned int result)
+static void fas216_done(FAS216_Info *info, unsigned int result)
 {
-    Scsi_Cmnd *SCpnt = info->SCpnt;
+	Scsi_Cmnd *SCpnt;
 
-    if (info->scsi.aborting) {
-	printk ("scsi%d.%c: uncaught abort - returning DID_ABORT\n",
-		info->host->host_no, fas216_target (info));
-	result = DID_ABORT;
-	info->scsi.aborting = 0;
-    }
+	fas216_checkmagic(info, "fas216_done");
 
-    info->stats.fins += 1;
+	SCpnt = info->SCpnt;
 
-    if (SCpnt) {
-    	info->scsi.phase = PHASE_IDLE;
-	info->SCpnt = NULL;
+	if (info->scsi.aborting) {
+		printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n",
+			info->host->host_no, fas216_target(info));
+		result = DID_ABORT;
+		info->scsi.aborting = 0;
+	}
+
+	info->stats.fins += 1;
+
+	if (SCpnt) {
+	    	info->scsi.phase = PHASE_IDLE;
+		info->SCpnt = NULL;
 
-	SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 |
+		SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 |
 				info->scsi.SCp.Status;
 
-	/*
-	 * In theory, this should not happen, but just in case it does.
-	 */
-	if (info->scsi.SCp.ptr && result == DID_OK) {
-	    switch (status_byte (SCpnt->result)) {
-	    case CHECK_CONDITION:
-	    case COMMAND_TERMINATED:
-	    case BUSY:
-	    case QUEUE_FULL:
-	    case RESERVATION_CONFLICT:
-		break;
+		/*
+		 * In theory, this should not happen, but just in case it does.
+		 */
+		if (info->scsi.SCp.ptr && result == DID_OK) {
+			switch (SCpnt->cmnd[0]) {
+			case INQUIRY:
+			case START_STOP:
+			case READ_CAPACITY:
+				break;
 
-	    default:
-		printk (KERN_ERR "scsi%d.H: incomplete data transfer "
-			"detected: result=%08X command=",
-			info->host->host_no, SCpnt->result);
-		print_command (SCpnt->cmnd);
-	    }
-	}
+			default:
+				switch (status_byte(SCpnt->result)) {
+				case CHECK_CONDITION:
+				case COMMAND_TERMINATED:
+				case BUSY:
+				case QUEUE_FULL:
+				case RESERVATION_CONFLICT:
+					break;
+
+				default:
+					printk(KERN_ERR "scsi%d.H: incomplete data transfer "
+						"detected: res=%08X ptr=%p len=%X command=",
+						info->host->host_no, SCpnt->result,
+						info->scsi.SCp.ptr, info->scsi.SCp.this_residual);
+					print_command(SCpnt->cmnd);
+				}
+			}
+		}
 #ifdef DEBUG_CONNECT
-	printk ("scsi%d.%c: scsi command (%p) complete, result=%08X\n",
-		info->host->host_no, fas216_target (info),
-		SCpnt, SCpnt->result);
+		printk("scsi%d.%c: scsi command (%p) complete, result=%08X\n",
+			info->host->host_no, fas216_target(info),
+			SCpnt, SCpnt->result);
 #endif
 
-	if (!SCpnt->scsi_done)
-	    panic ("scsi%d.H: null scsi_done function in fas216_done", info->host->host_no);
+		if (!SCpnt->scsi_done)
+			panic("scsi%d.H: null scsi_done function in "
+				"fas216_done", info->host->host_no);
 
-	clear_bit (SCpnt->target * 8 + SCpnt->lun, info->busyluns);
+		clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);
 
-	SCpnt->scsi_done (SCpnt);
-    } else
-	panic ("scsi%d.H: null command in fas216_done", info->host->host_no);
+		SCpnt->scsi_done(SCpnt);
+	} else
+		panic("scsi%d.H: null command in fas216_done", info->host->host_no);
 
-    if (info->scsi.irq != NO_IRQ)
-	fas216_kick (info);
+	if (info->scsi.irq != NO_IRQ)
+		fas216_kick(info);
 }
 
-/* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+/* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
  * Purpose : queue a command for adapter to process.
  * Params  : SCpnt - Command to queue
  *	     done  - done function to call once command is complete
  * Returns : 0 - success, else error
  */
-int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
 
+	fas216_checkmagic(info, "fas216_queue_command");
+
 #ifdef DEBUG_CONNECT
 	printk("scsi%d.%c: received queuable command (%p) %02X\n",
 		SCpnt->host->host_no, '0' + SCpnt->target,
@@ -1185,47 +1599,51 @@
 		/* add command into execute queue and let it complete under
 		 * the drivers interrupts.
 		 */
-		if (!queue_add_cmd_ordered (&info->queues.issue, SCpnt)) {
+		if (!queue_add_cmd_ordered(&info->queues.issue, SCpnt)) {
 			SCpnt->result = DID_ERROR << 16;
-			done (SCpnt);
+			done(SCpnt);
 		}
-		save_flags_cli (flags);
+		save_flags_cli(flags);
 		if (!info->SCpnt || info->scsi.disconnectable)
-			fas216_kick (info);
-		restore_flags (flags);
+			fas216_kick(info);
+		restore_flags(flags);
 	} else {
 		/* no interrupts to rely on - we'll have to handle the
 		 * command ourselves.  For now, we give up.
 		 */
 		SCpnt->result = DID_ERROR << 16;
-		done (SCpnt);
+		done(SCpnt);
 	}
 	return 0;
 }
 
-/* Function: void fas216_internal_done (Scsi_Cmnd *SCpnt)
+/* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt)
  * Purpose : trigger restart of a waiting thread in fas216_command
  * Params  : SCpnt - Command to wake
  */
-static void fas216_internal_done (Scsi_Cmnd *SCpnt)
+static void fas216_internal_done(Scsi_Cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
 
+	fas216_checkmagic(info, "fas216_internal_done");
+
 	info->internal_done = 1;
 }
 
-/* Function: int fas216_command (Scsi_Cmnd *SCpnt)
+/* Function: int fas216_command(Scsi_Cmnd *SCpnt)
  * Purpose : queue a command for adapter to process.
  * Params  : SCpnt - Command to queue
  * Returns : scsi result code
  */
-int fas216_command (Scsi_Cmnd *SCpnt)
+int fas216_command(Scsi_Cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
 	unsigned long flags;
 
+	fas216_checkmagic(info, "fas216_command");
+
 	info->internal_done = 0;
-	fas216_queue_command (SCpnt, fas216_internal_done);
+	fas216_queue_command(SCpnt, fas216_internal_done);
 
 	/*
 	 * This wastes time, since we can't return until the command is
@@ -1233,13 +1651,13 @@
 	 * However, we must re-enable interrupts, or else we'll be
 	 * waiting forever.
 	 */
-	save_flags (flags);
-	sti ();
+	save_flags(flags);
+	sti();
 
 	while (!info->internal_done)
-		barrier ();
+		barrier();
 
-	restore_flags (flags);
+	restore_flags(flags);
 
 	return SCpnt->result;
 }
@@ -1262,7 +1680,7 @@
 		*SCpntp1 = NULL;
 
 		SCpnt->result = result;
-		SCpnt->scsi_done (SCpnt);
+		SCpnt->scsi_done(SCpnt);
 	}
 
 	if (SCpnt == *SCpntp2)
@@ -1309,28 +1727,33 @@
 	return FAILED;
 }
 
-/* Function: int fas216_abort (Scsi_Cmnd *SCpnt)
+/* Function: int fas216_abort(Scsi_Cmnd *SCpnt)
  * Purpose : abort a command if something horrible happens.
  * Params  : SCpnt - Command that is believed to be causing a problem.
  * Returns : one of SCSI_ABORT_ macros.
  */
-int fas216_abort (Scsi_Cmnd *SCpnt)
+int fas216_abort(Scsi_Cmnd *SCpnt)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
 	int result = SCSI_ABORT_SNOOZE;
 
+	fas216_checkmagic(info, "fas216_abort");
+
 	info->stats.aborts += 1;
 
+	print_debug_list();
+	fas216_dumpinfo(info);
+	fas216_dumpstate(info);
 	printk(KERN_WARNING "scsi%d: fas216_abort: ", info->host->host_no);
 
 	do {
 		/* If command is waiting in the issue queue, then we can
 		 * simply remove the command and return abort status
 		 */
-		if (queue_removecmd (&info->queues.issue, SCpnt)) {
+		if (queue_removecmd(&info->queues.issue, SCpnt)) {
 			SCpnt->result = DID_ABORT << 16;
-			SCpnt->scsi_done (SCpnt);
-			printk ("command on issue queue");
+			SCpnt->scsi_done(SCpnt);
+			printk("command on issue queue");
 			result = SCSI_ABORT_SUCCESS;
 			break;
 		}
@@ -1338,14 +1761,14 @@
 		/* If the command is on the disconencted queue, we need to
 		 * reconnect to the device
 		 */
-		if (queue_cmdonqueue (&info->queues.disconnected, SCpnt))
-			printk ("command on disconnected queue");
+		if (queue_cmdonqueue(&info->queues.disconnected, SCpnt))
+			printk("command on disconnected queue");
 
 		/* If the command is connected, we need to flag that the
 		 * command needs to be aborted
 		 */
 		if (info->SCpnt == SCpnt)
-			printk ("command executing");
+			printk("command executing");
 
 		/* If the command is pending for execution, then again
 		 * this is simple - we remove it and report abort status
@@ -1353,14 +1776,14 @@
 		if (info->origSCpnt == SCpnt) {
 			info->origSCpnt = NULL;
 			SCpnt->result = DID_ABORT << 16;
-			SCpnt->scsi_done (SCpnt);
-			printk ("command waiting for execution");
+			SCpnt->scsi_done(SCpnt);
+			printk("command waiting for execution");
 			result = SCSI_ABORT_SUCCESS;
 			break;
 		}
 	} while (0);
 
-	printk ("\n");
+	printk("\n");
 
 	return result;
 }
@@ -1371,12 +1794,15 @@
  */
 static void fas216_reset_state(FAS216_Info *info)
 {
+	syncneg_t negstate;
 	int i;
 
+	fas216_checkmagic(info, "fas216_reset_state");
+
 	/*
 	 * Clear out all stale info in our state structure
 	 */
-	memset (info->busyluns, 0, sizeof (info->busyluns));
+	memset(info->busyluns, 0, sizeof(info->busyluns));
 	msgqueue_flush(&info->scsi.msgs);
 	info->scsi.reconnected.target = 0;
 	info->scsi.reconnected.lun = 0;
@@ -1385,6 +1811,16 @@
 	info->scsi.last_message = 0;
 	info->scsi.aborting = 0;
 	info->scsi.phase = PHASE_IDLE;
+	info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
+
+	if (info->host->dma_channel == NO_DMA || !info->dma.setup)
+		negstate = syncneg_invalid;
+	else
+#ifdef SCSI2_SYNC
+		negstate = syncneg_start;
+#else
+		negstate = syncneg_invalid;
+#endif
 
 	for (i = 0; i < 8; i++) {
 #ifndef NO_DISCONNECTS
@@ -1392,13 +1828,9 @@
 #else
 		info->device[i].disconnect_ok = 0;
 #endif
-		info->device[i].stp = fas216_syncperiod(info, info->ifcfg.asyncperiod);
+		info->device[i].negstate = negstate;
+		info->device[i].stp = info->scsi.async_stp;
 		info->device[i].sof = 0;
-#ifdef SCSI2SYNC
-		info->device[i].negstate = syncneg_start;
-#else
-		info->device[i].negstate = syncneg_complete;
-#endif
 	}
 }
 
@@ -1408,17 +1840,19 @@
  */
 static void fas216_init_chip(FAS216_Info *info)
 {
+	fas216_checkmagic(info, "fas216_init_chip");
+
 	outb(fas216_clockrate(info->ifcfg.clockrate), REG_CLKF(info));
 	outb(info->scsi.cfg[0], REG_CNTL1(info));
 	outb(info->scsi.cfg[1], REG_CNTL2(info));
 	outb(info->scsi.cfg[2], REG_CNTL3(info));
 	outb(info->ifcfg.select_timeout, REG_STIM(info));
 	outb(0, REG_SOF(info));
-	outb(fas216_syncperiod(info, info->ifcfg.asyncperiod), REG_STP(info));
+	outb(info->scsi.async_stp, REG_STP(info));
 	outb(info->scsi.cfg[0], REG_CNTL1(info));
 }
 
-/* Function: int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+/* Function: int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
  * Purpose : resets the adapter if something horrible happens.
  * Params  : SCpnt - Command that is believed to be causing a problem.
  *	     reset_flags - flags indicating reset type that is believed
@@ -1426,51 +1860,72 @@
  * Returns : one of SCSI_RESET_ macros, or'd with the SCSI_RESET_*_RESET
  *           macros.
  */
-int fas216_reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
+int fas216_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
 	Scsi_Cmnd *SCptr;
 	int result = 0;
 
+	fas216_checkmagic(info, "fas216_reset");
+
+	/*
+	 * Validate that command is actually on one of our queues if we're doing
+	 * an asynchronous reset
+	 */
+	if (reset_flags & SCSI_RESET_ASYNCHRONOUS &&
+	    SCpnt &&
+	    info->SCpnt != SCpnt &&
+	    info->origSCpnt != SCpnt &&
+	    !queue_cmdonqueue(&info->queues.disconnected, SCpnt) &&
+	    !queue_cmdonqueue(&info->queues.issue, SCpnt)) {
+		printk("scsi%d: fas216_reset: asynchronous reset for unknown command\n",
+		       info->host->host_no);
+		return SCSI_RESET_NOT_RUNNING;
+	}
+
 	info->stats.resets += 1;
 
+	print_debug_list();
 	printk(KERN_WARNING "scsi%d: fas216_reset: ", info->host->host_no);
+	if (SCpnt)
+		printk(" for target %d ", SCpnt->target);
 
 	outb(info->scsi.cfg[3], REG_CNTL3(info));
 
 	fas216_stoptransfer(info);
-	fas216_reset_state(info);
 
-	if (reset_flags & SCSI_RESET_SUGGEST_HOST_RESET) {
+	switch (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET)) {
+	case SCSI_RESET_SUGGEST_BUS_RESET:
+		outb(CMD_RESETSCSI, REG_CMD(info));
+		outb(CMD_NOP, REG_CMD(info));
+		result |= SCSI_RESET_BUS_RESET;
+		break;
+
+	case SCSI_RESET_SUGGEST_HOST_RESET:
 		outb(CMD_RESETCHIP, REG_CMD(info));
 		outb(CMD_NOP, REG_CMD(info));
 		result |= SCSI_RESET_HOST_RESET;
-	}
-
-	if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) {
-	    	outb(CMD_RESETSCSI, REG_CMD(info));
-    		outb(CMD_NOP, REG_CMD(info));
-	    	result |= SCSI_RESET_BUS_RESET;
-	}
+		break;
 
-	if (!(reset_flags &
-	      (SCSI_RESET_SUGGEST_BUS_RESET|SCSI_RESET_SUGGEST_HOST_RESET))) {
+	default:
 		outb(CMD_RESETCHIP, REG_CMD(info));
 		outb(CMD_NOP, REG_CMD(info));
 		outb(CMD_RESETSCSI, REG_CMD(info));
 		result |= SCSI_RESET_HOST_RESET | SCSI_RESET_BUS_RESET;
+		break;
 	}
 
-	if (result & SCSI_RESET_HOST_RESET)
-		fas216_init_chip(info);
+	udelay(300);
+	fas216_reset_state(info);
+	fas216_init_chip(info);
 
 	/*
 	 * Signal all commands in progress have been reset
 	 */
-	fas216_reportstatus (&info->SCpnt, &SCpnt, DID_RESET << 16);
+	fas216_reportstatus(&info->SCpnt, &SCpnt, DID_RESET << 16);
 
-	while ((SCptr = queue_remove (&info->queues.disconnected)) != NULL)
-		fas216_reportstatus (&SCptr, &SCpnt, DID_RESET << 16);
+	while ((SCptr = queue_remove(&info->queues.disconnected)) != NULL)
+		fas216_reportstatus(&SCptr, &SCpnt, DID_RESET << 16);
 
 	if (SCpnt) {
 		/*
@@ -1483,42 +1938,45 @@
 		queue_removecmd(&info->queues.issue, SCpnt);
 
 		SCpnt->result = DID_RESET << 16;
-		SCpnt->scsi_done (SCpnt);
+		SCpnt->scsi_done(SCpnt);
 	}
 
-	printk ("\n");
+	printk("\n");
 
 	return result | SCSI_RESET_SUCCESS;
 }
 
-/* Function: int fas216_init (struct Scsi_Host *instance)
+/* Function: int fas216_init(struct Scsi_Host *instance)
  * Purpose : initialise FAS/NCR/AMD SCSI ic.
  * Params  : instance - a driver-specific filled-out structure
  * Returns : 0 on success
  */
-int fas216_init (struct Scsi_Host *instance)
+int fas216_init(struct Scsi_Host *instance)
 {
 	FAS216_Info *info = (FAS216_Info *)instance->hostdata;
 	unsigned long flags;
 	int target_jiffies;
 
+	info->magic_start = MAGIC;
+	info->magic_end = MAGIC;
+
 	info->host = instance;
 	info->scsi.cfg[0] = instance->this_id;
 	info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE;
-	info->scsi.cfg[2] = CNTL3_ADIDCHK | CNTL3_G2CB | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+	info->scsi.cfg[2] = info->ifcfg.cntl3 | CNTL3_ADIDCHK | CNTL3_G2CB;
 	info->scsi.type = "unknown";
 	info->SCpnt = NULL;
 	fas216_reset_state(info);
 
-	memset (&info->stats, 0, sizeof (info->stats));
+	memset(&info->stats, 0, sizeof(info->stats));
 
-	msgqueue_initialise (&info->scsi.msgs);
+	msgqueue_initialise(&info->scsi.msgs);
 
-	if (!queue_initialise (&info->queues.issue))
+	if (!queue_initialise(&info->queues.issue))
 		return 1;
 
-	if (!queue_initialise (&info->queues.disconnected)) {
-		queue_free (&info->queues.issue);
+	if (!queue_initialise(&info->queues.disconnected)) {
+		queue_free(&info->queues.issue);
 		return 1;
 	}
 
@@ -1555,8 +2013,7 @@
 		break;
 	}
 
-	udelay (300);
-
+	udelay(300);
 	/* now for the real initialisation */
 	fas216_init_chip(info);
 
@@ -1565,32 +2022,39 @@
 
 	/* scsi standard says 250ms */
 	target_jiffies = jiffies + (25 * HZ) / 100;
-	save_flags (flags);
-	sti ();
+	save_flags(flags);
+	sti();
 
-	while (jiffies < target_jiffies) barrier ();
+	while (jiffies < target_jiffies) barrier();
 
-	restore_flags (flags);
+	restore_flags(flags);
 
 	outb(info->scsi.cfg[0], REG_CNTL1(info));
 	inb(REG_INST(info));
 
+	/* now for the real initialisation */
+	fas216_init_chip(info);
+
+	fas216_checkmagic(info, "fas216_init");
+
 	return 0;
 }
 
-/* Function: int fas216_release (struct Scsi_Host *instance)
+/* Function: int fas216_release(struct Scsi_Host *instance)
  * Purpose : release all resources and put everything to bed for
  *           FAS/NCR/AMD SCSI ic.
  * Params  : instance - a driver-specific filled-out structure
  * Returns : 0 on success
  */
-int fas216_release (struct Scsi_Host *instance)
+int fas216_release(struct Scsi_Host *instance)
 {
 	FAS216_Info *info = (FAS216_Info *)instance->hostdata;
 
+	fas216_checkmagic(info, "fas216_release");
+
 	outb(CMD_RESETCHIP, REG_CMD(info));
-	queue_free (&info->queues.disconnected);
-	queue_free (&info->queues.issue);
+	queue_free(&info->queues.disconnected);
+	queue_free(&info->queues.issue);
 
 	return 0;
 }
@@ -1609,12 +2073,12 @@
 
 
 #ifdef MODULE
-int init_module (void)
+int init_module(void)
 {
 	return 0;
 }
 
-void cleanup_module (void)
+void cleanup_module(void)
 {
 }
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/fas216.h linux/drivers/acorn/scsi/fas216.h
--- v2.1.100/linux/drivers/acorn/scsi/fas216.h	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/fas216.h	Fri May  8 00:42:39 1998
@@ -55,8 +55,8 @@
 
 /* status register (read) */
 #define REG_STAT(x)		((x)->scsi.io_port + (4 << (x)->scsi.io_shift))
-#define STAT_IO		(1 << 0)				/* IO phase		*/
-#define STAT_CD		(1 << 1)				/* CD phase		*/
+#define STAT_IO			(1 << 0)			/* IO phase		*/
+#define STAT_CD			(1 << 1)			/* CD phase		*/
 #define STAT_MSG		(1 << 2)			/* MSG phase		*/
 #define STAT_TRANSFERDONE	(1 << 3)			/* Transfer completed	*/
 #define STAT_TRANSFERCNTZ	(1 << 4)			/* Transfer counter is zero */
@@ -98,6 +98,7 @@
 #define IS_NOTCOMMAND		0x02				/* Not in command state	*/
 #define IS_EARLYPHASE		0x03				/* Early phase change	*/
 #define IS_COMPLETE		0x04				/* Command ok		*/
+#define IS_SOF			0x08				/* Sync off flag	*/
 
 /* Transfer period step (write) */
 #define REG_STP(x)		((x)->scsi.io_port + (6 << (x)->scsi.io_shift))
@@ -170,6 +171,7 @@
 typedef enum {
 	PHASE_IDLE,					/* we're not planning on doing anything	*/
 	PHASE_SELECTION,				/* selecting a device			*/
+	PHASE_MESSAGESENT,				/* selected, and we're sending cmd	*/
 	PHASE_RECONNECTED,				/* reconnected				*/
 	PHASE_DATAOUT,					/* data out to device			*/
 	PHASE_DATAIN,					/* data in from device			*/
@@ -188,6 +190,7 @@
 
 typedef enum {
 	fasdma_none,					/* No dma				*/
+	fasdma_pio,					/* PIO mode				*/
 	fasdma_pseudo,					/* Pseudo DMA				*/
 	fasdma_real_block,				/* Real DMA, on block by block basis	*/
 	fasdma_real_all					/* Real DMA, on request by request	*/
@@ -196,10 +199,14 @@
 typedef enum {
 	syncneg_start,					/* Negociate with device for Sync xfers	*/
 	syncneg_sent,					/* Sync Xfer negociation sent		*/
-	syncneg_complete				/* Sync Xfer complete			*/
+	syncneg_complete,				/* Sync Xfer complete			*/
+	syncneg_invalid					/* Sync Xfer not supported		*/
 } syncneg_t;
 
+#define MAGIC	0x441296bdUL
+
 typedef struct {
+	unsigned long		magic_start;
 	struct Scsi_Host	*host;			/* host					*/
 	Scsi_Cmnd		*SCpnt;			/* currently processing command		*/
 	Scsi_Cmnd		*origSCpnt;		/* original connecting command		*/
@@ -208,7 +215,7 @@
 	struct {
 		unsigned int	io_port;		/* base address of FAS216		*/
 		unsigned int	io_shift;		/* shift to adjust reg offsets by	*/
-		unsigned char	irq;			/* interrupt				*/
+		unsigned int	irq;			/* interrupt				*/
 		unsigned char	cfg[4];			/* configuration registers		*/
 		const char	*type;			/* chip type				*/
 		phase_t		phase;			/* current phase			*/
@@ -223,6 +230,7 @@
 
 		MsgQueue_t	msgs;			/* message queue for connected device	*/
 
+		unsigned int	async_stp;		/* Async transfer STP value		*/
 		unsigned short	last_message;		/* last message to be sent		*/
 
 		unsigned char	disconnectable:1;	/* this command can be disconnected	*/
@@ -246,8 +254,9 @@
 	struct {
 		unsigned char	clockrate;		/* clock rate of FAS device (MHz)	*/
 		unsigned char	select_timeout;		/* timeout (R5)				*/
-		unsigned int	asyncperiod;		/* Async transfer period (ns)		*/
 		unsigned char	sync_max_depth;		/* Synchronous xfer max fifo depth	*/
+		unsigned char	cntl3;			/* Control Reg 3			*/
+		unsigned int	asyncperiod;		/* Async transfer period (ns)		*/
 	} ifcfg;
 
 	/* queue handling */
@@ -268,13 +277,15 @@
 	/* dma */
 	struct {
 		fasdmatype_t	transfer_type;		/* current type of DMA transfer		*/
-		fasdmatype_t	(*setup) (struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction);
-		int		(*pseudo)(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer);
+		fasdmatype_t	(*setup) (struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_dma);
+		void		(*pseudo)(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer);
 		void		(*stop)  (struct Scsi_Host *host, Scsi_Pointer *SCp);
 	} dma;
 
 	/* miscellaneous */
 	int			internal_done;		/* flag to indicate request done */
+
+	unsigned long		magic_end;
 } FAS216_Info;
 
 /* Function: int fas216_init (struct Scsi_Host *instance)
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/msgqueue.c linux/drivers/acorn/scsi/msgqueue.c
--- v2.1.100/linux/drivers/acorn/scsi/msgqueue.c	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/msgqueue.c	Fri May  8 00:42:39 1998
@@ -11,12 +11,12 @@
 #include "msgqueue.h"
 
 /*
- * Function: struct msgqueue_entry *mqe_alloc (MsgQueue_t *msgq)
+ * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
  * Purpose : Allocate a message queue entry
  * Params  : msgq - message queue to claim entry for
  * Returns : message queue entry or NULL.
  */
-static struct msgqueue_entry *mqe_alloc (MsgQueue_t *msgq)
+static struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq)
 {
 	struct msgqueue_entry *mq;
 
@@ -27,12 +27,12 @@
 }
 
 /*
- * Function: void mqe_free (MsgQueue_t *msgq, struct msgqueue_entry *mq)
+ * Function: void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq)
  * Purpose : free a message queue entry
  * Params  : msgq - message queue to free entry from
  *	     mq   - message queue entry to free
  */
-static void mqe_free (MsgQueue_t *msgq, struct msgqueue_entry *mq)
+static void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq)
 {
 	if (mq) {
 		mq->next = msgq->free;
@@ -41,11 +41,11 @@
 }
 
 /*
- * Function: void msgqueue_initialise (MsgQueue_t *msgq)
+ * Function: void msgqueue_initialise(MsgQueue_t *msgq)
  * Purpose : initialise a message queue
  * Params  : msgq - queue to initialise
  */
-void msgqueue_initialise (MsgQueue_t *msgq)
+void msgqueue_initialise(MsgQueue_t *msgq)
 {
 	int i;
 
@@ -60,21 +60,21 @@
 
 
 /*
- * Function: void msgqueue_free (MsgQueue_t *msgq)
+ * Function: void msgqueue_free(MsgQueue_t *msgq)
  * Purpose : free a queue
  * Params  : msgq - queue to free
  */
-void msgqueue_free (MsgQueue_t *msgq)
+void msgqueue_free(MsgQueue_t *msgq)
 {
 }
 
 /*
- * Function: int msgqueue_msglength (MsgQueue_t *msgq)
+ * Function: int msgqueue_msglength(MsgQueue_t *msgq)
  * Purpose : calculate the total length of all messages on the message queue
  * Params  : msgq - queue to examine
  * Returns : number of bytes of messages in queue
  */
-int msgqueue_msglength (MsgQueue_t *msgq)
+int msgqueue_msglength(MsgQueue_t *msgq)
 {
 	struct msgqueue_entry *mq = msgq->qe;
 	int length = 0;
@@ -86,19 +86,19 @@
 }
 
 /*
- * Function: char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length)
+ * Function: char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length)
  * Purpose : return a message & its length
  * Params  : msgq   - queue to obtain message from
  *	     length - pointer to int for message length
- * Returns : pointer to message string
+ * Returns : pointer to message string, or NULL
  */
-char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length)
+char *msgqueue_getnextmsg(MsgQueue_t *msgq, int *length)
 {
 	struct msgqueue_entry *mq;
 
 	if ((mq = msgq->qe) != NULL) {
 		msgq->qe = mq->next;
-		mqe_free (msgq, mq);
+		mqe_free(msgq, mq);
 		*length = mq->length;
 	}
 
@@ -106,26 +106,42 @@
 }
 
 /*
- * Function: int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...)
+ * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length)
+ * Purpose : return next message & length without removing it from the list
+ * Params  : msgq   - queue to obtain message from
+ *         : length - pointer to int for message length
+ * Returns : pointer to message string, or NULL
+ */
+char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length)
+{
+	struct msgqueue_entry *mq = msgq->qe;
+
+	*length = mq ? mq->length : 0;
+
+	return mq ? mq->msg : NULL;
+}
+
+/*
+ * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
  * Purpose : add a message onto a message queue
  * Params  : msgq   - queue to add message on
  *	     length - length of message
  *	     ...    - message bytes
  * Returns : != 0 if successful
  */
-int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...)
+int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...)
 {
-	struct msgqueue_entry *mq = mqe_alloc (msgq);
+	struct msgqueue_entry *mq = mqe_alloc(msgq);
 	va_list ap;
 
 	if (mq) {
 		struct msgqueue_entry **mqp;
 		int i;
 
-		va_start (ap, length);
+		va_start(ap, length);
 		for (i = 0; i < length; i++)
-			mq->msg[i] = va_arg (ap, unsigned char);
-		va_end (ap);
+			mq->msg[i] = va_arg(ap, unsigned char);
+		va_end(ap);
 
 		mq->length = length;
 		mq->next = NULL;
@@ -141,17 +157,17 @@
 }
 
 /*
- * Function: void msgqueue_flush (MsgQueue_t *msgq)
+ * Function: void msgqueue_flush(MsgQueue_t *msgq)
  * Purpose : flush all messages from message queue
  * Params  : msgq - queue to flush
  */
-void msgqueue_flush (MsgQueue_t *msgq)
+void msgqueue_flush(MsgQueue_t *msgq)
 {
 	struct msgqueue_entry *mq, *mqnext;
 
 	for (mq = msgq->qe; mq; mq = mqnext) {
 		mqnext = mq->next;
-		mqe_free (msgq, mq);
+		mqe_free(msgq, mq);
 	}
 	msgq->qe = NULL;
 }
@@ -160,16 +176,17 @@
 EXPORT_SYMBOL(msgqueue_free);
 EXPORT_SYMBOL(msgqueue_msglength);
 EXPORT_SYMBOL(msgqueue_getnextmsg);
+EXPORT_SYMBOL(msgqueue_peeknextmsg);
 EXPORT_SYMBOL(msgqueue_addmsg);
 EXPORT_SYMBOL(msgqueue_flush);
 
 #ifdef MODULE
-int init_module (void)
+int init_module(void)
 {
 	return 0;
 }
 
-void cleanup_module (void)
+void cleanup_module(void)
 {
 }
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/msgqueue.h linux/drivers/acorn/scsi/msgqueue.h
--- v2.1.100/linux/drivers/acorn/scsi/msgqueue.h	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/msgqueue.h	Fri May  8 00:42:39 1998
@@ -47,9 +47,18 @@
  * Purpose : return a message & its length
  * Params  : msgq   - queue to obtain message from
  *	     length - pointer to int for message length
- * Returns : pointer to message string
+ * Returns : pointer to message string, or NULL
  */
 extern char *msgqueue_getnextmsg (MsgQueue_t *msgq, int *length);
+
+/*
+ * Function: char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length)
+ * Purpose : return next message & length without removing it from the list
+ * Params  : msgq   - queue to obtain message from
+ *         : length - pointer to int for message length
+ * Returns : pointer to message string, or NULL
+ */
+extern char *msgqueue_peeknextmsg(MsgQueue_t *msgq, int *length);
 
 /*
  * Function: int msgqueue_addmsg (MsgQueue_t *msgq, int length, ...)
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c
--- v2.1.100/linux/drivers/acorn/scsi/oak.c	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/oak.c	Fri May  8 00:42:39 1998
@@ -33,6 +33,11 @@
 
 /*
  * $Log: oak.c,v $
+ * Revision 1.3  1998/05/03 20:45:37  alan
+ * ARM SCSI update. This adds the eesox driver and massively updates the
+ * Cumana driver. The folks who bought cumana arent anal retentive all
+ * docs are secret weenies so now there are docs ..
+ *
  * Revision 1.2  1998/03/08 05:49:48  davem
  * Merge to 2.1.89
  *
@@ -122,7 +127,7 @@
 	    printk("scsi%d: that the board had an interrupt!\n", instance->host_no);
 	}
 
-	printk("scsi%d: at port %X irq", instance->host_no, instance->io_port);
+	printk("scsi%d: at port %lX irq", instance->host_no, instance->io_port);
 	if (instance->irq == IRQ_NONE)
 	    printk ("s disabled");
 	else
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c
--- v2.1.100/linux/drivers/acorn/scsi/powertec.c	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/powertec.c	Fri May  8 00:42:39 1998
@@ -1,15 +1,17 @@
 /*
  * linux/arch/arm/drivers/scsi/powertec.c
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1998 Russell King
  *
  * This driver is based on experimentation.  Hence, it may have made
  * assumptions about the particular card that I have available, and
  * may not be reliable!
  *
  * Changelog:
- *  01-10-1997	RMK	Created, READONLY version
- *  15-02-1998	RMK	Added DMA support and hardware definitions
+ *  01-10-1997	RMK	Created, READONLY version.
+ *  15-02-1998	RMK	Added DMA support and hardware definitions.
+ *  15-04-1998	RMK	Only do PIO if FAS216 will allow it.
+ *  02-05-1998	RMK	Moved DMA sg list into per-interface structure.
  */
 
 #include <linux/module.h>
@@ -23,10 +25,10 @@
 #include <linux/stat.h>
 
 #include <asm/delay.h>
-#include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/ecard.h>
+#include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/pgtable.h>
 
 #include "../../scsi/sd.h"
@@ -36,7 +38,7 @@
 /* Configuration */
 #define POWERTEC_XTALFREQ	40
 #define POWERTEC_ASYNC_PERIOD	200
-#define POWERTEC_SYNC_DEPTH	16
+#define POWERTEC_SYNC_DEPTH	7
 
 /*
  * List of devices that the driver will recognise
@@ -45,8 +47,16 @@
 
 #define POWERTEC_FAS216_OFFSET	0xc00
 #define POWERTEC_FAS216_SHIFT	4
+
 #define POWERTEC_INTR_STATUS	0x800
 #define POWERTEC_INTR_BIT	0x80
+
+#define POWERTEC_RESET_CONTROL	0x406
+#define POWERTEC_RESET_BIT	1
+
+#define POWERTEC_TERM_CONTROL	0x806
+#define POWERTEC_TERM_ENABLE	1
+
 #define POWERTEC_INTR_CONTROL	0x407
 #define POWERTEC_INTR_ENABLE	1
 #define POWERTEC_INTR_DISABLE	0
@@ -56,19 +66,24 @@
  */
 #define VER_MAJOR	0
 #define VER_MINOR	0
-#define VER_PATCH	1
+#define VER_PATCH	2
 
 static struct expansion_card *ecs[MAX_ECARDS];
 
+/*
+ * Use term=0,1,0,0,0 to turn terminators on/off
+ */
+int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
+
 static struct proc_dir_entry proc_scsi_powertec = {
 	PROC_SCSI_QLOGICISP, 8, "powertec",
 	S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
-/* Function: void powertecscsi_irqenable(ec, irqnr)
- * Purpose : Enable interrupts on powertec SCSI card
- * Params  : ec    - expansion card structure
- *         : irqnr - interrupt number
+/* Prototype: void powertecscsi_irqenable(ec, irqnr)
+ * Purpose  : Enable interrupts on Powertec SCSI card
+ * Params   : ec    - expansion card structure
+ *          : irqnr - interrupt number
  */
 static void
 powertecscsi_irqenable(struct expansion_card *ec, int irqnr)
@@ -77,10 +92,10 @@
 	outb(POWERTEC_INTR_ENABLE, port);
 }
 
-/* Function: void powertecscsi_irqdisable(ec, irqnr)
- * Purpose : Disable interrupts on powertec SCSI card
- * Params  : ec    - expansion card structure
- *         : irqnr - interrupt number
+/* Prototype: void powertecscsi_irqdisable(ec, irqnr)
+ * Purpose  : Disable interrupts on Powertec SCSI card
+ * Params   : ec    - expansion card structure
+ *          : irqnr - interrupt number
  */
 static void
 powertecscsi_irqdisable(struct expansion_card *ec, int irqnr)
@@ -96,19 +111,36 @@
 	NULL
 };
 
-/* Function: void powertecscsi_intr(int irq, void *dev_id,
- *				    struct pt_regs *regs)
- * Purpose : handle interrupts from Powertec SCSI card
- * Params  : irq - interrupt number
- *	     dev_id - user-defined (Scsi_Host structure)
- *	     regs - processor registers at interrupt
+/* Prototype: void powertecscsi_terminator_ctl(host, on_off)
+ * Purpose  : Turn the Powertec SCSI terminators on or off
+ * Params   : host   - card to turn on/off
+ *          : on_off - !0 to turn on, 0 to turn off
+ */
+static void
+powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off)
+{
+	PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata;
+
+	if (on_off)
+		info->control.terms = POWERTEC_TERM_ENABLE;
+	else
+		info->control.terms = 0;
+
+	outb(info->control.terms, info->control.term_port);
+}
+
+/* Prototype: void powertecscsi_intr(irq, *dev_id, *regs)
+ * Purpose  : handle interrupts from Powertec SCSI card
+ * Params   : irq    - interrupt number
+ *	      dev_id - user-defined (Scsi_Host structure)
+ *	      regs   - processor registers at interrupt
  */
 static void
 powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct Scsi_Host *instance = (struct Scsi_Host *)dev_id;
+	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;
 
-    fas216_intr(instance);
+	fas216_intr(host);
 }
 
 static void
@@ -125,66 +157,73 @@
 				  (unsigned long)addr + len);
 }
 
-/* Function: fasdmatype_t powertecscsi_dma_setup(instance, SCpnt, direction)
- * Purpose : initialises DMA/PIO
- * Params  : instance  - host
- *	     SCpnt     - command
- *	     direction - DMA on to/off of card
- * Returns : type of transfer to be performed
+/* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type)
+ * Purpose  : initialises DMA/PIO
+ * Params   : host      - host
+ *	      SCpnt     - command
+ *	      direction - DMA on to/off of card
+ *	      min_type  - minimum DMA support that we must have for this transfer
+ * Returns  : type of transfer to be performed
  */
 static fasdmatype_t
-powertecscsi_dma_setup(struct Scsi_Host *instance, Scsi_Pointer *SCp,
-		       fasdmadir_t direction)
+powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp,
+		       fasdmadir_t direction, fasdmatype_t min_type)
 {
-	if (instance->dma_channel != NO_DMA && SCp->this_residual >= 512) {
+	PowerTecScsi_Info *info = (PowerTecScsi_Info *)host->hostdata;
+	int dmach = host->dma_channel;
+
+	if (dmach != NO_DMA &&
+	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
 		int buf;
-static		dmasg_t dmasg[256];
 
-		for (buf = 1; buf <= SCp->buffers_residual; buf++) {
-			dmasg[buf].address = __virt_to_bus(
+		for (buf = 1; buf <= SCp->buffers_residual &&
+			      buf < NR_SG; buf++) {
+			info->dmasg[buf].address = __virt_to_bus(
 				(unsigned long)SCp->buffer[buf].address);
-			dmasg[buf].length = SCp->buffer[buf].length;
+			info->dmasg[buf].length = SCp->buffer[buf].length;
 
 			powertecscsi_invalidate(SCp->buffer[buf].address,
 						SCp->buffer[buf].length,
 						direction);
 		}
 
-		dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr);
-		dmasg[0].length = SCp->this_residual;
+		info->dmasg[0].address = __virt_to_phys((unsigned long)SCp->ptr);
+		info->dmasg[0].length = SCp->this_residual;
 		powertecscsi_invalidate(SCp->ptr,
 					SCp->this_residual, direction);
 
-		disable_dma(instance->dma_channel);
-		set_dma_sg(instance->dma_channel, dmasg, buf);
-		set_dma_mode(instance->dma_channel,
+		disable_dma(dmach);
+		set_dma_sg(dmach, info->dmasg, buf);
+		set_dma_mode(dmach,
 			     direction == DMA_OUT ? DMA_MODE_WRITE :
 						    DMA_MODE_READ);
-		enable_dma(instance->dma_channel);
+		enable_dma(dmach);
 		return fasdma_real_all;
 	}
+
 	/*
-	 * We don't do DMA, we only do slow PIO
+	 * If we're not doing DMA,
+	 *  we'll do slow PIO
 	 */
-	return fasdma_none;
+	return fasdma_pio;
 }
 
-/* Function: int powertecscsi_dma_stop(instance, SCpnt)
- * Purpose : stops DMA/PIO
- * Params  : instance  - host
- *	     SCpnt     - command
+/* Prototype: int powertecscsi_dma_stop(host, SCpnt)
+ * Purpose  : stops DMA/PIO
+ * Params   : host  - host
+ *	      SCpnt - command
  */
 static void
-powertecscsi_dma_stop(struct Scsi_Host *instance, Scsi_Pointer *SCp)
+powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
 {
-	if (instance->dma_channel != NO_DMA)
-		disable_dma(instance->dma_channel);
+	if (host->dma_channel != NO_DMA)
+		disable_dma(host->dma_channel);
 }
 
-/* Function: int powertecscsi_detect(Scsi_Host_Template * tpnt)
- * Purpose : initialises PowerTec SCSI driver
- * Params  : tpnt - template for this SCSI adapter
- * Returns : >0 if host found, 0 otherwise.
+/* Prototype: int powertecscsi_detect(Scsi_Host_Template * tpnt)
+ * Purpose  : initialises PowerTec SCSI driver
+ * Params   : tpnt - template for this SCSI adapter
+ * Returns  : >0 if host found, 0 otherwise.
  */
 int
 powertecscsi_detect(Scsi_Host_Template *tpnt)
@@ -192,14 +231,14 @@
 	static const card_ids powertecscsi_cids[] =
 			{ POWERTECSCSI_LIST, { 0xffff, 0xffff} };
 	int count = 0;
-	struct Scsi_Host *instance;
+	struct Scsi_Host *host;
   
 	tpnt->proc_dir = &proc_scsi_powertec;
 	memset(ecs, 0, sizeof (ecs));
 
 	ecard_startfind();
 
-	while(1) {
+	while (1) {
 	    	PowerTecScsi_Info *info;
 
 		ecs[count] = ecard_find(0, powertecscsi_cids);
@@ -208,88 +247,94 @@
 
 		ecard_claim(ecs[count]);
 
-		instance = scsi_register(tpnt, sizeof (PowerTecScsi_Info));
-		if (!instance) {
+		host = scsi_register(tpnt, sizeof (PowerTecScsi_Info));
+		if (!host) {
 			ecard_release(ecs[count]);
 			break;
 		}
 
-		instance->io_port = ecard_address(ecs[count], ECARD_IOC, 0);
-		instance->irq = ecs[count]->irq;
-
-		ecs[count]->irqaddr = (unsigned char *)
-			    ioaddr(instance->io_port + POWERTEC_INTR_STATUS);
-		ecs[count]->irqmask = POWERTEC_INTR_BIT;
-		ecs[count]->irq_data = (void *)
-			    (instance->io_port + POWERTEC_INTR_CONTROL);
-		ecs[count]->ops = (expansioncard_ops_t *)&powertecscsi_ops;
-
-		request_region(instance->io_port + POWERTEC_FAS216_OFFSET,
-				16 << POWERTEC_FAS216_SHIFT, "powertec2-fas");
+		host->io_port = ecard_address(ecs[count], ECARD_IOC, ECARD_FAST);
+		host->irq = ecs[count]->irq;
+		host->dma_channel = ecs[count]->dma;
+		info = (PowerTecScsi_Info *)host->hostdata;
+
+		info->control.term_port = host->io_port + POWERTEC_TERM_CONTROL;
+		info->control.terms = term[count] ? POWERTEC_TERM_ENABLE : 0;
+		powertecscsi_terminator_ctl(host, info->control.terms);
 
-		if (request_irq(instance->irq, powertecscsi_intr,
-				SA_INTERRUPT, "powertec", instance)) {
+		info->info.scsi.io_port	=
+				host->io_port + POWERTEC_FAS216_OFFSET;
+		info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT;
+		info->info.scsi.irq		= host->irq;
+		info->info.ifcfg.clockrate	= POWERTEC_XTALFREQ;
+		info->info.ifcfg.select_timeout	= 255;
+		info->info.ifcfg.asyncperiod	= POWERTEC_ASYNC_PERIOD;
+		info->info.ifcfg.sync_max_depth	= POWERTEC_SYNC_DEPTH;
+		info->info.ifcfg.cntl3		= CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK;
+		info->info.dma.setup		= powertecscsi_dma_setup;
+		info->info.dma.pseudo		= NULL;
+		info->info.dma.stop		= powertecscsi_dma_stop;
+
+		ecs[count]->irqaddr	= (unsigned char *)
+			    ioaddr(host->io_port + POWERTEC_INTR_STATUS);
+		ecs[count]->irqmask	= POWERTEC_INTR_BIT;
+		ecs[count]->irq_data	= (void *)
+			    (host->io_port + POWERTEC_INTR_CONTROL);
+		ecs[count]->ops		= (expansioncard_ops_t *)&powertecscsi_ops;
+
+		request_region(host->io_port + POWERTEC_FAS216_OFFSET,
+			       16 << POWERTEC_FAS216_SHIFT, "powertec2-fas");
+
+		if (host->irq != NO_IRQ &&
+		    request_irq(host->irq, powertecscsi_intr,
+				SA_INTERRUPT, "powertec", host)) {
 			printk("scsi%d: IRQ%d not free, interrupts disabled\n",
-			       instance->host_no, instance->irq);
-			instance->irq = NO_IRQ;
+			       host->host_no, host->irq);
+			host->irq = NO_IRQ;
+			info->info.scsi.irq = NO_IRQ;
 		}
 
-		info = (PowerTecScsi_Info *)instance->hostdata;
-
-		instance->dma_channel = 3; /* slot 1 */
-		if (request_dma(instance->dma_channel, "powertec")) {
+		if (host->dma_channel != NO_DMA &&
+		    request_dma(host->dma_channel, "powertec")) {
 			printk("scsi%d: DMA%d not free, DMA disabled\n",
-			       instance->host_no, instance->dma_channel);
-			instance->dma_channel = NO_DMA;
+			       host->host_no, host->dma_channel);
+			host->dma_channel = NO_DMA;
 		}
 
-		info->info.scsi.io_port	=
-				instance->io_port + POWERTEC_FAS216_OFFSET;
-		info->info.scsi.io_shift= POWERTEC_FAS216_SHIFT;
-		info->info.scsi.irq	= instance->irq;
-		info->info.ifcfg.clockrate = POWERTEC_XTALFREQ;
-		info->info.ifcfg.select_timeout = 255;
-		info->info.ifcfg.asyncperiod = POWERTEC_ASYNC_PERIOD;
-		info->info.ifcfg.sync_max_depth = POWERTEC_SYNC_DEPTH;
-		info->info.dma.setup	= powertecscsi_dma_setup;
-		info->info.dma.pseudo	= NULL;
-		info->info.dma.stop	= powertecscsi_dma_stop;
-
-		fas216_init(instance);
+		fas216_init(host);
 		++count;
 	}
 	return count;
 }
 
-/* Function: int powertecscsi_release(struct Scsi_Host * host)
- * Purpose : releases all resources used by this adapter
- * Params  : host - driver host structure to return info for.
- * Returns : nothing
+/* Prototype: int powertecscsi_release(struct Scsi_Host * host)
+ * Purpose  : releases all resources used by this adapter
+ * Params   : host - driver host structure to return info for.
  */
-int powertecscsi_release(struct Scsi_Host *instance)
+int powertecscsi_release(struct Scsi_Host *host)
 {
 	int i;
 
-	fas216_release(instance);
+	fas216_release(host);
 
-	if (instance->irq != NO_IRQ)
-		free_irq(instance->irq, instance);
-	if (instance->dma_channel != NO_DMA)
-		free_dma(instance->dma_channel);
-	release_region(instance->io_port + POWERTEC_FAS216_OFFSET,
+	if (host->irq != NO_IRQ)
+		free_irq(host->irq, host);
+	if (host->dma_channel != NO_DMA)
+		free_dma(host->dma_channel);
+	release_region(host->io_port + POWERTEC_FAS216_OFFSET,
 		       16 << POWERTEC_FAS216_SHIFT);
 
 	for (i = 0; i < MAX_ECARDS; i++)
 		if (ecs[i] &&
-		    instance->io_port == ecard_address(ecs[i], ECARD_IOC, 0))
+		    host->io_port == ecard_address(ecs[i], ECARD_IOC, ECARD_FAST))
 			ecard_release(ecs[i]);
 	return 0;
 }
 
-/* Function: const char *powertecscsi_info(struct Scsi_Host * host)
- * Purpose : returns a descriptive string about this interface,
- * Params  : host - driver host structure to return info for.
- * Returns : pointer to a static buffer containing null terminated string.
+/* Prototype: const char *powertecscsi_info(struct Scsi_Host * host)
+ * Purpose  : returns a descriptive string about this interface,
+ * Params   : host - driver host structure to return info for.
+ * Returns  : pointer to a static buffer containing null terminated string.
  */
 const char *powertecscsi_info(struct Scsi_Host *host)
 {
@@ -297,7 +342,7 @@
 	static char string[100], *p;
 
 	p = string;
-	p += sprintf(string, "%s at port %X ",
+	p += sprintf(string, "%s at port %lX ",
 		     host->hostt->name, host->io_port);
 
 	if (host->irq != NO_IRQ)
@@ -314,21 +359,55 @@
 		     VER_MAJOR, VER_MINOR, VER_PATCH,
 		     info->info.scsi.type);
 
+	p += sprintf(p, " terminators %s",
+		     info->control.terms ? "on" : "off");
+
 	return string;
 }
 
-/* Function: int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
+/* Prototype: int powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
+ * Purpose  : Set a driver specific function
+ * Params   : host   - host to setup
+ *          : buffer - buffer containing string describing operation
+ *          : length - length of string
+ * Returns  : -EINVAL, or 0
+ */
+static int
+powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
+{
+	int ret = length;
+
+	if (length >= 12 && strncmp(buffer, "POWERTECSCSI", 12) == 0) {
+		buffer += 12;
+		length -= 12;
+
+		if (length >= 5 && strncmp(buffer, "term=", 5) == 0) {
+			if (buffer[5] == '1')
+				powertecscsi_terminator_ctl(host, 1);
+			else if (buffer[5] == '0')
+				powertecscsi_terminator_ctl(host, 0);
+			else
+				ret = -EINVAL;
+		} else
+			ret = -EINVAL;
+	} else
+		ret = -EINVAL;
+
+	return ret;
+}
+
+/* Prototype: int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
  *					int length, int host_no, int inout)
- * Purpose : Return information about the driver to a user process accessing
- *	     the /proc filesystem.
- * Params  : buffer - a buffer to write information to
- *	     start  - a pointer into this buffer set by this routine to the start
- *		      of the required information.
- *	     offset - offset into information that we have read upto.
- *	     length - length of buffer
- *	     host_no - host number to return information for
- *	     inout  - 0 for reading, 1 for writing.
- * Returns : length of data written to buffer.
+ * Purpose  : Return information about the driver to a user process accessing
+ *	      the /proc filesystem.
+ * Params   : buffer - a buffer to write information to
+ *	      start  - a pointer into this buffer set by this routine to the start
+ *		       of the required information.
+ *	      offset - offset into information that we have read upto.
+ *	      length - length of buffer
+ *	      host_no - host number to return information for
+ *	      inout  - 0 for reading, 1 for writing.
+ * Returns  : length of data written to buffer.
  */
 int powertecscsi_proc_info(char *buffer, char **start, off_t offset,
 			    int length, int host_no, int inout)
@@ -346,27 +425,28 @@
 	if (!host)
 		return 0;
 
-	info = (PowerTecScsi_Info *)host->hostdata;
 	if (inout == 1)
-		return -EINVAL;
+		return powertecscsi_set_proc_info(host, buffer, length);
+
+	info = (PowerTecScsi_Info *)host->hostdata;
 
 	begin = 0;
 	pos = sprintf(buffer,
 			"PowerTec SCSI driver version %d.%d.%d\n",
 			VER_MAJOR, VER_MINOR, VER_PATCH);
 	pos += sprintf(buffer + pos,
-			"Address: %08X    IRQ : %d     DMA : %d\n"
-			"FAS    : %s\n\n"
+			"Address: %08lX    IRQ : %d     DMA : %d\n"
+			"FAS    : %-10s  TERM: %-3s\n\n"
 			"Statistics:\n",
 			host->io_port, host->irq, host->dma_channel,
-			info->info.scsi.type);
+			info->info.scsi.type, info->control.terms ? "on" : "off");
 
 	pos += sprintf(buffer+pos,
-			"Queued commands: %-10d   Issued commands: %-10d\n"
-			"Done commands  : %-10d   Reads          : %-10d\n"
-			"Writes         : %-10d   Others         : %-10d\n"
-			"Disconnects    : %-10d   Aborts         : %-10d\n"
-			"Resets         : %-10d\n",
+			"Queued commands: %-10u   Issued commands: %-10u\n"
+			"Done commands  : %-10u   Reads          : %-10u\n"
+			"Writes         : %-10u   Others         : %-10u\n"
+			"Disconnects    : %-10u   Aborts         : %-10u\n"
+			"Resets         : %-10u\n",
 			info->info.stats.queues,      info->info.stats.removes,
 			info->info.stats.fins,        info->info.stats.reads,
 			info->info.stats.writes,      info->info.stats.miscs,
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/powertec.h linux/drivers/acorn/scsi/powertec.h
--- v2.1.100/linux/drivers/acorn/scsi/powertec.h	Wed Apr  8 19:36:25 1998
+++ linux/drivers/acorn/scsi/powertec.h	Fri May  8 00:42:39 1998
@@ -1,7 +1,7 @@
 /*
  * PowerTec SCSI driver
  *
- * Copyright (C) 1997 Russell King
+ * Copyright (C) 1997-1998 Russell King
  */
 #ifndef POWERTECSCSI_H
 #define POWERTECSCSI_H
@@ -64,10 +64,20 @@
 
 #ifndef HOSTS_C
 
+#include <asm/dma.h>
+
+#define NR_SG	256
+
 typedef struct {
-    FAS216_Info info;
+	FAS216_Info info;
+
+	struct {
+		unsigned int term_port;
+		unsigned int terms;
+	} control;
 
-    /* other info... */
+	/* other info... */
+	dmasg_t		dmasg[NR_SG];	/* Scatter DMA list	*/
 } PowerTecScsi_Info;
 
 #endif /* HOSTS_C */
diff -u --recursive --new-file v2.1.100/linux/drivers/acorn/scsi/queue.c linux/drivers/acorn/scsi/queue.c
--- v2.1.100/linux/drivers/acorn/scsi/queue.c	Mon Feb 23 18:12:03 1998
+++ linux/drivers/acorn/scsi/queue.c	Fri May  8 00:42:39 1998
@@ -298,7 +298,7 @@
 			else
 				queue->tail = NULL;
 		} else {
-		 	prev->next = q->next;
+			prev->next = q->next;
 			if (prev->next)
 				prev->next->prev = prev;
 			else
diff -u --recursive --new-file v2.1.100/linux/drivers/ap1000/apfddi.c linux/drivers/ap1000/apfddi.c
--- v2.1.100/linux/drivers/ap1000/apfddi.c	Fri Feb  7 05:54:54 1997
+++ linux/drivers/ap1000/apfddi.c	Fri May  8 00:47:24 1998
@@ -488,6 +488,13 @@
 int apfddi_init(struct device *dev)
 {
     int i;
+
+    /*
+     * Check if this thing has already been initialised.
+     */
+    if (apfddi_device != NULL)
+	return -ENODEV;
+
     printk("apfddi_init(): Initialising fddi interface\n");
 
     apfddi_device = dev;
@@ -523,12 +530,6 @@
 
     memset(dev->broadcast, 0xFF, ETH_ALEN);
     
-    dev->family = AF_INET;
-    dev->pa_addr = in_aton("150.203.142.28");  /* hibana-f */
-    dev->pa_mask = in_aton("255.255.255.0");
-    dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
-    dev->pa_alen = 4;
-
     return(0);
 }
 
diff -u --recursive --new-file v2.1.100/linux/drivers/ap1000/bif.c linux/drivers/ap1000/bif.c
--- v2.1.100/linux/drivers/ap1000/bif.c	Thu Feb 12 20:56:05 1998
+++ linux/drivers/ap1000/bif.c	Fri May  8 00:47:24 1998
@@ -127,7 +127,6 @@
     dev->rebuild_header	= bif_rebuild_header;
     dev->open = bif_open;
     dev->flags = IFF_NOARP;   /* Don't use ARP on this device */
-    dev->family = AF_INET;
     dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
     if (dev->priv == NULL)
 	return -ENOMEM;
@@ -138,10 +137,6 @@
     dev->stop = bif_stop;
     dev->get_stats = bif_get_stats;
 
-    /* Initialise the bif device structure */
-    for (i = 0; i < DEV_NUMBUFFS; i++)
-	skb_queue_head_init(&dev->buffs[i]);
-    
     dev->set_mac_address = bif_set_mac_address;
     dev->header_cache_update = NULL;
     dev->do_ioctl = bif_do_ioctl;    
@@ -149,12 +144,9 @@
     dev->set_multicast_list = bif_set_multicast_list;
 
     memset(dev->broadcast, 0xFF, ETH_ALEN);
-    
-    dev->pa_addr = 0;
-    dev->pa_brdaddr = 0;
-    dev->pa_mask = 0;
-    dev->pa_alen = 4;
 
+    dev_init_buffers(dev);
+    
     return(0);
 }
 
diff -u --recursive --new-file v2.1.100/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c
--- v2.1.100/linux/drivers/ap1000/ddv.c	Thu May  7 22:51:47 1998
+++ linux/drivers/ap1000/ddv.c	Fri May  8 00:47:24 1998
@@ -60,6 +60,8 @@
    to make things a bit more efficient */
 #define SECTOR_BLOCK_SHIFT 9
 
+#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1)
+
 /* try to read ahead a bit */
 #define DDV_READ_AHEAD 64
 
diff -u --recursive --new-file v2.1.100/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.1.100/linux/drivers/block/Config.in	Mon Apr  6 17:40:59 1998
+++ linux/drivers/block/Config.in	Fri May  8 18:12:30 1998
@@ -60,7 +60,7 @@
 comment 'Additional Block Devices'
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-#tristate 'Network block device support' CONFIG_BLK_DEV_NBD
+tristate 'Network block device support' CONFIG_BLK_DEV_NBD
 bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
 if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
   tristate '   Linear (append) mode' CONFIG_MD_LINEAR
diff -u --recursive --new-file v2.1.100/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.1.100/linux/drivers/block/Makefile	Mon Apr  6 17:40:59 1998
+++ linux/drivers/block/Makefile	Fri May  8 18:12:30 1998
@@ -38,6 +38,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_AMIGA_FLOPPY),y)
+  L_OBJS += amiflop.o
+else
+  ifeq ($(CONFIG_AMIGA_FLOPPY),m)
+    M_OBJS += amiflop.o
+  endif
+endif
+
+ifeq ($(CONFIG_ATARI_FLOPPY),y)
+  L_OBJS += ataflop.o
+else
+  ifeq ($(CONFIG_ATARI_FLOPPY),m)
+  M_OBJS += ataflop.o
+  endif
+endif
+
 ifeq ($(CONFIG_ATARI_ACSI),y)
   LX_OBJS += acsi.o
 else
@@ -91,9 +107,7 @@
 else
   ifeq ($(CONFIG_BLK_DEV_IDE),m)
   MIX_OBJS += ide.o
-  ifeq ($(CONFIG_PROC_FS),y)
-    M_OBJS += ide-proc.o
-  endif
+  # ide-mod includes ide-proc
   M_OBJS += ide-mod.o
   MX_OBJS += ide-probe.o
   endif
diff -u --recursive --new-file v2.1.100/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.1.100/linux/drivers/block/acsi.c	Thu May  7 22:51:47 1998
+++ linux/drivers/block/acsi.c	Fri May  8 18:12:30 1998
@@ -1851,7 +1851,7 @@
 
 	if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
 		printk( KERN_ERR "acsi: cleanup_module failed\n");
-	
+
 	for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
 		if (*gdp == &acsi_gendisk)
 			break;
diff -u --recursive --new-file v2.1.100/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.100/linux/drivers/block/floppy.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/floppy.c	Fri May  8 00:27:34 1998
@@ -694,7 +694,7 @@
 		DPRINT("checking disk change line for drive %d\n",drive);
 		DPRINT("jiffies=%ld\n", jiffies);
 		DPRINT("disk change line=%x\n",fd_inb(FD_DIR)&0x80);
-		DPRINT("flags=%x\n",UDRS->flags);
+		DPRINT("flags=%lx\n",UDRS->flags);
 	}
 #endif
 	if (UDP->flags & FD_BROKEN_DCL)
diff -u --recursive --new-file v2.1.100/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.1.100/linux/drivers/block/hd.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/hd.c	Fri May  8 18:12:30 1998
@@ -73,6 +73,8 @@
 static int reset = 0;
 static int hd_error = 0;
 
+#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
+
 /*
  *  This struct defines the HD's and their types.
  */
diff -u --recursive --new-file v2.1.100/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.100/linux/drivers/block/ide.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/ide.c	Fri May  8 18:12:30 1998
@@ -3,7 +3,6 @@
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
-#define _IDE_C		/* needed by <linux/blk.h> */
 
 /*
  *  Maintained by Mark Lord  <mlord@pobox.com>
@@ -98,6 +97,8 @@
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
+#define _IDE_C			/* Tell ide.h it's really us */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -147,6 +148,28 @@
  * This is declared extern in ide.h, for access by other IDE modules:
  */
 ide_hwif_t	ide_hwifs[MAX_HWIFS];	/* master data repository */
+
+/*
+ * This is our end_request replacement function.
+ */
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup)
+{
+	struct request *req;
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock,flags);
+	req = hwgroup->rq;
+
+	if (end_that_request_first(req, uptodate, DEVICE_NAME))
+		goto out;
+	add_blkdev_randomness(MAJOR(req->rq_dev));
+	hwgroup->drive->queue = req->next;
+        blk_dev[MAJOR(req->rq_dev)].current_request = NULL;
+        hwgroup->rq = NULL;
+	end_that_request_last(req);
+out:
+	spin_unlock_irqrestore(&io_request_lock,flags);
+}
 
 #if (DISK_RECOVERY_TIME > 0)
 /*
diff -u --recursive --new-file v2.1.100/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.1.100/linux/drivers/block/ide.h	Thu May  7 22:51:48 1998
+++ linux/drivers/block/ide.h	Fri May  8 18:21:47 1998
@@ -508,10 +508,13 @@
 #endif
 
 /*
- * One final include file, which references some of the data/defns from above
+ * We need blk.h, but we replace its end_request by our own version.
  */
-#define IDE_DRIVER	/* "parameter" for blk.h */
+#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
+#define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
 #include <linux/blk.h>
+
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
 
 /*
  * This is used for (nearly) all data transfers from/to the IDE interface
diff -u --recursive --new-file v2.1.100/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.1.100/linux/drivers/block/ll_rw_blk.c	Tue Apr 14 14:29:20 1998
+++ linux/drivers/block/ll_rw_blk.c	Fri May  8 18:12:30 1998
@@ -435,7 +435,7 @@
 /* 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. */
-        if (major == LOOP_MAJOR)
+	 if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
 	     max_req >>= 1;
 
 	/*
@@ -452,7 +452,7 @@
 	if (!req) {
 		/* MD and loop can't handle plugging without deadlocking */
 		if (major != MD_MAJOR && major != LOOP_MAJOR && 
-		    major != DDV_MAJOR)
+		    major != DDV_MAJOR && major != NBD_MAJOR)
 			plug_device(blk_dev + major); /* is atomic */
 	} else switch (major) {
 	     case IDE0_MAJOR:	/* same as HD_MAJOR */
@@ -669,7 +669,7 @@
 	}
 	buffersize = PAGE_SIZE / nb;
 
-	if (major == LOOP_MAJOR)
+	if ((major == LOOP_MAJOR) || (major == NBD_MAJOR))
 	     max_req >>= 1;
 	for (j=0, i=0; i<nb;)
 	{
@@ -716,6 +716,58 @@
 	}
 }
 
+/*
+ * First step of what used to be end_request
+ *
+ * 0 means continue with end_that_request_last,
+ * 1 means we are done
+ */
+
+int 
+end_that_request_first( struct request *req, int uptodate, char *name ) 
+{
+	struct buffer_head * bh;
+	int nsect;
+
+	req->errors = 0;
+	if (!uptodate) {
+		printk("end_request: I/O error, dev %s (%s), sector %lu\n",
+			kdevname(req->rq_dev), name, req->sector);
+		if ((bh = req->bh) != NULL) {
+			nsect = bh->b_size >> 9;
+			req->nr_sectors--;
+			req->nr_sectors &= ~(nsect - 1);
+			req->sector += nsect;
+			req->sector &= ~(nsect - 1);
+		}
+	}
+
+	if ((bh = req->bh) != NULL) {
+		req->bh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+		bh->b_end_io(bh, uptodate);
+		if ((bh = req->bh) != NULL) {
+			req->current_nr_sectors = bh->b_size >> 9;
+			if (req->nr_sectors < req->current_nr_sectors) {
+				req->nr_sectors = req->current_nr_sectors;
+				printk("end_request: buffer-list destroyed\n");
+			}
+			req->buffer = bh->b_data;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void
+end_that_request_last( struct request *req ) 
+{
+	if (req->sem != NULL)
+		up(req->sem);
+	req->rq_status = RQ_INACTIVE;
+	wake_up(&wait_for_request);
+}
+
 __initfunc(int blk_dev_init(void))
 {
 	struct request * req;
@@ -771,10 +823,17 @@
 #ifdef CONFIG_MAC_FLOPPY
 	swim3_init();
 #endif
+#ifdef CONFIG_AMIGA_FLOPPY
+	amiga_floppy_init();
+#endif
+#ifdef CONFIG_ATARI_FLOPPY
+	atari_floppy_init();
+#endif
 #ifdef CONFIG_BLK_DEV_FD
 	floppy_init();
 #else
-#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__)
+#if !defined (__mc68000__) && !defined(CONFIG_PMAC) && !defined(__sparc__)\
+    && !defined(CONFIG_APUS)
 	outb_p(0xc, 0x3f2);
 #endif
 #endif
@@ -820,7 +879,12 @@
 #ifdef CONFIG_DDV
 	ddv_init();
 #endif
+#ifdef CONFIG_BLK_DEV_NBD
+	nbd_init();
+#endif
 	return 0;
 };
 
 EXPORT_SYMBOL(io_request_lock);
+EXPORT_SYMBOL(end_that_request_first);
+EXPORT_SYMBOL(end_that_request_last);
diff -u --recursive --new-file v2.1.100/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.1.100/linux/drivers/block/md.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/md.c	Fri May  8 00:17:13 1998
@@ -70,7 +70,6 @@
 static struct hd_struct md_hd_struct[MAX_MD_DEV];
 static int md_blocksizes[MAX_MD_DEV];
 int md_maxreadahead[MAX_MD_DEV];
-static struct md_thread md_threads[MAX_MD_THREADS];
 #if SUPPORT_RECONSTRUCTION
 static struct md_thread *md_sync_thread = NULL;
 #endif /* SUPPORT_RECONSTRUCTION */
@@ -97,6 +96,8 @@
 static struct md_personality *pers[MAX_PERSONALITY]={NULL, };
 struct md_dev md_dev[MAX_MD_DEV];
 
+int md_thread(void * arg);
+
 static struct gendisk *find_gendisk (kdev_t dev)
 {
   struct gendisk *tmp=gendisk_head;
@@ -803,39 +804,98 @@
 {
   printk ("Got md request, not good...");
   return;
-}  
+}
+
+void md_wakeup_thread(struct md_thread *thread)
+{
+	set_bit(THREAD_WAKEUP, &thread->flags);
+	wake_up(&thread->wqueue);
+}
 
-/*
- * We run MAX_MD_THREADS from md_init() and arbitrate them in run time.
- * This is not so elegant, but how can we use kernel_thread() from within
- * loadable modules?
- */
 struct md_thread *md_register_thread (void (*run) (void *), void *data)
 {
-	int i;
-	for (i = 0; i < MAX_MD_THREADS; i++) {
-		if (md_threads[i].run == NULL) {
-			md_threads[i].run = run;
-			md_threads[i].data = data;
-			return md_threads + i;
-		}
+	struct md_thread *thread = (struct md_thread *)
+		kmalloc(sizeof(struct md_thread), GFP_KERNEL);
+	int ret;
+	struct semaphore sem = MUTEX_LOCKED;
+	
+	if (!thread) return NULL;
+	
+	memset(thread, 0, sizeof(struct md_thread));
+	init_waitqueue(&thread->wqueue);
+	
+	thread->sem = &sem;
+	thread->run = run;
+	thread->data = data;
+	ret = kernel_thread(md_thread, thread, 0);
+	if (ret < 0) {
+		kfree(thread);
+		return NULL;
 	}
-	return NULL;
+	down(&sem);
+	return thread;
 }
 
 void md_unregister_thread (struct md_thread *thread)
 {
+	struct semaphore sem = MUTEX_LOCKED;
+	
+	thread->sem = &sem;
 	thread->run = NULL;
-	thread->data = NULL;
-	thread->flags = 0;
+	if (thread->tsk)
+		printk("Killing md_thread %d %p %s\n",
+		       thread->tsk->pid, thread->tsk, thread->tsk->comm);
+	else
+		printk("Aiee. md_thread has 0 tsk\n");
+	send_sig(SIGKILL, thread->tsk, 1);
+	printk("downing on %p\n", &sem);
+	down(&sem);
 }
 
-void md_wakeup_thread(struct md_thread *thread)
+#define SHUTDOWN_SIGS   (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
+
+int md_thread(void * arg)
 {
-	set_bit(THREAD_WAKEUP, &thread->flags);
-	wake_up(&thread->wqueue);
-}
+	struct md_thread *thread = arg;
+
+	lock_kernel();
+	exit_mm(current);
+	exit_files(current);
+	exit_fs(current);
+	
+	current->session = 1;
+	current->pgrp = 1;
+	sprintf(current->comm, "md_thread");
+	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
+	thread->tsk = current;
+	up(thread->sem);
 
+	for (;;) {
+		cli();
+		if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
+			do {
+			        spin_lock(&current->sigmask_lock);
+				flush_signals(current);
+	  			spin_unlock(&current->sigmask_lock);
+				interruptible_sleep_on(&thread->wqueue);
+				cli();
+				if (test_bit(THREAD_WAKEUP, &thread->flags))
+					break;
+				if (!thread->run) {
+					sti();
+					up(thread->sem);
+					return 0;
+				}
+			} while (signal_pending(current));
+		}
+		sti();
+		clear_bit(THREAD_WAKEUP, &thread->flags);
+		if (thread->run) {
+			thread->run(thread->data);
+			run_task_queue(&tq_disk);
+		}
+	}
+}
 
 EXPORT_SYMBOL(md_size);
 EXPORT_SYMBOL(md_maxreadahead);
@@ -981,37 +1041,6 @@
   return 0;
 } 
 
-int md_thread(void * arg)
-{
-	struct md_thread *thread = arg;
-
-	current->session = 1;
-	current->pgrp = 1;
-	sprintf(current->comm, "md_thread");
-
-	lock_kernel();
-	for (;;) {
-		sti();
-		clear_bit(THREAD_WAKEUP, &thread->flags);
-		if (thread->run) {
-			thread->run(thread->data);
-			run_task_queue(&tq_disk);
-		}
-		cli();
-		if (!test_bit(THREAD_WAKEUP, &thread->flags)) {
-			do {
-			         spin_lock(&current->sigmask_lock);
-				 flush_signals(current);
-				 spin_unlock(&current->sigmask_lock);
-				 interruptible_sleep_on(&thread->wqueue);
-				 cli();
-				 if (test_bit(THREAD_WAKEUP, &thread->flags))
-				 	break;
-			} while (signal_pending(current));
-		}
-	}
-}
-
 static md_descriptor_t *get_spare(struct md_dev *mddev)
 {
 	int i;
@@ -1281,8 +1310,6 @@
 
 __initfunc(int md_init (void))
 {
-  int i;
-
   printk ("md driver %d.%d.%d MAX_MD_DEV=%d, MAX_REAL=%d\n",
     MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION,
     MAX_MD_DEV, MAX_REAL);
@@ -1291,15 +1318,6 @@
   {
     printk ("Unable to get major %d for md\n", MD_MAJOR);
     return (-1);
-  }
-
-  memset(md_threads, 0, MAX_MD_THREADS * sizeof(struct md_thread));
-  printk("md: starting %d kernel threads\n", MAX_MD_THREADS);
-  for (i = 0; i < MAX_MD_THREADS; i++) {
-    md_threads[i].run = NULL;
-    init_waitqueue(&md_threads[i].wqueue);
-    md_threads[i].flags = 0;
-    kernel_thread (md_thread, md_threads + i, 0);
   }
 
   blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST;
diff -u --recursive --new-file v2.1.100/linux/drivers/block/raid0.c linux/drivers/block/raid0.c
--- v2.1.100/linux/drivers/block/raid0.c	Sat Nov  8 11:39:12 1997
+++ linux/drivers/block/raid0.c	Fri May  8 00:17:13 1998
@@ -104,7 +104,7 @@
     md_size[minor]/data->smallest->size +
     (md_size[minor]%data->smallest->size ? 1 : 0);
 
-  printk ("raid0 : Allocating %d bytes for hash.\n",sizeof(struct raid0_hash)*nb_zone);
+  printk ("raid0 : Allocating %ld bytes for hash.\n",(long)sizeof(struct raid0_hash)*nb_zone);
   if ((data->hash_table=vmalloc (sizeof (struct raid0_hash)*nb_zone)) == NULL)
   {
     vfree(data->strip_zone);
diff -u --recursive --new-file v2.1.100/linux/drivers/block/raid5.c linux/drivers/block/raid5.c
--- v2.1.100/linux/drivers/block/raid5.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/raid5.c	Fri May  8 00:17:13 1998
@@ -21,6 +21,7 @@
 #include <linux/raid5.h>
 #include <asm/bitops.h>
 #include <asm/atomic.h>
+#include <asm/md.h>
 
 static struct md_personality raid5_personality;
 
@@ -741,10 +742,16 @@
 	return blocknr;
 }
 
+#ifdef HAVE_ARCH_XORBLOCK
 static void xor_block(struct buffer_head *dest, struct buffer_head *source)
 {
-	int lines = dest->b_size / (sizeof (int)) / 8, i;
-	int *destp = (int *) dest->b_data, *sourcep = (int *) source->b_data;
+	__xor_block((char *) dest->b_data, (char *) source->b_data, dest->b_size);
+}
+#else
+static void xor_block(struct buffer_head *dest, struct buffer_head *source)
+{
+	long lines = dest->b_size / (sizeof (long)) / 8, i;
+	long *destp = (long *) dest->b_data, *sourcep = (long *) source->b_data;
 
 	for (i = lines; i > 0; i--) {
 		*(destp + 0) ^= *(sourcep + 0);
@@ -759,6 +766,7 @@
 		sourcep += 8;
 	}
 }
+#endif
 
 static void compute_block(struct stripe_head *sh, int dd_idx)
 {
diff -u --recursive --new-file v2.1.100/linux/drivers/block/swim3.c linux/drivers/block/swim3.c
--- v2.1.100/linux/drivers/block/swim3.c	Sun Dec 21 17:41:24 1997
+++ linux/drivers/block/swim3.c	Fri May  8 18:12:30 1998
@@ -21,6 +21,7 @@
 #include <asm/dbdma.h>
 #include <asm/prom.h>
 #include <asm/uaccess.h>
+#include <asm/mediabay.h>
 
 #define MAJOR_NR	FLOPPY_MAJOR
 #include <linux/blk.h>
@@ -134,9 +135,11 @@
 	int	ref_count;
 	int	expect_cyl;
 	struct timer_list timeout;
+	int	timeout_pending;
 	int	ejected;
 	struct wait_queue *wait;
 	int	wanted;
+	int	in_media_bay;
 	char	dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
 };
 
@@ -161,6 +164,8 @@
 static int swim3_readbit(struct floppy_state *fs, int bit);
 static void do_fd_request(void);
 static void start_request(struct floppy_state *fs);
+static void set_timeout(struct floppy_state *fs, int nticks,
+			void (*proc)(unsigned long));
 static void scan_track(struct floppy_state *fs);
 static void seek_track(struct floppy_state *fs, int n);
 static void init_dma(struct dbdma_cmd *cp, int cmd, void *buf, int count);
@@ -179,10 +184,10 @@
 			unsigned int cmd, unsigned long param);
 static int floppy_open(struct inode *inode, struct file *filp);
 static int floppy_release(struct inode *inode, struct file *filp);
-static long floppy_read(struct inode *inode, struct file *filp,
-			char *buf, unsigned long count);
-static long floppy_write(struct inode *inode, struct file *filp,
-			 const char *buf, unsigned long count);
+static ssize_t floppy_read(struct file *filp, char *buf,
+			   size_t count, loff_t *ppos);
+static ssize_t floppy_write(struct file *filp, const char *buf,
+			    size_t count, loff_t *ppos);
 static int floppy_check_change(kdev_t dev);
 static int floppy_revalidate(kdev_t dev);
 int swim3_init(void);
@@ -294,6 +299,22 @@
 	}
 }
 
+static void set_timeout(struct floppy_state *fs, int nticks,
+			void (*proc)(unsigned long))
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	if (fs->timeout_pending)
+		del_timer(&fs->timeout);
+	fs->timeout.expires = jiffies + nticks;
+	fs->timeout.function = proc;
+	fs->timeout.data = (unsigned long) fs;
+	add_timer(&fs->timeout);
+	fs->timeout_pending = 1;
+	restore_flags(flags);
+}
+
 static inline void scan_track(struct floppy_state *fs)
 {
 	volatile struct swim3 *sw = fs->swim3;
@@ -304,11 +325,7 @@
 	out_8(&sw->control_bis, SCAN_TRACK);
 	/* enable intr when track found */
 	out_8(&sw->intr_enable, ERROR | SEEN_SECTOR);
-	/* enable timeout */
-	fs->timeout.expires = jiffies + HZ;
-	fs->timeout.function = scan_timeout;
-	fs->timeout.data = (unsigned long) fs;
-	add_timer(&fs->timeout);
+	set_timeout(fs, HZ, scan_timeout);	/* enable timeout */
 }
 
 static inline void seek_track(struct floppy_state *fs, int n)
@@ -327,11 +344,7 @@
 	out_8(&sw->control_bis, DO_SEEK);
 	/* enable intr when seek finished */
 	out_8(&sw->intr_enable, ERROR | SEEK_DONE);
-	/* enable timeout */
-	fs->timeout.expires = jiffies + HZ/2;
-	fs->timeout.function = seek_timeout;
-	fs->timeout.data = (unsigned long) fs;
-	add_timer(&fs->timeout);
+	set_timeout(fs, HZ/2, seek_timeout);	/* enable timeout */
 }
 
 static inline void init_dma(struct dbdma_cmd *cp, int cmd,
@@ -384,11 +397,7 @@
 	      (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | SCAN_TRACK);
 	/* enable intr when transfer complete */
 	out_8(&sw->intr_enable, ERROR | TRANSFER_DONE);
-	/* enable timeout */
-	fs->timeout.expires = jiffies + 2*HZ;
-	fs->timeout.function = xfer_timeout;
-	fs->timeout.data = (unsigned long) fs;
-	add_timer(&fs->timeout);
+	set_timeout(fs, 2*HZ, xfer_timeout);	/* enable timeout */
 }
 
 static void act(struct floppy_state *fs)
@@ -434,10 +443,7 @@
 			in_8(&sw->intr);	/* clear DATA_CHANGED */
 			if (in_8(&sw->status) & DATA) {
 				/* seek_complete is not yet true */
-				fs->timeout.expires = jiffies + HZ/2;
-				fs->timeout.function = seek_timeout;
-				fs->timeout.data = (unsigned long) fs;
-				add_timer(&fs->timeout);
+				set_timeout(fs, HZ/2, seek_timeout);
 				return;
 			}
 			out_8(&sw->intr_enable, 0);
@@ -474,6 +480,7 @@
 	struct floppy_state *fs = (struct floppy_state *) data;
 	volatile struct swim3 *sw = fs->swim3;
 
+	fs->timeout_pending = 0;
 	out_8(&sw->control_bic, SCAN_TRACK);
 	out_8(&sw->select, RELAX);
 	out_8(&sw->intr_enable, 0);
@@ -493,6 +500,7 @@
 	struct floppy_state *fs = (struct floppy_state *) data;
 	volatile struct swim3 *sw = fs->swim3;
 
+	fs->timeout_pending = 0;
 	if (fs->state == settling) {
 		printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n",
 		       sw->select, sw->control, sw->status, sw->intr, sw->intr_enable);
@@ -520,6 +528,7 @@
 	struct dbdma_cmd *cp = fs->dma_cmd;
 	unsigned long s;
 
+	fs->timeout_pending = 0;
 	st_le32(&dr->control, RUN << 16);
 	out_8(&sw->intr_enable, 0);
 	out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK);
@@ -550,6 +559,9 @@
 
 	err = in_8(&sw->error);
 	intr = in_8(&sw->intr);
+#if 0
+	printk(KERN_DEBUG "swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err);
+#endif
 	if ((intr & ERROR) && fs->state != do_transfer)
 		printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n",
 		       fs->state, CURRENT->cmd, intr, err);
@@ -560,6 +572,7 @@
 			out_8(&sw->select, RELAX);
 			out_8(&sw->intr_enable, 0);
 			del_timer(&fs->timeout);
+			fs->timeout_pending = 0;
 			if (sw->ctrack == 0xff) {
 				printk(KERN_ERR "swim3: seen sector but cyl=ff?\n");
 				fs->cur_cyl = -1;
@@ -589,6 +602,7 @@
 			out_8(&sw->select, RELAX);
 			out_8(&sw->intr_enable, 0);
 			del_timer(&fs->timeout);
+			fs->timeout_pending = 0;
 			if (fs->state == seeking)
 				++fs->retries;
 			fs->state = settling;
@@ -598,6 +612,7 @@
 	case settling:
 		out_8(&sw->intr_enable, 0);
 		del_timer(&fs->timeout);
+		fs->timeout_pending = 0;
 		act(fs);
 		break;
 	case do_transfer:
@@ -610,6 +625,7 @@
 		out_8(&sw->control_bic, WRITE_SECTORS | SCAN_TRACK);
 		out_8(&sw->select, RELAX);
 		del_timer(&fs->timeout);
+		fs->timeout_pending = 0;
 		if (CURRENT->cmd == WRITE)
 			++cp;
 		stat = ld_le16(&cp->xfer_status);
@@ -772,6 +788,12 @@
 	sw = fs->swim3;
 	err = 0;
 	if (fs->ref_count == 0) {
+		if (fs->in_media_bay && !check_media_bay(MB_FD))
+			return -ENXIO;
+		out_8(&sw->mode, 0x95);
+		out_8(&sw->control_bic, 0xff);
+		out_8(&sw->reg5, 0x28);
+		udelay(1);
 		out_8(&sw->intr_enable, 0);
 		out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE);
 		swim3_action(fs, MOTOR_ON);
@@ -905,9 +927,10 @@
 	return ret;
 }
 
-static long floppy_read(struct inode *inode, struct file *filp,
-			char *buf, unsigned long count)
+static ssize_t floppy_read(struct file *filp, char *buf,
+			   size_t count, loff_t *ppos)
 {
+	struct inode *inode = filp->f_dentry->d_inode;
 	struct floppy_state *fs;
 
 	if (MINOR(inode->i_rdev) != 0)
@@ -915,12 +938,13 @@
 	fs = &floppy_states[0];
 	if (fs->ejected)
 		return -ENXIO;
-	return block_read(inode, filp, buf, count);
+	return block_read(filp, buf, count, ppos);
 }
 
-static long floppy_write(struct inode *inode, struct file *filp,
-			 const char *buf, unsigned long count)
+static ssize_t floppy_write(struct file * filp, const char * buf,
+			    size_t count, loff_t *ppos)
 {
+	struct inode * inode = filp->f_dentry->d_inode;
 	struct floppy_state *fs;
 
 	if (MINOR(inode->i_rdev) != 0)
@@ -928,7 +952,7 @@
 	fs = &floppy_states[0];
 	if (fs->ejected)
 		return -ENXIO;
-	return block_write(inode, filp, buf, count);
+	return block_write(filp, buf, count, ppos);
 }
 
 static void floppy_off(unsigned int nr)
@@ -955,9 +979,16 @@
 {
 	struct device_node *swims;
 	struct floppy_state *fs = &floppy_states[0];
-	volatile struct swim3 *sw;
+	int is_3400 = 0;
+
+	if (find_devices("media-bay") != NULL) {
+		/* assume this is a PB3400 */
+		swims = find_devices("floppy");
+		is_3400 = 1;
+	} else {
+		swims = find_devices("swim3");
+	}
 
-	swims = find_devices("swim3");
 	if (swims == NULL)
 		return 0;
 
@@ -982,13 +1013,14 @@
 	fs->state = idle;
 	fs->swim3 = (volatile struct swim3 *) swims->addrs[0].address;
 	fs->dma = (struct dbdma_regs *) swims->addrs[1].address;
-	fs->swim3_intr = swims->intrs[0];
-	fs->dma_intr = swims->intrs[1];
+	fs->swim3_intr = swims->intrs[0].line;
+	fs->dma_intr = swims->intrs[1].line;
 	fs->cur_cyl = -1;
 	fs->cur_sector = -1;
 	fs->secpercyl = 36;
 	fs->secpertrack = 18;
 	fs->total_secs = 2880;
+	fs->in_media_bay = is_3400;
 
 	fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
 	memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
@@ -1004,10 +1036,7 @@
 		return -EBUSY;
 	}
 
-	sw = fs->swim3;
-	out_8(&sw->mode, 0x95);
-	out_8(&sw->control_bic, 0xff);
-	out_8(&sw->reg5, 0x28);
+	init_timer(&fs->timeout);
 
 	do_floppy = NULL;
 
diff -u --recursive --new-file v2.1.100/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.1.100/linux/drivers/block/xd.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/xd.c	Thu May  7 23:53:35 1998
@@ -708,8 +708,7 @@
 	switch (address) {
 		case 0x00000:
 		case 0xC8000:	break;			/*initial: 0x320 */
-		case 0xCA000:	if (xd[3]<=0) xd_iobase = 0x324; 
-				break;
+		case 0xCA000:	xd_iobase = 0x324; 
 		case 0xD0000:				/*5150CX*/
 		case 0xD8000:	break;			/*5150CX & 5150XL*/
 		default:        printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
diff -u --recursive --new-file v2.1.100/linux/drivers/char/hfmodem/refclock.c linux/drivers/char/hfmodem/refclock.c
--- v2.1.100/linux/drivers/char/hfmodem/refclock.c	Tue Aug  5 09:48:55 1997
+++ linux/drivers/char/hfmodem/refclock.c	Thu May  7 23:50:19 1998
@@ -65,49 +65,13 @@
 /* --------------------------------------------------------------------- */
 
 #ifdef __i386__
-
 __initfunc(static void i386_capability(void))
 {
-        unsigned long flags;
-        unsigned long fl1;
-        union {
-                struct {
-                        unsigned int ebx, edx, ecx;
-                } r;
-                unsigned char s[13];
-        } id;
-        unsigned int eax;
-	unsigned int x86_capability;
-
-        save_flags(flags);
-        flags |= 0x200000;
-        restore_flags(flags);
-        save_flags(flags);
-        fl1 = flags;
-        flags &= ~0x200000;
-        restore_flags(flags);
-        save_flags(flags);
-        if (!(fl1 & 0x200000) || (flags & 0x200000)) {
-                printk(KERN_WARNING "%s: cpu does not support CPUID\n", hfmodem_drvname);
-                return;
-        }
-        __asm__ ("cpuid" : "=a" (eax), "=b" (id.r.ebx), "=c" (id.r.ecx), "=d" (id.r.edx) :
-                 "0" (0));
-        id.s[12] = 0;
-        if (eax < 1) {
-                printk(KERN_WARNING "%s: cpu (vendor string %s) does not support capability "
-                       "list\n", hfmodem_drvname, id.s);
-                return;
-        }
-        printk(KERN_INFO "%s: cpu: vendor string %s ", hfmodem_drvname, id.s);
-        __asm__ ("cpuid" : "=a" (eax), "=d" (x86_capability) : "0" (1) : "ebx", "ecx");
-        printk("fam %d mdl %d step %d cap 0x%x\n", (eax >> 8) & 15, (eax >> 4) & 15, eax & 15, 
-	       x86_capability);
-	if (x86_capability & 0x10)
+	if (boot_cpu_data.x86_capability & 0x10)
 		rdtsc_ok = 1;
 	else
 		printk(KERN_INFO "%s: cpu does not support the rdtsc instruction\n", hfmodem_drvname);
-}       
+}
 #endif /* __i386__ */   
 
 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.1.100/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c
--- v2.1.100/linux/drivers/char/sysrq.c	Thu Feb 12 20:56:06 1998
+++ linux/drivers/char/sysrq.c	Fri May  8 17:54:39 1998
@@ -19,6 +19,7 @@
 #include <linux/reboot.h>
 #include <linux/sysrq.h>
 #include <linux/kbd_kern.h>
+#include <linux/quotaops.h>
 #include <asm/ptrace.h>
 #include <asm/smp_lock.h>
 
@@ -188,7 +189,7 @@
 			printk("R/O\n");
 			return;
 		}
-		quota_off(dev, -1);
+		DQUOT_OFF(dev);
 		fsync_dev(dev);
 		flags = MS_RDONLY;
 		if (sb->s_op && sb->s_op->remount_fs) {
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- v2.1.100/linux/drivers/macintosh/Makefile	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/Makefile	Fri May  8 00:25:50 1998
@@ -19,10 +19,10 @@
 L_OBJS   := via-cuda.o adb.o nvram.o macio-adb.o via-pmu.o mediabay.o
 endif
 
-ifeq ($(CONFIG_SERIAL)$(CONFIG_PMAC),yy)
+ifeq ($(CONFIG_MAC_SERIAL),y)
   LX_OBJS += macserial.o
 else
-  ifeq ($(CONFIG_SERIAL)$(CONFIG_PMAC),my)
+  ifeq ($(CONFIG_MAC_SERIAL),m)
     MX_OBJS += macserial.o
   endif
 endif
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.1.100/linux/drivers/macintosh/adb.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/adb.c	Fri May  8 00:25:50 1998
@@ -17,8 +17,9 @@
 #include <asm/pmu.h>
 #include <asm/uaccess.h>
 #include <asm/hydra.h>
+#include <asm/init.h>
 
-enum adb_hw adb_hardware;
+enum adb_hw adb_hardware = ADB_NONE;
 int (*adb_send_request)(struct adb_request *req, int sync);
 int (*adb_autopoll)(int on);
 static void adb_scan_bus(void);
@@ -29,6 +30,8 @@
 	int handler_id;
 } adb_handler[16];
 
+__openfirmware
+
 static int adb_nodev(void)
 {
 	return -1;
@@ -137,7 +140,6 @@
 
 void adb_init(void)
 {
-	adb_hardware = ADB_NONE;
 	adb_send_request = (void *) adb_nodev;
 	adb_autopoll = (void *) adb_nodev;
 	if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/aty.c linux/drivers/macintosh/aty.c
--- v2.1.100/linux/drivers/macintosh/aty.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/aty.c	Fri May  8 00:25:50 1998
@@ -25,6 +25,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/pci-bridge.h>
+#include <asm/init.h>
 #include "pmac-cons.h"
 #include "aty.h"
 
@@ -150,6 +151,8 @@
 	&aty_vt_reg_init_19,
 	&aty_vt_reg_init_20
 };
+
+__openfirmware
 
 static inline int
 aty_vram_reqd(int vmode, int cmode)
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/chips.c linux/drivers/macintosh/chips.c
--- v2.1.100/linux/drivers/macintosh/chips.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/chips.c	Fri May  8 00:25:50 1998
@@ -22,6 +22,7 @@
 #include <asm/cuda.h>
 #include <asm/pmu.h>
 #include <asm/pci-bridge.h>
+#include <asm/init.h>
 #include "pmac-cons.h"
 #include "chips.h"
 
@@ -31,6 +32,8 @@
 static unsigned char *io_space;
 static unsigned long chips_base_phys;
 static unsigned long chips_io_phys;
+
+__openfirmware
 
 void
 map_chips_display(struct device_node *dp)
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/control.c linux/drivers/macintosh/control.c
--- v2.1.100/linux/drivers/macintosh/control.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/control.c	Fri May  8 00:25:50 1998
@@ -19,6 +19,7 @@
 #include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/pgtable.h>
+#include <asm/init.h>
 #include <linux/selection.h>
 #include "pmac-cons.h"
 #include "control.h"
@@ -265,6 +266,8 @@
 	&control_reg_init_19,
 	&control_reg_init_20
 };
+
+__openfirmware
 
 /*
  * Get the monitor sense value.
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/imstt.c linux/drivers/macintosh/imstt.c
--- v2.1.100/linux/drivers/macintosh/imstt.c	Sat May  2 14:19:53 1998
+++ linux/drivers/macintosh/imstt.c	Fri May  8 00:25:50 1998
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/pci-bridge.h>
+#include <asm/init.h>
 #include <linux/selection.h>
 #include <linux/vt_kern.h>
 #include "pmac-cons.h"
@@ -480,6 +481,8 @@
 static int read_imstt_sense(void);
 static int imstt_vram_reqd(int vmode, int cmode);
 
+
+__openfirmware
 
 #if 0
 static int get_tvp_ireg(int iaddr)
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.1.100/linux/drivers/macintosh/mac_keyb.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/mac_keyb.c	Fri May  8 00:25:50 1998
@@ -20,6 +20,7 @@
 #include <asm/bitops.h>
 #include <asm/adb.h>
 #include <asm/cuda.h>
+#include <asm/init.h>
 
 #include <linux/kbd_kern.h>
 #include <linux/kbd_ll.h>
@@ -28,7 +29,7 @@
 #define KEYB_LEDREG	2	/* register # for leds on ADB keyboard */
 #define MOUSE_DATAREG	0	/* reg# for movement/button codes from mouse */
 
-static u_short macplain_map[NR_KEYS] = __initdata {
+static u_short macplain_map[NR_KEYS] __initdata = {
 	0xfb61,	0xfb73,	0xfb64,	0xfb66,	0xfb68,	0xfb67,	0xfb7a,	0xfb78,
 	0xfb63,	0xfb76,	0xf200,	0xfb62,	0xfb71,	0xfb77,	0xfb65,	0xfb72,
 	0xfb79,	0xfb74,	0xf031,	0xf032,	0xf033,	0xf034,	0xf036,	0xf035,
@@ -194,6 +195,8 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* scroll lock */
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
+
+__openfirmware
 
 int mackbd_setkeycode(unsigned int scancode, unsigned int keycode)
 {
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/macio-adb.c linux/drivers/macintosh/macio-adb.c
--- v2.1.100/linux/drivers/macintosh/macio-adb.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/macio-adb.c	Fri May  8 00:25:50 1998
@@ -14,6 +14,7 @@
 #include <asm/hydra.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/init.h>
 
 struct preg {
 	unsigned char r;
@@ -63,6 +64,8 @@
 static int macio_adb_autopoll(int on);
 static void macio_adb_poll(void);
 static void completed(void);
+
+__openfirmware
 
 void macio_adb_init(void)
 {
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.1.100/linux/drivers/macintosh/macserial.c	Thu May  7 22:51:50 1998
+++ linux/drivers/macintosh/macserial.c	Fri May  8 00:25:50 1998
@@ -36,6 +36,7 @@
 #ifdef CONFIG_KGDB
 #include <asm/kgdb.h>
 #endif
+#include <asm/init.h>
 
 #include "macserial.h"
 
@@ -79,9 +80,9 @@
 #endif
 #define ZS_CLOCK         3686400 	/* Z8530 RTxC input clock rate */
 
-DECLARE_TASK_QUEUE(tq_serial);
+static DECLARE_TASK_QUEUE(tq_serial);
 
-struct tty_driver serial_driver, callout_driver;
+static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
 
 /* serial subtype definitions */
@@ -127,6 +128,8 @@
 static unsigned char tmp_buf[4096]; /* This is cheating */
 static struct semaphore tmp_buf_sem = MUTEX;
 
+__openfirmware
+
 static inline int serial_paranoia_check(struct mac_serial *info,
 					dev_t device, const char *routine)
 {
@@ -281,7 +284,7 @@
 {
 	info->event |= 1 << event;
 	queue_task(&info->tqueue, &tq_serial);
-	mark_bh(SERIAL_BH);
+	mark_bh(MACSERIAL_BH);
 }
 
 static _INLINE_ void receive_chars(struct mac_serial *info,
@@ -410,7 +413,7 @@
 /*
  * This is the serial driver's generic interrupt routine
  */
-void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct mac_serial *info = (struct mac_serial *) dev_id;
 	unsigned char zs_intreg;
@@ -1311,7 +1314,7 @@
 /*
  * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
-void rs_hangup(struct tty_struct *tty)
+static void rs_hangup(struct tty_struct *tty)
 {
 	struct mac_serial * info = (struct mac_serial *)tty->driver_data;
 
@@ -1464,7 +1467,7 @@
  * the IRQ chain.   It also performs the serial-specific
  * initialization for the tty structure.
  */
-int rs_open(struct tty_struct *tty, struct file * filp)
+static int rs_open(struct tty_struct *tty, struct file * filp)
 {
 	struct mac_serial	*info;
 	int 			retval, line;
@@ -1599,14 +1602,14 @@
 }
 
 /* rs_init inits the driver */
-int rs_init(void)
+int macserial_init(void)
 {
 	int channel, i;
 	unsigned long flags;
 	struct mac_serial *info;
 
 	/* Setup base handler, and timer table. */
-	init_bh(SERIAL_BH, do_serial_bh);
+	init_bh(MACSERIAL_BH, do_serial_bh);
 	timer_table[RS_TIMER].fn = rs_timer;
 	timer_table[RS_TIMER].expires = 0;
 
@@ -1722,6 +1725,7 @@
 	return 0;
 }
 
+#if 0
 /*
  * register_serial and unregister_serial allows for serial ports to be
  * configured at run-time, to support PCMCIA modems.
@@ -1736,6 +1740,7 @@
 {
 	return;
 }
+#endif
 
 /*
  * ------------------------------------------------------------
@@ -1864,10 +1869,9 @@
 /*
  *	Register console.
  */
-__initfunc (long serial_console_init(long kmem_start, long kmem_end))
+__initfunc (void serial_console_init(void))
 {
 	register_console(&sercons);
-	return kmem_start;
 }
 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
 #ifdef CONFIG_KGDB
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c
--- v2.1.100/linux/drivers/macintosh/mediabay.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/mediabay.c	Fri May  8 00:25:50 1998
@@ -21,6 +21,7 @@
 #include <asm/io.h>
 #include <asm/ohare.h>
 #include <asm/mediabay.h>
+#include <asm/init.h>
 
 struct media_bay_hw {
 	unsigned char	b0;
@@ -84,6 +85,8 @@
  * an infinite loop calling the media bay interrupt handler.
  * Therefore we do it all by polling the media bay once each tick.
  */
+
+__pmac /* I don't know of any chrp with a mediabay -- Cort */
 
 void
 media_bay_init(void)
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c
--- v2.1.100/linux/drivers/macintosh/nvram.c	Mon Jan 12 15:18:14 1998
+++ linux/drivers/macintosh/nvram.c	Fri May  8 00:25:50 1998
@@ -9,8 +9,11 @@
 #include <linux/nvram.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
+#include <asm/init.h>
 
 #define NVRAM_SIZE	8192
+
+__openfirmware
 
 static long long nvram_llseek(struct file *file, loff_t offset, int origin)
 {
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/platinum.c linux/drivers/macintosh/platinum.c
--- v2.1.100/linux/drivers/macintosh/platinum.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/platinum.c	Fri May  8 00:25:50 1998
@@ -17,6 +17,7 @@
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/init.h>
 #include <linux/selection.h>
 #include "pmac-cons.h"
 #include "platinum.h"
@@ -351,6 +352,8 @@
 	&platinum_reg_init_19,
 	&platinum_reg_init_20
 };
+
+__openfirmware
 
 /*
  * Get the monitor sense value.
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/pmac-cons.c linux/drivers/macintosh/pmac-cons.c
--- v2.1.100/linux/drivers/macintosh/pmac-cons.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/pmac-cons.c	Fri May  8 00:25:50 1998
@@ -6,6 +6,7 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/malloc.h>
 #include <linux/tty.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
@@ -23,6 +24,7 @@
 #include <asm/cuda.h>
 #define INCLUDE_LINUX_LOGO_DATA
 #include <asm/linux_logo.h>
+#include <asm/init.h>
 #include <linux/selection.h>
 #include <linux/console_struct.h>
 #include <linux/vt_kern.h>
@@ -193,6 +195,8 @@
 	  aty_setmode, aty_set_palette, aty_set_blanking },
  	{ "ATY,mach64_3DU", map_aty_display, aty_init,
 	  aty_setmode, aty_set_palette, aty_set_blanking },
+ 	{ "ATY,XCLAIM3DPro", map_aty_display, aty_init,
+	  aty_setmode, aty_set_palette, aty_set_blanking },
 #endif
 #ifdef CONFIG_IMSTT_VIDEO
 	{ "IMS,tt128mb", map_imstt_display_ibm, imstt_init, 
@@ -225,6 +229,8 @@
 #define cmapsz	(16*256)
 extern unsigned char vga_font[cmapsz];
 
+__openfirmware
+
 static inline unsigned pixel32(int currcons, int cidx)
 {
 	cidx *= 3;
@@ -637,20 +643,20 @@
 		color_mode = ints[2];
 }
 
-unsigned long
-con_type_init(unsigned long mem_start, const char **type_p)
+void
+con_type_init(const char **type_p)
 {
+	unsigned long nb = MAX_TEXT_COLS * MAX_TEXT_ROWS * 2;
+
 	if (current_display == NULL)
-		return mem_start;
+		return;
 	current_display->init_interface();
 	can_do_color = 1;
 	video_type = VIDEO_TYPE_PMAC;
 	*type_p = display_info.name;
-	video_mem_base = mem_start;
-	mem_start += MAX_TEXT_COLS * MAX_TEXT_ROWS * 2;
-	video_mem_term = mem_start;
+	video_mem_base = (unsigned long) kmalloc(nb, GFP_ATOMIC);
+	video_mem_term = video_mem_base + nb;
 	memset((char *) video_mem_base, 0, video_screen_size);
-	return mem_start;
 }
 
 int
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/valkyrie.c linux/drivers/macintosh/valkyrie.c
--- v2.1.100/linux/drivers/macintosh/valkyrie.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/valkyrie.c	Fri May  8 00:25:50 1998
@@ -19,6 +19,7 @@
 #include <asm/adb.h>
 #include <asm/cuda.h>
 #include <asm/pgtable.h>
+#include <asm/init.h>
 #include <linux/selection.h>
 #include "pmac-cons.h"
 #include "valkyrie.h"
@@ -141,6 +142,8 @@
 	&valkyrie_reg_init_15,
 	NULL, NULL, NULL, NULL, NULL
 };
+
+__openfirmware
 
 /*
  * Get the monitor sense value.
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/via-cuda.c linux/drivers/macintosh/via-cuda.c
--- v2.1.100/linux/drivers/macintosh/via-cuda.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/via-cuda.c	Fri May  8 00:25:50 1998
@@ -20,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
+#include <asm/init.h>
 
 static volatile unsigned char *via;
 
@@ -72,6 +73,7 @@
 static unsigned char *reply_ptr;
 static int reading_reply;
 static int data_index;
+static struct device_node *vias;
 
 static int init_via(void);
 static void cuda_start(void);
@@ -80,11 +82,11 @@
 static int cuda_adb_send_request(struct adb_request *req, int sync);
 static int cuda_adb_autopoll(int on);
 
+__openfirmware
+
 void
-via_cuda_init()
+find_via_cuda()
 {
-    struct device_node *vias;
-
     vias = find_devices("via-cuda");
     if (vias == 0)
 	return;
@@ -111,12 +113,21 @@
     }
     via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000);
 
+    cuda_state = idle;
+
     if (!init_via()) {
 	printk(KERN_ERR "init_via failed\n");
-	return;
+	via = NULL;
     }
 
-    cuda_state = idle;
+    adb_hardware = ADB_VIACUDA;
+}
+
+void
+via_cuda_init(void)
+{
+    if (via == NULL)
+	return;
 
     if (request_irq(vias->intrs[0].line, via_interrupt, 0, "VIA", (void *)0)) {
 	printk(KERN_ERR "VIA: can't get irq %d\n", vias->intrs[0].line);
@@ -128,7 +139,6 @@
     via[IER] = IER_SET|SR_INT; eieio();	/* enable interrupt from SR */
 
     /* Set function pointers */
-    adb_hardware = ADB_VIACUDA;
     adb_send_request = cuda_adb_send_request;
     adb_autopoll = cuda_adb_autopoll;
 }
diff -u --recursive --new-file v2.1.100/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.1.100/linux/drivers/macintosh/via-pmu.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/macintosh/via-pmu.c	Fri May  8 00:25:50 1998
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
+#include <asm/init.h>
 
 static volatile unsigned char *via;
 
@@ -79,6 +80,7 @@
 static int pmu_adb_flags;
 static int adb_dev_map = 0;
 static struct adb_request bright_req_1, bright_req_2;
+static struct device_node *vias;
 
 static int init_pmu(void);
 static int pmu_queue_request(struct adb_request *req);
@@ -138,11 +140,11 @@
 /*f8*/	{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
 };
 
+__openfirmware
+
 void
-via_pmu_init()
+find_via_pmu()
 {
-	struct device_node *vias;
-
 	vias = find_devices("via-pmu");
 	if (vias == 0)
 		return;
@@ -174,8 +176,20 @@
 	pmu_state = idle;
 
 	if (!init_pmu())
+		via = NULL;
+
+	adb_hardware = ADB_VIAPMU;
+}
+
+void
+via_pmu_init(void)
+{
+	if (vias == NULL)
 		return;
 
+	bright_req_1.complete = 1;
+	bright_req_2.complete = 1;
+
 	if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU",
 			(void *)0)) {
 		printk(KERN_ERR "VIA-PMU: can't get irq %d\n",
@@ -187,12 +201,8 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 
 	/* Set function pointers */
-	adb_hardware = ADB_VIAPMU;
 	adb_send_request = pmu_adb_send_request;
 	adb_autopoll = pmu_adb_autopoll;
-
-	bright_req_1.complete = 1;
-	bright_req_2.complete = 1;
 }
 
 static int
diff -u --recursive --new-file v2.1.100/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.1.100/linux/drivers/net/8390.c	Thu Feb 12 20:56:07 1998
+++ linux/drivers/net/8390.c	Thu May  7 23:50:19 1998
@@ -33,6 +33,8 @@
   Alexey Kuznetsov	: use the 8390's six bit hash multicast filter.
   Paul Gortmaker	: tweak ANK's above multicast changes a bit.
   Paul Gortmaker	: update packet statistics for v2.1.x
+  Alan Cox		: support arbitary stupid port mappings on the
+  			  68K Macintosh. Support >16bit I/O spaces
 
 
   Sources:
@@ -41,8 +43,9 @@
   */
 
 static const char *version =
-    "8390.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -55,7 +58,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/in.h>
@@ -115,50 +118,53 @@
    */
 int ei_open(struct device *dev)
 {
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
 
-    /* This can't happen unless somebody forgot to call ethdev_init(). */
-    if (ei_local == NULL) {
-	printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
-	return -ENXIO;
-    }
-    
-    NS8390_init(dev, 1);
-    dev->start = 1;
-    ei_local->irqlock = 0;
-    return 0;
+	/* This can't happen unless somebody forgot to call ethdev_init(). */
+	if (ei_local == NULL) 
+	{
+		printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
+		return -ENXIO;
+	}
+    
+	NS8390_init(dev, 1);
+	dev->start = 1;
+	ei_local->irqlock = 0;
+	return 0;
 }
 
 /* Opposite of above. Only used when "ifconfig <devname> down" is done. */
 int ei_close(struct device *dev)
 {
-    NS8390_init(dev, 0);
-    dev->start = 0;
-    return 0;
+	NS8390_init(dev, 0);
+	dev->start = 0;
+	return 0;
 }
 
 static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
 {
-    int e8390_base = dev->base_addr;
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
-    int length, send_length, output_page;
-
-/*
- *  We normally shouldn't be called if dev->tbusy is set, but the
- *  existing code does anyway. If it has been too long since the
- *  last Tx, we assume the board has died and kick it.
- */
+	int e8390_base = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int length, send_length, output_page;
+
+	/*
+	 *  We normally shouldn't be called if dev->tbusy is set, but the
+	 *  existing code does anyway. If it has been too long since the
+	 *  last Tx, we assume the board has died and kick it.
+	 */
  
-    if (dev->tbusy) {	/* Do timeouts, just like the 8003 driver. */
+	if (dev->tbusy) 
+	{	/* Do timeouts, just like the 8003 driver. */
 		int txsr = inb(e8390_base+EN0_TSR), isr;
 		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < TX_TIMEOUT ||	(tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) {
+		if (tickssofar < TX_TIMEOUT ||	(tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) 
 			return 1;
-		}
+
 		ei_local->stat.tx_errors++;
 		isr = inb(e8390_base+EN0_ISR);
-		if (dev->start == 0) {
-			printk("%s: xmit on stopped card\n", dev->name);
+		if (dev->start == 0) 
+		{
+			printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
 			return 1;
 		}
 
@@ -169,138 +175,153 @@
 		 */
 
 		printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
-		   dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
-		   (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
+			dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
+			(isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
 
-		if (!isr && !ei_local->stat.tx_packets) {
-		   /* The 8390 probably hasn't gotten on the cable yet. */
-		   ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
+		if (!isr && !ei_local->stat.tx_packets) 
+		{
+			/* The 8390 probably hasn't gotten on the cable yet. */
+			ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
 		}
 
 		/* Try to restart the card.  Perhaps the user has fixed something. */
 		ei_reset_8390(dev);
 		NS8390_init(dev, 1);
 		dev->trans_start = jiffies;
-    }
+	}
     
-    length = skb->len;
+	length = skb->len;
 
-    /* Mask interrupts from the ethercard. */
-    outb_p(0x00, e8390_base + EN0_IMR);
-    disable_irq(dev->irq);
-    synchronize_irq();
-    if (dev->interrupt) {
-	printk("%s: Tx request while isr active.\n",dev->name);
-	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-	enable_irq(dev->irq);
-	ei_local->stat.tx_errors++;
-	dev_kfree_skb(skb);
-	return 0;
-    }
-    ei_local->irqlock = 1;
+	/* Mask interrupts from the ethercard. */
+	outb_p(0x00, e8390_base + EN0_IMR);
+	disable_irq(dev->irq);
+	synchronize_irq();
+	if (dev->interrupt) 
+	{
+		printk(KERN_WARNING "%s: Tx request while isr active.\n",dev->name);
+		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+		enable_irq(dev->irq);
+		ei_local->stat.tx_errors++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+	ei_local->irqlock = 1;
 
-    send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
+	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
     
 #ifdef EI_PINGPONG
 
-    /*
-     * We have two Tx slots available for use. Find the first free
-     * slot, and then perform some sanity checks. With two Tx bufs,
-     * you get very close to transmitting back-to-back packets. With
-     * only one Tx buf, the transmitter sits idle while you reload the
-     * card, leaving a substantial gap between each transmitted packet.
-     */
-
-    if (ei_local->tx1 == 0) {
-	output_page = ei_local->tx_start_page;
-	ei_local->tx1 = send_length;
-	if (ei_debug  &&  ei_local->tx2 > 0)
-		printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
-			dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
-    } else if (ei_local->tx2 == 0) {
-	output_page = ei_local->tx_start_page + TX_1X_PAGES;
-	ei_local->tx2 = send_length;
-	if (ei_debug  &&  ei_local->tx1 > 0)
-		printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
-			dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
-    } else {	/* We should never get here. */
-	if (ei_debug)
-		printk("%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n",
-			dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
-	ei_local->irqlock = 0;
-	dev->tbusy = 1;
-	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-	enable_irq(dev->irq);
-	ei_local->stat.tx_errors++;
-	return 1;
-    }
-
-    /*
-     * Okay, now upload the packet and trigger a send if the transmitter
-     * isn't already sending. If it is busy, the interrupt handler will
-     * trigger the send later, upon receiving a Tx done interrupt.
-     */
+	/*
+	 * We have two Tx slots available for use. Find the first free
+	 * slot, and then perform some sanity checks. With two Tx bufs,
+	 * you get very close to transmitting back-to-back packets. With
+	 * only one Tx buf, the transmitter sits idle while you reload the
+	 * card, leaving a substantial gap between each transmitted packet.
+	 */
 
-    ei_block_output(dev, length, skb->data, output_page);
-    if (! ei_local->txing) {
-	ei_local->txing = 1;
-	NS8390_trigger_send(dev, send_length, output_page);
-	dev->trans_start = jiffies;
-	if (output_page == ei_local->tx_start_page) {
-		ei_local->tx1 = -1;
-		ei_local->lasttx = -1;
-	} else {
-		ei_local->tx2 = -1;
-		ei_local->lasttx = -2;
+	if (ei_local->tx1 == 0) 
+	{
+		output_page = ei_local->tx_start_page;
+		ei_local->tx1 = send_length;
+		if (ei_debug  &&  ei_local->tx2 > 0)
+			printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
+				dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
+	}
+	else if (ei_local->tx2 == 0) 
+	{
+		output_page = ei_local->tx_start_page + TX_1X_PAGES;
+		ei_local->tx2 = send_length;
+		if (ei_debug  &&  ei_local->tx1 > 0)
+			printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
+				dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
+	}
+	else
+	{	/* We should never get here. */
+		if (ei_debug)
+			printk(KERN_DEBUG "%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n",
+				dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+		ei_local->irqlock = 0;
+		dev->tbusy = 1;
+		outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+		enable_irq(dev->irq);
+		ei_local->stat.tx_errors++;
+		return 1;
+	}
+
+	/*
+	 * Okay, now upload the packet and trigger a send if the transmitter
+	 * isn't already sending. If it is busy, the interrupt handler will
+	 * trigger the send later, upon receiving a Tx done interrupt.
+	 */
+
+	ei_block_output(dev, length, skb->data, output_page);
+	if (! ei_local->txing) 
+	{
+		ei_local->txing = 1;
+		NS8390_trigger_send(dev, send_length, output_page);
+		dev->trans_start = jiffies;
+		if (output_page == ei_local->tx_start_page) 
+		{
+			ei_local->tx1 = -1;
+			ei_local->lasttx = -1;
+		}
+		else 
+		{
+			ei_local->tx2 = -1;
+			ei_local->lasttx = -2;
+		}
 	}
-    } else
-	ei_local->txqueue++;
+	else ei_local->txqueue++;
 
-    dev->tbusy = (ei_local->tx1  &&  ei_local->tx2);
+	dev->tbusy = (ei_local->tx1  &&  ei_local->tx2);
 
 #else	/* EI_PINGPONG */
 
-    /*
-     * Only one Tx buffer in use. You need two Tx bufs to come close to
-     * back-to-back transmits. Expect a 20 -> 25% performance hit on
-     * reasonable hardware if you only use one Tx buffer.
-     */
-
-    ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
-    ei_local->txing = 1;
-    NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
-    dev->trans_start = jiffies;
-    dev->tbusy = 1;
+	/*
+	 * Only one Tx buffer in use. You need two Tx bufs to come close to
+	 * back-to-back transmits. Expect a 20 -> 25% performance hit on
+	 * reasonable hardware if you only use one Tx buffer.
+	 */
+
+	ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
+	ei_local->txing = 1;
+	NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
+	dev->trans_start = jiffies;
+	dev->tbusy = 1;
 
 #endif	/* EI_PINGPONG */
 
-    /* Turn 8390 interrupts back on. */
-    ei_local->irqlock = 0;
-    outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-    enable_irq(dev->irq);
+	/* Turn 8390 interrupts back on. */
+	ei_local->irqlock = 0;
+	outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+	enable_irq(dev->irq);
 
-    dev_kfree_skb (skb);
-    ei_local->stat.tx_bytes += send_length;
+	dev_kfree_skb (skb);
+	ei_local->stat.tx_bytes += send_length;
     
-    return 0;
+	return 0;
 }
 
 /* The typical workload of the driver:
    Handle the ether interface interrupts. */
+
 void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct device *dev = dev_id;
-    int e8390_base;
-    int interrupts, nr_serviced = 0;
-    struct ei_device *ei_local;
+	int e8390_base;
+	int interrupts, nr_serviced = 0;
+	struct ei_device *ei_local;
     
-    if (dev == NULL) {
+	if (dev == NULL) 
+	{
 		printk ("net_interrupt(): irq %d for unknown device.\n", irq);
 		return;
-    }
-    e8390_base = dev->base_addr;
-    ei_local = (struct ei_device *) dev->priv;
-    if (dev->interrupt || ei_local->irqlock) {
+	}
+    
+	e8390_base = dev->base_addr;
+	ei_local = (struct ei_device *) dev->priv;
+	if (dev->interrupt || ei_local->irqlock) 
+	{
 #if 1 /* This might just be an interrupt for a PCI device sharing this line */
 		/* The "irqlock" check is only for testing. */
 		printk(ei_local->irqlock
@@ -310,39 +331,42 @@
 			   inb_p(e8390_base + EN0_IMR));
 #endif
 		return;
-    }
+	}
     
-    dev->interrupt = 1;
-    sti();
+	dev->interrupt = 1;
+	sti();
     
-    /* Change to page 0 and read the intr status reg. */
-    outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
-    if (ei_debug > 3)
+	/* Change to page 0 and read the intr status reg. */
+	outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+	if (ei_debug > 3)
 		printk("%s: interrupt(isr=%#2.2x).\n", dev->name,
 			   inb_p(e8390_base + EN0_ISR));
     
-    /* !!Assumption!! -- we stay in page 0.	 Don't break this. */
-    while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
-		   && ++nr_serviced < MAX_SERVICE) {
-		if (dev->start == 0) {
-			printk("%s: interrupt from stopped card\n", dev->name);
+	/* !!Assumption!! -- we stay in page 0.	 Don't break this. */
+	while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
+		   && ++nr_serviced < MAX_SERVICE) 
+	{
+		if (dev->start == 0) 
+		{
+			printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
 			interrupts = 0;
 			break;
 		}
-		if (interrupts & ENISR_OVER) {
+		if (interrupts & ENISR_OVER) 
 			ei_rx_overrun(dev);
-		} else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
+		else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) 
+		{
 			/* Got a good (?) packet. */
 			ei_receive(dev);
 		}
 		/* Push the next to-transmit packet through. */
-		if (interrupts & ENISR_TX) {
+		if (interrupts & ENISR_TX)
 			ei_tx_intr(dev);
-		} else if (interrupts & ENISR_TX_ERR) {
+		else if (interrupts & ENISR_TX_ERR)
 			ei_tx_err(dev);
-		}
 
-		if (interrupts & ENISR_COUNTERS) {
+		if (interrupts & ENISR_COUNTERS) 
+		{
 			ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
 			ei_local->stat.rx_crc_errors   += inb_p(e8390_base + EN0_COUNTER1);
 			ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
@@ -350,16 +374,19 @@
 		}
 		
 		/* Ignore any RDC interrupts that make it back to here. */
-		if (interrupts & ENISR_RDC) {
+		if (interrupts & ENISR_RDC) 
+		{
 			outb_p(ENISR_RDC, e8390_base + EN0_ISR);
 		}
 
 		outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
-    }
+	}
     
-    if (interrupts && ei_debug) {
+	if (interrupts && ei_debug) 
+	{
 		outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
-		if (nr_serviced >= MAX_SERVICE) {
+		if (nr_serviced >= MAX_SERVICE) 
+		{
 			printk("%s: Too much work at interrupt, status %#2.2x\n",
 				   dev->name, interrupts);
 			outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
@@ -367,9 +394,9 @@
 			printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
 			outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
 		}
-    }
-    dev->interrupt = 0;
-    return;
+	}
+	dev->interrupt = 0;
+	return;
 }
 
 /*
@@ -383,128 +410,143 @@
 
 static void ei_tx_err(struct device *dev)
 {
-    int e8390_base = dev->base_addr;
-    unsigned char txsr = inb_p(e8390_base+EN0_TSR);
-    unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int e8390_base = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	unsigned char txsr = inb_p(e8390_base+EN0_TSR);
+	unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
 
 #ifdef VERBOSE_ERROR_DUMP
-    printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
-    if (txsr & ENTSR_ABT)
+	printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
+	if (txsr & ENTSR_ABT)
 		printk("excess-collisions ");
-    if (txsr & ENTSR_ND)
+	if (txsr & ENTSR_ND)
 		printk("non-deferral ");
-    if (txsr & ENTSR_CRS)
+	if (txsr & ENTSR_CRS)
 		printk("lost-carrier ");
-    if (txsr & ENTSR_FU)
+	if (txsr & ENTSR_FU)
 		printk("FIFO-underrun ");
-    if (txsr & ENTSR_CDH)
+	if (txsr & ENTSR_CDH)
 		printk("lost-heartbeat ");
-    printk("\n");
+	printk("\n");
 #endif
 
-    outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
+	outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
 
-    if (tx_was_aborted)
+	if (tx_was_aborted)
 		ei_tx_intr(dev);
-    else {
+	else 
+	{
 		ei_local->stat.tx_errors++;
 		if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
 		if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
 		if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++;
-    }
+	}
 }
 
 /* We have finished a transmit: check for errors and then trigger the next
    packet to be sent. */
+
 static void ei_tx_intr(struct device *dev)
 {
-    int e8390_base = dev->base_addr;
-    int status = inb(e8390_base + EN0_TSR);
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int e8390_base = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int status = inb(e8390_base + EN0_TSR);
     
-    outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
+	outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
 
 #ifdef EI_PINGPONG
 
-    /*
-     * There are two Tx buffers, see which one finished, and trigger
-     * the send of another one if it exists.
-     */
-    ei_local->txqueue--;
-    if (ei_local->tx1 < 0) {
-	if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
-		printk("%s: bogus last_tx_buffer %d, tx1=%d.\n",
-			   ei_local->name, ei_local->lasttx, ei_local->tx1);
-	ei_local->tx1 = 0;
-	dev->tbusy = 0;
-	if (ei_local->tx2 > 0) {
-		ei_local->txing = 1;
-		NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
-		dev->trans_start = jiffies;
-		ei_local->tx2 = -1,
-		ei_local->lasttx = 2;
-	} else
-		ei_local->lasttx = 20, ei_local->txing = 0;
-    } else if (ei_local->tx2 < 0) {
-	if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
-		printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
-			   ei_local->name, ei_local->lasttx, ei_local->tx2);
-	ei_local->tx2 = 0;
-	dev->tbusy = 0;
-	if (ei_local->tx1 > 0) {
-		ei_local->txing = 1;
-		NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
-		dev->trans_start = jiffies;
-		ei_local->tx1 = -1;
-		ei_local->lasttx = 1;
-	} else
-		ei_local->lasttx = 10, ei_local->txing = 0;
-    } else
-	printk("%s: unexpected TX-done interrupt, lasttx=%d.\n",
-		   dev->name, ei_local->lasttx);
+	/*
+	 * There are two Tx buffers, see which one finished, and trigger
+	 * the send of another one if it exists.
+	 */
+	ei_local->txqueue--;
+
+	if (ei_local->tx1 < 0) 
+	{
+		if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+			printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n",
+				ei_local->name, ei_local->lasttx, ei_local->tx1);
+		ei_local->tx1 = 0;
+		dev->tbusy = 0;
+		if (ei_local->tx2 > 0) 
+		{
+			ei_local->txing = 1;
+			NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+			dev->trans_start = jiffies;
+			ei_local->tx2 = -1,
+			ei_local->lasttx = 2;
+		}
+		else ei_local->lasttx = 20, ei_local->txing = 0;	
+	}
+	else if (ei_local->tx2 < 0) 
+	{
+		if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
+			printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
+				ei_local->name, ei_local->lasttx, ei_local->tx2);
+		ei_local->tx2 = 0;
+		dev->tbusy = 0;
+		if (ei_local->tx1 > 0) 
+		{
+			ei_local->txing = 1;
+			NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+			dev->trans_start = jiffies;
+			ei_local->tx1 = -1;
+			ei_local->lasttx = 1;
+		}
+		else
+			ei_local->lasttx = 10, ei_local->txing = 0;
+	}
+	else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n",
+			dev->name, ei_local->lasttx);
 
 #else	/* EI_PINGPONG */
-    /*
-     *  Single Tx buffer: mark it free so another packet can be loaded.
-     */
-    ei_local->txing = 0;
-    dev->tbusy = 0;
+	/*
+	 *  Single Tx buffer: mark it free so another packet can be loaded.
+	 */
+	ei_local->txing = 0;
+	dev->tbusy = 0;
 #endif
 
-    /* Minimize Tx latency: update the statistics after we restart TXing. */
-    if (status & ENTSR_COL)
-	ei_local->stat.collisions++;
-    if (status & ENTSR_PTX)
-	ei_local->stat.tx_packets++;
-    else {
-	ei_local->stat.tx_errors++;
-	if (status & ENTSR_ABT) {
-		ei_local->stat.tx_aborted_errors++;
-		ei_local->stat.collisions += 16;
-	}
-	if (status & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
-	if (status & ENTSR_FU)  ei_local->stat.tx_fifo_errors++;
-	if (status & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
-	if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++;
-    }
-
-    mark_bh (NET_BH);
+	/* Minimize Tx latency: update the statistics after we restart TXing. */
+	if (status & ENTSR_COL)
+		ei_local->stat.collisions++;
+	if (status & ENTSR_PTX)
+		ei_local->stat.tx_packets++;
+	else 
+	{
+		ei_local->stat.tx_errors++;
+		if (status & ENTSR_ABT) 
+		{
+			ei_local->stat.tx_aborted_errors++;
+			ei_local->stat.collisions += 16;
+		}
+		if (status & ENTSR_CRS) 
+			ei_local->stat.tx_carrier_errors++;
+		if (status & ENTSR_FU) 
+			ei_local->stat.tx_fifo_errors++;
+		if (status & ENTSR_CDH)
+			ei_local->stat.tx_heartbeat_errors++;
+		if (status & ENTSR_OWC)
+			ei_local->stat.tx_window_errors++;
+	}
+	mark_bh (NET_BH);
 }
 
 /* We have a good packet(s), get it/them out of the buffers. */
 
 static void ei_receive(struct device *dev)
 {
-    int e8390_base = dev->base_addr;
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
-    unsigned char rxing_page, this_frame, next_frame;
-    unsigned short current_offset;
-    int rx_pkt_count = 0;
-    struct e8390_pkt_hdr rx_frame;
-    int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
+	int e8390_base = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	unsigned char rxing_page, this_frame, next_frame;
+	unsigned short current_offset;
+	int rx_pkt_count = 0;
+	struct e8390_pkt_hdr rx_frame;
+	int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
     
-    while (++rx_pkt_count < 10) {
+	while (++rx_pkt_count < 10) 
+	{
 		int pkt_len, pkt_stat;
 		
 		/* Get the rx page (incoming packet pointer). */
@@ -520,7 +562,7 @@
 		/* Someday we'll omit the previous, iff we never get this message.
 		   (There is at least one clone claimed to have a problem.)  */
 		if (ei_debug > 0  &&  this_frame != ei_local->current_page)
-			printk("%s: mismatched read page pointers %2x vs %2x.\n",
+			printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n",
 				   dev->name, this_frame, ei_local->current_page);
 		
 		if (this_frame == rxing_page)	/* Read all the frames? */
@@ -547,24 +589,30 @@
 			continue;
 		}
 
-		if (pkt_len < 60  ||  pkt_len > 1518) {
+		if (pkt_len < 60  ||  pkt_len > 1518) 
+		{
 			if (ei_debug)
-				printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
+				printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
 					   dev->name, rx_frame.count, rx_frame.status,
 					   rx_frame.next);
 			ei_local->stat.rx_errors++;
 			ei_local->stat.rx_length_errors++;
-		} else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
+		}
+		 else if ((pkt_stat & 0x0F) == ENRSR_RXOK) 
+		{
 			struct sk_buff *skb;
 			
 			skb = dev_alloc_skb(pkt_len+2);
-			if (skb == NULL) {
+			if (skb == NULL) 
+			{
 				if (ei_debug > 1)
-					printk("%s: Couldn't allocate a sk_buff of size %d.\n",
+					printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n",
 						   dev->name, pkt_len);
 				ei_local->stat.rx_dropped++;
 				break;
-			} else {
+			}
+			else
+			{
 				skb_reserve(skb,2);	/* IP headers on 16 byte boundaries */
 				skb->dev = dev;
 				skb_put(skb, pkt_len);	/* Make room */
@@ -576,9 +624,11 @@
 				if (pkt_stat & ENRSR_PHY)
 					ei_local->stat.multicast++;
 			}
-		} else {
+		} 
+		else 
+		{
 			if (ei_debug)
-				printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+				printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
 					   dev->name, rx_frame.status, rx_frame.next,
 					   rx_frame.count);
 			ei_local->stat.rx_errors++;
@@ -596,12 +646,12 @@
 		}
 		ei_local->current_page = next_frame;
 		outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
-    }
+	}
 
-    /* We used to also ack ENISR_OVER here, but that would sometimes mask
-    a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
-    outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
-    return;
+	/* We used to also ack ENISR_OVER here, but that would sometimes mask
+	   a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
+	outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
+	return;
 }
 
 /* 
@@ -611,93 +661,99 @@
  * This includes causing "the NIC to defer indefinitely when it is stopped
  * on a busy network."  Ugh.
  */
+
 static void ei_rx_overrun(struct device *dev)
 {
-    int e8390_base = dev->base_addr;
-    unsigned char was_txing, must_resend = 0;
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
-    
-    /*
-     * Record whether a Tx was in progress and then issue the
-     * stop command.
-     */
-    was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-    
-    if (ei_debug > 1)
-	printk("%s: Receiver overrun.\n", dev->name);
-    ei_local->stat.rx_over_errors++;
-    
-    /* 
-     * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
-     * Early datasheets said to poll the reset bit, but now they say that
-     * it "is not a reliable indicator and subsequently should be ignored."
-     * We wait at least 10ms.
-     */
-    udelay(10*1000);
-
-    /*
-     * Reset RBCR[01] back to zero as per magic incantation.
-     */
-    outb_p(0x00, e8390_base+EN0_RCNTLO);
-    outb_p(0x00, e8390_base+EN0_RCNTHI);
-
-    /*
-     * See if any Tx was interrupted or not. According to NS, this
-     * step is vital, and skipping it will cause no end of havoc.
-     */
-    if (was_txing) { 
-	unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
-	if (!tx_completed) must_resend = 1;
-    }
-
-    /*
-     * Have to enter loopback mode and then restart the NIC before
-     * you are allowed to slurp packets up off the ring.
-     */
-    outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
-    outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
-
-    /*
-     * Clear the Rx ring of all the debris, and ack the interrupt.
-     */
-    ei_receive(dev);
-    outb_p(ENISR_OVER, e8390_base+EN0_ISR);
-
-    /*
-     * Leave loopback mode, and resend any packet that got stopped.
-     */
-    outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); 
-    if (must_resend)
-    	outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
-	
+	int e8390_base = dev->base_addr;
+	unsigned char was_txing, must_resend = 0;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+    
+	/*
+	 * Record whether a Tx was in progress and then issue the
+	 * stop command.
+	 */
+	was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+    
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name);
+	ei_local->stat.rx_over_errors++;
+    
+	/* 
+	 * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+	 * Early datasheets said to poll the reset bit, but now they say that
+	 * it "is not a reliable indicator and subsequently should be ignored."
+	 * We wait at least 10ms.
+	 */
+
+	udelay(10*1000);
+
+	/*
+	 * Reset RBCR[01] back to zero as per magic incantation.
+	 */
+	outb_p(0x00, e8390_base+EN0_RCNTLO);
+	outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+	/*
+	 * See if any Tx was interrupted or not. According to NS, this
+	 * step is vital, and skipping it will cause no end of havoc.
+	 */
+
+	if (was_txing)
+	{ 
+		unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+		if (!tx_completed)
+			must_resend = 1;
+	}
+
+	/*
+	 * Have to enter loopback mode and then restart the NIC before
+	 * you are allowed to slurp packets up off the ring.
+	 */
+	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+	outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+	/*
+	 * Clear the Rx ring of all the debris, and ack the interrupt.
+	 */
+	ei_receive(dev);
+	outb_p(ENISR_OVER, e8390_base+EN0_ISR);
+
+	/*
+	 * Leave loopback mode, and resend any packet that got stopped.
+	 */
+	outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); 
+	if (must_resend)
+    		outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
 }
 
 static struct net_device_stats *get_stats(struct device *dev)
 {
-    short ioaddr = dev->base_addr;
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int ioaddr = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
     
-    /* If the card is stopped, just return the present stats. */
-    if (dev->start == 0) return &ei_local->stat;
-
-    /* Read the counter registers, assuming we are in page 0. */
-    ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
-    ei_local->stat.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
-    ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
+	/* If the card is stopped, just return the present stats. */
+	if (dev->start == 0) 
+		return &ei_local->stat;
+
+	/* Read the counter registers, assuming we are in page 0. */
+	ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
+	ei_local->stat.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
+	ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
     
-    return &ei_local->stat;
+	return &ei_local->stat;
 }
 
 /*
  * Update the given Autodin II CRC value with another data byte.
  */
+
 static inline u32 update_crc(u8 byte, u32 current_crc)
 {
 	int bit;
 	u8 ah = 0;
-
-	for (bit=0; bit<8; bit++) {
+	for (bit=0; bit<8; bit++) 
+	{
 		u8 carry = (current_crc>>31);
 		current_crc <<= 1;
 		ah = ((ah<<1) | carry) ^ byte;
@@ -713,14 +769,17 @@
  * Form the 64 bit 8390 multicast table from the linked list of addresses
  * associated with this dev structure.
  */
+ 
 static inline void make_mc_bits(u8 *bits, struct device *dev)
 {
 	struct dev_mc_list *dmi;
 
-	for (dmi=dev->mc_list; dmi; dmi=dmi->next) {
+	for (dmi=dev->mc_list; dmi; dmi=dmi->next) 
+	{
 		int i;
 		u32 crc;
-		if (dmi->dmi_addrlen != ETH_ALEN) {
+		if (dmi->dmi_addrlen != ETH_ALEN) 
+		{
 			printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);
 			continue;
 		}
@@ -741,17 +800,19 @@
  
 static void set_multicast_list(struct device *dev)
 {
-	short ioaddr = dev->base_addr;
+	int e8390_base = dev->base_addr;
 	int i;
 	unsigned long flags;
-	struct ei_device *ei = (struct ei_device*)dev->priv;
+	struct ei_device *ei_local = (struct ei_device*)dev->priv;
 
-	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
-		memset(ei->mcfilter, 0, 8);
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) 
+	{
+		memset(ei_local->mcfilter, 0, 8);
 		if (dev->mc_list)
-			make_mc_bits(ei->mcfilter, dev);
-	} else
-		memset(ei->mcfilter, 0xFF, 8);	/* mcast set to accept-all */
+			make_mc_bits(ei_local->mcfilter, dev);
+	}
+	else
+		memset(ei_local->mcfilter, 0xFF, 8);	/* mcast set to accept-all */
 
 	/* 
 	 * DP8390 manuals don't specify any magic sequence for altering
@@ -761,30 +822,35 @@
 	 * to stopping the NIC, loading the table and then restarting.
 	 */
 	if (dev->start)
-		outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
+		outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
 	save_flags(flags);
 	cli();
-	outb_p(E8390_NODMA + E8390_PAGE1, ioaddr + E8390_CMD);
-	for(i = 0; i < 8; i++)
-		outb_p(ei->mcfilter[i], ioaddr + EN1_MULT + i);
-	outb_p(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
+	outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+	for(i = 0; i < 8; i++) 
+	{
+		outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+		if(inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
+			printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
+	}
+	outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
 	restore_flags(flags);
 
-	if(dev->flags&IFF_PROMISC)
-		outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
+  	if(dev->flags&IFF_PROMISC)
+  		outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
 	else if(dev->flags&IFF_ALLMULTI || dev->mc_list)
-		outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
-	else
-		outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
+  		outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+  	else
+  		outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
 }
 
 /* Initialize the rest of the 8390 device structure. */
 __initfunc(int ethdev_init(struct device *dev))
 {
-    if (ei_debug > 1)
+	if (ei_debug > 1)
 		printk(version);
     
-    if (dev->priv == NULL) {
+	if (dev->priv == NULL) 
+	{
 		struct ei_device *ei_local;
 		
 		dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
@@ -792,106 +858,116 @@
 			return -ENOMEM;
 		memset(dev->priv, 0, sizeof(struct ei_device));
 		ei_local = (struct ei_device *)dev->priv;
-    }
+	}
     
-    dev->hard_start_xmit = &ei_start_xmit;
-    dev->get_stats	= get_stats;
-    dev->set_multicast_list = &set_multicast_list;
+	dev->hard_start_xmit = &ei_start_xmit;
+	dev->get_stats	= get_stats;
+	dev->set_multicast_list = &set_multicast_list;
 
-    ether_setup(dev);
+	ether_setup(dev);
         
-    return 0;
+	return 0;
 }
 
 
+
 /* This page of functions should be 8390 generic */
 /* Follow National Semi's recommendations for initializing the "NIC". */
+
 void NS8390_init(struct device *dev, int startp)
 {
-    int e8390_base = dev->base_addr;
-    struct ei_device *ei_local = (struct ei_device *) dev->priv;
-    int i;
-    int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
-    unsigned long flags;
-    
-    /* Follow National Semi's recommendations for initing the DP83902. */
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */
-    outb_p(endcfg, e8390_base + EN0_DCFG);	/* 0x48 or 0x49 */
-    /* Clear the remote byte count registers. */
-    outb_p(0x00,  e8390_base + EN0_RCNTLO);
-    outb_p(0x00,  e8390_base + EN0_RCNTHI);
-    /* Set to monitor and loopback mode -- this is vital!. */
-    outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
-    outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
-    /* Set the transmit page and receive ring. */
-    outb_p(ei_local->tx_start_page,	 e8390_base + EN0_TPSR);
-    ei_local->tx1 = ei_local->tx2 = 0;
-    outb_p(ei_local->rx_start_page,	 e8390_base + EN0_STARTPG);
-    outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
-    ei_local->current_page = ei_local->rx_start_page;		/* assert boundary+1 */
-    outb_p(ei_local->stop_page,	  e8390_base + EN0_STOPPG);
-    /* Clear the pending interrupts and mask. */
-    outb_p(0xFF, e8390_base + EN0_ISR);
-    outb_p(0x00,  e8390_base + EN0_IMR);
-    
-    /* Copy the station address into the DS8390 registers. */
-    save_flags(flags);
-    cli();
-    outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */
-    for(i = 0; i < 6; i++) {
-		outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i);
-    }
-    
-    outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base);
-    restore_flags(flags);
-    dev->tbusy = 0;
-    dev->interrupt = 0;
-    ei_local->tx1 = ei_local->tx2 = 0;
-    ei_local->txing = 0;
-    if (startp) {
+	int e8390_base = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int i;
+	int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
+	unsigned long flags;
+    
+	if(sizeof(struct e8390_pkt_hdr)!=4)
+    		panic("8390.c: header struct mispacked\n");    
+	/* Follow National Semi's recommendations for initing the DP83902. */
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+	outb_p(endcfg, e8390_base + EN0_DCFG);	/* 0x48 or 0x49 */
+	/* Clear the remote byte count registers. */
+	outb_p(0x00,  e8390_base + EN0_RCNTLO);
+	outb_p(0x00,  e8390_base + EN0_RCNTHI);
+	/* Set to monitor and loopback mode -- this is vital!. */
+	outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+	/* Set the transmit page and receive ring. */
+	outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+	ei_local->tx1 = ei_local->tx2 = 0;
+	outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+	outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);	/* 3c503 says 0x3f,NS0x26*/
+	ei_local->current_page = ei_local->rx_start_page;		/* assert boundary+1 */
+	outb_p(ei_local->stop_page,	  e8390_base + EN0_STOPPG);
+	/* Clear the pending interrupts and mask. */
+	outb_p(0xFF, e8390_base + EN0_ISR);
+	outb_p(0x00,  e8390_base + EN0_IMR);
+    
+	/* Copy the station address into the DS8390 registers. */
+	save_flags(flags);
+	cli();
+	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+	for(i = 0; i < 6; i++) 
+	{
+		outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+		if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
+			printk(KERN_ERR "Hw. address read/write mismap %d\n",i);
+	}
+
+	outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+	restore_flags(flags);
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	ei_local->tx1 = ei_local->tx2 = 0;
+	ei_local->txing = 0;
+
+	if (startp) 
+	{
 		outb_p(0xff,  e8390_base + EN0_ISR);
 		outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
-		outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base);
+		outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
 		outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
 		/* 3c503 TechMan says rxconfig only after the NIC is started. */
 		outb_p(E8390_RXCONFIG,	e8390_base + EN0_RXCR); /* rx on,  */
 		set_multicast_list(dev);	/* (re)load the mcast table */
-    }
-    return;
+	}
+	return;
 }
 
 /* Trigger a transmit start, assuming the length is valid. */
 static void NS8390_trigger_send(struct device *dev, unsigned int length,
 								int start_page)
 {
-    int e8390_base = dev->base_addr;
+	struct ei_device *ei_local = (struct ei_device *) dev->priv;
+	int e8390_base = dev->base_addr;
     
-    outb_p(E8390_NODMA+E8390_PAGE0, e8390_base);
+	outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
     
-    if (inb_p(e8390_base) & E8390_TRANS) {
-		printk("%s: trigger_send() called with the transmitter busy.\n",
-			   dev->name);
+	if (inb_p(e8390_base) & E8390_TRANS) 
+	{
+		printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n",
+			dev->name);
 		return;
-    }
-    outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
-    outb_p(length >> 8, e8390_base + EN0_TCNTHI);
-    outb_p(start_page, e8390_base + EN0_TPSR);
-    outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base);
-    return;
+	}
+	outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+	outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+	outb_p(start_page, e8390_base + EN0_TPSR);
+	outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
 }
 
 #ifdef MODULE
 
 int init_module(void)
 {
-     return 0;
+	return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 }
+
 #endif /* MODULE */
 
 /*
diff -u --recursive --new-file v2.1.100/linux/drivers/net/8390.h linux/drivers/net/8390.h
--- v2.1.100/linux/drivers/net/8390.h	Wed Oct 22 08:28:35 1997
+++ linux/drivers/net/8390.h	Thu May  7 23:50:19 1998
@@ -75,6 +75,7 @@
   unsigned char saved_irq;	/* Original dev->irq value. */
   /* The new statistics table. */
   struct net_device_stats stat;
+  unsigned char *reg_offset;    /* Register mapping table */
 };
 
 /* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -104,34 +105,41 @@
 #define E8390_PAGE1	0x40	/* using the two high-order bits */
 #define E8390_PAGE2	0x80	/* Page 3 is invalid. */
 
-#define E8390_CMD	0x00	/* The command register (for all pages) */
+
+#ifndef CONFIG_MAC
+#define EI_SHIFT(x)	(x)
+#else
+#define EI_SHIFT(x)	(ei_local->reg_offset[x])
+#endif
+
+#define E8390_CMD	EI_SHIFT(0x00)  /* The command register (for all pages) */
 /* Page 0 register offsets. */
-#define EN0_CLDALO	0x01	/* Low byte of current local dma addr  RD */
-#define EN0_STARTPG	0x01	/* Starting page of ring bfr WR */
-#define EN0_CLDAHI	0x02	/* High byte of current local dma addr  RD */
-#define EN0_STOPPG	0x02	/* Ending page +1 of ring bfr WR */
-#define EN0_BOUNDARY	0x03	/* Boundary page of ring bfr RD WR */
-#define EN0_TSR		0x04	/* Transmit status reg RD */
-#define EN0_TPSR	0x04	/* Transmit starting page WR */
-#define EN0_NCR		0x05	/* Number of collision reg RD */
-#define EN0_TCNTLO	0x05	/* Low  byte of tx byte count WR */
-#define EN0_FIFO	0x06	/* FIFO RD */
-#define EN0_TCNTHI	0x06	/* High byte of tx byte count WR */
-#define EN0_ISR		0x07	/* Interrupt status reg RD WR */
-#define EN0_CRDALO	0x08	/* low byte of current remote dma address RD */
-#define EN0_RSARLO	0x08	/* Remote start address reg 0 */
-#define EN0_CRDAHI	0x09	/* high byte, current remote dma address RD */
-#define EN0_RSARHI	0x09	/* Remote start address reg 1 */
-#define EN0_RCNTLO	0x0a	/* Remote byte count reg WR */
-#define EN0_RCNTHI	0x0b	/* Remote byte count reg WR */
-#define EN0_RSR		0x0c	/* rx status reg RD */
-#define EN0_RXCR	0x0c	/* RX configuration reg WR */
-#define EN0_TXCR	0x0d	/* TX configuration reg WR */
-#define EN0_COUNTER0	0x0d	/* Rcv alignment error counter RD */
-#define EN0_DCFG	0x0e	/* Data configuration reg WR */
-#define EN0_COUNTER1	0x0e	/* Rcv CRC error counter RD */
-#define EN0_IMR		0x0f	/* Interrupt mask reg WR */
-#define EN0_COUNTER2	0x0f	/* Rcv missed frame error counter RD */
+#define EN0_CLDALO	EI_SHIFT(0x01)	/* Low byte of current local dma addr  RD */
+#define EN0_STARTPG	EI_SHIFT(0x01)	/* Starting page of ring bfr WR */
+#define EN0_CLDAHI	EI_SHIFT(0x02)	/* High byte of current local dma addr  RD */
+#define EN0_STOPPG	EI_SHIFT(0x02)	/* Ending page +1 of ring bfr WR */
+#define EN0_BOUNDARY	EI_SHIFT(0x03)	/* Boundary page of ring bfr RD WR */
+#define EN0_TSR		EI_SHIFT(0x04)	/* Transmit status reg RD */
+#define EN0_TPSR	EI_SHIFT(0x04)	/* Transmit starting page WR */
+#define EN0_NCR		EI_SHIFT(0x05)	/* Number of collision reg RD */
+#define EN0_TCNTLO	EI_SHIFT(0x05)	/* Low  byte of tx byte count WR */
+#define EN0_FIFO	EI_SHIFT(0x06)	/* FIFO RD */
+#define EN0_TCNTHI	EI_SHIFT(0x06)	/* High byte of tx byte count WR */
+#define EN0_ISR		EI_SHIFT(0x07)	/* Interrupt status reg RD WR */
+#define EN0_CRDALO	EI_SHIFT(0x08)	/* low byte of current remote dma address RD */
+#define EN0_RSARLO	EI_SHIFT(0x08)	/* Remote start address reg 0 */
+#define EN0_CRDAHI	EI_SHIFT(0x09)	/* high byte, current remote dma address RD */
+#define EN0_RSARHI	EI_SHIFT(0x09)	/* Remote start address reg 1 */
+#define EN0_RCNTLO	EI_SHIFT(0x0a)	/* Remote byte count reg WR */
+#define EN0_RCNTHI	EI_SHIFT(0x0b)	/* Remote byte count reg WR */
+#define EN0_RSR		EI_SHIFT(0x0c)	/* rx status reg RD */
+#define EN0_RXCR	EI_SHIFT(0x0c)	/* RX configuration reg WR */
+#define EN0_TXCR	EI_SHIFT(0x0d)	/* TX configuration reg WR */
+#define EN0_COUNTER0	EI_SHIFT(0x0d)	/* Rcv alignment error counter RD */
+#define EN0_DCFG	EI_SHIFT(0x0e)	/* Data configuration reg WR */
+#define EN0_COUNTER1	EI_SHIFT(0x0e)	/* Rcv CRC error counter RD */
+#define EN0_IMR		EI_SHIFT(0x0f)	/* Interrupt mask reg WR */
+#define EN0_COUNTER2	EI_SHIFT(0x0f)	/* Rcv missed frame error counter RD */
 
 /* Bits in EN0_ISR - Interrupt status register */
 #define ENISR_RX	0x01	/* Receiver, no error */
@@ -148,9 +156,11 @@
 #define ENDCFG_WTS	0x01	/* word transfer mode selection */
 
 /* Page 1 register offsets. */
-#define EN1_PHYS   0x01	/* This board's physical enet addr RD WR */
-#define EN1_CURPAG 0x07	/* Current memory page RD WR */
-#define EN1_MULT   0x08	/* Multicast filter mask array (8 bytes) RD WR */
+#define EN1_PHYS   EI_SHIFT(0x01)	/* This board's physical enet addr RD WR */
+#define EN1_PHYS_SHIFT(i)  EI_SHIFT(i+1) /* Get and set mac address */
+#define EN1_CURPAG EI_SHIFT(0x07)	/* Current memory page RD WR */
+#define EN1_MULT   EI_SHIFT(0x08)	/* Multicast filter mask array (8 bytes) RD WR */
+#define EN1_MULT_SHIFT(i)  EI_SHIFT(8+i) /* Get and set multicast filter */
 
 /* Bits in received packet status byte and EN0_RSR*/
 #define ENRSR_RXOK	0x01	/* Received a good packet */
@@ -158,7 +168,7 @@
 #define ENRSR_FAE	0x04	/* frame alignment error */
 #define ENRSR_FO	0x08	/* FIFO overrun */
 #define ENRSR_MPA	0x10	/* missed pkt */
-#define ENRSR_PHY	0x20	/* physical/multicase address */
+#define ENRSR_PHY	0x20	/* physical/multicast address */
 #define ENRSR_DIS	0x40	/* receiver disable. set in monitor mode */
 #define ENRSR_DEF	0x80	/* deferring */
 
diff -u --recursive --new-file v2.1.100/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.100/linux/drivers/net/Config.in	Thu Apr 23 20:21:33 1998
+++ linux/drivers/net/Config.in	Fri May  8 00:20:47 1998
@@ -34,8 +34,8 @@
   if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
     tristate '3c501 support' CONFIG_EL1
     tristate '3c503 support' CONFIG_EL2
+    tristate '3c505 support' CONFIG_ELPLUS
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate '3c505 support' CONFIG_ELPLUS
       tristate '3c507 support' CONFIG_EL16
       if [ "$CONFIG_MCA" = "y" ]; then
         tristate '3c523 support' CONFIG_ELMC
@@ -62,6 +62,10 @@
     fi
     tristate 'NI5210 support' CONFIG_NI52
     tristate 'NI6510 support' CONFIG_NI65
+  fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'RealTek 8129/8139 (not 8019/8029!) support' CONFIG_RTL8139
+      tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN
   fi
   bool 'Other ISA cards' CONFIG_NET_ISA
   if [ "$CONFIG_NET_ISA" = "y" ]; then
diff -u --recursive --new-file v2.1.100/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.100/linux/drivers/net/Makefile	Wed Apr  8 19:36:26 1998
+++ linux/drivers/net/Makefile	Fri May  8 00:20:47 1998
@@ -71,7 +71,6 @@
 L_OBJS += sk_g16.o
 endif
 
-
 ifeq ($(CONFIG_HP100),y)
 L_OBJS += hp100.o
 else
@@ -419,6 +418,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_RTL8139),y)
+L_OBJS += rtl8139.o
+else
+  ifeq ($(CONFIG_RTL8139),m)
+  M_OBJS += rtl8139.o
+  endif
+endif
+
+ifeq ($(CONFIG_YELLOWFIN),y)
+L_OBJS += yellowfin.o
+else
+  ifeq ($(CONFIG_YELLOWFIN),m)
+  M_OBJS += yellowfin.o
+  endif
+endif
+
 ifeq ($(CONFIG_WAVELAN),y)
 L_OBJS += wavelan.o
 else
@@ -747,7 +762,7 @@
 endif
 
 ifeq ($(CONFIG_VENDOR_SANGOMA),y)
-  L_OBJS += sdladrv.o
+  LX_OBJS += sdladrv.o
   L_OBJS += sdlamain.o
   ifeq ($(CONFIG_WANPIPE_X25),y)
     L_OBJS += sdla_x25.o
diff -u --recursive --new-file v2.1.100/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.100/linux/drivers/net/Space.c	Wed Apr  8 19:36:26 1998
+++ linux/drivers/net/Space.c	Fri May  8 00:20:47 1998
@@ -95,6 +95,10 @@
 extern int cs89x0_probe(struct device *dev);
 extern int ethertap_probe(struct device *dev);
 extern int epic100_probe(struct device *dev);
+extern int rtl8139_probe(struct device *dev);
+
+/* Gigabit Ethernet adapters */
+extern int yellowfin_probe(struct device *dev);
 
 /* Detachable devices ("pocket adaptors") */
 extern int atp_init(struct device *);
@@ -105,6 +109,9 @@
 extern int dfx_probe(struct device *dev);
 extern int apfddi_init(struct device *dev);
 
+/* HIPPI boards */
+extern int cern_hippi_probe(struct device *);
+
 
 __initfunc(static int ethif_probe(struct device *dev))
 {
@@ -291,6 +298,12 @@
 #ifdef CONFIG_EPIC100
 	&& epic100_probe(dev)
 #endif
+#ifdef CONFIG_RTL8139
+        && rtl8139_probe(dev)
+#endif
+#ifdef CONFIG_YELLOWFIN
+        && yellowfin_probe(dev)
+#endif
 	&& 1 ) {
 	return 1;	/* -ENODEV or -EAGAIN would be more accurate. */
     }
@@ -320,6 +333,28 @@
 }
 #endif
 
+#ifdef CONFIG_HIPPI
+static int hippi_probe(struct device *dev)
+{
+	/*
+	 * Damn this is ugly.
+	 *
+	 * Why the heck would we want to determine this from the base
+	 * address? Stupid PC'ism .... grrrrr.
+	 */
+	if (dev->base_addr == -1)
+		return 1;
+
+	if (1
+#ifdef CONFIG_CERN_HIPPI
+	    && cern_hippi_probe(dev)
+#endif
+	    && 1 ) {
+		return 1; /* -ENODEV or -EAGAIN would be more accurate. */
+	}
+	return 0;
+}
+#endif
 
 #ifdef CONFIG_ETHERTAP
     static struct device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, };
@@ -539,6 +574,20 @@
 		{"fddi0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi1_dev, fddiif_probe};
 #undef	NEXT_DEV
 #define	NEXT_DEV	(&fddi0_dev)
+#endif 
+
+#ifdef CONFIG_HIPPI
+	static struct device hip3_dev =
+		{"hip3", 0, 0, 0, 0, -1, 0, 0, 0, 0, NEXT_DEV, hippi_probe};
+	static struct device hip2_dev =
+		{"hip2", 0, 0, 0, 0, -1, 0, 0, 0, 0, &hip3_dev, hippi_probe};
+	static struct device hip1_dev =
+		{"hip1", 0, 0, 0, 0, -1, 0, 0, 0, 0, &hip2_dev, hippi_probe};
+	static struct device hip0_dev =
+		{"hip0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &hip1_dev, hippi_probe};
+
+#undef	NEXT_DEV
+#define	NEXT_DEV	(&hip0_dev)
 #endif 
 
 #ifdef CONFIG_APBIF
diff -u --recursive --new-file v2.1.100/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c
--- v2.1.100/linux/drivers/net/am79c961a.c	Mon Feb 23 18:12:05 1998
+++ linux/drivers/net/am79c961a.c	Fri May  8 00:42:39 1998
@@ -1,11 +1,10 @@
 /*
- *	linux/drivers/net/am79c961.c
+ * linux/drivers/net/am79c961.c
  *
- *	Derived from various things including skeleton.c
+ * Derived from various things including skeleton.c
  *
- *	R.M.King 1995.
+ * R.M.King 1995.
  */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -35,33 +34,42 @@
 #include "am79c961a.h"
 
 static unsigned int net_debug = NET_DEBUG;
-static void am79c961_setmulticastlist (struct device *dev);
+
+static void
+am79c961_setmulticastlist (struct device *dev);
 
 static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.00\n";
 
-static void write_rreg (unsigned long base, unsigned int reg, unsigned short val)
+#define FUNC_PROLOGUE \
+	struct dev_priv *priv = (struct dev_priv *)dev->priv
+
+/* --------------------------------------------------------------------------- */
+
+static void
+write_rreg (unsigned long base, unsigned int reg, unsigned short val)
 {
-    __asm__("
-	strh	%1, [%2]	@ NET_RAP
-	strh	%0, [%2, #-4]	@ NET_RDP
-	" : : "r" (val), "r" (reg), "r" (0xf0000464));
+	__asm__("
+		strh	%1, [%2]	@ NET_RAP
+		strh	%0, [%2, #-4]	@ NET_RDP
+		" : : "r" (val), "r" (reg), "r" (0xf0000464));
 }
 
 static inline void
 write_ireg (unsigned long base, unsigned int reg, unsigned short val)
 {
-    __asm__("
-	strh	%1, [%2]	@ NET_RAP
-	strh	%0, [%2, #8]	@ NET_RDP
-	" : : "r" (val), "r" (reg), "r" (0xf0000464));
+	__asm__("
+		strh	%1, [%2]	@ NET_RAP
+		strh	%0, [%2, #8]	@ NET_RDP
+		" : : "r" (val), "r" (reg), "r" (0xf0000464));
 }
 
 #define am_writeword(dev,off,val)\
-    __asm__("\
-	strh	%0, [%1]\
-	" : : "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1)));
+	__asm__("\
+		strh	%0, [%1]\
+		" : : "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1)));
 
-static inline void am_writebuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
+static inline void
+am_writebuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
 {
 	offset = 0xe0000000 + (offset << 1);
 	length = (length + 1) & ~1;
@@ -72,8 +80,7 @@
 		buf += 2;
 		length -= 2;
 	}
-	while (length > 8) 
-	{
+	while (length > 8) {
 		unsigned int tmp, tmp2;
 		__asm__ __volatile__("
 			ldmia	%1!, {%2, %3}
@@ -107,7 +114,8 @@
 	return v;
 }
 
-static inline unsigned short am_readword (struct device *dev, unsigned long off)
+static inline unsigned short
+am_readword (struct device *dev, unsigned long off)
 {
 	unsigned long address = 0xe0000000 + (off << 1);
 	unsigned short val;
@@ -118,7 +126,8 @@
 	return val;
 }
 
-static inline void am_readbuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
+static inline void
+am_readbuffer(struct device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
 {
 	offset = 0xe0000000 + (offset << 1);
 	length = (length + 1) & ~1;
@@ -158,12 +167,8 @@
 	}
 }
 
-/*
- *	From here on is mostly non ARM specific. Watch the fact it knows
- *	the chip can hit all memory (kmalloc).
- */
-
-static int am79c961_ramtest(struct device *dev, unsigned int val)
+static int
+am79c961_ramtest(struct device *dev, unsigned int val)
 {
 	unsigned char *buffer = kmalloc (65536, GFP_KERNEL);
 	int i, error = 0, errorcount = 0;
@@ -190,9 +195,10 @@
 	return errorcount;
 }
 
-static void am79c961_init_for_open(struct device *dev)
+static void
+am79c961_init_for_open(struct device *dev)
 {
-    	struct dev_priv *priv = (struct dev_priv *)dev->priv;
+	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	unsigned long hdr_addr, first_free_addr;
 	unsigned long flags;
 	unsigned char *p;
@@ -212,9 +218,8 @@
 	priv->rxtail = 0;
 	priv->rxhdr = hdr_addr;
 
-	for (i = 0; i < RX_BUFFERS; i++) 
-	{
-    		priv->rxbuffer[i] = first_free_addr;
+	for (i = 0; i < RX_BUFFERS; i++) {
+		priv->rxbuffer[i] = first_free_addr;
 		am_writeword (dev, hdr_addr, first_free_addr);
 		am_writeword (dev, hdr_addr + 2, RMD_OWN);
 		am_writeword (dev, hdr_addr + 4, (-1600));
@@ -225,9 +230,8 @@
 	priv->txhead = 0;
 	priv->txtail = 0;
 	priv->txhdr = hdr_addr;
-	for (i = 0; i < TX_BUFFERS; i++) 
-	{
-    		priv->txbuffer[i] = first_free_addr;
+	for (i = 0; i < TX_BUFFERS; i++) {
+		priv->txbuffer[i] = first_free_addr;
 		am_writeword (dev, hdr_addr, first_free_addr);
 		am_writeword (dev, hdr_addr + 2, 0);
 		am_writeword (dev, hdr_addr + 4, 0);
@@ -251,7 +255,7 @@
 	write_rreg (dev->base_addr, BASERXH, 0);
 	write_rreg (dev->base_addr, BASETXL, priv->txhdr);
 	write_rreg (dev->base_addr, BASERXH, 0);
-	write_rreg (dev->base_addr, POLLINT, 0);	
+	write_rreg (dev->base_addr, POLLINT, 0);
 	write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
 	write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
 	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
@@ -259,7 +263,8 @@
 	write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
 }
 
-static int am79c961_init(struct device *dev)
+static int
+am79c961_init(struct device *dev)
 {
 	unsigned long flags;
 
@@ -280,15 +285,14 @@
 /*
  * This is the real probe routine.
  */
-
-static int am79c961_probe1(struct device *dev)
+static int
+am79c961_probe1(struct device *dev)
 {
 	static unsigned version_printed = 0;
 	struct dev_priv *priv;
 	int i;
 
-	if (!dev->priv) 
-	{
+	if (!dev->priv) {
 		dev->priv = kmalloc (sizeof (struct dev_priv), GFP_KERNEL);
 		if (!dev->priv)
 			return -ENOMEM;
@@ -300,21 +304,19 @@
 	/*
 	 * The PNP initialisation should have been done by the ether bootp loader.
 	 */
-	 
 	inb ((dev->base_addr + NET_RESET) >> 1);	/* reset the device */
 
 	udelay (5);
 
 	if (inb (dev->base_addr >> 1) != 0x08 ||
-		inb ((dev->base_addr >> 1) + 1) != 00 ||
-		inb ((dev->base_addr >> 1) + 2) != 0x2b) 
-	{
+	    inb ((dev->base_addr >> 1) + 1) != 00 ||
+	    inb ((dev->base_addr >> 1) + 2) != 0x2b) {
 		kfree (dev->priv);
 		dev->priv = NULL;
 		return -ENODEV;
-	 }
+	}
 
-	 /*
+	/*
 	 * Ok, we've found a valid hw ID
 	 */
 
@@ -325,14 +327,12 @@
 	request_region (dev->base_addr, 0x18, "am79c961");
 
 	/* Retrive and print the ethernet address. */
-	for (i = 0; i < 6; i++) 
-	{
-    		dev->dev_addr[i] = inb ((dev->base_addr >> 1) + i) & 0xff;
+	for (i = 0; i < 6; i++) {
+		dev->dev_addr[i] = inb ((dev->base_addr >> 1) + i) & 0xff;
 		printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
 	}
 
-	if (am79c961_init(dev)) 
-	{
+	if (am79c961_init(dev)) {
 		kfree (dev->priv);
 		dev->priv = NULL;
 		return -ENODEV;
@@ -346,10 +346,12 @@
 
 	/* Fill in the fields of the device structure with ethernet values. */
 	ether_setup(dev);
+
 	return 0;
 }
 
-int am79c961_probe(struct device *dev)
+int
+am79c961_probe(struct device *dev)
 {
 	static int initialised = 0;
 
@@ -371,10 +373,10 @@
  * registers that "should" only need to be set once at boot, so that
  * there is non-reboot way to recover if something goes wrong.
  */
-
-static int am79c961_open(struct device *dev)
+static int
+am79c961_open(struct device *dev)
 {
-    	struct dev_priv *priv = (struct dev_priv *)dev->priv;
+	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
 	MOD_INC_USE_COUNT;
 
@@ -384,6 +386,7 @@
 		return -EAGAIN;
 
 	am79c961_init_for_open(dev);
+
 	dev->tbusy = 0;
 	dev->interrupt = 0;
 	dev->start = 1;
@@ -393,13 +396,14 @@
 /*
  * The inverse routine to am79c961_open().
  */
- 
-static int am79c961_close(struct device *dev)
+static int
+am79c961_close(struct device *dev)
 {
 	dev->tbusy = 1;
 	dev->start = 0;
 
 	am79c961_init(dev);
+
 	free_irq (dev->irq, dev);
 
 	MOD_DEC_USE_COUNT;
@@ -410,10 +414,9 @@
  * Get the current statistics.	This may be called with the card open or
  * closed.
  */
-
 static struct enet_statistics *am79c961_getstats (struct device *dev)
 {
-    	struct dev_priv *priv = (struct dev_priv *)dev->priv;
+	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 	return &priv->stats;
 }
 
@@ -423,7 +426,6 @@
  * We don't attempt any packet filtering.  The card may have a SEEQ 8004
  * in which does not have the other ethernet address registers present...
  */
-
 static void am79c961_setmulticastlist (struct device *dev)
 {
 	unsigned long flags;
@@ -441,18 +443,16 @@
 }
 
 /*
- *	Transmit a packet
+ * Transmit a packet
  */
-
-static int am79c961_sendpacket(struct sk_buff *skb, struct device *dev)
+static int
+am79c961_sendpacket(struct sk_buff *skb, struct device *dev)
 {
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
 
-	if (!dev->tbusy) 
-	{
+	if (!dev->tbusy) {
 again:
-		if (!test_and_set_bit(0, (void*)&dev->tbusy)) 
-		{
+		if (!test_and_set_bit(0, (void*)&dev->tbusy)) {
 			unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 			unsigned int hdraddr, bufaddr;
 			unsigned long flags;
@@ -474,17 +474,12 @@
 
 			if (!(am_readword (dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN))
 				dev->tbusy = 0;
-			dev_kfree_skb (skb, FREE_WRITE);
+			dev_kfree_skb (skb);
 			return 0;
-		}
-		else
-		{
+		} else
 			printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name);
 			return 1;
-		}
-	}
-	else 
-	{
+	} else {
 		int tickssofar = jiffies - dev->trans_start;
 		if (tickssofar < 5)
 			return 1;
@@ -496,7 +491,8 @@
 	}
 }
 
-static void am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void
+am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct device *dev = (struct device *)dev_id;
 	struct dev_priv *priv = (struct dev_priv *)dev->priv;
@@ -508,6 +504,7 @@
 #endif
 
 	dev->interrupt = 1;
+
 	status = read_rreg (dev->base_addr, CSR0);
 	write_rreg (dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
 
@@ -529,14 +526,13 @@
 /*
  * If we have a good packet(s), get it/them out of the buffers.
  */
-
-static void am79c961_rx(struct device *dev, struct dev_priv *priv)
+static void
+am79c961_rx(struct device *dev, struct dev_priv *priv)
 {
 	unsigned long hdraddr;
 	unsigned long pktaddr;
 
-	do 
-	{
+	do {
 		unsigned long status;
 		struct sk_buff *skb;
 		int len;
@@ -552,18 +548,15 @@
 		if (priv->rxtail >= RX_BUFFERS)
 			priv->rxtail = 0;
 
-		if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) 
-		{
+		if ((status & (RMD_ERR|RMD_STP|RMD_ENP)) != (RMD_STP|RMD_ENP)) {
 			am_writeword (dev, hdraddr + 2, RMD_OWN);
 			priv->stats.rx_errors ++;
-			if (status & RMD_ERR) 
-			{
+			if (status & RMD_ERR) {
 				if (status & RMD_FRAM)
 					priv->stats.rx_frame_errors ++;
 				if (status & RMD_CRC)
 					priv->stats.rx_crc_errors ++;
-			}
-			else if (status & RMD_STP)
+			} else if (status & RMD_STP)
 				priv->stats.rx_length_errors ++;
 			continue;
 		}
@@ -595,8 +588,8 @@
 /*
  * Update stats for the transmitted packet
  */
-
-static void am79c961_tx(struct device *dev, struct dev_priv *priv)
+static void
+am79c961_tx(struct device *dev, struct dev_priv *priv)
 {
 	do {
 		unsigned long hdraddr;
diff -u --recursive --new-file v2.1.100/linux/drivers/net/com90xx.c linux/drivers/net/com90xx.c
--- v2.1.100/linux/drivers/net/com90xx.c	Mon Feb 23 18:12:05 1998
+++ linux/drivers/net/com90xx.c	Fri May  8 00:20:47 1998
@@ -1,28 +1,28 @@
-/*	$Id: com90xx.c,v 1.6 1997/11/09 11:05:01 mj Exp $
+/*      $Id: com90xx.c,v 1.9 1998/03/21 18:02:51 alan Exp $
 
-	Derived from the original arcnet.c,
-	Written 1994-1996 by Avery Pennarun,
-	which was in turn derived from skeleton.c by Donald Becker.
+   Derived from the original arcnet.c,
+   Written 1994-1996 by Avery Pennarun,
+   which was in turn derived from skeleton.c by Donald Becker.
 
-	Contact Avery at: apenwarr@bond.net or
-	RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
+   Contact Avery at: apenwarr@bond.net or
+   RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
 
-	**********************
+   **********************
 
-	The original copyright of skeleton.c was as follows:
+   The original copyright of skeleton.c was as follows:
 
-	skeleton.c Written 1993 by Donald Becker.
-	Copyright 1993 United States Government as represented by the
-        Director, National Security Agency.  This software may only be used
-        and distributed according to the terms of the GNU Public License as
-        modified by SRC, incorporated herein by reference.
+   skeleton.c Written 1993 by Donald Becker.
+   Copyright 1993 United States Government as represented by the
+   Director, National Security Agency.  This software may only be used
+   and distributed according to the terms of the GNU Public License as
+   modified by SRC, incorporated herein by reference.
 
-	**********************
+   **********************
 
-	For more details, see drivers/net/arcnet.c
+   For more details, see drivers/net/arcnet.c
 
-	**********************
-*/
+   **********************
+ */
 
 
 #include <linux/module.h>
@@ -94,34 +94,34 @@
 #ifdef MODULE
 static
 #endif
-       int arc90xx_probe(struct device *dev);
-static void arc90xx_rx(struct device *dev,int recbuf);
-static int arc90xx_found(struct device *dev,int ioaddr,int airq,u_long shmem,int more);
-static void arc90xx_inthandler (struct device *dev);
-static int arc90xx_reset (struct device *dev, int reset_delay);
-static void arc90xx_setmask (struct device *dev, u_char mask);
-static void arc90xx_command (struct device *dev, u_char command);
-static u_char arc90xx_status (struct device *dev);
-static void arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
-		      char *data,int length,int daddr,int exceptA, int offset);
-static  void arc90xx_openclose(int open);
+int arc90xx_probe(struct device *dev);
+static void arc90xx_rx(struct device *dev, int recbuf);
+static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more);
+static void arc90xx_inthandler(struct device *dev);
+static int arc90xx_reset(struct device *dev, int reset_delay);
+static void arc90xx_setmask(struct device *dev, u_char mask);
+static void arc90xx_command(struct device *dev, u_char command);
+static u_char arc90xx_status(struct device *dev);
+static void arc90xx_prepare_tx(struct device *dev, u_char * hdr, int hdrlen,
+	     char *data, int length, int daddr, int exceptA, int offset);
+static void arc90xx_openclose(int open);
 
 
 /* Module parameters */
 
 #ifdef MODULE
-static int io=0x0;	/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
-static int irq=0;	/* or use the insmod io= irq= shmem= options */
-static int shmem=0;
-static char *device;	/* use eg. device="arc1" to change name */
+static int io = 0x0;		/* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */
+static int irq = 0;		/* or use the insmod io= irq= shmem= options */
+static int shmem = 0;
+static char *device;		/* use eg. device="arc1" to change name */
 
 MODULE_PARM(io, "i");
 MODULE_PARM(irq, "i");
 MODULE_PARM(shmem, "i");
 MODULE_PARM(device, "s");
 #else
-__initfunc(void com90xx_setup (char *str, int *ints));
-char __initdata com90xx_explicit=0;
+__initfunc(void com90xx_setup(char *str, int *ints));
+char __initdata com90xx_explicit = 0;
 
 extern struct device arcnet_devs[];
 extern char arcnet_dev_names[][10];
@@ -139,12 +139,12 @@
 #define _STATUS  (ioaddr+0)	/* readable */
 #define _COMMAND (ioaddr+1)	/* writable, returns random vals on read (?) */
 #define _RESET  (ioaddr+8)	/* software reset (on read) */
-#define _MEMDATA  (ioaddr+12)            /* Data port for IO-mapped memory */
-#define _ADDR_HI  (ioaddr+15)            /* Control registers for said */
+#define _MEMDATA  (ioaddr+12)	/* Data port for IO-mapped memory */
+#define _ADDR_HI  (ioaddr+15)	/* Control registers for said */
 #define _ADDR_LO  (ioaddr+14)
-#define _CONFIG  (ioaddr+2)      /* Configuration register */
+#define _CONFIG  (ioaddr+2)	/* Configuration register */
 
-#define RDDATAflag      0x00     /* Next access is a read/~write */
+#define RDDATAflag      0x00	/* Next access is a read/~write */
 
 #define ARCSTATUS	inb(_STATUS)
 #define ACOMMAND(cmd) 	outb((cmd),_COMMAND)
@@ -153,7 +153,7 @@
 #define ARCRESET	inb(_RESET)
 
 static const char *version =
- "com90xx.c: v3.00 97/11/09 Avery Pennarun <apenwarr@bond.net> et al.\n";
+"com90xx.c: v3.00 97/11/09 Avery Pennarun <apenwarr@bond.net> et al.\n";
 
 
 /****************************************************************************
@@ -166,7 +166,7 @@
  *  If dev->base_addr == 0, probe all likely locations.
  *  If dev->base_addr == 1, always return failure.
  *  If dev->base_addr == 2, allocate space for the device and return success
- *  			    (detachable devices only).
+ *                          (detachable devices only).
  *
  * NOTE: the list of possible ports/shmems is static, so it is retained
  * across calls to arcnet_probe.  So, if more than one ARCnet probe is made,
@@ -175,811 +175,736 @@
  * FIXME: grab all devices in one shot and eliminate the big static array.
  */
 
-static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = { 0 };
-static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = { 0 };
+static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata = {
+	0
+};
+static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata = {
+	0
+};
 
 __initfunc(int arc90xx_probe(struct device *dev))
 {
-  static int init_once = 0;
-  static int numports=sizeof(ports)/sizeof(ports[0]),
-    numshmems=sizeof(shmems)/sizeof(shmems[0]);
-  int count,status,delayval,ioaddr,numprint,airq,retval=-ENODEV,
-    openparen=0;
-  unsigned long airqmask;
-  int *port;
-  u_long *shmem;
-
-  if (!init_once)
-    {
-      for (count=0x200; count<=0x3f0; count+=16)
-	ports[(count-0x200)/16] = count;
-      for (count=0xA0000; count<=0xFF800; count+=2048)
-	shmems[(count-0xA0000)/2048] = count;
-      BUGLVL(D_NORMAL) printk(version);
-      BUGMSG(D_DURING,"space used for probe buffers: %d+%d=%d bytes\n",
-	 sizeof(ports),sizeof(shmems),
-	 sizeof(ports)+sizeof(shmems));
-    }
-  init_once++;
-
-  BUGMSG(D_INIT,"given: base %lXh, IRQ %d, shmem %lXh\n",
-	 dev->base_addr,dev->irq,dev->mem_start);
-
-  if (dev->base_addr > 0x1ff)	/* Check a single specified port */
-    {
-      ports[0]=dev->base_addr;
-      numports=1;
-    }
-  else if (dev->base_addr > 0)	/* Don't probe at all. */
-    return -ENXIO;
-
-  if (dev->mem_start)
-    {
-      shmems[0]=dev->mem_start;
-      numshmems=1;
-    }
-
-  /* Stage 1: abandon any reserved ports, or ones with status==0xFF
-   * (empty), and reset any others by reading the reset port.
-   */
-  BUGMSG(D_INIT,"Stage 1: ");
-  numprint=0;
-  for (port = &ports[0]; port-ports<numports; port++)
-    {
-      numprint++;
-      if (numprint>8)
-	{
-	  BUGMSG2(D_INIT,"\n");
-	  BUGMSG(D_INIT,"Stage 1: ");
-	  numprint=1;
-	}
-      BUGMSG2(D_INIT,"%Xh ",*port);
-
-      ioaddr=*port;
-
-      if (check_region(*port, ARCNET_TOTAL_SIZE))
-	{
-	  BUGMSG2(D_INIT_REASONS,"(check_region)\n");
-	  BUGMSG(D_INIT_REASONS,"Stage 1: ");
-	  BUGLVL(D_INIT_REASONS) numprint=0;
-	  *port=ports[numports-1];
-	  numports--;
-	  port--;
-	  continue;
-	}
-
-      if (ARCSTATUS == 0xFF)
-	{
-	  BUGMSG2(D_INIT_REASONS,"(empty)\n");
-	  BUGMSG(D_INIT_REASONS,"Stage 1: ");
-	  BUGLVL(D_INIT_REASONS) numprint=0;
-	  *port=ports[numports-1];
-	  numports--;
-	  port--;
-	  continue;
-	}
-
-      ARCRESET;	/* begin resetting card */
-
-      BUGMSG2(D_INIT_REASONS,"\n");
-      BUGMSG(D_INIT_REASONS,"Stage 1: ");
-      BUGLVL(D_INIT_REASONS) numprint=0;
-    }
-  BUGMSG2(D_INIT,"\n");
-
-  if (!numports)
-    {
-      BUGMSG(D_NORMAL,"Stage 1: No ARCnet cards found.\n");
-      return -ENODEV;
-    }
-
-  /* Stage 2: we have now reset any possible ARCnet cards, so we can't
-   * do anything until they finish.  If D_INIT, print the list of
-   * cards that are left.
-   */
-  BUGMSG(D_INIT,"Stage 2: ");
-  numprint=0;
-  for (port = &ports[0]; port-ports<numports; port++)
-    {
-      numprint++;
-      if (numprint>8)
-	{
-	  BUGMSG2(D_INIT,"\n");
-	  BUGMSG(D_INIT,"Stage 2: ");
-	  numprint=1;
-	}
-      BUGMSG2(D_INIT,"%Xh ",*port);
-    }
-  BUGMSG2(D_INIT,"\n");
-  JIFFER(RESETtime);
-
-  /* Stage 3: abandon any shmem addresses that don't have the signature
-   * 0xD1 byte in the right place, or are read-only.
-   */
-  BUGMSG(D_INIT,"Stage 3: ");
-  numprint=0;
-  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-    {
-      u_long ptr;
-
-      numprint++;
-      if (numprint>8)
-	{
-	  BUGMSG2(D_INIT,"\n");
-	  BUGMSG(D_INIT,"Stage 3: ");
-	  numprint=1;
-	}
-      BUGMSG2(D_INIT,"%lXh ",*shmem);
-
-      ptr=(u_long)(*shmem);
-
-      if (readb(ptr) != TESTvalue)
-	{
-	  BUGMSG2(D_INIT_REASONS,"(mem=%02Xh, not %02Xh)\n",
-		  readb(ptr),TESTvalue);
-	  BUGMSG(D_INIT_REASONS,"Stage 3: ");
-	  BUGLVL(D_INIT_REASONS) numprint=0;
-	  *shmem=shmems[numshmems-1];
-	  numshmems--;
-	  shmem--;
-	  continue;
-	}
-
-      /* By writing 0x42 to the TESTvalue location, we also make
-       * sure no "mirror" shmem areas show up - if they occur
-       * in another pass through this loop, they will be discarded
-       * because *cptr != TESTvalue.
-       */
-      writeb(0x42,ptr);
-      if (readb(ptr) != 0x42)
-	{
-	  BUGMSG2(D_INIT_REASONS,"(read only)\n");
-	  BUGMSG(D_INIT_REASONS,"Stage 3: ");
-	  *shmem=shmems[numshmems-1];
-	  numshmems--;
-	  shmem--;
-	  continue;
-	}
-
-      BUGMSG2(D_INIT_REASONS,"\n");
-      BUGMSG(D_INIT_REASONS,"Stage 3: ");
-      BUGLVL(D_INIT_REASONS) numprint=0;
-    }
-  BUGMSG2(D_INIT,"\n");
-
-  if (!numshmems)
-    {
-      BUGMSG(D_NORMAL,"Stage 3: No ARCnet cards found.\n");
-      return -ENODEV;
-    }
-
-  /* Stage 4: something of a dummy, to report the shmems that are
-   * still possible after stage 3.
-   */
-  BUGMSG(D_INIT,"Stage 4: ");
-  numprint=0;
-  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-    {
-      numprint++;
-      if (numprint>8)
-	{
-	  BUGMSG2(D_INIT,"\n");
-	  BUGMSG(D_INIT,"Stage 4: ");
-	  numprint=1;
-	}
-      BUGMSG2(D_INIT,"%lXh ",*shmem);
-    }
-  BUGMSG2(D_INIT,"\n");
-
-  /* Stage 5: for any ports that have the correct status, can disable
-   * the RESET flag, and (if no irq is given) generate an autoirq,
-   * register an ARCnet device.
-   *
-   * Currently, we can only register one device per probe, so quit
-   * after the first one is found.
-   */
-  BUGMSG(D_INIT,"Stage 5: ");
-  numprint=0;
-  for (port = &ports[0]; port-ports<numports; port++)
-    {
-      numprint++;
-      if (numprint>8)
-	{
-	  BUGMSG2(D_INIT,"\n");
-	  BUGMSG(D_INIT,"Stage 5: ");
-	  numprint=1;
-	}
-      BUGMSG2(D_INIT,"%Xh ",*port);
-
-      ioaddr=*port;
-      status=ARCSTATUS;
-
-      if ((status & 0x9D)
-	  != (NORXflag|RECONflag|TXFREEflag|RESETflag))
-	{
-	  BUGMSG2(D_INIT_REASONS,"(status=%Xh)\n",status);
-	  BUGMSG(D_INIT_REASONS,"Stage 5: ");
-	  BUGLVL(D_INIT_REASONS) numprint=0;
-	  *port=ports[numports-1];
-	  numports--;
-	  port--;
-	  continue;
-	}
-
-      ACOMMAND(CFLAGScmd|RESETclear|CONFIGclear);
-      status=ARCSTATUS;
-      if (status & RESETflag)
-	{
-	  BUGMSG2(D_INIT_REASONS," (eternal reset, status=%Xh)\n",
-		  status);
-	  BUGMSG(D_INIT_REASONS,"Stage 5: ");
-	  BUGLVL(D_INIT_REASONS) numprint=0;
-	  *port=ports[numports-1];
-	  numports--;
-	  port--;
-	  continue;
-	}
-
-      /* skip this completely if an IRQ was given, because maybe
-       * we're on a machine that locks during autoirq!
-       */
-      if (!dev->irq)
-	{
-	  /* if we do this, we're sure to get an IRQ since the
-	   * card has just reset and the NORXflag is on until
-	   * we tell it to start receiving.
-	   */
-	  airqmask = probe_irq_on();
-	  AINTMASK(NORXflag);
-	  udelay(1);
-	  AINTMASK(0);
-	  airq = probe_irq_off(airqmask);
-
-	  if (airq<=0)
-	    {
-	      BUGMSG2(D_INIT_REASONS,"(airq=%d)\n",airq);
-	      BUGMSG(D_INIT_REASONS,"Stage 5: ");
-	      BUGLVL(D_INIT_REASONS) numprint=0;
-	      *port=ports[numports-1];
-	      numports--;
-	      port--;
-	      continue;
-	    }
-	}
-      else
-	{
-	  airq=dev->irq;
-	}
-
-      BUGMSG2(D_INIT,"(%d,", airq);
-      openparen=1;
-
-      /* Everything seems okay.  But which shmem, if any, puts
-       * back its signature byte when the card is reset?
-       *
-       * If there are multiple cards installed, there might be
-       * multiple shmems still in the list.
-       */
-#ifdef FAST_PROBE
-      if (numports>1 || numshmems>1)
-	{
-	  ARCRESET;
-	  JIFFER(RESETtime);
-	}
-      else
-	{
-	  /* just one shmem and port, assume they match */
-	  writeb(TESTvalue,shmems[0]);
+	static int init_once = 0;
+	static int numports = sizeof(ports) / sizeof(ports[0]), numshmems = sizeof(shmems) / sizeof(shmems[0]);
+	int count, status, delayval, ioaddr, numprint, airq, retval = -ENODEV,
+	 openparen = 0;
+	unsigned long airqmask;
+	int *port;
+	u_long *shmem;
+
+	if (!init_once) {
+		for (count = 0x200; count <= 0x3f0; count += 16)
+			ports[(count - 0x200) / 16] = count;
+		for (count = 0xA0000; count <= 0xFF800; count += 2048)
+			shmems[(count - 0xA0000) / 2048] = count;
+		BUGLVL(D_NORMAL) printk(version);
+		BUGMSG(D_DURING, "space used for probe buffers: %d+%d=%d bytes\n",
+		       sizeof(ports), sizeof(shmems),
+		       sizeof(ports) + sizeof(shmems));
+	}
+	init_once++;
+
+	BUGMSG(D_INIT, "given: base %lXh, IRQ %d, shmem %lXh\n",
+	       dev->base_addr, dev->irq, dev->mem_start);
+
+	if (dev->base_addr > 0x1ff) {	/* Check a single specified port */
+		ports[0] = dev->base_addr;
+		numports = 1;
+	} else if (dev->base_addr > 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+	if (dev->mem_start) {
+		shmems[0] = dev->mem_start;
+		numshmems = 1;
+	}
+	/* Stage 1: abandon any reserved ports, or ones with status==0xFF
+	 * (empty), and reset any others by reading the reset port.
+	 */
+	BUGMSG(D_INIT, "Stage 1: ");
+	numprint = 0;
+	for (port = &ports[0]; port - ports < numports; port++) {
+		numprint++;
+		if (numprint > 8) {
+			BUGMSG2(D_INIT, "\n");
+			BUGMSG(D_INIT, "Stage 1: ");
+			numprint = 1;
+		}
+		BUGMSG2(D_INIT, "%Xh ", *port);
+
+		ioaddr = *port;
+
+		if (check_region(*port, ARCNET_TOTAL_SIZE)) {
+			BUGMSG2(D_INIT_REASONS, "(check_region)\n");
+			BUGMSG(D_INIT_REASONS, "Stage 1: ");
+			BUGLVL(D_INIT_REASONS) numprint = 0;
+			*port = ports[numports - 1];
+			numports--;
+			port--;
+			continue;
+		}
+		if (ARCSTATUS == 0xFF) {
+			BUGMSG2(D_INIT_REASONS, "(empty)\n");
+			BUGMSG(D_INIT_REASONS, "Stage 1: ");
+			BUGLVL(D_INIT_REASONS) numprint = 0;
+			*port = ports[numports - 1];
+			numports--;
+			port--;
+			continue;
+		}
+		ARCRESET;	/* begin resetting card */
+
+		BUGMSG2(D_INIT_REASONS, "\n");
+		BUGMSG(D_INIT_REASONS, "Stage 1: ");
+		BUGLVL(D_INIT_REASONS) numprint = 0;
+	}
+	BUGMSG2(D_INIT, "\n");
+
+	if (!numports) {
+		BUGMSG(D_NORMAL, "Stage 1: No ARCnet cards found.\n");
+		return -ENODEV;
+	}
+	/* Stage 2: we have now reset any possible ARCnet cards, so we can't
+	 * do anything until they finish.  If D_INIT, print the list of
+	 * cards that are left.
+	 */
+	BUGMSG(D_INIT, "Stage 2: ");
+	numprint = 0;
+	for (port = &ports[0]; port - ports < numports; port++) {
+		numprint++;
+		if (numprint > 8) {
+			BUGMSG2(D_INIT, "\n");
+			BUGMSG(D_INIT, "Stage 2: ");
+			numprint = 1;
+		}
+		BUGMSG2(D_INIT, "%Xh ", *port);
+	}
+	BUGMSG2(D_INIT, "\n");
+	JIFFER(RESETtime);
+
+	/* Stage 3: abandon any shmem addresses that don't have the signature
+	 * 0xD1 byte in the right place, or are read-only.
+	 */
+	BUGMSG(D_INIT, "Stage 3: ");
+	numprint = 0;
+	for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) {
+		u_long ptr;
+
+		numprint++;
+		if (numprint > 8) {
+			BUGMSG2(D_INIT, "\n");
+			BUGMSG(D_INIT, "Stage 3: ");
+			numprint = 1;
+		}
+		BUGMSG2(D_INIT, "%lXh ", *shmem);
+
+		ptr = (u_long) (*shmem);
+
+		if (readb(ptr) != TESTvalue) {
+			BUGMSG2(D_INIT_REASONS, "(mem=%02Xh, not %02Xh)\n",
+				readb(ptr), TESTvalue);
+			BUGMSG(D_INIT_REASONS, "Stage 3: ");
+			BUGLVL(D_INIT_REASONS) numprint = 0;
+			*shmem = shmems[numshmems - 1];
+			numshmems--;
+			shmem--;
+			continue;
+		}
+		/* By writing 0x42 to the TESTvalue location, we also make
+		 * sure no "mirror" shmem areas show up - if they occur
+		 * in another pass through this loop, they will be discarded
+		 * because *cptr != TESTvalue.
+		 */
+		writeb(0x42, ptr);
+		if (readb(ptr) != 0x42) {
+			BUGMSG2(D_INIT_REASONS, "(read only)\n");
+			BUGMSG(D_INIT_REASONS, "Stage 3: ");
+			*shmem = shmems[numshmems - 1];
+			numshmems--;
+			shmem--;
+			continue;
+		}
+		BUGMSG2(D_INIT_REASONS, "\n");
+		BUGMSG(D_INIT_REASONS, "Stage 3: ");
+		BUGLVL(D_INIT_REASONS) numprint = 0;
+	}
+	BUGMSG2(D_INIT, "\n");
+
+	if (!numshmems) {
+		BUGMSG(D_NORMAL, "Stage 3: No ARCnet cards found.\n");
+		return -ENODEV;
+	}
+	/* Stage 4: something of a dummy, to report the shmems that are
+	 * still possible after stage 3.
+	 */
+	BUGMSG(D_INIT, "Stage 4: ");
+	numprint = 0;
+	for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) {
+		numprint++;
+		if (numprint > 8) {
+			BUGMSG2(D_INIT, "\n");
+			BUGMSG(D_INIT, "Stage 4: ");
+			numprint = 1;
+		}
+		BUGMSG2(D_INIT, "%lXh ", *shmem);
 	}
+	BUGMSG2(D_INIT, "\n");
+
+	/* Stage 5: for any ports that have the correct status, can disable
+	 * the RESET flag, and (if no irq is given) generate an autoirq,
+	 * register an ARCnet device.
+	 *
+	 * Currently, we can only register one device per probe, so quit
+	 * after the first one is found.
+	 */
+	BUGMSG(D_INIT, "Stage 5: ");
+	numprint = 0;
+	for (port = &ports[0]; port - ports < numports; port++) {
+		numprint++;
+		if (numprint > 8) {
+			BUGMSG2(D_INIT, "\n");
+			BUGMSG(D_INIT, "Stage 5: ");
+			numprint = 1;
+		}
+		BUGMSG2(D_INIT, "%Xh ", *port);
+
+		ioaddr = *port;
+		status = ARCSTATUS;
+
+		if ((status & 0x9D)
+		    != (NORXflag | RECONflag | TXFREEflag | RESETflag)) {
+			BUGMSG2(D_INIT_REASONS, "(status=%Xh)\n", status);
+			BUGMSG(D_INIT_REASONS, "Stage 5: ");
+			BUGLVL(D_INIT_REASONS) numprint = 0;
+			*port = ports[numports - 1];
+			numports--;
+			port--;
+			continue;
+		}
+		ACOMMAND(CFLAGScmd | RESETclear | CONFIGclear);
+		status = ARCSTATUS;
+		if (status & RESETflag) {
+			BUGMSG2(D_INIT_REASONS, " (eternal reset, status=%Xh)\n",
+				status);
+			BUGMSG(D_INIT_REASONS, "Stage 5: ");
+			BUGLVL(D_INIT_REASONS) numprint = 0;
+			*port = ports[numports - 1];
+			numports--;
+			port--;
+			continue;
+		}
+		/* skip this completely if an IRQ was given, because maybe
+		 * we're on a machine that locks during autoirq!
+		 */
+		if (!dev->irq) {
+			/* if we do this, we're sure to get an IRQ since the
+			 * card has just reset and the NORXflag is on until
+			 * we tell it to start receiving.
+			 */
+			airqmask = probe_irq_on();
+			AINTMASK(NORXflag);
+			udelay(1);
+			AINTMASK(0);
+			airq = probe_irq_off(airqmask);
+
+			if (airq <= 0) {
+				BUGMSG2(D_INIT_REASONS, "(airq=%d)\n", airq);
+				BUGMSG(D_INIT_REASONS, "Stage 5: ");
+				BUGLVL(D_INIT_REASONS) numprint = 0;
+				*port = ports[numports - 1];
+				numports--;
+				port--;
+				continue;
+			}
+		} else {
+			airq = dev->irq;
+		}
+
+		BUGMSG2(D_INIT, "(%d,", airq);
+		openparen = 1;
+
+		/* Everything seems okay.  But which shmem, if any, puts
+		 * back its signature byte when the card is reset?
+		 *
+		 * If there are multiple cards installed, there might be
+		 * multiple shmems still in the list.
+		 */
+#ifdef FAST_PROBE
+		if (numports > 1 || numshmems > 1) {
+			ARCRESET;
+			JIFFER(RESETtime);
+		} else {
+			/* just one shmem and port, assume they match */
+			writeb(TESTvalue, shmems[0]);
+		}
 #else
-      ARCRESET;
-      JIFFER(RESETtime);
+		ARCRESET;
+		JIFFER(RESETtime);
 #endif
 
-      for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-	{
-	  u_long ptr;
-	  ptr=(u_long)(*shmem);
-
-	  if (readb(ptr) == TESTvalue)	/* found one */
-	    {
-	      int probe_more;
-	      BUGMSG2(D_INIT,"%lXh)\n", *shmem);
-	      openparen=0;
-
-	      /* register the card */
-	      if (init_once == 1 && numshmems > 1)
-		probe_more = numshmems - 1;
-	      else
-		probe_more = 0;
-	      retval=arc90xx_found(dev,*port,airq,*shmem,probe_more);
-	      if (retval) openparen=0;
-
-	      /* remove shmem from the list */
-	      *shmem=shmems[numshmems-1];
-	      numshmems--;
-
-	      break;
-	    }
-	  else
-	    {
-	      BUGMSG2(D_INIT_REASONS,"%Xh-", readb(ptr));
-	    }
-	}
-
-      if (openparen)
-	{
-	  BUGMSG2(D_INIT,"no matching shmem)\n");
-	  BUGMSG(D_INIT_REASONS,"Stage 5: ");
-	  BUGLVL(D_INIT_REASONS) numprint=0;
-	}
-
-      *port=ports[numports-1];
-      numports--;
-      port--;
-
-      if (!retval) break;
-    }
-  BUGMSG(D_INIT_REASONS,"\n");
-
-  /* Now put back TESTvalue on all leftover shmems.
-   */
-  for (shmem = &shmems[0]; shmem-shmems<numshmems; shmem++)
-    writeb(TESTvalue,*shmem);
+		for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++) {
+			u_long ptr;
+			ptr = (u_long) (*shmem);
+
+			if (readb(ptr) == TESTvalue) {	/* found one */
+				int probe_more;
+				BUGMSG2(D_INIT, "%lXh)\n", *shmem);
+				openparen = 0;
+
+				/* register the card */
+				if (init_once == 1 && numshmems > 1)
+					probe_more = numshmems - 1;
+				else
+					probe_more = 0;
+				retval = arc90xx_found(dev, *port, airq, *shmem, probe_more);
+				if (retval)
+					openparen = 0;
+
+				/* remove shmem from the list */
+				*shmem = shmems[numshmems - 1];
+				numshmems--;
+
+				break;
+			} else {
+				BUGMSG2(D_INIT_REASONS, "%Xh-", readb(ptr));
+			}
+		}
 
-  if (retval) BUGMSG(D_NORMAL,"Stage 5: No ARCnet cards found.\n");
-  return retval;
+		if (openparen) {
+			BUGMSG2(D_INIT, "no matching shmem)\n");
+			BUGMSG(D_INIT_REASONS, "Stage 5: ");
+			BUGLVL(D_INIT_REASONS) numprint = 0;
+		}
+		*port = ports[numports - 1];
+		numports--;
+		port--;
+
+		if (!retval)
+			break;
+	}
+	BUGMSG(D_INIT_REASONS, "\n");
+
+	/* Now put back TESTvalue on all leftover shmems.
+	 */
+	for (shmem = &shmems[0]; shmem - shmems < numshmems; shmem++)
+		writeb(TESTvalue, *shmem);
+
+	if (retval)
+		BUGMSG(D_NORMAL, "Stage 5: No ARCnet cards found.\n");
+	return retval;
 }
 
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
-__initfunc(static int arc90xx_found(struct device *dev,int ioaddr,int airq, u_long shmem, int more))
+__initfunc(static int arc90xx_found(struct device *dev, int ioaddr, int airq, u_long shmem, int more))
 {
-  struct arcnet_local *lp;
-  u_long first_mirror,last_mirror;
-  int mirror_size;
-
-  /* reserve the irq */
-  if (request_irq(airq,&arcnet_interrupt,0,"arcnet (90xx)",dev))
-    {
-      BUGMSG(D_NORMAL,"Can't get IRQ %d!\n",airq);
-      return -ENODEV;
-    }
-  dev->irq=airq;
-
-  /* reserve the I/O region - guaranteed to work by check_region */
-  request_region(ioaddr,ARCNET_TOTAL_SIZE,"arcnet (90xx)");
-  dev->base_addr=ioaddr;
+	struct arcnet_local *lp;
+	u_long first_mirror, last_mirror;
+	int mirror_size;
+
+	/* reserve the irq */
+	if (request_irq(airq, &arcnet_interrupt, 0, "arcnet (90xx)", dev)) {
+		BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", airq);
+		return -ENODEV;
+	}
+	dev->irq = airq;
+
+	/* reserve the I/O region - guaranteed to work by check_region */
+	request_region(ioaddr, ARCNET_TOTAL_SIZE, "arcnet (90xx)");
+	dev->base_addr = ioaddr;
 
-  /* find the real shared memory start/end points, including mirrors */
+	/* find the real shared memory start/end points, including mirrors */
 #define BUFFER_SIZE (512)
 #define MIRROR_SIZE (BUFFER_SIZE*4)
 
-  /* guess the actual size of one "memory mirror" - the number of
-   * bytes between copies of the shared memory.  On most cards, it's
-   * 2k (or there are no mirrors at all) but on some, it's 4k.
-   */
-  mirror_size=MIRROR_SIZE;
-  if (readb(shmem)==TESTvalue
-      && readb(shmem-mirror_size)!=TESTvalue
-      && readb(shmem-2*mirror_size)==TESTvalue)
-    mirror_size*=2;
-
-  first_mirror=last_mirror=shmem;
-  while (readb(first_mirror)==TESTvalue) first_mirror-=mirror_size;
-  first_mirror+=mirror_size;
-
-  while (readb(last_mirror)==TESTvalue) last_mirror+=mirror_size;
-  last_mirror-=mirror_size;
-
-  dev->mem_start=first_mirror;
-  dev->mem_end=last_mirror+MIRROR_SIZE-1;
-  dev->rmem_start=dev->mem_start+BUFFER_SIZE*0;
-  dev->rmem_end=dev->mem_start+BUFFER_SIZE*2-1;
-
-  /* Initialize the rest of the device structure. */
-
-  dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
-  if (dev->priv == NULL)
-    {
-      free_irq(airq,dev);
-      release_region(ioaddr,ARCNET_TOTAL_SIZE);
-      return -ENOMEM;
-    }
-  memset(dev->priv,0,sizeof(struct arcnet_local));
-  lp=(struct arcnet_local *)(dev->priv);
-  lp->card_type = ARC_90xx;
-  lp->card_type_str = "COM 90xx";
-  lp->arcnet_reset=arc90xx_reset;
-  lp->asetmask=arc90xx_setmask;
-  lp->astatus=arc90xx_status;
-  lp->acommand=arc90xx_command;
-  lp->openclose_device=arc90xx_openclose;
-  lp->prepare_tx=arc90xx_prepare_tx;
-  lp->inthandler=arc90xx_inthandler;
-
-  /* Fill in the fields of the device structure with generic
-   * values.
-   */
-  arcnet_setup(dev);
-
-  /* And now fill particular fields with arcnet values */
-  dev->mtu=1500; /* completely arbitrary - agrees with ether, though */
-  dev->hard_header_len=sizeof(struct ClientData);
-  lp->sequence=1;
-  lp->recbuf=0;
-
-  BUGMSG(D_DURING,"ClientData header size is %d.\n",
-	 sizeof(struct ClientData));
-  BUGMSG(D_DURING,"HardHeader size is %d.\n",
-	 sizeof(struct archdr));
-
-  /* get and check the station ID from offset 1 in shmem */
-  lp->stationid = readb(first_mirror+1);
-
-  if (lp->stationid==0)
-    BUGMSG(D_NORMAL,"WARNING!  Station address 00 is reserved "
-	   "for broadcasts!\n");
-  else if (lp->stationid==255)
-    BUGMSG(D_NORMAL,"WARNING!  Station address FF may confuse "
-	   "DOS networking programs!\n");
-  dev->dev_addr[0]=lp->stationid;
-
-  BUGMSG(D_NORMAL,"ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, "
-	 "ShMem %lXh (%ld*%xh).\n",
-	 lp->stationid,
-	 dev->base_addr, dev->irq, dev->mem_start,
-	 (dev->mem_end-dev->mem_start+1)/mirror_size,mirror_size);
-
-  /* OK. We're finished. If there are probably other cards, add other
-   * COM90xx drivers to the device chain, so they get probed later.
-   */
+	/* guess the actual size of one "memory mirror" - the number of
+	 * bytes between copies of the shared memory.  On most cards, it's
+	 * 2k (or there are no mirrors at all) but on some, it's 4k.
+	 */
+	mirror_size = MIRROR_SIZE;
+	if (readb(shmem) == TESTvalue
+	    && readb(shmem - mirror_size) != TESTvalue
+	    && readb(shmem - 2 * mirror_size) == TESTvalue)
+		mirror_size *= 2;
+
+	first_mirror = last_mirror = shmem;
+	while (readb(first_mirror) == TESTvalue)
+		first_mirror -= mirror_size;
+	first_mirror += mirror_size;
+
+	while (readb(last_mirror) == TESTvalue)
+		last_mirror += mirror_size;
+	last_mirror -= mirror_size;
+
+	dev->mem_start = first_mirror;
+	dev->mem_end = last_mirror + MIRROR_SIZE - 1;
+	dev->rmem_start = dev->mem_start + BUFFER_SIZE * 0;
+	dev->rmem_end = dev->mem_start + BUFFER_SIZE * 2 - 1;
+
+	/* Initialize the rest of the device structure. */
+
+	dev->priv = kmalloc(sizeof(struct arcnet_local), GFP_KERNEL);
+	if (dev->priv == NULL) {
+		free_irq(airq, dev);
+		release_region(ioaddr, ARCNET_TOTAL_SIZE);
+		return -ENOMEM;
+	}
+	memset(dev->priv, 0, sizeof(struct arcnet_local));
+	lp = (struct arcnet_local *) (dev->priv);
+	lp->card_type = ARC_90xx;
+	lp->card_type_str = "COM 90xx";
+	lp->arcnet_reset = arc90xx_reset;
+	lp->asetmask = arc90xx_setmask;
+	lp->astatus = arc90xx_status;
+	lp->acommand = arc90xx_command;
+	lp->openclose_device = arc90xx_openclose;
+	lp->prepare_tx = arc90xx_prepare_tx;
+	lp->inthandler = arc90xx_inthandler;
+
+	/* Fill in the fields of the device structure with generic
+	 * values.
+	 */
+	arcnet_setup(dev);
+
+	/* And now fill particular fields with arcnet values */
+	dev->mtu = 1500;	/* completely arbitrary - agrees with ether, though */
+	dev->hard_header_len = sizeof(struct ClientData);
+	lp->sequence = 1;
+	lp->recbuf = 0;
+
+	BUGMSG(D_DURING, "ClientData header size is %d.\n",
+	       sizeof(struct ClientData));
+	BUGMSG(D_DURING, "HardHeader size is %d.\n",
+	       sizeof(struct archdr));
+
+	/* get and check the station ID from offset 1 in shmem */
+	lp->stationid = readb(first_mirror + 1);
+
+	if (lp->stationid == 0)
+		BUGMSG(D_NORMAL, "WARNING!  Station address 00 is reserved "
+		       "for broadcasts!\n");
+	else if (lp->stationid == 255)
+		BUGMSG(D_NORMAL, "WARNING!  Station address FF may confuse "
+		       "DOS networking programs!\n");
+	dev->dev_addr[0] = lp->stationid;
+
+	BUGMSG(D_NORMAL, "ARCnet COM90xx: station %02Xh found at %03lXh, IRQ %d, "
+	       "ShMem %lXh (%ld*%xh).\n",
+	       lp->stationid,
+	       dev->base_addr, dev->irq, dev->mem_start,
+	 (dev->mem_end - dev->mem_start + 1) / mirror_size, mirror_size);
+
+	/* OK. We're finished. If there are probably other cards, add other
+	 * COM90xx drivers to the device chain, so they get probed later.
+	 */
 
 #ifndef MODULE
-  while (!com90xx_explicit && more--)
-    {
-      if (arcnet_num_devs < MAX_ARCNET_DEVS)
-	{
-	  arcnet_devs[arcnet_num_devs].next=dev->next;
-	  dev->next=&arcnet_devs[arcnet_num_devs];
-	  dev=dev->next;
-	  dev->name=(char *)&arcnet_dev_names[arcnet_num_devs];
-	  arcnet_num_devs++;
-	}
-      else
-	{
-	  BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n");
-	  return 0;
-	}
-      arcnet_makename(dev->name);
-      dev->init=arc90xx_probe;
-    }
+	while (!com90xx_explicit && more--) {
+		if (arcnet_num_devs < MAX_ARCNET_DEVS) {
+			arcnet_devs[arcnet_num_devs].next = dev->next;
+			dev->next = &arcnet_devs[arcnet_num_devs];
+			dev = dev->next;
+			dev->name = (char *) &arcnet_dev_names[arcnet_num_devs];
+			arcnet_num_devs++;
+		} else {
+			BUGMSG(D_NORMAL, "Too many arcnet devices - no more will be probed for.\n");
+			return 0;
+		}
+		arcnet_makename(dev->name);
+		dev->init = arc90xx_probe;
+	}
 #endif
 
-  return 0;
+	return 0;
 }
 
 
 /* Do a hardware reset on the card, and set up necessary registers.
- *
+
  * This should be called as little as possible, because it disrupts the
  * token on the network (causes a RECON) and requires a significant delay.
  *
  * However, it does make sure the card is in a defined state.
  */
-int arc90xx_reset(struct device *dev,int reset_delay)
+int arc90xx_reset(struct device *dev, int reset_delay)
 {
-  struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-  short ioaddr=dev->base_addr;
-  int delayval,recbuf=lp->recbuf;
-
-  if (reset_delay==3)
-    {
-      ARCRESET;
-      return 0;
-    }
-
-  /* no IRQ's, please! */
-  lp->intmask=0;
-  SETMASK;
-
-  BUGMSG(D_INIT,"Resetting %s (status=%Xh)\n",
-	 dev->name,ARCSTATUS);
-
-  if (reset_delay)
-    {
-      /* reset the card */
-      ARCRESET;
-      JIFFER(RESETtime);
-    }
-
-  ACOMMAND(CFLAGScmd|RESETclear); /* clear flags & end reset */
-  ACOMMAND(CFLAGScmd|CONFIGclear);
-
-  /* verify that the ARCnet signature byte is present */
-  if (readb(dev->mem_start) != TESTvalue)
-    {
-      BUGMSG(D_NORMAL,"reset failed: TESTvalue not present.\n");
-      return 1;
-    }
-
-  /* clear out status variables */
-  recbuf=lp->recbuf=0;
-  lp->txbuf=2;
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	short ioaddr = dev->base_addr;
+	int delayval, recbuf = lp->recbuf;
+
+	if (reset_delay == 3) {
+		ARCRESET;
+		return 0;
+	}
+	/* no IRQ's, please! */
+	lp->intmask = 0;
+	SETMASK;
+
+	BUGMSG(D_INIT, "Resetting %s (status=%Xh)\n",
+	       dev->name, ARCSTATUS);
+
+	if (reset_delay) {
+		/* reset the card */
+		ARCRESET;
+		JIFFER(RESETtime);
+	}
+	ACOMMAND(CFLAGScmd | RESETclear);	/* clear flags & end reset */
+	ACOMMAND(CFLAGScmd | CONFIGclear);
+
+	/* verify that the ARCnet signature byte is present */
+	if (readb(dev->mem_start) != TESTvalue) {
+		BUGMSG(D_NORMAL, "reset failed: TESTvalue not present.\n");
+		return 1;
+	}
+	/* clear out status variables */
+	recbuf = lp->recbuf = 0;
+	lp->txbuf = 2;
 
-  /* enable extended (512-byte) packets */
-  ACOMMAND(CONFIGcmd|EXTconf);
+	/* enable extended (512-byte) packets */
+	ACOMMAND(CONFIGcmd | EXTconf);
 
 #ifndef SLOW_XMIT_COPY
-  /* clean out all the memory to make debugging make more sense :) */
-  BUGLVL(D_DURING)
-    memset_io(dev->mem_start,0x42,2048);
+	/* clean out all the memory to make debugging make more sense :) */
+	BUGLVL(D_DURING)
+	    memset_io(dev->mem_start, 0x42, 2048);
 #endif
 
-  /* and enable receive of our first packet to the first buffer */
-  EnableReceiver();
+	/* and enable receive of our first packet to the first buffer */
+	EnableReceiver();
 
-  /* re-enable interrupts */
-  lp->intmask|=NORXflag;
+	/* re-enable interrupts */
+	lp->intmask |= NORXflag;
 #ifdef DETECT_RECONFIGS
-  lp->intmask|=RECONflag;
+	lp->intmask |= RECONflag;
 #endif
-  SETMASK;
+	SETMASK;
 
-  /* done!  return success. */
-  return 0;
+	/* done!  return success. */
+	return 0;
 }
 
 
 static void arc90xx_openclose(int open)
 {
- if (open)
-   MOD_INC_USE_COUNT;
- else
-   MOD_DEC_USE_COUNT;
+	if (open)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
 }
 
 
 static void arc90xx_setmask(struct device *dev, u_char mask)
 {
-  short ioaddr=dev->base_addr;
+	short ioaddr = dev->base_addr;
 
-  AINTMASK(mask);
+	AINTMASK(mask);
 }
 
 
 static u_char arc90xx_status(struct device *dev)
 {
-  short ioaddr=dev->base_addr;
+	short ioaddr = dev->base_addr;
 
-  return ARCSTATUS;
+	return ARCSTATUS;
 }
 
 
 static void arc90xx_command(struct device *dev, u_char cmd)
 {
-  short ioaddr=dev->base_addr;
+	short ioaddr = dev->base_addr;
 
-  ACOMMAND(cmd);
+	ACOMMAND(cmd);
 }
 
 
 /* The actual interrupt handler routine - handle various IRQ's generated
  * by the card.
  */
-static void
-arc90xx_inthandler(struct device *dev)
+static void arc90xx_inthandler(struct device *dev)
 {
-  struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
-  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;
-
-  AINTMASK(0);
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	int ioaddr = dev->base_addr, status, boguscount = 3, didsomething;
 
-  BUGMSG(D_DURING,"in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
-	 ARCSTATUS,lp->intmask);
+	AINTMASK(0);
 
-  do
-    {
-      status = ARCSTATUS;
-      didsomething=0;
+	BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",
+	       ARCSTATUS, lp->intmask);
 
-      /* RESET flag was enabled - card is resetting and if RX
-       * is disabled, it's NOT because we just got a packet.
-       */
-      if (status & RESETflag)
-	{
-	  BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",
-		 status);
-	  arc90xx_reset(dev,0);
+	do {
+		status = ARCSTATUS;
+		didsomething = 0;
+
+		/* RESET flag was enabled - card is resetting and if RX
+		 * is disabled, it's NOT because we just got a packet.
+		 */
+		if (status & RESETflag) {
+			BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n",
+			       status);
+			arc90xx_reset(dev, 0);
 
-	  /* all other flag values are just garbage */
-	  break;
-	}
-
-      /* RX is inhibited - we must have received something. */
-      if (status & lp->intmask & NORXflag)
-	{
-	  int recbuf=lp->recbuf=!lp->recbuf;
-
-	  BUGMSG(D_DURING,"receive irq (status=%Xh)\n",
-		 status);
-
-	  /* enable receive of our next packet */
-	  EnableReceiver();
-
-	  /* Got a packet. */
-	  arc90xx_rx(dev,!recbuf);
-
-	  didsomething++;
-	}
-
-      /* it can only be an xmit-done irq if we're xmitting :) */
-      /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/
-      if (status & lp->intmask & TXFREEflag)
-	{
-	  struct Outgoing *out=&(lp->outgoing);
-	  int was_sending=lp->sending;
+			/* all other flag values are just garbage */
+			break;
+		}
+		/* RX is inhibited - we must have received something. */
+		if (status & lp->intmask & NORXflag) {
+			int recbuf = lp->recbuf = !lp->recbuf;
 
-	  lp->intmask &= ~TXFREEflag;
+			BUGMSG(D_DURING, "receive irq (status=%Xh)\n",
+			       status);
 
-	  lp->in_txhandler++;
-	  if (was_sending) lp->sending--;
+			/* enable receive of our next packet */
+			EnableReceiver();
 
-	  BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
-		 status,out->numsegs,out->segnum,out->skb);
+			/* Got a packet. */
+			arc90xx_rx(dev, !recbuf);
 
-	  if (was_sending && !(status&TXACKflag))
-	    {
-	      if (lp->lasttrans_dest != 0)
-		{
-		  BUGMSG(D_EXTRA,"transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
-			 status,lp->lasttrans_dest);
-		  lp->stats.tx_errors++;
-		  lp->stats.tx_carrier_errors++;
+			didsomething++;
 		}
-	      else
-		{
-		  BUGMSG(D_DURING,"broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
-			 status,
-			 lp->lasttrans_dest);
+		/* it can only be an xmit-done irq if we're xmitting :) */
+		/*if (status&TXFREEflag && !lp->in_txhandler && lp->sending) */
+		if (status & lp->intmask & TXFREEflag) {
+			struct Outgoing *out = &(lp->outgoing);
+			int was_sending = lp->sending;
+
+			lp->intmask &= ~TXFREEflag;
+
+			lp->in_txhandler++;
+			if (was_sending)
+				lp->sending--;
+
+			BUGMSG(D_DURING, "TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",
+			    status, out->numsegs, out->segnum, out->skb);
+
+			if (was_sending && !(status & TXACKflag)) {
+				if (lp->lasttrans_dest != 0) {
+					BUGMSG(D_EXTRA, "transmit was not acknowledged! (status=%Xh, dest=%02Xh)\n",
+					     status, lp->lasttrans_dest);
+					lp->stats.tx_errors++;
+					lp->stats.tx_carrier_errors++;
+				} else {
+					BUGMSG(D_DURING, "broadcast was not acknowledged; that's normal (status=%Xh, dest=%02Xh)\n",
+					       status,
+					       lp->lasttrans_dest);
+				}
+			}
+			/* send packet if there is one */
+			arcnet_go_tx(dev, 0);
+			didsomething++;
+
+			if (lp->intx) {
+				BUGMSG(D_DURING, "TXDONE while intx! (status=%Xh, intx=%d)\n",
+				       ARCSTATUS, lp->intx);
+				lp->in_txhandler--;
+				continue;
+			}
+			if (!lp->outgoing.skb) {
+				BUGMSG(D_DURING, "TX IRQ done: no split to continue.\n");
+
+				/* inform upper layers */
+				if (!lp->txready)
+					arcnet_tx_done(dev, lp);
+				lp->in_txhandler--;
+				continue;
+			}
+			/* if more than one segment, and not all segments
+			 * are done, then continue xmit.
+			 */
+			if (out->segnum < out->numsegs)
+				arcnetA_continue_tx(dev);
+			arcnet_go_tx(dev, 0);
+
+			/* if segnum==numsegs, the transmission is finished;
+			 * free the skb.
+			 */
+			if (out->segnum >= out->numsegs) {
+				/* transmit completed */
+				out->segnum++;
+				if (out->skb) {
+					lp->stats.tx_bytes += out->skb->len;
+					dev_kfree_skb(out->skb);
+				}
+				out->skb = NULL;
+
+				/* inform upper layers */
+				if (!lp->txready)
+					arcnet_tx_done(dev, lp);
+			}
+			didsomething++;
+
+			lp->in_txhandler--;
+		} else if (lp->txready && !lp->sending && !lp->intx) {
+			BUGMSG(D_NORMAL, "recovery from silent TX (status=%Xh)\n",
+			       status);
+			arcnet_go_tx(dev, 0);
+			didsomething++;
 		}
-	    }
-
-	  /* send packet if there is one */
-	  arcnet_go_tx(dev,0);
-	  didsomething++;
-
-	  if (lp->intx)
-	    {
-	      BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",
-		     ARCSTATUS,lp->intx);
-	      lp->in_txhandler--;
-	      continue;
-	    }
-
-	  if (!lp->outgoing.skb)
-	    {
-	      BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");
-
-	      /* inform upper layers */
-	      if (!lp->txready) arcnet_tx_done(dev, lp);
-	      lp->in_txhandler--;
-	      continue;
-	    }
-
-	  /* if more than one segment, and not all segments
-	   * are done, then continue xmit.
-	   */
-	  if (out->segnum<out->numsegs)
-	    arcnetA_continue_tx(dev);
-	  arcnet_go_tx(dev,0);
-
-	  /* if segnum==numsegs, the transmission is finished;
-	   * free the skb.
-	   */
-	  if (out->segnum>=out->numsegs)
-	    {
-	      /* transmit completed */
-	      out->segnum++;
-	      if (out->skb)
-		{
-		  lp->stats.tx_bytes += out->skb->len;
-		  dev_kfree_skb(out->skb);
-		}
-	      out->skb=NULL;
-
-	      /* inform upper layers */
-	      if (!lp->txready) arcnet_tx_done(dev, lp);
-	    }
-	  didsomething++;
-
-	  lp->in_txhandler--;
-	}
-      else if (lp->txready && !lp->sending && !lp->intx)
-	{
-	  BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",
-		 status);
-	  arcnet_go_tx(dev,0);
-	  didsomething++;
-	}
-
 #ifdef DETECT_RECONFIGS
-      if (status & (lp->intmask) & RECONflag)
-	{
-	  ACOMMAND(CFLAGScmd|CONFIGclear);
-	  lp->stats.tx_carrier_errors++;
+		if (status & (lp->intmask) & RECONflag) {
+			ACOMMAND(CFLAGScmd | CONFIGclear);
+			lp->stats.tx_carrier_errors++;
 
 #ifdef SHOW_RECONFIGS
-	  BUGMSG(D_NORMAL,"Network reconfiguration detected (status=%Xh)\n",
-		 status);
-#endif /* SHOW_RECONFIGS */
+			BUGMSG(D_NORMAL, "Network reconfiguration detected (status=%Xh)\n",
+			       status);
+#endif				/* SHOW_RECONFIGS */
 
 #ifdef RECON_THRESHOLD
-	  /* is the RECON info empty or old? */
-	  if (!lp->first_recon || !lp->last_recon ||
-	      jiffies-lp->last_recon > HZ*10)
-	    {
-	      if (lp->network_down)
-		BUGMSG(D_NORMAL,"reconfiguration detected: cabling restored?\n");
-	      lp->first_recon=lp->last_recon=jiffies;
-	      lp->num_recons=lp->network_down=0;
-
-	      BUGMSG(D_DURING,"recon: clearing counters.\n");
-	    }
-	  else /* add to current RECON counter */
-	    {
-	      lp->last_recon=jiffies;
-	      lp->num_recons++;
-
-	      BUGMSG(D_DURING,"recon: counter=%d, time=%lds, net=%d\n",
-		     lp->num_recons,
-		     (lp->last_recon-lp->first_recon)/HZ,
-		     lp->network_down);
-
-	      /* if network is marked up;
-	       * and first_recon and last_recon are 60+ sec
-	       *   apart;
-	       * and the average no. of recons counted is
-	       *   > RECON_THRESHOLD/min;
-	       * then print a warning message.
-	       */
-	      if (!lp->network_down
-		  && (lp->last_recon-lp->first_recon)<=HZ*60
-		  && lp->num_recons >= RECON_THRESHOLD)
-		{
-		  lp->network_down=1;
-		  BUGMSG(D_NORMAL,"many reconfigurations detected: cabling problem?\n");
-		}
-	      else if (!lp->network_down
-		       && lp->last_recon-lp->first_recon > HZ*60)
-		{
-		  /* reset counters if we've gone for
-		   * over a minute.
-		   */
-		  lp->first_recon=lp->last_recon;
-		  lp->num_recons=1;
-		}
-	    }
-	}
-      else if (lp->network_down && jiffies-lp->last_recon > HZ*10)
-	{
-	  if (lp->network_down)
-	    BUGMSG(D_NORMAL,"cabling restored?\n");
-	  lp->first_recon=lp->last_recon=0;
-	  lp->num_recons=lp->network_down=0;
+			/* is the RECON info empty or old? */
+			if (!lp->first_recon || !lp->last_recon ||
+			    jiffies - lp->last_recon > HZ * 10) {
+				if (lp->network_down)
+					BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");
+				lp->first_recon = lp->last_recon = jiffies;
+				lp->num_recons = lp->network_down = 0;
+
+				BUGMSG(D_DURING, "recon: clearing counters.\n");
+			} else {	/* add to current RECON counter */
+				lp->last_recon = jiffies;
+				lp->num_recons++;
+
+				BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n",
+				       lp->num_recons,
+				 (lp->last_recon - lp->first_recon) / HZ,
+				       lp->network_down);
+
+				/* if network is marked up;
+				 * and first_recon and last_recon are 60+ sec
+				 *   apart;
+				 * and the average no. of recons counted is
+				 *   > RECON_THRESHOLD/min;
+				 * then print a warning message.
+				 */
+				if (!lp->network_down
+				    && (lp->last_recon - lp->first_recon) <= HZ * 60
+				  && lp->num_recons >= RECON_THRESHOLD) {
+					lp->network_down = 1;
+					BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n");
+				} else if (!lp->network_down
+					   && lp->last_recon - lp->first_recon > HZ * 60) {
+					/* reset counters if we've gone for
+					 * over a minute.
+					 */
+					lp->first_recon = lp->last_recon;
+					lp->num_recons = 1;
+				}
+			}
+		} else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) {
+			if (lp->network_down)
+				BUGMSG(D_NORMAL, "cabling restored?\n");
+			lp->first_recon = lp->last_recon = 0;
+			lp->num_recons = lp->network_down = 0;
 
-	  BUGMSG(D_DURING,"not recon: clearing counters anyway.\n");
+			BUGMSG(D_DURING, "not recon: clearing counters anyway.\n");
 #endif
-	}
-#endif /* DETECT_RECONFIGS */
-    } while (--boguscount && didsomething);
+		}
+#endif				/* DETECT_RECONFIGS */
+	} while (--boguscount && didsomething);
 
-  BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",
-	 ARCSTATUS,boguscount);
-  BUGMSG(D_DURING,"\n");
+	BUGMSG(D_DURING, "net_interrupt complete (status=%Xh, count=%d)\n",
+	       ARCSTATUS, boguscount);
+	BUGMSG(D_DURING, "\n");
 
-  SETMASK;	/* put back interrupt mask */
+	SETMASK;		/* put back interrupt mask */
 }
 
 
@@ -987,57 +912,52 @@
  * arcnet_rx routing to deal with it.
  */
 
-static void
-arc90xx_rx(struct device *dev,int recbuf)
+static void arc90xx_rx(struct device *dev, int recbuf)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  int ioaddr=dev->base_addr;
-  union ArcPacket *arcpacket=
-    (union ArcPacket *)phys_to_virt(dev->mem_start+recbuf*512);
-  u_char *arcsoft;
-  short length,offset;
-  u_char daddr,saddr;
-
-  lp->stats.rx_packets++;
-
-  saddr=arcpacket->hardheader.source;
-
-  /* if source is 0, it's a "used" packet! */
-  if (saddr==0)
-    {
-      BUGMSG(D_NORMAL,"discarding old packet. (status=%Xh)\n",
-	     ARCSTATUS);
-      lp->stats.rx_errors++;
-      return;
-    }
-  /* Set source address to zero to mark it as old */
-
-  arcpacket->hardheader.source=0;
-
-  daddr=arcpacket->hardheader.destination;
-
-  if (arcpacket->hardheader.offset1) /* Normal Packet */
-    {
-      offset=arcpacket->hardheader.offset1;
-      arcsoft=&arcpacket->raw[offset];
-      length=256-offset;
-    }
-  else		/* ExtendedPacket or ExceptionPacket */
-    {
-      offset=arcpacket->hardheader.offset2;
-      arcsoft=&arcpacket->raw[offset];
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	int ioaddr = dev->base_addr;
+	union ArcPacket *arcpacket =
+	(union ArcPacket *) phys_to_virt(dev->mem_start + recbuf * 512);
+	u_char *arcsoft;
+	short length, offset;
+	u_char daddr, saddr;
 
-      length=512-offset;
-    }
+	lp->stats.rx_packets++;
 
-  arcnet_rx(lp, arcsoft, length, saddr, daddr);
+	saddr = arcpacket->hardheader.source;
 
-  BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");
+	/* if source is 0, it's a "used" packet! */
+	if (saddr == 0) {
+		BUGMSG(D_NORMAL, "discarding old packet. (status=%Xh)\n",
+		       ARCSTATUS);
+		lp->stats.rx_errors++;
+		return;
+	}
+	/* Set source address to zero to mark it as old */
+
+	arcpacket->hardheader.source = 0;
+
+	daddr = arcpacket->hardheader.destination;
+
+	if (arcpacket->hardheader.offset1) {	/* Normal Packet */
+		offset = arcpacket->hardheader.offset1;
+		arcsoft = &arcpacket->raw[offset];
+		length = 256 - offset;
+	} else {		/* ExtendedPacket or ExceptionPacket */
+		offset = arcpacket->hardheader.offset2;
+		arcsoft = &arcpacket->raw[offset];
+
+		length = 512 - offset;
+	}
+
+	arcnet_rx(lp, arcsoft, length, saddr, daddr);
+
+	BUGLVL(D_RX) arcnet_dump_packet(lp->adev, arcpacket->raw, length > 240, "rx");
 
 #ifndef SLOW_XMIT_COPY
-  /* clean out the page to make debugging make more sense :) */
-  BUGLVL(D_DURING)
-    memset((void *)arcpacket->raw,0x42,512);
+	/* clean out the page to make debugging make more sense :) */
+	BUGLVL(D_DURING)
+	    memset((void *) arcpacket->raw, 0x42, 512);
 #endif
 }
 
@@ -1045,91 +965,84 @@
 /* Given an skb, copy a packet into the ARCnet buffers for later transmission
  * by arcnet_go_tx.
  */
-static void
-arc90xx_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
-		char *data,int length,int daddr,int exceptA, int offset)
+static void arc90xx_prepare_tx(struct device *dev, u_char * hdr, int hdrlen,
+	      char *data, int length, int daddr, int exceptA, int offset)
 {
-  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-  union ArcPacket *arcpacket =
-    (union ArcPacket *)phys_to_virt(dev->mem_start+512*(lp->txbuf^1));
+	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	union ArcPacket *arcpacket =
+	(union ArcPacket *) phys_to_virt(dev->mem_start + 512 * (lp->txbuf ^ 1));
 
 #ifdef SLOW_XMIT_COPY
-  char *iptr,*iend,*optr;
+	char *iptr, *iend, *optr;
 #endif
 
-  lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */
+	lp->txbuf = lp->txbuf ^ 1;	/* XOR with 1 to alternate between 2 and 3 */
 
-  length+=hdrlen;
+	length += hdrlen;
 
-  BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
-	 hdr,length,data);
+	BUGMSG(D_TX, "arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",
+	       hdr, length, data);
 
 #ifndef SLOW_XMIT_COPY
-  /* clean out the page to make debugging make more sense :) */
-  BUGLVL(D_DURING)
-    memset_io(dev->mem_start+lp->txbuf*512,0x42,512);
+	/* clean out the page to make debugging make more sense :) */
+	BUGLVL(D_DURING)
+	    memset_io(dev->mem_start + lp->txbuf * 512, 0x42, 512);
 #endif
 
-  arcpacket->hardheader.destination=daddr;
+	arcpacket->hardheader.destination = daddr;
 
-  /* load packet into shared memory */
-  if (length<=MTU)	/* Normal (256-byte) Packet */
-    arcpacket->hardheader.offset1=offset=offset?offset:256-length;
-
-  else if (length>=MinTU || offset)	/* Extended (512-byte) Packet */
-    {
-       arcpacket->hardheader.offset1=0;
-       arcpacket->hardheader.offset2=offset=offset?offset:512-length;
-    }
-  else if (exceptA)		/* RFC1201 Exception Packet */
-    {
-       arcpacket->hardheader.offset1=0;
-       arcpacket->hardheader.offset2=offset=512-length-4;
-
-       /* exception-specific stuff - these four bytes
-	* make the packet long enough to fit in a 512-byte
-	* frame.
-	*/
-
-       arcpacket->raw[offset+0]=hdr[0];
-       arcpacket->raw[offset+1]=0xFF; /* FF flag */
-       arcpacket->raw[offset+2]=0xFF; /* FF padding */
-       arcpacket->raw[offset+3]=0xFF; /* FF padding */
-       offset+=4;
-    }
-  else				/* "other" Exception packet */
-    {
-      /* RFC1051 - set 4 trailing bytes to 0 */
-      memset(&arcpacket->raw[508],0,4);
-
-      /* now round up to MinTU */
-      arcpacket->hardheader.offset1=0;
-      arcpacket->hardheader.offset2=offset=512-MinTU;
-    }
-
-  /* copy the packet into ARCnet shmem
-   *  - the first bytes of ClientData header are skipped
-   */
+	/* load packet into shared memory */
+	if (length <= MTU)	/* Normal (256-byte) Packet */
+		arcpacket->hardheader.offset1 = offset = offset ? offset : 256 - length;
+
+	else if (length >= MinTU || offset) {	/* Extended (512-byte) Packet */
+		arcpacket->hardheader.offset1 = 0;
+		arcpacket->hardheader.offset2 = offset = offset ? offset : 512 - length;
+	} else if (exceptA) {	/* RFC1201 Exception Packet */
+		arcpacket->hardheader.offset1 = 0;
+		arcpacket->hardheader.offset2 = offset = 512 - length - 4;
+
+		/* exception-specific stuff - these four bytes
+		 * make the packet long enough to fit in a 512-byte
+		 * frame.
+		 */
+
+		arcpacket->raw[offset + 0] = hdr[0];
+		arcpacket->raw[offset + 1] = 0xFF;	/* FF flag */
+		arcpacket->raw[offset + 2] = 0xFF;	/* FF padding */
+		arcpacket->raw[offset + 3] = 0xFF;	/* FF padding */
+		offset += 4;
+	} else {		/* "other" Exception packet */
+		/* RFC1051 - set 4 trailing bytes to 0 */
+		memset(&arcpacket->raw[508], 0, 4);
+
+		/* now round up to MinTU */
+		arcpacket->hardheader.offset1 = 0;
+		arcpacket->hardheader.offset2 = offset = 512 - MinTU;
+	}
+
+	/* copy the packet into ARCnet shmem
+	 *  - the first bytes of ClientData header are skipped
+	 */
 
-  memcpy((u_char*)arcpacket+offset, (u_char*)hdr,hdrlen);
+	memcpy((u_char *) arcpacket + offset, (u_char *) hdr, hdrlen);
 #ifdef SLOW_XMIT_COPY
-  for (iptr=data,iend=iptr+length-hdrlen,optr=(char *)arcpacket+offset+hdrlen;
-       iptr<iend; iptr++,optr++)
-    {
-      *optr=*iptr;
-      /*udelay(5);*/
-    }
+	for (iptr = data, iend = iptr + length - hdrlen, optr = (char *) arcpacket + offset + hdrlen;
+	     iptr < iend; iptr++, optr++) {
+		*optr = *iptr;
+		/*udelay(5); */
+	}
 #else
-  memcpy((u_char*)arcpacket+offset+hdrlen, data,length-hdrlen);
+	memcpy((u_char *) arcpacket + offset + hdrlen, data, length - hdrlen);
 #endif
 
-  BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",
-	 daddr,length);
+	BUGMSG(D_DURING, "transmitting packet to station %02Xh (%d bytes)\n",
+	       daddr, length);
 
-  BUGLVL(D_TX) arcnet_dump_packet(dev,arcpacket->raw,length>MTU,"tx");
+	BUGLVL(D_TX) arcnet_dump_packet(dev, arcpacket->raw, length > MTU, "tx");
 
-  lp->lastload_dest=daddr;
-  lp->txready=lp->txbuf;	/* packet is ready for sending */
+	lp->lastload_dest = daddr;
+	lp->txready = lp->txbuf;	/* packet is ready for sending */
 }
 
 
@@ -1143,118 +1056,112 @@
 #ifdef MODULE
 
 static char devicename[9] = "";
-static struct device thiscard = {
-  devicename, /* device name is inserted by linux/drivers/net/net_init.c */
-  0, 0, 0, 0,
-  0, 0,  /* I/O address, IRQ */
-  0, 0, 0, NULL, arc90xx_probe
+static struct device thiscard =
+{
+	devicename,		/* device name is inserted by linux/drivers/net/net_init.c */
+	0, 0, 0, 0,
+	0, 0,			/* I/O address, IRQ */
+	0, 0, 0, NULL, arc90xx_probe
 };
 
 
 int init_module(void)
 {
-  struct device *dev=&thiscard;
-  if (device)
-    strcpy(dev->name,device);
-  else arcnet_makename(dev->name);
-
-  dev->base_addr=io;
-
-  dev->irq=irq;
-  if (dev->irq==2) dev->irq=9;
-
-  if (shmem)
-    {
-      dev->mem_start=shmem;
-      dev->mem_end=thiscard.mem_start+512*4-1;
-      dev->rmem_start=thiscard.mem_start+512*0;
-      dev->rmem_end=thiscard.mem_start+512*2-1;
-    }
-
-  if (register_netdev(dev) != 0)
-    return -EIO;
-  arcnet_use_count(1);
-  return 0;
+	struct device *dev = &thiscard;
+	if (device)
+		strcpy(dev->name, device);
+	else
+		arcnet_makename(dev->name);
+
+	dev->base_addr = io;
+
+	dev->irq = irq;
+	if (dev->irq == 2)
+		dev->irq = 9;
+
+	if (shmem) {
+		dev->mem_start = shmem;
+		dev->mem_end = thiscard.mem_start + 512 * 4 - 1;
+		dev->rmem_start = thiscard.mem_start + 512 * 0;
+		dev->rmem_end = thiscard.mem_start + 512 * 2 - 1;
+	}
+	if (register_netdev(dev) != 0)
+		return -EIO;
+	arcnet_use_count(1);
+	return 0;
 }
 
 void cleanup_module(void)
 {
-  struct device *dev=&thiscard;
-  int ioaddr=dev->mem_start;
+	struct device *dev = &thiscard;
+	int ioaddr = dev->mem_start;
 
-  if (dev->start) (*dev->stop)(dev);
+	if (dev->start)
+		(*dev->stop) (dev);
 
-  /* Flush TX and disable RX */
-  if (ioaddr)
-    {
-      AINTMASK(0);		/* disable IRQ's */
-      ACOMMAND(NOTXcmd);	/* stop transmit */
-      ACOMMAND(NORXcmd);	/* disable receive */
+	/* Flush TX and disable RX */
+	if (ioaddr) {
+		AINTMASK(0);	/* disable IRQ's */
+		ACOMMAND(NOTXcmd);	/* stop transmit */
+		ACOMMAND(NORXcmd);	/* disable receive */
 
 #if defined(IO_MAPPED_BUFFERS) && !defined(COM20020)
-      /* Set the thing back to MMAP mode, in case the old
-	 driver is loaded later */
-      outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);
+		/* Set the thing back to MMAP mode, in case the old
+		   driver is loaded later */
+		outb((inb(_CONFIG) & ~IOMAPflag), _CONFIG);
 #endif
-    }
-
-  if (dev->irq)
-    {
-      free_irq(dev->irq,dev);
-    }
-
-  if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);
-  unregister_netdev(dev);
-  kfree(dev->priv);
-  dev->priv = NULL;
-  arcnet_use_count(0);
+	}
+	if (dev->irq) {
+		free_irq(dev->irq, dev);
+	}
+	if (dev->base_addr)
+		release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
+	unregister_netdev(dev);
+	kfree(dev->priv);
+	dev->priv = NULL;
+	arcnet_use_count(0);
 }
 
 #else
 
-__initfunc(void com90xx_setup (char *str, int *ints))
+__initfunc(void com90xx_setup(char *str, int *ints))
 {
-  struct device *dev;
-
-  if (arcnet_num_devs == MAX_ARCNET_DEVS)
-    {
-      printk("com90xx: Too many ARCnet devices registered (max %d).\n",
-	     MAX_ARCNET_DEVS);
-      return;
-    }
+	struct device *dev;
 
-  if (!ints[0] && (!str || !*str))
-    {
-      printk("com90xx: Disabled.\n");
-      com90xx_explicit++;
-      return;
-    }
-
-  dev=&arcnet_devs[arcnet_num_devs];
+	if (arcnet_num_devs == MAX_ARCNET_DEVS) {
+		printk("com90xx: Too many ARCnet devices registered (max %d).\n",
+		       MAX_ARCNET_DEVS);
+		return;
+	}
+	if (!ints[0] && (!str || !*str)) {
+		printk("com90xx: Disabled.\n");
+		com90xx_explicit++;
+		return;
+	}
+	dev = &arcnet_devs[arcnet_num_devs];
 
-  dev->dev_addr[3]=3;
-  dev->init=arc90xx_probe;
+	dev->dev_addr[3] = 3;
+	dev->init = arc90xx_probe;
 
-  switch(ints[0])
-    {
-    case 4: /* ERROR */
-      printk("com20020: Too many arguments.\n");
+	switch (ints[0]) {
+	case 4:		/* ERROR */
+		printk("com20020: Too many arguments.\n");
 
-    case 3: /* Mem address */
-      dev->mem_start=ints[3];
+	case 3:		/* Mem address */
+		dev->mem_start = ints[3];
 
-    case 2: /* IRQ */
-      dev->irq=ints[2];
+	case 2:		/* IRQ */
+		dev->irq = ints[2];
 
-    case 1: /* IO address */
-      dev->base_addr=ints[1];
-    }
+	case 1:		/* IO address */
+		dev->base_addr = ints[1];
+	}
 
-  dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];
+	dev->name = (char *) &arcnet_dev_names[arcnet_num_devs];
 
-  if (str)
-    strncpy(dev->name, str, 9);
+	if (str)
+		strncpy(dev->name, str, 9);
 
-  arcnet_num_devs++;
+	arcnet_num_devs++;
 }
-#endif /* MODULE */
+#endif				/* MODULE */
diff -u --recursive --new-file v2.1.100/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.1.100/linux/drivers/net/defxx.c	Mon Apr  6 17:41:00 1998
+++ linux/drivers/net/defxx.c	Fri May  8 00:08:02 1998
@@ -2013,6 +2013,8 @@
 
 	bp->stats.rx_packets			= bp->rcv_total_frames;
 	bp->stats.tx_packets			= bp->xmt_total_frames;
+	bp->stats.rx_bytes			= bp->rcv_total_bytes;
+	bp->stats.tx_bytes			= bp->xmt_total_bytes;
 	bp->stats.rx_errors				= (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors);
 	bp->stats.tx_errors				= bp->xmt_length_errors;
 	bp->stats.rx_dropped			= bp->rcv_discards;
@@ -3099,6 +3101,8 @@
 					bp->rcv_total_frames++;
 					if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
 						bp->rcv_multicast_frames++;
+				 
+					bp->rcv_total_bytes += skb->len;
 				}
 			}
 			}
@@ -3375,13 +3379,14 @@
 
 		p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
 
-		/* Return skb to operating system */
-
-		dev_kfree_skb(p_xmt_drv_descr->p_skb);
-
 		/* Increment transmit counters */
 
 		bp->xmt_total_frames++;
+		bp->xmt_total_bytes += p_xmt_drv_descr->p_skb->len;
+
+		/* Return skb to operating system */
+
+		dev_kfree_skb(p_xmt_drv_descr->p_skb);
 
 		/*
 		 * Move to start of next packet by updating completion index
diff -u --recursive --new-file v2.1.100/linux/drivers/net/defxx.h linux/drivers/net/defxx.h
--- v2.1.100/linux/drivers/net/defxx.h	Mon Apr  6 17:41:00 1998
+++ linux/drivers/net/defxx.h	Fri May  8 00:08:02 1998
@@ -1771,9 +1771,12 @@
 	u32						rcv_length_errors;
 	u32						rcv_total_frames;
 	u32						rcv_multicast_frames;
+	u32						rcv_total_bytes;
+
 	u32						xmt_discards;
 	u32						xmt_length_errors;
 	u32						xmt_total_frames;
+	u32						xmt_total_bytes;
 	} DFX_board_t;
 
 #endif	/* #ifndef _DEFXX_H_ */
diff -u --recursive --new-file v2.1.100/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.1.100/linux/drivers/net/epic100.c	Wed Apr  8 19:36:27 1998
+++ linux/drivers/net/epic100.c	Fri May  8 00:20:47 1998
@@ -69,7 +69,6 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#include <linux/bios32.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -124,6 +123,7 @@
 
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
 #else
 #ifdef MODULE
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
@@ -258,7 +258,7 @@
 #endif
 
 static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
-									 int chip_id, int options, int card_idx);
+                                 int chip_id, int options, int card_idx);
 static int epic_open(struct device *dev);
 static int read_eeprom(int ioaddr, int location);
 static int mii_read(int ioaddr, int phy_id, int location);
@@ -293,11 +293,17 @@
 	   well with the current structure.  So instead we detect just the
 	   Epic cards in slot order. */
 
-	if (pcibios_present()) {
+	if (pci_present()) {
 		unsigned char pci_bus, pci_device_fn;
 
 		for (;pci_index < 0xff; pci_index++) {
-			unsigned char pci_irq_line, pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+			unsigned int pci_irq_line;
+			struct pci_dev *pdev;
+#else
+			unsigned char pci_irq_line;
+#endif
+			unsigned char pci_latency;
 			unsigned short pci_command, vendor, device;
 			unsigned int pci_ioaddr, chip_idx = 0;
 
@@ -317,10 +323,16 @@
 
 			pcibios_read_config_word(pci_bus, pci_device_fn,
 									 PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[0];
+#else
 			pcibios_read_config_byte(pci_bus, pci_device_fn,
 									 PCI_INTERRUPT_LINE, &pci_irq_line);
 			pcibios_read_config_dword(pci_bus, pci_device_fn,
 									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
 			/* Remove I/O space marker in bit 0. */
 			pci_ioaddr &= ~3;
 
@@ -730,6 +742,17 @@
 	struct epic_private *tp = (struct epic_private *)dev->priv;
 	int entry;
 	u32 flag;
+
+#ifndef final_version
+	if (skb == NULL || skb->len <= 0) {
+		printk("%s: Obsolete driver layer request made: skbuff==NULL.\n",
+			   dev->name);
+#if 0
+		dev_tint(dev);
+#endif
+		return 0;
+	}
+#endif
 
 	/* Block a timer-based transmit from overlapping.  This could better be
 	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
diff -u --recursive --new-file v2.1.100/linux/drivers/net/myri_sbus.h linux/drivers/net/myri_sbus.h
--- v2.1.100/linux/drivers/net/myri_sbus.h	Thu Mar 27 14:40:04 1997
+++ linux/drivers/net/myri_sbus.h	Fri May  8 00:20:47 1998
@@ -171,7 +171,7 @@
 #define MYRINET_MTU        8432
 #define RX_ALLOC_SIZE      8448
 #define MYRI_PAD_LEN       2
-#define RX_COPY_THRESHOLD  128
+#define RX_COPY_THRESHOLD  256
 
 /* These numbers are cast in stone, new firmware is needed if
  * you want to change them.
diff -u --recursive --new-file v2.1.100/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.1.100/linux/drivers/net/net_init.c	Sun Nov 30 14:00:38 1997
+++ linux/drivers/net/net_init.c	Fri May  8 00:20:47 1998
@@ -35,9 +35,10 @@
 #include <linux/string.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/hippidevice.h>
 #include <linux/trdevice.h>
 #include <linux/if_arp.h>
-#include <linux/fddidevice.h>
 #include <linux/if_ltalk.h>
 #include <linux/rtnetlink.h>
 
@@ -162,6 +163,63 @@
 
 #endif
 
+#ifdef CONFIG_HIPPI
+static int hippi_change_mtu(struct device *dev, int new_mtu)
+{
+	/*
+	 * HIPPI's got these nice large MTUs.
+	 */
+	if ((new_mtu < 68) || (new_mtu > 65280))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return(0);
+}
+
+
+/*
+ * For HIPPI we will actually use the lower 4 bytes of the hardware
+ * address as the I-FIELD rather than the actual hardware address.
+ */
+static int hippi_mac_addr(struct device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	if(dev->start)
+		return -EBUSY;
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	return 0;
+}
+
+
+struct device *init_hippi_dev(struct device *dev, int sizeof_priv)
+{
+	struct device *tmp_dev;		/* pointer to a device structure */
+
+	/* Find next free HIPPI entry */
+
+	for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next)
+		if ((strncmp(tmp_dev->name, "hip", 3) == 0) &&
+		    (tmp_dev->base_addr == 0))
+			break;
+
+	if (tmp_dev == NULL)
+	{
+		printk("Could not find free HIPPI device structure.\n");
+		return NULL;
+	}
+		
+	tmp_dev->init = NULL;
+	sizeof_priv = (sizeof_priv + 3) & ~3;
+	tmp_dev->priv = sizeof_priv ?								kmalloc(sizeof_priv, GFP_KERNEL) : NULL;
+
+	if (tmp_dev->priv)
+		memset(dev->priv, 0, sizeof_priv);
+
+	/* Initialize remaining device structure information */
+
+	hippi_setup(tmp_dev);
+	return tmp_dev;
+}
+#endif
 
 void ether_setup(struct device *dev)
 {
@@ -233,6 +291,40 @@
 	return;
 }
 
+#endif
+
+#ifdef CONFIG_HIPPI
+void hippi_setup(struct device *dev)
+{
+	dev->set_multicast_list	= NULL;
+	dev->change_mtu			= hippi_change_mtu;
+	dev->hard_header		= hippi_header;
+	dev->rebuild_header 		= hippi_rebuild_header;
+	dev->set_mac_address 		= hippi_mac_addr;
+	dev->hard_header_parse		= NULL;
+	dev->hard_header_cache		= NULL;
+	dev->header_cache_update	= NULL;
+
+	/*
+	 * We don't support HIPPI `ARP' for the time being, and probably
+	 * never will unless someone else implements it. However we
+	 * still need a fake ARPHRD to make ifconfig and friends play ball.
+	 */
+	dev->type		= ARPHRD_HIPPI;
+	dev->hard_header_len 	= HIPPI_HLEN;
+	dev->mtu		= 65280;
+	dev->addr_len		= HIPPI_ALEN;
+	dev->tx_queue_len	= 25 /* 5 */;
+	memset(dev->broadcast, 0xFF, HIPPI_ALEN);
+
+	/* New-style flags. */
+	dev->flags	= IFF_NODYNARP; /*
+					 * HIPPI doesn't support
+					 * broadcast+multicast and we only
+					 * use static ARP tables.
+					 */
+	dev_init_buffers(dev);
+}
 #endif
 
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
diff -u --recursive --new-file v2.1.100/linux/drivers/net/rtl8139.c linux/drivers/net/rtl8139.c
--- v2.1.100/linux/drivers/net/rtl8139.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rtl8139.c	Fri May  8 00:20:47 1998
@@ -0,0 +1,1356 @@
+/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
+/*
+	Written 1997 by Donald Becker.
+
+	This software may be used and distributed according to the terms
+	of the GNU Public License, incorporated herein by reference.
+    All other rights reserved.
+
+	This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet
+	chips.
+
+	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+	Center of Excellence in Space Data and Information Sciences
+	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+	Support and updates available at
+	http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html
+*/
+
+static const char *version =
+"rtl8139.c:v0.14 12/9/97 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. */
+static int max_interrupt_work = 10;
+
+/* Size of the in-memory receive ring. */
+#define RX_BUF_LEN_IDX	3			/* 0==8K, 1==16K, 2==32K, 3==64K */
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE	1536
+
+/* PCI Tuning Parameters
+   Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256	/* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024. */
+#define RX_FIFO_THRESH	4		/* Rx buffer level before first PCI xfer.  */
+#define RX_DMA_BURST	4		/* Maximum PCI burst, '4' is 256 bytes */
+#define TX_DMA_BURST	4
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  ((4000*HZ)/1000)
+
+#include <linux/config.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+   This is only in the support-all-kernels source code. */
+#include <linux/version.h>		/* Evil, but neccessary */
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
+#define RUN_AT(x) (x)			/* What to put in timer->expires.  */
+#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
+#define virt_to_bus(addr)  ((unsigned long)addr)
+#define bus_to_virt(addr) ((void*)addr)
+
+#else  /* 1.3.0 and later */
+#define RUN_AT(x) (jiffies + (x))
+#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+#endif
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
+#ifdef MODULE
+#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
+char kernel_version[] = UTS_RELEASE;
+#endif
+#else
+#undef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT
+#undef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+#endif /* 1.3.38 */
+
+#if (LINUX_VERSION_CODE >= 0x10344)
+#define NEW_MULTICAST
+#include <linux/delay.h>
+#endif
+
+#ifdef SA_SHIRQ
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
+#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+#else
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
+#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+#endif
+
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
+#endif
+
+/* The I/O extent. */
+#define RTL8129_TOTAL_SIZE 0x80
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry rtl8139_drv =
+{"RTL8139", rtl8139_probe, RTL8129_TOTAL_SIZE, NULL};
+#endif
+
+static int rtl8129_debug = 1;
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the RealTek RTL8129, the RealTek Fast
+Ethernet controllers for PCI.  This chip is used on a few clone boards.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+Note: Kernel versions earlier than 1.3.73 do not support shared PCI
+interrupt lines.
+
+III. Driver operation
+
+IIIa. Rx Ring buffers
+
+The receive unit uses a single linear ring buffer rather than the more
+common (and more efficient) descriptor-based architecture.  Incoming frames
+are sequentially stored into the Rx region, and the host copies them into
+skbuffs.
+
+Comment: While it is theoretically possible to process many frames in place,
+any delay in Rx processing would cause us to drop frames.  More importantly,
+the Linux protocol stack is not designed to operate in this manner.
+
+IIIb. Tx operation
+
+The RTL8129 uses a fixed set of four Tx descriptors in register space.
+In a stunningly bad design choice, Tx frames must be 32 bit aligned.  Linux
+aligns the IP header on word boundaries, and 14 byte ethernet header means
+that almost all frames will need to be copied to an alignment buffer.
+
+IVb. References
+
+http://www.realtek.com.tw/cn/cn.html
+http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
+
+IVc. Errata
+
+*/
+
+#ifndef PCI_VENDOR_ID_REALTEK
+#define PCI_VENDOR_ID_REALTEK		0x10ec
+#endif
+#ifndef PCI_DEVICE_ID_REALTEK_8129
+#define PCI_DEVICE_ID_REALTEK_8129	0x8129
+#endif
+#ifndef PCI_DEVICE_ID_REALTEK_8139
+#define PCI_DEVICE_ID_REALTEK_8139	0x8139
+#endif
+
+/* The rest of these values should never change. */
+#define NUM_TX_DESC	4			/* Number of Tx descriptor registers. */
+
+/* Symbolic offsets to registers. */
+enum RTL8129_registers {
+	MAC0=0,						/* Ethernet hardware address. */
+	MAR0=8,						/* Multicast filter. */
+	TxStat0=0x10,				/* Transmit status (Four 32bit registers). */
+	TxAddr0=0x20,				/* Tx descriptors (also four 32bit). */
+	RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
+	ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
+	IntrMask=0x3C, IntrStatus=0x3E,
+	TxConfig=0x40, RxConfig=0x44,
+	Timer=0x48,					/* A general-purpose counter. */
+	RxMissed=0x4C,				/* 24 bits valid, write clears. */
+	Cfg9346=0x50, Config0=0x51, Config1=0x52,
+	FlashReg=0x54, GPPinData=0x58, GPPinDir=0x59, MII_SMI=0x5A, HltClk=0x5B,
+	MultiIntr=0x5C, TxSummary=0x60,
+	BMCR=0x62, BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68, NWayExpansion=0x6A,
+};
+
+enum ChipCmdBits {
+	CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, };
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatusBits {
+	PCIErr=0x8000, PCSTimeout=0x4000,
+	RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10,
+	TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01,
+};
+enum TxStatusBits {
+	TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000,
+	TxOutOfWindow=0x20000000, TxAborted=0x40000000, TxCarrierLost=0x80000000,
+};
+enum RxStatusBits {
+	RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000,
+	RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004,
+	RxBadAlign=0x0002, RxStatusOK=0x0001,
+};
+
+struct rtl8129_private {
+	char devname[8];			/* Used only for kernel debugging. */
+	const char *product_name;
+	struct device *next_module;
+	int chip_id;
+	int chip_revision;
+	struct enet_statistics stats;
+	struct timer_list timer;	/* Media selection timer. */
+	unsigned int cur_rx, cur_tx;		/* The next free and used entries */
+	unsigned int dirty_rx, dirty_tx;
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct sk_buff* tx_skbuff[NUM_TX_DESC];
+	unsigned char *tx_buf[NUM_TX_DESC];	/* Tx bounce buffers */
+	unsigned char *rx_ring;
+	unsigned char *tx_bufs;				/* Tx bounce buffer region. */
+	unsigned char mc_filter[8];			/* Current multicast filter. */
+	char phys[4];						/* MII device addresses. */
+	unsigned int tx_full:1;				/* The Tx queue is full. */
+	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+	unsigned int 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. */
+	unsigned int mediasense:1;			/* Media sensing in progress. */
+};
+
+#ifdef MODULE
+/* Used to pass the full-duplex flag, etc. */
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#if LINUX_VERSION_CODE > 0x20118
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver");
+MODULE_PARM(debug, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_interrupt_work, "i");
+#endif
+#endif
+
+static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
+									 int chip_id, int options, int card_idx);
+static int rtl8129_open(struct device *dev);
+static int read_eeprom(int ioaddr, int location);
+static int mdio_read(int ioaddr, int phy_id, int location);
+static void rtl8129_timer(unsigned long data);
+static void rtl8129_tx_timeout(struct device *dev);
+static void rtl8129_init_ring(struct device *dev);
+static int rtl8129_start_xmit(struct sk_buff *skb, struct device *dev);
+static int rtl8129_rx(struct device *dev);
+static void rtl8129_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int rtl8129_close(struct device *dev);
+static struct enet_statistics *rtl8129_get_stats(struct device *dev);
+#ifdef NEW_MULTICAST
+static void set_rx_mode(struct device *dev);
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+
+
+
+#ifdef MODULE
+/* A list of all installed RTL8129 devices, for removing the driver module. */
+static struct device *root_rtl8129_dev = NULL;
+#endif
+
+int rtl8139_probe(struct device *dev)
+{
+	int cards_found = 0;
+	static int pci_index = 0;	/* Static, for multiple probe calls. */
+
+	/* Ideally we would detect all network cards in slot order.  That would
+	   be best done a central PCI probe dispatch, which wouldn't work
+	   well with the current structure.  So instead we detect just the
+	   Rtl81*9 cards in slot order. */
+
+	if (pci_present()) {
+		unsigned char pci_bus, pci_device_fn;
+
+		for (;pci_index < 0xff; pci_index++) {
+			unsigned char pci_latency;
+#if LINUX_VERSION_CODE >= 0x20155
+			unsigned int pci_irq_line;
+			struct pci_dev *pdev;
+#else
+			unsigned char pci_irq_line;
+#endif
+			unsigned short pci_command, new_command, vendor, device;
+			unsigned int pci_ioaddr;
+
+			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+#ifdef REVERSE_PROBE_ORDER
+									0xff - pci_index,
+#else
+									pci_index,
+#endif
+									&pci_bus, &pci_device_fn)
+				!= PCIBIOS_SUCCESSFUL)
+				break;
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_VENDOR_ID, &vendor);
+			if (vendor != PCI_VENDOR_ID_REALTEK)
+				continue;
+
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[0];
+#else
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+									 PCI_INTERRUPT_LINE, &pci_irq_line);
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
+			/* Remove I/O space marker in bit 0. */
+			pci_ioaddr &= ~3;
+
+			if (device != PCI_DEVICE_ID_REALTEK_8129
+				&&  device != PCI_DEVICE_ID_REALTEK_8139) {
+				printk(KERN_NOTICE"Unknown RealTek PCI ethernet chip type "
+					   "%4.4x detected: not configured.\n", device);
+				continue;
+			}
+			if (check_region(pci_ioaddr, RTL8129_TOTAL_SIZE))
+				continue;
+
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_COMMAND, &pci_command);
+			new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+			if (pci_command != new_command) {
+				printk(KERN_INFO "  The PCI BIOS has not enabled this"
+					   " device!  Updating PCI config %4.4x->%4.4x.\n",
+					   pci_command, new_command);
+				pcibios_write_config_word(pci_bus, pci_device_fn,
+										  PCI_COMMAND, new_command);
+			}
+
+#ifdef MODULE
+			dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device,
+								 options[cards_found], cards_found);
+#else
+			dev = rtl8129_probe1(dev, pci_ioaddr, pci_irq_line, device,
+								 dev ? dev->mem_start : 0, -1);
+#endif
+
+			if (dev) {
+				pcibios_read_config_byte(pci_bus, pci_device_fn,
+										 PCI_LATENCY_TIMER, &pci_latency);
+				if (pci_latency < 32) {
+					printk(KERN_NOTICE"  PCI latency timer (CFLT) is "
+						   "unreasonably low at %d.  Setting to 64 clocks.\n",
+						   pci_latency);
+					pcibios_write_config_byte(pci_bus, pci_device_fn,
+											  PCI_LATENCY_TIMER, 64);
+				} else if (rtl8129_debug > 1)
+					printk(KERN_INFO"  PCI latency timer (CFLT) is %#x.\n",
+						   pci_latency);
+				dev = 0;
+				cards_found++;
+			}
+		}
+	}
+
+#if defined (MODULE)
+	return cards_found;
+#else
+	return cards_found ? 0 : -ENODEV;
+#endif
+}
+
+static struct device *rtl8129_probe1(struct device *dev, int ioaddr, int irq,
+								   int chip_id, int options, int card_idx)
+{
+	static int did_version = 0;			/* Already printed version info. */
+	struct rtl8129_private *tp;
+	int i;
+
+	if (rtl8129_debug > 0  &&  did_version++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	dev = init_etherdev(dev, 0);
+
+	printk(KERN_INFO "%s: RealTek RTL%x at %#3x, IRQ %d, ",
+		   dev->name, chip_id, ioaddr, irq);
+
+	/* Bring the chip out of low-power mode. */
+	outb(0x00, ioaddr + Config1);
+
+	/* Perhaps this should be read from the EEPROM? */
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + MAC0 + i);
+
+	for (i = 0; i < 5; i++)
+		printk("%2.2x:", dev->dev_addr[i]);
+	printk("%2.2x.\n", dev->dev_addr[i]);
+
+	if (rtl8129_debug > 1) {
+		printk(KERN_INFO "%s: EEPROM contents\n", dev->name);
+		for (i = 0; i < 64; i++)
+			printk(" %4.4x%s", read_eeprom(ioaddr, i),
+				   i%16 == 15 ? "\n"KERN_INFO : "");
+	}
+
+	/* We do a request_region() to register /proc/ioports info. */
+	request_region(ioaddr, RTL8129_TOTAL_SIZE, "RealTek RTL8129/39 Fast Ethernet");
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	/* Some data structures must be quadword aligned. */
+	tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
+	memset(tp, 0, sizeof(*tp));
+	dev->priv = tp;
+
+#ifdef MODULE
+	tp->next_module = root_rtl8129_dev;
+	root_rtl8129_dev = dev;
+#endif
+
+	tp->chip_id = chip_id;
+
+	/* Find the connected MII xcvrs.
+	   Doing this in open() would allow detecting external xcvrs later, but
+	   takes too much time. */
+	if (chip_id == 0x8129) {
+		int phy, phy_idx;
+		for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+			 phy++) {
+			int mii_status = mdio_read(ioaddr, phy, 1);
+
+			if (mii_status != 0xffff  && mii_status != 0x0000) {
+				tp->phys[phy_idx++] = phy;
+				printk(KERN_INFO "%s: MII transceiver found at address %d.\n",
+					   dev->name, phy);
+			}
+		}
+		if (phy_idx == 0) {
+			printk(KERN_INFO "%s: No MII transceivers found!  Assuming SYM "
+				   "transceiver.\n",
+				   dev->name);
+			tp->phys[0] = -1;
+		}
+	} else {
+			tp->phys[0] = -1;
+	}
+
+	/* Put the chip into low-power mode. */
+	outb(0xC0, ioaddr + Cfg9346);
+	outb(0x03, ioaddr + Config1);
+	outb('H', ioaddr + HltClk);		/* 'R' would leave the clock running. */
+
+	/* The lower four bits are the media type. */
+	if (options > 0) {
+		tp->full_duplex = (options & 16) ? 1 : 0;
+		tp->default_port = options & 15;
+		if (tp->default_port)
+			tp->medialock = 1;
+	}
+#ifdef MODULE
+	if (card_idx >= 0) {
+		if (full_duplex[card_idx] >= 0)
+			tp->full_duplex = full_duplex[card_idx];
+	}
+#endif
+
+	/* The Rtl8129-specific entries in the device structure. */
+	dev->open = &rtl8129_open;
+	dev->hard_start_xmit = &rtl8129_start_xmit;
+	dev->stop = &rtl8129_close;
+	dev->get_stats = &rtl8129_get_stats;
+	dev->set_multicast_list = &set_rx_mode;
+
+	return dev;
+}
+
+/* Serial EEPROM section. */
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
+#define EE_CS			0x08	/* EEPROM chip select. */
+#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
+#define EE_WRITE_0		0x00
+#define EE_WRITE_1		0x02
+#define EE_DATA_READ	0x01	/* EEPROM chip data out. */
+#define EE_ENB			(0x80 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+   The 1.2 code is a "nasty" timing loop, but PC compatible machines are
+   *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro.  */
+#ifdef _LINUX_DELAY_H
+#define eeprom_delay(nanosec)	udelay((nanosec + 999)/1000)
+#else
+#define eeprom_delay(nanosec)	do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#endif
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD	(5 << 6)
+#define EE_READ_CMD		(6 << 6)
+#define EE_ERASE_CMD	(7 << 6)
+
+static int read_eeprom(int ioaddr, int location)
+{
+	int i;
+	unsigned short retval = 0;
+	short ee_addr = ioaddr + Cfg9346;
+	int read_cmd = location | EE_READ_CMD;
+
+	outb(EE_ENB & ~EE_CS, ee_addr);
+	outb(EE_ENB, ee_addr);
+
+	/* Shift the read command bits out. */
+	for (i = 10; i >= 0; i--) {
+		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+		outb(EE_ENB | dataval, ee_addr);
+		eeprom_delay(100);
+		outb(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay(150);
+		outb(EE_ENB | dataval, ee_addr);	/* Finish EEPROM a clock tick. */
+		eeprom_delay(250);
+	}
+	outb(EE_ENB, ee_addr);
+
+	for (i = 16; i > 0; i--) {
+		outb(EE_ENB | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay(100);
+		retval = (retval << 1) | ((inb(ee_addr) & EE_DATA_READ) ? 1 : 0);
+		outb(EE_ENB, ee_addr);
+		eeprom_delay(100);
+	}
+
+	/* Terminate the EEPROM access. */
+	outb(~EE_CS, ee_addr);
+	return retval;
+}
+
+/* MII serial management: mostly bogus for now. */
+/* Read and write the MII management registers using software-generated
+   serial MDIO protocol.  The maxium data clock rate is 2.5 Mhz. */
+#define MDIO_DIR		0x80
+#define MDIO_DATA_OUT	0x04
+#define MDIO_DATA_IN	0x02
+#define MDIO_CLK		0x01
+#ifdef _LINUX_DELAY_H
+#define mdio_delay()	udelay(1) /* Really 400ns. */
+#else
+#define mdio_delay()	__SLOW_DOWN_IO;
+#endif
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void mdio_sync(int ioaddr)
+{
+	int i;
+	int mdio_addr = ioaddr + MII_SMI;
+
+	for (i = 32; i >= 0; i--) {
+		outb(MDIO_DIR | MDIO_DATA_OUT, mdio_addr);
+		mdio_delay();
+		outb(MDIO_DIR | MDIO_DATA_OUT | MDIO_CLK, mdio_addr);
+		mdio_delay();
+	}
+	return;
+}
+static int mdio_read(int ioaddr, int phy_id, int location)
+{
+	int i;
+	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+	int retval = 0;
+	int mdio_addr = ioaddr + MII_SMI;
+
+	mdio_sync(ioaddr);
+	/* Shift the read command bits out. */
+	for (i = 15; i >= 0; i--) {
+		int dataval =
+		  (read_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
+
+		outb(MDIO_DIR | dataval, mdio_addr);
+		mdio_delay();
+		outb(MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
+		mdio_delay();
+	}
+
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		outb(0, mdio_addr);
+		mdio_delay();
+		retval = (retval << 1) | ((inb(mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
+		outb(MDIO_CLK, mdio_addr);
+		mdio_delay();
+	}
+	return (retval>>1) & 0xffff;
+}
+
+static int
+rtl8129_open(struct device *dev)
+{
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int i;
+	int full_duplex = 0;
+
+	/* Soft reset the chip. */
+	outb(CmdReset, ioaddr + ChipCmd);
+
+#ifdef SA_SHIRQ
+	if (request_irq(dev->irq, &rtl8129_interrupt, SA_SHIRQ,
+					"RealTek RTL8129/39 Fast Ethernet", dev)) {
+		return -EAGAIN;
+	}
+#else
+	if (irq2dev_map[dev->irq] != NULL
+		|| (irq2dev_map[dev->irq] = dev) == NULL
+		|| dev->irq == 0
+		|| request_irq(dev->irq, &rtl8129_interrupt, 0, "RTL8129")) {
+		return -EAGAIN;
+	}
+#endif
+
+	MOD_INC_USE_COUNT;
+
+	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) {
+		if (tp->tx_bufs)
+			kfree(tp->tx_bufs);
+		if (rtl8129_debug > 0)
+			printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",
+				   dev->name, RX_BUF_LEN);
+		return -ENOMEM;
+	}
+	rtl8129_init_ring(dev);
+
+#ifndef final_version
+	/* Used to monitor rx ring overflow. */
+	memset(tp->rx_ring + RX_BUF_LEN, 0xcc, 16);
+#endif
+
+	/* Check that the chip has finished the reset. */
+	for (i = 1000; i > 0; i--)
+		if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
+			break;
+#ifndef final_version
+	if (rtl8129_debug > 2)
+		printk(KERN_DEBUG"%s: reset finished with status %2.2x after %d loops.\n",
+			   dev->name, inb(ioaddr + ChipCmd), 1000-i);
+#endif
+
+	for (i = 0; i < 6; i++)
+		outb(dev->dev_addr[i], ioaddr + MAC0 + i);
+
+	/* Must enable Tx/Rx before setting transfer thresholds! */
+	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+	outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) | (RX_DMA_BURST<<8),
+		 ioaddr + RxConfig);
+	outl((TX_DMA_BURST<<8)|0x03000000, ioaddr + TxConfig);
+
+	full_duplex = tp->full_duplex;
+	if (tp->phys[0] >= 0  ||  tp->chip_id == 0x8139) {
+		u16 mii_reg5;
+		if (tp->chip_id == 0x8139)
+			mii_reg5 = inw(ioaddr + NWayLPAR);
+		else
+			mii_reg5 = mdio_read(ioaddr, tp->phys[0], 5);
+		if (mii_reg5 == 0xffff)
+			;					/* Not there */
+		else if ((mii_reg5 & 0x0100) == 0x0100
+				 || (mii_reg5 & 0x00C0) == 0x0040)
+			full_duplex = 1;
+		if (rtl8129_debug > 1)
+			printk(KERN_INFO"%s: Setting %s%s-duplex based on"
+				   " auto-negotiated partner ability %4.4x.\n", dev->name,
+				   mii_reg5 == 0 ? "" :
+				   (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
+				   full_duplex ? "full" : "half", mii_reg5);
+	}
+
+	outb(0xC0, ioaddr + Cfg9346);
+	outb(full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+	outb(0x00, ioaddr + Cfg9346);
+
+	outl(virt_to_bus(tp->rx_ring), ioaddr + RxBuf);
+
+	/* Start the chip's Tx and Rx process. */
+	outl(0, ioaddr + RxMissed);
+	set_rx_mode(dev);
+
+	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+#ifndef final_version
+	if (rtl8129_debug > 1)
+		printk(KERN_DEBUG"%s:  In rtl8129_open() Tx/Rx Config %8.8x/%8.8x"
+			   " Chip Config %2.2x/%2.2x.\n",
+			   dev->name, inl(ioaddr + TxConfig), inl(ioaddr + RxConfig),
+			   inb(ioaddr + Config0), inb(ioaddr + Config1));
+#endif
+
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* Enable all known interrupts by setting the interrupt mask. */
+	outw(PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver
+		| TxErr | TxOK | RxErr | RxOK, ioaddr + IntrMask);
+
+	if (rtl8129_debug > 1)
+		printk(KERN_DEBUG"%s: rtl8129_open() ioaddr %4.4x IRQ %d"
+			   " GP Pins %2.2x %s-duplex.\n",
+			   dev->name, ioaddr, dev->irq, inb(ioaddr + GPPinData),
+			   full_duplex ? "full" : "half");
+
+	/* Set the timer to switch to check for link beat and perhaps switch
+	   to an alternate media type. */
+	init_timer(&tp->timer);
+	tp->timer.expires = RUN_AT((24*HZ)/10);			/* 2.4 sec. */
+	tp->timer.data = (unsigned long)dev;
+	tp->timer.function = &rtl8129_timer;				/* timer handler */
+	add_timer(&tp->timer);
+
+	return 0;
+}
+
+static void rtl8129_timer(unsigned long data)
+{
+	struct device *dev = (struct device *)data;
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int next_tick = 0;
+
+	if (tp->chip_id == 0x8139) {
+		u16 mii_reg5 = inw(ioaddr + NWayLPAR);
+		if ((mii_reg5 & 0x0100) == 0x0100
+			|| (mii_reg5 & 0x00C0) == 0x0040)
+			if ( ! tp->full_duplex) {
+				tp->full_duplex = 1;
+				if (rtl8129_debug > 0)
+					printk(KERN_INFO "%s: Switching to full-duplex based on "
+						   "link partner ability of %4.4x.\n",
+						   dev->name, mii_reg5);
+				outb(0xC0, ioaddr + Cfg9346);
+				outb(tp->full_duplex ? 0x60 : 0x20, ioaddr + Config1);
+				outb(0x00, ioaddr + Cfg9346);
+			}
+	}
+	if (rtl8129_debug > 2) {
+		if (tp->chip_id == 0x8129)
+			printk(KERN_DEBUG"%s: Media selection tick, GP pins %2.2x.\n",
+				   dev->name, inb(ioaddr + GPPinData));
+		else
+			printk(KERN_DEBUG"%s: Media selection tick, Link partner %4.4x.\n",
+				   dev->name, inw(ioaddr + NWayLPAR));
+		printk(KERN_DEBUG"%s:  Other registers are IntMask %4.4x IntStatus %4.4x"
+			   " RxStatus %4.4x.\n",
+			   dev->name, inw(ioaddr + IntrMask), inw(ioaddr + IntrStatus),
+			   inl(ioaddr + RxEarlyStatus));
+		printk(KERN_DEBUG"%s:  Chip config %2.2x %2.2x.\n",
+			   dev->name, inb(ioaddr + Config0), inb(ioaddr + Config1));
+	}
+
+	if (next_tick) {
+		tp->timer.expires = RUN_AT(next_tick);
+		add_timer(&tp->timer);
+	}
+}
+
+static void rtl8129_tx_timeout(struct device *dev)
+{
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int i;
+
+	if (rtl8129_debug > 0)
+		printk(KERN_WARNING "%s: Transmit timeout, status %2.2x %4.4x.\n",
+			   dev->name, inb(ioaddr + ChipCmd), inw(ioaddr + IntrStatus));
+	for (i = 0; i < NUM_TX_DESC; i++)
+		printk(KERN_DEBUG"%s:  Tx descriptor %d is %8.8x.%s\n",
+			   dev->name, i, inl(ioaddr + TxStat0 + i*4),
+			   i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : "");
+	if (tp->chip_id == 0x8129) {
+		int mii_reg;
+		printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]);
+		for (mii_reg = 0; mii_reg < 8; mii_reg++)
+			printk(" %4.4x", mdio_read(ioaddr, tp->phys[0], mii_reg));
+		printk(".\n");
+	} else {
+		printk(KERN_DEBUG"%s: MII status register is %4.4x.\n",
+			   dev->name, inw(ioaddr + BMSR));
+	}
+	/* Restart the chip Tx process. */
+	outb(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
+	/* Continue from any transmit abort. */
+	outl((TX_DMA_BURST<<8) || 0x03000001, ioaddr + TxConfig);
+
+	dev->trans_start = jiffies;
+	tp->stats.tx_errors++;
+	return;
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void
+rtl8129_init_ring(struct device *dev)
+{
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int i;
+
+	tp->tx_full = 0;
+	tp->cur_rx = tp->cur_tx = 0;
+	tp->dirty_rx = tp->dirty_tx = 0;
+
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		tp->tx_skbuff[i] = 0;
+		tp->tx_buf[i] = &tp->tx_bufs[i*TX_BUF_SIZE];
+	}
+}
+
+static int
+rtl8129_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int entry;
+
+#ifndef final_version
+	if (skb == NULL || skb->len <= 0) {
+		printk(KERN_ERR"%s: Obsolete driver Tx request made: skbuff==NULL.\n",
+			   dev->name);
+#if 0
+		dev_tint(dev);
+#endif
+		return 0;
+	}
+#endif
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		if (jiffies - dev->trans_start < TX_TIMEOUT)
+			return 1;
+		rtl8129_tx_timeout(dev);
+		return 1;
+	}
+
+	/* Calculate the next Tx descriptor entry. */
+	entry = tp->cur_tx % NUM_TX_DESC;
+
+	tp->tx_skbuff[entry] = skb;
+	if ((long)skb->data & 3) {			/* Must use alignment buffer. */
+		memcpy(tp->tx_buf[entry], skb->data, skb->len);
+		outl(virt_to_bus(tp->tx_buf[entry]), ioaddr + TxAddr0 + entry*4);
+	} else
+		outl(virt_to_bus(skb->data), ioaddr + TxAddr0 + entry*4);
+	/* Note: the chip doesn't have auto-pad! */
+	outl(((TX_FIFO_THRESH<<11) & 0x003f0000) |
+		 (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN),
+		 ioaddr + TxStat0 + entry*4);
+
+	if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
+		dev->tbusy = 0;
+	} else {
+		tp->tx_full = 1;
+	}
+
+	dev->trans_start = jiffies;
+	if (rtl8129_debug > 4)
+		printk(KERN_DEBUG"%s: Queued Tx packet at %p size %d to slot %d.\n",
+			   dev->name, skb->data, skb->len, entry);
+
+	return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void rtl8129_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+{
+#ifdef SA_SHIRQ
+	struct device *dev = (struct device *)dev_instance;
+#else
+	struct device *dev = (struct device *)(irq2dev_map[irq]);
+#endif
+	struct rtl8129_private *tp;
+	int ioaddr, boguscnt = max_interrupt_work;
+	int status;
+
+	if (dev == NULL) {
+		printk (KERN_ERR"rtl8139_interrupt(): IRQ %d for unknown device.\n",
+				irq);
+		return;
+	}
+
+	ioaddr = dev->base_addr;
+	tp = (struct rtl8129_private *)dev->priv;
+	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+		return;
+	}
+
+	do {
+		status = inw(ioaddr + IntrStatus);
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		outw(status, ioaddr + IntrStatus);
+
+		if (rtl8129_debug > 4)
+			printk(KERN_DEBUG"%s: interrupt  status=%#4.4x new intstat=%#4.4x.\n",
+				   dev->name, status, inw(ioaddr + IntrStatus));
+
+		if ((status & (PCIErr|PCSTimeout|RxUnderrun|RxOverflow|RxFIFOOver
+					   |TxErr|TxOK|RxErr|RxOK)) == 0)
+			break;
+
+		if (status & (RxOK|RxUnderrun|RxOverflow|RxFIFOOver))/* Rx interrupt */
+			rtl8129_rx(dev);
+
+		if (status & (TxOK | TxErr)) {
+			unsigned int dirty_tx;
+
+			for (dirty_tx = tp->dirty_tx; dirty_tx < tp->cur_tx; dirty_tx++) {
+				int entry = dirty_tx % NUM_TX_DESC;
+				int txstatus = inl(ioaddr + TxStat0 + entry*4);
+
+				if ( ! (txstatus & TxHostOwns))
+					break;			/* It still hasn't been Txed */
+
+				/* 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++;
+						outl((TX_DMA_BURST<<8)|0x03000001, ioaddr + TxConfig);
+					}
+					if (txstatus&TxCarrierLost) tp->stats.tx_carrier_errors++;
+					if (txstatus&TxOutOfWindow) tp->stats.tx_window_errors++;
+#ifdef ETHER_STATS
+					if ((txstatus & 0x0f000000) == 0x0f000000)
+						tp->stats.collisions16++;
+#endif
+				} else {
+#ifdef ETHER_STATS
+					/* No count for tp->stats.tx_deferred */
+#endif
+					if (txstatus & TxUnderrun) {
+						/* Todo: increase the Tx FIFO threshold. */
+						tp->stats.tx_fifo_errors++;
+					}
+					tp->stats.collisions += (txstatus >> 24) & 15;
+					tp->stats.tx_packets++;
+				}
+
+				/* Free the original skb. */
+				dev_kfree_skb(tp->tx_skbuff[entry]);
+				tp->tx_skbuff[entry] = 0;
+			}
+
+#ifndef final_version
+			if (tp->cur_tx - dirty_tx > NUM_TX_DESC) {
+				printk(KERN_ERR"%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+					   dev->name, dirty_tx, tp->cur_tx, tp->tx_full);
+				dirty_tx += NUM_TX_DESC;
+			}
+#endif
+
+			if (tp->tx_full && dev->tbusy
+				&& 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;
+		}
+
+		/* Check uncommon events with one test. */
+		if (status & (PCIErr|PCSTimeout |RxUnderrun|RxOverflow|RxFIFOOver
+					  |TxErr|RxErr)) {
+
+#ifndef final_version
+			if (rtl8129_debug > 0)
+				printk(KERN_DEBUG"%s: Unusual error, status %4.4x.\n",
+							   dev->name, status);
+#endif
+
+			/* Update the error count. */
+			tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
+			outl(0, ioaddr + RxMissed);
+
+			if (status & (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
+				tp->stats.rx_errors++;
+
+			if (status & (PCSTimeout)) tp->stats.rx_length_errors++;
+			if (status & (RxUnderrun|RxFIFOOver)) tp->stats.rx_fifo_errors++;
+			if (status & RxOverflow) {
+				tp->stats.rx_over_errors++;
+				tp->cur_rx = inw(ioaddr + RxBufAddr) % RX_BUF_LEN;
+				outw(tp->cur_rx - 16, ioaddr + RxBufPtr);
+			}
+			/* Error sources cleared above. */
+		}
+		if (--boguscnt < 0) {
+			printk(KERN_WARNING"%s: Too much work at interrupt, "
+				   "IntrStatus=0x%4.4x.\n",
+				   dev->name, status);
+			/* Clear all interrupt sources. */
+			outw(0xffff, ioaddr + IntrStatus);
+			break;
+		}
+	} while (1);
+
+	if (rtl8129_debug > 3)
+		printk(KERN_DEBUG"%s: exiting interrupt, intr_status=%#4.4x.\n",
+			   dev->name, inl(ioaddr + IntrStatus));
+
+#ifndef final_version
+	/* Code that should never be run!  Perhaps remove after testing.. */
+	{
+		static int stopit = 10;
+		if (dev->start == 0  &&  --stopit < 0) {
+			printk(KERN_ERR"%s: Emergency stop, looping startup interrupt.\n",
+				   dev->name);
+			FREE_IRQ(irq, dev);
+		}
+	}
+#endif
+
+	dev->interrupt = 0;
+	return;
+}
+
+/* Todo: The data sheet doesn't describe the Rx ring at all, so I'm winging
+   it here until I have a chip to play with. 8/30/97 */
+static int
+rtl8129_rx(struct device *dev)
+{
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	unsigned char *rx_ring = tp->rx_ring;
+	u16 cur_rx = tp->cur_rx;
+
+	if (rtl8129_debug > 4)
+		printk(KERN_DEBUG"%s: In rtl8129_rx(), current %4.4x BufAddr %4.4x,"
+			   " free to %4.4x, Cmd %2.2x.\n",
+			   dev->name, cur_rx, inw(ioaddr + RxBufAddr),
+			   inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
+
+	while ((inb(ioaddr + ChipCmd) & 1) == 0) {
+		u16 ring_offset = cur_rx % RX_BUF_LEN;
+		u32 rx_status = *(u32*)(rx_ring + ring_offset);
+		u16 rx_size = rx_status >> 16;
+
+		if (rtl8129_debug > 4) {
+			int i;
+			printk(KERN_DEBUG"%s:  rtl8129_rx() status %4.4x, size %4.4x, cur %4.4x.\n",
+				   dev->name, rx_status, rx_size, cur_rx);
+			printk(KERN_DEBUG"%s: Frame contents ", dev->name);
+			for (i = 0; i < 70; i++)
+				printk(" %2.2x", rx_ring[ring_offset + i]);
+			printk(".\n");
+		}
+		if (rx_status & RxTooLong) {
+			if (rtl8129_debug > 0)
+				printk(KERN_NOTICE"%s: Oversized Ethernet frame, status %4.4x!\n",
+					   dev->name, rx_status);
+			tp->stats.rx_length_errors++;
+		} else if (rx_status &
+				   (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) {
+			if (rtl8129_debug > 1)
+				printk(KERN_DEBUG"%s: Ethernet frame had errors,"
+					   " status %4.4x.\n", dev->name, rx_status);
+			tp->stats.rx_errors++;
+			if (rx_status & (RxBadSymbol|RxBadAlign))
+				tp->stats.rx_frame_errors++;
+			if (rx_status & (RxRunt|RxTooLong)) tp->stats.rx_length_errors++;
+			if (rx_status & RxCRCErr) tp->stats.rx_crc_errors++;
+		} else {
+			/* Malloc up new buffer, compatible with net-2e. */
+			/* Omit the four octet CRC from the length. */
+			struct sk_buff *skb;
+
+			skb = DEV_ALLOC_SKB(rx_size + 2);
+			if (skb == NULL) {
+				printk(KERN_WARNING"%s: Memory squeeze, deferring packet.\n",
+					   dev->name);
+				/* We should check that some rx space is free.
+				   If not, free one and mark stats->rx_dropped++. */
+				tp->stats.rx_dropped++;
+				break;
+			}
+			skb->dev = dev;
+			skb_reserve(skb, 2);	/* 16 byte align the IP fields. */
+			if (ring_offset+rx_size+4 > RX_BUF_LEN) {
+				int semi_count = RX_BUF_LEN - ring_offset - 4;
+				memcpy(skb_put(skb, semi_count), &rx_ring[ring_offset + 4],
+					   semi_count);
+				memcpy(skb_put(skb, rx_size-semi_count), rx_ring,
+					   rx_size-semi_count);
+				if (rtl8129_debug > 4) {
+					int i;
+					printk(KERN_DEBUG"%s:  Frame wrap @%d", dev->name, semi_count);
+					for (i = 0; i < 16; i++)
+						printk(" %2.2x", rx_ring[i]);
+					printk(".\n");
+					memset(rx_ring, 0xcc, 16);
+				}
+			} else
+				memcpy(skb_put(skb, rx_size), &rx_ring[ring_offset + 4],
+					   rx_size);
+#if LINUX_VERSION_CODE >= 0x10300
+			skb->protocol = eth_type_trans(skb, dev);
+#else
+			skb->len = rx_size;
+#endif
+			netif_rx(skb);
+			tp->stats.rx_packets++;
+		}
+
+		cur_rx += rx_size + 4;
+		cur_rx = (cur_rx + 3) & ~3;
+		outw(cur_rx - 16, ioaddr + RxBufPtr);
+	}
+	if (rtl8129_debug > 4)
+		printk(KERN_DEBUG"%s: Done rtl8129_rx(), current %4.4x BufAddr %4.4x,"
+			   " free to %4.4x, Cmd %2.2x.\n",
+			   dev->name, cur_rx, inw(ioaddr + RxBufAddr),
+			   inw(ioaddr + RxBufPtr), inb(ioaddr + ChipCmd));
+	tp->cur_rx = cur_rx;
+	return 0;
+}
+
+static int
+rtl8129_close(struct device *dev)
+{
+	int ioaddr = dev->base_addr;
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int i;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	if (rtl8129_debug > 1)
+		printk(KERN_DEBUG"%s: Shutting down ethercard, status was 0x%4.4x.\n",
+			   dev->name, inw(ioaddr + IntrStatus));
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	outw(0x0000, ioaddr + IntrMask);
+
+	/* Stop the chip's Tx and Rx DMA processes. */
+	outb(0x00, ioaddr + ChipCmd);
+
+	/* Update the error counts. */
+	tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
+	outl(0, ioaddr + RxMissed);
+
+	del_timer(&tp->timer);
+
+#ifdef SA_SHIRQ
+	free_irq(dev->irq, dev);
+#else
+	free_irq(dev->irq);
+	irq2dev_map[dev->irq] = 0;
+#endif
+
+#ifndef final_version
+	/* Used to monitor rx ring overflow. */
+	for (i = 0; i < 16; i++)
+		if (tp->rx_ring[RX_BUF_LEN+i] != 0xcc) {
+			printk(KERN_WARNING"%s: Rx ring overflowed!  Values are ",
+				   dev->name);
+			for (i = 0; i < 16; i++)
+				printk(" %2.2x", tp->rx_ring[RX_BUF_LEN + i]);
+			printk(".\n");
+			break;
+		}
+#endif
+
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		if (tp->tx_skbuff[i])
+			dev_kfree_skb(tp->tx_skbuff[i]);
+		tp->tx_skbuff[i] = 0;
+	}
+	kfree(tp->rx_ring);
+	kfree(tp->tx_bufs);
+
+	/* Green! Put the chip in low-power mode. */
+	outb(0xC0, ioaddr + Cfg9346);
+	outb(0x03, ioaddr + Config1);
+	outb('H', ioaddr + HltClk);		/* 'R' would leave the clock running. */
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static struct enet_statistics *
+rtl8129_get_stats(struct device *dev)
+{
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+
+	if (dev->start) {
+		tp->stats.rx_missed_errors += inl(ioaddr + RxMissed);
+		outl(0, ioaddr + RxMissed);
+	}
+
+	return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   Note that we only use exclusion around actually queueing the
+   new frame, not around filling tp->setup_frame.  This is non-deterministic
+   when re-entered but still correct. */
+
+/* The little-endian AUTODIN II ethernet CRC calculation.
+   N.B. Do not use for bulk data, use a table-based routine instead.
+   This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline unsigned ether_crc_le(int length, unsigned char *data)
+{
+	unsigned int crc = 0xffffffff;	/* Initial value. */
+	while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 8; --bit >= 0; current_octet >>= 1) {
+			if ((crc ^ current_octet) & 1) {
+				crc >>= 1;
+				crc ^= ethernet_polynomial_le;
+			} else
+				crc >>= 1;
+		}
+	}
+	return crc;
+}
+
+
+static void
+#ifdef NEW_MULTICAST
+set_rx_mode(struct device *dev)
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+{
+	int ioaddr = dev->base_addr;
+	struct rtl8129_private *tp = (struct rtl8129_private *)dev->priv;
+	unsigned char mc_filter[8];		 /* Multicast hash filter */
+	int i;
+
+	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
+		/* Unconditionally log net taps. */
+		printk(KERN_NOTICE"%s: Promiscuous mode enabled.\n", dev->name);
+		memset(mc_filter, 0xff, sizeof(mc_filter));
+		outb(0x0F, ioaddr + RxConfig);
+	} else if ((dev->mc_count > 1000)  ||  (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to filter perfectly -- accept all multicasts. */
+		memset(mc_filter, 0xff, sizeof(mc_filter));
+		outb(0x0E, ioaddr + RxConfig);
+	} else if (dev->mc_count == 0) {
+		outb(0x0A, ioaddr + RxConfig);
+		return;
+	} else {
+		struct dev_mc_list *mclist;
+
+		memset(mc_filter, 0, sizeof(mc_filter));
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+			 i++, mclist = mclist->next)
+			set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
+					mc_filter);
+	}
+	/* ToDo: perhaps we need to stop the Tx and Rx process here? */
+	if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
+		for (i = 0; i < 2; i++)
+			outl(((u32 *)mc_filter)[i], ioaddr + MAR0 + i*4);
+		memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+	}
+	if (rtl8129_debug > 3)
+		printk(KERN_DEBUG"%s:   set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
+			   dev->name, dev->flags, inl(ioaddr + RxConfig));
+	return;
+}
+
+#ifdef MODULE
+
+/* An additional parameter that may be passed in... */
+static int debug = -1;
+
+int
+init_module(void)
+{
+	int cards_found;
+
+	if (debug >= 0)
+		rtl8129_debug = debug;
+
+	root_rtl8129_dev = NULL;
+	cards_found = rtl8139_probe(0);
+
+	return cards_found ? 0 : -ENODEV;
+}
+
+void
+cleanup_module(void)
+{
+	struct device *next_dev;
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_rtl8129_dev) {
+		next_dev = ((struct rtl8129_private *)root_rtl8129_dev->priv)->next_module;
+		unregister_netdev(root_rtl8129_dev);
+		release_region(root_rtl8129_dev->base_addr, RTL8129_TOTAL_SIZE);
+		kfree(root_rtl8129_dev);
+		root_rtl8129_dev = next_dev;
+	}
+}
+
+#endif  /* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c"
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -u --recursive --new-file v2.1.100/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c
--- v2.1.100/linux/drivers/net/sgiseeq.c	Thu Feb 12 20:56:09 1998
+++ linux/drivers/net/sgiseeq.c	Fri May  8 00:20:47 1998
@@ -1,7 +1,9 @@
-/* $Id: sgiseeq.c,v 1.3 1997/11/16 13:57:45 alan Exp $
+/*
  * sgiseeq.c: Seeq8003 ethernet driver for SGI machines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * $Id: sgiseeq.c,v 1.5 1998/05/01 01:35:40 ralf Exp $
  */
 
 #include <linux/kernel.h>
@@ -15,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 
+#include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -173,7 +176,7 @@
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 			ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
 			ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer);
-			flush_cache_all();
+//			flush_cache_all();
 		}
 		ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT);
 	}
@@ -186,7 +189,7 @@
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 			ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
 			ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer);
-			flush_cache_all();
+//			flush_cache_all();
 		}
 		ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT);
 	}
@@ -351,6 +354,25 @@
 	}
 }
 
+static inline void kick_tx(struct sgiseeq_tx_desc *td,
+			   volatile struct hpc3_ethregs *hregs)
+{
+	/* If the HPC aint doin nothin, and there are more packets
+	 * with ETXD cleared and XIU set we must make very certain
+	 * that we restart the HPC else we risk locking up the
+	 * adapter.  The following code is only safe iff the HPCDMA
+	 * is not active!
+	 */
+	while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
+	      (HPCDMA_XIU | HPCDMA_ETXD))
+		td = (struct sgiseeq_tx_desc *)
+			KSEG1ADDR(td->tdma.pnext);
+	if(td->tdma.cntinfo & HPCDMA_XIU) {
+		hregs->tx_ndptr = PHYSADDR(td);
+		hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
+	}
+}
+
 static inline void sgiseeq_tx(struct device *dev, struct sgiseeq_private *sp,
 			      volatile struct hpc3_ethregs *hregs,
 			      volatile struct sgiseeq_regs *sregs)
@@ -361,32 +383,14 @@
 
 	tx_maybe_reset_collisions(sp, sregs);
 
-	if(!(status & HPC3_ETXCTRL_ACTIVE)) {
-		if(!(status & SEEQ_TSTAT_PTRANS)) {
-			/* Oops, HPC detected some sort of error. */
-			if(status & SEEQ_TSTAT_R16)
-				sp->stats.tx_aborted_errors++;
-			if(status & SEEQ_TSTAT_UFLOW)
-				sp->stats.tx_fifo_errors++;
-			if(status & SEEQ_TSTAT_LCLS)
-				sp->stats.collisions++;
-		}
-		/* If the HPC aint doin nothin, and there are more packets
-		 * with ETXD cleared and XIU set we must make very certain
-		 * that we restart the HPC else we risk locking up the
-		 * adapter.  The following read of tx_ndptr is only safe
-		 * iff the HPCDMA is not active!
-		 */
-		td = (struct sgiseeq_tx_desc *)
-			KSEG1ADDR(((hregs->tx_ndptr) & ~0xf));
-		while((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
-		      (HPCDMA_XIU | HPCDMA_ETXD))
-			td = (struct sgiseeq_tx_desc *)
-				KSEG1ADDR(td->tdma.pnext);
-		if(td->tdma.cntinfo & HPCDMA_XIU) {
-			hregs->tx_ndptr = PHYSADDR(td);
-			hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
-		}
+	if(!(status & (HPC3_ETXCTRL_ACTIVE | SEEQ_TSTAT_PTRANS))) {
+		/* Oops, HPC detected some sort of error. */
+		if(status & SEEQ_TSTAT_R16)
+			sp->stats.tx_aborted_errors++;
+		if(status & SEEQ_TSTAT_UFLOW)
+			sp->stats.tx_fifo_errors++;
+		if(status & SEEQ_TSTAT_LCLS)
+			sp->stats.collisions++;
 	}
 
 	/* Ack 'em... */
@@ -395,8 +399,13 @@
 
 		if(!(td->tdma.cntinfo & (HPCDMA_XIU)))
 			break;
-		if(!(td->tdma.cntinfo & (HPCDMA_ETXD)))
+		if(!(td->tdma.cntinfo & (HPCDMA_ETXD))) {
+			if(!(status & HPC3_ETXCTRL_ACTIVE)) {
+				hregs->tx_ndptr = PHYSADDR(td);
+				hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
+			}
 			break;
+		}
 		sp->stats.tx_packets++;
 		sp->tx_old = NEXT_TX(sp->tx_old);
 		td->tdma.cntinfo &= ~(HPCDMA_XIU | HPCDMA_XIE);
@@ -501,13 +510,14 @@
 	/* Are we bolixed? */
 	if(dev->tbusy) {
 		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 20)
+			return 1;
 
 		printk("%s: transmit timed out, ticks=%d resetting\n",
 		       dev->name, tickssofar);
 		sgiseeq_reset(dev);
 		return 0;
 	}
-
 	/* Are we getting in someone else's way? */
 	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		printk("%s: Transmitter access conflict.\n", dev->name);
@@ -565,10 +575,9 @@
 	sp->tx_new = NEXT_TX(sp->tx_new); /* Advance. */
 
 	/* Maybe kick the HPC back into motion. */
-	if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE)) {
-		hregs->tx_ndptr = PHYSADDR(&sp->srings.tx_desc[sp->tx_old]);
-		hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
-	}
+	if(!(hregs->tx_ctrl & HPC3_ETXCTRL_ACTIVE))
+		kick_tx(&sp->srings.tx_desc[sp->tx_old], hregs);
+
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
 
@@ -656,15 +665,17 @@
 	sp->name = sgiseeqstr;
 
 	sp->srings.rx_desc = (struct sgiseeq_rx_desc *)
-		(KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0])));
+	                     (KSEG1ADDR(ALIGNED(&sp->srings.rxvector[0])));
+	dma_cache_wback_inv((unsigned long)&sp->srings.rxvector,
+	                    sizeof(sp->srings.rxvector));
 	sp->srings.tx_desc = (struct sgiseeq_tx_desc *)
-		(KSEG1ADDR(ALIGNED(&sp->srings.txvector[0])));
-	flush_cache_all();
+	                     (KSEG1ADDR(ALIGNED(&sp->srings.txvector[0])));
+	dma_cache_wback_inv((unsigned long)&sp->srings.txvector,
+	                    sizeof(sp->srings.txvector));
 
 	/* A couple calculations now, saves many cycles later. */
 	setup_rx_ring(sp->srings.rx_desc, SEEQ_RX_BUFFERS);
 	setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
-	flush_cache_all();
 
 	/* Reset the chip. */
 	hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs);
diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.1.100/linux/drivers/net/sunhme.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/net/sunhme.c	Fri May  8 00:20:47 1998
@@ -58,6 +58,70 @@
 #undef SXDEBUG
 #undef RXDEBUG
 #undef TXDEBUG
+#undef TXLOGGING
+
+#ifdef TXLOGGING
+struct hme_tx_logent {
+	unsigned int tstamp;
+	int tx_new, tx_old;
+	unsigned int action;
+#define TXLOG_ACTION_IRQ	0x01
+#define TXLOG_ACTION_TXMIT	0x02
+#define TXLOG_ACTION_TBUSY	0x04
+#define TXLOG_ACTION_NBUFS	0x08
+	unsigned int status;
+};
+#define TX_LOG_LEN	128
+static struct hme_tx_logent tx_log[TX_LOG_LEN];
+static int txlog_cur_entry = 0;
+static __inline__ void tx_add_log(struct happy_meal *hp, unsigned int a, unsigned int s)
+{
+	struct hme_tx_logent *tlp;
+	unsigned long flags;
+
+	save_and_cli(flags);
+	tlp = &tx_log[txlog_cur_entry];
+	tlp->tstamp = (unsigned int)jiffies;
+	tlp->tx_new = hp->tx_new;
+	tlp->tx_old = hp->tx_old;
+	tlp->action = a;
+	tlp->status = s;
+	txlog_cur_entry = (txlog_cur_entry + 1) & (TX_LOG_LEN - 1);
+	restore_flags(flags);
+}
+static __inline__ void tx_dump_log(void)
+{
+	int i, this;
+
+	this = txlog_cur_entry;
+	for(i = 0; i < TX_LOG_LEN; i++) {
+		printk("TXLOG[%d]: j[%08x] tx[N(%d)O(%d)] action[%08x] stat[%08x]\n", i,
+		       tx_log[this].tstamp,
+		       tx_log[this].tx_new, tx_log[this].tx_old,
+		       tx_log[this].action, tx_log[this].status);
+		this = (this + 1) & (TX_LOG_LEN - 1);
+	}
+}
+static __inline__ void tx_dump_ring(struct happy_meal *hp)
+{
+	struct hmeal_init_block *hb = hp->happy_block;
+	struct happy_meal_txd *tp = &hb->happy_meal_txd[0];
+	int i;
+
+	for(i = 0; i < TX_RING_SIZE; i+=4) {
+		printk("TXD[%d..%d]: [%08x:%08x] [%08x:%08x] [%08x:%08x] [%08x:%08x]\n",
+		       i, i + 4,
+		       le32_to_cpu(tp[i].tx_flags), le32_to_cpu(tp[i].tx_addr),
+		       le32_to_cpu(tp[i + 1].tx_flags), le32_to_cpu(tp[i + 1].tx_addr),
+		       le32_to_cpu(tp[i + 2].tx_flags), le32_to_cpu(tp[i + 2].tx_addr),
+		       le32_to_cpu(tp[i + 3].tx_flags), le32_to_cpu(tp[i + 3].tx_addr));
+	}
+}
+#else
+#define tx_add_log(hp, a, s)		do { } while(0)
+#define tx_dump_log()			do { } while(0)
+#define tx_dump_ring(hp)		do { } while(0)
+#endif
 
 #ifdef HMEDEBUG
 #define HMD(x)  printk x
@@ -73,7 +137,7 @@
 #define ASD(x)
 #endif
 
-#define DEFAULT_IPG0      32 /* For lance-mode only */
+#define DEFAULT_IPG0      16 /* For lance-mode only */
 #define DEFAULT_IPG1       8 /* For all modes */
 #define DEFAULT_IPG2       4 /* For all modes */
 #define DEFAULT_JAMSIZE    4 /* Toe jam */
@@ -376,18 +440,33 @@
 			full = 0;
 	}
 
-	/* XXX This may not be enough, we may need to reinit the entire
-	 * XXX Happy Meal front end for this to work every time.
+	/* Before changing other bits in the tx_cfg register, and in
+	 * general any of other the TX config registers too, you
+	 * must:
+	 * 1) Clear Enable
+	 * 2) Poll with reads until that bit reads back as zero
+	 * 3) Make TX configuration changes
+	 * 4) Set Enable once more
 	 */
-	if(full)
+	hme_write32(hp, &hp->bigmacregs->tx_cfg,
+		    hme_read32(hp, &hp->bigmacregs->tx_cfg) &
+		    ~(BIGMAC_TXCFG_ENABLE));
+	while(hme_read32(hp, &hp->bigmacregs->tx_cfg) & BIGMAC_TXCFG_ENABLE)
+		barrier();
+	if(full) {
+		hp->happy_flags |= HFLAG_FULL;
 		hme_write32(hp, &hp->bigmacregs->tx_cfg,
 			    hme_read32(hp, &hp->bigmacregs->tx_cfg) |
 			    BIGMAC_TXCFG_FULLDPLX);
-	else
+	} else {
+		hp->happy_flags &= ~(HFLAG_FULL);
 		hme_write32(hp, &hp->bigmacregs->tx_cfg,
 			    hme_read32(hp, &hp->bigmacregs->tx_cfg) &
 			    ~(BIGMAC_TXCFG_FULLDPLX));
-
+	}
+	hme_write32(hp, &hp->bigmacregs->tx_cfg,
+		    hme_read32(hp, &hp->bigmacregs->tx_cfg) |
+		    BIGMAC_TXCFG_ENABLE);
 	return 0;
 no_response:
 	return 1;
@@ -1220,8 +1299,8 @@
 	/* Load up the MAC address and random seed. */
 	HMD(("rseed/macaddr, "));
 
-	/* XXX use something less deterministic... */
-	hme_write32(hp, &bregs->rand_seed, 0xbd);
+	/* The docs recommend to use the 10LSB of our MAC here. */
+	hme_write32(hp, &bregs->rand_seed, ((e[5] | e[4]<<8)&0x3ff));
 
 	hme_write32(hp, &bregs->mac_addr2, ((e[4] << 8) | e[5]));
 	hme_write32(hp, &bregs->mac_addr1, ((e[2] << 8) | e[3]));
@@ -2013,7 +2092,7 @@
 		hp->dev->tbusy = 0;
 		mark_bh(NET_BH);
 	}
-
+	tx_add_log(hp, TXLOG_ACTION_IRQ, happy_status);
 	dev->interrupt = 0;
 	HMD(("done\n"));
 }
@@ -2154,29 +2233,29 @@
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
 
-	if(dev->tbusy) {
+	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		int tickssofar = jiffies - dev->trans_start;
 	    
-		if (tickssofar < 40) {
-			return 1;
-		} else {
+		if (tickssofar >= 40) {
 			printk ("%s: transmit timed out, resetting\n", dev->name);
 			hp->net_stats.tx_errors++;
+			tx_dump_log();
+			printk ("%s: Happy Status %08x TX[%08x:%08x]\n", dev->name,
+				hme_read32(hp, &hp->gregs->stat),
+				hme_read32(hp, &hp->etxregs->cfg),
+				hme_read32(hp, &hp->bigmacregs->tx_cfg));
 			happy_meal_init(hp, 0);
 			dev->tbusy = 0;
 			dev->trans_start = jiffies;
-			return 0;
-		}
-	}
-
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("happy meal: Transmitter access conflict.\n");
+		} else
+			tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0);
 		return 1;
 	}
 
-	if(!TX_BUFFS_AVAIL(hp))
+	if(!TX_BUFFS_AVAIL(hp)) {
+		tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
 		return 1;
-
+	}
 	len = skb->len;
 	entry = hp->tx_new;
 
@@ -2194,6 +2273,7 @@
 	if(TX_BUFFS_AVAIL(hp))
 		dev->tbusy = 0;
 
+	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
 	return 0;
 }
 
@@ -2203,29 +2283,32 @@
 	struct happy_meal *hp = (struct happy_meal *) dev->priv;
 	int len, entry;
 
-	if(dev->tbusy) {
+	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
 		int tickssofar = jiffies - dev->trans_start;
 	    
-		if (tickssofar < 40) {
-			return 1;
-		} else {
+		if (tickssofar >= 40) {
+			unsigned long flags;
+
 			printk ("%s: transmit timed out, resetting\n", dev->name);
+
+			save_and_cli(flags);
+			tx_dump_log();
+			tx_dump_ring(hp);
+			restore_flags(flags);
+
 			hp->net_stats.tx_errors++;
 			happy_meal_init(hp, 0);
 			dev->tbusy = 0;
 			dev->trans_start = jiffies;
-			return 0;
-		}
-	}
-
-	if(test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("happy meal: Transmitter access conflict.\n");
+		} else
+			tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_TBUSY, 0);
 		return 1;
 	}
 
-	if(!TX_BUFFS_AVAIL(hp))
+	if(!TX_BUFFS_AVAIL(hp)) {
+		tx_add_log(hp, TXLOG_ACTION_TXMIT|TXLOG_ACTION_NBUFS, 0);
 		return 1;
-
+	}
 	len = skb->len;
 	entry = hp->tx_new;
 
@@ -2243,6 +2326,7 @@
 	if(TX_BUFFS_AVAIL(hp))
 		dev->tbusy = 0;
 
+	tx_add_log(hp, TXLOG_ACTION_TXMIT, 0);
 	return 0;
 }
 #endif
@@ -2629,6 +2713,11 @@
 	pcibios_write_config_word(pdev->bus->number,
 				  pdev->devfn,
 				  PCI_COMMAND, pci_command);
+
+	/* Set the latency timer as well, PROM leaves it at zero. */
+	pcibios_write_config_byte(pdev->bus->number,
+				  pdev->devfn,
+				  PCI_LATENCY_TIMER, 240);
 
 #ifdef MODULE
 	/* We are home free at this point, link us in to the happy
diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h
--- v2.1.100/linux/drivers/net/sunhme.h	Thu Sep  4 13:25:28 1997
+++ linux/drivers/net/sunhme.h	Fri May  8 00:20:47 1998
@@ -468,9 +468,9 @@
 			    (hp)->tx_old - (hp)->tx_new - 1)
 
 #define RX_OFFSET          2
-#define RX_BUF_ALLOC_SIZE  (ETH_FRAME_LEN + RX_OFFSET + (64 * 3))
+#define RX_BUF_ALLOC_SIZE  (1546 + RX_OFFSET + 64)
 
-#define RX_COPY_THRESHOLD  128
+#define RX_COPY_THRESHOLD  256
 
 struct hmeal_init_block {
 	struct happy_meal_rxd happy_meal_rxd[RX_RING_MAXSIZE];
diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.1.100/linux/drivers/net/sunlance.c	Sat Apr 25 18:13:11 1998
+++ linux/drivers/net/sunlance.c	Fri May  8 00:20:48 1998
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.74 1998/02/12 07:37:25 davem Exp $
+/* $Id: sunlance.c,v 1.75 1998/04/24 12:29:50 davem Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *	Written 1995, 1996 by Miguel de Icaza
diff -u --recursive --new-file v2.1.100/linux/drivers/net/sunqe.h linux/drivers/net/sunqe.h
--- v2.1.100/linux/drivers/net/sunqe.h	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/sunqe.h	Fri May  8 00:20:48 1998
@@ -309,8 +309,8 @@
 	  (qp)->tx_old - (qp)->tx_new - (TX_RING_SIZE - SUN4C_TX_RING_SIZE))
 
 
-#define RX_COPY_THRESHOLD  128
-#define RX_BUF_ALLOC_SIZE  (ETH_FRAME_LEN + (64 * 3))
+#define RX_COPY_THRESHOLD  256
+#define RX_BUF_ALLOC_SIZE  (1546 + 64)
 
 struct qe_init_block {
 	struct qe_rxd qe_rxd[RX_RING_MAXSIZE];
diff -u --recursive --new-file v2.1.100/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.1.100/linux/drivers/net/yellowfin.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/yellowfin.c	Fri May  8 00:20:48 1998
@@ -0,0 +1,1309 @@
+/* yellowfin.c: A Packet Engines G-NIC ethernet driver for linux. */
+/*
+	Written 1997 by Donald Becker.
+
+	This software may be used and distributed according to the terms
+	of the GNU Public License, incorporated herein by reference.
+
+	This driver is for the Packet Engines G-NIC PCI Gigabit Ethernet adapter.
+
+	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+	Center of Excellence in Space Data and Information Sciences
+	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+	Support and updates available at
+	http://cesdis.gsfc.nasa.gov/linux/drivers/yellowfin.html
+*/
+
+static const char *version = "yellowfin.c:v0.10 12/5/97 becker@cesdis.gsfc.nasa.gov\n";
+
+/* A few user-configurable values. */
+
+static int max_interrupt_work = 20;
+static int min_pci_latency = 64;
+static int mtu = 0;
+#ifdef YF_PROTOTYPE			/* Support for prototype hardware errata. */
+/* System-wide count of bogus-rx frames. */
+static int bogus_rx = 0;
+static int dma_ctrl = 0x004A0263; 			/* Constrained by errata */
+static int fifo_cfg = 0x0020;				/* Bypass external Tx FIFO. */
+#elif YF_NEW
+static int dma_ctrl = 0x00CAC277;			/* Override when loading module! */
+static int fifo_cfg = 0x0028;
+#else
+static int dma_ctrl = 0x004A0263; 			/* Constrained by errata */
+static int fifo_cfg = 0x0020;				/* Bypass external Tx FIFO. */
+#endif
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
+   Setting to > 1518 effectively disables this feature. */
+static const rx_copybreak = 100;
+
+/* Keep the ring sizes a power of two for efficiency.
+   Making the Tx ring too large decreases the effectiveness of channel
+   bonding and packet priority.
+   There are no ill effects from too-large receive rings. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  ((2000*HZ)/1000)
+
+#include <linux/config.h>
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <asm/processor.h>		/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+   This is only in the support-all-kernels source code. */
+#include <linux/version.h>		/* Evil, but neccessary */
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
+#define RUN_AT(x) (x)			/* What to put in timer->expires.  */
+#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
+#define virt_to_bus(addr)  ((unsigned long)addr)
+#define bus_to_virt(addr) ((void*)addr)
+
+#else  /* 1.3.0 and later */
+#define RUN_AT(x) (jiffies + (x))
+#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+#endif
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
+#ifdef MODULE
+#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
+char kernel_version[] = UTS_RELEASE;
+#endif
+#else
+#undef MOD_INC_USE_COUNT
+#define MOD_INC_USE_COUNT
+#undef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+#endif /* 1.3.38 */
+
+#if (LINUX_VERSION_CODE >= 0x10344)
+#define NEW_MULTICAST
+#include <linux/delay.h>
+#endif
+#if (LINUX_VERSION_CODE >= 0x20100)
+#ifdef MODULE
+char kernel_version[] = UTS_RELEASE;
+#endif
+#endif
+#ifdef SA_SHIRQ
+#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
+#else
+#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+#endif
+#if (LINUX_VERSION_CODE < 0x20123)
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#include <linux/bios32.h>
+#endif
+
+static const char *card_name = "Yellowfin G-NIC Gbit Ethernet";
+
+/* The PCI I/O space extent. */
+#define YELLOWFIN_TOTAL_SIZE 0x100
+
+#ifdef HAVE_DEVLIST
+struct netdev_entry yellowfin_drv =
+{card_name, yellowfin_pci_probe, YELLOWFIN_TOTAL_SIZE, NULL};
+#endif
+
+#ifdef YELLOWFIN_DEBUG
+int yellowfin_debug = YELLOWFIN_DEBUG;
+#else
+int yellowfin_debug = 1;
+#endif
+
+/*
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the Packet Engines "Yellowfin" Gigabit
+Ethernet adapter.  The only PCA currently supported is the G-NIC 64-bit
+PCI card.
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS preferably should assign the
+PCI INTA signal to an otherwise unused system IRQ line.
+Note: Kernel versions earlier than 1.3.73 do not support shared PCI
+interrupt lines.
+
+III. Driver operation
+
+IIIa. Ring buffers
+
+The Yellowfin uses the Descriptor Based DMA Architecture specified by Apple.
+This is a descriptor list scheme similar to that used by the EEPro100 and
+Tulip.  This driver uses two statically allocated fixed-size descriptor lists
+formed into rings by a branch from the final descriptor to the beginning of
+the list.  The ring sizes are set at compile time by RX/TX_RING_SIZE.
+
+The driver allocates full frame size skbuffs for the Rx ring buffers at
+open() time and passes the skb->data field to the Yellowfin as receive data
+buffers.  When an incoming frame is less than RX_COPYBREAK bytes long,
+a fresh skbuff is allocated and the frame is copied to the new skbuff.
+When the incoming frame is larger, the skbuff is passed directly up the
+protocol stack and replaced by a newly allocated skbuff.
+
+The RX_COPYBREAK value is chosen to trade-off the memory wasted by
+using a full-sized skbuff for small frames vs. the copying costs of larger
+frames.  For small frames the copying cost is negligible (esp. considering
+that we are pre-loading the cache with immediately useful header
+information).  For large frames the copying cost is non-trivial, and the
+larger copy might flush the cache of useful data.
+
+IIIC. Synchronization
+
+The driver runs as two independent, single-threaded flows of control.  One
+is the send-packet routine, which enforces single-threaded use by the
+dev->tbusy flag.  The other thread is the interrupt handler, which is single
+threaded by the hardware and other software.
+
+The send packet thread has partial control over the Tx ring and 'dev->tbusy'
+flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
+queue slot is empty, it clears the tbusy flag when finished otherwise it sets
+the 'yp->tx_full' flag.
+
+The interrupt handler has exclusive control over the Rx ring and records stats
+from the Tx ring.  After reaping the stats, it marks the Tx queue entry as
+empty by incrementing the dirty_tx mark. Iff the 'yp->tx_full' flag is set, it
+clears both the tx_full and tbusy flags.
+
+IV. Notes
+
+Thanks to Kim Stearns of Packet Engines for providing a pair of G-NIC boards.
+
+IVb. References
+
+Yellowfin Engineering Design Specification, 4/23/97 Preliminary/Confidential
+http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html
+
+IVc. Errata
+
+See Packet Engines confidential appendix.
+
+*/
+
+/* A few values that may be tweaked. */
+#define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
+
+#ifndef PCI_VENDOR_ID_PKT_ENG		/* To be defined in linux/pci.h */
+#define PCI_VENDOR_ID_PKT_ENG			0x1000 /* Hmm, likely number.. */
+#define PCI_DEVICE_ID_YELLOWFIN			0x0702
+#endif
+
+/* The rest of these values should never change. */
+
+static void yellowfin_timer(unsigned long data);
+
+/* Offsets to the Yellowfin registers.  Various sizes and alignments. */
+enum yellowfin_offsets {
+	TxCtrl=0x00, TxStatus=0x04, TxPtr=0x0C,
+	TxIntrSel=0x10, TxBranchSel=0x14, TxWaitSel=0x18,
+	RxCtrl=0x40, RxStatus=0x44, RxPtr=0x4C,
+	RxIntrSel=0x50, RxBranchSel=0x54, RxWaitSel=0x58,
+	EventStatus=0x80, IntrEnb=0x82, IntrClear=0x84, IntrStatus=0x86,
+	ChipRev=0x8C, DMACtrl=0x90, Cnfg=0xA0, RxDepth=0xB8, FlowCtrl=0xBC,
+	AddrMode=0xD0, StnAddr=0xD2, HashTbl=0xD8, FIFOcfg=0xF8,
+};
+
+/* The Yellowfin Rx and Tx buffer descriptors. */
+struct yellowfin_desc {
+	u16 request_cnt;
+	u16 cmd;
+	u32 addr;
+	u32 branch_addr;
+	u16 result_cnt;
+	u16 status;
+};
+
+struct tx_status_words {
+	u16 tx_cnt;
+	u16 tx_errs;
+	u16 total_tx_cnt;
+	u16 paused;
+};
+
+/* Bits in yellowfin_desc.cmd */
+enum desc_cmd_bits {
+	CMD_TX_PKT=0x1000, CMD_RX_BUF=0x2000, CMD_TXSTATUS=0x3000,
+	CMD_NOP=0x6000, CMD_STOP=0x7000,
+	BRANCH_ALWAYS=0x0C, INTR_ALWAYS=0x30, WAIT_ALWAYS=0x03,
+	BRANCH_IFTRUE=0x04,
+};
+
+/* Bits in yellowfin_desc.status */
+enum desc_status_bits { RX_EOP=0x0040, };
+
+/* Bits in the interrupt status/mask registers. */
+enum intr_status_bits {
+	IntrRxDone=0x01, IntrRxInvalid=0x02, IntrRxPCIFault=0x04,IntrRxPCIErr=0x08,
+	IntrTxDone=0x10, IntrTxInvalid=0x20, IntrTxPCIFault=0x40,IntrTxPCIErr=0x80,
+	IntrEarlyRx=0x100, IntrWakeup=0x200, };
+
+struct yellowfin_private {
+	/* Descriptor rings first for alignment.  Tx requires a second descriptor
+	   for status. */
+	struct yellowfin_desc rx_ring[RX_RING_SIZE];
+	struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
+	const char *product_name;
+	struct device *next_module;
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	struct tx_status_words tx_status[TX_RING_SIZE];
+	/* The addresses of receive-in-place skbuffs. */
+	struct sk_buff* rx_skbuff[RX_RING_SIZE];
+	int chip_id;
+	struct enet_statistics stats;
+	struct timer_list timer;	/* Media selection timer. */
+	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
+	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+	unsigned int tx_full:1;				/* The Tx queue is full. */
+	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+	unsigned int medialock:1;			/* Do not sense media. */
+	unsigned int default_port:4;		/* Last dev->if_port value. */
+	u32 pad[4];							/* Used for 32-byte alignment */
+};
+
+#ifdef MODULE
+/* Used to pass the media type, etc. */
+#define MAX_UNITS 8				/* More are supported, limit only on options */
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+#if LINUX_VERSION_CODE > 0x20115
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("Packet Engines Yellowfin G-NIC Gigabit Ethernet driver");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(min_pci_latency, "i");
+MODULE_PARM(mtu, "i");
+MODULE_PARM(debug, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+#endif
+
+#endif
+
+static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq,
+								   int chip_id, int options);
+static int yellowfin_open(struct device *dev);
+static void yellowfin_timer(unsigned long data);
+static void yellowfin_tx_timeout(struct device *dev);
+static void yellowfin_init_ring(struct device *dev);
+static int yellowfin_start_xmit(struct sk_buff *skb, struct device *dev);
+static int yellowfin_rx(struct device *dev);
+static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs);
+static int yellowfin_close(struct device *dev);
+static struct enet_statistics *yellowfin_get_stats(struct device *dev);
+#ifdef NEW_MULTICAST
+static void set_rx_mode(struct device *dev);
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+
+
+
+#ifdef MODULE
+/* A list of all installed Yellowfin devices, for removing the driver module. */
+static struct device *root_yellowfin_dev = NULL;
+#endif
+
+int yellowfin_probe(struct device *dev)
+{
+	int cards_found = 0;
+	static int pci_index = 0;	/* Static, for multiple probe calls. */
+
+	/* Ideally we would detect all network cards in slot order.  That would
+	   be best done a central PCI probe dispatch, which wouldn't work
+	   well with the current structure.  So instead we detect just the
+	   Yellowfin cards in slot order. */
+
+	if (pci_present()) {
+		unsigned char pci_bus, pci_device_fn;
+
+		for (;pci_index < 0xff; pci_index++) {
+#if LINUX_VERSION_CODE >= 0x20155
+			unsigned int pci_irq_line;
+			struct pci_dev *pdev;
+#else
+			unsigned char pci_irq_line;
+#endif
+			unsigned char pci_latency;
+			unsigned short pci_command, vendor, device;
+			unsigned int pci_ioaddr, chip_idx = 0;
+
+#ifdef REVERSE_PROBE_ORDER
+			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+									0xfe - pci_index,
+									&pci_bus, &pci_device_fn)
+				!= PCIBIOS_SUCCESSFUL)
+				continue;
+#else
+			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+									pci_index,
+									&pci_bus, &pci_device_fn)
+				!= PCIBIOS_SUCCESSFUL)
+				break;
+#endif
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_VENDOR_ID, &vendor);
+			pcibios_read_config_word(pci_bus, pci_device_fn,
+									 PCI_DEVICE_ID, &device);
+#if LINUX_VERSION_CODE >= 0x20155
+			pdev = pci_find_slot(pci_bus, pci_device_fn);
+			pci_irq_line = pdev->irq;
+			pci_ioaddr = pdev->base_address[0];
+#else
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+									 PCI_INTERRUPT_LINE, &pci_irq_line);
+			pcibios_read_config_dword(pci_bus, pci_device_fn,
+									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+#endif
+			/* Remove I/O space marker in bit 0. */
+			pci_ioaddr &= ~3;
+
+			if (vendor != PCI_VENDOR_ID_PKT_ENG)
+				continue;
+
+			if (device != PCI_DEVICE_ID_YELLOWFIN)
+				continue;
+
+			if (yellowfin_debug > 2)
+				printk("Found Packet Engines Yellowfin G-NIC at I/O %#x, IRQ %d.\n",
+					   pci_ioaddr, pci_irq_line);
+
+			if (check_region(pci_ioaddr, YELLOWFIN_TOTAL_SIZE))
+				continue;
+
+#ifdef MODULE
+			dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
+						 cards_found < MAX_UNITS ? options[cards_found] : 0);
+#else
+			dev = yellowfin_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
+						 dev ? dev->mem_start : 0);
+#endif
+
+			if (dev) {
+			  /* Get and check the bus-master and latency values. */
+			  pcibios_read_config_word(pci_bus, pci_device_fn,
+									   PCI_COMMAND, &pci_command);
+			  if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+				printk("  PCI Master Bit has not been set! Setting...\n");
+				pci_command |= PCI_COMMAND_MASTER;
+				pcibios_write_config_word(pci_bus, pci_device_fn,
+										  PCI_COMMAND, pci_command);
+			  }
+			  pcibios_read_config_byte(pci_bus, pci_device_fn,
+									   PCI_LATENCY_TIMER, &pci_latency);
+			  if (pci_latency < min_pci_latency) {
+				printk("  PCI latency timer (CFLT) is unreasonably low at %d."
+					   "  Setting to %d clocks.\n",
+					   pci_latency, min_pci_latency);
+				pcibios_write_config_byte(pci_bus, pci_device_fn,
+										  PCI_LATENCY_TIMER, min_pci_latency);
+			  } else if (yellowfin_debug > 1)
+				printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
+			  dev = 0;
+			  cards_found++;
+			}
+		}
+	}
+
+#if defined (MODULE)
+	return cards_found;
+#else
+	return 0;
+#endif
+}
+
+static struct device *yellowfin_probe1(struct device *dev, int ioaddr, int irq,
+								   int chip_id, int options)
+{
+	static int did_version = 0;			/* Already printed version info. */
+	struct yellowfin_private *yp;
+	int i;
+
+	if (yellowfin_debug > 0  &&  did_version++ == 0)
+		printk(version);
+
+	dev = init_etherdev(dev, sizeof(struct yellowfin_private));
+
+	printk("%s: P-E Yellowfin type %8x at %#3x, ",
+		   dev->name, inl(ioaddr + ChipRev), ioaddr);
+
+	for (i = 0; i < 5; i++)
+		printk("%2.2x:", inb(ioaddr + StnAddr + i));
+	printk("%2.2x, IRQ %d.\n", inb(ioaddr + StnAddr + i), irq);
+	for (i = 0; i < 6; i++)
+		dev->dev_addr[i] = inb(ioaddr + StnAddr + i);
+
+	/* Reset the chip. */
+	outl(0x80000000, ioaddr + DMACtrl);
+
+
+	/* We do a request_region() only to register /proc/ioports info. */
+	request_region(ioaddr, YELLOWFIN_TOTAL_SIZE, card_name);
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	/* Make certain the descriptor lists are aligned. */
+	yp = (void *)(((long)kmalloc(sizeof(*yp), GFP_KERNEL) + 31) & ~31);
+	memset(yp, 0, sizeof(*yp));
+	dev->priv = yp;
+
+#ifdef MODULE
+	yp->next_module = root_yellowfin_dev;
+	root_yellowfin_dev = dev;
+#endif
+
+	yp->chip_id = chip_id;
+
+	yp->full_duplex = 1;
+#ifdef YELLOWFIN_DEFAULT_MEDIA
+	yp->default_port = YELLOWFIN_DEFAULT_MEDIA;
+#endif
+#ifdef YELLOWFIN_NO_MEDIA_SWITCH
+	yp->medialock = 1;
+#endif
+
+	/* The lower four bits are the media type. */
+	if (options > 0) {
+		yp->full_duplex = (options & 16) ? 1 : 0;
+		yp->default_port = options & 15;
+		if (yp->default_port)
+			yp->medialock = 1;
+	}
+
+	/* The Yellowfin-specific entries in the device structure. */
+	dev->open = &yellowfin_open;
+	dev->hard_start_xmit = &yellowfin_start_xmit;
+	dev->stop = &yellowfin_close;
+	dev->get_stats = &yellowfin_get_stats;
+	dev->set_multicast_list = &set_rx_mode;
+	if (mtu)
+		dev->mtu = mtu;
+
+	/* todo: Reset the xcvr interface and turn on heartbeat. */
+
+	return dev;
+}
+
+
+static int
+yellowfin_open(struct device *dev)
+{
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+
+	/* Reset the chip. */
+	outl(0x80000000, ioaddr + DMACtrl);
+
+#ifdef SA_SHIRQ
+	if (request_irq(dev->irq, &yellowfin_interrupt, SA_SHIRQ,
+					card_name, dev)) {
+		return -EAGAIN;
+	}
+#else
+	if (irq2dev_map[dev->irq] != NULL
+		|| (irq2dev_map[dev->irq] = dev) == NULL
+		|| dev->irq == 0
+		|| request_irq(dev->irq, &yellowfin_interrupt, 0, card_name)) {
+		return -EAGAIN;
+	}
+#endif
+
+	if (yellowfin_debug > 1)
+		printk("%s: yellowfin_open() irq %d.\n", dev->name, dev->irq);
+
+	MOD_INC_USE_COUNT;
+
+	yellowfin_init_ring(dev);
+
+	outl(virt_to_bus(yp->rx_ring), ioaddr + RxPtr);
+	outl(virt_to_bus(yp->tx_ring), ioaddr + TxPtr);
+
+	/* Set up various condition 'select' registers.
+	   There are no options here. */
+	outl(0x00800080, ioaddr + TxIntrSel); 	/* Interrupt on Tx abort */
+	outl(0x00800080, ioaddr + TxBranchSel);	/* Branch on Tx abort */
+	outl(0x00400040, ioaddr + TxWaitSel); 	/* Wait on Tx status */
+	outl(0x00400040, ioaddr + RxIntrSel);	/* Interrupt on Rx done */
+	outl(0x00400040, ioaddr + RxBranchSel);	/* Branch on Rx error */
+	outl(0x00400040, ioaddr + RxWaitSel);	/* Wait on Rx done */
+
+	/* Initialize other registers: with so many this eventually this will
+	   converted to an offset/value list. */
+	outl(dma_ctrl, ioaddr + DMACtrl);
+	outw(fifo_cfg, ioaddr + FIFOcfg);
+	/* Enable automatic generation of flow control frames, period 0xffff. */
+	outl(0x0030FFFF, ioaddr + FlowCtrl);
+
+	if (dev->if_port == 0)
+		dev->if_port = yp->default_port;
+
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+
+	/* We are always in full-duplex mode with the current chip! */
+	yp->full_duplex = 1;
+
+	/* Setting the Rx mode will start the Rx process. */
+	outw(0x01CD | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
+#ifdef NEW_MULTICAST
+	set_rx_mode(dev);
+#else
+	set_rx_mode(dev, 0, 0);
+#endif
+
+	dev->start = 1;
+
+	/* Enable interrupts by setting the interrupt mask. */
+	outw(0x81ff, ioaddr + IntrEnb);			/* See enum intr_status_bits */
+	outw(0x0000, ioaddr + EventStatus);		/* Clear non-interrupting events */
+	outl(0x80008000, ioaddr + RxCtrl);		/* Start Rx and Tx channels. */
+	outl(0x80008000, ioaddr + TxCtrl);
+
+	if (yellowfin_debug > 2) {
+		printk("%s: Done yellowfin_open().\n",
+			   dev->name);
+	}
+	/* Set the timer to check for link beat. */
+	init_timer(&yp->timer);
+	yp->timer.expires = RUN_AT((24*HZ)/10);			/* 2.4 sec. */
+	yp->timer.data = (unsigned long)dev;
+	yp->timer.function = &yellowfin_timer;				/* timer handler */
+	add_timer(&yp->timer);
+
+	return 0;
+}
+
+static void yellowfin_timer(unsigned long data)
+{
+	struct device *dev = (struct device *)data;
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int next_tick = 0;
+
+	if (yellowfin_debug > 3) {
+		printk("%s: Yellowfin timer tick, status %8.8x.\n",
+			   dev->name, inl(ioaddr + IntrStatus));
+	}
+	if (next_tick) {
+		yp->timer.expires = RUN_AT(next_tick);
+		add_timer(&yp->timer);
+	}
+}
+
+static void yellowfin_tx_timeout(struct device *dev)
+{
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	int ioaddr = dev->base_addr;
+	int i;
+
+	printk("%s: Yellowfin transmit timed out, status %8.8x, resetting...\n",
+		   dev->name, inl(ioaddr));
+
+#ifndef __alpha__
+  printk("  Rx ring %8.8x: ", (int)yp->rx_ring);
+  for (i = 0; i < RX_RING_SIZE; i++)
+	printk(" %8.8x", (unsigned int)yp->rx_ring[i].status);
+  printk("\n  Tx ring %8.8x: ", (int)yp->tx_ring);
+  for (i = 0; i < TX_RING_SIZE; i++)
+	printk(" %4.4x /%4.4x", yp->tx_status[i].tx_errs, yp->tx_ring[i].status);
+  printk("\n");
+#endif
+
+  /* Perhaps we should reinitialize the hardware here. */
+  dev->if_port = 0;
+  /* Stop and restart the chip's Tx processes . */
+
+  /* Trigger an immediate transmit demand. */
+
+  dev->trans_start = jiffies;
+  yp->stats.tx_errors++;
+  return;
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void
+yellowfin_init_ring(struct device *dev)
+{
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	int i;
+
+	yp->tx_full = 0;
+	yp->cur_rx = yp->cur_tx = 0;
+	yp->dirty_rx = yp->dirty_tx = 0;
+
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb;
+		int pkt_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+
+		yp->rx_ring[i].request_cnt = pkt_buf_sz;
+		yp->rx_ring[i].cmd = CMD_RX_BUF | INTR_ALWAYS;
+
+		skb = DEV_ALLOC_SKB(pkt_buf_sz);
+		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
+		yp->rx_skbuff[i] = skb;
+		if (skb == NULL)
+			break;			/* Bad news!  */
+		skb->dev = dev;			/* Mark as being used by this device. */
+#if LINUX_VERSION_CODE > 0x10300
+		yp->rx_ring[i].addr = virt_to_bus(skb->tail);
+#else
+		yp->rx_ring[i].addr = virt_to_bus(skb->data);
+#endif
+		yp->rx_ring[i].branch_addr = virt_to_bus(&yp->rx_ring[i+1]);
+	}
+	/* Mark the last entry as wrapping the ring. */
+	yp->rx_ring[i-1].cmd = CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS;
+	yp->rx_ring[i-1].branch_addr = virt_to_bus(&yp->rx_ring[0]);
+
+/*#define NO_TXSTATS*/
+#ifdef NO_TXSTATS
+	/* In this mode the Tx ring needs only a single descriptor. */
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		yp->tx_skbuff[i] = 0;
+		yp->tx_ring[i].cmd = CMD_STOP;
+		yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
+	}
+	yp->tx_ring[--i].cmd = CMD_STOP | BRANCH_ALWAYS; /* Wrap ring */
+	yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]);
+#else
+	/* Tx ring needs a pair of descriptors, the second for the status. */
+	for (i = 0; i < TX_RING_SIZE*2; i++) {
+		yp->tx_skbuff[i/2] = 0;
+		yp->tx_ring[i].cmd = CMD_STOP; /* Branch on Tx error. */
+		yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
+		i++;
+		yp->tx_ring[i].cmd = CMD_TXSTATUS; /* Interrupt, no wait. */
+		yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]);
+		yp->tx_ring[i].addr = virt_to_bus(&yp->tx_status[i/2]);
+		yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[i+1]);
+	}
+	/* Wrap ring */
+	yp->tx_ring[--i].cmd = CMD_TXSTATUS | BRANCH_ALWAYS | INTR_ALWAYS;
+	yp->tx_ring[i].branch_addr = virt_to_bus(&yp->tx_ring[0]);
+#endif
+}
+
+static int
+yellowfin_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	unsigned entry;
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		if (jiffies - dev->trans_start < TX_TIMEOUT)
+			return 1;
+		yellowfin_tx_timeout(dev);
+		return 1;
+	}
+
+	/* Caution: the write order is important here, set the base address
+	   with the "ownership" bits last. */
+
+	/* Calculate the next Tx descriptor entry. */
+	entry = yp->cur_tx % TX_RING_SIZE;
+
+	yp->tx_skbuff[entry] = skb;
+
+#ifdef NO_TXSTATS
+	yp->tx_ring[entry].request_cnt = skb->len;
+	yp->tx_ring[entry].addr = virt_to_bus(skb->data);
+	yp->tx_ring[entry].status = 0;
+	if (entry >= TX_RING_SIZE-1) {
+		yp->tx_ring[0].cmd = CMD_STOP; /* New stop command. */
+		yp->tx_ring[TX_RING_SIZE-1].cmd = CMD_TX_PKT | BRANCH_ALWAYS;
+	} else {
+		yp->tx_ring[entry+1].cmd = CMD_STOP; /* New stop command. */
+		yp->tx_ring[entry].cmd = CMD_TX_PKT | BRANCH_IFTRUE;
+	}
+	yp->cur_tx++;
+#else
+	yp->tx_ring[entry<<1].request_cnt = skb->len;
+	yp->tx_ring[entry<<1].addr = virt_to_bus(skb->data);
+	/* The input_last (status-write) command is constant, but we must rewrite
+	   the subsequent 'stop' command. */
+
+	yp->cur_tx++;
+	{
+		unsigned next_entry = yp->cur_tx % TX_RING_SIZE;
+		yp->tx_ring[next_entry<<1].cmd = CMD_STOP;
+	}
+	/* Final step -- overwrite the old 'stop' command. */
+
+	yp->tx_ring[entry<<1].cmd =
+		(entry % 6) == 0 ? CMD_TX_PKT | INTR_ALWAYS | BRANCH_IFTRUE :
+		CMD_TX_PKT | BRANCH_IFTRUE;
+#endif
+
+	/* Todo: explicitly flush cache lines here. */
+
+	/* Wake the potentially-idle transmit channel. */
+	outl(0x10001000, dev->base_addr + TxCtrl);
+
+	if (yp->cur_tx - yp->dirty_tx < TX_RING_SIZE - 1)
+		dev->tbusy = 0;					/* Typical path */
+	else
+		yp->tx_full = 1;
+	dev->trans_start = jiffies;
+
+	if (yellowfin_debug > 4) {
+		printk("%s: Yellowfin transmit frame #%d queued in slot %d.\n",
+			   dev->name, yp->cur_tx, entry);
+	}
+	return 0;
+}
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void yellowfin_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+{
+#ifdef SA_SHIRQ		/* Use the now-standard shared IRQ implementation. */
+	struct device *dev = (struct device *)dev_instance;
+#else
+	struct device *dev = (struct device *)(irq2dev_map[irq]);
+#endif
+
+	struct yellowfin_private *lp;
+	int ioaddr, boguscnt = max_interrupt_work;
+
+	if (dev == NULL) {
+		printk ("yellowfin_interrupt(): irq %d for unknown device.\n", irq);
+		return;
+	}
+
+	ioaddr = dev->base_addr;
+	lp = (struct yellowfin_private *)dev->priv;
+	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+		return;
+	}
+
+	do {
+		u16 intr_status = inw(ioaddr + IntrClear);
+		unsigned dirty_tx = lp->dirty_tx;
+
+		if (yellowfin_debug > 4)
+			printk("%s: Yellowfin interrupt, status %4.4x.\n",
+				   dev->name, intr_status);
+
+		if (intr_status == 0)
+			break;
+
+		if (intr_status & (IntrRxDone | IntrEarlyRx))
+			yellowfin_rx(dev);
+
+#ifdef NO_TXSTATS
+		for (; dirty_tx < lp->cur_tx; dirty_tx++) {
+			int entry = dirty_tx % TX_RING_SIZE;
+			if (lp->tx_ring[entry].status == 0)
+				break;
+			/* Free the original skb. */
+			dev_kfree_skb(lp->tx_skbuff[entry]);
+			lp->tx_skbuff[entry] = 0;
+			lp->stats.tx_packets++;
+		}
+		if (lp->tx_full && dev->tbusy
+			&& dirty_tx > lp->cur_tx - TX_RING_SIZE + 4) {
+			/* The ring is no longer full, clear tbusy. */
+			lp->tx_full = 0;
+			dev->tbusy = 0;
+			mark_bh(NET_BH);
+		}
+		lp->dirty_tx = dirty_tx;
+#else
+		if (intr_status & IntrTxDone
+			|| lp->tx_status[dirty_tx % TX_RING_SIZE].tx_errs) {
+
+			for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+				/* Todo: optimize this. */
+				int entry = dirty_tx % TX_RING_SIZE;
+				u16 tx_errs = lp->tx_status[entry].tx_errs;
+
+				if (tx_errs == 0)
+					break;			/* It still hasn't been Txed */
+				if (tx_errs & 0xF8100000) {
+					/* There was an major error, log it. */
+#ifndef final_version
+					if (yellowfin_debug > 1)
+						printk("%s: Transmit error, Tx status %4.4x.\n",
+							   dev->name, tx_errs);
+#endif
+					lp->stats.tx_errors++;
+					if (tx_errs & 0xF800) lp->stats.tx_aborted_errors++;
+					if (tx_errs & 0x0800) lp->stats.tx_carrier_errors++;
+					if (tx_errs & 0x2000) lp->stats.tx_window_errors++;
+					if (tx_errs & 0x8000) lp->stats.tx_fifo_errors++;
+#ifdef ETHER_STATS
+					if (tx_errs & 0x1000) lp->stats.collisions16++;
+#endif
+				} else {
+#ifdef ETHER_STATS
+					if (status & 0x0400) lp->stats.tx_deferred++;
+#endif
+					lp->stats.collisions += tx_errs & 15;
+					lp->stats.tx_packets++;
+				}
+
+				/* Free the original skb. */
+				dev_kfree_skb(lp->tx_skbuff[entry]);
+				lp->tx_skbuff[entry] = 0;
+				/* Mark status as empty. */
+				lp->tx_status[entry].tx_errs = 0;
+			}
+
+#ifndef final_version
+			if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+				printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
+					   dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+				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;
+		}
+#endif
+
+		/* Log errors and other events. */
+		if (intr_status & 0x2ee) {	/* Abnormal error summary. */
+			printk("%s: Something Wicked happened! %4.4x.\n",
+				   dev->name, intr_status);
+			/* Hmmmmm, it's not clear what to do here. */
+			if (intr_status & (IntrTxPCIErr | IntrTxPCIFault))
+				lp->stats.tx_errors++;
+			if (intr_status & (IntrRxPCIErr | IntrRxPCIFault))
+				lp->stats.rx_errors++;
+		}
+		if (--boguscnt < 0) {
+			printk("%s: Too much work at interrupt, status=0x%4.4x.\n",
+				   dev->name, intr_status);
+			break;
+		}
+	} while (1);
+
+	if (yellowfin_debug > 3)
+		printk("%s: exiting interrupt, status=%#4.4x.\n",
+			   dev->name, inw(ioaddr + IntrStatus));
+
+	/* Code that should never be run!  Perhaps remove after testing.. */
+	{
+		static int stopit = 10;
+		if (dev->start == 0  &&  --stopit < 0) {
+			printk("%s: Emergency stop, looping startup interrupt.\n",
+				   dev->name);
+#ifdef SA_SHIRQ
+			free_irq(irq, dev);
+#else
+			free_irq(irq);
+#endif
+		}
+	}
+
+	dev->interrupt = 0;
+	return;
+}
+
+/* This routine is logically part of the interrupt handler, but seperated
+   for clarity and better register allocation. */
+static int
+yellowfin_rx(struct device *dev)
+{
+	struct yellowfin_private *lp = (struct yellowfin_private *)dev->priv;
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	int entry = lp->cur_rx % RX_RING_SIZE;
+	int boguscnt = 20;
+
+	if (yellowfin_debug > 4) {
+		printk(" In yellowfin_rx(), entry %d status %4.4x.\n", entry,
+			   yp->rx_ring[entry].status);
+		printk("   #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x.\n",
+			   entry, yp->rx_ring[entry].cmd,
+			   yp->rx_ring[entry].request_cnt, yp->rx_ring[entry].addr,
+			   yp->rx_ring[entry].result_cnt, yp->rx_ring[entry].status);
+	}
+
+
+	/* If EOP is set on the next entry, it's a new packet. Send it up. */
+	while (yp->rx_ring[entry].status) {
+		/* Todo: optimize this mess. */
+		u16 desc_status = yp->rx_ring[entry].status;
+		struct yellowfin_desc *desc = &lp->rx_ring[entry];
+		int frm_size = desc->request_cnt - desc->result_cnt;
+		u8 *buf_addr = bus_to_virt(lp->rx_ring[entry].addr);
+		s16 frame_status = *(s16*)&(buf_addr[frm_size - 2]);
+
+		if (yellowfin_debug > 4)
+			printk("  yellowfin_rx() status was %4.4x.\n", frame_status);
+		if (--boguscnt < 0)
+			break;
+		if ( ! (desc_status & RX_EOP)) {
+			printk("%s: Oversized Ethernet frame spanned multiple buffers,"
+				   " status %4.4x!\n", dev->name, desc_status);
+			  lp->stats.rx_length_errors++;
+		} else if (frame_status & 0x0038) {
+			/* There was a error. */
+			if (yellowfin_debug > 3)
+				printk("  yellowfin_rx() Rx error was %4.4x.\n", frame_status);
+			lp->stats.rx_errors++;
+			if (frame_status & 0x0060) lp->stats.rx_length_errors++;
+			if (frame_status & 0x0008) lp->stats.rx_frame_errors++;
+			if (frame_status & 0x0010) lp->stats.rx_crc_errors++;
+			if (frame_status < 0) lp->stats.rx_dropped++;
+#ifdef YF_PROTOTYPE			/* Support for prototype hardware errata. */
+		} else if (memcmp(bus_to_virt(lp->rx_ring[entry].addr),
+						  dev->dev_addr, 6) != 0
+				   && memcmp(bus_to_virt(lp->rx_ring[entry].addr),
+							 "\0377\0377\0377\0377\0377\0377", 6) != 0) {
+			printk("%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
+				   dev->name,
+				   ((char *)bus_to_virt(lp->rx_ring[entry].addr))[0],
+				   ((char *)bus_to_virt(lp->rx_ring[entry].addr))[1],
+				   ((char *)bus_to_virt(lp->rx_ring[entry].addr))[2],
+				   ((char *)bus_to_virt(lp->rx_ring[entry].addr))[3],
+				   ((char *)bus_to_virt(lp->rx_ring[entry].addr))[4],
+				   ((char *)bus_to_virt(lp->rx_ring[entry].addr))[5]);
+			bogus_rx++;
+#endif
+		} else {
+			u8 bogus_cnt = buf_addr[frm_size - 8];
+			short pkt_len = frm_size - 8 - bogus_cnt;
+			struct sk_buff *skb;
+			int rx_in_place = 0;
+
+			/* Check if the packet is long enough to just accept without
+			   copying to a properly sized skbuff. */
+			if (pkt_len > rx_copybreak) {
+				struct sk_buff *newskb;
+				char *temp;
+
+				/* Get a fresh skbuff to replace the filled one. */
+				newskb = DEV_ALLOC_SKB(dev->mtu <= 1500 ? PKT_BUF_SZ
+									   : dev->mtu + 32);
+				if (newskb == NULL) {
+					skb = 0;		/* No memory, drop the packet. */
+					goto memory_squeeze;
+				}
+				/* Pass up the skb already on the Rx ring. */
+				skb = lp->rx_skbuff[entry];
+				temp = skb_put(skb, pkt_len);
+				if (bus_to_virt(lp->rx_ring[entry].addr) != temp)
+					printk("%s: Warning -- the skbuff addresses do not match"
+						   " in yellowfin_rx: %p vs. %p / %p.\n", dev->name,
+						   bus_to_virt(lp->rx_ring[entry].addr),
+						   skb->head, temp);
+				rx_in_place = 1;
+				lp->rx_skbuff[entry] = newskb;
+				newskb->dev = dev;
+				skb_reserve(newskb, 2);	/* 16 byte align IP header */
+				lp->rx_ring[entry].addr = virt_to_bus(newskb->tail);
+			} else
+				skb = DEV_ALLOC_SKB(pkt_len + 2);
+			memory_squeeze:
+			if (skb == NULL) {
+				printk("%s: Memory squeeze, deferring packet.\n", dev->name);
+				/* todo: Check that at least two ring entries are free.
+				   If not, free one and mark stats->rx_dropped++. */
+				break;
+			}
+			skb->dev = dev;
+			if (! rx_in_place) {
+				skb_reserve(skb, 2);	/* 16 byte align the data fields */
+				memcpy(skb_put(skb, pkt_len),
+					   bus_to_virt(lp->rx_ring[entry].addr), pkt_len);
+			}
+#if LINUX_VERSION_CODE > 0x10300
+			skb->protocol = eth_type_trans(skb, dev);
+#else
+			skb->len = pkt_len;
+#endif
+			netif_rx(skb);
+			lp->stats.rx_packets++;
+		}
+
+		/* Mark this entry as being the end-of-list, and the prior entry
+		   as now valid. */
+		lp->rx_ring[entry].cmd = CMD_STOP;
+		yp->rx_ring[entry].status = 0;
+		{
+			int prev_entry = entry - 1;
+			if (prev_entry < 0)
+				lp->rx_ring[RX_RING_SIZE - 1].cmd =
+					CMD_RX_BUF | INTR_ALWAYS | BRANCH_ALWAYS;
+			else
+				lp->rx_ring[prev_entry].cmd = CMD_RX_BUF | INTR_ALWAYS;
+		}
+		entry = (++lp->cur_rx) % RX_RING_SIZE;
+	}
+	/* todo: restart Rx engine if stopped.  For now we just make the Rx ring
+	   large enough to avoid this. */
+
+	return 0;
+}
+
+static int
+yellowfin_close(struct device *dev)
+{
+	int ioaddr = dev->base_addr;
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	int i;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	if (yellowfin_debug > 1) {
+		printk("%s: Shutting down ethercard, status was Tx %4.4x Rx %4.4x Int %2.2x.\n",
+			   dev->name, inw(ioaddr + TxStatus),
+			   inw(ioaddr + RxStatus), inl(ioaddr + IntrStatus));
+		printk("%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",
+			   dev->name, yp->cur_tx, yp->dirty_tx, yp->cur_rx, yp->dirty_rx);
+	}
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	outw(0x0000, ioaddr + IntrEnb);
+
+	/* Stop the chip's Tx and Rx processes. */
+	outl(0x80000000, ioaddr + RxCtrl);
+	outl(0x80000000, ioaddr + TxCtrl);
+
+	del_timer(&yp->timer);
+
+	if (yellowfin_debug > 2) {
+		printk("\n  Tx ring at %8.8x:\n", (int)virt_to_bus(yp->tx_ring));
+		for (i = 0; i < TX_RING_SIZE*2; i++)
+			printk(" %c #%d desc. %4.4x %4.4x %8.8x %8.8x %4.4x %4.4x.\n",
+				   inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
+				   i, yp->tx_ring[i].cmd,
+				   yp->tx_ring[i].request_cnt, yp->tx_ring[i].addr,
+				   yp->tx_ring[i].branch_addr,
+				   yp->tx_ring[i].result_cnt, yp->tx_ring[i].status);
+		printk("  Tx status %p:\n", yp->tx_status);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk("   #%d status %4.4x %4.4x %4.4x %4.4x.\n",
+				   i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs,
+				   yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused);
+
+		printk("\n  Rx ring %8.8x:\n", (int)virt_to_bus(yp->rx_ring));
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			printk(" %c #%d desc. %4.4x %4.4x %8.8x %4.4x %4.4x\n",
+				   inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
+				   i, yp->rx_ring[i].cmd,
+				   yp->rx_ring[i].request_cnt, yp->rx_ring[i].addr,
+				   yp->rx_ring[i].result_cnt, yp->rx_ring[i].status);
+			if (yellowfin_debug > 5) {
+				if (*(u8*)yp->rx_ring[i].addr != 0x69) {
+					int j;
+					for (j = 0; j < 0x50; j++)
+						printk(" %4.4x", ((u16*)yp->rx_ring[i].addr)[j]);
+					printk("\n");
+				}
+			}
+		}
+	}
+
+#ifdef SA_SHIRQ
+	free_irq(dev->irq, dev);
+#else
+	free_irq(dev->irq);
+	irq2dev_map[dev->irq] = 0;
+#endif
+
+	/* Free all the skbuffs in the Rx queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		yp->rx_ring[i].cmd = CMD_STOP;
+		yp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
+		if (yp->rx_skbuff[i]) {
+#if LINUX_VERSION_CODE < 0x20100
+			yp->rx_skbuff[i]->free = 1;
+#endif
+			dev_kfree_skb(yp->rx_skbuff[i]);
+		}
+		yp->rx_skbuff[i] = 0;
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (yp->tx_skbuff[i])
+			dev_kfree_skb(yp->tx_skbuff[i]);
+		yp->tx_skbuff[i] = 0;
+	}
+
+#ifdef YF_PROTOTYPE			/* Support for prototype hardware errata. */
+	if (yellowfin_debug > 0) {
+		printk("%s: Received %d frames that we should not have.\n",
+			   dev->name, bogus_rx);
+	}
+#endif
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static struct enet_statistics *
+yellowfin_get_stats(struct device *dev)
+{
+	struct yellowfin_private *yp = (struct yellowfin_private *)dev->priv;
+	return &yp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor. */
+
+/* The little-endian AUTODIN32 ethernet CRC calculation.
+   N.B. Do not use for bulk data, use a table-based routine instead.
+   This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline unsigned ether_crc_le(int length, unsigned char *data)
+{
+	unsigned int crc = 0xffffffff;	/* Initial value. */
+	while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 8; --bit >= 0; current_octet >>= 1) {
+			if ((crc ^ current_octet) & 1) {
+				crc >>= 1;
+				crc ^= ethernet_polynomial_le;
+			} else
+				crc >>= 1;
+		}
+	}
+	return crc;
+}
+
+
+static void
+#ifdef NEW_MULTICAST
+set_rx_mode(struct device *dev)
+#else
+static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
+#endif
+{
+	int ioaddr = dev->base_addr;
+	u16 cfg_value = inw(ioaddr + Cnfg);
+
+	/* Stop the Rx process to change any value. */
+	outw(cfg_value & ~0x1000, ioaddr + Cnfg);
+	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
+		/* Unconditionally log net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		outw(0x000F, ioaddr + AddrMode);
+	} else if ((dev->mc_count > 64)  ||  (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to filter well, or accept all multicasts. */
+		printk("%s: Set all-multicast mode.\n", dev->name);
+		outw(0x000B, ioaddr + AddrMode);
+	} else if (dev->mc_count > 0) { /* Must use the multicast hash table. */
+		struct dev_mc_list *mclist;
+		u16 hash_table[4];
+		int i;
+		memset(hash_table, 0, sizeof(hash_table));
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+			 i++, mclist = mclist->next) {
+			/* Due to a bug in the early chip versions, multiple filter
+			   slots must be set for each address. */
+			set_bit((ether_crc_le(3, mclist->dmi_addr) >> 3) & 0x3f,
+					hash_table);
+			set_bit((ether_crc_le(4, mclist->dmi_addr) >> 3) & 0x3f,
+					hash_table);
+			set_bit((ether_crc_le(5, mclist->dmi_addr) >> 3) & 0x3f,
+					hash_table);
+			set_bit((ether_crc_le(6, mclist->dmi_addr) >> 3) & 0x3f,
+					hash_table);
+		}
+		/* Copy the hash table to the chip. */
+		for (i = 0; i < 4; i++)
+			outw(hash_table[i], ioaddr + HashTbl + i*2);
+		printk("%s: Set multicast mode.\n", dev->name);
+		outw(0x0003, ioaddr + AddrMode);
+	} else {					/* Normal, unicast/broadcast-only mode. */
+		printk("%s: Set unicast mode.\n", dev->name);
+		outw(0x0001, ioaddr + AddrMode);
+	}
+	/* Restart the Rx process. */
+	outw(cfg_value | 0x1000, ioaddr + Cnfg);
+}
+
+#ifdef MODULE
+
+/* An additional parameter that may be passed in... */
+static int debug = -1;
+
+int
+init_module(void)
+{
+	int cards_found;
+
+	if (debug >= 0)
+		yellowfin_debug = debug;
+
+	root_yellowfin_dev = NULL;
+	cards_found = yellowfin_probe(0);
+
+	return cards_found ? 0 : -ENODEV;
+}
+
+void
+cleanup_module(void)
+{
+	struct device *next_dev;
+
+	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+	while (root_yellowfin_dev) {
+		next_dev = ((struct yellowfin_private *)root_yellowfin_dev->priv)->next_module;
+		unregister_netdev(root_yellowfin_dev);
+		release_region(root_yellowfin_dev->base_addr, YELLOWFIN_TOTAL_SIZE);
+		kfree(root_yellowfin_dev);
+		root_yellowfin_dev = next_dev;
+	}
+}
+
+#endif  /* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c yellowfin.c"
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- v2.1.100/linux/drivers/sbus/audio/amd7930.c	Mon Feb 23 18:12:06 1998
+++ linux/drivers/sbus/audio/amd7930.c	Fri May  8 00:23:41 1998
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 #include <asm/sbus.h>
 
-#include "audio.h"
+#include <asm/audioio.h>
 #include "amd7930.h"
 
 #define MAX_DRIVERS 1
@@ -342,7 +342,6 @@
 static void transceive_Dchannel(struct amd7930_info *info)
 {
 	__u8 dummy;
-	int lbrp=0;	/* Last Byte of Received Packet (LBRP) */
 
 #define D_XMIT_ERRORS (AMR_DER_COLLISION | AMR_DER_UNRN)
 #define D_RECV_ERRORS (AMR_DER_RABRT | AMR_DER_RFRAME | AMR_DER_FCS | \
@@ -433,7 +432,7 @@
 			channel->output_count = 0;
 			if (channel->output_callback)
 				(*channel->output_callback)
-					(channel->output_callback_arg);
+					(channel->output_callback_arg,1);
 		}
 	} else {
 		*io_reg = channel->xmit_idle_char;
@@ -631,9 +630,9 @@
 static void amd7930_sunaudio_getdev(struct sparcaudio_driver *drv,
 				 audio_device_t * audinfo)
 {
-	strncpy(audinfo->name, "amd7930", sizeof(audinfo->name) - 1);
-	strncpy(audinfo->version, "x", sizeof(audinfo->version) - 1);
-	strncpy(audinfo->config, "audio", sizeof(audinfo->config) - 1);
+	strncpy(audinfo->name, "SUNW,am79c30", sizeof(audinfo->name) - 1);
+	strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
+	strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
 }
 
 static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver *drv)
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.1.100/linux/drivers/sbus/audio/audio.c	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/audio/audio.c	Fri May  8 00:23:41 1998
@@ -2,6 +2,12 @@
  * drivers/sbus/audio/audio.c
  *
  * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
+ * Copyright (C) 1997 Derrick J. Brashear (shadow@dementia.org)
+ * Copyright (C) 1997 Brent Baccala (baccala@freesoft.org)
+ * 
+ * Mixer code adapted from code contributed by and
+ * Copyright (C) 1998 Michael Mraka (michael@fi.muni.cz)
+ *
  *
  * This is the audio midlayer that sits between the VFS character
  * devices and the low-level audio hardware device drivers.
@@ -22,7 +28,7 @@
 #include <linux/soundcard.h>
 #include <asm/uaccess.h>
 
-#include "audio.h"
+#include <asm/audioio.h>
 
 
 /*
@@ -58,6 +64,7 @@
 	 */
 
 	drv->num_output_buffers = 32;
+        drv->playing_count = 0;
 	drv->output_front = 0;
 	drv->output_rear = 0;
 	drv->output_count = 0;
@@ -74,6 +81,7 @@
 
 	/* Setup the circular queue of input buffers. */
 	drv->num_input_buffers = 32;
+        drv->recording_count = 0;
 	drv->input_front = 0;
 	drv->input_rear = 0;
 	drv->input_count = 0;
@@ -143,28 +151,25 @@
 	return 0;
 }
 
-static void sparcaudio_output_done_task(void * arg)
+void sparcaudio_output_done(struct sparcaudio_driver * drv, int reclaim)
 {
-	struct sparcaudio_driver *drv = (struct sparcaudio_driver *)arg;
-	unsigned long flags;
+    /* Reclaim a buffer unless it's still in the DMA pipe */
+    if (reclaim) {
+        if (drv->output_count > 0) 
+            drv->output_count--;
+        else 
+            if (drv->playing_count > 0) 
+                drv->playing_count--;
+    } else 
+        drv->playing_count++;
 
-	save_and_cli(flags);
-	drv->ops->start_output(drv,
-			       drv->output_buffers[drv->output_front],
-			       drv->output_sizes[drv->output_front]);
-	drv->output_active = 1;
-	restore_flags(flags);
-}
-
-void sparcaudio_output_done(struct sparcaudio_driver * drv)
-{
 	/* Point the queue after the "done" buffer. */
 	drv->output_size -= drv->output_sizes[drv->output_front];
 	drv->output_front = (drv->output_front + 1) % drv->num_output_buffers;
-	drv->output_count--;
 
 	/* If the output queue is empty, shutdown the driver. */
 	if (drv->output_count == 0) {
+            if (drv->playing_count == 0) {
 		/* Stop the lowlevel driver from outputing. */
 		drv->ops->stop_output(drv);
 		drv->output_active = 0;
@@ -173,19 +178,16 @@
 		wake_up_interruptible(&drv->output_write_wait);
 		wake_up_interruptible(&drv->output_drain_wait);
 		return;
+            }
 	}
 
-	/* Otherwise, queue a task to give the driver the next buffer. */
-	drv->tqueue.next = NULL;
-	drv->tqueue.sync = 0;
-	drv->tqueue.routine = sparcaudio_output_done_task;
-	drv->tqueue.data = drv;
-
-	queue_task(&drv->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-
-	/* Wake up any tasks that are waiting. */
-	wake_up_interruptible(&drv->output_write_wait);
+    /* If we got back a buffer, see if anyone wants to write to it */
+    if (reclaim || ((drv->output_count + drv->playing_count) 
+                    < drv->num_output_buffers))
+        wake_up_interruptible(&drv->output_write_wait);
+    
+    drv->ops->start_output(drv, drv->output_buffers[drv->output_front],
+                                drv->output_sizes[drv->output_front]);
 }
 
 void sparcaudio_input_done(struct sparcaudio_driver * drv)
@@ -263,7 +265,7 @@
 
 	/* If the low-level driver is not active, activate it. */
 	save_and_cli(flags);
-	if (! driver->output_active) {
+        if ((!driver->output_active) && (driver->output_count > 0)) {
 		driver->ops->start_output(driver,
 				driver->output_buffers[driver->output_front],
 				driver->output_sizes[driver->output_front]);
@@ -277,59 +279,184 @@
 {
 	int bytes_written = 0, bytes_to_copy;
 
-	/* Ensure that we have something to write. */
-	if (count < 1) {
-		sparcaudio_sync_output(driver);
-		return 0;
-	}
+        if (! file->f_mode & FMODE_WRITE)
+            return -EINVAL;
 
 	/* Loop until all output is written to device. */
 	while (count > 0) {
-		/* Check to make sure that an output buffer is available. */
-		/* If not, make valiant attempt */
-		if (driver->output_count == driver->num_output_buffers)
-			sparcaudio_reorganize_buffers(driver);
-
-		if (driver->output_count == driver->num_output_buffers) {
- 			/* We need buffers, so... */
-			sparcaudio_sync_output(driver);
- 			interruptible_sleep_on(&driver->output_write_wait);
-			if (signal_pending(current))
-				return bytes_written > 0 ? bytes_written : -EINTR;
+            /* Check to make sure that an output buffer is available. */
+            /* If not, make valiant attempt */
+            if (driver->num_output_buffers == 
+                (driver->output_count + driver->playing_count))
+                sparcaudio_reorganize_buffers(driver);
+            
+            if (driver->num_output_buffers == 
+                (driver->output_count + driver->playing_count)) {
+                /* We need buffers, so... */
+                sparcaudio_sync_output(driver);
+                interruptible_sleep_on(&driver->output_write_wait);
+                if (signal_pending(current))
+                    return bytes_written > 0 ? bytes_written : -EINTR;
 		}
 
-		/* Determine how much we can copy in this iteration. */
-		bytes_to_copy = count;
-		if (bytes_to_copy > PAGE_SIZE)
-			bytes_to_copy = PAGE_SIZE;
+            /* No buffers were freed. Go back to sleep */
+            if (driver->num_output_buffers == 
+                (driver->output_count + driver->playing_count)) 
+                continue;
+
+            /* Determine how much we can copy in this iteration. */
+            bytes_to_copy = count;
+            if (bytes_to_copy > PAGE_SIZE)
+                bytes_to_copy = PAGE_SIZE;
 
-		copy_from_user_ret(driver->output_buffers[driver->output_rear],
+            copy_from_user_ret(driver->output_buffers[driver->output_rear],
 			       buf, bytes_to_copy, -EFAULT);
 
-		/* Update the queue pointers. */
-		buf += bytes_to_copy;
-		count -= bytes_to_copy;
-		bytes_written += bytes_to_copy;
-		driver->output_sizes[driver->output_rear] = bytes_to_copy;
-		driver->output_rear = (driver->output_rear + 1) % driver->num_output_buffers;
-		driver->output_count++;
-		driver->output_size += bytes_to_copy;
-
-		/* Activate the driver if more than page of data is waiting. */
-		if (driver->output_size > 4096)
-			sparcaudio_sync_output(driver);
+            /* Update the queue pointers. */
+            buf += bytes_to_copy;
+            count -= bytes_to_copy;
+            bytes_written += bytes_to_copy;
+            driver->output_sizes[driver->output_rear] = bytes_to_copy;
+            driver->output_rear = (driver->output_rear + 1) % driver->num_output_buffers;
+            driver->output_count++;
+            driver->output_size += bytes_to_copy;
 	}
+        sparcaudio_sync_output(driver);
 
 	/* Return the number of bytes written to the caller. */
 	return bytes_written;
 }
 
+#define COPY_IN(arg, get) get_user(get, (int *)arg)
+#define COPY_OUT(arg, ret) put_user(ret, (int *)arg)
+
+/* Add these in as new devices are supported. Belongs in audioio.h, actually */
+#define SUPPORTED_MIXER_DEVICES         (SOUND_MASK_VOLUME)
+#define MONO_DEVICES (SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SPEAKER | SOUND_MASK_MIC)
+
+static inline int sparcaudio_mixer_ioctl(struct inode * inode, struct file * file,
+					 unsigned int cmd, unsigned long arg)
+{
+	int i = 0, j = 0;
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		/* For any missing routines, pretend we changed things anyhow for now */
+		switch (cmd & 0xff) {
+		case SOUND_MIXER_VOLUME:
+			if (driver->ops->get_output_channels)
+				j = driver->ops->get_output_channels(driver);
+			COPY_IN(arg, i);
+			if (j == 1) {
+				i = s_to_m(i);
+				if (driver->ops->set_output_volume)
+					driver->ops->set_output_volume(driver, i * 255/100);
+				if (driver->ops->get_output_volume)
+					i = driver->ops->get_output_volume(driver);
+				i = m_to_s(i);
+			} else {
+				/* there should be stuff here which calculates balance and
+				   volume on a stereo device. will do it eventually */
+				i = s_to_g(i);
+				if (driver->ops->set_output_volume)
+					driver->ops->set_output_volume(driver, i * 255/100);
+				if (driver->ops->get_output_volume)
+					i = driver->ops->get_output_volume(driver);
+				j = s_to_b(i);
+				if (driver->ops->set_output_balance)
+					driver->ops->set_output_balance(driver, j);
+				if (driver->ops->get_output_balance)
+					j = driver->ops->get_output_balance(driver);
+				i = b_to_s(i,j);
+			}
+			return COPY_OUT(arg, i);
+		default:
+			/* Play like we support other things */
+			return COPY_OUT(arg, i);
+		}
+	} else {
+		switch (cmd & 0xff) {
+		case SOUND_MIXER_RECSRC:
+			if (driver->ops->get_input_port)
+				i = driver->ops->get_input_port(driver);
+			/* only one should ever be selected */
+			if (i & AUDIO_ANALOG_LOOPBACK) j = SOUND_MASK_IMIX; /* ? */
+			if (i & AUDIO_CD) j = SOUND_MASK_CD;
+			if (i & AUDIO_LINE_IN) j = SOUND_MASK_LINE;
+			if (i & AUDIO_MICROPHONE) j = SOUND_MASK_MIC;
+
+			return COPY_OUT(arg, j);
+
+		case SOUND_MIXER_RECMASK:
+			if (driver->ops->get_input_ports)
+				i = driver->ops->get_input_ports(driver);
+			/* what do we support? */
+			if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC;
+			if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE;
+			if (i & AUDIO_CD) j |= SOUND_MASK_CD;
+			if (i & AUDIO_ANALOG_LOOPBACK) j |= SOUND_MASK_IMIX; /* ? */
+
+			return COPY_OUT(arg, j);
+
+		case SOUND_MIXER_CAPS: /* mixer capabilities */
+			i = SOUND_CAP_EXCL_INPUT;
+			return COPY_OUT(arg, i);
+
+		case SOUND_MIXER_DEVMASK: /* all supported devices */
+		case SOUND_MIXER_STEREODEVS: /* what supports stereo */
+			if (driver->ops->get_input_ports)
+				i = driver->ops->get_input_ports(driver);
+			/* what do we support? */
+			if (i & AUDIO_MICROPHONE) j |= SOUND_MASK_MIC;
+			if (i & AUDIO_LINE_IN) j |= SOUND_MASK_LINE;
+			if (i & AUDIO_CD) j |= SOUND_MASK_CD;
+			if (i & AUDIO_ANALOG_LOOPBACK) j |= SOUND_MASK_IMIX; /* ? */
+
+			if (driver->ops->get_output_ports)
+				i = driver->ops->get_output_ports(driver);
+			if (i & AUDIO_SPEAKER) j |= SOUND_MASK_SPEAKER;
+			if (i & AUDIO_HEADPHONE) j |= SOUND_MASK_LINE; /* ? */
+			if (i & AUDIO_LINE_OUT) j |= SOUND_MASK_LINE;
+			
+			j |= SOUND_MASK_VOLUME;
+
+			if ((cmd & 0xff) == SOUND_MIXER_STEREODEVS)
+			j &= ~(MONO_DEVICES);
+			return COPY_OUT(arg, j);
+
+		case SOUND_MIXER_VOLUME:
+			if (driver->ops->get_output_channels)
+				j = driver->ops->get_output_channels(driver);
+			if (j == 1) {
+				if (driver->ops->get_output_volume)
+					i = driver->ops->get_output_volume(driver);
+				i = m_to_s(i);
+			} else {
+				/* there should be stuff here which calculates balance and
+				   volume on a stereo device. will do it eventually */
+				if (driver->ops->get_output_volume)
+					i = driver->ops->get_output_volume(driver);
+				if (driver->ops->get_output_balance)
+					j = driver->ops->get_output_balance(driver);
+				i = b_to_s(i,j);
+			}
+			return COPY_OUT(arg, i);
+
+		default:
+			/* Play like we support other things */
+			return COPY_OUT(arg, i);
+		}
+	}
+}
+
 static int sparcaudio_ioctl(struct inode * inode, struct file * file,
 			    unsigned int cmd, unsigned long arg)
 {
 	int retval = 0;
 	struct audio_info ainfo;
 
+        if (((cmd >> 8) & 0xff) == 'M') {
+            return sparcaudio_mixer_ioctl(inode, file, cmd, arg);
+        }
+
 	switch (cmd) {
 	case SNDCTL_DSP_SYNC:
 	case AUDIO_DRAIN:
@@ -339,6 +466,40 @@
 		}
 		break;
 
+        case AUDIO_FLUSH:
+                if (driver->output_active && (file->f_mode & FMODE_WRITE)) {
+                    wake_up_interruptible(&driver->output_write_wait);
+                    driver->ops->stop_output(driver);
+                    driver->output_active = 0;
+                    driver->output_front = 0;
+                    driver->output_rear = 0;
+                    driver->output_count = 0;
+                    driver->output_size = 0;
+                    driver->playing_count = 0;
+                }
+                if (driver->input_active && (file->f_mode & FMODE_READ)) {
+                    wake_up_interruptible(&driver->input_read_wait);
+                    driver->ops->stop_input(driver);
+                    driver->input_active = 0;
+                    driver->input_front = 0;
+                    driver->input_rear = 0;
+                    driver->input_count = 0;
+                    driver->recording_count = 0;
+                }
+                if ((file->f_mode & FMODE_READ) && 
+                    !(driver->flags & SDF_OPEN_READ)) {
+                    driver->ops->start_input(driver, 
+                                             driver->input_buffers[driver->input_front],
+                                             PAGE_SIZE);
+                    driver->input_active = 1;
+                    }
+                if ((file->f_mode & FMODE_WRITE) && 
+                    !(driver->flags & SDF_OPEN_WRITE)) {
+                    sparcaudio_sync_output(driver);
+                    }
+                break;
+            
+
 	case AUDIO_GETDEV:
 		if (driver->ops->sunaudio_getdev) {
 			audio_device_t tmp;
@@ -686,6 +847,19 @@
 		  }
 
 	    }
+            /* Maybe this should be a routine instead of a macro */
+#define IF_SET_DO(x,y) if ((x) && Modify(y)) x(driver, y)
+#define IF_SETC_DO(x,y) if ((x) && Modifyc(y)) x(driver, y)
+            IF_SETC_DO(driver->ops->set_input_balance, (int)ainfo.record.balance);
+            IF_SETC_DO(driver->ops->set_output_balance, (int)ainfo.play.balance);
+            IF_SET_DO(driver->ops->set_input_volume, ainfo.record.gain);
+            IF_SET_DO(driver->ops->set_output_volume, ainfo.play.gain);
+            IF_SET_DO(driver->ops->set_input_port, ainfo.record.port);
+            IF_SET_DO(driver->ops->set_output_port, ainfo.play.port);
+            IF_SET_DO(driver->ops->set_monitor_volume, ainfo.monitor_gain);
+            IF_SET_DO(driver->ops->set_output_muted, ainfo.output_muted);
+#undef IF_SET_DO
+#undef IF_SETC_DO
 
 	    printk("sparcaudio_ioctl: AUDIO_SETINFO\n");
 	    break;
@@ -725,77 +899,83 @@
 
 static int sparcaudio_open(struct inode * inode, struct file * file)
 {
-	int err;
-
-	/* A low-level audio driver must exist. */
-	if (!driver)
-		return -ENODEV;
-
-	if (MINOR(inode->i_rdev) == 5) {
+    int minor = MINOR(inode->i_rdev);
+    int err;
 
-		file->f_op = &sparcaudioctl_fops;
-
-		MOD_INC_USE_COUNT;
-
-		return 0;
-	}
-
-	/* We only support minor #4 (/dev/audio) right now. */
-	if (MINOR(inode->i_rdev) != 4)
-		return -ENXIO;
-
-	/* If the driver is busy, then wait to get through. */
-	retry_open:
+    /* A low-level audio driver must exist. */
+    if (!driver)
+        return -ENODEV;
+
+    switch (minor) {
+    case SPARCAUDIO_AUDIOCTL_MINOR:
+        file->f_op = &sparcaudioctl_fops;
+        break;
+
+    case SPARCAUDIO_DSP16_MINOR:
+    case SPARCAUDIO_DSP_MINOR:
+    case SPARCAUDIO_AUDIO_MINOR:
+        /* If the driver is busy, then wait to get through. */
+    retry_open:
 	if (file->f_mode & FMODE_READ && driver->flags & SDF_OPEN_READ) {
-		if (file->f_flags & O_NONBLOCK)
-			return -EBUSY;
-
-		interruptible_sleep_on(&driver->open_wait);
-		if (signal_pending(current))
-			return -EINTR;
-		goto retry_open;
+            if (file->f_flags & O_NONBLOCK)
+                return -EBUSY;
+            
+            interruptible_sleep_on(&driver->open_wait);
+            if (signal_pending(current))
+                return -EINTR;
+            goto retry_open;
 	}
 	if (file->f_mode & FMODE_WRITE && driver->flags & SDF_OPEN_WRITE) {
-		if (file->f_flags & O_NONBLOCK)
-			return -EBUSY;
-
-		interruptible_sleep_on(&driver->open_wait);
-		if (signal_pending(current))
-			return -EINTR;
-		goto retry_open;
+            if (file->f_flags & O_NONBLOCK)
+                return -EBUSY;
+            
+            interruptible_sleep_on(&driver->open_wait);
+            if (signal_pending(current))
+                return -EINTR;
+            goto retry_open;
 	}
 
+	/* Allow the low-level driver to initialize itself. */
+	if (driver->ops->open) {
+            err = driver->ops->open(inode,file,driver);
+            if (err < 0)
+                return err;
+	}
+        
 	/* Mark the driver as locked for read and/or write. */
 	if (file->f_mode & FMODE_READ) {
-		driver->input_offset = 0;
-		driver->input_front = 0;
-		driver->input_rear = 0;
-		driver->input_count = 0;
-		driver->ops->start_input(driver, driver->input_buffers[driver->input_front],
-					 PAGE_SIZE);
-		driver->input_active = 1;
-		driver->flags |= SDF_OPEN_READ;
+            driver->input_offset = 0;
+            driver->input_front = 0;
+            driver->input_rear = 0;
+            driver->input_count = 0;
+            driver->recording_count = 0;
+            driver->ops->start_input(driver, driver->input_buffers[driver->input_front],
+                                     PAGE_SIZE);
+            driver->input_active = 1;
+            driver->flags |= SDF_OPEN_READ;
 	}
 	if (file->f_mode & FMODE_WRITE) {
-		driver->output_size = 0;
-		driver->output_front = 0;
-		driver->output_rear = 0;
-		driver->output_count = 0;
-		driver->output_active = 0;
-		driver->flags |= SDF_OPEN_WRITE;
+            driver->playing_count = 0;
+            driver->output_size = 0;
+            driver->output_front = 0;
+            driver->output_rear = 0;
+            driver->output_count = 0;
+            driver->output_active = 0;
+            driver->flags |= SDF_OPEN_WRITE;
 	}  
-
-	/* Allow the low-level driver to initialize itself. */
-	if (driver->ops->open) {
-		err = driver->ops->open(inode,file,driver);
-		if (err < 0)
-			return err;
-	}
-
-	MOD_INC_USE_COUNT;
-
-	/* Success! */
-	return 0;
+        break;
+    case SPARCAUDIO_MIXER_MINOR:     
+        file->f_op = &sparcaudioctl_fops;
+        break;
+
+    default:
+        return -ENXIO;
+    }
+
+    MOD_INC_USE_COUNT;
+    
+    /* Success! */
+    return 0;
 }
 
 static int sparcaudio_release(struct inode * inode, struct file * file)
@@ -876,3 +1056,22 @@
 	unregister_chrdev(SOUND_MAJOR, "sparcaudio");
 }
 #endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/audio.h linux/drivers/sbus/audio/audio.h
--- v2.1.100/linux/drivers/sbus/audio/audio.h	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/audio/audio.h	Wed Dec 31 16:00:00 1969
@@ -1,384 +0,0 @@
-/*
- * drivers/sbus/audio/audio.h
- *
- * Sparc Audio Midlayer
- * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
- */
-
-#ifndef _AUDIO_H_
-#define _AUDIO_H_
-
-/*
- *	SunOS/Solaris /dev/audio interface
- */
-
-#include <linux/types.h>
-#include <linux/time.h>
-#include <linux/ioctl.h>
-
-/*
- * This structure contains state information for audio device IO streams.
- */
-typedef struct audio_prinfo {
-	/*
-	 * The following values describe the audio data encoding.
-	 */
-	unsigned int sample_rate;	/* samples per second */
-	unsigned int channels;	/* number of interleaved channels */
-	unsigned int precision;	/* bit-width of each sample */
-	unsigned int encoding;	/* data encoding method */
-
-	/*
-	 * The following values control audio device configuration
-	 */
-	unsigned int gain;		/* gain level: 0 - 255 */
-	unsigned int port;		/* selected I/O port (see below) */
-	unsigned int avail_ports;	/* available I/O ports (see below) */
-	unsigned int _xxx[2];		/* Reserved for future use */
-
-	unsigned int buffer_size;	/* I/O buffer size */
-
-	/*
-	 * The following values describe driver state
-	 */
-	unsigned int samples;		/* number of samples converted */
-	unsigned int eof;		/* End Of File counter (play only) */
-
-	unsigned char	pause;		/* non-zero for pause, zero to resume */
-	unsigned char	error;		/* non-zero if overflow/underflow */
-	unsigned char	waiting;	/* non-zero if a process wants access */
-	unsigned char balance;	/* stereo channel balance */
-
-	unsigned short minordev;
-
-	/*
-	 * The following values are read-only state flags
-	 */
-	unsigned char open;		/* non-zero if open access permitted */
-	unsigned char active;		/* non-zero if I/O is active */
-} audio_prinfo_t;
-
-
-/*
- * This structure describes the current state of the audio device.
- */
-typedef struct audio_info {
-	/*
-	 * Per-stream information
-	 */
-	audio_prinfo_t play;	/* output status information */
-	audio_prinfo_t record;	/* input status information */
-
-	/*
-	 * Per-unit/channel information
-	 */
-	unsigned int monitor_gain;	/* input to output mix: 0 - 255 */
-	unsigned char output_muted;	/* non-zero if output is muted */
-	unsigned char _xxx[3];	/* Reserved for future use */
-	unsigned int _yyy[3];		/* Reserved for future use */
-} audio_info_t;
-
-
-/*
- * Audio encoding types
- */
-#define	AUDIO_ENCODING_NONE	(0)	/* no encoding assigned	  */
-#define	AUDIO_ENCODING_ULAW	(1)	/* u-law encoding	  */
-#define	AUDIO_ENCODING_ALAW	(2)	/* A-law encoding	  */
-#define	AUDIO_ENCODING_LINEAR	(3)	/* Linear PCM encoding	  */
-#define	AUDIO_ENCODING_DVI	(104)	/* DVI ADPCM		  */
-#define	AUDIO_ENCODING_LINEAR8	(105)	/* 8 bit UNSIGNED	  */
-#define	AUDIO_ENCODING_LINEARLE	(106)	/* Linear PCM LE encoding */
-
-/*
- * These ranges apply to record, play, and monitor gain values
- */
-#define	AUDIO_MIN_GAIN	(0)	/* minimum gain value */
-#define	AUDIO_MAX_GAIN	(255)	/* maximum gain value */
-
-/*
- * These values apply to the balance field to adjust channel gain values
- */
-#define	AUDIO_LEFT_BALANCE	(0)	/* left channel only	*/
-#define	AUDIO_MID_BALANCE	(32)	/* equal left/right channel */
-#define	AUDIO_RIGHT_BALANCE	(64)	/* right channel only	*/
-#define	AUDIO_BALANCE_SHIFT	(3)
-
-/*
- * Generic minimum/maximum limits for number of channels, both modes
- */
-#define	AUDIO_MIN_PLAY_CHANNELS	(1)
-#define	AUDIO_MAX_PLAY_CHANNELS	(4)
-#define	AUDIO_MIN_REC_CHANNELS	(1)
-#define	AUDIO_MAX_REC_CHANNELS	(4)
-
-/*
- * Generic minimum/maximum limits for sample precision
- */
-#define	AUDIO_MIN_PLAY_PRECISION	(8)
-#define	AUDIO_MAX_PLAY_PRECISION	(32)
-#define	AUDIO_MIN_REC_PRECISION		(8)
-#define	AUDIO_MAX_REC_PRECISION		(32)
-
-/*
- * Define some convenient names for typical audio ports
- */
-/*
- * output ports (several may be enabled simultaneously)
- */
-#define	AUDIO_SPEAKER		0x01	/* output to built-in speaker */
-#define	AUDIO_HEADPHONE		0x02	/* output to headphone jack */
-#define	AUDIO_LINE_OUT		0x04	/* output to line out	 */
-
-/*
- * input ports (usually only one at a time)
- */
-#define	AUDIO_MICROPHONE	0x01	/* input from microphone */
-#define	AUDIO_LINE_IN		0x02	/* input from line in	 */
-#define	AUDIO_CD		0x04	/* input from on-board CD inputs */
-#define	AUDIO_INTERNAL_CD_IN	AUDIO_CD	/* input from internal CDROM */
-/* Supposedly an undocumented feature of the 4231 */
-#define AUDIO_ANALOG_LOOPBACK   0x40
-
-
-/*
- * This macro initializes an audio_info structure to 'harmless' values.
- * Note that (~0) might not be a harmless value for a flag that was
- * a signed int.
- */
-#define	AUDIO_INITINFO(i)	{					\
-	unsigned int	*__x__;						\
-	for (__x__ = (unsigned int *)(i);				\
-	    (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t));	\
-	    *__x__++ = ~0);						\
-}
-
-
-/*
- * These allow testing for what the user wants to set 
- */
-#define AUD_INITVALUE   (~0)
-#define Modify(X)       ((unsigned int)(X) != AUD_INITVALUE)
-#define Modifys(X)      ((X) != (unsigned short)AUD_INITVALUE)
-#define Modifyc(X)      ((X) != (unsigned char)AUD_INITVALUE)
-
-/*
- * Parameter for the AUDIO_GETDEV ioctl to determine current
- * audio devices.
- */
-#define	MAX_AUDIO_DEV_LEN	(16)
-typedef struct audio_device {
-	char name[MAX_AUDIO_DEV_LEN];
-	char version[MAX_AUDIO_DEV_LEN];
-	char config[MAX_AUDIO_DEV_LEN];
-} audio_device_t;
-
-
-/*
- * Ioctl calls for the audio device.
- */
-
-/*
- * AUDIO_GETINFO retrieves the current state of the audio device.
- *
- * AUDIO_SETINFO copies all fields of the audio_info structure whose
- * values are not set to the initialized value (-1) to the device state.
- * It performs an implicit AUDIO_GETINFO to return the new state of the
- * device.  Note that the record.samples and play.samples fields are set
- * to the last value before the AUDIO_SETINFO took effect.  This allows
- * an application to reset the counters while atomically retrieving the
- * last value.
- *
- * AUDIO_DRAIN suspends the calling process until the write buffers are
- * empty.
- *
- * AUDIO_GETDEV returns a structure of type audio_device_t which contains
- * three strings.  The string "name" is a short identifying string (for
- * example, the SBus Fcode name string), the string "version" identifies
- * the current version of the device, and the "config" string identifies
- * the specific configuration of the audio stream.  All fields are
- * device-dependent -- see the device specific manual pages for details.
- */
-#define	AUDIO_GETINFO	_IOR('A', 1, audio_info_t)
-#define	AUDIO_SETINFO	_IOWR('A', 2, audio_info_t)
-#define	AUDIO_DRAIN	_IO('A', 3)
-#define	AUDIO_GETDEV	_IOR('A', 4, audio_device_t)
-#define	AUDIO_GETDEV_SUNOS	_IOR('A', 4, int)
-
-/* Define possible audio hardware configurations for 
- * old SunOS-style AUDIO_GETDEV ioctl */
-
-#define AUDIO_DEV_UNKNOWN       (0)     /* not defined */
-#define AUDIO_DEV_AMD           (1)     /* audioamd device */
-#define AUDIO_DEV_SPEAKERBOX    (2)     /* dbri device with speakerbox */
-#define AUDIO_DEV_CODEC         (3)     /* dbri device (internal speaker) */
-#define AUDIO_DEV_CS4231        (5)     /* cs4231 device */
-
-/*
- * The following ioctl sets the audio device into an internal loopback mode,
- * if the hardware supports this.  The argument is TRUE to set loopback,
- * FALSE to reset to normal operation.  If the hardware does not support
- * internal loopback, the ioctl should fail with EINVAL.
- */
-#define	AUDIO_DIAG_LOOPBACK	_IOW('A', 101, int)
-
-#ifdef notneeded
-/*
- * Structure sent up as a M_PROTO message on trace streams
- */
-typedef struct audtrace_hdr audtrace_hdr_t;
-struct audtrace_hdr {
-	unsigned int seq;		/* Sequence number (per-aud_stream) */
-	int type;		/* device-dependent */
-	struct timeval timestamp;
-	char _f[8];		/* filler */
-};
-#endif
-
-/*
- *	Linux kernel internal implementation.
- */
-
-#ifdef __KERNEL__
-
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/tqueue.h>
-#include <linux/wait.h>
-
-#define	SDF_OPEN_WRITE	0x00000001
-#define	SDF_OPEN_READ	0x00000002
-
-struct sparcaudio_driver
-{
-	const char * name;
-	struct sparcaudio_operations *ops;
-	void *private;
-	unsigned long flags;
-
-	/* Processes blocked on open() sit here. */
-	struct wait_queue *open_wait;
-
-	/* Task queue for this driver's bottom half. */
-	struct tq_struct tqueue;
-
-	/* Support for a circular queue of output buffers. */
-	__u8 **output_buffers;
-	size_t *output_sizes, output_size;
-	int num_output_buffers, output_front, output_rear;
-	int output_count, output_active;
-	struct wait_queue *output_write_wait, *output_drain_wait;
-
-	/* Support for a circular queue of input buffers. */
-	__u8 **input_buffers;
-	int input_offset;
-	int num_input_buffers, input_front, input_rear;
-	int input_count, input_active;
-	struct wait_queue *input_read_wait;
-};
-
-struct sparcaudio_operations
-{
-	int (*open)(struct inode *, struct file *, struct sparcaudio_driver *);
-	void (*release)(struct inode *, struct file *, struct sparcaudio_driver *);
-	int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long,
-		     struct sparcaudio_driver *);
-
-	/* Ask driver to begin playing a buffer. */
-	void (*start_output)(struct sparcaudio_driver *, __u8 *, unsigned long);
-
-	/* Ask driver to stop playing a buffer. */
-	void (*stop_output)(struct sparcaudio_driver *);
-
-	/* Ask driver to begin recording into a buffer. */
-	void (*start_input)(struct sparcaudio_driver *, __u8 *, unsigned long);
-
-	/* Ask driver to stop recording. */
-	void (*stop_input)(struct sparcaudio_driver *);
-
-	/* Return driver name/version to caller. (/dev/audio specific) */
-	void (*sunaudio_getdev)(struct sparcaudio_driver *, audio_device_t *);
-
-        /* Get and set the output volume. (0-255) */
-        int (*set_output_volume)(struct sparcaudio_driver *, int);
-        int (*get_output_volume)(struct sparcaudio_driver *);
-
-        /* Get and set the input volume. (0-255) */
-        int (*set_input_volume)(struct sparcaudio_driver *, int);
-        int (*get_input_volume)(struct sparcaudio_driver *);
-
-        /* Get and set the monitor volume. (0-255) */
-        int (*set_monitor_volume)(struct sparcaudio_driver *, int);
-        int (*get_monitor_volume)(struct sparcaudio_driver *);
-
-        /* Get and set the output balance. (0-64) */
-        int (*set_output_balance)(struct sparcaudio_driver *, int);
-        int (*get_output_balance)(struct sparcaudio_driver *);
-
-        /* Get and set the input balance. (0-64) */
-        int (*set_input_balance)(struct sparcaudio_driver *, int);
-        int (*get_input_balance)(struct sparcaudio_driver *);
-
-        /* Get and set the output channels. (1-4) */
-        int (*set_output_channels)(struct sparcaudio_driver *, int);
-        int (*get_output_channels)(struct sparcaudio_driver *);
-
-        /* Get and set the input channels. (1-4) */
-        int (*set_input_channels)(struct sparcaudio_driver *, int);
-        int (*get_input_channels)(struct sparcaudio_driver *);
-
-        /* Get and set the output precision. (8-32) */
-        int (*set_output_precision)(struct sparcaudio_driver *, int);
-        int (*get_output_precision)(struct sparcaudio_driver *);
-
-        /* Get and set the input precision. (8-32) */
-        int (*set_input_precision)(struct sparcaudio_driver *, int);
-        int (*get_input_precision)(struct sparcaudio_driver *);
-
-        /* Get and set the output port. () */
-        int (*set_output_port)(struct sparcaudio_driver *, int);
-        int (*get_output_port)(struct sparcaudio_driver *);
-
-        /* Get and set the input port. () */
-        int (*set_input_port)(struct sparcaudio_driver *, int);
-        int (*get_input_port)(struct sparcaudio_driver *);
-
-        /* Get and set the output encoding. () */
-        int (*set_output_encoding)(struct sparcaudio_driver *, int);
-        int (*get_output_encoding)(struct sparcaudio_driver *);
-
-        /* Get and set the input encoding. () */
-        int (*set_input_encoding)(struct sparcaudio_driver *, int);
-        int (*get_input_encoding)(struct sparcaudio_driver *);
-
-        /* Get and set the output rate. () */
-        int (*set_output_rate)(struct sparcaudio_driver *, int);
-        int (*get_output_rate)(struct sparcaudio_driver *);
-
-        /* Get and set the input rate. () */
-        int (*set_input_rate)(struct sparcaudio_driver *, int);
-        int (*get_input_rate)(struct sparcaudio_driver *);
-
-	/* Return driver number to caller. (SunOS /dev/audio specific) */
-	int (*sunaudio_getdev_sunos)(struct sparcaudio_driver *);
-
-	/* Get available ports */
-	int (*get_output_ports)(struct sparcaudio_driver *);
-	int (*get_input_ports)(struct sparcaudio_driver *);
-
-	/* Get and set output mute */
-	int (*set_output_muted)(struct sparcaudio_driver *, int);
-	int (*get_output_muted)(struct sparcaudio_driver *);
-};
-
-extern int register_sparcaudio_driver(struct sparcaudio_driver *);
-extern int unregister_sparcaudio_driver(struct sparcaudio_driver *);
-extern void sparcaudio_output_done(struct sparcaudio_driver *);
-extern void sparcaudio_input_done(struct sparcaudio_driver *);
-extern int sparcaudio_init(void);
-extern int amd7930_init(void);
-extern int cs4231_init(void);
-
-#endif  /* __KERNEL__ */
-
-#endif  /* _AUDIO_H */
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c
--- v2.1.100/linux/drivers/sbus/audio/cs4231.c	Mon Feb 23 18:12:06 1998
+++ linux/drivers/sbus/audio/cs4231.c	Fri May  8 00:23:41 1998
@@ -1,13 +1,20 @@
 /*
- * drivers/sbus/audio/cs4231.c
+ * Drivers/sbus/audio/cs4231.c
  *
+ * Copyright (C) 1996, 1997 Derrick J Brashear (shadow@andrew.cmu.edu)
+ *
+ * Based on the AMD7930 driver:
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
- * Copyright (C) 1996 Derrick J Brashear (shadow@andrew.cmu.edu)
  *
  * This is the lowlevel driver for the CS4231 audio chip found on some
- * sun4m machines.
+ * sun4m and sun4u machines.
+ * 
+ * This was culled from the Crystal docs on the 4231a, and the addendum they
+ * faxed me on the 4231.
+ * The APC DMA controller support unfortunately is not documented. Thanks, Sun
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -15,15 +22,15 @@
 #include <linux/interrupt.h>
 #include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 #include <asm/sbus.h>
 
-#include "audio.h"
+#include <asm/audioio.h>
 #include "cs4231.h"
 
 /* Stolen for now from compat.h */
@@ -34,194 +41,700 @@
 #define MIN(_a,_b)      ((_a)<(_b)?(_a):(_b))
 #endif
 
+#undef __CS4231_DEBUG
+#undef __CS4231_TRACE
+#undef __CS4231_ERROR
+#ifdef __CS4231_ERROR
+#define eprintk(x) printk x
+#else
+#define eprintk(x)
+#endif
+#ifdef __CS4231_TRACE
+#define tprintk(x) printk x
+#else
+#define tprintk(x)
+#endif
+#ifdef __CS4231_DEBUG
+#define dprintk(x) printk x
+#else
+#define dprintk(x)
+#endif
+
 #define MAX_DRIVERS 1
 static struct sparcaudio_driver drivers[MAX_DRIVERS];
 static int num_drivers;
 
-static int cs4231_playintr(struct sparcaudio_driver *drv);
+static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance);
+static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance);
+static void cs4231_ready(struct sparcaudio_driver *drv);
+static void cs4231_playintr(struct sparcaudio_driver *drv);
 static int cs4231_recintr(struct sparcaudio_driver *drv);
-static void cs4231_output_muted(struct sparcaudio_driver *drv, unsigned int value);
-static void cs4231_mute(struct sparcaudio_driver *drv);
+static int cs4231_output_muted(struct sparcaudio_driver *drv, int value);
 static void cs4231_pollinput(struct sparcaudio_driver *drv);
+static int cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length);
+static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int value);
 
-#define CHIP_BUG udelay(100); cs4231_ready(drv); udelay(1000);
+#define CHIP_READY udelay(100); cs4231_ready(drv); udelay(1000);
 
-/* Disable mode change, let chip auto-calibrate */
-static void cs4231_ready(struct sparcaudio_driver *drv) 
+/* Enable cs4231 interrupts atomically. */
+static __inline__ void cs4231_enable_interrupts(struct sparcaudio_driver *drv)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int x = 0;
+  register unsigned long flags;
 
-  cs4231_chip->pioregs->iar = (u_char)IAR_AUTOCAL_END;
-  while (cs4231_chip->pioregs->iar == IAR_NOT_READY && x <= CS_TIMEOUT) {
-    x++;
+  if (cs4231_chip->status & CS_STATUS_INTS_ON)
+    return;
+
+  tprintk(("enabling interrupts\n"));
+  save_flags(flags);
+  cli();
+  cs4231_chip->regs->iar = 0xa;
+  cs4231_chip->regs->idr = INTR_ON;
+  restore_flags(flags);
+
+  cs4231_chip->status |= CS_STATUS_INTS_ON;
+}
+
+/* Disable cs4231 interrupts atomically. */
+static __inline__ void cs4231_disable_interrupts(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  register unsigned long flags;
+
+  if (!(cs4231_chip->status & CS_STATUS_INTS_ON))
+    return;
+
+  tprintk(("disabling interrupts\n"));
+  save_flags(flags);
+  cli();
+  cs4231_chip->regs->iar = 0xa;
+  cs4231_chip->regs->idr = INTR_OFF;
+  restore_flags(flags);
+
+  cs4231_chip->status &= ~CS_STATUS_INTS_ON;
+}
+
+static __inline__ void cs4231_enable_play(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  register unsigned long flags;
+
+  tprintk(("enabling play\n"));
+  save_flags(flags);
+  cli();
+  cs4231_chip->regs->iar = 0x9;
+  cs4231_chip->regs->idr |= PEN_ENABLE;
+  restore_flags(flags);
+}
+
+static __inline__ void cs4231_disable_play(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  register unsigned long flags;
+
+  tprintk(("disabling play\n"));
+  save_flags(flags);
+  cli();
+  cs4231_chip->regs->iar = 0x9;
+  cs4231_chip->regs->idr &= PEN_DISABLE;
+  restore_flags(flags);
+}
+
+static __inline__ void cs4231_enable_rec(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  register unsigned long flags;
+
+  tprintk(("enabling rec\n"));
+  save_flags(flags);
+  cli();
+  cs4231_chip->regs->iar = 0x9;
+  cs4231_chip->regs->idr |= CEN_ENABLE;
+  restore_flags(flags);
+}
+
+static __inline__ void cs4231_disable_rec(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  register unsigned long flags;
+
+  tprintk(("disabling rec\n"));
+  save_flags(flags);
+  cli();
+  cs4231_chip->regs->iar = 0x9;
+  cs4231_chip->regs->idr &= CEN_DISABLE;
+  restore_flags(flags);
+}
+
+static int 
+cs4231_rate_to_bits(struct sparcaudio_driver *drv, int value)
+{
+  int set_bits;
+
+  switch (value) {
+  case 5512:
+    set_bits = CS4231_DFR_5512;
+    break;
+  case 6615:
+    set_bits = CS4231_DFR_6615;
+    break;
+  case 8000:
+    set_bits = CS4231_DFR_8000;
+    break;
+  case 9600:
+    set_bits = CS4231_DFR_9600;
+    break;
+  case 11025:
+    set_bits = CS4231_DFR_11025;
+    break;
+  case 16000:
+    set_bits = CS4231_DFR_16000;
+    break;
+  case 18900:
+    set_bits = CS4231_DFR_18900;
+    break;
+  case 22050:
+    set_bits = CS4231_DFR_22050;
+    break;
+  case 27429:
+    set_bits = CS4231_DFR_27429;
+    break;
+  case 32000:
+    set_bits = CS4231_DFR_32000;
+    break;
+  case 33075:
+    set_bits = CS4231_DFR_33075;
+    break;
+  case 37800:
+    set_bits = CS4231_DFR_37800;
+    break;
+  case 44100:
+    set_bits = CS4231_DFR_44100;
+    break;
+  case 48000:
+    set_bits = CS4231_DFR_48000;
+    break;
+  default:
+    set_bits = -(EINVAL);
+    break;
   }
+  return set_bits;
+}
 
-  x = 0;
-  cs4231_chip->pioregs->iar = 0x0b;
-  while (cs4231_chip->pioregs->idr == AUTOCAL_IN_PROGRESS && x <= CS_TIMEOUT) {
-    x++;
+static int 
+cs4231_encoding_to_bits(struct sparcaudio_driver *drv, int value)
+{
+  int set_bits;
+  
+  switch (value) {
+  case AUDIO_ENCODING_ULAW:
+    set_bits = CS4231_DFR_ULAW;
+    break;
+  case AUDIO_ENCODING_ALAW:
+    set_bits = CS4231_DFR_ALAW;
+    break;
+  case AUDIO_ENCODING_DVI:
+    set_bits = CS4231_DFR_ADPCM;
+    break;
+  case AUDIO_ENCODING_LINEARLE:
+    set_bits = CS4231_DFR_LINEARLE;
+    break;
+  case AUDIO_ENCODING_LINEAR:
+    set_bits = CS4231_DFR_LINEARBE;
+    break;
+  case AUDIO_ENCODING_LINEAR8:
+    set_bits = CS4231_DFR_LINEAR8;
+    break;
+  default:
+    set_bits = -(EINVAL);
+    break;
   }
+  
+  return set_bits;
 }
 
-/* Audio interrupt handler. */
-static void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static int
+cs4231_set_output_encoding(struct sparcaudio_driver *drv, int value)
 {
-  struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  __u8 dummy;
-  int ic = 1;
-  
-  /* Clear the interrupt. */
-  dummy = cs4231_chip->dmaregs.dmacsr;
-  cs4231_chip->dmaregs.dmacsr = dummy;
+  int tmp_bits, set_bits;
 
-  /* now go through and figure out what gets to claim the interrupt */
-  if (dummy & CS_PLAY_INT) {
-    if (dummy & CS_XINT_PNVA) {
-      /* recalculate number of samples */
-      cs4231_playintr(drv);
+  tprintk(("output encoding %d\n", value));
+  if (value != 0) {
+    set_bits = cs4231_encoding_to_bits(drv, value);
+    if (set_bits >= 0) {
+      cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
+      tmp_bits = cs4231_chip->regs->idr;
+      cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits);
+    
+      CHIP_READY
+
+      cs4231_chip->perchip_info.play.encoding = value;
+      return 0;
     }
-    ic = 0;
   }
-  if (dummy & CS_CAPT_INT) {
-    if (dummy & CS_XINT_CNVA) {
-      /* recalculate number of samples */
-      cs4231_recintr(drv);
+  eprintk(("output enc failed\n"));
+  return -EINVAL;
+}
+
+static int cs4231_get_output_encoding(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.play.encoding;
+}
+
+static int
+cs4231_set_input_encoding(struct sparcaudio_driver *drv, int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int tmp_bits, set_bits;
+
+  dprintk(("input encoding %d\n", value));
+  if (value != 0) {
+    set_bits = cs4231_encoding_to_bits(drv, value);
+    if (set_bits >= 0) {
+      cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
+      tmp_bits = cs4231_chip->regs->idr;
+      cs4231_chip->regs->idr = CHANGE_ENCODING(tmp_bits, set_bits);
+
+      CHIP_READY
+
+      cs4231_chip->perchip_info.record.encoding = value;
+      return 0;
     }
-    ic = 0;
   }
-  if ((dummy & CS_XINT_CEMP) 
-      && (cs4231_chip->perchip_info.record.active == 0)) 
-    {
-      ic = 0;
+  eprintk(("input enc failed\n"));
+  return -EINVAL;
+}
+
+static int cs4231_get_input_encoding(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.record.encoding;
+}
+
+static int
+cs4231_set_output_rate(struct sparcaudio_driver *drv, int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int tmp_bits, set_bits;
+
+  tprintk(("output rate %d\n", value));
+  if (value != 0) {
+    set_bits = cs4231_rate_to_bits(drv, value);
+    if (set_bits >= 0) {
+      cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
+      tmp_bits = cs4231_chip->regs->idr;
+      cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits);
+
+      CHIP_READY
+
+      cs4231_chip->perchip_info.play.sample_rate = value;
+      return 0;
     }
-  if ((dummy & CS_XINT_EMPT) && (cs4231_chip->perchip_info.play.active == 0)) {
-    cs4231_chip->dmaregs.dmacsr |= (CS_PPAUSE);
-    cs4231_chip->pioregs->iar = 0x9;
-    cs4231_chip->pioregs->idr &= PEN_DISABLE;
-    
-    cs4231_mute(drv);
+  }
+  eprintk(("output rate failed\n"));
+  return -EINVAL;
+}
+
+static int cs4231_get_output_rate(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.play.sample_rate;
+}
+
+static int
+cs4231_set_input_rate(struct sparcaudio_driver *drv, int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int tmp_bits, set_bits;
+
+  dprintk(("input rate %d\n", value));
+  if (value != 0) {
+    set_bits = cs4231_rate_to_bits(drv, value);
+    if (set_bits >= 0) {
+      cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
+      tmp_bits = cs4231_chip->regs->idr;
+      cs4231_chip->regs->idr = CHANGE_DFR(tmp_bits, set_bits);
+      
+      CHIP_READY
+
+      cs4231_chip->perchip_info.record.sample_rate = value;
+      return 0;
+    }
+  }
+  eprintk(("input rate failed\n"));
+  return -EINVAL;
+}
+
+static int cs4231_get_input_rate(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.record.sample_rate;
+}
+
+/* Generically we support 4 channels. This hardware does 2 */
+static int
+cs4231_set_input_channels(struct sparcaudio_driver *drv, int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int tmp_bits;
+
+  dprintk(("input channels %d\n", value));
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
+  tmp_bits = cs4231_chip->regs->idr;
+  switch (value) {
+  case 1:
+    cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits);
+    break;
+  case 2:
+    cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits);
+    break;
+  default:
+    eprintk(("input chan failed\n"));
+    return -(EINVAL);
+  }  
+
+  CHIP_READY
+
+  cs4231_chip->perchip_info.record.channels = value;
+  return 0;
+}
+
+static int cs4231_get_input_channels(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.record.channels;
+}
+
+/* Generically we support 4 channels. This hardware does 2 */
+static int
+cs4231_set_output_channels(struct sparcaudio_driver *drv, int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int tmp_bits;
+
+  tprintk(("output channels %d\n", value));
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x8;
+  tmp_bits = cs4231_chip->regs->idr;
+  switch (value) {
+  case 1:
+    cs4231_chip->regs->idr = CS4231_MONO_ON(tmp_bits);
+    break;
+  case 2:
+    cs4231_chip->regs->idr = CS4231_STEREO_ON(tmp_bits);
+    break;
+  default:
+    eprintk(("output chan failed\n"));
+    return -(EINVAL);
+  }  
+
+  CHIP_READY
     
-    /* recalculate number of samples */
-    /* cleanup DMA */
-    ic = 0;
+  cs4231_chip->perchip_info.play.channels = value;
+  return 0;
+}
+
+static int cs4231_get_output_channels(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.play.channels;
+}
+
+static int cs4231_set_input_precision(struct sparcaudio_driver *drv, int value)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      cs4231_chip->perchip_info.record.precision = value;
+      return 0;
+}
+
+static int cs4231_get_input_precision(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.record.precision;
+}
+
+static int cs4231_set_output_precision(struct sparcaudio_driver *drv, int value)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      cs4231_chip->perchip_info.play.precision = value;
+      return 0;
+}
+
+static int cs4231_get_output_precision(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.play.precision;
+}
+
+/* Wait until the auto calibration process has finished */
+static void
+cs4231_ready(struct sparcaudio_driver *drv) 
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  unsigned int x = 0;
+
+  cs4231_chip->regs->iar = IAR_AUTOCAL_END;
+  while (cs4231_chip->regs->iar == IAR_NOT_READY && x <= CS_TIMEOUT) {
+    x++;
   }
-  if (dummy & CS_GENL_INT) {
-    ic = 0;
+
+  x = 0;
+  cs4231_chip->regs->iar = 0x0b;
+  while (cs4231_chip->regs->idr == AUTOCAL_IN_PROGRESS && x <= CS_TIMEOUT) {
+    x++;
   }
 }
 
 /* Set output mute */
-static void cs4231_output_muted(struct sparcaudio_driver *drv, unsigned int value)
+static int cs4231_output_muted(struct sparcaudio_driver *drv, int value)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  tprintk(("in cs4231_output_muted: %d\n", value));
   if (!value) {
-    cs4231_chip->pioregs->iar = 0x7;
-    cs4231_chip->pioregs->idr &= OUTCR_UNMUTE;
-    cs4231_chip->pioregs->iar = 0x6;
-    cs4231_chip->pioregs->idr &= OUTCR_UNMUTE;
+    cs4231_chip->regs->iar = 0x7;
+    cs4231_chip->regs->idr &= OUTCR_UNMUTE;
+    cs4231_chip->regs->iar = 0x6;
+    cs4231_chip->regs->idr &= OUTCR_UNMUTE;
     cs4231_chip->perchip_info.output_muted = 0;
   } else {
-    cs4231_chip->pioregs->iar = 0x7;
-    cs4231_chip->pioregs->idr |= OUTCR_MUTE;
-    cs4231_chip->pioregs->iar = 0x6;
-    cs4231_chip->pioregs->idr |= OUTCR_MUTE;
+    cs4231_chip->regs->iar = 0x7;
+    cs4231_chip->regs->idr |= OUTCR_MUTE;
+    cs4231_chip->regs->iar = 0x6;
+    cs4231_chip->regs->idr |= OUTCR_MUTE;
     cs4231_chip->perchip_info.output_muted = 1;
   }
-  return /*(cs4231_chip->perchip_info.output_muted)*/;
+  return 0;
 }
 
-/* Set chip "output" port */
-static unsigned int cs4231_out_port(struct sparcaudio_driver *drv, unsigned int value)
+static int cs4231_get_output_muted(struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  return cs4231_chip->perchip_info.output_muted;
+}
+
+static int cs4231_get_output_ports(struct sparcaudio_driver *drv)
+{
+      return (AUDIO_LINE_OUT | AUDIO_SPEAKER | AUDIO_HEADPHONE);
+}
+
+static int cs4231_get_input_ports(struct sparcaudio_driver *drv)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int r = 0;
+  if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
+    return (AUDIO_LINE_IN | AUDIO_MICROPHONE | AUDIO_ANALOG_LOOPBACK);
+  else
+    return (AUDIO_INTERNAL_CD_IN | AUDIO_LINE_IN | AUDIO_MICROPHONE | 
+	    AUDIO_ANALOG_LOOPBACK);
+}
 
-  /* You can have any combo you want. Just don't tell anyone. */
+/* Set chip "output" port */
+static int cs4231_set_output_port(struct sparcaudio_driver *drv, int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int retval = 0;
 
-  cs4231_chip->pioregs->iar = 0x1a;
-  cs4231_chip->pioregs->idr |= MONO_IOCR_MUTE;
-  cs4231_chip->pioregs->iar = 0x0a;
-  cs4231_chip->pioregs->idr |= PINCR_LINE_MUTE;
-  cs4231_chip->pioregs->idr |= PINCR_HDPH_MUTE;
+  tprintk(("output port: %d\n", value));
+  /* Aaaaaah! It's all coming so fast! Turn it all off, then selectively
+   * enable things.
+   */
+  cs4231_chip->regs->iar = 0x1a;
+  cs4231_chip->regs->idr |= MONO_IOCR_MUTE;
+  cs4231_chip->regs->iar = 0x0a;
+  cs4231_chip->regs->idr |= PINCR_LINE_MUTE;
+  cs4231_chip->regs->idr |= PINCR_HDPH_MUTE;
 
   if (value & AUDIO_SPEAKER) {
-    cs4231_chip->pioregs->iar = 0x1a;
-    cs4231_chip->pioregs->idr &= ~MONO_IOCR_MUTE;
-    r |= AUDIO_SPEAKER;
+    cs4231_chip->regs->iar = 0x1a;
+    cs4231_chip->regs->idr &= ~MONO_IOCR_MUTE;
+    retval |= AUDIO_SPEAKER;
   }
 
   if (value & AUDIO_HEADPHONE) {
-   cs4231_chip->pioregs->iar = 0x0a;
-   cs4231_chip->pioregs->idr &= ~PINCR_HDPH_MUTE;
-   r |= AUDIO_HEADPHONE;
+   cs4231_chip->regs->iar = 0x0a;
+   cs4231_chip->regs->idr &= ~PINCR_HDPH_MUTE;
+   retval |= AUDIO_HEADPHONE;
   }
 
   if (value & AUDIO_LINE_OUT) {
-    cs4231_chip->pioregs->iar = 0x0a;
-    cs4231_chip->pioregs->idr &= ~PINCR_LINE_MUTE;
-    r |= AUDIO_LINE_OUT;
+    cs4231_chip->regs->iar = 0x0a;
+    cs4231_chip->regs->idr &= ~PINCR_LINE_MUTE;
+    retval |= AUDIO_LINE_OUT;
   }
   
-  return (r);
+  cs4231_chip->perchip_info.play.port = retval;
+
+  return (retval);
+}
+
+static int cs4231_get_output_port(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.play.port;
 }
 
 /* Set chip "input" port */
-static unsigned int cs4231_in_port(struct sparcaudio_driver *drv, unsigned int value)
+static int cs4231_set_input_port(struct sparcaudio_driver *drv, int value)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int r = 0;
+  int retval = 0;
 
-  /* The order of these seems to matter. Can't tell yet why. */
-  if (value & AUDIO_INTERNAL_CD_IN) {
-    cs4231_chip->pioregs->iar = 0x1;
-    cs4231_chip->pioregs->idr = CDROM_ENABLE(cs4231_chip->pioregs->idr);
-    cs4231_chip->pioregs->iar = 0x0;
-    cs4231_chip->pioregs->idr = CDROM_ENABLE(cs4231_chip->pioregs->idr);
-    r = AUDIO_INTERNAL_CD_IN;
+  dprintk(("input port: %d\n", value));
+
+  /* You can have one and only one. This is probably wrong, but
+   * appears to be how SunOS is doing it. Should be able to mix.
+   * More work to be done.
+   */
+
+  /* Ultra systems do not support AUDIO_INTERNAL_CD_IN */
+  if (!cs4231_chip->status & CS_STATUS_IS_ULTRA) {
+    if (value & AUDIO_INTERNAL_CD_IN) {
+      cs4231_chip->regs->iar = 0x1;
+      cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr);
+      cs4231_chip->regs->iar = 0x0;
+      cs4231_chip->regs->idr = CDROM_ENABLE(cs4231_chip->regs->idr);
+      retval = AUDIO_INTERNAL_CD_IN;
+    }
   }
   if ((value & AUDIO_LINE_IN)) {
-    cs4231_chip->pioregs->iar = 0x1;
-    cs4231_chip->pioregs->idr = LINE_ENABLE(cs4231_chip->pioregs->idr);
-    cs4231_chip->pioregs->iar = 0x0;
-    cs4231_chip->pioregs->idr = LINE_ENABLE(cs4231_chip->pioregs->idr);
-    r = AUDIO_LINE_IN;
+    cs4231_chip->regs->iar = 0x1;
+    cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr);
+    cs4231_chip->regs->iar = 0x0;
+    cs4231_chip->regs->idr = LINE_ENABLE(cs4231_chip->regs->idr);
+    retval = AUDIO_LINE_IN;
   } else if (value & AUDIO_MICROPHONE) {
-    cs4231_chip->pioregs->iar = 0x1;
-    cs4231_chip->pioregs->idr = MIC_ENABLE(cs4231_chip->pioregs->idr);
-    cs4231_chip->pioregs->iar = 0x0;
-    cs4231_chip->pioregs->idr = MIC_ENABLE(cs4231_chip->pioregs->idr);
-    r = AUDIO_MICROPHONE;
+    cs4231_chip->regs->iar = 0x1;
+    cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr);
+    cs4231_chip->regs->iar = 0x0;
+    cs4231_chip->regs->idr = MIC_ENABLE(cs4231_chip->regs->idr);
+    retval = AUDIO_MICROPHONE;
+  } else if (value & AUDIO_ANALOG_LOOPBACK) {
+    cs4231_chip->regs->iar = 0x1;
+    cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr);
+    cs4231_chip->regs->iar = 0x0;
+    cs4231_chip->regs->idr = OUTPUTLOOP_ENABLE(cs4231_chip->regs->idr);
+    retval = AUDIO_ANALOG_LOOPBACK;
   }
 
-  return (r);
+  cs4231_chip->perchip_info.record.port = retval;
+
+  return (retval);
+}
+
+static int cs4231_get_input_port(struct sparcaudio_driver *drv)
+{
+      struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+      return cs4231_chip->perchip_info.record.port;
 }
 
 /* Set chip "monitor" gain */
-static unsigned int cs4231_monitor_gain(struct sparcaudio_driver *drv, unsigned int value)
+static int cs4231_set_monitor_volume(struct sparcaudio_driver *drv, int value)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
   int a = 0;
 
+  tprintk(("monitor gain: %d\n", value));
+
+  /* This interpolation really sucks. The question is, be compatible 
+   * with ScumOS/Sloaris or not?
+   */
   a = CS4231_MON_MAX_ATEN - (value * (CS4231_MON_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1));
 
-  cs4231_chip->pioregs->iar = 0x0d;
+  cs4231_chip->regs->iar = 0x0d;
   if (a >= CS4231_MON_MAX_ATEN) 
-    cs4231_chip->pioregs->idr = LOOPB_OFF;
+    cs4231_chip->regs->idr = LOOPB_OFF;
+  else 
+    cs4231_chip->regs->idr = ((a << 2) | LOOPB_ON);
+
+  if (value == AUDIO_MAX_GAIN) 
+    cs4231_chip->perchip_info.monitor_gain = AUDIO_MAX_GAIN;
   else 
-    cs4231_chip->pioregs->idr = ((a << 2) | LOOPB_ON);
+    cs4231_chip->perchip_info.monitor_gain = ((CS4231_MAX_DEV_ATEN - a) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_DEV_ATEN + 1));
+
+  return 0;
+}
+
+static int cs4231_get_monitor_volume(struct sparcaudio_driver *drv)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+        return (int)cs4231_chip->perchip_info.monitor_gain;
+}
+
+/* But for play/record we have these cheesy jacket routines because of 
+ * how this crap gets set */
+static int cs4231_set_input_volume(struct sparcaudio_driver *drv, int value)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+	cs4231_record_gain(drv, value, cs4231_chip->perchip_info.record.balance);
+	
+        return 0;
+}
+
+static int cs4231_get_input_volume(struct sparcaudio_driver *drv)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+        return (int)cs4231_chip->perchip_info.record.gain;
+}
+
+static int cs4231_set_output_volume(struct sparcaudio_driver *drv, int value)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+	cs4231_play_gain(drv, value, cs4231_chip->perchip_info.play.balance);
+	
+        return 0;
+}
+
+static int cs4231_get_output_volume(struct sparcaudio_driver *drv)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+        return cs4231_chip->perchip_info.play.gain;
+}
+
+/* Likewise for balance */
+static int cs4231_set_input_balance(struct sparcaudio_driver *drv, int value)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+	cs4231_chip->perchip_info.record.balance = value;
+	cs4231_record_gain(drv, cs4231_chip->perchip_info.record.gain, cs4231_chip->perchip_info.record.balance);
+	
+        return 0;
+}
+
+static int cs4231_get_input_balance(struct sparcaudio_driver *drv)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+        return (int)cs4231_chip->perchip_info.record.balance;
+}
+
+static int cs4231_set_output_balance(struct sparcaudio_driver *drv, int value)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  if (value == AUDIO_MAX_GAIN) return AUDIO_MAX_GAIN;
+	cs4231_chip->perchip_info.play.balance = value;
+	cs4231_play_gain(drv, cs4231_chip->perchip_info.play.gain, cs4231_chip->perchip_info.play.balance);
+	
+        return 0;
+}
+
+static int cs4231_get_output_balance(struct sparcaudio_driver *drv)
+{
+        struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  return ((CS4231_MAX_DEV_ATEN - a) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_DEV_ATEN + 1));
+        return (int)cs4231_chip->perchip_info.play.balance;
 }
 
 /* Set chip record gain */
-static unsigned int cs4231_record_gain(struct sparcaudio_driver *drv, unsigned int value, unsigned char balance)
+static int cs4231_record_gain(struct sparcaudio_driver *drv, int value, unsigned char balance)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int tmp = 0, r, l, ra, la;
+  int tmp = 0, r, l, r_adj, l_adj;
   unsigned char old_gain;
 
   r = l = value;
@@ -232,31 +745,33 @@
     l = MAX(0, (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)));
   }
 
-  la = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
-  ra = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
+  l_adj = l * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
+  r_adj = r * (CS4231_MAX_GAIN + 1) / (AUDIO_MAX_GAIN + 1);
   
-  cs4231_chip->pioregs->iar = 0x0;
-  old_gain = cs4231_chip->pioregs->idr;
-  cs4231_chip->pioregs->idr = RECGAIN_SET(old_gain, la);
-  cs4231_chip->pioregs->iar = 0x1;
-  old_gain = cs4231_chip->pioregs->idr;
-  cs4231_chip->pioregs->idr = RECGAIN_SET(old_gain, ra);
+  cs4231_chip->regs->iar = 0x0;
+  old_gain = cs4231_chip->regs->idr;
+  cs4231_chip->regs->idr = RECGAIN_SET(old_gain, l_adj);
+  cs4231_chip->regs->iar = 0x1;
+  old_gain = cs4231_chip->regs->idr;
+  cs4231_chip->regs->idr = RECGAIN_SET(old_gain, r_adj);
   
   if (l == value) {
-    (l == 0) ? (tmp = 0) : (tmp = ((la + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1));
+    (l == 0) ? (tmp = 0) : (tmp = ((l_adj + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1));
   } else if (r == value) {
-    (r == 0) ? (tmp = 0) : (tmp = ((ra + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1));
+    (r == 0) ? (tmp = 0) : (tmp = ((r_adj + 1) * AUDIO_MAX_GAIN) / (CS4231_MAX_GAIN + 1));
   }
-  return (tmp);
+  cs4231_chip->perchip_info.record.gain = tmp;
+  return 0;
 }
 
 /* Set chip play gain */
-static unsigned int cs4231_play_gain(struct sparcaudio_driver *drv, unsigned int value, unsigned char balance)
+static int cs4231_play_gain(struct sparcaudio_driver *drv, int value, unsigned char balance)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  unsigned int tmp = 0, r, l, ra, la;
+  int tmp = 0, r, l, r_adj, l_adj;
   unsigned char old_gain;
 
+  tprintk(("in play_gain: %d %c\n", value, balance));
   r = l = value;
   if (balance < AUDIO_MID_BALANCE) {
     r = MAX(0, (int)(value - ((AUDIO_MID_BALANCE - balance) << AUDIO_BALANCE_SHIFT)));
@@ -264,156 +779,179 @@
     l = MAX(0, (int)(value - ((balance - AUDIO_MID_BALANCE) << AUDIO_BALANCE_SHIFT)));
   }
 
-  if (l == 0) {
-    la = CS4231_MAX_DEV_ATEN;
-  } else {
-    la = CS4231_MAX_ATEN - (l * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1));
-  }
-  if (r == 0) {
-    ra = CS4231_MAX_DEV_ATEN;
-  } else {
-    ra = CS4231_MAX_ATEN - (r * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1));
-  }
+  (l == 0) ? (l_adj = CS4231_MAX_DEV_ATEN) : (l_adj = CS4231_MAX_ATEN - (l * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)));
+  (r == 0) ? (r_adj = CS4231_MAX_DEV_ATEN) : (r_adj = CS4231_MAX_ATEN - (r * (CS4231_MAX_ATEN + 1) / (AUDIO_MAX_GAIN + 1)));
   
-  cs4231_chip->pioregs->iar = 0x6;
-  old_gain = cs4231_chip->pioregs->idr;
-  cs4231_chip->pioregs->idr = GAIN_SET(old_gain, la);
-  cs4231_chip->pioregs->iar = 0x7;
-  old_gain = cs4231_chip->pioregs->idr;
-  cs4231_chip->pioregs->idr = GAIN_SET(old_gain, ra);
+  cs4231_chip->regs->iar = 0x6;
+  old_gain = cs4231_chip->regs->idr;
+  cs4231_chip->regs->idr = GAIN_SET(old_gain, l_adj);
+  cs4231_chip->regs->iar = 0x7;
+  old_gain = cs4231_chip->regs->idr;
+  cs4231_chip->regs->idr = GAIN_SET(old_gain, r_adj);
   
   if ((value == 0) || (value == AUDIO_MAX_GAIN)) {
     tmp = value;
   } else {
     if (l == value) {
-      tmp = ((CS4231_MAX_ATEN - la) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1));
+      tmp = ((CS4231_MAX_ATEN - l_adj) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1));
     } else if (r == value) {
-      tmp = ((CS4231_MAX_ATEN - ra) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1));
+      tmp = ((CS4231_MAX_ATEN - r_adj) * (AUDIO_MAX_GAIN + 1) / (CS4231_MAX_ATEN + 1));
     }
   }
-  return (tmp);
+  cs4231_chip->perchip_info.play.gain = tmp;
+
+  return 0;
 }
 
 /* Reset the audio chip to a sane state. */
-static void cs4231_reset(struct sparcaudio_driver *drv)
+static void cs4231_chip_reset(struct sparcaudio_driver *drv)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  cs4231_chip->dmaregs.dmacsr = CS_CHIP_RESET;
-  cs4231_chip->dmaregs.dmacsr = 0x00;
-  cs4231_chip->dmaregs.dmacsr |= CS_CDC_RESET;
-  
-  udelay(100);
-  
-  cs4231_chip->dmaregs.dmacsr &= ~(CS_CDC_RESET);
-  cs4231_chip->pioregs->iar |= IAR_AUTOCAL_BEGIN;
+  tprintk(("in cs4231_chip_reset\n"));
+
+  cs4231_chip->regs->dmacsr = CS_CHIP_RESET;
+  cs4231_chip->regs->dmacsr = 0x00;
+  cs4231_chip->regs->dmacsr |= CS_CDC_RESET;
   
-  CHIP_BUG
-    
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x0c;
-  cs4231_chip->pioregs->idr = MISC_IR_MODE2;
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x08;
-  cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; /* Ulaw */
+  udelay(20);
   
-  CHIP_BUG
-    
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
-  cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT; /* Ulaw */
+  cs4231_chip->regs->dmacsr &= ~(CS_CDC_RESET);
+  cs4231_chip->regs->iar |= IAR_AUTOCAL_BEGIN;
   
-  CHIP_BUG
+  CHIP_READY
     
-  cs4231_chip->pioregs->iar = 0x19;
-  
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x0c;
+  cs4231_chip->regs->idr = MISC_IR_MODE2;
+
+  /* This is the equivalent of DEFAULT_DATA_FMAT */
+  cs4231_set_input_encoding(drv, AUDIO_ENCODING_ULAW);
+  cs4231_set_input_rate(drv, CS4231_RATE);
+  cs4231_set_input_channels(drv, CS4231_CHANNELS);
+  cs4231_set_input_precision(drv, CS4231_PRECISION);
+
+  cs4231_set_output_encoding(drv, AUDIO_ENCODING_ULAW);
+  cs4231_set_output_rate(drv, CS4231_RATE);
+  cs4231_set_output_channels(drv, CS4231_CHANNELS);
+  cs4231_set_output_precision(drv, CS4231_PRECISION);
+
+  cs4231_chip->regs->iar = 0x19;
   /* see what we can turn on */
-  if (cs4231_chip->pioregs->idr & CS4231A)
+  if (cs4231_chip->regs->idr & CS4231A) {
+    tprintk(("This is a CS4231A\n"));
     cs4231_chip->status |= CS_STATUS_REV_A;
-  else
+  } else
     cs4231_chip->status &= ~CS_STATUS_REV_A;
   
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x10;
-  cs4231_chip->pioregs->idr = OLB_ENABLE;
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x10;
+  cs4231_chip->regs->idr = OLB_ENABLE;
   
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x11;
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x11;
   if (cs4231_chip->status & CS_STATUS_REV_A)
-    cs4231_chip->pioregs->idr = (HPF_ON | XTALE_ON);
+    cs4231_chip->regs->idr = (HPF_ON | XTALE_ON);
   else
-    cs4231_chip->pioregs->idr = (HPF_ON);
+    cs4231_chip->regs->idr = (HPF_ON);
   
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1a;
-  cs4231_chip->pioregs->idr = 0x00;
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x1a;
+  cs4231_chip->regs->idr = 0x00;
   
   /* Now set things up for defaults */
-  cs4231_chip->perchip_info.play.port = cs4231_out_port(drv, AUDIO_SPEAKER);
-  cs4231_chip->perchip_info.record.port = cs4231_in_port(drv, AUDIO_MICROPHONE);
-  cs4231_chip->perchip_info.play.gain = cs4231_play_gain(drv, CS4231_DEFAULT_PLAYGAIN, AUDIO_MID_BALANCE);
-  cs4231_chip->perchip_info.record.gain = cs4231_record_gain(drv, CS4231_DEFAULT_RECGAIN, AUDIO_MID_BALANCE);
-  cs4231_chip->perchip_info.monitor_gain = cs4231_monitor_gain(drv, LOOPB_OFF);
+  cs4231_set_input_balance(drv, AUDIO_MID_BALANCE);
+  cs4231_set_output_balance(drv, AUDIO_MID_BALANCE);
+
+  cs4231_set_input_volume(drv, CS4231_DEFAULT_RECGAIN);
+  cs4231_set_output_volume(drv, CS4231_DEFAULT_PLAYGAIN);
+
+  cs4231_set_input_port(drv, AUDIO_MICROPHONE);
+  cs4231_set_output_port(drv, AUDIO_SPEAKER);
+
+  cs4231_set_monitor_volume(drv, LOOPB_OFF);
   
-  cs4231_chip->pioregs->iar = (u_char)IAR_AUTOCAL_END;
+  cs4231_chip->regs->iar = IAR_AUTOCAL_END;
   
   cs4231_ready(drv);
   
-  cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x09;
-  cs4231_chip->pioregs->idr &= ACAL_DISABLE;
-  cs4231_chip->pioregs->iar = (u_char)IAR_AUTOCAL_END;
+  cs4231_chip->regs->iar = IAR_AUTOCAL_BEGIN | 0x09;
+  cs4231_chip->regs->idr &= ACAL_DISABLE;
+  cs4231_chip->regs->iar = IAR_AUTOCAL_END;
   
   cs4231_ready(drv);
 
   cs4231_output_muted(drv, 0);
+
+  cs4231_chip->recording_count = 0;
+  cs4231_chip->playing_count = 0;
 }
 
-static void cs4231_mute(struct sparcaudio_driver *drv)
+static int 
+cs4231_length_to_samplecount(struct audio_prinfo *thisdir, unsigned int length)
 {
-  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  unsigned int count;
 
-  if (!(cs4231_chip->status & CS_STATUS_REV_A)) {
-    cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN;
-    udelay(100);
-    cs4231_chip->pioregs->iar = IAR_AUTOCAL_END;
-    CHIP_BUG
-  }
+  if (thisdir->channels == 2)
+    count = (length/2);
+  else 
+    count = length;
+  
+  if (thisdir->encoding == AUDIO_ENCODING_LINEAR)
+    count = (count/2);
+  else if (thisdir->encoding == AUDIO_ENCODING_DVI)
+    count = (count/4);
+  
+  return count;
 }
 
-/* Not yet useful */
-#if 0
-static int cs4231_len_to_sample(struct sparcaudio_driver *drv, int length, int direction)
+static void cs4231_getsamplecount(struct sparcaudio_driver *drv, unsigned int length, unsigned int direction)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
-  int sample;
+  struct audio_prinfo *thisdir;
+  unsigned int count, nextcount, curcount;
 
-  if (/* number of channels == 2*/0) {
-    sample = (length/2);
-  } else {
-    sample = length;
-  }
-  if (/*encoding == AUDIO_ENCODING_LINEAR*/0) {
-    sample = sample/2;
-  }
-  return (sample);
+  if (direction == 1) /* record */ 
+    {
+      thisdir = &cs4231_chip->perchip_info.record;
+      curcount = 
+	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacc);
+      nextcount = 
+	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmacnc);
+    }
+  else /* play */
+    {
+      thisdir = &cs4231_chip->perchip_info.play;
+      curcount = 
+	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapc);
+      nextcount = 
+	cs4231_length_to_samplecount(thisdir, cs4231_chip->regs->dmapnc);
+    }
+  count = thisdir->samples;
+  length = cs4231_length_to_samplecount(thisdir, length);
+  thisdir->samples = ((count - nextcount) + (length - curcount));
 }
-#endif
 
 static int cs4231_open(struct inode * inode, struct file * file, struct sparcaudio_driver *drv)
 {	
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  /* Set the default audio parameters. */
-  
-  cs4231_chip->perchip_info.play.sample_rate = CS4231_RATE;
-  cs4231_chip->perchip_info.play.channels = CS4231_CHANNELS;
-  cs4231_chip->perchip_info.play.precision = CS4231_PRECISION;
-  cs4231_chip->perchip_info.play.encoding = AUDIO_ENCODING_ULAW;
-  
-  cs4231_chip->perchip_info.record.sample_rate = CS4231_RATE;
-  cs4231_chip->perchip_info.record.channels = CS4231_CHANNELS;
-  cs4231_chip->perchip_info.record.precision = CS4231_PRECISION;
-  cs4231_chip->perchip_info.record.encoding = AUDIO_ENCODING_ULAW;
-  
+  /* Set the default audio parameters if not already in use. */
+  if (file->f_mode & FMODE_WRITE) {
+    if (!(drv->flags & SDF_OPEN_WRITE) && 
+	(cs4231_chip->perchip_info.play.active == 0)) {
+      cs4231_chip->perchip_info.play.open = 1;
+      cs4231_set_output_port(drv, AUDIO_SPEAKER);
+    }
+  }
+
+  if (file->f_mode & FMODE_READ) {
+    if (!(drv->flags & SDF_OPEN_READ) && 
+	(cs4231_chip->perchip_info.record.active == 0)) {
+      cs4231_chip->perchip_info.record.open = 1;
+      cs4231_set_input_port(drv, AUDIO_MICROPHONE);
+    }
+  }  
+
   cs4231_ready(drv);
   
-  cs4231_chip->status |= CS_STATUS_NEED_INIT;
-  
-  CHIP_BUG
+  CHIP_READY
     
   MOD_INC_USE_COUNT;
   
@@ -422,31 +960,48 @@
 
 static void cs4231_release(struct inode * inode, struct file * file, struct sparcaudio_driver *drv)
 {
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
   /* zero out any info about what data we have as well */
-  /* should insert init on close variable optionally calling cs4231_reset() */
+
+  if (file->f_mode & FMODE_READ) 
+      cs4231_chip->perchip_info.record.open = 0;
+
+  if (file->f_mode & FMODE_WRITE) 
+      cs4231_chip->perchip_info.play.open = 0;
+
+  if (!cs4231_chip->perchip_info.play.open && !cs4231_chip->perchip_info.record.open && (cs4231_chip->status & CS_STATUS_INIT_ON_CLOSE)) {
+    cs4231_chip_reset(drv);
+    cs4231_chip->status &= ~CS_STATUS_INIT_ON_CLOSE;
+  }
+
   MOD_DEC_USE_COUNT;
 }
 
-static int cs4231_playintr(struct sparcaudio_driver *drv)
+static void cs4231_playintr(struct sparcaudio_driver *drv)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  /* Send the next byte of outgoing data. */
-#if 0
-  if (cs4231_chip->output_ptr && cs4231_chip->output_count > 0) {
-    cs4231_chip->dmaregs.dmapnva = dma_handle;
-    cs4231_chip->dmaregs.dmapnc = length; 
-    cs4231_chip->output_ptr++;
-    cs4231_chip->output_count--;
-    
-    /* Done with the buffer? Notify the midlevel driver. */
-    if (cs4231_chip->output_count == 0) {
-      cs4231_chip->output_ptr = NULL;
-      cs4231_chip->output_count = 0;
-      sparcaudio_output_done(drv);
-    }
+  if (cs4231_chip->playlen == 0)
+    cs4231_chip->playlen = cs4231_chip->output_size;
+
+  if (cs4231_chip->output_ptr && cs4231_chip->output_size > 0) {
+    cs4231_chip->regs->dmapnva = (__u32) cs4231_chip->output_ptr;
+    cs4231_chip->regs->dmapnc = cs4231_chip->output_size;
+    cs4231_chip->output_size = 0;
+    cs4231_chip->output_ptr = NULL;
+    cs4231_chip->playing_count++;
+  }
+
+  /* Get two buffers into the pipe, then chain... */
+  if (cs4231_chip->playing_count < 3) 
+    sparcaudio_output_done(drv, 0);
+  else {
+    cs4231_chip->playing_count--;
+    sparcaudio_output_done(drv, 1);
   }
-#endif
+
+  return; 
 }
 
 static void cs4231_recmute(int fmt)
@@ -468,72 +1023,55 @@
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
-  cs4231_recmute(cs4231_chip->perchip_info.record.encoding);
-
   if (cs4231_chip->perchip_info.record.active == 0) {
     cs4231_pollinput(drv);
-    cs4231_chip->pioregs->iar = 0x9;
-    cs4231_chip->pioregs->idr &= CEN_DISABLE;
+    cs4231_recmute(cs4231_chip->perchip_info.record.encoding);
+    cs4231_disable_rec(drv);    
   }
-  /* Read the next byte of incoming data. */
-#if 0
-  if (cs4231_chip->input_ptr && cs4231_chip->input_count > 0) {
-    cs4231_chip->dmaregs.dmacnva = dma_handle;
-    cs4231_chip->dmaregs.dmacnc = length;
-    cs4231_chip->input_ptr++;
-    cs4231_chip->input_count--;
-    
-    /* Done with the buffer? Notify the midlevel driver. */
-    if (cs4231_chip->input_count == 0) {
-      cs4231_chip->input_ptr = NULL;
-      cs4231_chip->input_count = 0;
-      sparcaudio_input_done(drv);
-    }
+  if (cs4231_chip->input_ptr) {
+    cs4231_chip->regs->dmacnva = (__u32) cs4231_chip->input_ptr;
+    cs4231_chip->regs->dmacnc = cs4231_chip->input_size;
+    cs4231_chip->input_ptr = NULL;
+    cs4231_chip->input_size = 0;
+    sparcaudio_input_done(drv);
   }
-#endif
+  return 1;
 }
 
 static void cs4231_start_output(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
+  cs4231_chip->output_ptr = buffer;
+  cs4231_chip->output_size = count;
+
   if (cs4231_chip->perchip_info.play.active || (cs4231_chip->perchip_info.play.pause))
     return;
 
   cs4231_ready(drv);
 
-  if (cs4231_chip->status & CS_STATUS_NEED_INIT)
-    {
-      cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x08;
-      cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT;
-      cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
-      cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT;
-
-      CHIP_BUG
-
-      cs4231_chip->status &= ~CS_STATUS_NEED_INIT;
-    }
-
-  if (!cs4231_chip->perchip_info.play.pause) 
-    {
-      /* init dma foo here */
-      cs4231_chip->dmaregs.dmacsr &= ~CS_XINT_PLAY;
-      cs4231_chip->dmaregs.dmacsr &= ~CS_PPAUSE;
-      if (cs4231_playintr(drv)) {
-	cs4231_chip->dmaregs.dmacsr |= CS_PLAY_SETUP;
-	cs4231_chip->pioregs->iar = 0x9;
-	cs4231_chip->pioregs->idr |= PEN_ENABLE;
-      }
-    }
   cs4231_chip->perchip_info.play.active = 1;
+
+  cs4231_chip->playing_count = 0;
+  cs4231_disable_play(drv);
+  cs4231_chip->regs->dmacsr &= ~CS_XINT_PLAY;
+  cs4231_chip->regs->dmacsr &= ~CS_PPAUSE;
+  cs4231_playintr(drv);
+  cs4231_enable_play(drv);
+  cs4231_chip->regs->dmacsr |= CS_PLAY_SETUP;
+  cs4231_output_muted(drv, 0);
+  cs4231_ready(drv);
 }
 
 static void cs4231_stop_output(struct sparcaudio_driver *drv)
 {
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
+  tprintk(("in cs4231_stop_output\n"));
+  cs4231_chip->output_ptr = NULL;
+  cs4231_chip->output_size = 0;
   cs4231_chip->perchip_info.play.active = 0;
-  cs4231_chip->dmaregs.dmacsr |= (CS_PPAUSE);
+  cs4231_chip->regs->dmacsr |= (CS_PPAUSE);
 }
 
 static void cs4231_pollinput(struct sparcaudio_driver *drv)
@@ -541,10 +1079,10 @@
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
   int x = 0;
 
-  while (!(cs4231_chip->dmaregs.dmacsr & CS_XINT_COVF) && x <= CS_TIMEOUT) {
+  while (!(cs4231_chip->regs->dmacsr & CS_XINT_COVF) && x <= CS_TIMEOUT) {
     x++;
   }
-  cs4231_chip->dmaregs.dmacsr |= CS_XINT_CEMP;
+  cs4231_chip->regs->dmacsr |= CS_XINT_CEMP;
 }
 
 static void cs4231_start_input(struct sparcaudio_driver *drv, __u8 * buffer, unsigned long count)
@@ -556,29 +1094,14 @@
 
   cs4231_ready(drv);
 
-  if (cs4231_chip->status & CS_STATUS_NEED_INIT)
-    {
-      cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x08;
-      cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT;
-      cs4231_chip->pioregs->iar = IAR_AUTOCAL_BEGIN | 0x1c;
-      cs4231_chip->pioregs->idr = DEFAULT_DATA_FMAT;
-
-      CHIP_BUG
-
-      cs4231_chip->status &= ~CS_STATUS_NEED_INIT;
-    }
-
-  if (!cs4231_chip->perchip_info.record.pause)
-    {
-      /* init dma foo here */
-      cs4231_chip->dmaregs.dmacsr &= ~CS_XINT_CAPT;
-      cs4231_chip->dmaregs.dmacsr &= ~CS_CPAUSE;
-      cs4231_recintr(drv);
-      cs4231_chip->dmaregs.dmacsr |= CS_CAPT_SETUP;
-      cs4231_chip->pioregs->iar = 0x9;
-      cs4231_chip->pioregs->idr |= CEN_ENABLE;
-    }
   cs4231_chip->perchip_info.record.active = 1;
+  cs4231_chip->recording_count = 0;
+  /* init dma foo here */
+  cs4231_chip->regs->dmacsr &= ~CS_XINT_CAPT;
+  cs4231_chip->regs->dmacsr &= ~CS_CPAUSE;
+  cs4231_recintr(drv);
+  cs4231_chip->regs->dmacsr |= CS_CAPT_SETUP;
+  cs4231_enable_rec(drv);
 }
 
 static void cs4231_stop_input(struct sparcaudio_driver *drv)
@@ -586,43 +1109,166 @@
   struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
 
   cs4231_chip->perchip_info.record.active = 0;
-  cs4231_chip->dmaregs.dmacsr |= (CS_CPAUSE);
+  cs4231_chip->regs->dmacsr |= (CS_CPAUSE);
 
   cs4231_pollinput(drv);
 
   /* need adjust the end pointer, process the input, and clean up the dma */
 
-  cs4231_chip->pioregs->iar = 0x09;
-  cs4231_chip->pioregs->idr &= CEN_DISABLE;
+  cs4231_disable_rec(drv);
 }
 
 static void cs4231_audio_getdev(struct sparcaudio_driver *drv,
                                  audio_device_t * audinfo)
 {
-        strncpy(audinfo->name, "cs4231", sizeof(audinfo->name) - 1);
-        strncpy(audinfo->version, "x", sizeof(audinfo->version) - 1);
-        strncpy(audinfo->config, "audio", sizeof(audinfo->config) - 1);
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+  strncpy(audinfo->name, "SUNW,CS4231", sizeof(audinfo->name) - 1);
+  /* versions: SPARCstation 4/5=a, Ultra=b */
+  if (cs4231_chip->status & CS_STATUS_IS_ULTRA)
+    strncpy(audinfo->version, "b", sizeof(audinfo->version) - 1);
+  else
+    strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
+  strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
+}
+
+
+static int cs4231_audio_getdev_sunos(struct sparcaudio_driver *drv)
+{
+        return AUDIO_DEV_CS4231;
 }
 
+static void cs4231_loopback(struct sparcaudio_driver *drv, unsigned int value)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+
+  cs4231_chip->regs->iar = 0x0d;
+  cs4231_chip->regs->idr = (value ? LOOPB_ON : 0);
+}
+
+static int cs4231_ioctl(struct inode * inode, struct file * file,
+			unsigned int cmd, unsigned long arg, 
+			struct sparcaudio_driver *drv)
+{
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  int retval = 0;
+  
+  switch (cmd) {
+  case AUDIO_DIAG_LOOPBACK:
+    cs4231_chip->status |= CS_STATUS_INIT_ON_CLOSE;
+    cs4231_loopback(drv, (unsigned int)arg);
+    break;
+  default:
+    retval = -EINVAL;
+  }
+
+  return retval;
+}
 
-/* The ioctl handler should be expected to identify itself and handle loopback
-   mode */
-/* There will also be a handler for getinfo and setinfo */
+
+/* Audio interrupt handler. */
+void cs4231_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+  struct sparcaudio_driver *drv = (struct sparcaudio_driver *)dev_id;
+  struct cs4231_chip *cs4231_chip = (struct cs4231_chip *)drv->private;
+  __u32 dummy;
+  
+  tprintk(("in cs4231_interrupt\n"));
+
+  /* Clear the interrupt. */
+  dummy = cs4231_chip->regs->dmacsr;
+  cs4231_chip->regs->dmacsr = dummy;
+
+  /* now go through and figure out what gets to claim the interrupt 
+   * if anything since we may be doing shared interrupts 
+   */
+
+  if (dummy & CS_PLAY_INT) {
+    if (dummy & CS_XINT_PNVA) {
+      cs4231_chip->perchip_info.play.samples += 
+	cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.play), 
+				     cs4231_chip->playlen);
+      cs4231_playintr(drv);
+    }
+  }
+
+  if (dummy & CS_CAPT_INT) {
+    if (dummy & CS_XINT_CNVA) {
+      cs4231_chip->perchip_info.record.samples += 
+	cs4231_length_to_samplecount(&(cs4231_chip->perchip_info.record), 
+				     cs4231_chip->reclen);
+      cs4231_recintr(drv);
+    }
+  }
+  if ((dummy & CS_XINT_CEMP) 
+      && (cs4231_chip->perchip_info.record.active == 0)) 
+    {
+      cs4231_chip->perchip_info.record.active = 0;
+    }
+  if ((dummy & CS_XINT_EMPT) && (cs4231_chip->perchip_info.play.active == 0)) {
+    cs4231_chip->regs->dmacsr |= (CS_PPAUSE);
+    cs4231_disable_play(drv);
+    cs4231_output_muted(drv, 1);
+    
+    cs4231_getsamplecount(drv, cs4231_chip->playlen, 0);
+  }
+
+  if (dummy & CS_GENL_INT) {
+    /* If we get here we must be sharing an interrupt, but I haven't code 
+       to handle this right now */
+  }
+
+}
 
 static struct sparcaudio_operations cs4231_ops = {
 	cs4231_open,
 	cs4231_release,
-	NULL,			/* cs4231_ioctl */
+	cs4231_ioctl,
 	cs4231_start_output,
 	cs4231_stop_output,
 	cs4231_start_input,
         cs4231_stop_input,
 	cs4231_audio_getdev,
+        cs4231_set_output_volume,
+        cs4231_get_output_volume,
+        cs4231_set_input_volume,
+        cs4231_get_input_volume,
+        cs4231_set_monitor_volume,
+        cs4231_get_monitor_volume,
+	cs4231_set_output_balance,
+	cs4231_get_output_balance,
+        cs4231_set_input_balance,
+        cs4231_get_input_balance,
+        cs4231_set_output_channels,
+        cs4231_get_output_channels,
+        cs4231_set_input_channels,
+        cs4231_get_input_channels,
+        cs4231_set_output_precision,
+        cs4231_get_output_precision,
+        cs4231_set_input_precision,
+        cs4231_get_input_precision,
+        cs4231_set_output_port,
+        cs4231_get_output_port,
+        cs4231_set_input_port,
+        cs4231_get_input_port,
+        cs4231_set_output_encoding,
+        cs4231_get_output_encoding,
+        cs4231_set_input_encoding,
+        cs4231_get_input_encoding,
+        cs4231_set_output_rate,
+        cs4231_get_output_rate,
+        cs4231_set_input_rate,
+	cs4231_get_input_rate,
+	cs4231_audio_getdev_sunos,
+	cs4231_get_output_ports,
+	cs4231_get_input_ports,
+	cs4231_output_muted,
+	cs4231_get_output_muted,
 };
 
 /* Attach to an cs4231 chip given its PROM node. */
-static inline int
-cs4231_attach(struct sparcaudio_driver *drv, struct linux_sbus_device *sdev)
+static int cs4231_attach(struct sparcaudio_driver *drv, 
+			 struct linux_sbus_device *sdev)
 {
   struct cs4231_chip *cs4231_chip;
   int err;
@@ -639,57 +1285,76 @@
   /* Point at the information structure and initialize it. */
   drv->ops = &cs4231_ops;
   cs4231_chip = (struct cs4231_chip *)drv->private;
-#if 0
-  cs4231_chip->input_ptr = NULL;
-  cs4231_chip->input_count = 0;
-  cs4231_chip->output_ptr = NULL;
-  cs4231_chip->output_count = 0;
-#endif
+  cs4231_chip->input_ptr = cs4231_chip->output_ptr = NULL;
+  cs4231_chip->input_size = cs4231_chip->output_size = 0;
+  cs4231_chip->status = 0;
 
   /* Map the registers into memory. */
   prom_apply_sbus_ranges(sbus, sdev->reg_addrs, 1, sdev);
   cs4231_chip->regs_size = sdev->reg_addrs[0].reg_size;
-  cs4231_chip->pioregs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0, 
-  					sdev->reg_addrs[0].reg_size,
-				      "cs4231", sdev->reg_addrs[0].which_io, 0);
-  if (!cs4231_chip->pioregs) {
+  cs4231_chip->regs = sparc_alloc_io(sdev->reg_addrs[0].phys_addr, 0,
+				     sdev->reg_addrs[0].reg_size, 
+				     "cs4231", sdev->reg_addrs[0].which_io, 
+				     0);
+
+  if (!cs4231_chip->regs) {
     printk(KERN_ERR "cs4231: could not allocate registers\n");
     kfree(drv->private);
     return -EIO;
   }
 
-  /* Reset the audio chip. */
-  cs4231_reset(drv);
-
   /* Attach the interrupt handler to the audio interrupt. */
   cs4231_chip->irq = sdev->irqs[0].pri;
 
 #ifndef __sparc_v9__
   request_irq(cs4231_chip->irq, cs4231_interrupt, SA_SHIRQ, "cs4231", drv);
 #else
-  dcookie.real_dev_id = s;
+  dcookie.real_dev_id = drv;
   dcookie.imap = dcookie.iclr = 0;
   dcookie.pil = -1;
   dcookie.bus_cookie = sdev->my_bus;
-  request_irq (cs4231_chip->irq, cs4231_interrupt, (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), "cs4231", drv);
+  request_irq (cs4231_chip->irq, cs4231_interrupt, (SA_SHIRQ | SA_SBUS | SA_DCOOKIE), "cs4231", &dcookie);
   cs4231_chip->irq = dcookie.ret_ino;
 #endif
   enable_irq(cs4231_chip->irq);
 
+  cs4231_enable_interrupts(drv);
+
+  /* Reset the audio chip. */
+  cs4231_chip_reset(drv);
+
   /* Register ourselves with the midlevel audio driver. */
   err = register_sparcaudio_driver(drv);
+
   if (err < 0) {
     printk(KERN_ERR "cs4231: unable to register\n");
+    cs4231_disable_interrupts(drv);
     disable_irq(cs4231_chip->irq);
     free_irq(cs4231_chip->irq, drv);
-    sparc_free_io(cs4231_chip->pioregs, cs4231_chip->regs_size);
+    sparc_free_io(cs4231_chip->regs, cs4231_chip->regs_size);
     kfree(drv->private);
     return -EIO;
   }
 
+  cs4231_chip->perchip_info.play.active = 
+    cs4231_chip->perchip_info.play.pause = 0;
+
+  cs4231_chip->perchip_info.record.active = 
+    cs4231_chip->perchip_info.record.pause = 0;
+
+  cs4231_chip->perchip_info.play.avail_ports = (AUDIO_HEADPHONE |
+						AUDIO_SPEAKER |
+						AUDIO_LINE_OUT);
+
+  cs4231_chip->perchip_info.record.avail_ports = (AUDIO_INTERNAL_CD_IN |
+						  AUDIO_LINE_IN | 
+						  AUDIO_MICROPHONE |
+						  AUDIO_ANALOG_LOOPBACK);
+
   /* Announce the hardware to the user. */
-  printk(KERN_INFO "cs4231 at 0x%lx irq %d\n",
-	 (unsigned long)cs4231_chip->pioregs, cs4231_chip->irq);
+  printk(KERN_INFO "cs4231%c at 0x%lx irq %d\n",
+	 (cs4231_chip->status & CS_STATUS_REV_A) ? 'a' : ' ', 
+	 (unsigned long)cs4231_chip->regs, cs4231_chip->irq);
   
   /* Success! */
   return 0;
@@ -705,6 +1370,8 @@
   struct linux_sbus *bus;
   struct linux_sbus_device *sdev;
   
+  num_drivers = 0;
+  
   /* Probe each SBUS for cs4231 chips. */
   for_all_sbusdev(sdev,bus) {
     if (!strcmp(sdev->prom_name, "SUNW,CS4231")) {
@@ -727,10 +1394,11 @@
 {
         struct cs4231_chip *info = (struct cs4231_chip *)drv->private;
 
+	cs4231_disable_interrupts(drv);
         unregister_sparcaudio_driver(drv);
         disable_irq(info->irq);
         free_irq(info->irq, drv);
-        sparc_free_io(info->pioregs, info->regs_size);
+        sparc_free_io(info->regs, info->regs_size);
         kfree(drv->private);
 }
 
@@ -745,3 +1413,21 @@
 }
 #endif
 
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/audio/cs4231.h linux/drivers/sbus/audio/cs4231.h
--- v2.1.100/linux/drivers/sbus/audio/cs4231.h	Mon Mar 17 14:54:28 1997
+++ linux/drivers/sbus/audio/cs4231.h	Fri May  8 00:23:41 1998
@@ -10,65 +10,83 @@
 
 #include <linux/types.h>
 
+/* According to the CS4231A data provided on CS web site and sun's includes */
+
 struct cs4231_regs {
-         u_char iar;            /* Index Address Register */
-         u_char pad0[3];         
-         u_char idr;            /* Indexed Data Register */
-         u_char pad1[3];        
-         u_char statr;          /* Status Register */
-         u_char pad2[3];        
-         u_char piodr;          /* PIO Data Register I/O */
-         u_char pad3[3];        
+  __volatile__ __u8 iar;            /* Index Address Register */
+  __volatile__ __u8 pad0[3];         
+  __volatile__ __u8 idr;            /* Indexed Data Register */
+  __volatile__ __u8 pad1[3];        
+  __volatile__ __u8 statr;          /* Status Register */
+  __volatile__ __u8 pad2[3];        
+  __volatile__ __u8 piodr;          /* PIO Data Register */
+  __volatile__ __u8 pad3[3];        
+  __volatile__ __u32 dmacsr;         /* APC CSR */
+  __volatile__ __u32 dmapad[3];        
+  __volatile__ __u32 dmacva;         /* Capture Virtual Address */
+  __volatile__ __u32 dmacc;          /* Capture Count */
+  __volatile__ __u32 dmacnva;        /* Capture Next Virtual Address */
+  __volatile__ __u32 dmacnc;         /* Capture Next Count */
+  __volatile__ __u32 dmapva;         /* Playback Virtual Address */
+  __volatile__ __u32 dmapc;          /* Playback Count */
+  __volatile__ __u32 dmapnva;        /* Playback Next Virtual Address */
+  __volatile__ __u32 dmapnc;         /* Playback Next Count */
 };
 
-struct cs4231_dma {
-         u_long         dmacsr;         /* APC CSR */
-         u_long         dmapad[3];        
-         u_long         dmacva;         /* Capture Virtual Address */
-         u_long         dmacc;          /* Capture Count */
-         u_long         dmacnva;        /* Capture Next Virtual Address */
-         u_long         dmacnc;         /* Capture Next Count */
-         u_long         dmapva;         /* Playback Virtual Address */
-         u_long         dmapc;          /* Playback Count */
-         u_long         dmapnva;        /* Playback Next Virtual Address */
-         u_long         dmapnc;         /* Playback Next Count */
-};
+/* Our structure for each chip */
 
 struct cs4231_chip {
-        struct cs4231_regs *pioregs;
-        struct cs4231_dma dmaregs;
-	struct audio_info perchip_info;
-	int irq;
-	unsigned long regs_size;
-
-	/* Keep track of various info */
-	volatile unsigned int status;
-
-        int dma;
-        int dma2;
+  struct cs4231_regs *regs;
+  struct audio_info perchip_info;
+  unsigned int playlen, reclen;
+  int irq;
+  unsigned long regs_size;
+  
+  /* Keep track of various info */
+  volatile unsigned int status;
+  
+  /* Current buffer that the driver is playing. */
+  volatile __u8 * output_ptr;
+  volatile unsigned long output_size;
+
+  /* Current record buffer. */
+  volatile __u8 * input_ptr;
+  volatile unsigned long input_size;
+
+  /* Number of buffers in the pipe. */
+  volatile unsigned long playing_count;
+  volatile unsigned long recording_count;
 };
 
-/* Status bits */
+/* Local status bits */
 #define CS_STATUS_NEED_INIT 0x01
 #define CS_STATUS_INIT_ON_CLOSE 0x02
 #define CS_STATUS_REV_A 0x04
+#define CS_STATUS_INTS_ON 0x08
+#define CS_STATUS_IS_ULTRA 0x10
 
 #define CS_TIMEOUT      9000000
 
 #define GAIN_SET(var, gain)     ((var & ~(0x3f)) | gain)
 #define RECGAIN_SET(var, gain)  ((var & ~(0x1f)) | gain)
 
-#define IAR_AUTOCAL_BEGIN       0x40 /* IAR_MCE */
-#define IAR_AUTOCAL_END         ~(0x40) /* IAR_MCD */
-#define IAR_NOT_READY            0x80    /* 80h not ready CODEC state */
+/* bits 0-3 set address of register accessed by idr register */
+/* bit 4 allows access to idr registers 16-31 in mode 2 only */
+/* bit 5 if set causes dma transfers to cease if the int bit of status set */
+#define IAR_AUTOCAL_BEGIN       0x40    /* MCE */
+#define IAR_NOT_READY           0x80    /* INIT */
 
-/* Each register assumed mode 1 and 2 unless noted */
+#define IAR_AUTOCAL_END         ~(IAR_AUTOCAL_BEGIN) /* MCD */
+
+/* Registers 1-15 modes 1 and 2. Registers 16-31 mode 2 only */
+/* Registers assumed to be same in both modes unless noted */
 
 /* 0 - Left Input Control */
 /* 1 - Right Input Control */
 #define MIC_ENABLE(var)         ((var & 0x2f) | 0x80)
 #define LINE_ENABLE(var)        (var & 0x2f)
 #define CDROM_ENABLE(var)       ((var & 0x2f) | 0x40)
+#define OUTPUTLOOP_ENABLE(var)  ((var & 0x2f) | 0xC0)
 #define INPUTCR_AUX1            0x40
 
 /* 2 - Left Aux 1 Input Control */
@@ -85,31 +103,41 @@
 #define CHANGE_DFR(var, val)            ((var & ~(0xF)) | val)
 #define CHANGE_ENCODING(var, val)       ((var & ~(0xe0)) | val)
 #define DEFAULT_DATA_FMAT               CS4231_DFR_ULAW
+#define CS4231_DFR_5512                 0x01
+#define CS4231_DFR_6615                 0x0f
 #define CS4231_DFR_8000                 0x00
 #define CS4231_DFR_9600                 0x0e
 #define CS4231_DFR_11025                0x03
 #define CS4231_DFR_16000                0x02
 #define CS4231_DFR_18900                0x05
 #define CS4231_DFR_22050                0x07
+#define CS4231_DFR_27429                0x04
 #define CS4231_DFR_32000                0x06
+#define CS4231_DFR_33075                0x0d
 #define CS4231_DFR_37800                0x09
 #define CS4231_DFR_44100                0x0b
 #define CS4231_DFR_48000                0x0c
 #define CS4231_DFR_LINEAR8              0x00
 #define CS4231_DFR_ULAW                 0x20
+#define CS4231_DFR_LINEARLE             0x40
 #define CS4231_DFR_ALAW                 0x60
-#define CS4231_DFR_ADPCM                0xa0
-#define CS4231_DFR_LINEARBE             0xc0
+#define CS4231_DFR_ADPCM                0xa0 /* N/A in mode 1 */
+#define CS4231_DFR_LINEARBE             0xc0 /* N/A in mode 1 */
 #define CS4231_STEREO_ON(val)           (val | 0x10)
 #define CS4231_MONO_ON(val)             (val & ~0x10)
 
 /* 9 - Interface Config. Register */
-#define CHIP_INACTIVE           0x08
-#define PEN_ENABLE              (0x01)
+#define PEN_ENABLE              (0x01) /* Playback Enable */
 #define PEN_DISABLE             (~0x01)
-#define CEN_ENABLE              (0x02)
+#define CEN_ENABLE              (0x02) /* Capture Enable */
 #define CEN_DISABLE             (~0x02)
-#define ACAL_DISABLE            (~0x08)
+#define SDC_ENABLE              (0x04) /* Turn on single DMA Channel mode */
+#define ACAL_CONV               0x08   /* Turn on converter autocal */
+#define ACAL_DISABLE            (~0x08) 
+#define ACAL_DAC                0x10  /* Turn on DAC autocal */
+#define ACAL_FULL               (ACAL_DAC|ACAL_CONV) /* Turn on full autocal */
+#define PPIO                    0x20 /* do playback via PIO rather than DMA */
+#define CPIO                    0x40 /* do capture via PIO rather than DMA */
 #define ICR_AUTOCAL_INIT        0x01
 
 /* 10 - Pin Control Register */
@@ -129,8 +157,8 @@
 #define LOOPB_ON                0x01
 #define LOOPB_OFF               0x00
 
-/* 14 - Unused (mode 1) */
-/* 15 - Unused (mode 1) */
+/* 14 - shared play/capture upper (mode 1) */
+/* 15 - shared play/capture lower (mode 1) */
 
 /* 14 - Playback Upper (mode 2) */
 /* 15 - Playback Lower (mode 2) */
@@ -138,11 +166,16 @@
 /* The rest are mode 2 only */
 
 /* 16 - Alternate Feature 1 Enable */
-#define OLB_ENABLE              0x80
+#define DAC_ZERO                0x01
+#define PLAY_MCE                0x10
+#define CAPTURE_MCE             0x20
+#define TIMER_ENABLE            0x40
+#define OLB_ENABLE              0x80 /* go to 2.88 vpp analog output */
 
 /* 17 - Alternate Feature 2 Enable */
-#define HPF_ON                  0x01
-#define XTALE_ON                0x20
+#define HPF_ON                  0x01 /* High Pass Filter */
+#define XTALE_ON                0x02 /* Enable both crystals */
+#define APAR_OFF                0x04 /* ADPCM playback accum reset */
 
 /* 18 - Left Line Input Gain */
 /* 19 - Right Line Input Gain */
@@ -151,11 +184,18 @@
 /* 21 - Timer Low */
 
 /* 22 - unused */
-/* 23 - unused */
+
+/* 23 - Alt. Fea. Ena 3 */
+#define ACF 0x01
 
 /* 24 - Alternate Feature Status */
 #define CS_PU                   0x01 /* Underrun */
-#define CS_PO                   0x20 /* Overrun */
+#define CS_PO                   0x02 /* Overrun */
+#define CS_CU                   0x04 /* Underrun */
+#define CS_CO                   0x08 /* Overrun */
+#define CS_PI                   0x10 
+#define CS_CI                   0x20 
+#define CS_TI                   0x40 
 
 /* 25 - Version */
 #define CS4231A         0x20
@@ -163,7 +203,9 @@
 
 /* 26 - Mono I/O Control */
 #define CHANGE_MONO_GAIN(val)   ((val & ~(0xFF)) | val)
+#define MONO_IOCR_BYPASS     0x20 
 #define MONO_IOCR_MUTE       0x40
+#define MONO_IOCR_INMUTE     0x80
 
 /* 27 - Unused */
 
@@ -176,29 +218,29 @@
 /* 31 - Capture Lower */
 
 /* Following are CSR register definitions for the Sparc */
-/* Also list "Solaris" equivs for now, not really useful tho */
-#define CS_INT_PENDING 0x800000 /* APC_IP */ /* Interrupt Pending */
-#define CS_PLAY_INT    0x400000 /* APC_PI */ /* Playback interrupt */
-#define CS_CAPT_INT    0x200000 /* APC_CI */ /* Capture interrupt */
-#define CS_GENL_INT    0x100000 /* APC_EI */ /* General interrupt */
-#define CS_XINT_ENA    0x80000  /* APC_IE */ /* General ext int. enable */
-#define CS_XINT_PLAY   0x40000  /* APC_PIE */ /* Playback ext intr */
-#define CS_XINT_CAPT   0x20000  /* APC_CIE */ /* Capture ext intr */
-#define CS_XINT_GENL   0x10000  /* APC_EIE */ /* Error ext intr */
-#define CS_XINT_EMPT   0x8000   /* APC_PMI */ /* Pipe empty interrupt */
-#define CS_XINT_PEMP   0x4000   /* APC_PM */ /* Play pipe empty */
-#define CS_XINT_PNVA   0x2000   /* APC_PD */ /* Playback NVA dirty */
-#define CS_XINT_PENA   0x1000   /* APC_PMIE */ /* play pipe empty Int enable */
-#define CS_XINT_COVF   0x800    /* APC_CM */ /* Cap data dropped on floor */
-#define CS_XINT_CNVA   0x400    /* APC_CD */ /* Capture NVA dirty */
-#define CS_XINT_CEMP   0x200    /* APC_CMI */ /* Capture pipe empty interrupt */
-#define CS_XINT_CENA   0x100    /* APC_CMIE */ /* Cap. pipe empty int enable */
-#define CS_PPAUSE      0x80     /* APC_PPAUSE */ /* Pause the play DMA */
-#define CS_CPAUSE      0x40     /* APC_CPAUSE */ /* Pause the capture DMA */
-#define CS_CDC_RESET   0x20     /* APC_CODEC_PDN */ /* CODEC RESET */
-#define PDMA_READY     0x08     /* PDMA_GO */
-#define CDMA_READY     0x04     /* CDMA_GO */
-#define CS_CHIP_RESET  0x01     /* APC_RESET */       /* Reset the chip */
+
+#define CS_INT_PENDING 0x800000 /* Interrupt Pending */
+#define CS_PLAY_INT    0x400000 /* Playback interrupt */
+#define CS_CAPT_INT    0x200000 /* Capture interrupt */
+#define CS_GENL_INT    0x100000 /* General interrupt */
+#define CS_XINT_ENA    0x80000  /* General ext int. enable */
+#define CS_XINT_PLAY   0x40000  /* Playback ext intr */
+#define CS_XINT_CAPT   0x20000  /* Capture ext intr */
+#define CS_XINT_GENL   0x10000  /* Error ext intr */
+#define CS_XINT_EMPT   0x8000   /* Pipe empty interrupt */
+#define CS_XINT_PEMP   0x4000   /* Play pipe empty */
+#define CS_XINT_PNVA   0x2000   /* Playback NVA dirty */
+#define CS_XINT_PENA   0x1000   /* play pipe empty Int enable */
+#define CS_XINT_COVF   0x800    /* Cap data dropped on floor */
+#define CS_XINT_CNVA   0x400    /* Capture NVA dirty */
+#define CS_XINT_CEMP   0x200    /* Capture pipe empty interrupt */
+#define CS_XINT_CENA   0x100    /* Cap. pipe empty int enable */
+#define CS_PPAUSE      0x80     /* Pause the play DMA */
+#define CS_CPAUSE      0x40     /* Pause the capture DMA */
+#define CS_CDC_RESET   0x20     /* CODEC RESET */
+#define PDMA_READY     0x08     /* Play DMA Go */
+#define CDMA_READY     0x04     /* Capture DMA Go */
+#define CS_CHIP_RESET  0x01     /* Reset the chip */
 
 #define CS_INIT_SETUP  (CDMA_READY | PDMA_READY | CS_XINT_ENA | CS_XINT_PLAY | CS_XINT_GENL | CS_INT_PENDING | CS_PLAY_INT | CS_CAPT_INT | CS_GENL_INT) 
 
@@ -223,8 +265,5 @@
 #define CS4231_CHANNELS     (1)             /* channels/sample */
 
 #define CS4231_RATE   (8000)                /* default sample rate */
-/* Other rates supported are:
- * 9600, 11025, 16000, 18900, 22050, 32000, 37800, 44100, 48000 
- */
 
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/bwtwo.c linux/drivers/sbus/char/bwtwo.c
--- v2.1.100/linux/drivers/sbus/char/bwtwo.c	Sat Apr 25 18:13:11 1998
+++ linux/drivers/sbus/char/bwtwo.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: bwtwo.c,v 1.20 1998/03/10 20:18:22 jj Exp $
+/* $Id: bwtwo.c,v 1.21 1998/04/24 12:29:53 davem Exp $
  * bwtwo.c: bwtwo console driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/creator.c linux/drivers/sbus/char/creator.c
--- v2.1.100/linux/drivers/sbus/char/creator.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/creator.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: creator.c,v 1.14 1998/03/10 20:18:32 jj Exp $
+/* $Id: creator.c,v 1.15 1998/04/13 07:26:55 davem Exp $
  * creator.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -507,11 +507,10 @@
 		sbus_hw_hide_cursor ();
 }
 
-__initfunc(static unsigned long ffb_postsetup (fbinfo_t *fb, unsigned long memory_start))
+__initfunc(static void ffb_postsetup (fbinfo_t *fb))
 {
-	fb->info.ffb.clut = (u32 *)(memory_start);
-        fb->color_map = (u8 *)(memory_start+256*4);
-        return memory_start + 256*4 + 256*3;
+	fb->info.ffb.clut = kmalloc(256 * 4, GFP_ATOMIC);
+        fb->color_map = kmalloc(256 * 3, GFP_ATOMIC);
 }
 
 __initfunc(void creator_setup (fbinfo_t *fb, int slot, int ffb_node, unsigned long ffb, int ffb_io))
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/fb.h linux/drivers/sbus/char/fb.h
--- v2.1.100/linux/drivers/sbus/char/fb.h	Thu Sep  4 12:54:48 1997
+++ linux/drivers/sbus/char/fb.h	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: fb.h,v 1.33 1997/08/25 07:50:29 jj Exp $
+/* $Id: fb.h,v 1.34 1998/04/13 07:26:55 davem Exp $
  * fb.h: contains the definitions of the structures that various sun
  *       frame buffer can use to do console driver stuff.
  *
@@ -150,7 +150,7 @@
 	void   (*setcurshape)(struct fbinfo *);
 	void   (*setcursormap)(struct fbinfo *, unsigned char *, 
 			unsigned char *, unsigned char *);
-	unsigned long (*postsetup)(struct fbinfo *, unsigned long);
+	void   (*postsetup)(struct fbinfo *);
 	void (*clear_fb)(int);
 	void (*set_other_palette)(int);
 	void	(*blitc)(unsigned short, int, int);
@@ -208,7 +208,7 @@
 extern int sbus_hw_cursor_shown;
 extern int sun_prom_console_id;
 
-extern unsigned long cg_postsetup(fbinfo_t *, unsigned long);
+extern void cg_postsetup(fbinfo_t *);
 
 #define FB_DEV(x) (MINOR(x) / 32)
 
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/leo.c linux/drivers/sbus/char/leo.c
--- v2.1.100/linux/drivers/sbus/char/leo.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/leo.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: leo.c,v 1.26 1998/03/10 20:18:29 jj Exp $
+/* $Id: leo.c,v 1.27 1998/04/13 07:26:57 davem Exp $
  * leo.c: SUNW,leo 24/8bit frame buffer driver
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -503,14 +503,13 @@
 }
 
 
-__initfunc(static unsigned long leo_postsetup (fbinfo_t *fb, unsigned long memory_start))
+__initfunc(static void leo_postsetup (fbinfo_t *fb))
 {
-	fb->info.leo.cluts[0] = (u32 *)(memory_start);
-	fb->info.leo.cluts[1] = (u32 *)(memory_start+256*4);
-	fb->info.leo.cluts[2] = (u32 *)(memory_start+256*4*2);
-	fb->info.leo.xlut = (u8 *)(memory_start+256*4*3);
-	fb->color_map = (u8 *)(memory_start+256*4*3+256);
-	return memory_start + (256*4*3) + 256 + 256*3;
+	fb->info.leo.cluts[0] = kmalloc(256 * 4, GFP_ATOMIC);
+	fb->info.leo.cluts[1] = kmalloc(256 * 4, GFP_ATOMIC);
+	fb->info.leo.cluts[2] = kmalloc(256 * 4, GFP_ATOMIC);
+	fb->info.leo.xlut     = kmalloc(256,     GFP_ATOMIC);
+	fb->color_map         = kmalloc(256 * 3, GFP_ATOMIC);
 }
 
 __initfunc(void leo_setup (fbinfo_t *fb, int slot, u32 leo, int leo_io))
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/mach64.c linux/drivers/sbus/char/mach64.c
--- v2.1.100/linux/drivers/sbus/char/mach64.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/mach64.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: mach64.c,v 1.17 1998/04/06 06:42:23 davem Exp $
+/* $Id: mach64.c,v 1.18 1998/05/03 21:56:07 davem Exp $
  * mach64.c: Ultra/PCI Mach64 console driver.
  *
  * Just about all of this is from the PPC/mac driver, see that for
@@ -28,7 +28,7 @@
 #include "mach64.h"
 #include "fb.h"
 
-static unsigned int mach64_pci_membase;
+static unsigned int mach64_pci_membase, mach64_pci_membase2;
 static unsigned int mach64_pci_iobase;
 
 #define MACH64_LE_FBOFF	0x000000
@@ -83,6 +83,9 @@
 	if (vma->vm_offset == (mach64_pci_iobase & PAGE_MASK)) {
 		addr = __pa((pcivga_iobase & PAGE_MASK));
 		size = PAGE_SIZE;
+	} else if(mach64_pci_membase2 &&
+		  (vma->vm_offset == (mach64_pci_membase2 & PAGE_MASK))) {
+		addr = __pa((pcivga_membase2 & PAGE_MASK));
 	} else if (vma->vm_offset >= (mach64_pci_membase + 0x800000)) {
 		addr = __pa(pcivga_membase) - mach64_pci_membase
 			+ vma->vm_offset;
@@ -194,6 +197,9 @@
 	else
 		pcivga_membase = addr & PCI_BASE_ADDRESS_MEM_MASK;
 
+	pcivga_membase2 = (pdev->base_address[2] &
+			   PCI_BASE_ADDRESS_MEM_MASK);
+
 	if(!pcivga_iobase || !pcivga_membase) {
 		prom_printf("mach64_init: I/O or MEM baseaddr is missing\n");
 		prom_printf("mach64_init: ba[0]=%016lx ba[1]=%016lx\n",
@@ -209,8 +215,12 @@
 				  PCI_BASE_ADDRESS_1, &mach64_pci_iobase);
 	mach64_pci_iobase &= PCI_BASE_ADDRESS_IO_MASK;
 
-	printk("mach64_init: IOBASE[%016lx] MEMBASE[%016lx]\n",
-		pcivga_iobase, pcivga_membase);
+	pcibios_read_config_dword(pdev->bus->number, pdev->devfn,
+				  PCI_BASE_ADDRESS_2, &mach64_pci_membase2);
+	mach64_pci_membase2 &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	printk("mach64_init: IOBASE[%016lx] M1[%016lx] M2[%016lx]\n",
+		pcivga_iobase, pcivga_membase, pcivga_membase2);
 
 	cookie = pdev->sysdata;
 	pbm = cookie->pbm;
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/pcicons.c linux/drivers/sbus/char/pcicons.c
--- v2.1.100/linux/drivers/sbus/char/pcicons.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/pcicons.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: pcicons.c,v 1.13 1998/04/01 06:55:11 ecd Exp $
+/* $Id: pcicons.c,v 1.17 1998/05/03 21:56:10 davem Exp $
  * pcicons.c: PCI specific probing and console operations layer.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -17,6 +17,7 @@
 #include <linux/major.h>
 #include <linux/timer.h>
 #include <linux/version.h>
+#include <linux/malloc.h>
 
 #include <asm/uaccess.h>
 #include <asm/oplib.h>
@@ -47,6 +48,13 @@
 static void pci_install_consops(void);
 static int (*fbuf_offset)(int);
 
+static int color_fbuf_offset_1280_144 (int cindex)
+{
+	register int i = (cindex/144);
+	/* (1280 * CHAR_HEIGHT) == 101.0000.0000.0000 */
+	return skip_bytes + (i << 14) + (i << 12) + ((cindex % 144) << 3);
+}
+
 static int color_fbuf_offset_1152_128(int cindex)
 {
 	register int i = (cindex >> 7);
@@ -61,6 +69,30 @@
 	return skip_bytes + (i << 14) + ((cindex & 127) << 3);
 }
 
+static int color_fbuf_offset_800_96 (int cindex)
+{
+	register int i = (cindex / 96);
+	/* (800 * CHAR_HEIGHT) == 11.0010.0000.0000 */
+	return skip_bytes + (i<<13) + (i<<12) + (i<<9) + ((cindex % 96)<<3);
+}
+
+static int color_fbuf_offset_640_80 (int cindex)
+{
+	register int i = (cindex/80);
+	/* (640 * CHAR_HEIGHT) == 10.1000.0000.0000 */
+	return skip_bytes + (i << 13) + (i << 11) + ((cindex % 80) << 3);
+}
+	 
+static int color_fbuf_offset_generic (int cindex)
+{
+#if 0
+	/* XXX Implement me -DaveM */
+	return skip_bytes + (cindex / video_num_columns) * bytes_per_row + ((cindex % video_num_columns) << 3);
+#else
+	return 0;
+#endif
+}
+
 static __u32 expand_bits_8[16] = {
 	0x00000000,
 	0x000000ff,
@@ -349,7 +381,7 @@
 	for (i = 0; i < 256; i++) {
 		for (line = 0; line < CHAR_HEIGHT; line++) {
 			unsigned char value;
-			__get_user_ret(value, (arg + (i + 32 + line)), -EFAULT);
+			__get_user_ret(value, (arg + (i * 32 + line)), -EFAULT);
 			vga_font[i * CHAR_HEIGHT + line] = value;
 		}
 	}
@@ -478,16 +510,13 @@
 		fb->switch_from_graph();
 }
 
-static unsigned long
-pci_postsetup(fbinfo_t *fb, unsigned long memory_start)
+static void pci_postsetup(fbinfo_t *fb)
 {
-	fb->color_map = (char *)memory_start;
+	fb->color_map = kmalloc(fb->type.fb_cmsize * 3, GFP_ATOMIC);
 	pci_set_palette();
-	return memory_start + fb->type.fb_cmsize * 3;
 }
 
-__initfunc(static unsigned long
-pci_con_type_init(unsigned long kmem_start, const char **display_desc))
+__initfunc(static void pci_con_type_init(const char **display_desc))
 {
 	can_do_color = 1;
 
@@ -505,12 +534,9 @@
 		/*
 		 * Fake the screen memory with some CPU memory
 		 */
-		video_mem_base = kmem_start;
-		kmem_start += video_screen_size;
-		video_mem_term = kmem_start;
+		video_mem_base = (unsigned long)kmalloc(video_screen_size, GFP_ATOMIC);
+		video_mem_term = (video_mem_base + video_screen_size);
 	}
-
-	return kmem_start;
 }
 
 __initfunc(static void pci_con_type_init_finish(void))
@@ -573,14 +599,19 @@
 
 unsigned long pcivga_iobase = 0;
 unsigned long pcivga_membase = 0;
+unsigned long pcivga_membase2 = 0;
 
 static struct {
 	int depth;
 	int resx, resy;
 	int x_margin, y_margin;
 } scr_def[] = {
+	{ 8, 1280, 1024, 64, 80 },
+	{ 8, 1152, 1024, 64, 80 },
 	{ 8, 1152, 900, 64, 18 },
 	{ 8, 1024, 768, 0, 0 },
+	{ 8, 800, 600, 16, 12 },
+	{ 8, 640, 480, 0, 0 },
 	{ 0 }
 };
 
@@ -626,6 +657,9 @@
 		x_margin = scr_def[i].x_margin;
 		y_margin = scr_def[i].y_margin;
 		skip_bytes = y_margin * fb->linebytes + x_margin;
+
+		/* XXX Check that ORIG_VIDEO_COLS match -DaveM */
+		fbuf_offset = color_fbuf_offset_generic;
 		switch (fb->type.fb_width) {
 			case 1152:
 				fbuf_offset = color_fbuf_offset_1152_128;
@@ -633,11 +667,26 @@
 			case 1024:
 				fbuf_offset = color_fbuf_offset_1024_128;
 				break;
+			case 1280:
+				fbuf_offset = color_fbuf_offset_1280_144;
+				break;
+			case 800:
+				fbuf_offset = color_fbuf_offset_800_96;
+				break;
+			case 640:
+				fbuf_offset = color_fbuf_offset_640_80;
+				break;
 			default:
 				prom_printf("can't handle console width %d\n",
 					    fb->type.fb_width);
 				prom_halt();
 		}
+		break;
+	}
+	if(scr_def[i].depth == 0) {
+		prom_printf("can't support console resolution %dX%d\n",
+			    fb->type.fb_width, fb->type.fb_height);
+		prom_halt();
 	}
 
 	pci_install_consops();
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/pcicons.h linux/drivers/sbus/char/pcicons.h
--- v2.1.100/linux/drivers/sbus/char/pcicons.h	Thu Sep  4 12:54:48 1997
+++ linux/drivers/sbus/char/pcicons.h	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: pcicons.h,v 1.2 1997/08/24 12:13:11 ecd Exp $
+/* $Id: pcicons.h,v 1.3 1998/05/03 21:56:12 davem Exp $
  * pcicons.h: Stuff which is generic across all PCI console drivers.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -13,6 +13,7 @@
 
 extern unsigned long pcivga_iobase;
 extern unsigned long pcivga_membase;
+extern unsigned long pcivga_membase2;
 
 extern unsigned char vga_font[8192];
 
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/sbuscons.c linux/drivers/sbus/char/sbuscons.c
--- v2.1.100/linux/drivers/sbus/char/sbuscons.c	Sat Apr 25 18:13:11 1998
+++ linux/drivers/sbus/char/sbuscons.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: sbuscons.c,v 1.15 1998/03/31 01:49:50 davem Exp $
+/* $Id: sbuscons.c,v 1.17 1998/04/24 12:29:54 davem Exp $
  * sbuscons.c: Routines specific to SBUS frame buffer consoles.
  *
  * Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su)
@@ -366,8 +366,7 @@
 	sbus_blitc (*contents, (unsigned long) contents);
 }
 
-__initfunc(static unsigned long
-sbus_con_type_init(unsigned long kmem_start, const char **display_desc))
+__initfunc(static void sbus_con_type_init(const char **display_desc))
 {
         can_do_color = (con_type != FBTYPE_SUN2BW);
 
@@ -381,11 +380,9 @@
 		/*
 		 * fake the screen memory with some CPU memory
 		 */
-		video_mem_base = kmem_start;
-		kmem_start += video_screen_size;
-		video_mem_term = kmem_start;
+		video_mem_base = (unsigned long)kmalloc(video_screen_size, GFP_ATOMIC);
+		video_mem_term = (video_mem_base + video_screen_size);
 	}
-	return kmem_start;
 }
 
 __initfunc(static void sbus_con_type_init_finish(void))
@@ -694,10 +691,9 @@
 	        (*fb_restore_palette) (&fbinfo[0]);
 }
 
-__initfunc(unsigned long cg_postsetup(fbinfo_t *fb, unsigned long start_mem))
+__initfunc(void cg_postsetup(fbinfo_t *fb))
 {
-	fb->color_map = (char *)start_mem;
-	return start_mem + 256*3;
+	fb->color_map = kmalloc(256 * 3, GFP_ATOMIC);
 }
 
 static char *known_cards [] __initdata = {
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/suncons.c linux/drivers/sbus/char/suncons.c
--- v2.1.100/linux/drivers/sbus/char/suncons.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/suncons.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: suncons.c,v 1.79 1998/01/30 10:59:23 jj Exp $
+/* $Id: suncons.c,v 1.80 1998/04/13 07:27:01 davem Exp $
  * suncons.c: Sparc platform console generic layer.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -14,6 +14,7 @@
 #include <linux/vt.h>
 #include <linux/selection.h>
 #include <linux/proc_fs.h>
+#include <linux/malloc.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -100,10 +101,8 @@
 {
 }
 
-static unsigned long nop_con_type_init(unsigned long mem_start,
-				       const char **display_desc)
+static void nop_con_type_init(const char **display_desc)
 {
-	return mem_start;
 }
 
 static void nop_con_type_init_finish(void)
@@ -222,9 +221,9 @@
 	suncons_ops.console_restore_palette();
 }
 
-unsigned long con_type_init(unsigned long mem_start, const char **disp_desc)
+void con_type_init(const char **disp_desc)
 {
-	return suncons_ops.con_type_init(mem_start, disp_desc);
+	return suncons_ops.con_type_init(disp_desc);
 }
 
 void con_type_init_finish(void)
@@ -283,14 +282,14 @@
 extern int sbus_console_probe(void);
 extern int serial_console;
 
-__initfunc(static unsigned long finish_console_init(unsigned long memory_start))
+__initfunc(static void finish_console_init(void))
 {
 	static int confinish_has_run = 0;
 	int i, j;
 
 	if(confinish_has_run != 0) {
 		printk("finish_console_init: Someone tries to run me twice.\n");
-		return memory_start;
+		return;
 	}
 	for(i = FRAME_BUFFERS; i > 1; i--)
 		if(fbinfo[i - 1].type.fb_type != FBTYPE_NOTYPE)
@@ -299,7 +298,7 @@
 
 	for(j = 0; j < i; j++)
 		if (fbinfo[j].postsetup)
-			memory_start = (*fbinfo[j].postsetup)(fbinfo+j, memory_start);
+			(*fbinfo[j].postsetup)(fbinfo+j);
 
 	suncons_ops.clear_screen();
 
@@ -316,30 +315,50 @@
 #endif
 
 	confinish_has_run = 1;
+}
 
-	return memory_start;
+__initfunc(int con_is_present(void))
+{
+	return serial_console ? 0 : 1;
 }
 
 #ifdef CONFIG_PCI
+extern int pci_console_probe(void);
 extern void pci_console_inithook(void);
-#endif
 
-__initfunc(int con_is_present(void))
+__initfunc(void pci_console_init(void))
 {
-	return serial_console ? 0 : 1;
+	/* Nothing to do in this case. */
+	if (!con_is_present())
+		return;
+		
+	if (!cons_type) {
+		/* Some console was already found on SBUS or UPA */
+		return;
+	}
+
+	if(pci_console_probe()) {
+		prom_printf("Could not probe PCI console, bailing out...\n");
+		prom_halt();
+	}
+
+	finish_console_init();
+
+	con_type_init_finish();
 }
 
-__initfunc(unsigned long sun_console_init(unsigned long memory_start))
+#endif /* CONFIG_PCI */
+
+__initfunc(void sun_console_init(void))
 {
 	int i;
 
 	/* Nothing to do in this case. */
 	if (!con_is_present())
-		return memory_start;
+		return;
 
-	fbinfo = (fbinfo_t *)memory_start;
+	fbinfo = kmalloc(sizeof(fbinfo_t) * FRAME_BUFFERS, GFP_ATOMIC);
 	memset(fbinfo, 0, FRAME_BUFFERS * sizeof(fbinfo_t));
-	memory_start += (FRAME_BUFFERS * sizeof(fbinfo_t));
 	fbinfos = 0;
 
 	for (i = 0; i < FRAME_BUFFERS; i++)
@@ -348,39 +367,12 @@
 	if(sbus_console_probe()) {
 #ifdef CONFIG_PCI
 		cons_type = 1;
-		pci_console_inithook();
-		return memory_start;
+		return pci_console_inithook();
 #else
 		/* XXX We need to write PROM console fallback driver... */
 		prom_printf("Could not probe SBUS console, bailing out...\n");
 		prom_halt();
 #endif
 	}
-	return finish_console_init(memory_start);
-}
-
-#ifdef CONFIG_PCI
-extern int pci_console_probe(void);
-
-__initfunc(unsigned long pci_console_init(unsigned long memory_start))
-{
-	/* Nothing to do in this case. */
-	if (!con_is_present())
-		return memory_start;
-		
-	if (!cons_type) {
-		/* Some console was already found on SBUS or UPA */
-		return memory_start;
-	}
-
-	if(pci_console_probe()) {
-		prom_printf("Could not probe PCI console, bailing out...\n");
-		prom_halt();
-	}
-
-	memory_start = finish_console_init(memory_start);
-
-	con_type_init_finish();
-	return memory_start;
+	return finish_console_init();
 }
-#endif
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.1.100/linux/drivers/sbus/char/sunkbd.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/char/sunkbd.c	Fri May  8 00:23:41 1998
@@ -79,6 +79,11 @@
 
 struct l1a_kbd_state l1a_state = { 0, 0 };
 
+/* Dummy function for now, we need it to link.  -DaveM */
+void kbd_reset_setup(char *str, int *ints)
+{
+}
+
 #ifndef CONFIG_PCI
 struct wait_queue * keypress_wait = NULL;
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- v2.1.100/linux/drivers/sbus/char/sunserial.c	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/char/sunserial.c	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.56 1997/12/19 07:33:07 ecd Exp $
+/* $Id: sunserial.c,v 1.57 1998/04/13 07:27:02 davem Exp $
  * serial.c: Serial port driver infrastructure for the Sparc.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -77,11 +77,9 @@
 	printk(buffer);
 }
 
-__initfunc(long
-serial_console_init(long kmem_start, long kmem_end))
+__initfunc(void serial_console_init(void))
 {
 	sun_serial_finish_init();
-	return kmem_start;
 }
 
 void rs_change_mouse_baud(int baud)
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c
--- v2.1.100/linux/drivers/sbus/dvma.c	Sat Apr 25 18:13:11 1998
+++ linux/drivers/sbus/dvma.c	Fri May  8 00:23:41 1998
@@ -74,8 +74,8 @@
 }
 
 /* Probe this SBus DMA module(s) */
-__initfunc(unsigned long
-dvma_init(struct linux_sbus *sbus, unsigned long memory_start))
+__initfunc(void
+dvma_init(struct linux_sbus *sbus))
 {
 	struct linux_sbus_device *this_dev;
 	struct Linux_SBus_DMA *dma;
@@ -93,8 +93,7 @@
 			continue;
 
 		/* Found one... */
-		dma = (struct Linux_SBus_DMA *) memory_start;
-		memory_start += sizeof(struct Linux_SBus_DMA);
+		dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC);
 
 		dma->SBus_dev = this_dev;
 
@@ -127,22 +126,18 @@
 		init_one_dvma(dma, num_dma++);
 		
 	};  /* while(this_dev) */
-
-	return memory_start;
 }
 
 #ifdef CONFIG_SUN4
 
 #include <asm/sun4paddr.h>
 
-__initfunc(unsigned long
-sun4_dvma_init(unsigned long memory_start))
+__initfunc(void sun4_dvma_init(void))
 {
 	struct Linux_SBus_DMA *dma;
 	struct Linux_SBus_DMA *dchain;
 
-	dma = (struct Linux_SBus_DMA *) memory_start;
-	memory_start += sizeof(struct Linux_SBus_DMA);
+	dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC);
 
 	/* No SBUS */
 	dma->SBus_dev = 0x0;
@@ -158,7 +153,6 @@
 	dma->node = 0x0;
 
 	init_one_dvma(dma, 0);
-	return memory_start;
 }
 
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.1.100/linux/drivers/sbus/sbus.c	Thu Apr 23 20:21:34 1998
+++ linux/drivers/sbus/sbus.c	Fri May  8 00:23:41 1998
@@ -7,6 +7,7 @@
 #include <linux/malloc.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/malloc.h>
 
 #include <asm/system.h>
 #include <asm/sbus.h>
@@ -181,12 +182,10 @@
  * devices.
  */
 
-extern unsigned long sun_console_init(unsigned long);
-extern unsigned long iommu_init(int iommu_node, unsigned long memstart,
-				unsigned long memend, struct linux_sbus *sbus);
-extern unsigned long iounit_init(int sbi_node, int iounit_node, unsigned long memstart,
-				unsigned long memend, struct linux_sbus *sbus);
-unsigned long sun4_init(unsigned long memory_start, unsigned long memory_end);
+extern void sun_console_init(void);
+extern void iommu_init(int iommu_node, struct linux_sbus *sbus);
+extern void iounit_init(int sbi_node, int iounit_node, struct linux_sbus *sbus);
+void sun4_init(void);
 #ifdef CONFIG_SUN_OPENPROMIO
 extern int openprom_init(void);
 #endif
@@ -197,9 +196,8 @@
 extern int flash_init(void);
 #endif
 
-__initfunc(static unsigned long 
-sbus_do_child_siblings(unsigned long memory_start, int start_node,
-		       struct linux_sbus_device *child,
+__initfunc(static void
+sbus_do_child_siblings(int start_node, struct linux_sbus_device *child,
 		       struct linux_sbus *sbus))
 {
 	struct linux_sbus_device *this_dev = child;
@@ -208,8 +206,7 @@
 	/* Child already filled in, just need to traverse siblings. */
 	child->child = 0;
 	while((this_node = prom_getsibling(this_node)) != 0) {
-		this_dev->next = (struct linux_sbus_device *) memory_start;
-		memory_start += sizeof(struct linux_sbus_device);
+		this_dev->next = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC);
 		this_dev = this_dev->next;
 		this_dev->next = 0;
 
@@ -217,23 +214,19 @@
 		this_dev->my_bus = sbus;
 
 		if(prom_getchild(this_node)) {
-			this_dev->child = (struct linux_sbus_device *) memory_start;
-			memory_start += sizeof(struct linux_sbus_device);
+			this_dev->child = kmalloc(sizeof(struct linux_sbus_device),
+						  GFP_ATOMIC);
 			fill_sbus_device(prom_getchild(this_node), this_dev->child);
 			this_dev->child->my_bus = sbus;
-			memory_start = sbus_do_child_siblings(memory_start,
-							      prom_getchild(this_node),
-							      this_dev->child,
-							      sbus);
+			sbus_do_child_siblings(prom_getchild(this_node),
+					       this_dev->child, sbus);
 		} else {
 			this_dev->child = 0;
 		}
 	}
-	return memory_start;
 }
 
-__initfunc(unsigned long
-sbus_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void sbus_init(void))
 {
 	register int nd, this_sbus, sbus_devs, topnd, iommund;
 	unsigned int sbus_clock;
@@ -242,11 +235,9 @@
 	int num_sbus = 0;  /* How many did we find? */
 	
 #ifdef CONFIG_SUN4
-	return sun4_init(memory_start, memory_end);
+	return sun4_init();
 #endif
 
-	memory_start = ((memory_start + 7) & (~7));
-
 	topnd = prom_getchild(prom_root_node);
 	
 	/* Finding the first sbus is a special case... */
@@ -256,7 +247,7 @@
 		if(nd == 0) {
 #ifdef CONFIG_PCI
 			printk("SBUS: No SBUS's found.\n");
-			return sun_console_init(memory_start);
+			return sun_console_init();
 #else
 			prom_printf("YEEE, UltraSparc sbus not found\n");
 			prom_halt();
@@ -280,28 +271,21 @@
 	/* Ok, we've found the first one, allocate first SBus struct
 	 * and place in chain.
 	 */
-	sbus = SBus_chain = (struct linux_sbus *) memory_start;
-	memory_start += sizeof(struct linux_sbus);
+	sbus = SBus_chain = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC);
 	sbus->next = 0;
 	this_sbus=nd;
 
 	if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
-		memory_start = iommu_init(iommund,
-					  memory_start, memory_end,
-					  sbus);
+		iommu_init(iommund, sbus);
 
 	/* Loop until we find no more SBUS's */
 	while(this_sbus) {
 		/* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
 		if(sparc_cpu_model == sun4u)
-			memory_start = iommu_init(this_sbus,
-						  memory_start, memory_end,
-						  sbus);
+			iommu_init(this_sbus, sbus);
 #ifndef __sparc_v9__						  
 		else if (sparc_cpu_model == sun4d)
-			memory_start = iounit_init(this_sbus, iommund,
-						   memory_start, memory_end,
-						   sbus);
+			iounit_init(this_sbus, iommund, sbus);
 #endif						   
 		printk("sbus%d: ", num_sbus);
 		sbus_clock = prom_getint(this_sbus, "clock-frequency");
@@ -326,8 +310,7 @@
 
 		sbus_devs = prom_getchild(this_sbus);
 
-		sbus->devices = (struct linux_sbus_device *) memory_start;
-		memory_start += sizeof(struct linux_sbus_device);
+		sbus->devices = kmalloc(sizeof(struct linux_sbus_device), GFP_ATOMIC);
 
 		this_dev = sbus->devices;
 		this_dev->next = 0;
@@ -338,24 +321,21 @@
 		/* Should we traverse for children? */
 		if(prom_getchild(sbus_devs)) {
 			/* Allocate device node */
-			this_dev->child = (struct linux_sbus_device *) memory_start;
-			memory_start += sizeof(struct linux_sbus_device);
+			this_dev->child = kmalloc(sizeof(struct linux_sbus_device),
+						  GFP_ATOMIC);
 			/* Fill it */
-
 			fill_sbus_device(prom_getchild(sbus_devs), this_dev->child);
 			this_dev->child->my_bus = sbus;
-			memory_start = sbus_do_child_siblings(memory_start,
-							      prom_getchild(sbus_devs),
-							      this_dev->child,
-							      sbus);
+			sbus_do_child_siblings(prom_getchild(sbus_devs),
+					       this_dev->child, sbus);
 		} else {
 			this_dev->child = 0;
 		}
 
 		while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
 			/* Allocate device node */
-			this_dev->next = (struct linux_sbus_device *) memory_start;
-			memory_start += sizeof(struct linux_sbus_device);
+			this_dev->next = kmalloc(sizeof(struct linux_sbus_device),
+						 GFP_ATOMIC);
 			this_dev=this_dev->next;
 			this_dev->next=0;
 
@@ -367,24 +347,20 @@
 			if(prom_getchild(sbus_devs)) {
 				/* Get new device struct */
 				this_dev->child =
-					(struct linux_sbus_device *) memory_start;
-				memory_start += sizeof(struct linux_sbus_device);
-
+					kmalloc(sizeof(struct linux_sbus_device),
+						GFP_ATOMIC);
 				/* Fill it */
 				fill_sbus_device(prom_getchild(sbus_devs),
 						 this_dev->child);
 				this_dev->child->my_bus = sbus;
-				memory_start = sbus_do_child_siblings(
-						     memory_start,
-						     prom_getchild(sbus_devs),
-						     this_dev->child,
-						     sbus);
+				sbus_do_child_siblings(prom_getchild(sbus_devs),
+						     this_dev->child, sbus);
 			} else {
 				this_dev->child = 0;
 			}
 		}
 
-		memory_start = dvma_init(sbus, memory_start);
+		dvma_init(sbus);
 
 		num_sbus++;
 		if(sparc_cpu_model == sun4u) {
@@ -404,8 +380,7 @@
 			this_sbus = prom_searchsiblings(this_sbus, "sbus");
 		}
 		if(this_sbus) {
-			sbus->next = (struct linux_sbus *) memory_start;
-			memory_start += sizeof(struct linux_sbus);
+			sbus->next = kmalloc(sizeof(struct linux_sbus), GFP_ATOMIC);
 			sbus = sbus->next;
 			sbus->next = 0;
 		} else {
@@ -413,12 +388,11 @@
 		}
 	} /* while(this_sbus) */
 	if (sparc_cpu_model == sun4d) {
-		extern unsigned long sun4d_init_sbi_irq(unsigned long);
-		
-		memory_start = sun4d_init_sbi_irq(memory_start);
+		extern void sun4d_init_sbi_irq(void);
+		sun4d_init_sbi_irq();
 	}
 	
-	memory_start = sun_console_init(memory_start); /* whee... */
+	sun_console_init(); /* whee... */
 #ifdef CONFIG_SUN_OPENPROMIO
 	openprom_init();
 #endif
@@ -441,22 +415,15 @@
 		clock_probe();
 	}
 #endif
-	return memory_start;
 }
 
 #ifdef CONFIG_SUN4
 
-extern unsigned long sun4_dvma_init(unsigned long);
+extern void sun4_dvma_init(void);
 
-__initfunc(unsigned long
-sun4_init(unsigned long memory_start, unsigned long memory_end))
+__initfunc(void sun4_init(void))
 {
-	memory_start = ((memory_start + 7) & (~7));
-	
-	memory_start = sun_console_init(memory_start);
-	
-	memory_start = sun4_dvma_init(memory_start);
-	
-	return memory_start;
+	sun_console_init();
+	sun4_dvma_init();
 }
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.1.100/linux/drivers/scsi/Makefile	Tue Feb 17 13:12:47 1998
+++ linux/drivers/scsi/Makefile	Fri May  8 00:22:11 1998
@@ -163,6 +163,54 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_SGIWD93),y)
+L_OBJS += sgiwd93.o wd33c93.o
+else
+  ifeq ($(CONFIG_SCSI_SGIWD93),m)
+  M_OBJS += sgiwd93.o wd33c93.o
+  endif
+endif
+
+ifeq ($(CONFIG_CYBERSTORM_SCSI),y)
+L_OBJS += NCR53C9x.o cyberstorm.o
+else
+  ifeq ($(CONFIG_CYBERSTORM_SCSI),m)
+  M_OBJS += NCR53C9x.o cyberstorm.o
+  endif
+endif
+
+ifeq ($(CONFIG_CYBERSTORMII_SCSI),y)
+L_OBJS += NCR53C9x.o cyberstormII.o
+else
+  ifeq ($(CONFIG_CYBERSTORMII_SCSI),m)
+  M_OBJS += NCR53C9x.o cyberstormII.o
+  endif
+endif
+
+ifeq ($(CONFIG_BLZ2060_SCSI),y)
+L_OBJS += NCR53C9x.o blz2060.o
+else
+  ifeq ($(CONFIG_BLZ2060_SCSI),m)
+  M_OBJS += NCR53C9x.o blz2060.o
+  endif
+endif
+
+ifeq ($(CONFIG_BLZ1230_SCSI),y)
+L_OBJS += NCR53C9x.o blz1230.o
+else
+  ifeq ($(CONFIG_BLZ1230_SCSI),m)
+  M_OBJS += NCR53C9x.o blz1230.o
+  endif
+endif
+
+ifeq ($(CONFIG_FASTLANE_SCSI),y)
+L_OBJS += NCR53C9x.o fastlane.o
+else
+  ifeq ($(CONFIG_FASTLANE_SCSI),m)
+  M_OBJS += NCR53C9x.o fastlane.o
+  endif
+endif
+
 ifeq ($(CONFIG_ATARI_SCSI),y)
 L_OBJS += atari_scsi.o
 else
@@ -464,19 +512,26 @@
 
 include $(TOPDIR)/Rules.make
 
-53c8xx_d.h 53c8xx_u.h : 53c7,8xx.scr script_asm.pl
-	ln -sf 53c7,8xx.scr fake.c
-	$(CPP) -traditional -DCHIP=810 fake.c | grep -v '^#' | perl script_asm.pl 
+53c8xx_d.h: 53c7,8xx.scr script_asm.pl
+	ln -sf 53c7,8xx.scr fake8.c
+	$(CPP) -traditional -DCHIP=810 fake8.c | grep -v '^#' | perl script_asm.pl 
 	mv script.h 53c8xx_d.h
 	mv scriptu.h 53c8xx_u.h
-	rm fake.c
+	rm fake8.c
 
-53c7xx_d.h 53c7xx_u.h : 53c7xx.scr script_asm.pl
-	ln -sf 53c7xx.scr fake.c
-	$(CPP) -traditional -DCHIP=710 fake.c | grep -v '^#' | perl -s script_asm.pl -ncr7x0_family
+53c8xx_u.h: 53c8xx_d.h
+
+53c7xx_d.h: 53c7xx.scr script_asm.pl
+	ln -sf 53c7xx.scr fake7.c
+	$(CPP) -traditional -DCHIP=710 fake7.c | grep -v '^#' | perl -s script_asm.pl -ncr7x0_family
 	mv script.h 53c7xx_d.h
 	mv scriptu.h 53c7xx_u.h
-	rm fake.c
+	rm fake7.c
+
+53c7xx_u.h: 53c7xx_d.h
+
+53c7xx.o : 53c7xx_d.h 53c7xx.c
+	$(CC) $(CFLAGS) -c 53c7xx.c
 
 scsi_mod.o: $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \
 		scsicam.o scsi_proc.o scsi_error.o scsi_obsolete.o scsi_queue.o
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.1.100/linux/drivers/scsi/advansys.c	Thu Apr 23 20:21:35 1998
+++ linux/drivers/scsi/advansys.c	Fri May  8 17:46:24 1998
@@ -1,5 +1,5 @@
-/* $Id: advansys.c,v 1.49 1998/01/22 20:19:25 bobf Exp bobf $ */
-#define ASC_VERSION "3.1D"    /* AdvanSys Driver Version */
+/* $Id: advansys.c,v 1.50 1998/05/08 23:39:15 bobf Exp bobf $ */
+#define ASC_VERSION "3.1E"    /* AdvanSys Driver Version */
 
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
@@ -571,7 +571,7 @@
             be page aligned.
 
      3.1C (1/10/98):
-         1. Update latest BIOS version to 3.1E.
+         1. Update latest BIOS version checked for from the /proc file.
          2. Don't set microcode SDTR variable at initialization. Instead
             wait until device capabilities have been detected from an Inquiry
             command.
@@ -580,6 +580,18 @@
          1. Improve performance when the driver is compiled as module by
             allowing up to 64 scatter-gather elements instead of 8.
 
+     3.1E (5/1/98):
+         1. Set time delay in AscWaitTixISRDone() to 1000 ms.
+         2. Include SMP locking changes.
+         3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS
+            access functions.
+         4. Update board serial number printing.
+         5. Try allocating an IRQ both with and without the SA_INTERRUPT
+            flag set to allow IRQ sharing with drivers that do not set
+            the SA_INTERRUPT flag. Also display a more descriptive error
+            message if request_irq() fails.
+         5. Update to latest Asc and Adv Libraries.
+
   J. Known Problems or Issues
 
          1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around
@@ -598,7 +610,7 @@
      Erik Ratcliffe <erik@caldera.com> has done testing of the
      AdvanSys driver in the Caldera releases.
 
-     Rik van Riel <H.H.vanRiel@phys.uu.nl> provided a patch to
+     Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to
      AscWaitTixISRDone() which he found necessary to make the
      driver work with a SCSI-1 disk.
 
@@ -639,6 +651,7 @@
  * --- Linux Include Files 
  */
 
+#include <linux/config.h>
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
 #ifdef MODULE
 #include <linux/module.h>
@@ -670,13 +683,23 @@
 #endif /* version >= v1.3.0 */
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95)
 #include <asm/spinlock.h>
-#endif
+#endif /* version >= 2.1.95 */
 #include "scsi.h"
 #include "hosts.h"
 #include "sd.h"
 #include "advansys.h"
-
-#include <linux/bios32.h>
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,93)
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif /* CONFIG_PCI */
+#else /* version < v2.1.93 */
+/*
+ * For earlier than v2.1.93 the driver has its own PCI configuration.
+ * If PCI is not needed in a kernel before v2.1.93 this define can be
+ * turned-off to make the driver object smaller.
+ */
+#define ASC_CONFIG_PCI
+#endif /* version < v2.1.93 */
 
 /*
  * If Linux eventually defines a DID_UNDERRUN, the constant here can be
@@ -694,7 +717,7 @@
 #define ADVANSYS_ASSERT
 
 /* Enable driver tracing. */
-/*#define ADVANSYS_DEBUG*/
+/* #define ADVANSYS_DEBUG */
 
 /*
  * Because of no /proc to display them, statistics are disabled
@@ -724,7 +747,7 @@
 
 #define ASC_LIB_VERSION_MAJOR  1
 #define ASC_LIB_VERSION_MINOR  22
-#define ASC_LIB_SERIAL_NUMBER  111
+#define ASC_LIB_SERIAL_NUMBER  113
 
 typedef unsigned char uchar;
 
@@ -1489,7 +1512,7 @@
     ASC_SCSI_BIT_ID_TYPE can_tagged_qng;
     ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled;
     ASC_SCSI_BIT_ID_TYPE disc_enable;
-    uchar               res;
+    ASC_SCSI_BIT_ID_TYPE sdtr_enable;
     uchar               chip_scsi_id:4;
     uchar               isa_dma_speed:4;
     uchar               isa_dma_channel;
@@ -1952,8 +1975,6 @@
 STATIC ushort    AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *);
 STATIC ushort    AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *);
 STATIC ushort    AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc);
-STATIC void      AscInitPollIsrCallBack(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_QDONE_INFO *);
 STATIC int       AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *);
 STATIC uchar     AscMsgOutSDTR(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
 STATIC uchar     AscCalSDTRData(ASC_DVC_VAR asc_ptr_type *, uchar, uchar);
@@ -1996,31 +2017,6 @@
 STATIC uchar     _AscCopyLramScsiDoneQ(PortAddr, ushort,
                     ASC_QDONE_INFO *, ulong);
 STATIC int       AscIsrQDone(ASC_DVC_VAR asc_ptr_type *);
-STATIC int       AscScsiSetupCmdQ(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, uchar *, ulong);
-STATIC int       AscScsiInquiry(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, uchar *, int);
-STATIC int       AscScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *);
-STATIC int       AscScsiStartStopUnit(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, uchar);
-STATIC int       AscScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, uchar *);
-STATIC ulong     *swapfarbuf4(uchar *);
-STATIC int       PollQueueDone(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, int);
-STATIC int       PollScsiReadCapacity(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, ASC_CAP_INFO *);
-STATIC int       PollScsiInquiry(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, uchar *, int);
-STATIC int       PollScsiTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *);
-STATIC int       PollScsiStartUnit(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *);
-STATIC int       InitTestUnitReady(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *);
-STATIC int       AscPollQDone(ASC_DVC_VAR asc_ptr_type *,
-                    ASC_SCSI_REQ_Q *, int);
 STATIC int       AscCompareString(uchar *, uchar *, int);
 STATIC ushort    AscGetEisaChipCfg(PortAddr);
 STATIC ulong     AscGetEisaProductID(PortAddr);
@@ -2056,10 +2052,11 @@
 STATIC ushort    AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *);
 STATIC ushort    AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *);
 STATIC ushort    AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *);
-STATIC int       AscInitPollBegin(ASC_DVC_VAR asc_ptr_type *);
-STATIC int       AscInitPollEnd(ASC_DVC_VAR asc_ptr_type *);
-STATIC int       AscInitPollTarget(ASC_DVC_VAR asc_ptr_type *,
-                     ASC_SCSI_REQ_Q *, ASC_SCSI_INQUIRY *, ASC_CAP_INFO *);
+STATIC void      AscAsyncFix(ASC_DVC_VAR asc_ptr_type *, uchar,
+                    ASC_SCSI_INQUIRY *);
+STATIC int       AscTagQueuingSafe(ASC_SCSI_INQUIRY *);
+STATIC void      AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *,
+                    uchar, ASC_SCSI_INQUIRY *);
 STATIC int       AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *);
 STATIC int       AscISR(ASC_DVC_VAR asc_ptr_type *);
 STATIC uint      AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar,
@@ -2079,7 +2076,7 @@
  */
 
 #define ADV_LIB_VERSION_MAJOR  3
-#define ADV_LIB_VERSION_MINOR  34
+#define ADV_LIB_VERSION_MINOR  45
 
 /* d_os_dep.h */
 #define ADV_OS_LINUX
@@ -3150,10 +3147,6 @@
 #define ADV_IS_DATA_FLAG        0x08 /* 'addr' is data virtual pointer */
 #define ADV_IS_SGLIST_FLAG      0x10 /* 'addr' is sglist virtual pointer */
 
-/* 'IS_SCSIQ_FLAG is now obsolete; Instead use ADV_IS_SCSIQ_FLAG. */
-#define IS_SCSIQ_FLAG           ADV_IS_SCSIQ_FLAQ
-
-
 /* Return the address that is aligned at the next doubleword >= to 'addr'. */
 #define ADV_DWALIGN(addr)       (((ulong) (addr) + 0x3) & ~0x3)
 
@@ -3360,6 +3353,7 @@
 #define PCI_MAX_BUS             0xFF
 #define PCI_IOADDRESS_MASK      0xFFFE
 #define ASC_PCI_VENDORID        0x10CD
+#define ASC_PCI_DEVICE_ID_CNT   4       /* PCI Device ID count. */
 #define ASC_PCI_DEVICE_ID_1100  0x1100
 #define ASC_PCI_DEVICE_ID_1200  0x1200
 #define ASC_PCI_DEVICE_ID_1300  0x1300
@@ -3797,7 +3791,11 @@
     ASC_IS_PCI,
 };
 
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
 STATIC int pci_scan_method ASC_INITDATA = -1;
+#endif /* ASC_CONFIG_PCI */
+#endif /* version < v2.1.93 */
 
 /*
  * Used with the LILO 'advansys' option to eliminate or
@@ -3844,11 +3842,8 @@
 #endif /* version >= v1.3.0 */
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
 STATIC void         advansys_interrupt(int, struct pt_regs *);
-#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
-STATIC void         advansys_interrupt(int, void *, struct pt_regs *);
-#else /* version >= 2.1.95 */
+#else /* version >= v1.3.70 */
 STATIC void         advansys_interrupt(int, void *, struct pt_regs *);
-STATIC void         do_advansys_interrupt(int, void *, struct pt_regs *);
 #endif /* version >= v1.3.70 */
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
 STATIC void         advansys_select_queue_depths(struct Scsi_Host *,
@@ -3862,7 +3857,8 @@
 STATIC int        adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *);
 STATIC void       asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *);
 STATIC void       adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *);
-STATIC int        asc_init_dev(ASC_DVC_VAR *, Scsi_Cmnd *);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
 STATIC int        asc_srch_pci_dev(PCI_DEVICE *);
 STATIC uchar      asc_scan_method(void);
 STATIC int        asc_pci_find_dev(PCI_DEVICE *);
@@ -3870,6 +3866,8 @@
 STATIC ushort     asc_get_cfg_word(PCI_DATA *);
 STATIC uchar      asc_get_cfg_byte(PCI_DATA *);
 STATIC void       asc_put_cfg_byte(PCI_DATA *, uchar);
+#endif /* ASC_CONFIG_PCI */
+#endif /* version < v2.1.93 */
 STATIC void       asc_enqueue(asc_queue_t *, REQP, int);
 STATIC REQP       asc_dequeue(asc_queue_t *, int);
 STATIC REQP       asc_dequeue_list(asc_queue_t *, REQP *, int);
@@ -4180,8 +4178,27 @@
     ADV_DVC_VAR         *adv_dvc_varp = NULL;
     int                 ioport = 0;
     int                 share_irq = FALSE;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
     PCI_DEVICE          pciDevice;
     PCI_CONFIG_SPACE    pciConfig;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
+    unsigned long       pci_memory_address;
+#endif /* version >= v1,3,0 */
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+    struct pci_dev      *pci_devp = NULL;
+    int                 pci_device_id_cnt = 0;
+    unsigned int        pci_device_id[ASC_PCI_DEVICE_ID_CNT] = {
+                                    ASC_PCI_DEVICE_ID_1100,
+                                    ASC_PCI_DEVICE_ID_1200,
+                                    ASC_PCI_DEVICE_ID_1300,
+                                    ASC_PCI_DEVICE_ID_2300
+                        };
+    unsigned long       pci_memory_address;
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
     int                 warn_code, err_code;
     int                 ret;
 
@@ -4225,10 +4242,14 @@
         ioport = 0;
     }
 
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
     memset(&pciDevice, 0, sizeof(PCI_DEVICE));
     memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE));
     pciDevice.maxBusNumber = PCI_MAX_BUS;
     pciDevice.endSlot = PCI_MAX_SLOT;
+#endif /* ASC_CONFIG_PCI */
+#endif /* version < v2.1.93 */ 
 
     for (bus = 0; bus < ASC_NUM_BUS; bus++) {
 
@@ -4309,22 +4330,52 @@
                 iop = AscSearchIOPortAddr(iop, asc_bus[bus]);
                 break;
 
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
+            case ASC_IS_PCI:
+                if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
+                    iop = 0;
+                } else {
+                    ASC_DBG2(2,
+                        "advansys_detect: slotFound %d, busNumber %d\n",
+                        pciDevice.slotFound, pciDevice.busNumber);
+                    asc_get_pci_cfg(&pciDevice, &pciConfig);
+                    iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
+                    ASC_DBG2(1,
+                        "advansys_detect: vendorID %X, deviceID %X\n",
+                        pciConfig.vendorID, pciConfig.deviceID);
+                    ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
+                        iop, pciConfig.irqLine);
+                }
+                break;
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
             case ASC_IS_PCI:
-                    if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) {
-                        iop = 0;
+                while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) {
+                    if ((pci_devp = pci_find_device(ASC_PCI_VENDORID,
+                         pci_device_id[pci_device_id_cnt], pci_devp)) == NULL) {
+                        pci_device_id_cnt++;
                     } else {
-                        ASC_DBG2(2,
-                            "advansys_detect: slotFound %d, busNumber %d\n",
-                            pciDevice.slotFound, pciDevice.busNumber);
-                        asc_get_pci_cfg(&pciDevice, &pciConfig);
-                        iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK;
-                        ASC_DBG2(1,
-                            "advansys_detect: vendorID %X, deviceID %X\n",
-                            pciConfig.vendorID, pciConfig.deviceID);
-                        ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
-                            iop, pciConfig.irqLine);
+                        break;
                     }
+                }
+                if (pci_devp == NULL) {
+                    iop = 0;
+                } else {
+                    ASC_DBG2(2,
+                        "advansys_detect: devfn %d, bus number %d\n",
+                        pci_devp->devfn, pci_devp->bus->number);
+                    iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK;
+                    ASC_DBG2(1,
+                        "advansys_detect: vendorID %X, deviceID %X\n",
+                        pci_devp->vendor, pci_devp->device);
+                    ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n",
+                        iop, pci_devp->irq);
+                }
                 break;
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
 
             default:
                 ASC_PRINT1("advansys_detect: unknown bus type: %d\n",
@@ -4358,14 +4409,29 @@
             boardp->id = asc_board_count - 1;
 
             /*
-             * Handle both narrow and wide PCI boards.
+             * Handle both narrow and wide boards.
              *
              * If a Wide board was detected, set the board structure
              * wide board flag. Set-up the board structure based on
              * the board type.
              */
-            if ((asc_bus[bus] == ASC_IS_PCI &&
-                 pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) == 0) {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
+            if (asc_bus[bus] == ASC_IS_PCI &&
+                 pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) {
+                boardp->flags |= ASC_IS_WIDE_BOARD;
+            }
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+            if (asc_bus[bus] == ASC_IS_PCI &&
+                 pci_devp->device == ASC_PCI_DEVICE_ID_2300) {
+                boardp->flags |= ASC_IS_WIDE_BOARD;
+            }
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
+
+            if (ASC_NARROW_BOARD(boardp)) {
                 ASC_DBG(1, "advansys_detect: narrow board\n");
                 asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
                 asc_dvc_varp->bus_type = asc_bus[bus];
@@ -4376,7 +4442,6 @@
                 asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback;
             } else {
                 ASC_DBG(1, "advansys_detect: wide board\n");
-                boardp->flags |= ASC_IS_WIDE_BOARD;
                 adv_dvc_varp = &boardp->dvc_var.adv_dvc_var;
                 adv_dvc_varp->drv_ptr = (ulong) boardp;
                 adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg;
@@ -4396,20 +4461,41 @@
                  * PCI register base address will not cross a page
                  * boundary.
                  */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
+                pci_memory_address = pciConfig.baseAddress[1];
                 if ((boardp->ioremap_addr =
-                    ioremap(pciConfig.baseAddress[1] & PAGE_MASK,
+                    ioremap(pci_memory_address & PAGE_MASK,
                          PAGE_SIZE)) == 0) {
                    ASC_PRINT3(
 "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
-                   boardp->id, pciConfig.baseAddress[1], ADV_CONDOR_IOLEN);
+                   boardp->id, pci_memory_address, ADV_CONDOR_IOLEN);
                    scsi_unregister(shp);
                    asc_board_count--;
                    continue;
                 }
                 adv_dvc_varp->iop_base = (AdvPortAddr)
                     (boardp->ioremap_addr +
-                     (pciConfig.baseAddress[1] -
-                      (pciConfig.baseAddress[1] & PAGE_MASK)));
+                     (pci_memory_address - (pci_memory_address & PAGE_MASK)));
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+                pci_memory_address = pci_devp->base_address[1];
+                if ((boardp->ioremap_addr =
+                    ioremap(pci_memory_address & PAGE_MASK,
+                         PAGE_SIZE)) == 0) {
+                   ASC_PRINT3(
+"advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n",
+                   boardp->id, pci_memory_address, ADV_CONDOR_IOLEN);
+                   scsi_unregister(shp);
+                   asc_board_count--;
+                   continue;
+                }
+                adv_dvc_varp->iop_base = (AdvPortAddr)
+                    (boardp->ioremap_addr +
+                     (pci_memory_address - (pci_memory_address & PAGE_MASK)));
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
 #endif /* version >= v1,3,0 */
 
                 /*
@@ -4455,16 +4541,33 @@
                     shp->unchecked_isa_dma = FALSE;
                     share_irq = TRUE;
                     break;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
                 case ASC_IS_PCI:
                     shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine;
-                    shp->unchecked_isa_dma = FALSE;
-                    share_irq = TRUE;
                     asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
                     asc_dvc_varp->cfg->pci_slot_info =
                         ASC_PCI_MKID(pciDevice.busNumber,
                             pciDevice.slotFound,
                             pciDevice.devFunc);
+                    shp->unchecked_isa_dma = FALSE;
+                    share_irq = TRUE;
                     break;
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+                case ASC_IS_PCI:
+                    shp->irq = asc_dvc_varp->irq_no = pci_devp->irq;
+                    asc_dvc_varp->cfg->pci_device_id = pci_devp->device;
+                    asc_dvc_varp->cfg->pci_slot_info =
+                        ASC_PCI_MKID(pci_devp->bus->number,
+                            PCI_SLOT(pci_devp->devfn),
+                            PCI_FUNC(pci_devp->devfn));
+                    shp->unchecked_isa_dma = FALSE;
+                    share_irq = TRUE;
+                    break;
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
                 default:
                     ASC_PRINT2(
 "advansys_detect: board %d: unknown adapter type: %d\n",
@@ -4478,14 +4581,29 @@
                  * For Wide boards set PCI information before calling
                  * AdvInitGetConfig().
                  */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
                 shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine;
+                adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
+                adv_dvc_varp->cfg->pci_slot_info =
+                ASC_PCI_MKID(pciDevice.busNumber,
+                    pciDevice.slotFound,
+                    pciDevice.devFunc);
                 shp->unchecked_isa_dma = FALSE;
                 share_irq = TRUE;
-                adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID;
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+                shp->irq = adv_dvc_varp->irq_no = pci_devp->irq;
+                adv_dvc_varp->cfg->pci_device_id = pci_devp->device;
                 adv_dvc_varp->cfg->pci_slot_info =
-                    ASC_PCI_MKID(pciDevice.busNumber,
-                        pciDevice.slotFound,
-                        pciDevice.devFunc);
+                ASC_PCI_MKID(pci_devp->bus->number,
+                    PCI_SLOT(pci_devp->devfn),
+                    PCI_FUNC(pci_devp->devfn));
+                shp->unchecked_isa_dma = FALSE;
+                share_irq = TRUE;
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
             }
 
             /*
@@ -4580,7 +4698,7 @@
                  */
                 ep = &boardp->eep_config.asc_eep;
 
-                ep->init_sdtr = asc_dvc_varp->init_sdtr;
+                ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable;
                 ep->disc_enable = asc_dvc_varp->cfg->disc_enable;
                 ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled;
                 ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed;
@@ -4886,19 +5004,37 @@
 #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70)
             if ((ret = request_irq(shp->irq, advansys_interrupt,
                             SA_INTERRUPT, "advansys")) != 0)
-#elif LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
-            if ((ret = request_irq(shp->irq, advansys_interrupt,
-                            SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
-                            "advansys", boardp)) != 0)
-#else /* version >= 2.1.95 */
-            if ((ret = request_irq(shp->irq, do_advansys_interrupt,
+#else /* version >= v1.3.70 */
+           /*
+            * If request_irq() fails with the SA_INTERRUPT flag set,
+            * then try again without the SA_INTERRUPT flag set. This
+            * allows IRQ sharing to work even with other drivers that
+            * do not set the SA_INTERRUPT flag.
+            *
+            * If SA_INTERRUPT is not set, then interrupts are enabled
+            * before the driver interrupt function is called.
+            */
+            if (((ret = request_irq(shp->irq, advansys_interrupt,
                             SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
-                            "advansys", boardp)) != 0)
+                            "advansys", boardp)) != 0) &&
+                ((ret = request_irq(shp->irq, advansys_interrupt,
+                            (share_irq == TRUE ? SA_SHIRQ : 0),
+                            "advansys", boardp)) != 0))
 #endif /* version >= v1.3.70 */
             {
-                ASC_PRINT2(
-"advansys_detect: board %d: request_irq() failed %d\n",
-                    boardp->id, ret);
+                if (ret == -EBUSY) {
+                    ASC_PRINT2(
+"advansys_detect: board %d: request_irq(): IRQ %d already in use.\n",
+                        boardp->id, shp->irq);
+                } else if (ret == -EINVAL) {
+                    ASC_PRINT2(
+"advansys_detect: board %d: request_irq(): IRQ %d not valid.\n",
+                        boardp->id, shp->irq);
+                } else {
+                    ASC_PRINT3(
+"advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n",
+                        boardp->id, shp->irq, ret);
+                }
                 release_region(shp->io_port, shp->n_io_port);
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
                 iounmap(boardp->ioremap_addr);
@@ -5152,7 +5288,11 @@
                 busname = "ISA";
             }
             sprintf(info,
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u",
+#else /* version >= v2.1.92 */ 
+"AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u",
+#endif /* version >= v2.1.92 */ 
                 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
                 (unsigned) shp->base,
                 shp->io_port, shp->n_io_port - 1,
@@ -5165,7 +5305,11 @@
                 busname = "PCI";
             }
             sprintf(info,
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
                 "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u",
+#else /* version >= v2.1.92 */ 
+                "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u",
+#endif /* version >= v2.1.92 */ 
                 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
                 shp->io_port, shp->n_io_port - 1, shp->irq);
         } else {
@@ -5180,7 +5324,11 @@
                     boardp->id, asc_dvc_varp->bus_type);
             }
             sprintf(info,
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92)
                 "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u",
+#else /* version >= v2.1.92 */ 
+                "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u",
+#endif /* version >= v2.1.92 */ 
                 ASC_VERSION, busname, asc_dvc_varp->max_total_qng,
                 (unsigned) shp->base, shp->io_port - 1,
                 shp->n_io_port, shp->irq);
@@ -5730,13 +5878,6 @@
                 status = AscResetDevice(asc_dvc_varp, scp->target);
                 cli();
 
-                /*
-                 * If the device has been reset, try to initialize it.
-                 */
-                if (status == ASC_TRUE) {
-                    status = asc_init_dev(asc_dvc_varp, scp);
-                }
-
                 switch (status) {
                 case ASC_TRUE:
                     ASC_DBG(1, "advansys_reset: AscResetDevice() success\n");
@@ -5957,7 +6098,7 @@
         asc_scsi_done_list(done_scp);
     }
 
-    ASC_DBG1(1, "advansys_reset: ret %d", ret);
+    ASC_DBG1(1, "advansys_reset: ret %d\n", ret);
 
     /* Re-enable interrupts, if they were enabled on entry. */
     restore_flags(flags);
@@ -6121,15 +6262,27 @@
 advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #endif /* version >= v1.3.70 */
 {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
     int             flags;
+#else /* version >= v2.1.95 */
+    unsigned long   flags;
+#endif /* version >= v2.1.95 */
     int             i;
     asc_board_t     *boardp;
     Scsi_Cmnd       *done_scp = NULL, *last_scp = NULL;
     Scsi_Cmnd       *new_last_scp;
 
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
     /* Disable interrupts, if they aren't already disabled. */
     save_flags(flags);
     cli();
+#else /* version >= v2.1.95 */
+    /*
+     * Disable interrupts, if they aren't already disabled and acquire
+     * the I/O spinlock.
+     */
+    spin_lock_irqsave(&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
 
     ASC_DBG(1, "advansys_interrupt: begin\n");
 
@@ -6203,30 +6356,31 @@
 
     /*
      * It is possible for the request done function to re-enable
-     * interrupts without confusing the driver. But here interrupts
-     * aren't enabled until all requests have been completed.
+     * interrupts without confusing the driver. But here the
+     * original flags aren't restored until all requests have been
+     * completed.
      */
     asc_scsi_done_list(done_scp);
 
-    /* Re-enable interrupts, if they were enabled on entry. */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95)
+    /*
+     * Restore the original flags which will enable interrupts
+     * if and only if they were enabled on entry.
+     */
     restore_flags(flags);
+#else /* version >= v2.1.95 */
+    /*
+     * Release the I/O spinlock and restore the original flags
+     * which will enable interrupts if and only if they were
+     * enabled on entry.
+     */
+    spin_unlock_irqrestore(&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
 
     ASC_DBG(1, "advansys_interrupt: end\n");
     return;
 }
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95)
-static void
-do_advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-    unsigned long flags;
-
-    spin_lock_irqsave(&io_request_lock, flags);
-    advansys_interrupt(irq, dev_id, regs);
-    spin_unlock_irqrestore(&io_request_lock, flags);
-}
-#endif
-
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
 /*
  * Set the number of commands to queue per device for the
@@ -6366,21 +6520,6 @@
         asc_dvc_varp = &boardp->dvc_var.asc_dvc_var;
 
         /*
-         * Narrow Board - Asc Library requires special device initialization.
-         *
-         * If this is the first command, then initialize the device. If
-         * no device is found set 'DID_BAD_TARGET' and return.
-         */
-        if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0) {
-            if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) {
-                scp->result = HOST_BYTE(DID_BAD_TARGET);
-                asc_enqueue(&boardp->done, scp, ASC_BACK);
-                return ASC_ERROR;
-            }
-            boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
-        }
-
-        /*
          * Build Asc Library request structure using the
          * global structures 'asc_scsi_req' and 'asc_sg_head'.
          *
@@ -6925,7 +7064,7 @@
     asc_board_t         *boardp;
     Scsi_Cmnd           *scp;
     struct Scsi_Host    *shp;
-    int            underrun = ASC_FALSE;
+    int                 underrun = ASC_FALSE;
     int                 i;
 
     ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
@@ -6971,6 +7110,7 @@
      * Display a message and return.
      */
     boardp = ASC_BOARDP(shp);
+    ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var);
     if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
         ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n",
             boardp->id, (unsigned) scp);
@@ -6981,7 +7121,7 @@
      * Check for an underrun condition.
      */
     if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && 
-    qdonep->remain_bytes <= scp->request_bufflen != 0) {
+        qdonep->remain_bytes <= scp->request_bufflen != 0) {
         ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n",
         (unsigned) qdonep->remain_bytes);
         underrun = ASC_TRUE;
@@ -7002,13 +7142,28 @@
             scp->result = HOST_BYTE(DID_ERROR);
             break;
         }
-    /*
-     * If there was an underrun without any other error,
-     * set DID_ERROR to indicate the underrun error.
-     */
-    if (scp->result == 0 && underrun == ASC_TRUE) {
+
+        /*
+         * If an INQUIRY command completed successfully, then call
+         * the AscInquiryHandling() function to set-up the device.
+         */
+        if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 &&
+            (scp->request_bufflen - qdonep->remain_bytes) >= 8)
+        {
+            AscInquiryHandling(asc_dvc_varp, scp->target & 0x7,
+                (ASC_SCSI_INQUIRY *) scp->request_buffer);
+        }
+
+        /*
+         * If there was an underrun without any other error,
+         * set DID_ERROR to indicate the underrun error.
+         *
+         * Note: There is no way yet to indicate the number
+         * of underrun bytes.
+         */
+        if (scp->result == 0 && underrun == ASC_TRUE) {
             scp->result = HOST_BYTE(DID_UNDERRUN);
-    }
+        }
         break;
 
     case QD_WITH_ERROR:
@@ -7038,10 +7193,9 @@
 
         default:
             /* QHSTA error occurred */
-            ASC_DBG1(2, "asc_isr_callback: host_stat %x\n",
+            ASC_DBG1(1, "asc_isr_callback: host_stat %x\n",
                 qdonep->d3.host_stat);
-            scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
-                STATUS_BYTE(qdonep->d3.scsi_stat);
+            scp->result = HOST_BYTE(DID_BAD_TARGET);
             break;
         }
         break;
@@ -7053,12 +7207,23 @@
         break;
 
     default:
-        ASC_PRINT1("asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
+        ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat);
         scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) |
                 STATUS_BYTE(qdonep->d3.scsi_stat);
         break;
     }
 
+    /*
+     * If the 'init_tidmask' bit isn't already set for the target and the
+     * current request finished normally, then set the bit for the target
+     * to indicate that a device is present.
+     */
+    if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
+        qdonep->d3.done_stat == QD_NO_ERROR &&
+        qdonep->d3.host_stat == QHSTA_NO_ERROR) {
+        boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target);
+    }
+
     /* 
      * Because interrupts may be enabled by the 'Scsi_Cmnd' done
      * function, add the command to the end of the board's done queue.
@@ -7082,7 +7247,7 @@
     adv_req_t           *reqp;
     Scsi_Cmnd           *scp;
     struct Scsi_Host    *shp;
-    int            underrun = ASC_FALSE;
+    int                 underrun = ASC_FALSE;
     int                 i;
 
     ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
@@ -7150,6 +7315,7 @@
      * to free the adv_req_t and adv_sgblk_t, if any, structures.
      */
     boardp = ASC_BOARDP(shp);
+    ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var);
     if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) {
         ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n",
             boardp->id, (unsigned) scp);
@@ -7182,13 +7348,16 @@
             scp->result = HOST_BYTE(DID_ERROR);
             break;
         }
-    /*
-     * If there was an underrun without any other error,
-     * set DID_ERROR to indicate the underrun error.
-     */
-    if (scp->result == 0 && underrun == ASC_TRUE) {
-            scp->result = HOST_BYTE(DID_UNDERRUN);
-    }
+        /*
+         * If there was an underrun without any other error,
+         * set DID_ERROR to indicate the underrun error.
+         *
+         * Note: There is no way yet to indicate the number
+         * of underrun bytes.
+         */
+        if (scp->result == 0 && underrun == ASC_TRUE) {
+                scp->result = HOST_BYTE(DID_UNDERRUN);
+        }
         break;
 
     case QD_WITH_ERROR:
@@ -7218,7 +7387,7 @@
 
         default:
             /* Some other QHSTA error occurred. */
-            ASC_DBG1(2, "adv_isr_callback: host_status %x\n",
+            ASC_DBG1(1, "adv_isr_callback: host_status %x\n",
                 scsiqp->host_status);
             scp->result = HOST_BYTE(DID_BAD_TARGET);
             break;
@@ -7231,15 +7400,15 @@
         break;
 
     default:
-        ASC_PRINT1("adv_isr_callback: done_status %x\n", scsiqp->done_status);
+        ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status);
         scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status);
         break;
     }
 
     /*
      * If the 'init_tidmask' bit isn't already set for the target and the
-     * current request did not finish with a Selection Timeout, then set
-     * the bit for the target to indicate that a device is present.
+     * current request finished normally, then set the bit for the target
+     * to indicate that a device is present.
      */
     if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 &&
         scsiqp->done_status == QD_NO_ERROR &&
@@ -7276,119 +7445,8 @@
     return;
 }
 
-/*
- * asc_init_dev() - Narrow Board initialization function. 
- *
- * Perform one-time initialization of a device for Asc Library
- */
-STATIC int
-asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
-{
-    asc_board_t             *boardp;
-    ASC_SCSI_REQ_Q          *scsireqq;
-    ASC_CAP_INFO            *cap_info;
-    ASC_SCSI_INQUIRY        *inquiry;
-    int                     found;
-    ASC_SCSI_BIT_ID_TYPE    save_use_tagged_qng;
-    ASC_SCSI_BIT_ID_TYPE    save_can_tagged_qng;
-    int                     ret;
-#ifdef ADVANSYS_DEBUG
-    ASC_SCSI_BIT_ID_TYPE    tidmask; /* target id bit mask: 1 - 128 */
-#endif /* ADVANSYS_DEBUG */
-
-    ASC_DBG1(1, "asc_init_dev: target %d\n", (unsigned) scp->target);
-
-    /* The host's target id is set in init_tidmask during initialization. */
-    ASC_ASSERT(asc_dvc_varp->cfg->chip_scsi_id != scp->target);
-
-    boardp = ASC_BOARDP(scp->host);
-
-    /* Set-up AscInitPollTarget() arguments. */
-    scsireqq = &boardp->scsireqq;
-    memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
-    cap_info = &boardp->cap_info;
-    memset(cap_info, 0, sizeof(ASC_CAP_INFO));
-    inquiry = &boardp->inquiry;
-    memset(inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
-
-    /*
-     * AscInitPollBegin() re-initializes these bitmask fields to zero.
-     * Save the current bitmask value and 'or' them back in after calling
-     * AscInitPollEnd() below..
-     */
-    save_use_tagged_qng = asc_dvc_varp->use_tagged_qng;
-    save_can_tagged_qng = asc_dvc_varp->cfg->can_tagged_qng;
-
-    ASC_DBG(2, "asc_init_dev: AscInitPollBegin()\n");
-    if (AscInitPollBegin(asc_dvc_varp)) {
-        ASC_PRINT1("asc_init_dev: board %d: AscInitPollBegin() failed\n",
-            boardp->id);
-        return ASC_FALSE;
-    }
-
-    scsireqq->sense_ptr = &scsireqq->sense[0];
-    scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
-    scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
-    scsireqq->r1.target_lun = 0;
-    scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
-
-    found = ASC_FALSE;
-    ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
-    switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry,
-        cap_info)) {
-    case ASC_TRUE:
-        found = ASC_TRUE;
-#ifdef ADVANSYS_DEBUG
-        tidmask = ADV_TID_TO_TIDMASK(scp->target);
-        ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
-            cap_info->lba, cap_info->blk_size);
-        ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
-            inquiry->byte0.peri_dvc_type);
-        if (asc_dvc_varp->use_tagged_qng & tidmask) {
-            ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
-                asc_dvc_varp->max_dvc_qng[scp->target]);
-        } else {
-            ASC_DBG(1, "asc_init_dev: command queuing disabled\n");
-        }
-        if (asc_dvc_varp->init_sdtr & tidmask) {
-            ASC_DBG(1, "asc_init_dev: synchronous transfers enabled\n");
-        } else {
-            ASC_DBG(1, "asc_init_dev: synchronous transfers disabled\n");
-        }
-        /* Set bit means fix disabled. */
-        if (asc_dvc_varp->pci_fix_asyn_xfer & tidmask) {
-            ASC_DBG(1, "asc_init_dev: synchronous transfer fix disabled\n");
-        } else {
-            ASC_DBG(1, "asc_init_dev: synchronous transfer fix enabled\n");
-        }
-#endif /* ADVANSYS_DEBUG */
-        break;
-    case ASC_FALSE:
-        ASC_DBG(1, "asc_init_dev: no device found\n");
-        break;
-    case ASC_ERROR:
-        ASC_PRINT1("asc_init_dev: board %d: AscInitPollTarget() ASC_ERROR\n",
-                boardp->id);
-        break;
-    default:
-        ASC_PRINT2(
-"asc_init_dev: board %d: AscInitPollTarget() unknown ret %d\n",
-                boardp->id, ret);
-        break;
-    }
-
-    /* Restore previously set bits in the bitmask fields. */
-    asc_dvc_varp->use_tagged_qng |= save_use_tagged_qng;
-    asc_dvc_varp->cfg->can_tagged_qng |= save_can_tagged_qng;
-
-    ASC_DBG(2, "asc_init_dev: AscInitPollEnd()\n");
-    AscInitPollEnd(asc_dvc_varp);
-
-    ASC_DBG1(1, "asc_init_dev: found %d\n", found); 
-
-    return found;
-}
-
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
 /*
  * Search for an AdvanSys PCI device in the PCI configuration space.
  */
@@ -7397,7 +7455,7 @@
 asc_srch_pci_dev(PCI_DEVICE *pciDevice)
 )
 {
-    int ret;
+    int                        ret = PCI_DEVICE_NOT_FOUND;
 
     ASC_DBG(2, "asc_srch_pci_dev: begin\n");
 
@@ -7424,6 +7482,7 @@
             ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret);
         }
     }
+
     ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret);
     return ret;
 }
@@ -7524,7 +7583,7 @@
     uchar       counter;
     uchar       *localConfig;
 
-    ASC_DBG1(4, "asc_get_pci_cfg: slot found - %d\n ",
+    ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ",
         pciDevice->slotFound);
 
     pciData.type = pciDevice->type;
@@ -7636,8 +7695,74 @@
 )
 {
     uchar tmp;
+    ulong address;
+    ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func;
+    uchar t2CFA, t2CF8;
+    ulong t1CF8, t1CFC;
+
+    ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type);
 
-    pcibios_read_config_byte(pciData->bus, pciData->slot * 8 + pciData->func, pciData->offset, &tmp);
+    /*
+     * Check type of configuration mechanism.
+     */
+    if (pciData->type == 2) {
+        /*
+         * Save registers to be restored later.
+         */
+        t2CFA = inp(0xCFA);    /* save PCI bus register */
+        t2CF8 = inp(0xCF8);    /* save config space enable register */
+
+        /*
+         * Write the bus and enable registers.
+         */
+        /* set for type 1 cycle, if needed */
+        outp(0xCFA, pciData->bus);
+        /* set the function number */
+        outp(0xCF8, 0x10 | (pciData->func << 1));
+
+        /*
+         * Read configuration space type 2 locations.
+         */
+        tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset));
+
+        /*
+         * Restore registers.
+         */
+        outp(0xCF8, t2CF8);    /* restore the enable register */
+        outp(0xCFA, t2CFA);    /* restore PCI bus register */
+    } else {
+        /*
+         * Type 1 or 3 configuration mechanism.
+         *
+         * Save CONFIG_ADDRESS and CONFIG_DATA register values.
+         */
+        t1CF8 = inpl(0xCF8);
+        t1CFC = inpl(0xCFC);
+
+        /*
+         * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>,
+         * reg = <7:2>
+         */
+        address = (ulong) ((lbus << 16) | (lslot << 11) |
+            (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L);
+
+        /*
+         * Write out address to CONFIG_ADDRESS.
+         */
+        outpl(0xCF8, address);
+
+        /*
+         * Read in word from CONFIG_DATA.
+         */
+        tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF);
+
+        /*
+         * Restore registers.
+         */
+        outpl(0xCF8, t1CF8);
+        outpl(0xCFC, t1CFC);
+    }
+    ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp);
     return tmp;
 }
 
@@ -7725,6 +7850,8 @@
     }
     ASC_DBG(4, "asc_put_cfg_byte: end\n");
 }
+#endif /* ASC_CONFIG_PCI */
+#endif /* version < v2.1.93 */
 
 /*
  * Add a 'REQP' to the end of specified queue. Set 'tidmask'
@@ -8134,9 +8261,9 @@
             major, minor, letter >= 26 ? '?' : letter + 'A');
         ASC_PRT_NEXT();
 
-        /* Current available ROM BIOS release is 3.1E. */
+        /* Current available ROM BIOS release is 3.1C. */
         if (major < 3 || (major <= 3 && minor < 1) ||
-            (major <= 3 && minor <= 1 && letter < ('E'- 'A'))) {
+            (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) {
             upgrade = ASC_TRUE;
         }
     }
@@ -8153,18 +8280,18 @@
  * Add serial number to information bar if signature AAh
  * is found in at bit 15-9 (7 bits) of word 1.
  *
- * Serial Number consists 12 alpha-numeric digits.
+ * Serial Number consists fo 12 alpha-numeric digits.
  *
- *       1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits)
- *       2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits)
- *     3-4 - Product ID (0-99)        Word0: 10-0 (11 bits)
- *       5 - Product revision         Word0:  "         "
- *
- *         Signature                Word1: 15-9 (7 bits)
- *       6 - Year (4-9)               Word1: 8-6 (3 bits)
- *     7-8 - Week of the year         Word1: 5-0 (6 bits)
+ *       1 - Product type (A,B,C,D..)  Word0: 15-13 (3 bits)
+ *       2 - MFG Location (A,B,C,D..)  Word0: 12-10 (3 bits)
+ *     3-4 - Product ID (0-99)         Word0: 9-0 (10 bits)
+ *       5 - Product revision (A-J)    Word0:  "         "
+ *
+ *           Signature                 Word1: 15-9 (7 bits)
+ *       6 - Year (0-9)                Word1: 8-6 (3 bits) & Word2: 15 (1 bit)
+ *     7-8 - Week of the year (1-52)   Word1: 5-0 (6 bits)
  *
- *    9-12 - Serial Number            Word2: 15-0 (16 bits)
+ *    9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits)
  *
  * Note 1: Only production cards will have a serial number.
  *
@@ -8186,7 +8313,11 @@
         w = serialnum[0];
 
         /* Product type - 1st digit. */
-        *cp++ = 'A' + ((w & 0xE000) >> 13);
+        if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') {
+            /* Product type is P=Prototype */
+            *cp += 0x8;
+        }
+        cp++;
 
         /* Manufacturing location - 2nd digit. */
         *cp++ = 'A' + ((w & 0x1C00) >> 10);
@@ -8205,8 +8336,17 @@
          */
         w = serialnum[1];
 
-        /* Year - 6th digit. */
-        *cp++ = '0' + ((w & 0x1C0) >> 6);
+        /*
+         * Year - 6th digit.
+         *
+         * If bit 15 of third word is set, then the
+         * last digit of the year is greater than 7.
+         */
+        if (serialnum[2] & 0x8000) {
+            *cp++ = '8' + ((w & 0x1C0) >> 6);
+        } else {
+            *cp++ = '0' + ((w & 0x1C0) >> 6);
+        }
 
         /* Week of year - 7th, 8th digits. */
         num = w & 0x003F;
@@ -8217,7 +8357,7 @@
         /*
          * Third word
          */
-        w = serialnum[2];
+        w = serialnum[2] & 0x7FFF;
 
         /* Serial number - 9th digit. */
         *cp++ = 'A' + (w / 1000);
@@ -9233,6 +9373,8 @@
         ushort offset)
 )
 {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
     PCI_DATA    pciData;
 
     pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
@@ -9241,6 +9383,21 @@
     pciData.offset = offset;
     pciData.type = pci_scan_method;
     return asc_get_cfg_byte(&pciData);
+#else /* ASC_CONFIG_PCI */
+    return 0;
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+    uchar byte_data;
+    pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
+        PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
+            ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
+        offset, &byte_data);
+    return byte_data;
+#else /* CONFIG_PCI */
+    return 0;
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
 }
 
 /*
@@ -9254,6 +9411,8 @@
         uchar  byte_data)
 )
 {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
     PCI_DATA    pciData;
 
     pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
@@ -9262,6 +9421,15 @@
     pciData.offset = offset;
     pciData.type = pci_scan_method;
     asc_put_cfg_byte(&pciData, byte_data);
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+    pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
+        PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
+            ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
+        offset, byte_data);
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
 }
 
 /*
@@ -9358,6 +9526,8 @@
         ushort offset)
 )
 {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
     PCI_DATA    pciData;
 
     pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
@@ -9366,6 +9536,21 @@
     pciData.offset = offset;
     pciData.type = pci_scan_method;
     return asc_get_cfg_byte(&pciData);
+#else /* ASC_CONFIG_PCI */
+    return 0;
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+    uchar byte_data;
+    pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
+        PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
+            ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
+        offset, &byte_data);
+    return byte_data;
+#else /* CONFIG_PCI */
+    return 0;
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
 }
 
 /*
@@ -9379,6 +9564,8 @@
         uchar  byte_data)
 )
 {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93)
+#ifdef ASC_CONFIG_PCI
     PCI_DATA    pciData;
 
     pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info);
@@ -9387,6 +9574,15 @@
     pciData.offset = offset;
     pciData.type = pci_scan_method;
     asc_put_cfg_byte(&pciData, byte_data);
+#endif /* ASC_CONFIG_PCI */
+#else /* version >= v2.1.93 */ 
+#ifdef CONFIG_PCI
+    pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info),
+        PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info),
+            ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)),
+        offset, byte_data);
+#endif /* CONFIG_PCI */
+#endif /* version >= v2.1.93 */ 
 }
 
 /*
@@ -9703,8 +9899,9 @@
     printk("ASC_DVC_CFG at addr %x\n", (unsigned) h);
 
     printk(
-" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, res %x,\n",
-            h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, h->res);
+" can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n",
+            h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable,
+            h->sdtr_enable);
 
     printk(
 " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n",
@@ -10889,200 +11086,156 @@
     return (int_pending);
 }
 
-STATIC int
-AscScsiSetupCmdQ(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                    REG ASC_SCSI_REQ_Q * scsiq,
-                    uchar * buf_addr,
-                    ulong buf_len
-)
-{
-    ulong               phy_addr;
-
-    scsiq->r1.cntl = 0;
-    scsiq->r1.sg_queue_cnt = 0;
-    scsiq->r1.q_no = 0;
-    scsiq->r1.extra_bytes = 0;
-    scsiq->r3.scsi_stat = 0;
-    scsiq->r3.scsi_msg = 0;
-    scsiq->r3.host_stat = 0;
-    scsiq->r3.done_stat = 0;
-    scsiq->r2.vm_id = 0;
-    scsiq->r1.data_cnt = buf_len;
-    scsiq->cdbptr = (uchar *) scsiq->cdb;
-    scsiq->sense_ptr = (uchar *) scsiq->sense ;
-    scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ;
-    scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
-    scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
-    scsiq->r2.srb_ptr = (ulong) scsiq;
-    scsiq->r1.status = (uchar) QS_READY;
-    scsiq->r1.data_addr = 0L;
-    if (buf_len != 0L) {
-        if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
-                    (uchar *) buf_addr, scsiq->r1.data_cnt)) == 0L) {
-            return (ERR);
-        }
-        scsiq->r1.data_addr = phy_addr;
-    }
-    if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
-                       (uchar *) scsiq->sense_ptr,
-                       (ulong) scsiq->r1.sense_len)) == 0L) {
-        return (ERR);
-    }
-    scsiq->r1.sense_addr = phy_addr ;
-    return (0);
-}
-
 STATIC uchar _asc_mcode_buf[] ASC_INITDATA =
 {
   0x01,  0x03,  0x01,  0x19,  0x0F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
-  0x00,  0x00,  0x00,  0x00,  0xDB,  0x0C,  0x0A,  0x05,  0x01,  0x00,  0x00,  0x00,  0x00,  0xFF,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x91,  0x10,  0x0A,  0x05,  0x01,  0x00,  0x00,  0x00,  0x00,  0xFF,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0xFF,  0x80,  0xFF,  0xFF,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
-  0x00,  0x00,  0x00,  0x23,  0x00,  0x23,  0x00,  0x00,  0x00,  0x07,  0x00,  0xFF,  0x00,  0x00,  0x00,  0x00,
-  0xFF,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xD4,  0x88,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x23,  0x00,  0x24,  0x00,  0x00,  0x00,  0x07,  0x00,  0xFF,  0x00,  0x00,  0x00,  0x00,
+  0xFF,  0xFF,  0xFF,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0xE2,  0x88,  0x00,  0x00,  0x00,  0x00,
   0x80,  0x73,  0x48,  0x04,  0x36,  0x00,  0x00,  0xA2,  0xC2,  0x00,  0x80,  0x73,  0x03,  0x23,  0x36,  0x40,
   0xB6,  0x00,  0x36,  0x00,  0x05,  0xD6,  0x0C,  0xD2,  0x12,  0xDA,  0x00,  0xA2,  0xC2,  0x00,  0x92,  0x80,
-  0x10,  0x98,  0x50,  0x00,  0xF5,  0x00,  0x3A,  0x98,  0xDF,  0x23,  0x36,  0x60,  0xB6,  0x00,  0x92,  0x80,
-  0x4F,  0x00,  0xF5,  0x00,  0x3A,  0x98,  0xEF,  0x23,  0x36,  0x60,  0xB6,  0x00,  0x92,  0x80,  0x80,  0x62,
+  0x1E,  0x98,  0x50,  0x00,  0xF5,  0x00,  0x48,  0x98,  0xDF,  0x23,  0x36,  0x60,  0xB6,  0x00,  0x92,  0x80,
+  0x4F,  0x00,  0xF5,  0x00,  0x48,  0x98,  0xEF,  0x23,  0x36,  0x60,  0xB6,  0x00,  0x92,  0x80,  0x80,  0x62,
   0x92,  0x80,  0x00,  0x46,  0x17,  0xEE,  0x13,  0xEA,  0x02,  0x01,  0x09,  0xD8,  0xCD,  0x04,  0x4D,  0x00,
-  0x00,  0xA3,  0xD6,  0x00,  0x98,  0x97,  0x7F,  0x23,  0x04,  0x61,  0x84,  0x01,  0xE0,  0x84,  0xD2,  0xC1,
-  0x80,  0x73,  0xCD,  0x04,  0x4D,  0x00,  0x00,  0xA3,  0xE2,  0x01,  0x98,  0x97,  0xCE,  0x81,  0x00,  0x33,
-  0x02,  0x00,  0xB2,  0x88,  0x80,  0x73,  0x80,  0x77,  0x00,  0x01,  0x01,  0xA1,  0x02,  0x01,  0x4F,  0x00,
-  0x76,  0x97,  0x07,  0xA6,  0x0C,  0x01,  0x00,  0x33,  0x03,  0x00,  0xB2,  0x88,  0x03,  0x03,  0x03,  0xDE,
-  0x00,  0x33,  0x05,  0x00,  0xB2,  0x88,  0xCE,  0x00,  0x69,  0x60,  0xCE,  0x00,  0x02,  0x03,  0x4A,  0x60,
+  0x00,  0xA3,  0xD6,  0x00,  0xA6,  0x97,  0x7F,  0x23,  0x04,  0x61,  0x84,  0x01,  0xE6,  0x84,  0xD2,  0xC1,
+  0x80,  0x73,  0xCD,  0x04,  0x4D,  0x00,  0x00,  0xA3,  0xE2,  0x01,  0xA6,  0x97,  0xCE,  0x81,  0x00,  0x33,
+  0x02,  0x00,  0xC0,  0x88,  0x80,  0x73,  0x80,  0x77,  0x00,  0x01,  0x01,  0xA1,  0x02,  0x01,  0x4F,  0x00,
+  0x84,  0x97,  0x07,  0xA6,  0x0C,  0x01,  0x00,  0x33,  0x03,  0x00,  0xC0,  0x88,  0x03,  0x03,  0x03,  0xDE,
+  0x00,  0x33,  0x05,  0x00,  0xC0,  0x88,  0xCE,  0x00,  0x69,  0x60,  0xCE,  0x00,  0x02,  0x03,  0x4A,  0x60,
   0x00,  0xA2,  0x80,  0x01,  0x80,  0x63,  0x07,  0xA6,  0x2C,  0x01,  0x80,  0x81,  0x03,  0x03,  0x80,  0x63,
-  0xE2,  0x00,  0x07,  0xA6,  0x3C,  0x01,  0x00,  0x33,  0x04,  0x00,  0xB2,  0x88,  0x03,  0x07,  0x02,  0x01,
-  0x04,  0xCA,  0x0D,  0x23,  0x5A,  0x98,  0x4D,  0x04,  0xFE,  0x84,  0x05,  0xD8,  0x0D,  0x23,  0x5A,  0x98,
-  0xCD,  0x04,  0x15,  0x23,  0xE8,  0x88,  0xFB,  0x23,  0x02,  0x61,  0x82,  0x01,  0x80,  0x63,  0x02,  0x03,
-  0x06,  0xA3,  0x6A,  0x01,  0x00,  0x33,  0x0A,  0x00,  0xB2,  0x88,  0x4E,  0x00,  0x07,  0xA3,  0x76,  0x01,
-  0x00,  0x33,  0x0B,  0x00,  0xB2,  0x88,  0xCD,  0x04,  0x36,  0x2D,  0x00,  0x33,  0x1A,  0x00,  0xB2,  0x88,
+  0xE2,  0x00,  0x07,  0xA6,  0x3C,  0x01,  0x00,  0x33,  0x04,  0x00,  0xC0,  0x88,  0x03,  0x07,  0x02,  0x01,
+  0x04,  0xCA,  0x0D,  0x23,  0x68,  0x98,  0x4D,  0x04,  0x04,  0x85,  0x05,  0xD8,  0x0D,  0x23,  0x68,  0x98,
+  0xCD,  0x04,  0x15,  0x23,  0xF6,  0x88,  0xFB,  0x23,  0x02,  0x61,  0x82,  0x01,  0x80,  0x63,  0x02,  0x03,
+  0x06,  0xA3,  0x6A,  0x01,  0x00,  0x33,  0x0A,  0x00,  0xC0,  0x88,  0x4E,  0x00,  0x07,  0xA3,  0x76,  0x01,
+  0x00,  0x33,  0x0B,  0x00,  0xC0,  0x88,  0xCD,  0x04,  0x36,  0x2D,  0x00,  0x33,  0x1A,  0x00,  0xC0,  0x88,
   0x50,  0x04,  0x90,  0x81,  0x06,  0xAB,  0x8A,  0x01,  0x90,  0x81,  0x4E,  0x00,  0x07,  0xA3,  0x9A,  0x01,
-  0x50,  0x00,  0x00,  0xA3,  0x44,  0x01,  0x00,  0x05,  0x84,  0x81,  0x38,  0x97,  0x02,  0x01,  0x05,  0xC6,
+  0x50,  0x00,  0x00,  0xA3,  0x44,  0x01,  0x00,  0x05,  0x84,  0x81,  0x46,  0x97,  0x02,  0x01,  0x05,  0xC6,
   0x04,  0x23,  0xA0,  0x01,  0x15,  0x23,  0xA1,  0x01,  0xC6,  0x81,  0xFD,  0x23,  0x02,  0x61,  0x82,  0x01,
   0x0A,  0xDA,  0x4A,  0x00,  0x06,  0x61,  0x00,  0xA0,  0xBC,  0x01,  0x80,  0x63,  0xCD,  0x04,  0x36,  0x2D,
-  0x00,  0x33,  0x1B,  0x00,  0xB2,  0x88,  0x06,  0x23,  0x5A,  0x98,  0xCD,  0x04,  0xE0,  0x84,  0x06,  0x01,
-  0x00,  0xA2,  0xDC,  0x01,  0x57,  0x60,  0x00,  0xA0,  0xE2,  0x01,  0xE0,  0x84,  0x80,  0x23,  0xA0,  0x01,
-  0xE0,  0x84,  0x80,  0x73,  0x4B,  0x00,  0x06,  0x61,  0x00,  0xA2,  0x08,  0x02,  0x04,  0x01,  0x0C,  0xDE,
-  0x02,  0x01,  0x03,  0xCC,  0x4F,  0x00,  0x76,  0x97,  0x04,  0x82,  0x08,  0x23,  0x02,  0x41,  0x82,  0x01,
-  0x4F,  0x00,  0x54,  0x97,  0x48,  0x04,  0x84,  0x80,  0xE2,  0x97,  0x00,  0x46,  0x56,  0x00,  0x03,  0xC0,
+  0x00,  0x33,  0x1B,  0x00,  0xC0,  0x88,  0x06,  0x23,  0x68,  0x98,  0xCD,  0x04,  0xE6,  0x84,  0x06,  0x01,
+  0x00,  0xA2,  0xDC,  0x01,  0x57,  0x60,  0x00,  0xA0,  0xE2,  0x01,  0xE6,  0x84,  0x80,  0x23,  0xA0,  0x01,
+  0xE6,  0x84,  0x80,  0x73,  0x4B,  0x00,  0x06,  0x61,  0x00,  0xA2,  0x08,  0x02,  0x04,  0x01,  0x0C,  0xDE,
+  0x02,  0x01,  0x03,  0xCC,  0x4F,  0x00,  0x84,  0x97,  0x04,  0x82,  0x08,  0x23,  0x02,  0x41,  0x82,  0x01,
+  0x4F,  0x00,  0x62,  0x97,  0x48,  0x04,  0x84,  0x80,  0xF0,  0x97,  0x00,  0x46,  0x56,  0x00,  0x03,  0xC0,
   0x01,  0x23,  0xE8,  0x00,  0x81,  0x73,  0x06,  0x29,  0x03,  0x42,  0x06,  0xE2,  0x03,  0xEE,  0x67,  0xEB,
-  0x11,  0x23,  0xE8,  0x88,  0xF6,  0x97,  0xF4,  0x80,  0x80,  0x73,  0x80,  0x77,  0x06,  0xA6,  0x36,  0x02,
-  0x00,  0x33,  0x31,  0x00,  0xB2,  0x88,  0x04,  0x01,  0x03,  0xD8,  0xA4,  0x98,  0x4C,  0x96,  0x48,  0x82,
-  0xDC,  0x95,  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0xB6,  0x2D,  0x02,  0xA6,  0x72,  0x02,  0x07,  0xA6,
-  0x60,  0x02,  0x06,  0xA6,  0x64,  0x02,  0x03,  0xA6,  0x68,  0x02,  0x00,  0x33,  0x10,  0x00,  0xB2,  0x88,
-  0x76,  0x95,  0x4A,  0x82,  0x42,  0x96,  0x4A,  0x82,  0x04,  0x23,  0xA0,  0x01,  0x14,  0x23,  0xA1,  0x01,
-  0x36,  0x84,  0x04,  0x01,  0x0C,  0xDC,  0xE0,  0x23,  0x25,  0x61,  0xEF,  0x00,  0x14,  0x01,  0x4F,  0x04,
-  0xA8,  0x01,  0x6F,  0x00,  0xA5,  0x01,  0x03,  0x23,  0xA4,  0x01,  0x06,  0x23,  0x9C,  0x01,  0x24,  0x2B,
-  0x1C,  0x01,  0x02,  0xA6,  0xB0,  0x02,  0x07,  0xA6,  0x60,  0x02,  0x06,  0xA6,  0x64,  0x02,  0x03,  0xA6,
-  0x1A,  0x04,  0x01,  0xA6,  0xBA,  0x02,  0x00,  0xA6,  0xBA,  0x02,  0x00,  0x33,  0x12,  0x00,  0xB2,  0x88,
-  0x00,  0x0E,  0x80,  0x63,  0x00,  0x43,  0x00,  0xA0,  0x92,  0x02,  0x4D,  0x04,  0x04,  0x01,  0x0B,  0xDC,
-  0xE7,  0x23,  0x04,  0x61,  0x84,  0x01,  0x10,  0x31,  0x12,  0x35,  0x14,  0x01,  0xEC,  0x00,  0x6C,  0x38,
-  0x00,  0x3F,  0x00,  0x00,  0xF0,  0x82,  0x18,  0x23,  0x04,  0x61,  0x18,  0xA0,  0xE8,  0x02,  0x04,  0x01,
-  0x9C,  0xC8,  0x00,  0x33,  0x1F,  0x00,  0xB2,  0x88,  0x08,  0x31,  0x0A,  0x35,  0x0C,  0x39,  0x0E,  0x3D,
-  0x70,  0x98,  0xB6,  0x2D,  0x01,  0xA6,  0x1A,  0x03,  0x00,  0xA6,  0x1A,  0x03,  0x07,  0xA6,  0x12,  0x03,
-  0x06,  0xA6,  0x16,  0x03,  0x03,  0xA6,  0x1A,  0x04,  0x02,  0xA6,  0x72,  0x02,  0x00,  0x33,  0x33,  0x00,
-  0xB2,  0x88,  0x76,  0x95,  0xF4,  0x82,  0x42,  0x96,  0xF4,  0x82,  0x74,  0x98,  0x80,  0x42,  0x70,  0x98,
-  0x60,  0xE4,  0x04,  0x01,  0x29,  0xC8,  0x31,  0x05,  0x07,  0x01,  0x00,  0xA2,  0x5A,  0x03,  0x00,  0x43,
-  0x87,  0x01,  0x05,  0x05,  0x78,  0x98,  0x70,  0x98,  0x00,  0xA6,  0x1C,  0x03,  0x07,  0xA6,  0x52,  0x03,
-  0x03,  0xA6,  0x36,  0x04,  0x06,  0xA6,  0x56,  0x03,  0x01,  0xA6,  0x1C,  0x03,  0x00,  0x33,  0x25,  0x00,
-  0xB2,  0x88,  0x76,  0x95,  0x38,  0x83,  0x42,  0x96,  0x38,  0x83,  0x04,  0x01,  0x0C,  0xCE,  0x03,  0xC8,
-  0x00,  0x33,  0x42,  0x00,  0xB2,  0x88,  0x00,  0x01,  0x05,  0x05,  0xFF,  0xA2,  0x78,  0x03,  0xB1,  0x01,
-  0x08,  0x23,  0xB2,  0x01,  0x34,  0x83,  0x05,  0x05,  0x15,  0x01,  0x00,  0xA2,  0x98,  0x03,  0xEC,  0x00,
-  0x6E,  0x00,  0x95,  0x01,  0x6C,  0x38,  0x00,  0x3F,  0x00,  0x00,  0x01,  0xA6,  0x94,  0x03,  0x00,  0xA6,
-  0x94,  0x03,  0x0C,  0x84,  0x80,  0x42,  0x70,  0x98,  0x01,  0xA6,  0xA2,  0x03,  0x00,  0xA6,  0xBA,  0x03,
-  0x0C,  0x84,  0x98,  0x98,  0x80,  0x42,  0x01,  0xA6,  0xA2,  0x03,  0x07,  0xA6,  0xB0,  0x03,  0xD2,  0x83,
-  0x76,  0x95,  0xA6,  0x83,  0x00,  0x33,  0x2F,  0x00,  0xB2,  0x88,  0x98,  0x98,  0x80,  0x42,  0x00,  0xA6,
-  0xBA,  0x03,  0x07,  0xA6,  0xC8,  0x03,  0xD2,  0x83,  0x76,  0x95,  0xBE,  0x83,  0x00,  0x33,  0x26,  0x00,
-  0xB2,  0x88,  0x38,  0x2B,  0x80,  0x32,  0x80,  0x36,  0x04,  0x23,  0xA0,  0x01,  0x12,  0x23,  0xA1,  0x01,
-  0x0C,  0x84,  0x06,  0xF0,  0x06,  0xA4,  0xF0,  0x03,  0x80,  0x6B,  0x05,  0x23,  0x83,  0x03,  0x80,  0x63,
-  0x03,  0xA6,  0x0A,  0x04,  0x07,  0xA6,  0x02,  0x04,  0x06,  0xA6,  0x06,  0x04,  0x00,  0x33,  0x17,  0x00,
-  0xB2,  0x88,  0x76,  0x95,  0xF0,  0x83,  0x42,  0x96,  0xF0,  0x83,  0x1A,  0x84,  0x06,  0xF0,  0x06,  0xA4,
-  0x1A,  0x04,  0x80,  0x6B,  0x05,  0x23,  0x83,  0x03,  0x80,  0x63,  0xB6,  0x2D,  0x03,  0xA6,  0x36,  0x04,
-  0x07,  0xA6,  0x2E,  0x04,  0x06,  0xA6,  0x32,  0x04,  0x00,  0x33,  0x30,  0x00,  0xB2,  0x88,  0x76,  0x95,
-  0x1A,  0x84,  0x42,  0x96,  0x1A,  0x84,  0x1D,  0x01,  0x06,  0xCC,  0x00,  0x33,  0x00,  0x84,  0xC0,  0x20,
-  0x00,  0x23,  0xEA,  0x00,  0x81,  0x62,  0xA2,  0x0D,  0x80,  0x63,  0x07,  0xA6,  0x54,  0x04,  0x00,  0x33,
-  0x18,  0x00,  0xB2,  0x88,  0x03,  0x03,  0x80,  0x63,  0xA3,  0x01,  0x07,  0xA4,  0x5E,  0x04,  0x23,  0x01,
-  0x00,  0xA2,  0x80,  0x04,  0x0A,  0xA0,  0x70,  0x04,  0xE0,  0x00,  0x00,  0x33,  0x1D,  0x00,  0xB2,  0x88,
-  0x0B,  0xA0,  0x7C,  0x04,  0xE0,  0x00,  0x00,  0x33,  0x1E,  0x00,  0xB2,  0x88,  0x42,  0x23,  0xE8,  0x88,
-  0x00,  0x23,  0x22,  0xA3,  0xE0,  0x04,  0x08,  0x23,  0x22,  0xA3,  0x9C,  0x04,  0x28,  0x23,  0x22,  0xA3,
-  0xA8,  0x04,  0x02,  0x23,  0x22,  0xA3,  0xBE,  0x04,  0x42,  0x23,  0xE8,  0x88,  0x4A,  0x00,  0x06,  0x61,
-  0x00,  0xA0,  0xA8,  0x04,  0x45,  0x23,  0xE8,  0x88,  0xF6,  0x97,  0x00,  0xA2,  0xBA,  0x04,  0xA4,  0x98,
-  0x00,  0x33,  0x00,  0x82,  0xC0,  0x20,  0x81,  0x62,  0xF0,  0x81,  0x47,  0x23,  0xE8,  0x88,  0x04,  0x01,
-  0x0B,  0xDE,  0xF6,  0x97,  0xA4,  0x98,  0x00,  0x33,  0x00,  0x81,  0xC0,  0x20,  0x81,  0x62,  0x14,  0x01,
-  0x00,  0xA0,  0x08,  0x02,  0x43,  0x23,  0xE8,  0x88,  0x04,  0x23,  0xA0,  0x01,  0x44,  0x23,  0xA1,  0x01,
-  0x80,  0x73,  0x4D,  0x00,  0x03,  0xA3,  0xEE,  0x04,  0x00,  0x33,  0x27,  0x00,  0xB2,  0x88,  0x04,  0x01,
-  0x04,  0xDC,  0x02,  0x23,  0xA2,  0x01,  0x04,  0x23,  0xA0,  0x01,  0xF6,  0x97,  0x20,  0x95,  0x4B,  0x00,
-  0xF6,  0x00,  0x4F,  0x04,  0x4F,  0x00,  0x00,  0xA3,  0x1C,  0x05,  0x00,  0x05,  0x76,  0x00,  0x06,  0x61,
-  0x00,  0xA2,  0x16,  0x05,  0x04,  0x85,  0x38,  0x97,  0xCD,  0x04,  0x1E,  0x85,  0x48,  0x04,  0x84,  0x80,
-  0x02,  0x01,  0x03,  0xDA,  0x80,  0x23,  0x82,  0x01,  0x2E,  0x85,  0x02,  0x23,  0xA0,  0x01,  0x4A,  0x00,
-  0x06,  0x61,  0x00,  0xA2,  0x3A,  0x05,  0x1D,  0x01,  0x04,  0xD6,  0xFF,  0x23,  0x86,  0x41,  0x4B,  0x60,
-  0xCB,  0x00,  0xFF,  0x23,  0x80,  0x01,  0x49,  0x00,  0x81,  0x01,  0x04,  0x01,  0x02,  0xC8,  0x30,  0x01,
-  0x80,  0x01,  0xF7,  0x04,  0x03,  0x01,  0x49,  0x04,  0x80,  0x01,  0xC9,  0x00,  0x00,  0x05,  0x00,  0x01,
-  0xFF,  0xA0,  0x5A,  0x05,  0x77,  0x04,  0x01,  0x23,  0xEA,  0x00,  0x5D,  0x00,  0xFE,  0xC7,  0x00,  0x62,
-  0x00,  0x23,  0xEA,  0x00,  0x00,  0x63,  0x07,  0xA4,  0xDA,  0x05,  0x03,  0x03,  0x02,  0xA0,  0x88,  0x05,
-  0xD6,  0x85,  0x00,  0x33,  0x2D,  0x00,  0xB2,  0x88,  0x04,  0xA0,  0xAE,  0x05,  0x80,  0x63,  0x4A,  0x00,
-  0x06,  0x61,  0x00,  0xA2,  0x9A,  0x05,  0x1D,  0x01,  0x06,  0xD6,  0x02,  0x23,  0x02,  0x41,  0x82,  0x01,
-  0x50,  0x00,  0x54,  0x97,  0xFE,  0x84,  0x04,  0x23,  0x02,  0x41,  0x82,  0x01,  0xFE,  0x84,  0x08,  0xA0,
-  0xB4,  0x05,  0xD6,  0x85,  0x03,  0xA0,  0xBA,  0x05,  0xD6,  0x85,  0x01,  0xA0,  0xC4,  0x05,  0x88,  0x00,
-  0x80,  0x63,  0xB2,  0x86,  0x07,  0xA0,  0xD0,  0x05,  0x06,  0x23,  0x5A,  0x98,  0x48,  0x23,  0xE8,  0x88,
-  0x07,  0x23,  0x80,  0x00,  0xF8,  0x86,  0x80,  0x63,  0x76,  0x85,  0x00,  0x63,  0x4A,  0x00,  0x06,  0x61,
-  0x00,  0xA2,  0x18,  0x06,  0x1D,  0x01,  0x18,  0xD4,  0xC0,  0x23,  0x07,  0x41,  0x83,  0x03,  0x80,  0x63,
-  0x06,  0xA6,  0xFA,  0x05,  0x00,  0x33,  0x37,  0x00,  0xB2,  0x88,  0x1D,  0x01,  0x02,  0xD6,  0x46,  0x23,
-  0xE8,  0x88,  0x63,  0x60,  0x83,  0x03,  0x80,  0x63,  0x06,  0xA6,  0x12,  0x06,  0x00,  0x33,  0x38,  0x00,
-  0xB2,  0x88,  0xEF,  0x04,  0x6F,  0x00,  0x00,  0x63,  0x4B,  0x00,  0x06,  0x41,  0xCB,  0x00,  0x52,  0x00,
-  0x06,  0x61,  0x00,  0xA2,  0x30,  0x06,  0x1D,  0x01,  0x03,  0xCA,  0xC0,  0x23,  0x07,  0x41,  0x00,  0x63,
-  0x1D,  0x01,  0x04,  0xCC,  0x00,  0x33,  0x00,  0x83,  0xC0,  0x20,  0x81,  0x62,  0x80,  0x23,  0x07,  0x41,
-  0x00,  0x63,  0x80,  0x67,  0x08,  0x23,  0x83,  0x03,  0x80,  0x63,  0x00,  0x63,  0x06,  0xA6,  0x5E,  0x06,
-  0x07,  0xA6,  0x76,  0x05,  0x02,  0xA6,  0xEC,  0x06,  0x00,  0x33,  0x39,  0x00,  0xB2,  0x88,  0x00,  0x00,
-  0x01,  0xA0,  0x06,  0x07,  0xDC,  0x95,  0x83,  0x03,  0x80,  0x63,  0x06,  0xA6,  0x72,  0x06,  0x07,  0xA6,
-  0x76,  0x05,  0x00,  0x00,  0x01,  0xA0,  0x06,  0x07,  0x00,  0x2B,  0x40,  0x0E,  0x80,  0x63,  0x01,  0x00,
-  0x06,  0xA6,  0x8E,  0x06,  0x07,  0xA6,  0x76,  0x05,  0x00,  0x33,  0x3A,  0x00,  0xB2,  0x88,  0x40,  0x0E,
-  0x80,  0x63,  0x00,  0x43,  0x00,  0xA0,  0x80,  0x06,  0x06,  0xA6,  0xA6,  0x06,  0x07,  0xA6,  0x76,  0x05,
-  0x00,  0x33,  0x3B,  0x00,  0xB2,  0x88,  0x80,  0x67,  0x40,  0x0E,  0x80,  0x63,  0x07,  0xA6,  0x76,  0x05,
-  0x00,  0x63,  0x07,  0xA6,  0xBC,  0x06,  0x00,  0x33,  0x2A,  0x00,  0xB2,  0x88,  0x03,  0x03,  0x80,  0x63,
-  0x89,  0x00,  0x0A,  0x2B,  0x07,  0xA6,  0xCE,  0x06,  0x00,  0x33,  0x29,  0x00,  0xB2,  0x88,  0x00,  0x43,
-  0x00,  0xA2,  0xDA,  0x06,  0xC0,  0x0E,  0x80,  0x63,  0xC4,  0x86,  0xC0,  0x0E,  0x00,  0x33,  0x00,  0x80,
-  0xC0,  0x20,  0x81,  0x62,  0x04,  0x01,  0x08,  0xDA,  0x80,  0x63,  0x76,  0x85,  0x80,  0x67,  0x00,  0x33,
-  0x00,  0x40,  0xC0,  0x20,  0x81,  0x62,  0x00,  0x63,  0x80,  0x7B,  0x80,  0x63,  0x06,  0xA6,  0x6A,  0x06,
-  0x00,  0x33,  0x2C,  0x00,  0xB2,  0x88,  0x0C,  0xA2,  0x20,  0x07,  0xDC,  0x95,  0x83,  0x03,  0x80,  0x63,
-  0x06,  0xA6,  0x1E,  0x07,  0x07,  0xA6,  0x76,  0x05,  0x00,  0x33,  0x3D,  0x00,  0xB2,  0x88,  0x00,  0x00,
-  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0x0C,  0xA0,  0x36,  0x07,  0x07,  0xA6,  0x76,  0x05,  0xBF,  0x23,
-  0x04,  0x61,  0x84,  0x01,  0xE0,  0x84,  0x00,  0x63,  0xF0,  0x04,  0x01,  0x01,  0xF1,  0x00,  0x00,  0x01,
-  0xF2,  0x00,  0x01,  0x05,  0x80,  0x01,  0x72,  0x04,  0x71,  0x00,  0x81,  0x01,  0x70,  0x04,  0x80,  0x05,
-  0x81,  0x05,  0x00,  0x63,  0xF0,  0x04,  0xF2,  0x00,  0x72,  0x04,  0x01,  0x01,  0xF1,  0x00,  0x70,  0x00,
-  0x81,  0x01,  0x70,  0x04,  0x71,  0x00,  0x81,  0x01,  0x72,  0x00,  0x80,  0x01,  0x71,  0x04,  0x70,  0x00,
-  0x80,  0x01,  0x70,  0x04,  0x00,  0x63,  0xF0,  0x04,  0xF2,  0x00,  0x72,  0x04,  0x00,  0x01,  0xF1,  0x00,
-  0x70,  0x00,  0x80,  0x01,  0x70,  0x04,  0x71,  0x00,  0x80,  0x01,  0x72,  0x00,  0x81,  0x01,  0x71,  0x04,
-  0x70,  0x00,  0x81,  0x01,  0x70,  0x04,  0x00,  0x63,  0x00,  0x23,  0xB3,  0x01,  0x83,  0x05,  0xA3,  0x01,
-  0xA2,  0x01,  0xA1,  0x01,  0x01,  0x23,  0xA0,  0x01,  0x00,  0x01,  0xC8,  0x00,  0x03,  0xA1,  0xB6,  0x07,
-  0x00,  0x33,  0x07,  0x00,  0xB2,  0x88,  0x80,  0x05,  0x81,  0x05,  0x04,  0x01,  0x11,  0xC8,  0x48,  0x00,
-  0xB0,  0x01,  0xB1,  0x01,  0x08,  0x23,  0xB2,  0x01,  0x05,  0x01,  0x48,  0x04,  0x00,  0x43,  0x00,  0xA2,
-  0xD6,  0x07,  0x00,  0x05,  0xCC,  0x87,  0x00,  0x01,  0xC8,  0x00,  0xFF,  0x23,  0x80,  0x01,  0x05,  0x05,
-  0x00,  0x63,  0xF7,  0x04,  0x1A,  0x09,  0xF6,  0x08,  0x6E,  0x04,  0x00,  0x02,  0x80,  0x43,  0x76,  0x08,
-  0x80,  0x02,  0x77,  0x04,  0x00,  0x63,  0xF7,  0x04,  0x1A,  0x09,  0xF6,  0x08,  0x6E,  0x04,  0x00,  0x02,
-  0x00,  0xA0,  0x06,  0x08,  0x08,  0x88,  0x00,  0x43,  0x76,  0x08,  0x80,  0x02,  0x77,  0x04,  0x00,  0x63,
-  0xF3,  0x04,  0x00,  0x23,  0xF4,  0x00,  0x74,  0x00,  0x80,  0x43,  0xF4,  0x00,  0xCF,  0x40,  0x00,  0xA2,
-  0x36,  0x08,  0x74,  0x04,  0x02,  0x01,  0xF7,  0xC9,  0xF6,  0xD9,  0x00,  0x01,  0x01,  0xA1,  0x16,  0x08,
-  0xF6,  0x97,  0x20,  0x95,  0x16,  0x88,  0x73,  0x04,  0x00,  0x63,  0xF3,  0x04,  0x75,  0x04,  0x4C,  0x88,
-  0x02,  0x01,  0x04,  0xD8,  0x38,  0x97,  0xF6,  0x97,  0x20,  0x95,  0x3C,  0x88,  0x75,  0x00,  0x00,  0xA3,
-  0x56,  0x08,  0x00,  0x05,  0x40,  0x88,  0x73,  0x04,  0x00,  0x63,  0x80,  0x7B,  0x80,  0x63,  0x06,  0xA6,
-  0x68,  0x08,  0x00,  0x33,  0x3E,  0x00,  0xB2,  0x88,  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0x00,  0x63,
-  0x38,  0x2B,  0x8E,  0x88,  0x38,  0x2B,  0x84,  0x88,  0x32,  0x09,  0x31,  0x05,  0x84,  0x98,  0x05,  0x05,
-  0xB2,  0x09,  0x00,  0x63,  0x00,  0x32,  0x00,  0x36,  0x00,  0x3A,  0x00,  0x3E,  0x00,  0x63,  0x80,  0x32,
-  0x80,  0x36,  0x80,  0x3A,  0x80,  0x3E,  0x00,  0x63,  0x38,  0x2B,  0x40,  0x32,  0x40,  0x36,  0x40,  0x3A,
-  0x40,  0x3E,  0x00,  0x63,  0x5A,  0x20,  0xC9,  0x40,  0x00,  0xA0,  0xA4,  0x08,  0x5D,  0x00,  0xFE,  0xC3,
-  0x00,  0x63,  0x80,  0x73,  0xE6,  0x20,  0x02,  0x23,  0xE8,  0x00,  0x82,  0x73,  0xFF,  0xFD,  0x80,  0x73,
-  0x13,  0x23,  0xE8,  0x88,  0x66,  0x20,  0xC0,  0x20,  0x04,  0x23,  0xA0,  0x01,  0xA1,  0x23,  0xA1,  0x01,
-  0x81,  0x62,  0xD2,  0x88,  0x80,  0x73,  0x80,  0x77,  0x68,  0x00,  0x00,  0xA2,  0x80,  0x00,  0x03,  0xC2,
-  0xF1,  0xC7,  0x41,  0x23,  0xE8,  0x88,  0x11,  0x23,  0xA1,  0x01,  0x04,  0x23,  0xA0,  0x01,  0xE0,  0x84,
-
+  0x11,  0x23,  0xF6,  0x88,  0x04,  0x98,  0xF4,  0x80,  0x80,  0x73,  0x80,  0x77,  0x07,  0xA4,  0x32,  0x02,
+  0x7C,  0x95,  0x06,  0xA6,  0x3C,  0x02,  0x03,  0xA6,  0x4C,  0x04,  0xC0,  0x88,  0x04,  0x01,  0x03,  0xD8,
+  0xB2,  0x98,  0x6A,  0x96,  0x4E,  0x82,  0xFE,  0x95,  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0xB6,  0x2D,
+  0x02,  0xA6,  0x78,  0x02,  0x07,  0xA6,  0x66,  0x02,  0x06,  0xA6,  0x6A,  0x02,  0x03,  0xA6,  0x6E,  0x02,
+  0x00,  0x33,  0x10,  0x00,  0xC0,  0x88,  0x7C,  0x95,  0x50,  0x82,  0x60,  0x96,  0x50,  0x82,  0x04,  0x23,
+  0xA0,  0x01,  0x14,  0x23,  0xA1,  0x01,  0x3C,  0x84,  0x04,  0x01,  0x0C,  0xDC,  0xE0,  0x23,  0x25,  0x61,
+  0xEF,  0x00,  0x14,  0x01,  0x4F,  0x04,  0xA8,  0x01,  0x6F,  0x00,  0xA5,  0x01,  0x03,  0x23,  0xA4,  0x01,
+  0x06,  0x23,  0x9C,  0x01,  0x24,  0x2B,  0x1C,  0x01,  0x02,  0xA6,  0xB6,  0x02,  0x07,  0xA6,  0x66,  0x02,
+  0x06,  0xA6,  0x6A,  0x02,  0x03,  0xA6,  0x20,  0x04,  0x01,  0xA6,  0xC0,  0x02,  0x00,  0xA6,  0xC0,  0x02,
+  0x00,  0x33,  0x12,  0x00,  0xC0,  0x88,  0x00,  0x0E,  0x80,  0x63,  0x00,  0x43,  0x00,  0xA0,  0x98,  0x02,
+  0x4D,  0x04,  0x04,  0x01,  0x0B,  0xDC,  0xE7,  0x23,  0x04,  0x61,  0x84,  0x01,  0x10,  0x31,  0x12,  0x35,
+  0x14,  0x01,  0xEC,  0x00,  0x6C,  0x38,  0x00,  0x3F,  0x00,  0x00,  0xF6,  0x82,  0x18,  0x23,  0x04,  0x61,
+  0x18,  0xA0,  0xEE,  0x02,  0x04,  0x01,  0x9C,  0xC8,  0x00,  0x33,  0x1F,  0x00,  0xC0,  0x88,  0x08,  0x31,
+  0x0A,  0x35,  0x0C,  0x39,  0x0E,  0x3D,  0x7E,  0x98,  0xB6,  0x2D,  0x01,  0xA6,  0x20,  0x03,  0x00,  0xA6,
+  0x20,  0x03,  0x07,  0xA6,  0x18,  0x03,  0x06,  0xA6,  0x1C,  0x03,  0x03,  0xA6,  0x20,  0x04,  0x02,  0xA6,
+  0x78,  0x02,  0x00,  0x33,  0x33,  0x00,  0xC0,  0x88,  0x7C,  0x95,  0xFA,  0x82,  0x60,  0x96,  0xFA,  0x82,
+  0x82,  0x98,  0x80,  0x42,  0x7E,  0x98,  0x60,  0xE4,  0x04,  0x01,  0x29,  0xC8,  0x31,  0x05,  0x07,  0x01,
+  0x00,  0xA2,  0x60,  0x03,  0x00,  0x43,  0x87,  0x01,  0x05,  0x05,  0x86,  0x98,  0x7E,  0x98,  0x00,  0xA6,
+  0x22,  0x03,  0x07,  0xA6,  0x58,  0x03,  0x03,  0xA6,  0x3C,  0x04,  0x06,  0xA6,  0x5C,  0x03,  0x01,  0xA6,
+  0x22,  0x03,  0x00,  0x33,  0x25,  0x00,  0xC0,  0x88,  0x7C,  0x95,  0x3E,  0x83,  0x60,  0x96,  0x3E,  0x83,
+  0x04,  0x01,  0x0C,  0xCE,  0x03,  0xC8,  0x00,  0x33,  0x42,  0x00,  0xC0,  0x88,  0x00,  0x01,  0x05,  0x05,
+  0xFF,  0xA2,  0x7E,  0x03,  0xB1,  0x01,  0x08,  0x23,  0xB2,  0x01,  0x3A,  0x83,  0x05,  0x05,  0x15,  0x01,
+  0x00,  0xA2,  0x9E,  0x03,  0xEC,  0x00,  0x6E,  0x00,  0x95,  0x01,  0x6C,  0x38,  0x00,  0x3F,  0x00,  0x00,
+  0x01,  0xA6,  0x9A,  0x03,  0x00,  0xA6,  0x9A,  0x03,  0x12,  0x84,  0x80,  0x42,  0x7E,  0x98,  0x01,  0xA6,
+  0xA8,  0x03,  0x00,  0xA6,  0xC0,  0x03,  0x12,  0x84,  0xA6,  0x98,  0x80,  0x42,  0x01,  0xA6,  0xA8,  0x03,
+  0x07,  0xA6,  0xB6,  0x03,  0xD8,  0x83,  0x7C,  0x95,  0xAC,  0x83,  0x00,  0x33,  0x2F,  0x00,  0xC0,  0x88,
+  0xA6,  0x98,  0x80,  0x42,  0x00,  0xA6,  0xC0,  0x03,  0x07,  0xA6,  0xCE,  0x03,  0xD8,  0x83,  0x7C,  0x95,
+  0xC4,  0x83,  0x00,  0x33,  0x26,  0x00,  0xC0,  0x88,  0x38,  0x2B,  0x80,  0x32,  0x80,  0x36,  0x04,  0x23,
+  0xA0,  0x01,  0x12,  0x23,  0xA1,  0x01,  0x12,  0x84,  0x06,  0xF0,  0x06,  0xA4,  0xF6,  0x03,  0x80,  0x6B,
+  0x05,  0x23,  0x83,  0x03,  0x80,  0x63,  0x03,  0xA6,  0x10,  0x04,  0x07,  0xA6,  0x08,  0x04,  0x06,  0xA6,
+  0x0C,  0x04,  0x00,  0x33,  0x17,  0x00,  0xC0,  0x88,  0x7C,  0x95,  0xF6,  0x83,  0x60,  0x96,  0xF6,  0x83,
+  0x20,  0x84,  0x06,  0xF0,  0x06,  0xA4,  0x20,  0x04,  0x80,  0x6B,  0x05,  0x23,  0x83,  0x03,  0x80,  0x63,
+  0xB6,  0x2D,  0x03,  0xA6,  0x3C,  0x04,  0x07,  0xA6,  0x34,  0x04,  0x06,  0xA6,  0x38,  0x04,  0x00,  0x33,
+  0x30,  0x00,  0xC0,  0x88,  0x7C,  0x95,  0x20,  0x84,  0x60,  0x96,  0x20,  0x84,  0x1D,  0x01,  0x06,  0xCC,
+  0x00,  0x33,  0x00,  0x84,  0xC0,  0x20,  0x00,  0x23,  0xEA,  0x00,  0x81,  0x62,  0xA2,  0x0D,  0x80,  0x63,
+  0x07,  0xA6,  0x5A,  0x04,  0x00,  0x33,  0x18,  0x00,  0xC0,  0x88,  0x03,  0x03,  0x80,  0x63,  0xA3,  0x01,
+  0x07,  0xA4,  0x64,  0x04,  0x23,  0x01,  0x00,  0xA2,  0x86,  0x04,  0x0A,  0xA0,  0x76,  0x04,  0xE0,  0x00,
+  0x00,  0x33,  0x1D,  0x00,  0xC0,  0x88,  0x0B,  0xA0,  0x82,  0x04,  0xE0,  0x00,  0x00,  0x33,  0x1E,  0x00,
+  0xC0,  0x88,  0x42,  0x23,  0xF6,  0x88,  0x00,  0x23,  0x22,  0xA3,  0xE6,  0x04,  0x08,  0x23,  0x22,  0xA3,
+  0xA2,  0x04,  0x28,  0x23,  0x22,  0xA3,  0xAE,  0x04,  0x02,  0x23,  0x22,  0xA3,  0xC4,  0x04,  0x42,  0x23,
+  0xF6,  0x88,  0x4A,  0x00,  0x06,  0x61,  0x00,  0xA0,  0xAE,  0x04,  0x45,  0x23,  0xF6,  0x88,  0x04,  0x98,
+  0x00,  0xA2,  0xC0,  0x04,  0xB2,  0x98,  0x00,  0x33,  0x00,  0x82,  0xC0,  0x20,  0x81,  0x62,  0xF0,  0x81,
+  0x47,  0x23,  0xF6,  0x88,  0x04,  0x01,  0x0B,  0xDE,  0x04,  0x98,  0xB2,  0x98,  0x00,  0x33,  0x00,  0x81,
+  0xC0,  0x20,  0x81,  0x62,  0x14,  0x01,  0x00,  0xA0,  0x08,  0x02,  0x43,  0x23,  0xF6,  0x88,  0x04,  0x23,
+  0xA0,  0x01,  0x44,  0x23,  0xA1,  0x01,  0x80,  0x73,  0x4D,  0x00,  0x03,  0xA3,  0xF4,  0x04,  0x00,  0x33,
+  0x27,  0x00,  0xC0,  0x88,  0x04,  0x01,  0x04,  0xDC,  0x02,  0x23,  0xA2,  0x01,  0x04,  0x23,  0xA0,  0x01,
+  0x04,  0x98,  0x26,  0x95,  0x4B,  0x00,  0xF6,  0x00,  0x4F,  0x04,  0x4F,  0x00,  0x00,  0xA3,  0x22,  0x05,
+  0x00,  0x05,  0x76,  0x00,  0x06,  0x61,  0x00,  0xA2,  0x1C,  0x05,  0x0A,  0x85,  0x46,  0x97,  0xCD,  0x04,
+  0x24,  0x85,  0x48,  0x04,  0x84,  0x80,  0x02,  0x01,  0x03,  0xDA,  0x80,  0x23,  0x82,  0x01,  0x34,  0x85,
+  0x02,  0x23,  0xA0,  0x01,  0x4A,  0x00,  0x06,  0x61,  0x00,  0xA2,  0x40,  0x05,  0x1D,  0x01,  0x04,  0xD6,
+  0xFF,  0x23,  0x86,  0x41,  0x4B,  0x60,  0xCB,  0x00,  0xFF,  0x23,  0x80,  0x01,  0x49,  0x00,  0x81,  0x01,
+  0x04,  0x01,  0x02,  0xC8,  0x30,  0x01,  0x80,  0x01,  0xF7,  0x04,  0x03,  0x01,  0x49,  0x04,  0x80,  0x01,
+  0xC9,  0x00,  0x00,  0x05,  0x00,  0x01,  0xFF,  0xA0,  0x60,  0x05,  0x77,  0x04,  0x01,  0x23,  0xEA,  0x00,
+  0x5D,  0x00,  0xFE,  0xC7,  0x00,  0x62,  0x00,  0x23,  0xEA,  0x00,  0x00,  0x63,  0x07,  0xA4,  0xF8,  0x05,
+  0x03,  0x03,  0x02,  0xA0,  0x8E,  0x05,  0xF4,  0x85,  0x00,  0x33,  0x2D,  0x00,  0xC0,  0x88,  0x04,  0xA0,
+  0xB8,  0x05,  0x80,  0x63,  0x00,  0x23,  0xDF,  0x00,  0x4A,  0x00,  0x06,  0x61,  0x00,  0xA2,  0xA4,  0x05,
+  0x1D,  0x01,  0x06,  0xD6,  0x02,  0x23,  0x02,  0x41,  0x82,  0x01,  0x50,  0x00,  0x62,  0x97,  0x04,  0x85,
+  0x04,  0x23,  0x02,  0x41,  0x82,  0x01,  0x04,  0x85,  0x08,  0xA0,  0xBE,  0x05,  0xF4,  0x85,  0x03,  0xA0,
+  0xC4,  0x05,  0xF4,  0x85,  0x01,  0xA0,  0xCE,  0x05,  0x88,  0x00,  0x80,  0x63,  0xCC,  0x86,  0x07,  0xA0,
+  0xEE,  0x05,  0x5F,  0x00,  0x00,  0x2B,  0xDF,  0x08,  0x00,  0xA2,  0xE6,  0x05,  0x80,  0x67,  0x80,  0x63,
+  0x01,  0xA2,  0x7A,  0x06,  0x7C,  0x85,  0x06,  0x23,  0x68,  0x98,  0x48,  0x23,  0xF6,  0x88,  0x07,  0x23,
+  0x80,  0x00,  0x06,  0x87,  0x80,  0x63,  0x7C,  0x85,  0x00,  0x23,  0xDF,  0x00,  0x00,  0x63,  0x4A,  0x00,
+  0x06,  0x61,  0x00,  0xA2,  0x36,  0x06,  0x1D,  0x01,  0x16,  0xD4,  0xC0,  0x23,  0x07,  0x41,  0x83,  0x03,
+  0x80,  0x63,  0x06,  0xA6,  0x1C,  0x06,  0x00,  0x33,  0x37,  0x00,  0xC0,  0x88,  0x1D,  0x01,  0x01,  0xD6,
+  0x20,  0x23,  0x63,  0x60,  0x83,  0x03,  0x80,  0x63,  0x02,  0x23,  0xDF,  0x00,  0x07,  0xA6,  0x7C,  0x05,
+  0xEF,  0x04,  0x6F,  0x00,  0x00,  0x63,  0x4B,  0x00,  0x06,  0x41,  0xCB,  0x00,  0x52,  0x00,  0x06,  0x61,
+  0x00,  0xA2,  0x4E,  0x06,  0x1D,  0x01,  0x03,  0xCA,  0xC0,  0x23,  0x07,  0x41,  0x00,  0x63,  0x1D,  0x01,
+  0x04,  0xCC,  0x00,  0x33,  0x00,  0x83,  0xC0,  0x20,  0x81,  0x62,  0x80,  0x23,  0x07,  0x41,  0x00,  0x63,
+  0x80,  0x67,  0x08,  0x23,  0x83,  0x03,  0x80,  0x63,  0x00,  0x63,  0x01,  0x23,  0xDF,  0x00,  0x06,  0xA6,
+  0x84,  0x06,  0x07,  0xA6,  0x7C,  0x05,  0x80,  0x67,  0x80,  0x63,  0x00,  0x33,  0x00,  0x40,  0xC0,  0x20,
+  0x81,  0x62,  0x00,  0x63,  0x00,  0x00,  0xFE,  0x95,  0x83,  0x03,  0x80,  0x63,  0x06,  0xA6,  0x94,  0x06,
+  0x07,  0xA6,  0x7C,  0x05,  0x00,  0x00,  0x01,  0xA0,  0x14,  0x07,  0x00,  0x2B,  0x40,  0x0E,  0x80,  0x63,
+  0x01,  0x00,  0x06,  0xA6,  0xAA,  0x06,  0x07,  0xA6,  0x7C,  0x05,  0x40,  0x0E,  0x80,  0x63,  0x00,  0x43,
+  0x00,  0xA0,  0xA2,  0x06,  0x06,  0xA6,  0xBC,  0x06,  0x07,  0xA6,  0x7C,  0x05,  0x80,  0x67,  0x40,  0x0E,
+  0x80,  0x63,  0x07,  0xA6,  0x7C,  0x05,  0x00,  0x23,  0xDF,  0x00,  0x00,  0x63,  0x07,  0xA6,  0xD6,  0x06,
+  0x00,  0x33,  0x2A,  0x00,  0xC0,  0x88,  0x03,  0x03,  0x80,  0x63,  0x89,  0x00,  0x0A,  0x2B,  0x07,  0xA6,
+  0xE8,  0x06,  0x00,  0x33,  0x29,  0x00,  0xC0,  0x88,  0x00,  0x43,  0x00,  0xA2,  0xF4,  0x06,  0xC0,  0x0E,
+  0x80,  0x63,  0xDE,  0x86,  0xC0,  0x0E,  0x00,  0x33,  0x00,  0x80,  0xC0,  0x20,  0x81,  0x62,  0x04,  0x01,
+  0x02,  0xDA,  0x80,  0x63,  0x7C,  0x85,  0x80,  0x7B,  0x80,  0x63,  0x06,  0xA6,  0x8C,  0x06,  0x00,  0x33,
+  0x2C,  0x00,  0xC0,  0x88,  0x0C,  0xA2,  0x2E,  0x07,  0xFE,  0x95,  0x83,  0x03,  0x80,  0x63,  0x06,  0xA6,
+  0x2C,  0x07,  0x07,  0xA6,  0x7C,  0x05,  0x00,  0x33,  0x3D,  0x00,  0xC0,  0x88,  0x00,  0x00,  0x80,  0x67,
+  0x83,  0x03,  0x80,  0x63,  0x0C,  0xA0,  0x44,  0x07,  0x07,  0xA6,  0x7C,  0x05,  0xBF,  0x23,  0x04,  0x61,
+  0x84,  0x01,  0xE6,  0x84,  0x00,  0x63,  0xF0,  0x04,  0x01,  0x01,  0xF1,  0x00,  0x00,  0x01,  0xF2,  0x00,
+  0x01,  0x05,  0x80,  0x01,  0x72,  0x04,  0x71,  0x00,  0x81,  0x01,  0x70,  0x04,  0x80,  0x05,  0x81,  0x05,
+  0x00,  0x63,  0xF0,  0x04,  0xF2,  0x00,  0x72,  0x04,  0x01,  0x01,  0xF1,  0x00,  0x70,  0x00,  0x81,  0x01,
+  0x70,  0x04,  0x71,  0x00,  0x81,  0x01,  0x72,  0x00,  0x80,  0x01,  0x71,  0x04,  0x70,  0x00,  0x80,  0x01,
+  0x70,  0x04,  0x00,  0x63,  0xF0,  0x04,  0xF2,  0x00,  0x72,  0x04,  0x00,  0x01,  0xF1,  0x00,  0x70,  0x00,
+  0x80,  0x01,  0x70,  0x04,  0x71,  0x00,  0x80,  0x01,  0x72,  0x00,  0x81,  0x01,  0x71,  0x04,  0x70,  0x00,
+  0x81,  0x01,  0x70,  0x04,  0x00,  0x63,  0x00,  0x23,  0xB3,  0x01,  0x83,  0x05,  0xA3,  0x01,  0xA2,  0x01,
+  0xA1,  0x01,  0x01,  0x23,  0xA0,  0x01,  0x00,  0x01,  0xC8,  0x00,  0x03,  0xA1,  0xC4,  0x07,  0x00,  0x33,
+  0x07,  0x00,  0xC0,  0x88,  0x80,  0x05,  0x81,  0x05,  0x04,  0x01,  0x11,  0xC8,  0x48,  0x00,  0xB0,  0x01,
+  0xB1,  0x01,  0x08,  0x23,  0xB2,  0x01,  0x05,  0x01,  0x48,  0x04,  0x00,  0x43,  0x00,  0xA2,  0xE4,  0x07,
+  0x00,  0x05,  0xDA,  0x87,  0x00,  0x01,  0xC8,  0x00,  0xFF,  0x23,  0x80,  0x01,  0x05,  0x05,  0x00,  0x63,
+  0xF7,  0x04,  0x1A,  0x09,  0xF6,  0x08,  0x6E,  0x04,  0x00,  0x02,  0x80,  0x43,  0x76,  0x08,  0x80,  0x02,
+  0x77,  0x04,  0x00,  0x63,  0xF7,  0x04,  0x1A,  0x09,  0xF6,  0x08,  0x6E,  0x04,  0x00,  0x02,  0x00,  0xA0,
+  0x14,  0x08,  0x16,  0x88,  0x00,  0x43,  0x76,  0x08,  0x80,  0x02,  0x77,  0x04,  0x00,  0x63,  0xF3,  0x04,
+  0x00,  0x23,  0xF4,  0x00,  0x74,  0x00,  0x80,  0x43,  0xF4,  0x00,  0xCF,  0x40,  0x00,  0xA2,  0x44,  0x08,
+  0x74,  0x04,  0x02,  0x01,  0xF7,  0xC9,  0xF6,  0xD9,  0x00,  0x01,  0x01,  0xA1,  0x24,  0x08,  0x04,  0x98,
+  0x26,  0x95,  0x24,  0x88,  0x73,  0x04,  0x00,  0x63,  0xF3,  0x04,  0x75,  0x04,  0x5A,  0x88,  0x02,  0x01,
+  0x04,  0xD8,  0x46,  0x97,  0x04,  0x98,  0x26,  0x95,  0x4A,  0x88,  0x75,  0x00,  0x00,  0xA3,  0x64,  0x08,
+  0x00,  0x05,  0x4E,  0x88,  0x73,  0x04,  0x00,  0x63,  0x80,  0x7B,  0x80,  0x63,  0x06,  0xA6,  0x76,  0x08,
+  0x00,  0x33,  0x3E,  0x00,  0xC0,  0x88,  0x80,  0x67,  0x83,  0x03,  0x80,  0x63,  0x00,  0x63,  0x38,  0x2B,
+  0x9C,  0x88,  0x38,  0x2B,  0x92,  0x88,  0x32,  0x09,  0x31,  0x05,  0x92,  0x98,  0x05,  0x05,  0xB2,  0x09,
+  0x00,  0x63,  0x00,  0x32,  0x00,  0x36,  0x00,  0x3A,  0x00,  0x3E,  0x00,  0x63,  0x80,  0x32,  0x80,  0x36,
+  0x80,  0x3A,  0x80,  0x3E,  0x00,  0x63,  0x38,  0x2B,  0x40,  0x32,  0x40,  0x36,  0x40,  0x3A,  0x40,  0x3E,
+  0x00,  0x63,  0x5A,  0x20,  0xC9,  0x40,  0x00,  0xA0,  0xB2,  0x08,  0x5D,  0x00,  0xFE,  0xC3,  0x00,  0x63,
+  0x80,  0x73,  0xE6,  0x20,  0x02,  0x23,  0xE8,  0x00,  0x82,  0x73,  0xFF,  0xFD,  0x80,  0x73,  0x13,  0x23,
+  0xF6,  0x88,  0x66,  0x20,  0xC0,  0x20,  0x04,  0x23,  0xA0,  0x01,  0xA1,  0x23,  0xA1,  0x01,  0x81,  0x62,
+  0xE0,  0x88,  0x80,  0x73,  0x80,  0x77,  0x68,  0x00,  0x00,  0xA2,  0x80,  0x00,  0x03,  0xC2,  0xF1,  0xC7,
+  0x41,  0x23,  0xF6,  0x88,  0x11,  0x23,  0xA1,  0x01,  0x04,  0x23,  0xA0,  0x01,  0xE6,  0x84,
 };
 
 STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf);
-STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012A727FUL ;
+STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012B5442UL;
 
 #define ASC_SYN_OFFSET_ONE_DISABLE_LIST  16
 STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] =
@@ -12190,7 +12343,7 @@
         if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) {
             break;
         }
-        DvcSleepMilliSecond(100L);
+        DvcSleepMilliSecond(1000L);
         if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) {
             break;
         }
@@ -12808,11 +12961,12 @@
     asc_dvc->cfg->can_tagged_qng = 0 ;
     asc_dvc->cfg->cmd_qng_enabled = 0;
     asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
-    asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET;
+    asc_dvc->init_sdtr = 0;
     asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
     asc_dvc->scsi_reset_wait = 3;
     asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
     asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
+    asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET;
     asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
     asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
     asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
@@ -12967,7 +13121,7 @@
                 warn_code |= ASC_WARN_EEPROM_CHKSUM ;
             }
     }
-    asc_dvc->init_sdtr = eep_config->init_sdtr;
+    asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr ;
     asc_dvc->cfg->disc_enable = eep_config->disc_enable;
     asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng;
     asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed;
@@ -13085,47 +13239,6 @@
     return (warn_code);
 }
 
-STATIC void
-AscInitPollIsrCallBack(
-                          ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                          ASC_QDONE_INFO * scsi_done_q
-)
-{
-    ASC_SCSI_REQ_Q *scsiq_req;
-    ASC_ISR_CALLBACK    asc_isr_callback;
-    uchar               cp_sen_len;
-    uchar               i;
-
-    ASC_DBG(1, "AscInitPollIsrCallBack: begin\n");
-    if ((scsi_done_q->d2.flag & ASC_FLAG_SCSIQ_REQ) != 0) {
-        scsiq_req = (ASC_SCSI_REQ_Q *) scsi_done_q->d2.srb_ptr;
-        scsiq_req->r3.done_stat = scsi_done_q->d3.done_stat;
-        scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
-        scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
-        scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
-        ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n",
-            scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat,
-            scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg);
-        if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
-            (scsi_done_q->d3.host_stat == 0)) {
-            cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
-            if (scsiq_req->r1.sense_len < ASC_MIN_SENSE_LEN) {
-                cp_sen_len = (uchar) scsiq_req->r1.sense_len;
-            }
-            for (i = 0; i < cp_sen_len; i++) {
-                scsiq_req->sense[i] = scsiq_req->sense_ptr[i];
-            }
-        }
-    } else {
-        if (asc_dvc->isr_callback != 0) {
-            asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback;
-            (*asc_isr_callback) (asc_dvc, scsi_done_q);
-        }
-    }
-    ASC_DBG(1, "AscInitPollIsrCallBack: end\n");
-    return;
-}
-
 ASC_INITFUNC(
 STATIC int
 AscTestExternalLram(
@@ -13395,413 +13508,124 @@
     return (n_error);
 }
 
-STATIC int
-AscInitPollBegin(
-                    REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    PortAddr            iop_base;
-
-    iop_base = asc_dvc->iop_base;
-    AscDisableInterrupt(iop_base);
-    asc_dvc->init_state |= ASC_INIT_STATE_BEG_INQUIRY;
-    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, 0x00);
-    asc_dvc->use_tagged_qng = 0;
-    asc_dvc->cfg->can_tagged_qng = 0;
-    asc_dvc->saved_ptr2func = (ulong) asc_dvc->isr_callback;
-    asc_dvc->isr_callback = ASC_GET_PTR2FUNC(AscInitPollIsrCallBack);
-    return (0);
-}
-
-STATIC int
-AscInitPollEnd(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
-{
-    PortAddr            iop_base;
-    rint                i;
-
-    iop_base = asc_dvc->iop_base;
-    asc_dvc->isr_callback = (Ptr2Func) asc_dvc->saved_ptr2func;
-    AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B,
-                     asc_dvc->cfg->disc_enable);
-    AscWriteLramByte(iop_base, ASCV_USE_TAGGED_QNG_B,
-                     asc_dvc->use_tagged_qng);
-    AscWriteLramByte(iop_base, ASCV_CAN_TAGGED_QNG_B,
-                     asc_dvc->cfg->can_tagged_qng);
-    for (i = 0; i <= ASC_MAX_TID; i++) {
-        AscWriteLramByte(iop_base,
-                      (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) i),
-                         asc_dvc->max_dvc_qng[i]);
-    }
-    AscAckInterrupt(iop_base);
-    AscEnableInterrupt(iop_base);
-    asc_dvc->init_state |= ASC_INIT_STATE_END_INQUIRY;
-    return (0);
-}
-
-STATIC int
-AscInitPollTarget(
-                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     REG ASC_SCSI_REQ_Q * scsiq,
-                     REG ASC_SCSI_INQUIRY * inq,
-                     REG ASC_CAP_INFO * cap_info
-)
+STATIC void
+AscAsyncFix(
+               ASC_DVC_VAR asc_ptr_type *asc_dvc,
+               uchar tid_no,
+               ASC_SCSI_INQUIRY *inq)
 {
-    uchar               tid_no, lun;
-    uchar               dvc_type;
+    uchar                dvc_type;
     ASC_SCSI_BIT_ID_TYPE tid_bits;
-    int                 dvc_found;
-    int                 support_read_cap;
-    int                 tmp_disable_init_sdtr;
-    int                 sta;
 
-    dvc_found = 0;
-    tmp_disable_init_sdtr = FALSE;
-    tid_bits = scsiq->r1.target_id;
-    lun = scsiq->r1.target_lun;
-    tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
-    if (((asc_dvc->init_sdtr & tid_bits) != 0) &&
-        ((asc_dvc->sdtr_done & tid_bits) == 0)) {
-        asc_dvc->init_sdtr &= ~tid_bits;
-        tmp_disable_init_sdtr = TRUE;
-    }
-    ASC_DBG(1, "AscInitPollTarget: before PollScsiInquiry\n");
-    if (PollScsiInquiry(asc_dvc, scsiq, (uchar *) inq,
-        sizeof (ASC_SCSI_INQUIRY)) == 1) {
-        dvc_found = 1;
-        dvc_type = inq->byte0.peri_dvc_type;
-        if (dvc_type != SCSI_TYPE_UNKNOWN) {
-            support_read_cap = TRUE;
-            if ((dvc_type != SCSI_TYPE_DASD)
-                && (dvc_type != SCSI_TYPE_WORM)
-                && (dvc_type != SCSI_TYPE_CDROM)
-                && (dvc_type != SCSI_TYPE_OPTMEM)) {
-                asc_dvc->start_motor &= ~tid_bits;
-                support_read_cap = FALSE;
-            }
-            if (lun == 0) {
-                if ((inq->byte3.rsp_data_fmt >= 2) ||
-                    (inq->byte2.ansi_apr_ver >= 2)) {
-                    if (inq->byte7.CmdQue) {
-                        asc_dvc->cfg->can_tagged_qng |= tid_bits;
-                        if (asc_dvc->cfg->cmd_qng_enabled & tid_bits) {
-                                asc_dvc->use_tagged_qng |= tid_bits;
-                                asc_dvc->max_dvc_qng[tid_no] = asc_dvc->cfg->max_tag_qng[tid_no];
-                        }
-                    }
-                    if (!inq->byte7.Sync) {
-                        asc_dvc->init_sdtr &= ~tid_bits;
-                        asc_dvc->sdtr_done &= ~tid_bits;
-                    } else if (tmp_disable_init_sdtr) {
-                        asc_dvc->init_sdtr |= tid_bits;
-                    }
-                } else {
-                    asc_dvc->init_sdtr &= ~tid_bits;
-                    asc_dvc->sdtr_done &= ~tid_bits;
-                    asc_dvc->use_tagged_qng &= ~tid_bits;
-                }
-            }
-            if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
-                if (!(asc_dvc->init_sdtr & tid_bits)) {
-                    if ((dvc_type == SCSI_TYPE_CDROM) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                            (uchar *) "HP ", 3) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
-                    }
-                    asc_dvc->pci_fix_asyn_xfer |= tid_bits;
-                    if ((dvc_type == SCSI_TYPE_PROC) || (dvc_type == SCSI_TYPE_SCANNER)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                    }
-                    if ((dvc_type == SCSI_TYPE_SASD) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                            (uchar *) "TANDBERG", 8) == 0) &&
-                        (AscCompareString((uchar *) inq->product_id,
-                         (uchar *) " TDC 36", 7) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                    }
-                    if ((dvc_type == SCSI_TYPE_SASD) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                         (uchar *) "WANGTEK ", 8) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
-                    }
+    dvc_type = inq->byte0.peri_dvc_type;
+    tid_bits = ASC_TIX_TO_TARGET_ID(tid_no);
 
-                    if ((dvc_type == SCSI_TYPE_CDROM) &&
-                       (AscCompareString((uchar *)inq->vendor_id,
-                        (uchar *)"NEC     ", 8) == 0) &&
-                        (AscCompareString((uchar *)inq->product_id,
-                         (uchar *)"CD-ROM DRIVE    ", 16) == 0)) {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ;
-                    }
-                    if ((dvc_type == SCSI_TYPE_CDROM) &&
-                        (AscCompareString((uchar *) inq->vendor_id,
-                         (uchar *) "YAMAHA", 6) == 0)  &&
-                        (AscCompareString((uchar *) inq->product_id,
-                         (uchar *) "CDR400", 6) == 0))
-                    {
-                        asc_dvc->pci_fix_asyn_xfer &= ~tid_bits ;
-                    }
- 
-                    if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
-                        AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
-                                                ASYN_SDTR_DATA_FIX_PCI_REV_AB);
-                    }
-                }
-            }
-            sta = 1;
-            ASC_DBG(1, "AscInitPollTarget: before InitTestUnitReady\n");
-            sta = InitTestUnitReady(asc_dvc, scsiq);
-            if (sta == 1) {
-                if ((cap_info != 0L) && support_read_cap) {
-                    ASC_DBG(1,
-                        "AscInitPollTarget: before PollScsiReadCapacity\n");
-                    if (PollScsiReadCapacity(asc_dvc, scsiq,
-                                             cap_info) != 1) {
-                        cap_info->lba = 0L;
-                        cap_info->blk_size = 0x0000;
-                    } else {
-                    }
-                }
+    if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) {
+        if (!(asc_dvc->init_sdtr & tid_bits)) {
+            if ((dvc_type == SCSI_TYPE_CDROM) &&
+                (AscCompareString((uchar *) inq->vendor_id,
+                    (uchar *) "HP ", 3) == 0)) {
+                asc_dvc->pci_fix_asyn_xfer_always |= tid_bits;
+            }
+            asc_dvc->pci_fix_asyn_xfer |= tid_bits;
+            if ((dvc_type == SCSI_TYPE_PROC) ||
+                (dvc_type == SCSI_TYPE_SCANNER)) {
+                asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+            }
+            if ((dvc_type == SCSI_TYPE_SASD) &&
+                (AscCompareString((uchar *) inq->vendor_id,
+                 (uchar *) "TANDBERG", 8) == 0) &&
+                (AscCompareString((uchar *) inq->product_id,
+                 (uchar *) " TDC 36", 7) == 0)) {
+                asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+            }
+            if ((dvc_type == SCSI_TYPE_SASD) &&
+                (AscCompareString((uchar *) inq->vendor_id,
+                 (uchar *) "WANGTEK ", 8) == 0)) {
+                asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+            }
+
+            if ((dvc_type == SCSI_TYPE_CDROM) &&
+                (AscCompareString((uchar *) inq->vendor_id,
+                 (uchar *) "NEC     ", 8) == 0) &&
+                (AscCompareString((uchar *) inq->product_id,
+                 (uchar *) "CD-ROM DRIVE    ", 16) == 0)) {
+                asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+            }
+
+            if ((dvc_type == SCSI_TYPE_CDROM) &&
+                (AscCompareString((uchar *) inq->vendor_id,
+                 (uchar *) "YAMAHA", 6) == 0) &&
+                (AscCompareString((uchar *) inq->product_id,
+                 (uchar *) "CDR400", 6) == 0)) {
+                asc_dvc->pci_fix_asyn_xfer &= ~tid_bits;
+            }
+            if (asc_dvc->pci_fix_asyn_xfer & tid_bits) {
+                AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no,
+                                        ASYN_SDTR_DATA_FIX_PCI_REV_AB);
             }
-        } else {
-            asc_dvc->start_motor &= ~tid_bits;
         }
-    } else if (tmp_disable_init_sdtr) {
-        asc_dvc->init_sdtr |= tid_bits;
     }
-    ASC_DBG1(1, "AscInitPollTarget: dvc_found %d\n", dvc_found);
-    return (dvc_found);
-}
-
-STATIC int
-PollQueueDone(
-                 REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                 REG ASC_SCSI_REQ_Q * scsiq,
-                 int timeout_sec
-)
-{
-    int                 status;
-    int                 retry = 0;
-
-    ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec);
-    do {
-        ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n");
-        if ((status = AscExeScsiQueue(asc_dvc,
-                (ASC_SCSI_Q *) scsiq)) == 1) {
-            ASC_DBG(1, "PollQueueDone: before AscPollQDone\n");
-            if ((status = AscPollQDone(asc_dvc, scsiq,
-                                       timeout_sec)) != 1) {
-                ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-                if (status == 0x80) {
-                    if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
-                        break;
-                    }
-                    scsiq->r3.done_stat = 0;
-                    scsiq->r3.host_stat = 0;
-                    scsiq->r3.scsi_stat = 0;
-                    scsiq->r3.scsi_msg = 0;
-                    DvcSleepMilliSecond(1000);
-                    continue;
-                }
-                scsiq->r3.done_stat = 0;
-                scsiq->r3.host_stat = 0;
-                scsiq->r3.scsi_stat = 0;
-                scsiq->r3.scsi_msg = 0;
-                ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n");
-                AscAbortSRB(asc_dvc, (ulong) scsiq);
-            }
-            ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-            ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
-            return (scsiq->r3.done_stat);
-        }
-        ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-        DvcSleepMilliSecond(5);
-    } while (((status == 0) || (status == 0x80)) &&
-              retry++ < ASC_MAX_INIT_BUSY_RETRY);
-    ASC_DBG1(1, "PollQueueDone: status %x\n", status);
-    ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n");
-    return (scsiq->r3.done_stat = QD_WITH_ERROR);
-}
-
-STATIC int
-PollScsiInquiry(
-                   REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                   REG ASC_SCSI_REQ_Q * scsiq,
-                   uchar * buf,
-                   int buf_len
-)
-{
-    if (AscScsiInquiry(asc_dvc, scsiq, buf, buf_len) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 4));
-}
-
-STATIC int
-PollScsiStartUnit(
-                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    if (AscScsiStartStopUnit(asc_dvc, scsiq, 1) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 40));
+    return;
 }
 
 STATIC int
-PollScsiReadCapacity(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        REG ASC_SCSI_REQ_Q * scsiq,
-                        REG ASC_CAP_INFO * cap_info
-)
+AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq)
 {
-    ASC_CAP_INFO        scsi_cap_info;
-    int                 status;
-
-    if (AscScsiReadCapacity(asc_dvc, scsiq,
-                            (uchar *) & scsi_cap_info) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    status = PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 8);
-    if (status == 1) {
-        cap_info->lba = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.lba);
-        cap_info->blk_size = (ulong) * swapfarbuf4((uchar *) & scsi_cap_info.blk_size);
-        return (scsiq->r3.done_stat);
+    if ((inq->add_len >= 32) &&
+        (AscCompareString((uchar *) inq->vendor_id,
+            (uchar *) "QUANTUM XP34301", 15) == 0) &&
+        (AscCompareString((uchar *) inq->product_rev_level,
+            (uchar *) "1071", 4) == 0))
+    {
+        return 0;
     }
-    return (scsiq->r3.done_stat = QD_WITH_ERROR);
-}
-
-STATIC ulong *
-swapfarbuf4(
-    uchar *buf
-)
-{
-    uchar      tmp;
-
-    tmp = buf[3];
-    buf[3] = buf[0];
-    buf[0] = tmp;
-
-    tmp = buf[1];
-    buf[1] = buf[2];
-    buf[2] = tmp;
-
-    return ((ulong *) buf);
+    return 1;
 }
 
-STATIC int
-PollScsiTestUnitReady(
-                         REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                         REG ASC_SCSI_REQ_Q * scsiq
-)
+STATIC void
+AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc,
+                   uchar tid_no, ASC_SCSI_INQUIRY *inq)
 {
-    if (AscScsiTestUnitReady(asc_dvc, scsiq) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    return (PollQueueDone(asc_dvc, (ASC_SCSI_REQ_Q *) scsiq, 12));
-}
+    ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no);
+    ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng;
 
-STATIC int
-InitTestUnitReady(
-                     REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                     REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    ASC_SCSI_BIT_ID_TYPE tid_bits;
-    int                 retry;
-    ASC_REQ_SENSE *sen;
+    orig_init_sdtr = asc_dvc->init_sdtr;
+    orig_use_tagged_qng = asc_dvc->use_tagged_qng;
 
-    retry = 0;
-    tid_bits = scsiq->r1.target_id;
-    while (retry++ < 4) {
-        PollScsiTestUnitReady(asc_dvc, scsiq);
-        if (scsiq->r3.done_stat == 0x01) {
-            return (1);
-        } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
-            sen = (ASC_REQ_SENSE *) scsiq->sense_ptr;
-            if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
-                ((sen->err_code & 0x70) != 0)) {
-                if (sen->sense_key == SCSI_SENKEY_NOT_READY) {
-                    if (sen->asc == SCSI_ASC_NOMEDIA)
-                    {
-                        break;
-                    }
-                    if (asc_dvc->start_motor & tid_bits) {
-                        if (PollScsiStartUnit(asc_dvc, scsiq) == 1) {
-                            DvcSleepMilliSecond(250);
-                            continue;
-                        } else {
-                            asc_dvc->start_motor &= ~tid_bits;
-                            break;
-                        }
-                    } else {
-                        DvcSleepMilliSecond(250);
-                    }
-                } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) {
-                    DvcSleepMilliSecond(250);
-                } else {
-                    break;
-                }
-            } else {
-                break;
+    asc_dvc->init_sdtr &= ~tid_bit;
+    asc_dvc->cfg->can_tagged_qng &= ~tid_bit;
+    asc_dvc->use_tagged_qng &= ~tid_bit;
+
+    if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) {
+        if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) {
+            asc_dvc->init_sdtr |= tid_bit;
+        }
+        if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) {
+            if (AscTagQueuingSafe(inq)) {
+                asc_dvc->use_tagged_qng |= tid_bit;
+                asc_dvc->cfg->can_tagged_qng |= tid_bit;
             }
-        } else if (scsiq->r3.done_stat == QD_ABORTED_BY_HOST) {
-            break;
-        } else {
-            break;
         }
     }
-    return (0);
-}
-
-STATIC int
-AscPollQDone(
-                REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                REG ASC_SCSI_REQ_Q * scsiq,
-                int timeout_sec
-)
-{
-    int                 loop, loop_end;
-    int                 sta;
-    PortAddr            iop_base;
-
-    iop_base = asc_dvc->iop_base;
-    loop = 0;
-    loop_end = timeout_sec * 100;
-    sta = 1;
-    while (TRUE) {
-        if (asc_dvc->err_code != 0) {
-            scsiq->r3.done_stat = QD_WITH_ERROR;
-            ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code);
-            sta = ERR;
-            break;
-        }
-        if (scsiq->r3.done_stat != QD_IN_PROGRESS) {
-            if ((scsiq->r3.done_stat == QD_WITH_ERROR) &&
-                (scsiq->r3.scsi_stat == SS_TARGET_BUSY)) {
-                sta = 0x80;
-            }
-            break;
-        }
-        DvcSleepMilliSecond(10);
-        if (loop++ > loop_end) {
-            ASC_DBG(1, "AscPollQDone: loop finished\n");
-            sta = 0;
-            break;
-        }
-        if (AscIsChipHalted(iop_base)) {
-            ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n");
-            AscISR(asc_dvc);
-            loop = 0;
-        } else {
-            if (AscIsIntPending(iop_base)) {
-                ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n");
-                AscISR(asc_dvc);
-            }
-        }
+    if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) {
+        AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B,
+                         asc_dvc->cfg->disc_enable);
+        AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B,
+                         asc_dvc->use_tagged_qng);
+        AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B,
+                         asc_dvc->cfg->can_tagged_qng);
+
+        asc_dvc->max_dvc_qng[tid_no] =
+          asc_dvc->cfg->max_tag_qng[tid_no];
+        AscWriteLramByte(asc_dvc->iop_base,
+                         (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no),
+                         asc_dvc->max_dvc_qng[tid_no]);
     }
-    return (sta);
+    if (orig_init_sdtr != asc_dvc->init_sdtr) {
+        AscAsyncFix(asc_dvc, tid_no, inq);
+    }
+    return;
 }
 
 STATIC int
@@ -13998,105 +13822,16 @@
 }
 
 
-STATIC int
-AscScsiInquiry(
-                  REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                  REG ASC_SCSI_REQ_Q * scsiq,
-                  uchar * buf,
-                  int buf_len
-)
-{
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, buf,
-                         (ulong) buf_len) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    scsiq->cdb[0] = (uchar) SCSICMD_Inquiry;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = buf_len;
-    scsiq->cdb[5] = 0;
-    scsiq->r2.cdb_len = 6;
-    return (0);
-}
-
-STATIC int
-AscScsiReadCapacity(
-                       REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                       REG ASC_SCSI_REQ_Q * scsiq,
-                       uchar * info
-)
-{
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, info, 8L) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    scsiq->cdb[0] = (uchar) SCSICMD_ReadCapacity;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = 0;
-    scsiq->cdb[5] = 0;
-    scsiq->cdb[6] = 0;
-    scsiq->cdb[7] = 0;
-    scsiq->cdb[8] = 0;
-    scsiq->cdb[9] = 0;
-    scsiq->r2.cdb_len = 10;
-    return (0);
-}
-
-STATIC int
-AscScsiTestUnitReady(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        REG ASC_SCSI_REQ_Q * scsiq
-)
-{
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR,
-                         (ulong) 0L) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
-    scsiq->cdb[0] = (uchar) SCSICMD_TestUnitReady;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = 0;
-    scsiq->cdb[5] = 0;
-    scsiq->r2.cdb_len = 6;
-    return (0);
-}
-
-STATIC int
-AscScsiStartStopUnit(
-                        REG ASC_DVC_VAR asc_ptr_type * asc_dvc,
-                        REG ASC_SCSI_REQ_Q * scsiq,
-                        uchar op_mode
-)
-{
-    if (AscScsiSetupCmdQ(asc_dvc, scsiq, FNULLPTR, (ulong) 0L) == ERR) {
-        return (scsiq->r3.done_stat = QD_WITH_ERROR);
-    }
-    scsiq->r1.cntl = (uchar) ASC_SCSIDIR_NODATA;
-    scsiq->cdb[0] = (uchar) SCSICMD_StartStopUnit;
-    scsiq->cdb[1] = scsiq->r1.target_lun << 5;
-    scsiq->cdb[2] = 0;
-    scsiq->cdb[3] = 0;
-    scsiq->cdb[4] = op_mode;
-    scsiq->cdb[5] = 0;
-    scsiq->r2.cdb_len = 6;
-    return (0);
-}
-
-
 /*
  * --- Adv Library Functions
  */
 
 /* a_qswap.h */
 STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = {
-  0x9C,  0xF0,  0x80,  0x01,  0x00,  0xF0,  0x40,  0x0A,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x9C,  0xF0,  0x80,  0x01,  0x00,  0xF0,  0x44,  0x0A,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
-  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x72,  0x01,  0xD2,  0x11,  0x00,  0x00,  0x70,  0x01,
-  0x30,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x88,  0x0F,  0x22,  0x03,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x72,  0x01,  0xD6,  0x11,  0x00,  0x00,  0x70,  0x01,
+  0x30,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x90,  0x10,  0x2D,  0x03,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
@@ -14116,273 +13851,274 @@
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
-  0x00,  0x00,  0x04,  0xF7,  0x70,  0x01,  0x0C,  0x1C,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF2,  0xD2,  0x0A,
+  0x00,  0x00,  0x04,  0xF7,  0x70,  0x01,  0x0C,  0x1C,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF2,  0xD6,  0x0A,
   0x04,  0xF7,  0x70,  0x01,  0x06,  0xF7,  0x02,  0x00,  0x3E,  0x57,  0x3C,  0x56,  0x0C,  0x1C,  0x00,  0xFC,
-  0xA6,  0x00,  0x01,  0x58,  0xAA,  0x13,  0x20,  0xF0,  0x9A,  0x03,  0x06,  0xEC,  0xB9,  0x00,  0x0E,  0x47,
+  0xA6,  0x00,  0x01,  0x58,  0xAA,  0x13,  0x20,  0xF0,  0xA6,  0x03,  0x06,  0xEC,  0xB9,  0x00,  0x0E,  0x47,
   0x03,  0xE6,  0x10,  0x00,  0xCE,  0x45,  0x02,  0x13,  0x3E,  0x57,  0x06,  0xEA,  0xB9,  0x00,  0x47,  0x4B,
-  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x4E,  0x12,  0x03,  0xF6,  0xC0,  0x00,
-  0x00,  0xF2,  0x64,  0x0A,  0x41,  0x58,  0x03,  0xF6,  0xD0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x49,  0x44,
-  0x59,  0xF0,  0x0A,  0x02,  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x44,  0x58,  0x00,  0xF2,
-  0xDE,  0x0D,  0x02,  0xCC,  0x4A,  0xE4,  0x01,  0x00,  0x55,  0xF0,  0x08,  0x03,  0x45,  0xF4,  0x02,  0x00,
-  0x83,  0x5A,  0x04,  0xCC,  0x01,  0x4A,  0x12,  0x12,  0x00,  0xF2,  0xDE,  0x0D,  0x00,  0xCD,  0x48,  0xE4,
-  0x01,  0x00,  0xE9,  0x13,  0x00,  0xF2,  0xC2,  0x0F,  0xFA,  0x10,  0x0E,  0x47,  0x03,  0xE6,  0x10,  0x00,
+  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x01,  0x48,  0x4E,  0x12,  0x03,  0xF6,  0xC0,  0x00,
+  0x00,  0xF2,  0x68,  0x0A,  0x41,  0x58,  0x03,  0xF6,  0xD0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x49,  0x44,
+  0x59,  0xF0,  0x0A,  0x02,  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x44,  0x58,  0x00,  0xF2,
+  0xE2,  0x0D,  0x02,  0xCC,  0x4A,  0xE4,  0x01,  0x00,  0x55,  0xF0,  0x08,  0x03,  0x45,  0xF4,  0x02,  0x00,
+  0x83,  0x5A,  0x04,  0xCC,  0x01,  0x4A,  0x12,  0x12,  0x00,  0xF2,  0xE2,  0x0D,  0x00,  0xCD,  0x48,  0xE4,
+  0x01,  0x00,  0xE9,  0x13,  0x00,  0xF2,  0xC6,  0x0F,  0xFA,  0x10,  0x0E,  0x47,  0x03,  0xE6,  0x10,  0x00,
   0xCE,  0x45,  0x02,  0x13,  0x3E,  0x57,  0xCE,  0x47,  0x97,  0x13,  0x04,  0xEC,  0xB4,  0x00,  0x00,  0xF2,
-  0xDE,  0x0D,  0x00,  0xCD,  0x48,  0xE4,  0x00,  0x00,  0x12,  0x12,  0x3E,  0x57,  0x06,  0xCC,  0x45,  0xF4,
+  0xE2,  0x0D,  0x00,  0xCD,  0x48,  0xE4,  0x00,  0x00,  0x12,  0x12,  0x3E,  0x57,  0x06,  0xCC,  0x45,  0xF4,
   0x02,  0x00,  0x83,  0x5A,  0x00,  0xCC,  0x00,  0xEA,  0xB4,  0x00,  0x92,  0x10,  0x00,  0xF0,  0x8C,  0x01,
   0x43,  0xF0,  0x5C,  0x02,  0x44,  0xF0,  0x60,  0x02,  0x45,  0xF0,  0x64,  0x02,  0x46,  0xF0,  0x68,  0x02,
   0x47,  0xF0,  0x6E,  0x02,  0x48,  0xF0,  0x9E,  0x02,  0xB9,  0x54,  0x62,  0x10,  0x00,  0x1C,  0x5A,  0x10,
-  0x02,  0x1C,  0x56,  0x10,  0x1E,  0x1C,  0x52,  0x10,  0x00,  0xF2,  0x1A,  0x11,  0x50,  0x10,  0x06,  0xFC,
-  0xA8,  0x00,  0x03,  0xF6,  0xBE,  0x00,  0x00,  0xF2,  0x4A,  0x0A,  0x8C,  0x10,  0x01,  0xF6,  0x01,  0x00,
-  0x01,  0xFA,  0xA8,  0x00,  0x00,  0xF2,  0x28,  0x0B,  0x06,  0x10,  0xB9,  0x54,  0x01,  0xFA,  0xA8,  0x00,
-  0x03,  0xF6,  0xBE,  0x00,  0x00,  0xF2,  0x54,  0x0A,  0x01,  0xFC,  0xA8,  0x00,  0x20,  0x10,  0x58,  0x1C,
-  0x00,  0xF2,  0x18,  0x0B,  0x5A,  0x1C,  0x01,  0xF6,  0x01,  0x00,  0x38,  0x54,  0x00,  0xFA,  0xA6,  0x00,
+  0x02,  0x1C,  0x56,  0x10,  0x1E,  0x1C,  0x52,  0x10,  0x00,  0xF2,  0x1E,  0x11,  0x50,  0x10,  0x06,  0xFC,
+  0xA8,  0x00,  0x03,  0xF6,  0xBE,  0x00,  0x00,  0xF2,  0x4E,  0x0A,  0x8C,  0x10,  0x01,  0xF6,  0x01,  0x00,
+  0x01,  0xFA,  0xA8,  0x00,  0x00,  0xF2,  0x2C,  0x0B,  0x06,  0x10,  0xB9,  0x54,  0x01,  0xFA,  0xA8,  0x00,
+  0x03,  0xF6,  0xBE,  0x00,  0x00,  0xF2,  0x58,  0x0A,  0x01,  0xFC,  0xA8,  0x00,  0x20,  0x10,  0x58,  0x1C,
+  0x00,  0xF2,  0x1C,  0x0B,  0x5A,  0x1C,  0x01,  0xF6,  0x01,  0x00,  0x38,  0x54,  0x00,  0xFA,  0xA6,  0x00,
   0x01,  0xFA,  0xA8,  0x00,  0x20,  0x1C,  0x00,  0xF0,  0x72,  0x01,  0x01,  0xF6,  0x01,  0x00,  0x38,  0x54,
   0x00,  0xFA,  0xA6,  0x00,  0x01,  0xFA,  0xA8,  0x00,  0x20,  0x1C,  0x00,  0xF0,  0x80,  0x01,  0x03,  0xF6,
-  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x0A,  0x13,  0x00,  0xF2,  0x34,  0x10,  0x00,  0xF2,
-  0x50,  0x0F,  0x24,  0x10,  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x02,  0xF6,  0xD0,  0x00,
-  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x49,  0x44,  0x5B,  0xF0,  0x04,  0x03,  0x00,  0xF2,  0x98,  0x0F,
-  0x00,  0xF0,  0x80,  0x01,  0x00,  0xF2,  0x10,  0x10,  0x0C,  0x1C,  0x02,  0x4B,  0xBF,  0x57,  0x9E,  0x43,
-  0x77,  0x57,  0x07,  0x4B,  0x20,  0xF0,  0x9A,  0x03,  0x40,  0x1C,  0x1E,  0xF0,  0x30,  0x03,  0x26,  0xF0,
-  0x2C,  0x03,  0xA0,  0xF0,  0x1A,  0x03,  0x11,  0xF0,  0x9A,  0x03,  0x12,  0x10,  0x9F,  0xF0,  0x3E,  0x03,
-  0x46,  0x1C,  0x82,  0xE7,  0x05,  0x00,  0x9E,  0xE7,  0x11,  0x00,  0x00,  0xF0,  0x02,  0x0A,  0x0C,  0x1C,
+  0xE0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x01,  0x48,  0x0A,  0x13,  0x00,  0xF2,  0x38,  0x10,  0x00,  0xF2,
+  0x54,  0x0F,  0x24,  0x10,  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x02,  0xF6,  0xD0,  0x00,
+  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x49,  0x44,  0x5B,  0xF0,  0x04,  0x03,  0x00,  0xF2,  0x9C,  0x0F,
+  0x00,  0xF0,  0x80,  0x01,  0x00,  0xF2,  0x14,  0x10,  0x0C,  0x1C,  0x02,  0x4B,  0xBF,  0x57,  0x9E,  0x43,
+  0x77,  0x57,  0x07,  0x4B,  0x20,  0xF0,  0xA6,  0x03,  0x40,  0x1C,  0x1E,  0xF0,  0x30,  0x03,  0x26,  0xF0,
+  0x2C,  0x03,  0xA0,  0xF0,  0x1A,  0x03,  0x11,  0xF0,  0xA6,  0x03,  0x12,  0x10,  0x9F,  0xF0,  0x3E,  0x03,
+  0x46,  0x1C,  0x82,  0xE7,  0x05,  0x00,  0x9E,  0xE7,  0x11,  0x00,  0x00,  0xF0,  0x06,  0x0A,  0x0C,  0x1C,
   0x48,  0x1C,  0x46,  0x1C,  0x38,  0x54,  0x00,  0xEC,  0xBA,  0x00,  0x08,  0x44,  0x00,  0xEA,  0xBA,  0x00,
-  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x08,  0x44,  0x00,  0x4C,  0x82,  0xE7,  0x02,  0x00,
-  0x00,  0xF2,  0x0E,  0x11,  0x00,  0xF2,  0x0E,  0x11,  0x06,  0xF0,  0x74,  0x03,  0x1E,  0xF0,  0xF8,  0x09,
-  0x00,  0xF0,  0xFE,  0x09,  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0x55,  0xF0,  0xA0,  0x04,  0x01,  0xE6,
-  0x0C,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,
-  0xC4,  0x11,  0x01,  0xF0,  0x7C,  0x02,  0x00,  0xF0,  0x8A,  0x02,  0x46,  0x1C,  0x0C,  0x1C,  0x67,  0x1B,
-  0xBF,  0x57,  0x77,  0x57,  0x02,  0x4B,  0x48,  0x1C,  0x32,  0x1C,  0x00,  0xF2,  0x8E,  0x0D,  0x30,  0x1C,
-  0x96,  0xF0,  0xB0,  0x03,  0xB1,  0xF0,  0xB4,  0x03,  0x1E,  0xF0,  0xF8,  0x09,  0x85,  0xF0,  0xFE,  0x09,
-  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0x14,  0x12,  0x01,  0xE6,  0x0C,  0x00,  0x00,  0xF2,  0x4A,  0x0D,
-  0x00,  0xF2,  0x0E,  0x11,  0x01,  0xF0,  0x7C,  0x02,  0x00,  0xF0,  0x8A,  0x02,  0x03,  0xF6,  0xE0,  0x00,
-  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x55,  0xF0,  0x8C,  0x04,  0x03,  0x82,  0x03,  0xFC,  0xA0,  0x00,
-  0x9B,  0x57,  0x40,  0x12,  0x69,  0x18,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0x36,  0x04,  0x69,  0x08,
-  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0xFE,  0x09,  0x68,  0x08,  0x4C,  0x44,  0x28,  0x12,  0x44,  0x48,
-  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x45,  0x58,  0x00,  0xF2,  0xF2,  0x0D,  0x00,  0xCC,
-  0x01,  0x48,  0x55,  0xF0,  0x8C,  0x04,  0x4C,  0x44,  0xEF,  0x13,  0x00,  0xF2,  0xC2,  0x0F,  0x00,  0xF2,
-  0x10,  0x10,  0x08,  0x10,  0x68,  0x18,  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,  0x04,  0x80,  0x18,  0xE4,
-  0x10,  0x00,  0x28,  0x12,  0x01,  0xE6,  0x06,  0x00,  0x04,  0x80,  0x18,  0xE4,  0x01,  0x00,  0x04,  0x12,
-  0x01,  0xE6,  0x0D,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x04,  0xE6,  0x02,  0x00,
-  0x9E,  0xE7,  0x15,  0x00,  0x01,  0xF0,  0x18,  0x0A,  0x00,  0xF0,  0xFE,  0x09,  0x69,  0x08,  0x05,  0x80,
-  0x48,  0xE4,  0x00,  0x00,  0x0C,  0x12,  0x00,  0xE6,  0x11,  0x00,  0x00,  0xEA,  0xB8,  0x00,  0x00,  0xF2,
-  0xB2,  0x10,  0x82,  0xE7,  0x02,  0x00,  0x1C,  0x90,  0x40,  0x5C,  0x00,  0x16,  0x01,  0xE6,  0x06,  0x00,
-  0x00,  0xF2,  0x4A,  0x0D,  0x01,  0xF0,  0x80,  0x01,  0x1E,  0xF0,  0x80,  0x01,  0x00,  0xF0,  0x94,  0x04,
-  0x42,  0x5B,  0x06,  0xF7,  0x03,  0x00,  0x46,  0x59,  0xBF,  0x57,  0x77,  0x57,  0x01,  0xE6,  0x80,  0x00,
-  0x07,  0x80,  0x31,  0x44,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x5E,  0x13,  0x20,  0x80,  0x48,  0xE4,
-  0x03,  0x00,  0x56,  0x12,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x4C,  0x13,  0x00,  0xFC,  0xA2,  0x00,
-  0x98,  0x57,  0x55,  0xF0,  0x18,  0x05,  0x31,  0xE4,  0x40,  0x00,  0x00,  0xFC,  0xA0,  0x00,  0x98,  0x57,
-  0x36,  0x12,  0x4C,  0x1C,  0x00,  0xF2,  0x0E,  0x11,  0x89,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,
-  0x2A,  0x05,  0x82,  0xE7,  0x06,  0x00,  0x1B,  0x80,  0x48,  0xE4,  0x22,  0x00,  0x5B,  0xF0,  0x08,  0x05,
-  0x48,  0xE4,  0x20,  0x00,  0x59,  0xF0,  0x0C,  0x05,  0x00,  0xE6,  0x20,  0x00,  0x09,  0x48,  0x00,  0xF2,
-  0x0E,  0x11,  0x86,  0xF0,  0x2A,  0x05,  0x83,  0x80,  0x04,  0x10,  0x00,  0xF2,  0x9E,  0x0D,  0x00,  0xE6,
-  0x01,  0x00,  0x00,  0xEA,  0x26,  0x01,  0x01,  0xEA,  0x27,  0x01,  0x04,  0x80,  0x18,  0xE4,  0x10,  0x00,
-  0x36,  0x12,  0xB9,  0x54,  0x00,  0xF2,  0xF2,  0x0E,  0x01,  0xE6,  0x06,  0x00,  0x04,  0x80,  0x18,  0xE4,
-  0x01,  0x00,  0x04,  0x12,  0x01,  0xE6,  0x0D,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,
-  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0x04,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,
-  0x01,  0xF0,  0x18,  0x0A,  0x00,  0xF0,  0xFE,  0x09,  0x00,  0xFC,  0x20,  0x01,  0x98,  0x57,  0x34,  0x12,
-  0x00,  0xFC,  0x24,  0x01,  0x98,  0x57,  0x2C,  0x13,  0xB9,  0x54,  0x00,  0xF2,  0xF2,  0x0E,  0x86,  0xF0,
-  0xA4,  0x05,  0x03,  0xF6,  0x01,  0x00,  0x00,  0xF2,  0x88,  0x0E,  0x85,  0xF0,  0x9A,  0x05,  0x82,  0xE7,
-  0x03,  0x00,  0x00,  0xF2,  0x5C,  0x0B,  0x82,  0xE7,  0x02,  0x00,  0x00,  0xFC,  0x24,  0x01,  0xB0,  0x57,
-  0x00,  0xFA,  0x24,  0x01,  0x00,  0xFC,  0x9E,  0x00,  0x98,  0x57,  0x5A,  0x12,  0x00,  0xFC,  0xB6,  0x00,
-  0x98,  0x57,  0x52,  0x13,  0x03,  0xE6,  0x0C,  0x00,  0x00,  0xFC,  0x9C,  0x00,  0x98,  0x57,  0x04,  0x13,
-  0x03,  0xE6,  0x19,  0x00,  0x05,  0xE6,  0x08,  0x00,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,
-  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,  0x00,  0x80,  0x04,  0x13,  0x05,  0xE6,  0x0F,  0x00,  0xB9,  0x54,
-  0x00,  0xF2,  0xF2,  0x0E,  0x86,  0xF0,  0x06,  0x06,  0x00,  0xF2,  0xB6,  0x0E,  0x85,  0xF0,  0xFC,  0x05,
-  0x82,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x5C,  0x0B,  0x82,  0xE7,  0x02,  0x00,  0x00,  0xFC,  0xB6,  0x00,
-  0xB0,  0x57,  0x00,  0xFA,  0xB6,  0x00,  0x01,  0xF6,  0x01,  0x00,  0x00,  0xF2,  0xF2,  0x0E,  0x9C,  0x32,
-  0x4E,  0x1C,  0x32,  0x1C,  0x00,  0xF2,  0x8E,  0x0D,  0x30,  0x1C,  0x82,  0xE7,  0x04,  0x00,  0xB1,  0xF0,
-  0x1E,  0x06,  0x0A,  0xF0,  0x3A,  0x06,  0x05,  0xF0,  0xD2,  0x06,  0x06,  0xF0,  0xD8,  0x06,  0x09,  0xF0,
-  0x20,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0x00,  0xF0,  0xFE,  0x09,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,
-  0x30,  0x12,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x21,  0x80,  0x18,  0xE4,  0xE0,  0x00,
-  0x09,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,
-  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x99,  0xA4,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,
-  0x9A,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x34,  0x12,  0x09,  0xE7,  0x1B,  0x00,  0x00,  0xF2,
-  0x0E,  0x11,  0x21,  0x80,  0x18,  0xE4,  0xE0,  0x00,  0x09,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,
-  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,
-  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF0,  0x08,  0x09,  0xBB,  0x55,
-  0x9A,  0x81,  0x03,  0xF7,  0x20,  0x00,  0x09,  0x6F,  0x93,  0x45,  0x55,  0xF0,  0xDE,  0x06,  0xB1,  0xF0,
-  0xBE,  0x06,  0x0A,  0xF0,  0xB6,  0x06,  0x09,  0xF0,  0x20,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0x00,  0xF0,
-  0xFE,  0x09,  0x00,  0xF2,  0x5C,  0x0B,  0x47,  0x10,  0x09,  0xE7,  0x08,  0x00,  0x41,  0x10,  0x05,  0x80,
-  0x48,  0xE4,  0x00,  0x00,  0x1E,  0x12,  0x00,  0xE6,  0x11,  0x00,  0x00,  0xEA,  0xB8,  0x00,  0x00,  0xF2,
-  0xB2,  0x10,  0x2C,  0x90,  0xAE,  0x90,  0x08,  0x50,  0x8A,  0x50,  0x38,  0x54,  0x1F,  0x40,  0x00,  0xF2,
-  0xB0,  0x0D,  0x08,  0x10,  0x08,  0x90,  0x8A,  0x90,  0x30,  0x50,  0xB2,  0x50,  0x9C,  0x32,  0x0C,  0x92,
-  0x8E,  0x92,  0x38,  0x54,  0x04,  0x80,  0x30,  0xE4,  0x08,  0x00,  0x04,  0x40,  0x0C,  0x1C,  0x00,  0xF6,
-  0x03,  0x00,  0xB1,  0xF0,  0x22,  0x07,  0x9E,  0xF0,  0x36,  0x07,  0x01,  0x48,  0x55,  0xF0,  0xF8,  0x09,
-  0x0C,  0x1C,  0x10,  0x44,  0xED,  0x10,  0x0B,  0xF0,  0x5A,  0x07,  0x0C,  0xF0,  0x5E,  0x07,  0x05,  0xF0,
-  0x4E,  0x07,  0x06,  0xF0,  0x54,  0x07,  0x09,  0xF0,  0x20,  0x09,  0x00,  0xF0,  0xFE,  0x09,  0x00,  0xF2,
-  0x5C,  0x0B,  0xCF,  0x10,  0x09,  0xE7,  0x08,  0x00,  0xC9,  0x10,  0x2E,  0x1C,  0x02,  0x10,  0x2C,  0x1C,
-  0xAA,  0xF0,  0x60,  0x07,  0xAC,  0xF0,  0x6E,  0x07,  0x40,  0x10,  0x34,  0x1C,  0xF3,  0x10,  0xAD,  0xF0,
-  0x78,  0x07,  0xC8,  0x10,  0x36,  0x1C,  0xE9,  0x10,  0x2B,  0xF0,  0x7E,  0x08,  0x6B,  0x18,  0x18,  0xF4,
-  0x00,  0xFE,  0x20,  0x12,  0x01,  0x58,  0xD2,  0xF0,  0x7E,  0x08,  0x76,  0x18,  0x18,  0xF4,  0x03,  0x00,
-  0xEC,  0x12,  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0xE2,  0x12,  0x0B,  0xF0,  0x60,  0x07,
-  0x0C,  0xF0,  0x60,  0x07,  0x36,  0x1C,  0x34,  0x1C,  0xB7,  0x10,  0x38,  0x54,  0xB9,  0x54,  0x84,  0x80,
-  0x19,  0xE4,  0x20,  0x00,  0xB2,  0x13,  0x85,  0x80,  0x81,  0x48,  0x66,  0x12,  0x04,  0x80,  0x18,  0xE4,
-  0x08,  0x00,  0x58,  0x13,  0x1F,  0x80,  0x08,  0x44,  0xC8,  0x44,  0x9F,  0x12,  0x1F,  0x40,  0x34,  0x91,
-  0xB6,  0x91,  0x44,  0x55,  0xE5,  0x55,  0x02,  0xEC,  0xB8,  0x00,  0x02,  0x49,  0xBB,  0x55,  0x82,  0x81,
-  0xC0,  0x55,  0x48,  0xF4,  0x0F,  0x00,  0x5A,  0xF0,  0x16,  0x08,  0x4A,  0xE4,  0x17,  0x00,  0xD5,  0xF0,
-  0xF6,  0x07,  0x02,  0xF6,  0x0F,  0x00,  0x02,  0xF4,  0x02,  0x00,  0x02,  0xEA,  0xB8,  0x00,  0x04,  0x91,
-  0x86,  0x91,  0x02,  0x4B,  0x2C,  0x90,  0x08,  0x50,  0x2E,  0x90,  0x0A,  0x50,  0x2C,  0x51,  0xAE,  0x51,
-  0x00,  0xF2,  0xB2,  0x10,  0x38,  0x54,  0x00,  0xF2,  0xB0,  0x0D,  0x56,  0x10,  0x34,  0x91,  0xB6,  0x91,
-  0x0C,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x08,  0x00,  0x41,  0x12,  0x0C,  0x91,  0x8E,  0x91,  0x04,  0x80,
-  0x18,  0xE4,  0xF7,  0x00,  0x04,  0x40,  0x30,  0x90,  0xB2,  0x90,  0x36,  0x10,  0x02,  0x80,  0x48,  0xE4,
-  0x10,  0x00,  0x31,  0x12,  0x82,  0xE7,  0x10,  0x00,  0x84,  0x80,  0x19,  0xE4,  0x20,  0x00,  0x10,  0x13,
-  0x0C,  0x90,  0x8E,  0x90,  0x5D,  0xF0,  0x74,  0x07,  0x0C,  0x58,  0x8D,  0x58,  0x00,  0xF0,  0x60,  0x07,
-  0x38,  0x54,  0xB9,  0x54,  0x19,  0x80,  0xF1,  0x10,  0x3A,  0x55,  0x19,  0x81,  0xBB,  0x55,  0x10,  0x90,
-  0x92,  0x90,  0x10,  0x58,  0x91,  0x58,  0x14,  0x59,  0x95,  0x59,  0x00,  0xF0,  0x60,  0x07,  0x04,  0x80,
-  0x18,  0xE4,  0x20,  0x00,  0x06,  0x12,  0x6C,  0x19,  0x19,  0x41,  0x7C,  0x10,  0x6C,  0x19,  0x0C,  0x51,
-  0xED,  0x19,  0x8E,  0x51,  0x6B,  0x18,  0x18,  0xF4,  0x00,  0xFF,  0x02,  0x13,  0x6A,  0x10,  0x01,  0x58,
-  0xD2,  0xF0,  0xBC,  0x08,  0x76,  0x18,  0x18,  0xF4,  0x03,  0x00,  0x0A,  0x12,  0x00,  0xFC,  0x22,  0x01,
-  0x18,  0xF4,  0x01,  0x00,  0x06,  0x13,  0x9E,  0xE7,  0x16,  0x00,  0x4C,  0x10,  0xD1,  0xF0,  0xC6,  0x08,
-  0x9E,  0xE7,  0x17,  0x00,  0x42,  0x10,  0xD0,  0xF0,  0xD0,  0x08,  0x9E,  0xE7,  0x19,  0x00,  0x38,  0x10,
-  0xCF,  0xF0,  0xDA,  0x08,  0x9E,  0xE7,  0x20,  0x00,  0x2E,  0x10,  0xCE,  0xF0,  0xE4,  0x08,  0x9E,  0xE7,
-  0x21,  0x00,  0x24,  0x10,  0xCD,  0xF0,  0xEE,  0x08,  0x9E,  0xE7,  0x22,  0x00,  0x1A,  0x10,  0xCC,  0xF0,
-  0x00,  0x09,  0x84,  0x80,  0x19,  0xE4,  0x04,  0x00,  0x06,  0x12,  0x9E,  0xE7,  0x12,  0x00,  0x08,  0x10,
-  0xCB,  0xF0,  0x08,  0x09,  0x9E,  0xE7,  0x24,  0x00,  0xB1,  0xF0,  0x08,  0x09,  0x05,  0xF0,  0x1A,  0x09,
-  0x09,  0xF0,  0x20,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0xE4,  0x10,  0x00,  0xF2,  0x5C,  0x0B,  0xE9,  0x10,
-  0x9C,  0x32,  0x82,  0xE7,  0x20,  0x00,  0x32,  0x1C,  0xE9,  0x09,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,
-  0xFE,  0x09,  0x69,  0x08,  0x01,  0xF0,  0x40,  0x09,  0x1E,  0xF0,  0xF8,  0x09,  0x00,  0xF0,  0x34,  0x09,
-  0x30,  0x44,  0x06,  0x12,  0x9E,  0xE7,  0x42,  0x00,  0xB8,  0x10,  0x04,  0xF6,  0x01,  0x00,  0xB3,  0x45,
-  0x74,  0x12,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x22,  0x13,  0x4B,  0xE4,  0x02,  0x00,  0x36,  0x12,
-  0x4B,  0xE4,  0x28,  0x00,  0xAC,  0x13,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0x03,  0xF6,
-  0xD0,  0x00,  0xFA,  0x14,  0x82,  0xE7,  0x01,  0x00,  0x00,  0xF0,  0x80,  0x01,  0x9E,  0xE7,  0x44,  0x00,
-  0x4B,  0xE4,  0x02,  0x00,  0x06,  0x12,  0x03,  0xE6,  0x02,  0x00,  0x76,  0x10,  0x00,  0xF2,  0x9E,  0x0D,
-  0x03,  0xE6,  0x02,  0x00,  0x6C,  0x10,  0x00,  0xF2,  0x9E,  0x0D,  0x19,  0x82,  0x34,  0x46,  0x0A,  0x13,
-  0x03,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x43,  0x00,  0x68,  0x10,  0x04,  0x80,  0x30,  0xE4,  0x20,  0x00,
-  0x04,  0x40,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0x82,  0xE7,  0x01,  0x00,  0x06,  0xF7,
-  0x02,  0x00,  0x00,  0xF0,  0x08,  0x03,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x06,  0x12,  0x03,  0xE6,
-  0x02,  0x00,  0x3E,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x3A,  0x12,  0x04,  0x80,  0x18,  0xE4,
-  0xFD,  0x00,  0x04,  0x40,  0x1C,  0x1C,  0x9D,  0xF0,  0xE6,  0x09,  0x1C,  0x1C,  0x9D,  0xF0,  0xEC,  0x09,
-  0xC1,  0x10,  0x9E,  0xE7,  0x13,  0x00,  0x0A,  0x10,  0x9E,  0xE7,  0x41,  0x00,  0x04,  0x10,  0x9E,  0xE7,
-  0x24,  0x00,  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0xD5,  0xF0,  0x8A,  0x02,  0x04,  0xE6,  0x04,  0x00,
-  0x06,  0x10,  0x04,  0xE6,  0x04,  0x00,  0x9D,  0x41,  0x1C,  0x42,  0x9F,  0xE7,  0x00,  0x00,  0x06,  0xF7,
-  0x02,  0x00,  0x03,  0xF6,  0xE0,  0x00,  0x3C,  0x14,  0x44,  0x58,  0x45,  0x58,  0x00,  0xF2,  0xF2,  0x0D,
-  0x00,  0xF2,  0x7A,  0x10,  0x00,  0xF2,  0xC2,  0x0F,  0x3C,  0x14,  0x1E,  0x1C,  0x00,  0xF0,  0x80,  0x01,
-  0x12,  0x1C,  0x22,  0x1C,  0xD2,  0x14,  0x00,  0xF0,  0x72,  0x01,  0x83,  0x59,  0x03,  0xDC,  0x73,  0x57,
-  0x80,  0x5D,  0x00,  0x16,  0x83,  0x59,  0x03,  0xDC,  0x38,  0x54,  0x70,  0x57,  0x33,  0x54,  0x3B,  0x54,
-  0x80,  0x5D,  0x00,  0x16,  0x03,  0x57,  0x83,  0x59,  0x38,  0x54,  0x00,  0xCC,  0x00,  0x16,  0x03,  0x57,
-  0x83,  0x59,  0x00,  0x4C,  0x00,  0x16,  0x02,  0x80,  0x48,  0xE4,  0x01,  0x00,  0x0E,  0x12,  0x48,  0xE4,
-  0x05,  0x00,  0x08,  0x12,  0x00,  0xF2,  0xB8,  0x11,  0x00,  0xF2,  0xC4,  0x11,  0xC1,  0x5A,  0x3A,  0x55,
-  0x02,  0xEC,  0xB5,  0x00,  0x45,  0x59,  0x00,  0xF2,  0xF2,  0x0D,  0x83,  0x58,  0x30,  0xE7,  0x00,  0x00,
-  0x10,  0x4D,  0x30,  0xE7,  0x40,  0x00,  0x10,  0x4F,  0x38,  0x90,  0xBA,  0x90,  0x10,  0x5C,  0x80,  0x5C,
-  0x83,  0x5A,  0x10,  0x4E,  0x04,  0xEA,  0xB5,  0x00,  0x43,  0x5B,  0x03,  0xF4,  0xE0,  0x00,  0x83,  0x59,
-  0x04,  0xCC,  0x01,  0x4A,  0x0A,  0x12,  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,  0x00,  0xF2,  0x34,  0x10,
-  0x00,  0x16,  0x08,  0x1C,  0x00,  0xFC,  0xAC,  0x00,  0x06,  0x58,  0x67,  0x18,  0x18,  0xF4,  0x8F,  0xE1,
-  0x01,  0xFC,  0xAE,  0x00,  0x19,  0xF4,  0x70,  0x1E,  0xB0,  0x54,  0x07,  0x58,  0x00,  0xFC,  0xB0,  0x00,
-  0x08,  0x58,  0x00,  0xFC,  0xB2,  0x00,  0x09,  0x58,  0x0A,  0x1C,  0x00,  0xE6,  0x0F,  0x00,  0x00,  0xEA,
-  0xB9,  0x00,  0x38,  0x54,  0x00,  0xFA,  0x24,  0x01,  0x00,  0xFA,  0xB6,  0x00,  0x18,  0x1C,  0x14,  0x1C,
-  0x10,  0x1C,  0x32,  0x1C,  0x12,  0x1C,  0x00,  0x16,  0x3E,  0x57,  0x0C,  0x14,  0x0E,  0x47,  0x07,  0xE6,
-  0x10,  0x00,  0xCE,  0x47,  0xF5,  0x13,  0x00,  0x16,  0x00,  0xF2,  0x9E,  0x0D,  0x02,  0x4B,  0x03,  0xF6,
-  0xE0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x01,  0x48,  0x20,  0x12,  0x44,  0x58,  0x45,  0x58,  0x9E,  0xE7,
-  0x15,  0x00,  0x9C,  0xE7,  0x04,  0x00,  0x00,  0xF2,  0xF2,  0x0D,  0x00,  0xF2,  0x7A,  0x10,  0x00,  0xF2,
-  0xC2,  0x0F,  0x00,  0xF2,  0x76,  0x0A,  0x1E,  0x1C,  0xD5,  0x10,  0x00,  0x16,  0x69,  0x08,  0x48,  0xE4,
-  0x04,  0x00,  0x64,  0x12,  0x48,  0xE4,  0x02,  0x00,  0x20,  0x12,  0x48,  0xE4,  0x03,  0x00,  0x1A,  0x12,
-  0x48,  0xE4,  0x08,  0x00,  0x14,  0x12,  0x48,  0xE4,  0x01,  0x00,  0xF0,  0x12,  0x48,  0xE4,  0x07,  0x00,
-  0x12,  0x12,  0x01,  0xE6,  0x07,  0x00,  0x00,  0xF2,  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x05,  0xF0,
-  0x5C,  0x0B,  0x00,  0x16,  0x00,  0xE6,  0x01,  0x00,  0x00,  0xEA,  0x99,  0x00,  0x02,  0x80,  0x48,  0xE4,
-  0x03,  0x00,  0xB9,  0x12,  0x48,  0xE4,  0x06,  0x00,  0xB3,  0x12,  0x01,  0xE6,  0x06,  0x00,  0x00,  0xF2,
-  0x4A,  0x0D,  0x00,  0xF2,  0x0E,  0x11,  0x04,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,  0x01,  0xF0,
-  0x18,  0x0A,  0x00,  0xF0,  0xFE,  0x09,  0x00,  0x16,  0x02,  0x80,  0x48,  0xE4,  0x10,  0x00,  0x1C,  0x12,
-  0x82,  0xE7,  0x08,  0x00,  0x3C,  0x56,  0x03,  0x82,  0x00,  0xF2,  0xDE,  0x0D,  0x30,  0xE7,  0x08,  0x00,
-  0x04,  0xF7,  0x70,  0x01,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF0,  0x80,  0x01,  0x6C,  0x19,  0xED,  0x19,
-  0x5D,  0xF0,  0xD0,  0x0B,  0x44,  0x55,  0xE5,  0x55,  0x59,  0xF0,  0x4E,  0x0C,  0x04,  0x55,  0xA5,  0x55,
-  0x1F,  0x80,  0x01,  0xEC,  0xB8,  0x00,  0x82,  0x48,  0x82,  0x80,  0x49,  0x44,  0x2E,  0x13,  0x01,  0xEC,
-  0xB8,  0x00,  0x41,  0xE4,  0x02,  0x00,  0x01,  0xEA,  0xB8,  0x00,  0x49,  0xE4,  0x11,  0x00,  0x59,  0xF0,
-  0x2A,  0x0C,  0x01,  0xE6,  0x17,  0x00,  0x01,  0xEA,  0xB8,  0x00,  0x02,  0x4B,  0x88,  0x90,  0xAC,  0x50,
-  0x8A,  0x90,  0xAE,  0x50,  0x01,  0xEC,  0xB8,  0x00,  0x82,  0x48,  0x82,  0x80,  0x10,  0x44,  0x02,  0x4B,
-  0x1F,  0x40,  0xC0,  0x44,  0x00,  0xF2,  0xB0,  0x0D,  0x04,  0x55,  0xA5,  0x55,  0x9F,  0x10,  0x0C,  0x51,
-  0x8E,  0x51,  0x30,  0x90,  0xB2,  0x90,  0x00,  0x56,  0xA1,  0x56,  0x30,  0x50,  0xB2,  0x50,  0x34,  0x90,
-  0xB6,  0x90,  0x40,  0x56,  0xE1,  0x56,  0x34,  0x50,  0xB6,  0x50,  0x65,  0x10,  0xB1,  0xF0,  0x6C,  0x0C,
-  0x85,  0xF0,  0xC6,  0x0B,  0xE9,  0x09,  0x4B,  0xE4,  0x03,  0x00,  0x78,  0x12,  0x4B,  0xE4,  0x02,  0x00,
-  0x01,  0x13,  0xB1,  0xF0,  0x82,  0x0C,  0x85,  0xF0,  0xC6,  0x0B,  0x69,  0x08,  0x48,  0xE4,  0x03,  0x00,
-  0xD5,  0xF0,  0x82,  0x0B,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0xC6,  0x0B,  0xE8,  0x09,  0x3C,  0x56,
-  0x00,  0xFC,  0x20,  0x01,  0x98,  0x57,  0x02,  0x13,  0xBB,  0x45,  0x4B,  0xE4,  0x00,  0x00,  0x08,  0x12,
-  0x03,  0xE6,  0x01,  0x00,  0x04,  0xF6,  0x00,  0x80,  0xA8,  0x14,  0xD2,  0x14,  0x30,  0x1C,  0x02,  0x80,
-  0x48,  0xE4,  0x03,  0x00,  0x10,  0x13,  0x00,  0xFC,  0xB6,  0x00,  0x98,  0x57,  0x02,  0x13,  0x4C,  0x1C,
-  0x3E,  0x1C,  0x00,  0xF0,  0x8A,  0x0B,  0x00,  0xFC,  0x24,  0x01,  0xB0,  0x57,  0x00,  0xFA,  0x24,  0x01,
-  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0x8A,  0x0B,  0x00,  0xF2,  0x88,  0x0E,
-  0x00,  0xF0,  0x8A,  0x0B,  0xB1,  0xF0,  0xF4,  0x0C,  0x85,  0xF0,  0x82,  0x0B,  0x69,  0x08,  0x48,  0xE4,
-  0x01,  0x00,  0xD5,  0xF0,  0x82,  0x0B,  0xFC,  0x14,  0x42,  0x58,  0x6C,  0x14,  0x80,  0x14,  0x30,  0x1C,
-  0x4A,  0xF4,  0x02,  0x00,  0x55,  0xF0,  0x82,  0x0B,  0x4A,  0xF4,  0x01,  0x00,  0x0E,  0x12,  0x02,  0x80,
-  0x48,  0xE4,  0x03,  0x00,  0x06,  0x13,  0x3E,  0x1C,  0x00,  0xF0,  0x8A,  0x0B,  0x00,  0xFC,  0xB6,  0x00,
-  0xB0,  0x57,  0x00,  0xFA,  0xB6,  0x00,  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,
-  0x8A,  0x0B,  0x00,  0xF2,  0xB6,  0x0E,  0x00,  0xF0,  0x8A,  0x0B,  0x4C,  0x1C,  0xB1,  0xF0,  0x4C,  0x0D,
-  0x85,  0xF0,  0x58,  0x0D,  0x69,  0x08,  0xF3,  0x10,  0x86,  0xF0,  0x60,  0x0D,  0x4E,  0x1C,  0x89,  0x48,
-  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,
-  0xFF,  0x7F,  0x30,  0x56,  0x00,  0x5C,  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,
-  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,  0x00,  0x80,  0x30,  0x56,  0x00,  0x5C,  0x00,  0x16,  0x00,  0xF6,
-  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x0B,  0x58,  0x00,  0x16,  0x03,  0xF6,
-  0x24,  0x01,  0x00,  0xF2,  0x54,  0x0A,  0x03,  0xF6,  0xB6,  0x00,  0x00,  0xF2,  0x54,  0x0A,  0x00,  0x16,
-  0x02,  0xEC,  0xB8,  0x00,  0x02,  0x49,  0x18,  0xF4,  0xFF,  0x00,  0x00,  0x54,  0x00,  0x54,  0x00,  0x54,
-  0x00,  0xF4,  0x08,  0x00,  0xE1,  0x18,  0x80,  0x54,  0x03,  0x58,  0x00,  0xDD,  0x01,  0xDD,  0x02,  0xDD,
-  0x03,  0xDC,  0x02,  0x4B,  0x30,  0x50,  0xB2,  0x50,  0x34,  0x51,  0xB6,  0x51,  0x00,  0x16,  0x45,  0x5A,
-  0x1D,  0xF4,  0xFF,  0x00,  0x85,  0x56,  0x85,  0x56,  0x85,  0x56,  0x05,  0xF4,  0x02,  0x12,  0x83,  0x5A,
-  0x00,  0x16,  0x1D,  0xF4,  0xFF,  0x00,  0x85,  0x56,  0x85,  0x56,  0x85,  0x56,  0x05,  0xF4,  0x00,  0x12,
-  0x83,  0x5A,  0x00,  0x16,  0x38,  0x54,  0xBB,  0x55,  0x3C,  0x56,  0xBD,  0x56,  0x00,  0xF2,  0x0E,  0x11,
-  0x85,  0xF0,  0x7E,  0x0E,  0xE9,  0x09,  0xC1,  0x59,  0x00,  0xF2,  0x0E,  0x11,  0x85,  0xF0,  0x7E,  0x0E,
-  0xE8,  0x0A,  0x83,  0x55,  0x83,  0x55,  0x4B,  0xF4,  0x90,  0x01,  0x5C,  0xF0,  0x32,  0x0E,  0xBD,  0x56,
-  0x40,  0x10,  0x4B,  0xF4,  0x30,  0x00,  0x59,  0xF0,  0x44,  0x0E,  0x01,  0xF6,  0x0C,  0x00,  0x00,  0xF6,
-  0x01,  0x00,  0x2E,  0x10,  0x02,  0xFC,  0x9C,  0x00,  0x9A,  0x57,  0x14,  0x13,  0x4B,  0xF4,  0x64,  0x00,
-  0x59,  0xF0,  0x60,  0x0E,  0x03,  0xF6,  0x64,  0x00,  0x01,  0xF6,  0x19,  0x00,  0x00,  0xF6,  0x01,  0x00,
-  0x43,  0xF4,  0x33,  0x00,  0x56,  0xF0,  0x72,  0x0E,  0x04,  0xF4,  0x00,  0x01,  0x43,  0xF4,  0x19,  0x00,
-  0xF3,  0x10,  0xB4,  0x56,  0xC3,  0x58,  0x02,  0xFC,  0x9E,  0x00,  0x9A,  0x57,  0x08,  0x13,  0x3C,  0x56,
-  0x00,  0xF6,  0x02,  0x00,  0x00,  0x16,  0x00,  0x16,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,
-  0x86,  0xF0,  0xB4,  0x0E,  0x09,  0xE7,  0x02,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xB4,  0x0E,
-  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xB4,  0x0E,  0x4E,  0x1C,  0x89,  0x49,
-  0x00,  0xF2,  0x0E,  0x11,  0x00,  0x16,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,
-  0xEE,  0x0E,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xEE,  0x0E,  0x09,  0xE7,
-  0x01,  0x00,  0x00,  0xF2,  0x0E,  0x11,  0x86,  0xF0,  0xEE,  0x0E,  0x89,  0x49,  0x00,  0xF2,  0x0E,  0x11,
-  0x86,  0xF0,  0xEE,  0x0E,  0x4E,  0x1C,  0x89,  0x4A,  0x00,  0xF2,  0x0E,  0x11,  0x00,  0x16,  0x3C,  0x56,
-  0x00,  0x16,  0x00,  0xEC,  0x26,  0x01,  0x48,  0xE4,  0x01,  0x00,  0x1E,  0x13,  0x38,  0x44,  0x00,  0xEA,
-  0x26,  0x01,  0x49,  0xF4,  0x00,  0x00,  0x04,  0x12,  0x4E,  0x1C,  0x02,  0x10,  0x4C,  0x1C,  0x01,  0xEC,
-  0x27,  0x01,  0x89,  0x48,  0x00,  0xF2,  0x0E,  0x11,  0x02,  0x14,  0x00,  0x16,  0x85,  0xF0,  0x4E,  0x0F,
-  0x38,  0x54,  0x00,  0xEA,  0x99,  0x00,  0x00,  0xF2,  0x5C,  0x0B,  0x02,  0x80,  0x48,  0xE4,  0x06,  0x00,
-  0x1C,  0x13,  0x00,  0xEC,  0x99,  0x00,  0x48,  0xE4,  0x01,  0x00,  0x0A,  0x12,  0x04,  0x80,  0x30,  0xE4,
-  0x01,  0x00,  0x04,  0x40,  0x08,  0x10,  0x04,  0x80,  0x18,  0xE4,  0xFE,  0x00,  0x04,  0x40,  0x00,  0x16,
-  0x02,  0xF6,  0xE0,  0x00,  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x81,  0x48,  0x22,  0x12,  0x00,  0x4E,
-  0x83,  0x5A,  0x90,  0x4C,  0x20,  0xE7,  0x00,  0x00,  0xC3,  0x58,  0x1B,  0xF4,  0xFF,  0x00,  0x83,  0x55,
-  0x83,  0x55,  0x83,  0x55,  0x03,  0xF4,  0x00,  0x12,  0x8B,  0x55,  0x83,  0x59,  0x00,  0x4E,  0x00,  0x16,
-  0x00,  0x4E,  0x02,  0xF6,  0xF0,  0x00,  0x02,  0x57,  0x03,  0x59,  0x00,  0x4E,  0x83,  0x5A,  0x30,  0xE7,
-  0x00,  0x00,  0x20,  0xE7,  0x00,  0x00,  0x00,  0x16,  0x02,  0xF6,  0xF0,  0x00,  0x02,  0x57,  0x03,  0x59,
-  0x01,  0xCC,  0x00,  0x4E,  0x83,  0x5A,  0x30,  0xE7,  0x00,  0x00,  0x80,  0x4C,  0xC3,  0x58,  0x1B,  0xF4,
-  0xFF,  0x00,  0x83,  0x55,  0x83,  0x55,  0x83,  0x55,  0x03,  0xF4,  0x00,  0x12,  0x83,  0x59,  0x00,  0x4E,
-  0x00,  0x16,  0x03,  0xF6,  0xE0,  0x00,  0x03,  0x57,  0x83,  0x59,  0x3A,  0x55,  0x02,  0xCC,  0x45,  0x5A,
-  0x00,  0xF2,  0xF2,  0x0D,  0xC0,  0x5A,  0x40,  0x5C,  0x38,  0x54,  0x00,  0xCD,  0x01,  0xCC,  0x4A,  0x46,
-  0x0A,  0x13,  0x83,  0x59,  0x00,  0x4C,  0x01,  0x48,  0x16,  0x13,  0x0C,  0x10,  0xC5,  0x58,  0x00,  0xF2,
-  0xF2,  0x0D,  0x00,  0x4C,  0x01,  0x48,  0x08,  0x13,  0x05,  0xF6,  0xF0,  0x00,  0x05,  0x57,  0x08,  0x10,
-  0x45,  0x58,  0x00,  0xF2,  0xF2,  0x0D,  0x8D,  0x56,  0x83,  0x5A,  0x80,  0x4C,  0x05,  0x17,  0x00,  0x16,
-  0x02,  0x4B,  0x06,  0xF7,  0x04,  0x00,  0x62,  0x0B,  0x03,  0x82,  0x00,  0xF2,  0xDE,  0x0D,  0x02,  0x80,
-  0x00,  0x4C,  0x45,  0xF4,  0x02,  0x00,  0x52,  0x14,  0x06,  0xF7,  0x02,  0x00,  0x06,  0x14,  0x00,  0xF2,
-  0x50,  0x0F,  0x00,  0x16,  0x02,  0x4B,  0x01,  0xF6,  0xFF,  0x00,  0x38,  0x1C,  0x05,  0xF4,  0x04,  0x00,
-  0x83,  0x5A,  0x18,  0xDF,  0x19,  0xDF,  0x1D,  0xF7,  0x3C,  0x00,  0xB8,  0xF0,  0x4A,  0x10,  0x9C,  0x14,
-  0x01,  0x48,  0x1C,  0x13,  0x0E,  0xF7,  0x3C,  0x00,  0x03,  0xF7,  0x04,  0x00,  0xAF,  0x19,  0x03,  0x42,
-  0x45,  0xF4,  0x02,  0x00,  0x83,  0x5A,  0x02,  0xCC,  0x02,  0x41,  0x45,  0xF4,  0x02,  0x00,  0x00,  0x16,
-  0x91,  0x44,  0xD5,  0xF0,  0x3A,  0x10,  0x00,  0xF0,  0x9E,  0x02,  0x01,  0xF6,  0xFF,  0x00,  0x38,  0x1C,
-  0x05,  0xF4,  0x04,  0x00,  0x83,  0x5A,  0x18,  0xDF,  0x19,  0xDF,  0x0E,  0xF7,  0x3C,  0x00,  0x03,  0xF7,
-  0x04,  0x00,  0x0F,  0x79,  0x1C,  0xF7,  0x3C,  0x00,  0xB8,  0xF0,  0x98,  0x10,  0x4E,  0x14,  0x01,  0x48,
-  0x06,  0x13,  0x45,  0xF4,  0x04,  0x00,  0x00,  0x16,  0x91,  0x44,  0xD5,  0xF0,  0x7E,  0x10,  0x00,  0xF0,
-  0x9E,  0x02,  0x02,  0xF6,  0xFF,  0x00,  0x38,  0x1C,  0x2C,  0xBC,  0xAE,  0xBC,  0xE2,  0x08,  0x00,  0xEC,
-  0xB8,  0x00,  0x02,  0x48,  0x1D,  0xF7,  0x80,  0x00,  0xB8,  0xF0,  0xC8,  0x10,  0x1E,  0x14,  0x01,  0x48,
-  0x0E,  0x13,  0x0E,  0xF7,  0x80,  0x00,  0x38,  0x54,  0x03,  0x58,  0xAF,  0x19,  0x82,  0x48,  0x00,  0x16,
-  0x82,  0x48,  0x12,  0x45,  0xD5,  0xF0,  0xB6,  0x10,  0x00,  0xF0,  0x9E,  0x02,  0x39,  0xF0,  0xF4,  0x10,
-  0x38,  0x44,  0x00,  0x16,  0x7E,  0x18,  0x18,  0xF4,  0x03,  0x00,  0x04,  0x13,  0x61,  0x18,  0x00,  0x16,
-  0x38,  0x1C,  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0xF1,  0x12,  0xE3,  0x10,  0x30,  0x44,
-  0x30,  0x44,  0x30,  0x44,  0xB1,  0xF0,  0x14,  0x11,  0x00,  0x16,  0x3E,  0x57,  0x03,  0xF6,  0xE0,  0x00,
-  0x03,  0x57,  0x83,  0x59,  0x04,  0xCC,  0x01,  0x4A,  0x6A,  0x12,  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,
-  0x02,  0x4B,  0x70,  0x14,  0x34,  0x13,  0x02,  0x80,  0x48,  0xE4,  0x08,  0x00,  0x18,  0x12,  0x9C,  0xE7,
-  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,  0x00,  0xF2,  0xC2,  0x0F,  0x00,  0xF2,  0x76,  0x0A,  0x1E,  0x1C,
-  0x01,  0xF6,  0x01,  0x00,  0x00,  0x16,  0x30,  0xE4,  0x10,  0x00,  0x04,  0x40,  0x00,  0xF2,  0xDE,  0x0D,
-  0x20,  0xE7,  0x01,  0x00,  0x01,  0xF6,  0x01,  0x00,  0x00,  0x16,  0x04,  0xDC,  0x01,  0x4A,  0x24,  0x12,
-  0x45,  0x5A,  0x00,  0xF2,  0xF2,  0x0D,  0x43,  0x5B,  0x06,  0xEC,  0x98,  0x00,  0x00,  0xF2,  0x34,  0x10,
-  0xC6,  0x59,  0x20,  0x14,  0x0A,  0x13,  0x00,  0xF2,  0xC2,  0x0F,  0x00,  0xF2,  0x10,  0x10,  0xA7,  0x10,
-  0x83,  0x5A,  0xD7,  0x10,  0x0E,  0x47,  0x07,  0xE6,  0x10,  0x00,  0xCE,  0x47,  0x5A,  0xF0,  0x1C,  0x11,
-  0xB9,  0x54,  0x00,  0x16,  0x14,  0x90,  0x96,  0x90,  0x02,  0xFC,  0xA8,  0x00,  0x03,  0xFC,  0xAA,  0x00,
-  0x48,  0x55,  0x02,  0x13,  0xC9,  0x55,  0x00,  0x16,  0x00,  0xEC,  0xBA,  0x00,  0x10,  0x44,  0x00,  0xEA,
-  0xBA,  0x00,  0x00,  0x16,  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x64,  0x0A,  0x10,  0x44,  0x00,  0x4C,
-  0x00,  0x16 };
+  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x08,  0x44,  0x00,  0x4C,  0x82,  0xE7,  0x02,  0x00,
+  0x00,  0xF2,  0x12,  0x11,  0x00,  0xF2,  0x12,  0x11,  0x85,  0xF0,  0x70,  0x03,  0x00,  0xF2,  0x60,  0x0B,
+  0x06,  0xF0,  0x80,  0x03,  0x09,  0xF0,  0x24,  0x09,  0x1E,  0xF0,  0xFC,  0x09,  0x00,  0xF0,  0x02,  0x0A,
+  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0x55,  0xF0,  0xAC,  0x04,  0x01,  0xE6,  0x0C,  0x00,  0x00,  0xF2,
+  0x4E,  0x0D,  0x00,  0xF2,  0x12,  0x11,  0x00,  0xF2,  0xBC,  0x11,  0x00,  0xF2,  0xC8,  0x11,  0x01,  0xF0,
+  0x7C,  0x02,  0x00,  0xF0,  0x8A,  0x02,  0x46,  0x1C,  0x0C,  0x1C,  0x67,  0x1B,  0xBF,  0x57,  0x77,  0x57,
+  0x02,  0x4B,  0x48,  0x1C,  0x32,  0x1C,  0x00,  0xF2,  0x92,  0x0D,  0x30,  0x1C,  0x96,  0xF0,  0xBC,  0x03,
+  0xB1,  0xF0,  0xC0,  0x03,  0x1E,  0xF0,  0xFC,  0x09,  0x85,  0xF0,  0x02,  0x0A,  0x00,  0xFC,  0xBE,  0x00,
+  0x98,  0x57,  0x14,  0x12,  0x01,  0xE6,  0x0C,  0x00,  0x00,  0xF2,  0x4E,  0x0D,  0x00,  0xF2,  0x12,  0x11,
+  0x01,  0xF0,  0x7C,  0x02,  0x00,  0xF0,  0x8A,  0x02,  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x68,  0x0A,
+  0x01,  0x48,  0x55,  0xF0,  0x98,  0x04,  0x03,  0x82,  0x03,  0xFC,  0xA0,  0x00,  0x9B,  0x57,  0x40,  0x12,
+  0x69,  0x18,  0x00,  0xF2,  0x12,  0x11,  0x85,  0xF0,  0x42,  0x04,  0x69,  0x08,  0x00,  0xF2,  0x12,  0x11,
+  0x85,  0xF0,  0x02,  0x0A,  0x68,  0x08,  0x4C,  0x44,  0x28,  0x12,  0x44,  0x48,  0x03,  0xF6,  0xE0,  0x00,
+  0x00,  0xF2,  0x68,  0x0A,  0x45,  0x58,  0x00,  0xF2,  0xF6,  0x0D,  0x00,  0xCC,  0x01,  0x48,  0x55,  0xF0,
+  0x98,  0x04,  0x4C,  0x44,  0xEF,  0x13,  0x00,  0xF2,  0xC6,  0x0F,  0x00,  0xF2,  0x14,  0x10,  0x08,  0x10,
+  0x68,  0x18,  0x45,  0x5A,  0x00,  0xF2,  0xF6,  0x0D,  0x04,  0x80,  0x18,  0xE4,  0x10,  0x00,  0x28,  0x12,
+  0x01,  0xE6,  0x06,  0x00,  0x04,  0x80,  0x18,  0xE4,  0x01,  0x00,  0x04,  0x12,  0x01,  0xE6,  0x0D,  0x00,
+  0x00,  0xF2,  0x4E,  0x0D,  0x00,  0xF2,  0x12,  0x11,  0x04,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,
+  0x01,  0xF0,  0x1C,  0x0A,  0x00,  0xF0,  0x02,  0x0A,  0x69,  0x08,  0x05,  0x80,  0x48,  0xE4,  0x00,  0x00,
+  0x0C,  0x12,  0x00,  0xE6,  0x11,  0x00,  0x00,  0xEA,  0xB8,  0x00,  0x00,  0xF2,  0xB6,  0x10,  0x82,  0xE7,
+  0x02,  0x00,  0x1C,  0x90,  0x40,  0x5C,  0x00,  0x16,  0x01,  0xE6,  0x06,  0x00,  0x00,  0xF2,  0x4E,  0x0D,
+  0x01,  0xF0,  0x80,  0x01,  0x1E,  0xF0,  0x80,  0x01,  0x00,  0xF0,  0xA0,  0x04,  0x42,  0x5B,  0x06,  0xF7,
+  0x03,  0x00,  0x46,  0x59,  0xBF,  0x57,  0x77,  0x57,  0x01,  0xE6,  0x80,  0x00,  0x07,  0x80,  0x31,  0x44,
+  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x56,  0x13,  0x20,  0x80,  0x48,  0xE4,  0x03,  0x00,  0x4E,  0x12,
+  0x00,  0xFC,  0xA2,  0x00,  0x98,  0x57,  0x55,  0xF0,  0x1C,  0x05,  0x31,  0xE4,  0x40,  0x00,  0x00,  0xFC,
+  0xA0,  0x00,  0x98,  0x57,  0x36,  0x12,  0x4C,  0x1C,  0x00,  0xF2,  0x12,  0x11,  0x89,  0x48,  0x00,  0xF2,
+  0x12,  0x11,  0x86,  0xF0,  0x2E,  0x05,  0x82,  0xE7,  0x06,  0x00,  0x1B,  0x80,  0x48,  0xE4,  0x22,  0x00,
+  0x5B,  0xF0,  0x0C,  0x05,  0x48,  0xE4,  0x20,  0x00,  0x59,  0xF0,  0x10,  0x05,  0x00,  0xE6,  0x20,  0x00,
+  0x09,  0x48,  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,  0x2E,  0x05,  0x83,  0x80,  0x04,  0x10,  0x00,  0xF2,
+  0xA2,  0x0D,  0x00,  0xE6,  0x01,  0x00,  0x00,  0xEA,  0x26,  0x01,  0x01,  0xEA,  0x27,  0x01,  0x04,  0x80,
+  0x18,  0xE4,  0x10,  0x00,  0x36,  0x12,  0xB9,  0x54,  0x00,  0xF2,  0xF6,  0x0E,  0x01,  0xE6,  0x06,  0x00,
+  0x04,  0x80,  0x18,  0xE4,  0x01,  0x00,  0x04,  0x12,  0x01,  0xE6,  0x0D,  0x00,  0x00,  0xF2,  0x4E,  0x0D,
+  0x00,  0xF2,  0x12,  0x11,  0x00,  0xF2,  0xBC,  0x11,  0x00,  0xF2,  0xC8,  0x11,  0x04,  0xE6,  0x02,  0x00,
+  0x9E,  0xE7,  0x15,  0x00,  0x01,  0xF0,  0x1C,  0x0A,  0x00,  0xF0,  0x02,  0x0A,  0x00,  0xFC,  0x20,  0x01,
+  0x98,  0x57,  0x34,  0x12,  0x00,  0xFC,  0x24,  0x01,  0x98,  0x57,  0x2C,  0x13,  0xB9,  0x54,  0x00,  0xF2,
+  0xF6,  0x0E,  0x86,  0xF0,  0xA8,  0x05,  0x03,  0xF6,  0x01,  0x00,  0x00,  0xF2,  0x8C,  0x0E,  0x85,  0xF0,
+  0x9E,  0x05,  0x82,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x60,  0x0B,  0x82,  0xE7,  0x02,  0x00,  0x00,  0xFC,
+  0x24,  0x01,  0xB0,  0x57,  0x00,  0xFA,  0x24,  0x01,  0x00,  0xFC,  0x9E,  0x00,  0x98,  0x57,  0x5A,  0x12,
+  0x00,  0xFC,  0xB6,  0x00,  0x98,  0x57,  0x52,  0x13,  0x03,  0xE6,  0x0C,  0x00,  0x00,  0xFC,  0x9C,  0x00,
+  0x98,  0x57,  0x04,  0x13,  0x03,  0xE6,  0x19,  0x00,  0x05,  0xE6,  0x08,  0x00,  0x00,  0xF6,  0x00,  0x01,
+  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,  0x00,  0x80,  0x04,  0x13,  0x05,  0xE6,
+  0x0F,  0x00,  0xB9,  0x54,  0x00,  0xF2,  0xF6,  0x0E,  0x86,  0xF0,  0x0A,  0x06,  0x00,  0xF2,  0xBA,  0x0E,
+  0x85,  0xF0,  0x00,  0x06,  0x82,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x60,  0x0B,  0x82,  0xE7,  0x02,  0x00,
+  0x00,  0xFC,  0xB6,  0x00,  0xB0,  0x57,  0x00,  0xFA,  0xB6,  0x00,  0x01,  0xF6,  0x01,  0x00,  0x00,  0xF2,
+  0xF6,  0x0E,  0x9C,  0x32,  0x4E,  0x1C,  0x32,  0x1C,  0x00,  0xF2,  0x92,  0x0D,  0x30,  0x1C,  0x82,  0xE7,
+  0x04,  0x00,  0xB1,  0xF0,  0x22,  0x06,  0x0A,  0xF0,  0x3E,  0x06,  0x05,  0xF0,  0xD6,  0x06,  0x06,  0xF0,
+  0xDC,  0x06,  0x09,  0xF0,  0x24,  0x09,  0x1E,  0xF0,  0xFC,  0x09,  0x00,  0xF0,  0x02,  0x0A,  0x04,  0x80,
+  0x18,  0xE4,  0x20,  0x00,  0x30,  0x12,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x21,  0x80,
+  0x18,  0xE4,  0xE0,  0x00,  0x09,  0x48,  0x00,  0xF2,  0x12,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,
+  0x12,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x99,  0xA4,  0x00,  0xF2,  0x12,  0x11,
+  0x09,  0xE7,  0x00,  0x00,  0x9A,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x34,  0x12,  0x09,  0xE7,
+  0x1B,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x21,  0x80,  0x18,  0xE4,  0xE0,  0x00,  0x09,  0x48,  0x00,  0xF2,
+  0x12,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF2,
+  0x12,  0x11,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x09,  0xE7,  0x00,  0x00,  0x00,  0xF0,
+  0x0C,  0x09,  0xBB,  0x55,  0x9A,  0x81,  0x03,  0xF7,  0x20,  0x00,  0x09,  0x6F,  0x93,  0x45,  0x55,  0xF0,
+  0xE2,  0x06,  0xB1,  0xF0,  0xC2,  0x06,  0x0A,  0xF0,  0xBA,  0x06,  0x09,  0xF0,  0x24,  0x09,  0x1E,  0xF0,
+  0xFC,  0x09,  0x00,  0xF0,  0x02,  0x0A,  0x00,  0xF2,  0x60,  0x0B,  0x47,  0x10,  0x09,  0xE7,  0x08,  0x00,
+  0x41,  0x10,  0x05,  0x80,  0x48,  0xE4,  0x00,  0x00,  0x1E,  0x12,  0x00,  0xE6,  0x11,  0x00,  0x00,  0xEA,
+  0xB8,  0x00,  0x00,  0xF2,  0xB6,  0x10,  0x2C,  0x90,  0xAE,  0x90,  0x08,  0x50,  0x8A,  0x50,  0x38,  0x54,
+  0x1F,  0x40,  0x00,  0xF2,  0xB4,  0x0D,  0x08,  0x10,  0x08,  0x90,  0x8A,  0x90,  0x30,  0x50,  0xB2,  0x50,
+  0x9C,  0x32,  0x0C,  0x92,  0x8E,  0x92,  0x38,  0x54,  0x04,  0x80,  0x30,  0xE4,  0x08,  0x00,  0x04,  0x40,
+  0x0C,  0x1C,  0x00,  0xF6,  0x03,  0x00,  0xB1,  0xF0,  0x26,  0x07,  0x9E,  0xF0,  0x3A,  0x07,  0x01,  0x48,
+  0x55,  0xF0,  0xFC,  0x09,  0x0C,  0x1C,  0x10,  0x44,  0xED,  0x10,  0x0B,  0xF0,  0x5E,  0x07,  0x0C,  0xF0,
+  0x62,  0x07,  0x05,  0xF0,  0x52,  0x07,  0x06,  0xF0,  0x58,  0x07,  0x09,  0xF0,  0x24,  0x09,  0x00,  0xF0,
+  0x02,  0x0A,  0x00,  0xF2,  0x60,  0x0B,  0xCF,  0x10,  0x09,  0xE7,  0x08,  0x00,  0xC9,  0x10,  0x2E,  0x1C,
+  0x02,  0x10,  0x2C,  0x1C,  0xAA,  0xF0,  0x64,  0x07,  0xAC,  0xF0,  0x72,  0x07,  0x40,  0x10,  0x34,  0x1C,
+  0xF3,  0x10,  0xAD,  0xF0,  0x7C,  0x07,  0xC8,  0x10,  0x36,  0x1C,  0xE9,  0x10,  0x2B,  0xF0,  0x82,  0x08,
+  0x6B,  0x18,  0x18,  0xF4,  0x00,  0xFE,  0x20,  0x12,  0x01,  0x58,  0xD2,  0xF0,  0x82,  0x08,  0x76,  0x18,
+  0x18,  0xF4,  0x03,  0x00,  0xEC,  0x12,  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0xE2,  0x12,
+  0x0B,  0xF0,  0x64,  0x07,  0x0C,  0xF0,  0x64,  0x07,  0x36,  0x1C,  0x34,  0x1C,  0xB7,  0x10,  0x38,  0x54,
+  0xB9,  0x54,  0x84,  0x80,  0x19,  0xE4,  0x20,  0x00,  0xB2,  0x13,  0x85,  0x80,  0x81,  0x48,  0x66,  0x12,
+  0x04,  0x80,  0x18,  0xE4,  0x08,  0x00,  0x58,  0x13,  0x1F,  0x80,  0x08,  0x44,  0xC8,  0x44,  0x9F,  0x12,
+  0x1F,  0x40,  0x34,  0x91,  0xB6,  0x91,  0x44,  0x55,  0xE5,  0x55,  0x02,  0xEC,  0xB8,  0x00,  0x02,  0x49,
+  0xBB,  0x55,  0x82,  0x81,  0xC0,  0x55,  0x48,  0xF4,  0x0F,  0x00,  0x5A,  0xF0,  0x1A,  0x08,  0x4A,  0xE4,
+  0x17,  0x00,  0xD5,  0xF0,  0xFA,  0x07,  0x02,  0xF6,  0x0F,  0x00,  0x02,  0xF4,  0x02,  0x00,  0x02,  0xEA,
+  0xB8,  0x00,  0x04,  0x91,  0x86,  0x91,  0x02,  0x4B,  0x2C,  0x90,  0x08,  0x50,  0x2E,  0x90,  0x0A,  0x50,
+  0x2C,  0x51,  0xAE,  0x51,  0x00,  0xF2,  0xB6,  0x10,  0x38,  0x54,  0x00,  0xF2,  0xB4,  0x0D,  0x56,  0x10,
+  0x34,  0x91,  0xB6,  0x91,  0x0C,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x08,  0x00,  0x41,  0x12,  0x0C,  0x91,
+  0x8E,  0x91,  0x04,  0x80,  0x18,  0xE4,  0xF7,  0x00,  0x04,  0x40,  0x30,  0x90,  0xB2,  0x90,  0x36,  0x10,
+  0x02,  0x80,  0x48,  0xE4,  0x10,  0x00,  0x31,  0x12,  0x82,  0xE7,  0x10,  0x00,  0x84,  0x80,  0x19,  0xE4,
+  0x20,  0x00,  0x10,  0x13,  0x0C,  0x90,  0x8E,  0x90,  0x5D,  0xF0,  0x78,  0x07,  0x0C,  0x58,  0x8D,  0x58,
+  0x00,  0xF0,  0x64,  0x07,  0x38,  0x54,  0xB9,  0x54,  0x19,  0x80,  0xF1,  0x10,  0x3A,  0x55,  0x19,  0x81,
+  0xBB,  0x55,  0x10,  0x90,  0x92,  0x90,  0x10,  0x58,  0x91,  0x58,  0x14,  0x59,  0x95,  0x59,  0x00,  0xF0,
+  0x64,  0x07,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x06,  0x12,  0x6C,  0x19,  0x19,  0x41,  0x7C,  0x10,
+  0x6C,  0x19,  0x0C,  0x51,  0xED,  0x19,  0x8E,  0x51,  0x6B,  0x18,  0x18,  0xF4,  0x00,  0xFF,  0x02,  0x13,
+  0x6A,  0x10,  0x01,  0x58,  0xD2,  0xF0,  0xC0,  0x08,  0x76,  0x18,  0x18,  0xF4,  0x03,  0x00,  0x0A,  0x12,
+  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0x06,  0x13,  0x9E,  0xE7,  0x16,  0x00,  0x4C,  0x10,
+  0xD1,  0xF0,  0xCA,  0x08,  0x9E,  0xE7,  0x17,  0x00,  0x42,  0x10,  0xD0,  0xF0,  0xD4,  0x08,  0x9E,  0xE7,
+  0x19,  0x00,  0x38,  0x10,  0xCF,  0xF0,  0xDE,  0x08,  0x9E,  0xE7,  0x20,  0x00,  0x2E,  0x10,  0xCE,  0xF0,
+  0xE8,  0x08,  0x9E,  0xE7,  0x21,  0x00,  0x24,  0x10,  0xCD,  0xF0,  0xF2,  0x08,  0x9E,  0xE7,  0x22,  0x00,
+  0x1A,  0x10,  0xCC,  0xF0,  0x04,  0x09,  0x84,  0x80,  0x19,  0xE4,  0x04,  0x00,  0x06,  0x12,  0x9E,  0xE7,
+  0x12,  0x00,  0x08,  0x10,  0xCB,  0xF0,  0x0C,  0x09,  0x9E,  0xE7,  0x24,  0x00,  0xB1,  0xF0,  0x0C,  0x09,
+  0x05,  0xF0,  0x1E,  0x09,  0x09,  0xF0,  0x24,  0x09,  0x1E,  0xF0,  0xFC,  0x09,  0xE4,  0x10,  0x00,  0xF2,
+  0x60,  0x0B,  0xE9,  0x10,  0x9C,  0x32,  0x82,  0xE7,  0x20,  0x00,  0x32,  0x1C,  0xE9,  0x09,  0x00,  0xF2,
+  0x12,  0x11,  0x85,  0xF0,  0x02,  0x0A,  0x69,  0x08,  0x01,  0xF0,  0x44,  0x09,  0x1E,  0xF0,  0xFC,  0x09,
+  0x00,  0xF0,  0x38,  0x09,  0x30,  0x44,  0x06,  0x12,  0x9E,  0xE7,  0x42,  0x00,  0xB8,  0x10,  0x04,  0xF6,
+  0x01,  0x00,  0xB3,  0x45,  0x74,  0x12,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,  0x22,  0x13,  0x4B,  0xE4,
+  0x02,  0x00,  0x36,  0x12,  0x4B,  0xE4,  0x28,  0x00,  0xAC,  0x13,  0x00,  0xF2,  0xBC,  0x11,  0x00,  0xF2,
+  0xC8,  0x11,  0x03,  0xF6,  0xD0,  0x00,  0xFA,  0x14,  0x82,  0xE7,  0x01,  0x00,  0x00,  0xF0,  0x80,  0x01,
+  0x9E,  0xE7,  0x44,  0x00,  0x4B,  0xE4,  0x02,  0x00,  0x06,  0x12,  0x03,  0xE6,  0x02,  0x00,  0x76,  0x10,
+  0x00,  0xF2,  0xA2,  0x0D,  0x03,  0xE6,  0x02,  0x00,  0x6C,  0x10,  0x00,  0xF2,  0xA2,  0x0D,  0x19,  0x82,
+  0x34,  0x46,  0x0A,  0x13,  0x03,  0xE6,  0x02,  0x00,  0x9E,  0xE7,  0x43,  0x00,  0x68,  0x10,  0x04,  0x80,
+  0x30,  0xE4,  0x20,  0x00,  0x04,  0x40,  0x00,  0xF2,  0xBC,  0x11,  0x00,  0xF2,  0xC8,  0x11,  0x82,  0xE7,
+  0x01,  0x00,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF0,  0x08,  0x03,  0x04,  0x80,  0x18,  0xE4,  0x20,  0x00,
+  0x06,  0x12,  0x03,  0xE6,  0x02,  0x00,  0x3E,  0x10,  0x04,  0x80,  0x18,  0xE4,  0x02,  0x00,  0x3A,  0x12,
+  0x04,  0x80,  0x18,  0xE4,  0xFD,  0x00,  0x04,  0x40,  0x1C,  0x1C,  0x9D,  0xF0,  0xEA,  0x09,  0x1C,  0x1C,
+  0x9D,  0xF0,  0xF0,  0x09,  0xC1,  0x10,  0x9E,  0xE7,  0x13,  0x00,  0x0A,  0x10,  0x9E,  0xE7,  0x41,  0x00,
+  0x04,  0x10,  0x9E,  0xE7,  0x24,  0x00,  0x00,  0xFC,  0xBE,  0x00,  0x98,  0x57,  0xD5,  0xF0,  0x8A,  0x02,
+  0x04,  0xE6,  0x04,  0x00,  0x06,  0x10,  0x04,  0xE6,  0x04,  0x00,  0x9D,  0x41,  0x1C,  0x42,  0x9F,  0xE7,
+  0x00,  0x00,  0x06,  0xF7,  0x02,  0x00,  0x03,  0xF6,  0xE0,  0x00,  0x3C,  0x14,  0x44,  0x58,  0x45,  0x58,
+  0x00,  0xF2,  0xF6,  0x0D,  0x00,  0xF2,  0x7E,  0x10,  0x00,  0xF2,  0xC6,  0x0F,  0x3C,  0x14,  0x1E,  0x1C,
+  0x00,  0xF0,  0x80,  0x01,  0x12,  0x1C,  0x22,  0x1C,  0xD2,  0x14,  0x00,  0xF0,  0x72,  0x01,  0x83,  0x59,
+  0x03,  0xDC,  0x73,  0x57,  0x80,  0x5D,  0x00,  0x16,  0x83,  0x59,  0x03,  0xDC,  0x38,  0x54,  0x70,  0x57,
+  0x33,  0x54,  0x3B,  0x54,  0x80,  0x5D,  0x00,  0x16,  0x03,  0x57,  0x83,  0x59,  0x38,  0x54,  0x00,  0xCC,
+  0x00,  0x16,  0x03,  0x57,  0x83,  0x59,  0x00,  0x4C,  0x00,  0x16,  0x02,  0x80,  0x48,  0xE4,  0x01,  0x00,
+  0x0E,  0x12,  0x48,  0xE4,  0x05,  0x00,  0x08,  0x12,  0x00,  0xF2,  0xBC,  0x11,  0x00,  0xF2,  0xC8,  0x11,
+  0xC1,  0x5A,  0x3A,  0x55,  0x02,  0xEC,  0xB5,  0x00,  0x45,  0x59,  0x00,  0xF2,  0xF6,  0x0D,  0x83,  0x58,
+  0x30,  0xE7,  0x00,  0x00,  0x10,  0x4D,  0x30,  0xE7,  0x40,  0x00,  0x10,  0x4F,  0x38,  0x90,  0xBA,  0x90,
+  0x10,  0x5C,  0x80,  0x5C,  0x83,  0x5A,  0x10,  0x4E,  0x04,  0xEA,  0xB5,  0x00,  0x43,  0x5B,  0x03,  0xF4,
+  0xE0,  0x00,  0x83,  0x59,  0x04,  0xCC,  0x01,  0x4A,  0x0A,  0x12,  0x45,  0x5A,  0x00,  0xF2,  0xF6,  0x0D,
+  0x00,  0xF2,  0x38,  0x10,  0x00,  0x16,  0x08,  0x1C,  0x00,  0xFC,  0xAC,  0x00,  0x06,  0x58,  0x67,  0x18,
+  0x18,  0xF4,  0x8F,  0xE1,  0x01,  0xFC,  0xAE,  0x00,  0x19,  0xF4,  0x70,  0x1E,  0xB0,  0x54,  0x07,  0x58,
+  0x00,  0xFC,  0xB0,  0x00,  0x08,  0x58,  0x00,  0xFC,  0xB2,  0x00,  0x09,  0x58,  0x0A,  0x1C,  0x00,  0xE6,
+  0x0F,  0x00,  0x00,  0xEA,  0xB9,  0x00,  0x38,  0x54,  0x00,  0xFA,  0x24,  0x01,  0x00,  0xFA,  0xB6,  0x00,
+  0x18,  0x1C,  0x14,  0x1C,  0x10,  0x1C,  0x32,  0x1C,  0x12,  0x1C,  0x00,  0x16,  0x3E,  0x57,  0x0C,  0x14,
+  0x0E,  0x47,  0x07,  0xE6,  0x10,  0x00,  0xCE,  0x47,  0xF5,  0x13,  0x00,  0x16,  0x00,  0xF2,  0xA2,  0x0D,
+  0x02,  0x4B,  0x03,  0xF6,  0xE0,  0x00,  0x00,  0xF2,  0x68,  0x0A,  0x01,  0x48,  0x20,  0x12,  0x44,  0x58,
+  0x45,  0x58,  0x9E,  0xE7,  0x15,  0x00,  0x9C,  0xE7,  0x04,  0x00,  0x00,  0xF2,  0xF6,  0x0D,  0x00,  0xF2,
+  0x7E,  0x10,  0x00,  0xF2,  0xC6,  0x0F,  0x00,  0xF2,  0x7A,  0x0A,  0x1E,  0x1C,  0xD5,  0x10,  0x00,  0x16,
+  0x69,  0x08,  0x48,  0xE4,  0x04,  0x00,  0x64,  0x12,  0x48,  0xE4,  0x02,  0x00,  0x20,  0x12,  0x48,  0xE4,
+  0x03,  0x00,  0x1A,  0x12,  0x48,  0xE4,  0x08,  0x00,  0x14,  0x12,  0x48,  0xE4,  0x01,  0x00,  0xF0,  0x12,
+  0x48,  0xE4,  0x07,  0x00,  0x12,  0x12,  0x01,  0xE6,  0x07,  0x00,  0x00,  0xF2,  0x4E,  0x0D,  0x00,  0xF2,
+  0x12,  0x11,  0x05,  0xF0,  0x60,  0x0B,  0x00,  0x16,  0x00,  0xE6,  0x01,  0x00,  0x00,  0xEA,  0x99,  0x00,
+  0x02,  0x80,  0x48,  0xE4,  0x03,  0x00,  0xE7,  0x12,  0x48,  0xE4,  0x06,  0x00,  0xE1,  0x12,  0x01,  0xE6,
+  0x06,  0x00,  0x00,  0xF2,  0x4E,  0x0D,  0x00,  0xF2,  0x12,  0x11,  0x04,  0xE6,  0x02,  0x00,  0x9E,  0xE7,
+  0x15,  0x00,  0x01,  0xF0,  0x1C,  0x0A,  0x00,  0xF0,  0x02,  0x0A,  0x00,  0x16,  0x02,  0x80,  0x48,  0xE4,
+  0x10,  0x00,  0x1C,  0x12,  0x82,  0xE7,  0x08,  0x00,  0x3C,  0x56,  0x03,  0x82,  0x00,  0xF2,  0xE2,  0x0D,
+  0x30,  0xE7,  0x08,  0x00,  0x04,  0xF7,  0x70,  0x01,  0x06,  0xF7,  0x02,  0x00,  0x00,  0xF0,  0x80,  0x01,
+  0x6C,  0x19,  0xED,  0x19,  0x5D,  0xF0,  0xD4,  0x0B,  0x44,  0x55,  0xE5,  0x55,  0x59,  0xF0,  0x52,  0x0C,
+  0x04,  0x55,  0xA5,  0x55,  0x1F,  0x80,  0x01,  0xEC,  0xB8,  0x00,  0x82,  0x48,  0x82,  0x80,  0x49,  0x44,
+  0x2E,  0x13,  0x01,  0xEC,  0xB8,  0x00,  0x41,  0xE4,  0x02,  0x00,  0x01,  0xEA,  0xB8,  0x00,  0x49,  0xE4,
+  0x11,  0x00,  0x59,  0xF0,  0x2E,  0x0C,  0x01,  0xE6,  0x17,  0x00,  0x01,  0xEA,  0xB8,  0x00,  0x02,  0x4B,
+  0x88,  0x90,  0xAC,  0x50,  0x8A,  0x90,  0xAE,  0x50,  0x01,  0xEC,  0xB8,  0x00,  0x82,  0x48,  0x82,  0x80,
+  0x10,  0x44,  0x02,  0x4B,  0x1F,  0x40,  0xC0,  0x44,  0x00,  0xF2,  0xB4,  0x0D,  0x04,  0x55,  0xA5,  0x55,
+  0x9F,  0x10,  0x0C,  0x51,  0x8E,  0x51,  0x30,  0x90,  0xB2,  0x90,  0x00,  0x56,  0xA1,  0x56,  0x30,  0x50,
+  0xB2,  0x50,  0x34,  0x90,  0xB6,  0x90,  0x40,  0x56,  0xE1,  0x56,  0x34,  0x50,  0xB6,  0x50,  0x65,  0x10,
+  0xB1,  0xF0,  0x70,  0x0C,  0x85,  0xF0,  0xCA,  0x0B,  0xE9,  0x09,  0x4B,  0xE4,  0x03,  0x00,  0x78,  0x12,
+  0x4B,  0xE4,  0x02,  0x00,  0x01,  0x13,  0xB1,  0xF0,  0x86,  0x0C,  0x85,  0xF0,  0xCA,  0x0B,  0x69,  0x08,
+  0x48,  0xE4,  0x03,  0x00,  0xD5,  0xF0,  0x86,  0x0B,  0x00,  0xF2,  0x12,  0x11,  0x85,  0xF0,  0xCA,  0x0B,
+  0xE8,  0x09,  0x3C,  0x56,  0x00,  0xFC,  0x20,  0x01,  0x98,  0x57,  0x02,  0x13,  0xBB,  0x45,  0x4B,  0xE4,
+  0x00,  0x00,  0x08,  0x12,  0x03,  0xE6,  0x01,  0x00,  0x04,  0xF6,  0x00,  0x80,  0xA8,  0x14,  0xD2,  0x14,
+  0x30,  0x1C,  0x02,  0x80,  0x48,  0xE4,  0x03,  0x00,  0x10,  0x13,  0x00,  0xFC,  0xB6,  0x00,  0x98,  0x57,
+  0x02,  0x13,  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF0,  0x8E,  0x0B,  0x00,  0xFC,  0x24,  0x01,  0xB0,  0x57,
+  0x00,  0xFA,  0x24,  0x01,  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,  0x8E,  0x0B,
+  0x00,  0xF2,  0x8C,  0x0E,  0x00,  0xF0,  0x8E,  0x0B,  0xB1,  0xF0,  0xF8,  0x0C,  0x85,  0xF0,  0x86,  0x0B,
+  0x69,  0x08,  0x48,  0xE4,  0x01,  0x00,  0xD5,  0xF0,  0x86,  0x0B,  0xFC,  0x14,  0x42,  0x58,  0x6C,  0x14,
+  0x80,  0x14,  0x30,  0x1C,  0x4A,  0xF4,  0x02,  0x00,  0x55,  0xF0,  0x86,  0x0B,  0x4A,  0xF4,  0x01,  0x00,
+  0x0E,  0x12,  0x02,  0x80,  0x48,  0xE4,  0x03,  0x00,  0x06,  0x13,  0x3E,  0x1C,  0x00,  0xF0,  0x8E,  0x0B,
+  0x00,  0xFC,  0xB6,  0x00,  0xB0,  0x57,  0x00,  0xFA,  0xB6,  0x00,  0x4C,  0x1C,  0x3E,  0x1C,  0x00,  0xF2,
+  0x12,  0x11,  0x86,  0xF0,  0x8E,  0x0B,  0x00,  0xF2,  0xBA,  0x0E,  0x00,  0xF0,  0x8E,  0x0B,  0x4C,  0x1C,
+  0xB1,  0xF0,  0x50,  0x0D,  0x85,  0xF0,  0x5C,  0x0D,  0x69,  0x08,  0xF3,  0x10,  0x86,  0xF0,  0x64,  0x0D,
+  0x4E,  0x1C,  0x89,  0x48,  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,
+  0x00,  0xDC,  0x18,  0xF4,  0xFF,  0x7F,  0x30,  0x56,  0x00,  0x5C,  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,
+  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x18,  0xF4,  0x00,  0x80,  0x30,  0x56,  0x00,  0x5C,
+  0x00,  0x16,  0x00,  0xF6,  0x00,  0x01,  0x00,  0x57,  0x00,  0x57,  0x03,  0x58,  0x00,  0xDC,  0x0B,  0x58,
+  0x00,  0x16,  0x03,  0xF6,  0x24,  0x01,  0x00,  0xF2,  0x58,  0x0A,  0x03,  0xF6,  0xB6,  0x00,  0x00,  0xF2,
+  0x58,  0x0A,  0x00,  0x16,  0x02,  0xEC,  0xB8,  0x00,  0x02,  0x49,  0x18,  0xF4,  0xFF,  0x00,  0x00,  0x54,
+  0x00,  0x54,  0x00,  0x54,  0x00,  0xF4,  0x08,  0x00,  0xE1,  0x18,  0x80,  0x54,  0x03,  0x58,  0x00,  0xDD,
+  0x01,  0xDD,  0x02,  0xDD,  0x03,  0xDC,  0x02,  0x4B,  0x30,  0x50,  0xB2,  0x50,  0x34,  0x51,  0xB6,  0x51,
+  0x00,  0x16,  0x45,  0x5A,  0x1D,  0xF4,  0xFF,  0x00,  0x85,  0x56,  0x85,  0x56,  0x85,  0x56,  0x05,  0xF4,
+  0x02,  0x12,  0x83,  0x5A,  0x00,  0x16,  0x1D,  0xF4,  0xFF,  0x00,  0x85,  0x56,  0x85,  0x56,  0x85,  0x56,
+  0x05,  0xF4,  0x00,  0x12,  0x83,  0x5A,  0x00,  0x16,  0x38,  0x54,  0xBB,  0x55,  0x3C,  0x56,  0xBD,  0x56,
+  0x00,  0xF2,  0x12,  0x11,  0x85,  0xF0,  0x82,  0x0E,  0xE9,  0x09,  0xC1,  0x59,  0x00,  0xF2,  0x12,  0x11,
+  0x85,  0xF0,  0x82,  0x0E,  0xE8,  0x0A,  0x83,  0x55,  0x83,  0x55,  0x4B,  0xF4,  0x90,  0x01,  0x5C,  0xF0,
+  0x36,  0x0E,  0xBD,  0x56,  0x40,  0x10,  0x4B,  0xF4,  0x30,  0x00,  0x59,  0xF0,  0x48,  0x0E,  0x01,  0xF6,
+  0x0C,  0x00,  0x00,  0xF6,  0x01,  0x00,  0x2E,  0x10,  0x02,  0xFC,  0x9C,  0x00,  0x9A,  0x57,  0x14,  0x13,
+  0x4B,  0xF4,  0x64,  0x00,  0x59,  0xF0,  0x64,  0x0E,  0x03,  0xF6,  0x64,  0x00,  0x01,  0xF6,  0x19,  0x00,
+  0x00,  0xF6,  0x01,  0x00,  0x43,  0xF4,  0x33,  0x00,  0x56,  0xF0,  0x76,  0x0E,  0x04,  0xF4,  0x00,  0x01,
+  0x43,  0xF4,  0x19,  0x00,  0xF3,  0x10,  0xB4,  0x56,  0xC3,  0x58,  0x02,  0xFC,  0x9E,  0x00,  0x9A,  0x57,
+  0x08,  0x13,  0x3C,  0x56,  0x00,  0xF6,  0x02,  0x00,  0x00,  0x16,  0x00,  0x16,  0x09,  0xE7,  0x01,  0x00,
+  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,  0xB8,  0x0E,  0x09,  0xE7,  0x02,  0x00,  0x00,  0xF2,  0x12,  0x11,
+  0x86,  0xF0,  0xB8,  0x0E,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,  0xB8,  0x0E,
+  0x4E,  0x1C,  0x89,  0x49,  0x00,  0xF2,  0x12,  0x11,  0x00,  0x16,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,
+  0x12,  0x11,  0x86,  0xF0,  0xF2,  0x0E,  0x09,  0xE7,  0x03,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,
+  0xF2,  0x0E,  0x09,  0xE7,  0x01,  0x00,  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,  0xF2,  0x0E,  0x89,  0x49,
+  0x00,  0xF2,  0x12,  0x11,  0x86,  0xF0,  0xF2,  0x0E,  0x4E,  0x1C,  0x89,  0x4A,  0x00,  0xF2,  0x12,  0x11,
+  0x00,  0x16,  0x3C,  0x56,  0x00,  0x16,  0x00,  0xEC,  0x26,  0x01,  0x48,  0xE4,  0x01,  0x00,  0x1E,  0x13,
+  0x38,  0x44,  0x00,  0xEA,  0x26,  0x01,  0x49,  0xF4,  0x00,  0x00,  0x04,  0x12,  0x4E,  0x1C,  0x02,  0x10,
+  0x4C,  0x1C,  0x01,  0xEC,  0x27,  0x01,  0x89,  0x48,  0x00,  0xF2,  0x12,  0x11,  0x02,  0x14,  0x00,  0x16,
+  0x85,  0xF0,  0x52,  0x0F,  0x38,  0x54,  0x00,  0xEA,  0x99,  0x00,  0x00,  0xF2,  0x60,  0x0B,  0x02,  0x80,
+  0x48,  0xE4,  0x06,  0x00,  0x1C,  0x13,  0x00,  0xEC,  0x99,  0x00,  0x48,  0xE4,  0x01,  0x00,  0x0A,  0x12,
+  0x04,  0x80,  0x30,  0xE4,  0x01,  0x00,  0x04,  0x40,  0x08,  0x10,  0x04,  0x80,  0x18,  0xE4,  0xFE,  0x00,
+  0x04,  0x40,  0x00,  0x16,  0x02,  0xF6,  0xE0,  0x00,  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x81,  0x48,
+  0x22,  0x12,  0x00,  0x4E,  0x83,  0x5A,  0x90,  0x4C,  0x20,  0xE7,  0x00,  0x00,  0xC3,  0x58,  0x1B,  0xF4,
+  0xFF,  0x00,  0x83,  0x55,  0x83,  0x55,  0x83,  0x55,  0x03,  0xF4,  0x00,  0x12,  0x8B,  0x55,  0x83,  0x59,
+  0x00,  0x4E,  0x00,  0x16,  0x00,  0x4E,  0x02,  0xF6,  0xF0,  0x00,  0x02,  0x57,  0x03,  0x59,  0x00,  0x4E,
+  0x83,  0x5A,  0x30,  0xE7,  0x00,  0x00,  0x20,  0xE7,  0x00,  0x00,  0x00,  0x16,  0x02,  0xF6,  0xF0,  0x00,
+  0x02,  0x57,  0x03,  0x59,  0x01,  0xCC,  0x00,  0x4E,  0x83,  0x5A,  0x30,  0xE7,  0x00,  0x00,  0x80,  0x4C,
+  0xC3,  0x58,  0x1B,  0xF4,  0xFF,  0x00,  0x83,  0x55,  0x83,  0x55,  0x83,  0x55,  0x03,  0xF4,  0x00,  0x12,
+  0x83,  0x59,  0x00,  0x4E,  0x00,  0x16,  0x03,  0xF6,  0xE0,  0x00,  0x03,  0x57,  0x83,  0x59,  0x3A,  0x55,
+  0x02,  0xCC,  0x45,  0x5A,  0x00,  0xF2,  0xF6,  0x0D,  0xC0,  0x5A,  0x40,  0x5C,  0x38,  0x54,  0x00,  0xCD,
+  0x01,  0xCC,  0x4A,  0x46,  0x0A,  0x13,  0x83,  0x59,  0x00,  0x4C,  0x01,  0x48,  0x16,  0x13,  0x0C,  0x10,
+  0xC5,  0x58,  0x00,  0xF2,  0xF6,  0x0D,  0x00,  0x4C,  0x01,  0x48,  0x08,  0x13,  0x05,  0xF6,  0xF0,  0x00,
+  0x05,  0x57,  0x08,  0x10,  0x45,  0x58,  0x00,  0xF2,  0xF6,  0x0D,  0x8D,  0x56,  0x83,  0x5A,  0x80,  0x4C,
+  0x05,  0x17,  0x00,  0x16,  0x02,  0x4B,  0x06,  0xF7,  0x04,  0x00,  0x62,  0x0B,  0x03,  0x82,  0x00,  0xF2,
+  0xE2,  0x0D,  0x02,  0x80,  0x00,  0x4C,  0x45,  0xF4,  0x02,  0x00,  0x52,  0x14,  0x06,  0xF7,  0x02,  0x00,
+  0x06,  0x14,  0x00,  0xF2,  0x54,  0x0F,  0x00,  0x16,  0x02,  0x4B,  0x01,  0xF6,  0xFF,  0x00,  0x38,  0x1C,
+  0x05,  0xF4,  0x04,  0x00,  0x83,  0x5A,  0x18,  0xDF,  0x19,  0xDF,  0x1D,  0xF7,  0x3C,  0x00,  0xB8,  0xF0,
+  0x4E,  0x10,  0x9C,  0x14,  0x01,  0x48,  0x1C,  0x13,  0x0E,  0xF7,  0x3C,  0x00,  0x03,  0xF7,  0x04,  0x00,
+  0xAF,  0x19,  0x03,  0x42,  0x45,  0xF4,  0x02,  0x00,  0x83,  0x5A,  0x02,  0xCC,  0x02,  0x41,  0x45,  0xF4,
+  0x02,  0x00,  0x00,  0x16,  0x91,  0x44,  0xD5,  0xF0,  0x3E,  0x10,  0x00,  0xF0,  0x9E,  0x02,  0x01,  0xF6,
+  0xFF,  0x00,  0x38,  0x1C,  0x05,  0xF4,  0x04,  0x00,  0x83,  0x5A,  0x18,  0xDF,  0x19,  0xDF,  0x0E,  0xF7,
+  0x3C,  0x00,  0x03,  0xF7,  0x04,  0x00,  0x0F,  0x79,  0x1C,  0xF7,  0x3C,  0x00,  0xB8,  0xF0,  0x9C,  0x10,
+  0x4E,  0x14,  0x01,  0x48,  0x06,  0x13,  0x45,  0xF4,  0x04,  0x00,  0x00,  0x16,  0x91,  0x44,  0xD5,  0xF0,
+  0x82,  0x10,  0x00,  0xF0,  0x9E,  0x02,  0x02,  0xF6,  0xFF,  0x00,  0x38,  0x1C,  0x2C,  0xBC,  0xAE,  0xBC,
+  0xE2,  0x08,  0x00,  0xEC,  0xB8,  0x00,  0x02,  0x48,  0x1D,  0xF7,  0x80,  0x00,  0xB8,  0xF0,  0xCC,  0x10,
+  0x1E,  0x14,  0x01,  0x48,  0x0E,  0x13,  0x0E,  0xF7,  0x80,  0x00,  0x38,  0x54,  0x03,  0x58,  0xAF,  0x19,
+  0x82,  0x48,  0x00,  0x16,  0x82,  0x48,  0x12,  0x45,  0xD5,  0xF0,  0xBA,  0x10,  0x00,  0xF0,  0x9E,  0x02,
+  0x39,  0xF0,  0xF8,  0x10,  0x38,  0x44,  0x00,  0x16,  0x7E,  0x18,  0x18,  0xF4,  0x03,  0x00,  0x04,  0x13,
+  0x61,  0x18,  0x00,  0x16,  0x38,  0x1C,  0x00,  0xFC,  0x22,  0x01,  0x18,  0xF4,  0x01,  0x00,  0xF1,  0x12,
+  0xE3,  0x10,  0x30,  0x44,  0x30,  0x44,  0x30,  0x44,  0xB1,  0xF0,  0x18,  0x11,  0x00,  0x16,  0x3E,  0x57,
+  0x03,  0xF6,  0xE0,  0x00,  0x03,  0x57,  0x83,  0x59,  0x04,  0xCC,  0x01,  0x4A,  0x6A,  0x12,  0x45,  0x5A,
+  0x00,  0xF2,  0xF6,  0x0D,  0x02,  0x4B,  0x70,  0x14,  0x34,  0x13,  0x02,  0x80,  0x48,  0xE4,  0x08,  0x00,
+  0x18,  0x12,  0x9C,  0xE7,  0x02,  0x00,  0x9E,  0xE7,  0x15,  0x00,  0x00,  0xF2,  0xC6,  0x0F,  0x00,  0xF2,
+  0x7A,  0x0A,  0x1E,  0x1C,  0x01,  0xF6,  0x01,  0x00,  0x00,  0x16,  0x30,  0xE4,  0x10,  0x00,  0x04,  0x40,
+  0x00,  0xF2,  0xE2,  0x0D,  0x20,  0xE7,  0x01,  0x00,  0x01,  0xF6,  0x01,  0x00,  0x00,  0x16,  0x04,  0xDC,
+  0x01,  0x4A,  0x24,  0x12,  0x45,  0x5A,  0x00,  0xF2,  0xF6,  0x0D,  0x43,  0x5B,  0x06,  0xEC,  0x98,  0x00,
+  0x00,  0xF2,  0x38,  0x10,  0xC6,  0x59,  0x20,  0x14,  0x0A,  0x13,  0x00,  0xF2,  0xC6,  0x0F,  0x00,  0xF2,
+  0x14,  0x10,  0xA7,  0x10,  0x83,  0x5A,  0xD7,  0x10,  0x0E,  0x47,  0x07,  0xE6,  0x10,  0x00,  0xCE,  0x47,
+  0x5A,  0xF0,  0x20,  0x11,  0xB9,  0x54,  0x00,  0x16,  0x14,  0x90,  0x96,  0x90,  0x02,  0xFC,  0xA8,  0x00,
+  0x03,  0xFC,  0xAA,  0x00,  0x48,  0x55,  0x02,  0x13,  0xC9,  0x55,  0x00,  0x16,  0x00,  0xEC,  0xBA,  0x00,
+  0x10,  0x44,  0x00,  0xEA,  0xBA,  0x00,  0x00,  0x16,  0x03,  0xF6,  0xC0,  0x00,  0x00,  0xF2,  0x68,  0x0A,
+  0x10,  0x44,  0x00,  0x4C,  0x00,  0x16
+};
 
 unsigned short _adv_mcode_size ASC_INITDATA =
-    sizeof(_adv_mcode_buf); /* 0x11D2 */
-unsigned long  _adv_mcode_chksum ASC_INITDATA = 0x0347D07AUL;
+    sizeof(_adv_mcode_buf); /* 0x11D6 */
+unsigned long  _adv_mcode_chksum ASC_INITDATA = 0x03494981UL;
 
 /* a_init.c */
 /*
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.1.100/linux/drivers/scsi/aic7xxx.c	Tue Apr 14 14:29:21 1998
+++ linux/drivers/scsi/aic7xxx.c	Fri May  8 00:22:11 1998
@@ -242,7 +242,7 @@
 #  include <linux/bios32.h>
 #endif
 
-#if !defined(__alpha__)
+#if !defined(__alpha__) && !defined(__sparc__)
 #  define MMAPIO
 #endif
 
@@ -950,10 +950,10 @@
   unsigned short           needwdtr_copy;    /* default config */
   unsigned short           ultraenb;         /* Ultra mode target list */
   unsigned short           bios_control;     /* bios control - SEEPROM */
+  unsigned int             irq;              /* IRQ for this adapter */
   unsigned short           adapter_control;  /* adapter control - SEEPROM */
   unsigned char            pci_bus;
   unsigned char            pci_device_fn;
-  unsigned char            irq;              /* IRQ for this adapter */
 
 #ifdef AIC7XXX_PROC_STATS
   /*
@@ -5245,6 +5245,7 @@
   }
 }
 
+#if defined(__i386__) || defined(__alpha__)
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_probe
@@ -5322,6 +5323,7 @@
 
   return (AHC_NONE);
 }
+#endif /* __i386__ || __alpha__ */
 
 /*+F*************************************************************************
  * Function:
@@ -7266,7 +7268,7 @@
     unsigned short command;
     unsigned int  devconfig, i;
 #ifdef MMAPIO
-    unsigned long page_offset;
+    unsigned long page_offset, base;
 #endif
     struct aic7xxx_host *first_7895 = NULL;
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,92)
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/amiga7xx.c linux/drivers/scsi/amiga7xx.c
--- v2.1.100/linux/drivers/scsi/amiga7xx.c	Thu Mar 26 15:57:03 1998
+++ linux/drivers/scsi/amiga7xx.c	Fri May  8 00:22:11 1998
@@ -33,17 +33,14 @@
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
-extern ncr53c7xx_init (Scsi_Host_Template *tpnt, int board, int chip, 
-		       u32 base, int io_port, int irq, int dma,
-		       long long options, int clock);
-
 int amiga7xx_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
     unsigned int key;
-    int num = 0, clock;
+    int num = 0;
+    unsigned long address;
     long long options;
-    const struct ConfigDev *cd;
+    struct ConfigDev *cd;
 
     if (called || !MACH_IS_AMIGA)
 	return 0;
@@ -53,7 +50,6 @@
 #ifdef CONFIG_WARPENGINE_SCSI
     if ((key = zorro_find(ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx, 0, 0)))
     {
-	unsigned long address;
 	cd = zorro_get_board(key);
 	address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr,
 		cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL);
@@ -87,9 +83,8 @@
 
 #ifdef CONFIG_A4091_SCSI
     while ( (key = zorro_find(ZORRO_PROD_CBM_A4091_1, 0, 0)) ||
-	    (key = zorro_find(ZORRO_PROD_CBM_A4091_2, 0, 0)) )
+	 (key = zorro_find(ZORRO_PROD_CBM_A4091_2, 0, 0)) )
     {
-	unsigned long address;
 	cd = zorro_get_board(key);
 	address = (unsigned long)kernel_map((unsigned long)cd->cd_BoardAddr,
 		cd->cd_BoardSize, KERNELMAP_NOCACHE_SER, NULL);
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz1230.c linux/drivers/scsi/blz1230.c
--- v2.1.100/linux/drivers/scsi/blz1230.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/blz1230.c	Fri May  8 00:22:11 1998
@@ -0,0 +1,269 @@
+/* blz1230.c: Driver for Blizzard 1230 SCSI IV Controller.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * This driver is based on the CyberStorm driver, hence the occasional
+ * reference to CyberStorm.
+ */
+
+/* TODO:
+ *
+ * 1) Figure out how to make a cleaner merge with the sparc driver with regard
+ *    to the caches and the Sparc MMU mapping.
+ * 2) Make as few routines required outside the generic driver. A lot of the
+ *    routines in this file used to be inline!
+ */
+
+#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 "blz1230.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include <asm/pgtable.h>
+
+#define MKIV 1
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, 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);
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int blz1230_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	unsigned int key;
+	unsigned long address;
+	struct ESP_regs *eregs;
+
+#if MKIV
+	if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260, 0, 0))){
+#else
+	if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, 0, 0))){
+#endif
+		esp_dev = zorro_get_board(key);
+
+		/* Do some magic to figure out if the blizzard is
+		 * equipped with a SCSI controller
+		 */
+		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
+#if MKIV
+		eregs = (struct ESP_regs *)(address + BLZ1230_ESP_ADDR);
+#else
+		eregs = (struct ESP_regs *)(address + BLZ1230II_ESP_ADDR);
+#endif
+
+		eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7);
+		udelay(5);
+		if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7))
+			return 0; /* Bail out if address did not hold data */
+
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = 0;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = 0;
+		esp->dma_led_on = 0;
+		esp->dma_led_off = 0;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		/* SCSI chip speed */
+		esp->cfreq = 40000000;
+
+		/* The DMA registers on the Blizzard are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+#if MKIV
+		esp->dregs = (void *)(address + BLZ1230_DMA_ADDR);
+#else
+		esp->dregs = (void *)(address + BLZ1230II_DMA_ADDR);
+#endif	
+	
+		/* ESP register base */
+		esp->eregs = eregs;
+
+		/* Set the command buffer */
+		esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer);
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+			    "Blizzard 1230 SCSI IV", esp_intr);
+
+		/* Figure out our scsi ID on the bus */
+		esp->scsi_id = 7;
+		
+		/* Check for differential SCSI-bus */
+		/* What is this stuff? */
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+
+		printk("\nESP: 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 int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the Blizzard DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	/* I don't think there's any limit on the Blizzard DMA. So we use what
+	 * the ESP chip can handle (24 bit).
+	 */
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > 0x1000000)
+		sz = 0x1000000;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
+		custom.intreqr, custom.intenar));
+}
+
+void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+#if MKIV
+	struct blz1230_dma_registers *dregs = 
+		(struct blz1230_dma_registers *) (esp->dregs);
+#else
+	struct blz1230II_dma_registers *dregs = 
+		(struct blz1230II_dma_registers *) (esp->dregs);
+#endif
+
+	cache_clear(addr, length);
+
+	addr >>= 1;
+	addr &= ~(BLZ1230_DMA_WRITE);
+
+	/* First set latch */
+	dregs->dma_latch = (addr >> 24) & 0xff;
+
+	/* Then pump the address to the DMA address register */
+#if MKIV
+	dregs->dma_addr = (addr >> 24) & 0xff;
+#endif
+	dregs->dma_addr = (addr >> 16) & 0xff;
+	dregs->dma_addr = (addr >>  8) & 0xff;
+	dregs->dma_addr = (addr      ) & 0xff;
+}
+
+void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+#if MKIV
+	struct blz1230_dma_registers *dregs = 
+		(struct blz1230_dma_registers *) (esp->dregs);
+#else
+	struct blz1230II_dma_registers *dregs = 
+		(struct blz1230II_dma_registers *) (esp->dregs);
+#endif
+
+	cache_push(addr, length);
+
+	addr >>= 1;
+	addr |= BLZ1230_DMA_WRITE;
+
+	/* First set latch */
+	dregs->dma_latch = (addr >> 24) & 0xff;
+
+	/* Then pump the address to the DMA address register */
+#if MKIV
+	dregs->dma_addr = (addr >> 24) & 0xff;
+#endif
+	dregs->dma_addr = (addr >> 16) & 0xff;
+	dregs->dma_addr = (addr >>  8) & 0xff;
+	dregs->dma_addr = (addr      ) & 0xff;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+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)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+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);
+	}
+}
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz1230.h linux/drivers/scsi/blz1230.h
--- v2.1.100/linux/drivers/scsi/blz1230.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/blz1230.h	Fri May  8 00:22:11 1998
@@ -0,0 +1,82 @@
+/* blz1230.h: Defines and structures for the Blizzard 1230 SCSI IV driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * This file is based on cyber_esp.h (hence the occasional reference to
+ * CyberStorm).
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef BLZ1230_H
+#define BLZ1230_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define BLZ1230_ESP_ADDR 0x8000
+#define BLZ1230_DMA_ADDR 0x10000
+#define BLZ1230II_ESP_ADDR 0x10000
+#define BLZ1230II_DMA_ADDR 0x10021
+
+
+/* The Blizzard 1230 DMA interface
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Only two things can be programmed in the Blizzard DMA:
+ *  1) The data direction is controlled by the status of bit 31 (1 = write)
+ *  2) The source/dest address (word aligned, shifted one right) in bits 30-0
+ *
+ * Program DMA by first latching the highest byte of the address/direction
+ * (i.e. bits 31-24 of the long word constructed as described in steps 1+2
+ * above). Then write each byte of the address/direction (starting with the
+ * top byte, working down) to the DMA address register.
+ *
+ * Figure out interrupt status by reading the ESP status byte.
+ */
+struct blz1230_dma_registers {
+	volatile unsigned char dma_addr; 	/* DMA address      [0x0000] */
+	unsigned char dmapad2[0x7fff];
+	volatile unsigned char dma_latch; 	/* DMA latch        [0x8000] */
+};
+
+struct blz1230II_dma_registers {
+	volatile unsigned char dma_addr; 	/* DMA address      [0x0000] */
+	unsigned char dmapad2[0xf];
+	volatile unsigned char dma_latch; 	/* DMA latch        [0x0010] */
+};
+
+#define BLZ1230_DMA_WRITE 0x80000000
+
+extern int blz1230_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_BLZ1230 {                                                               \
+/* struct SHT *next */                                         NULL,                   \
+/* long *usage_count */                                        NULL,                   \
+/* struct proc_dir_entry *proc_dir */                          &proc_scsi_esp,         \
+/* int (*proc_info)(char *, char **, off_t, int, int, int) */  &esp_proc_info,                   \
+/* const char *name */                                         "Blizzard1230 SCSI IV", \
+/* int detect(struct SHT *) */                                 blz1230_esp_detect,             \
+/* int release(struct Scsi_Host *) */                          NULL,                   \
+/* const char *info(struct Scsi_Host *) */                     esp_info,               \
+/* int command(Scsi_Cmnd *) */                                 esp_command,            \
+/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue,              \
+/* int abort(Scsi_Cmnd *) */                                   esp_abort,              \
+/* int reset(Scsi_Cmnd *) */                                   esp_reset,              \
+/* int slave_attach(int, int) */                               NULL,                   \
+/* int bios_param(Disk *, kdev_t, int[]) */                    NULL,                   \
+/* int can_queue */                                            7,                      \
+/* int this_id */                                              7,                      \
+/* short unsigned int sg_tablesize */                          SG_ALL,                 \
+/* short cmd_per_lun */                                        1,                      \
+/* unsigned char present */                                    0,                      \
+/* unsigned unchecked_isa_dma:1 */                             0,                      \
+/* unsigned use_clustering:1 */                                DISABLE_CLUSTERING, }
+
+#endif /* BLZ1230_H */
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz2060.c linux/drivers/scsi/blz2060.c
--- v2.1.100/linux/drivers/scsi/blz2060.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/blz2060.c	Fri May  8 00:22:11 1998
@@ -0,0 +1,232 @@
+/* blz2060.c: Driver for Blizzard 2060 SCSI Controller.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * This driver is based on the CyberStorm driver, hence the occasional
+ * reference to CyberStorm.
+ */
+
+/* TODO:
+ *
+ * 1) Figure out how to make a cleaner merge with the sparc driver with regard
+ *    to the caches and the Sparc MMU mapping.
+ * 2) Make as few routines required outside the generic driver. A lot of the
+ *    routines in this file used to be inline!
+ */
+
+#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 "blz2060.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include <asm/pgtable.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, 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 void dma_led_off(struct NCR_ESP *esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int blz2060_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	unsigned int key;
+	unsigned long address;
+
+	if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_2060, 0, 0))){
+		esp_dev = zorro_get_board(key);
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = 0;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = 0;
+		esp->dma_led_on = &dma_led_on;
+		esp->dma_led_off = &dma_led_off;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		/* SCSI chip speed */
+		esp->cfreq = 40000000;
+
+		/* The DMA registers on the Blizzard are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
+		esp->dregs = (void *)(address + BLZ2060_DMA_ADDR);
+
+		/* ESP register base */
+		esp->eregs = (struct ESP_regs *)(address + BLZ2060_ESP_ADDR);
+		
+		/* Set the command buffer */
+		esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer);
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+			    "Blizzard 2060 SCSI", esp_intr);
+
+		/* Figure out our scsi ID on the bus */
+		esp->scsi_id = 7;
+		
+		/* Check for differential SCSI-bus */
+		/* What is this stuff? */
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+
+		printk("\nESP: 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 int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the Blizzard DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	/* I don't think there's any limit on the Blizzard DMA. So we use what
+	 * the ESP chip can handle (24 bit).
+	 */
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > 0x1000000)
+		sz = 0x1000000;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
+		custom.intreqr, custom.intenar));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct blz2060_dma_registers *dregs = 
+		(struct blz2060_dma_registers *) (esp->dregs);
+
+	cache_clear(addr, length);
+
+	addr >>= 1;
+	addr &= ~(BLZ2060_DMA_WRITE);
+	dregs->dma_addr3 = (addr      ) & 0xff;
+	dregs->dma_addr2 = (addr >>  8) & 0xff;
+	dregs->dma_addr1 = (addr >> 16) & 0xff;
+	dregs->dma_addr0 = (addr >> 24) & 0xff;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct blz2060_dma_registers *dregs = 
+		(struct blz2060_dma_registers *) (esp->dregs);
+
+	cache_push(addr, length);
+
+	addr >>= 1;
+	addr |= BLZ2060_DMA_WRITE;
+	dregs->dma_addr3 = (addr      ) & 0xff;
+	dregs->dma_addr2 = (addr >>  8) & 0xff;
+	dregs->dma_addr1 = (addr >> 16) & 0xff;
+	dregs->dma_addr0 = (addr >> 24) & 0xff;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	return (esp->eregs->esp_status & ESP_STAT_INTR);
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+	((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl =
+		BLZ2060_DMA_LED;
+}
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+	((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl = 0;
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+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);
+	}
+}
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/blz2060.h linux/drivers/scsi/blz2060.h
--- v2.1.100/linux/drivers/scsi/blz2060.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/blz2060.h	Fri May  8 00:22:11 1998
@@ -0,0 +1,78 @@
+/* blz2060.h: Defines and structures for the Blizzard 2060 SCSI driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * This file is based on cyber_esp.h (hence the occasional reference to
+ * CyberStorm).
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef BLZ2060_H
+#define BLZ2060_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define BLZ2060_ESP_ADDR 0x1ff00
+#define BLZ2060_DMA_ADDR 0x1ffe0
+
+
+/* The Blizzard 2060 DMA interface
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Only two things can be programmed in the Blizzard DMA:
+ *  1) The data direction is controlled by the status of bit 31 (1 = write)
+ *  2) The source/dest address (word aligned, shifted one right) in bits 30-0
+ *
+ * Figure out interrupt status by reading the ESP status byte.
+ */
+struct blz2060_dma_registers {
+	volatile unsigned char dma_led_ctrl;	/* DMA led control   [0x000] */
+	unsigned char dmapad1[0x0f];
+	volatile unsigned char dma_addr0; 	/* DMA address (MSB) [0x010] */
+	unsigned char dmapad2[0x03];
+	volatile unsigned char dma_addr1; 	/* DMA address       [0x014] */
+	unsigned char dmapad3[0x03];
+	volatile unsigned char dma_addr2; 	/* DMA address       [0x018] */
+	unsigned char dmapad4[0x03];
+	volatile unsigned char dma_addr3; 	/* DMA address (LSB) [0x01c] */
+};
+
+#define BLZ2060_DMA_WRITE 0x80000000
+
+/* DMA control bits */
+#define BLZ2060_DMA_LED    0x02		/* HD led control 1 = off */
+
+extern int blz2060_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_BLZ2060 {                                                               \
+/* struct SHT *next */                                         NULL,                   \
+/* long *usage_count */                                        NULL,                   \
+/* struct proc_dir_entry *proc_dir */                          &proc_scsi_esp,         \
+/* int (*proc_info)(char *, char **, off_t, int, int, int) */  &esp_proc_info,                   \
+/* const char *name */                                         "Blizzard2060 SCSI", \
+/* int detect(struct SHT *) */                                 blz2060_esp_detect,             \
+/* int release(struct Scsi_Host *) */                          NULL,                   \
+/* const char *info(struct Scsi_Host *) */                     esp_info,               \
+/* int command(Scsi_Cmnd *) */                                 esp_command,            \
+/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue,              \
+/* int abort(Scsi_Cmnd *) */                                   esp_abort,              \
+/* int reset(Scsi_Cmnd *) */                                   esp_reset,              \
+/* int slave_attach(int, int) */                               NULL,                   \
+/* int bios_param(Disk *, kdev_t, int[]) */                    NULL,                   \
+/* int can_queue */                                            7,                      \
+/* int this_id */                                              7,                      \
+/* short unsigned int sg_tablesize */                          SG_ALL,                 \
+/* short cmd_per_lun */                                        1,                      \
+/* unsigned char present */                                    0,                      \
+/* unsigned unchecked_isa_dma:1 */                             0,                      \
+/* unsigned use_clustering:1 */                                DISABLE_CLUSTERING, }
+
+#endif /* BLZ2060_H */
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstorm.c linux/drivers/scsi/cyberstorm.c
--- v2.1.100/linux/drivers/scsi/cyberstorm.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/cyberstorm.c	Fri May  8 00:22:12 1998
@@ -0,0 +1,297 @@
+/* cyberstorm.c: Driver for CyberStorm SCSI Controller.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * The CyberStorm SCSI driver is based on David S. Miller's ESP driver
+ * for the Sparc computers. 
+ * 
+ * This work was made possible by Phase5 who willingly (and most generously)
+ * supported me with hardware and all the information I needed.
+ */
+
+/* TODO:
+ *
+ * 1) Figure out how to make a cleaner merge with the sparc driver with regard
+ *    to the caches and the Sparc MMU mapping.
+ * 2) Make as few routines required outside the generic driver. A lot of the
+ *    routines in this file used to be inline!
+ */
+
+#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 "cyberstorm.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include <asm/pgtable.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, 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 void dma_led_off(struct NCR_ESP *esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+
+static unsigned char ctrl_data = 0;	/* Keep backup of the stuff written
+				 * to ctrl_reg. Always write a copy
+				 * to this register when writing to
+				 * the hardware register!
+				 */
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int cyber_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	unsigned int key;
+	unsigned long address;
+
+
+	if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, 0, 0)) ||
+	    (key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, 0, 0))){
+		esp_dev = zorro_get_board(key);
+
+		/* Figure out if this is a CyberStorm or really a 
+		 * Fastlane/Blizzard Mk II by looking at the board size.
+		 * CyberStorm maps 64kB
+		 * (ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM does anyway)
+		 */
+		if((unsigned long)esp_dev->cd_BoardSize != 0x10000)
+			return 0;
+
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = 0;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = 0;
+		esp->dma_led_on = &dma_led_on;
+		esp->dma_led_off = &dma_led_off;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		/* SCSI chip speed */
+		esp->cfreq = 40000000;
+
+		/* The DMA registers on the CyberStorm are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
+		esp->dregs = (void *)(address + CYBER_DMA_ADDR);
+
+		/* ESP register base */
+		esp->eregs = (struct ESP_regs *)(address + CYBER_ESP_ADDR);
+		
+		/* Set the command buffer */
+		esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer);
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+			    "CyberStorm SCSI", esp_intr);
+		/* Figure out our scsi ID on the bus */
+		/* The DMA cond flag contains a hardcoded jumper bit
+		 * which can be used to select host number 6 or 7.
+		 * However, even though it may change, we use a hardcoded
+		 * value of 7.
+		 */
+		esp->scsi_id = 7;
+		
+		/* Check for differential SCSI-bus */
+		/* What is this stuff? */
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+
+		printk("\nESP: 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 int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	/* I don't think there's any limit on the CyberDMA. So we use what
+	 * the ESP chip can handle (24 bit).
+	 */
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > 0x1000000)
+		sz = 0x1000000;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
+		esp->esp_id, ((struct cyber_dma_registers *)
+			      (esp->dregs))->cond_reg));
+	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
+		custom.intreqr, custom.intenar));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct cyber_dma_registers *dregs = 
+		(struct cyber_dma_registers *) esp->dregs;
+
+	cache_clear(addr, length);
+
+	addr &= ~(1);
+	dregs->dma_addr0 = (addr >> 24) & 0xff;
+	dregs->dma_addr1 = (addr >> 16) & 0xff;
+	dregs->dma_addr2 = (addr >>  8) & 0xff;
+	dregs->dma_addr3 = (addr      ) & 0xff;
+	ctrl_data &= ~(CYBER_DMA_WRITE);
+
+	/* Check if physical address is outside Z2 space and of
+	 * block length/block aligned in memory. If this is the
+	 * case, enable 32 bit transfer. In all other cases, fall back
+	 * to 16 bit transfer.
+	 * Obviously 32 bit transfer should be enabled if the DMA address
+	 * and length are 32 bit aligned. However, this leads to some
+	 * strange behavior. Even 64 bit aligned addr/length fails.
+	 * Until I've found a reason for this, 32 bit transfer is only
+	 * used for full-block transfers (1kB).
+	 *							-jskov
+	 */
+#if 0
+	if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) &&
+						(addr < 0xff0000)))
+		ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
+	else
+		ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */
+#else
+	ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
+#endif
+	dregs->ctrl_reg = ctrl_data;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct cyber_dma_registers *dregs = 
+		(struct cyber_dma_registers *) esp->dregs;
+
+	cache_push(addr, length);
+
+	addr |= 1;
+	dregs->dma_addr0 = (addr >> 24) & 0xff;
+	dregs->dma_addr1 = (addr >> 16) & 0xff;
+	dregs->dma_addr2 = (addr >>  8) & 0xff;
+	dregs->dma_addr3 = (addr      ) & 0xff;
+	ctrl_data |= CYBER_DMA_WRITE;
+
+	/* See comment above */
+#if 0
+	if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) &&
+						(addr < 0xff0000)))
+		ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
+	else
+		ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */
+#else
+	ctrl_data &= ~(CYBER_DMA_Z3);	/* Z2, do 16 bit DMA */
+#endif
+	dregs->ctrl_reg = ctrl_data;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	/* It's important to check the DMA IRQ bit in the correct way! */
+	return ((esp->eregs->esp_status & ESP_STAT_INTR) &&
+		((((struct cyber_dma_registers *)(esp->dregs))->cond_reg) &
+		 CYBER_DMA_HNDL_INTR));
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+	ctrl_data &= ~CYBER_DMA_LED;
+	((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
+}
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+	ctrl_data |= CYBER_DMA_LED;
+	((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+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);
+	}
+}
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstorm.h linux/drivers/scsi/cyberstorm.h
--- v2.1.100/linux/drivers/scsi/cyberstorm.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/cyberstorm.h	Fri May  8 00:22:12 1998
@@ -0,0 +1,82 @@
+/* cyberstorm.h: Defines and structures for the CyberStorm SCSI driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef CYBER_ESP_H
+#define CYBER_ESP_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define CYBER_ESP_ADDR 0xf400
+#define CYBER_DMA_ADDR 0xf800
+
+
+/* The CyberStorm DMA interface */
+struct cyber_dma_registers {
+	volatile unsigned char dma_addr0;	/* DMA address (MSB) [0x000] */
+	unsigned char dmapad1[1];
+	volatile unsigned char dma_addr1;	/* DMA address       [0x002] */
+	unsigned char dmapad2[1];
+	volatile unsigned char dma_addr2;	/* DMA address       [0x004] */
+	unsigned char dmapad3[1];
+	volatile unsigned char dma_addr3;	/* DMA address (LSB) [0x006] */
+	unsigned char dmapad4[0x3fb];
+	volatile unsigned char cond_reg;        /* DMA cond    (ro)  [0x402] */
+#define ctrl_reg  cond_reg			/* DMA control (wo)  [0x402] */
+};
+
+/* DMA control bits */
+#define CYBER_DMA_LED    0x80	/* HD led control 1 = on */
+#define CYBER_DMA_WRITE  0x40	/* DMA direction. 1 = write */
+#define CYBER_DMA_Z3     0x20	/* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */
+
+/* DMA status bits */
+#define CYBER_DMA_HNDL_INTR 0x80	/* DMA IRQ pending? */
+
+/* The bits below appears to be Phase5 Debug bits only; they were not
+ * described by Phase5 so using them may seem a bit stupid...
+ */
+#define CYBER_HOST_ID 0x02	/* If set, host ID should be 7, otherwise
+				 * it should be 6.
+				 */
+#define CYBER_SLOW_CABLE 0x08	/* If *not* set, assume SLOW_CABLE */
+
+extern int cyber_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_CYBERSTORM {                                                               \
+/* struct SHT *next */                                         NULL,                   \
+/* long *usage_count */                                        NULL,                   \
+/* struct proc_dir_entry *proc_dir */                          &proc_scsi_esp,         \
+/* int (*proc_info)(char *, char **, off_t, int, int, int) */  &esp_proc_info,                   \
+/* const char *name */                                         "CyberStorm SCSI", \
+/* int detect(struct SHT *) */                                 cyber_esp_detect,  \
+/* int release(struct Scsi_Host *) */                          NULL,                   \
+/* const char *info(struct Scsi_Host *) */                     esp_info,               \
+/* int command(Scsi_Cmnd *) */                                 esp_command,            \
+/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue,              \
+/* int abort(Scsi_Cmnd *) */                                   esp_abort,              \
+/* int reset(Scsi_Cmnd *) */                                   esp_reset,              \
+/* int slave_attach(int, int) */                               NULL,                   \
+/* int bios_param(Disk *, kdev_t, int[]) */                    NULL,                   \
+/* int can_queue */                                            7,                      \
+/* int this_id */                                              7,                      \
+/* short unsigned int sg_tablesize */                          SG_ALL,                 \
+/* short cmd_per_lun */                                        1,                      \
+/* unsigned char present */                                    0,                      \
+/* unsigned unchecked_isa_dma:1 */                             0,                      \
+/* unsigned use_clustering:1 */                                DISABLE_CLUSTERING, }
+
+#endif /* CYBER_ESP_H */
+
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstormII.c linux/drivers/scsi/cyberstormII.c
--- v2.1.100/linux/drivers/scsi/cyberstormII.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/cyberstormII.c	Fri May  8 00:22:12 1998
@@ -0,0 +1,244 @@
+/* cyberstormII.c: Driver for CyberStorm SCSI Mk II
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * This driver is based on cyberstorm.c
+ */
+
+/* TODO:
+ *
+ * 1) Figure out how to make a cleaner merge with the sparc driver with regard
+ *    to the caches and the Sparc MMU mapping.
+ * 2) Make as few routines required outside the generic driver. A lot of the
+ *    routines in this file used to be inline!
+ */
+
+#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 "cyberstormII.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include <asm/pgtable.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, 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 void dma_led_off(struct NCR_ESP *esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are transfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int cyberII_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	unsigned int key;
+	unsigned long address;
+	struct ESP_regs *eregs;
+
+	if((key = zorro_find(ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, 0, 0))){
+		esp_dev = zorro_get_board(key);
+
+		/* Do some magic to figure out if the CyberStorm Mk II
+		 * is equipped with a SCSI controller
+		 */
+		address = (unsigned long)ZTWO_VADDR(esp_dev->cd_BoardAddr);
+		eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR);
+
+		eregs->esp_cfg1 = (ESP_CONFIG1_PENABLE | 7);
+		udelay(5);
+		if(eregs->esp_cfg1 != (ESP_CONFIG1_PENABLE | 7))
+			return 0; /* Bail out if address did not hold data */
+
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = 0;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = 0;
+		esp->dma_led_on = &dma_led_on;
+		esp->dma_led_off = &dma_led_off;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		/* SCSI chip speed */
+		esp->cfreq = 40000000;
+
+		/* The DMA registers on the CyberStorm are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+		esp->dregs = (void *)(address + CYBERII_DMA_ADDR);
+
+		/* ESP register base */
+		esp->eregs = eregs;
+		
+		/* Set the command buffer */
+		esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer);
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+			    "CyberStorm SCSI Mk II", esp_intr);
+
+		/* Figure out our scsi ID on the bus */
+		esp->scsi_id = 7;
+		
+		/* Check for differential SCSI-bus */
+		/* What is this stuff? */
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+
+		printk("\nESP: 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 int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	/* I don't think there's any limit on the CyberDMA. So we use what
+	 * the ESP chip can handle (24 bit).
+	 */
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > 0x1000000)
+		sz = 0x1000000;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
+		esp->esp_id, ((struct cyberII_dma_registers *)
+			      (esp->dregs))->cond_reg));
+	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
+		custom.intreqr, custom.intenar));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct cyberII_dma_registers *dregs = 
+		(struct cyberII_dma_registers *) esp->dregs;
+
+	cache_clear(addr, length);
+
+	addr &= ~(1);
+	dregs->dma_addr0 = (addr >> 24) & 0xff;
+	dregs->dma_addr1 = (addr >> 16) & 0xff;
+	dregs->dma_addr2 = (addr >>  8) & 0xff;
+	dregs->dma_addr3 = (addr      ) & 0xff;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct cyberII_dma_registers *dregs = 
+		(struct cyberII_dma_registers *) esp->dregs;
+
+	cache_push(addr, length);
+
+	addr |= 1;
+	dregs->dma_addr0 = (addr >> 24) & 0xff;
+	dregs->dma_addr1 = (addr >> 16) & 0xff;
+	dregs->dma_addr2 = (addr >>  8) & 0xff;
+	dregs->dma_addr3 = (addr      ) & 0xff;
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	/* It's important to check the DMA IRQ bit in the correct way! */
+	return (esp->eregs->esp_status & ESP_STAT_INTR);
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+	((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg &= ~CYBERII_DMA_LED;
+}
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+	((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg |= CYBERII_DMA_LED;
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+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);
+	}
+}
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/cyberstormII.h linux/drivers/scsi/cyberstormII.h
--- v2.1.100/linux/drivers/scsi/cyberstormII.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/cyberstormII.h	Fri May  8 00:22:12 1998
@@ -0,0 +1,69 @@
+/* cyberstormII.h: Defines and structures for the CyberStorm SCSI Mk II driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef CYBERII_ESP_H
+#define CYBERII_ESP_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define CYBERII_ESP_ADDR 0x1ff03
+#define CYBERII_DMA_ADDR 0x1ff43
+
+
+/* The CyberStorm II DMA interface */
+struct cyberII_dma_registers {
+	volatile unsigned char cond_reg;        /* DMA cond    (ro)  [0x000] */
+#define ctrl_reg  cond_reg			/* DMA control (wo)  [0x000] */
+	unsigned char dmapad4[0x3f];
+	volatile unsigned char dma_addr0;	/* DMA address (MSB) [0x040] */
+	unsigned char dmapad1[3];
+	volatile unsigned char dma_addr1;	/* DMA address       [0x044] */
+	unsigned char dmapad2[3];
+	volatile unsigned char dma_addr2;	/* DMA address       [0x048] */
+	unsigned char dmapad3[3];
+	volatile unsigned char dma_addr3;	/* DMA address (LSB) [0x04c] */
+};
+
+/* DMA control bits */
+#define CYBERII_DMA_LED    0x02	/* HD led control 1 = on */
+
+
+extern int cyberII_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_CYBERSTORMII {                                                               \
+/* struct SHT *next */                                         NULL,                   \
+/* long *usage_count */                                        NULL,                   \
+/* struct proc_dir_entry *proc_dir */                          &proc_scsi_esp,         \
+/* int (*proc_info)(char *, char **, off_t, int, int, int) */  &esp_proc_info,                   \
+/* const char *name */                                         "CyberStorm Mk II SCSI", \
+/* int detect(struct SHT *) */                                 cyberII_esp_detect,  \
+/* int release(struct Scsi_Host *) */                          NULL,                   \
+/* const char *info(struct Scsi_Host *) */                     esp_info,               \
+/* int command(Scsi_Cmnd *) */                                 esp_command,            \
+/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue,              \
+/* int abort(Scsi_Cmnd *) */                                   esp_abort,              \
+/* int reset(Scsi_Cmnd *) */                                   esp_reset,              \
+/* int slave_attach(int, int) */                               NULL,                   \
+/* int bios_param(Disk *, kdev_t, int[]) */                    NULL,                   \
+/* int can_queue */                                            7,                      \
+/* int this_id */                                              7,                      \
+/* short unsigned int sg_tablesize */                          SG_ALL,                 \
+/* short cmd_per_lun */                                        1,                      \
+/* unsigned char present */                                    0,                      \
+/* unsigned unchecked_isa_dma:1 */                             0,                      \
+/* unsigned use_clustering:1 */                                DISABLE_CLUSTERING, }
+
+#endif /* CYBERII_ESP_H */
+
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.1.100/linux/drivers/scsi/esp.c	Tue Apr 14 14:29:22 1998
+++ linux/drivers/scsi/esp.c	Fri May  8 00:22:12 1998
@@ -173,7 +173,9 @@
 
 /* Forward declarations. */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
-static void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+#ifndef __sparc_v9__
+static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs);
+#endif
 
 /* Debugging routines */
 struct esp_cmdstrings {
@@ -641,25 +643,385 @@
 	trash = eregs->esp_intrpt;
 }
 
-/* Detecting ESP chips on the machine.  This is the simple and easy
- * version.
- */
-__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
+__initfunc(int detect_one_esp
+(Scsi_Host_Template *tpnt, struct linux_sbus_device *esp_dev, struct linux_sbus_device *espdma,
+ struct linux_sbus *sbus, int id, int hme))
 {
-#ifdef __sparc_v9__
 	struct devid_cookie dcookie;
-#endif
 	struct Sparc_ESP *esp, *elink;
 	struct Scsi_Host *esp_host;
-	struct linux_sbus *sbus;
-	struct linux_sbus_device *esp_dev, *sbdev_iter;
 	struct Sparc_ESP_regs *eregs;
 	struct sparc_dma_registers *dregs;
 	struct Linux_SBus_DMA *dma, *dlink;
 	unsigned int fmhz;
 	unchar ccf, bsizes, bsizes_more;
-	int nesps = 0, esps_in_use = 0;
 	int esp_node, i;
+	
+	esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP));
+	if(!esp_host)
+		panic("Cannot register ESP SCSI host");
+	if(hme)
+		esp_host->max_id = 16;
+	esp = (struct Sparc_ESP *) esp_host->hostdata;
+	if(!esp)
+		panic("No esp in hostdata");
+	esp->ehost = esp_host;
+	esp->edev = esp_dev;
+	esp->esp_id = id;
+
+	/* Put into the chain of esp chips detected */
+	if(espchain) {
+		elink = espchain;
+		while(elink->next) elink = elink->next;
+		elink->next = esp;
+	} else {
+		espchain = esp;
+	}
+	esp->next = 0;
+
+	/* Get misc. prom information */
+#define ESP_IS_MY_DVMA(esp, dma)  \
+	(!dma->SBus_dev || \
+	 ((esp->edev->my_bus == dma->SBus_dev->my_bus) && \
+          (esp->edev->slot == dma->SBus_dev->slot) && \
+	  (!strcmp(dma->SBus_dev->prom_name, "dma") || \
+	   !strcmp(dma->SBus_dev->prom_name, "espdma"))))
+
+	esp_node = esp_dev->prom_node;
+	prom_getstring(esp_node, "name", esp->prom_name,
+		       sizeof(esp->prom_name));
+	esp->prom_node = esp_node;
+	if(espdma) {
+		for_each_dvma(dlink) {
+			if(dlink->SBus_dev == espdma)
+				break;
+		}
+	} else {
+		for_each_dvma(dlink) {
+			if(ESP_IS_MY_DVMA(esp, dlink) &&
+			   !dlink->allocated)
+				break;
+		}
+	}
+#undef ESP_IS_MY_DVMA
+	/* If we don't know how to handle the dvma,
+	 * do not use this device.
+	 */
+	if(!dlink){
+		printk ("Cannot find dvma for ESP%d's SCSI\n",
+			esp->esp_id);
+		scsi_unregister (esp_host);
+		return -1;
+	}
+	if (dlink->allocated){
+		printk ("esp%d: can't use my espdma\n",
+			esp->esp_id);
+		scsi_unregister (esp_host);
+		return -1;
+	}
+	dlink->allocated = 1;
+	dma = dlink;
+	esp->dma = dma;
+	esp->dregs = dregs = dma->regs;
+
+	/* Map in the ESP registers from I/O space */
+	if(!hme) {
+		prom_apply_sbus_ranges(esp->edev->my_bus, 
+				       esp->edev->reg_addrs,
+				       1, esp->edev);
+
+		esp->eregs = eregs = (struct Sparc_ESP_regs *)
+		sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0,
+			       PAGE_SIZE, "ESP Registers",
+			       esp->edev->reg_addrs[0].which_io, 0x0);
+	} else {
+		/* On HME, two reg sets exist, first is DVMA,
+		 * second is ESP registers.
+		 */
+		esp->eregs = eregs = (struct Sparc_ESP_regs *)
+		sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0,
+			       PAGE_SIZE, "ESP Registers",
+			       esp->edev->reg_addrs[1].which_io, 0x0);
+	}
+	if(!eregs)
+		panic("ESP registers unmappable");
+	esp->esp_command =
+		sparc_dvma_malloc(16, "ESP DVMA Cmd Block",
+				  &esp->esp_command_dvma);
+	if(!esp->esp_command || !esp->esp_command_dvma)
+		panic("ESP DVMA transport area unmappable");
+
+	/* Set up the irq's etc. */
+	esp->ehost->base = (unsigned char *) esp->eregs;
+	esp->ehost->io_port =
+		esp->edev->reg_addrs[0].phys_addr;
+	esp->ehost->n_io_port = (unsigned char)
+		esp->edev->reg_addrs[0].reg_size;
+	esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri;
+
+#ifndef __sparc_v9__
+	if (sparc_cpu_model != sun4d) {
+		/* Allocate the irq only if necessary */
+		for_each_esp(elink) {
+			if((elink != esp) && (esp->irq == elink->irq)) {
+				goto esp_irq_acquired; /* BASIC rulez */
+			}
+		}
+		if(request_irq(esp->ehost->irq, esp_intr, SA_SHIRQ,
+			       "Sparc ESP SCSI", NULL))
+			panic("Cannot acquire ESP irq line");
+esp_irq_acquired:
+		printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq);
+	} else {
+		dcookie.real_dev_id = esp;
+		dcookie.bus_cookie = esp_dev;
+		if (request_irq(esp->ehost->irq, esp_intr_4d,
+			(SA_SHIRQ | SA_DCOOKIE),
+			"Sparc ESP SCSI", &dcookie))
+			panic("Cannot acquire ESP irq line");
+		printk("esp%d: INO[%x] IRQ %d ", esp->esp_id, dcookie.ret_ino, esp->ehost->irq);
+		esp->ehost->irq = esp->irq = dcookie.ret_ino;
+	}
+#else
+	/* On Ultra we must always call request_irq for each
+	 * esp, so that imap registers get setup etc.
+	 */
+	dcookie.real_dev_id = esp;
+	dcookie.imap = dcookie.iclr = 0;
+	dcookie.pil = -1;
+	dcookie.bus_cookie = sbus;
+	if(request_irq(esp->ehost->irq, esp_intr,
+		       (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
+		       "Sparc ESP SCSI", &dcookie))
+		panic("Cannot acquire ESP irq line");
+	esp->ehost->irq = esp->irq = dcookie.ret_ino;
+	printk("esp%d: INO[%x] IRQ %d ",
+	       esp->esp_id, esp->ehost->irq, dcookie.ret_pil);
+#endif
+
+	/* Figure out our scsi ID on the bus */
+	esp->scsi_id = prom_getintdefault(esp->prom_node,
+					  "initiator-id",
+					  -1);
+	if(esp->scsi_id == -1)
+		esp->scsi_id = prom_getintdefault(esp->prom_node,
+						  "scsi-initiator-id",
+						  -1);
+	if(esp->scsi_id == -1)
+		esp->scsi_id = (!esp->edev->my_bus) ? 7 :
+			prom_getintdefault(esp->edev->my_bus->prom_node,
+					   "scsi-initiator-id",
+					   7);
+	esp->ehost->this_id = esp->scsi_id;
+	esp->scsi_id_mask = (1 << esp->scsi_id);
+
+	/* Check for differential SCSI-bus */
+	esp->diff = prom_getbool(esp->prom_node, "differential");
+	if(esp->diff)
+		printk("Differential ");
+
+	/* Check out the clock properties of the chip. */
+
+	/* This is getting messy but it has to be done
+	 * correctly or else you get weird behavior all
+	 * over the place.  We are trying to basically
+	 * figure out three pieces of information.
+	 *
+	 * a) Clock Conversion Factor
+	 *
+	 *    This is a representation of the input
+	 *    crystal clock frequency going into the
+	 *    ESP on this machine.  Any operation whose
+	 *    timing is longer than 400ns depends on this
+	 *    value being correct.  For example, you'll
+	 *    get blips for arbitration/selection during
+	 *    high load or with multiple targets if this
+	 *    is not set correctly.
+	 *
+	 * b) Selection Time-Out
+	 *
+	 *    The ESP isn't very bright and will arbitrate
+	 *    for the bus and try to select a target
+	 *    forever if you let it.  This value tells
+	 *    the ESP when it has taken too long to
+	 *    negotiate and that it should interrupt
+	 *    the CPU so we can see what happened.
+	 *    The value is computed as follows (from
+	 *    NCR/Symbios chip docs).
+	 *
+	 *          (Time Out Period) *  (Input Clock)
+	 *    STO = ----------------------------------
+	 *          (8192) * (Clock Conversion Factor)
+	 *
+	 *    You usually want the time out period to be
+	 *    around 250ms, I think we'll set it a little
+	 *    bit higher to account for fully loaded SCSI
+	 *    bus's and slow devices that don't respond so
+	 *    quickly to selection attempts. (yeah, I know
+	 *    this is out of spec. but there is a lot of
+	 *    buggy pieces of firmware out there so bite me)
+	 *
+	 * c) Imperical constants for synchronous offset
+	 *    and transfer period register values
+	 *
+	 *    This entails the smallest and largest sync
+	 *    period we could ever handle on this ESP.
+	 */
+
+	fmhz = prom_getintdefault(esp->prom_node,
+				  "clock-frequency",
+				  -1);
+	if(fmhz==-1)
+		fmhz = (!esp->edev->my_bus) ? 0 :
+			prom_getintdefault(esp->edev->my_bus->prom_node,
+					   "clock-frequency",
+					   -1);
+	if(fmhz <= (5000000))
+		ccf = 0;
+	else
+		ccf = (((5000000 - 1) + (fmhz))/(5000000));
+	if(!ccf || ccf > 8) {
+		/* If we can't find anything reasonable,
+		 * just assume 20MHZ.  This is the clock
+		 * frequency of the older sun4c's where I've
+		 * been unable to find the clock-frequency
+		 * PROM property.  All other machines provide
+		 * useful values it seems.
+		 */
+		ccf = ESP_CCF_F4;
+		fmhz = (20000000);
+	}
+	if(ccf==(ESP_CCF_F7+1))
+		esp->cfact = ESP_CCF_F0;
+	else if(ccf == ESP_CCF_NEVER)
+		esp->cfact = ESP_CCF_F2;
+	else
+		esp->cfact = ccf;
+	esp->cfreq = fmhz;
+	esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
+	esp->ctick = ESP_TICK(ccf, esp->ccycle);
+	esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
+	esp->sync_defp = SYNC_DEFP_SLOW;
+	printk("SCSI ID %d  Clock %d MHz CCF=%d Time-Out %d ",
+	       esp->scsi_id, (fmhz / 1000000),
+	       ccf, (int) esp->neg_defp);
+
+	/* Find the burst sizes this dma/sbus/esp supports. */
+	bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
+	bsizes &= 0xff;
+	if(espdma) {
+		bsizes_more = prom_getintdefault(
+				  espdma->prom_node,
+				  "burst-sizes", 0xff);
+		if(bsizes_more != 0xff)
+			bsizes &= bsizes_more;
+	}
+	if (esp->edev->my_bus) {
+		bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node,
+						 "burst-sizes", 0xff);
+		if(bsizes_more != 0xff)
+			bsizes &= bsizes_more;
+	}
+
+	if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
+	   (bsizes & DMA_BURST32)==0)
+		bsizes = (DMA_BURST32 - 1);
+
+	esp->bursts = bsizes;
+
+	/* Probe the revision of this esp */
+	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
+	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+	eregs->esp_cfg2 = esp->config2;
+	if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
+	   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+		printk("NCR53C90(esp100) detected\n");
+		esp->erev = esp100;
+	} else {
+		eregs->esp_cfg2 = esp->config2 = 0;
+		eregs->esp_cfg3 = 0;
+		eregs->esp_cfg3 = esp->config3[0] = 5;
+		if(eregs->esp_cfg3 != 5) {
+			printk("NCR53C90A(esp100a) detected\n");
+			esp->erev = esp100a;
+		} else {
+			int target;
+
+			for(target=0; target<8; target++)
+				esp->config3[target] = 0;
+			eregs->esp_cfg3 = 0;
+			if(ccf > ESP_CCF_F5) {
+				printk("NCR53C9XF(espfast) detected\n");
+				esp->erev = fast;
+				eregs->esp_cfg2 = esp->config2 = 0;
+				esp->sync_defp = SYNC_DEFP_FAST;
+			} else {
+				printk("NCR53C9x(esp236) detected\n");
+				esp->erev = esp236;
+				eregs->esp_cfg2 = esp->config2 = 0;
+			}
+		}
+	}				
+
+	/* Initialize the command queues */
+	esp->current_SC = 0;
+	esp->disconnected_SC = 0;
+	esp->issue_SC = 0;
+
+	/* Clear the state machines. */
+	esp->targets_present = 0;
+	esp->resetting_bus = 0;
+	esp->snip = 0;
+	esp->targets_present = 0;
+	for(i = 0; i < 32; i++)
+		esp->espcmdlog[i] = 0;
+	esp->espcmdent = 0;
+	for(i = 0; i < 16; i++) {
+		esp->cur_msgout[i] = 0;
+		esp->cur_msgin[i] = 0;
+	}
+	esp->prevmsgout = esp->prevmsgin = 0;
+	esp->msgout_len = esp->msgin_len = 0;
+
+	/* Reset the thing before we try anything... */
+	esp_bootup_reset(esp, eregs);
+
+	return 0;
+}
+
+/* Detecting ESP chips on the machine.  This is the simple and easy
+ * version.
+ */
+
+#ifdef CONFIG_SUN4
+
+#include <asm/sun4paddr.h>
+
+__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
+{
+	static struct linux_sbus_device esp_dev;
+	int esps_in_use = 0;
+
+	espchain = 0;
+
+	memset (&esp_dev, 0, sizeof(esp_dev));
+	esp_dev.reg_addrs[0].phys_addr = SUN4_300_ESP_PHYSADDR;
+	esp_dev.irqs[0].pri = 4;
+
+	if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0))
+		esps_in_use++;
+	printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use);
+	esps_running = esps_in_use;
+	return esps_in_use;
+}
+
+#else /* !CONFIG_SUN4 */
+
+__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
+{
+	struct linux_sbus *sbus;
+	struct linux_sbus_device *esp_dev, *sbdev_iter;
+	int nesps = 0, esps_in_use = 0;
 
 	espchain = 0;
 	if(!SBus_chain) {
@@ -693,320 +1055,10 @@
 						continue; /* how can this happen? */
 				}
 			}
-			esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP));
-			if(!esp_host)
-				panic("Cannot register ESP SCSI host");
-			if(hme)
-				esp_host->max_id = 16;
-			esp = (struct Sparc_ESP *) esp_host->hostdata;
-			if(!esp)
-				panic("No esp in hostdata");
-			esp->ehost = esp_host;
-			esp->edev = esp_dev;
-			esp->esp_id = nesps++;
-
-			/* Put into the chain of esp chips detected */
-			if(espchain) {
-				elink = espchain;
-				while(elink->next) elink = elink->next;
-				elink->next = esp;
-			} else {
-				espchain = esp;
-			}
-			esp->next = 0;
-
-			/* Get misc. prom information */
-#define ESP_IS_MY_DVMA(esp, dma)  \
-	((esp->edev->my_bus == dma->SBus_dev->my_bus) && \
-         (esp->edev->slot == dma->SBus_dev->slot) && \
-	 (!strcmp(dma->SBus_dev->prom_name, "dma") || \
-	  !strcmp(dma->SBus_dev->prom_name, "espdma")))
-
-			esp_node = esp_dev->prom_node;
-			prom_getstring(esp_node, "name", esp->prom_name,
-				       sizeof(esp->prom_name));
-			esp->prom_node = esp_node;
-			if(espdma) {
-				for_each_dvma(dlink) {
-					if(dlink->SBus_dev == espdma)
-						break;
-				}
-			} else {
-				for_each_dvma(dlink) {
-					if(ESP_IS_MY_DVMA(esp, dlink) &&
-					   !dlink->allocated)
-						break;
-				}
-			}
-#undef ESP_IS_MY_DVMA
-			/* If we don't know how to handle the dvma,
-			 * do not use this device.
-			 */
-			if(!dlink){
-				printk ("Cannot find dvma for ESP%d's SCSI\n",
-					esp->esp_id);
-				scsi_unregister (esp_host);
+			
+			if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0)
 				continue;
-			}
-			if (dlink->allocated){
-				printk ("esp%d: can't use my espdma\n",
-					esp->esp_id);
-				scsi_unregister (esp_host);
-				continue;
-			}
-			dlink->allocated = 1;
-			dma = dlink;
-			esp->dma = dma;
-			esp->dregs = dregs = dma->regs;
-
-			/* Map in the ESP registers from I/O space */
-			if(!hme) {
-				prom_apply_sbus_ranges(esp->edev->my_bus, 
-						       esp->edev->reg_addrs,
-						       1, esp->edev);
-
-				esp->eregs = eregs = (struct Sparc_ESP_regs *)
-				sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0,
-					       PAGE_SIZE, "ESP Registers",
-					       esp->edev->reg_addrs[0].which_io, 0x0);
-			} else {
-				/* On HME, two reg sets exist, first is DVMA,
-				 * second is ESP registers.
-				 */
-				esp->eregs = eregs = (struct Sparc_ESP_regs *)
-				sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0,
-					       PAGE_SIZE, "ESP Registers",
-					       esp->edev->reg_addrs[1].which_io, 0x0);
-			}
-			if(!eregs)
-				panic("ESP registers unmappable");
-			esp->esp_command =
-				sparc_dvma_malloc(16, "ESP DVMA Cmd Block",
-						  &esp->esp_command_dvma);
-			if(!esp->esp_command || !esp->esp_command_dvma)
-				panic("ESP DVMA transport area unmappable");
-
-			/* Set up the irq's etc. */
-			esp->ehost->base = (unsigned char *) esp->eregs;
-			esp->ehost->io_port =
-				esp->edev->reg_addrs[0].phys_addr;
-			esp->ehost->n_io_port = (unsigned char)
-				esp->edev->reg_addrs[0].reg_size;
-			esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri;
-
-#ifndef __sparc_v9__
-			/* Allocate the irq only if necessary */
-			for_each_esp(elink) {
-				if((elink != esp) && (esp->irq == elink->irq)) {
-					goto esp_irq_acquired; /* BASIC rulez */
-				}
-			}
-			if(request_irq(esp->ehost->irq, do_esp_intr, SA_SHIRQ,
-				       "Sparc ESP SCSI", NULL))
-				panic("Cannot acquire ESP irq line");
-esp_irq_acquired:
-			printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq);
-#else
-			/* On Ultra we must always call request_irq for each
-			 * esp, so that imap registers get setup etc.
-			 */
-			dcookie.real_dev_id = esp;
-			dcookie.imap = dcookie.iclr = 0;
-			dcookie.pil = -1;
-			dcookie.bus_cookie = sbus;
-			if(request_irq(esp->ehost->irq, do_esp_intr,
-				       (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
-				       "Sparc ESP SCSI", &dcookie))
-				panic("Cannot acquire ESP irq line");
-			esp->ehost->irq = esp->irq = dcookie.ret_ino;
-			printk("esp%d: INO[%x] IRQ %d ",
-			       esp->esp_id, esp->ehost->irq, dcookie.ret_pil);
-#endif
-
-			/* Figure out our scsi ID on the bus */
-			esp->scsi_id = prom_getintdefault(esp->prom_node,
-							  "initiator-id",
-							  -1);
-			if(esp->scsi_id == -1)
-				esp->scsi_id = prom_getintdefault(esp->prom_node,
-								  "scsi-initiator-id",
-								  -1);
-			if(esp->scsi_id == -1)
-				esp->scsi_id =
-					prom_getintdefault(esp->edev->my_bus->prom_node,
-							   "scsi-initiator-id",
-							   7);
-			esp->ehost->this_id = esp->scsi_id;
-			esp->scsi_id_mask = (1 << esp->scsi_id);
-
-			/* Check for differential SCSI-bus */
-			esp->diff = prom_getbool(esp->prom_node, "differential");
-			if(esp->diff)
-				printk("Differential ");
-
-			/* Check out the clock properties of the chip. */
-
-			/* This is getting messy but it has to be done
-			 * correctly or else you get weird behavior all
-			 * over the place.  We are trying to basically
-			 * figure out three pieces of information.
-			 *
-			 * a) Clock Conversion Factor
-			 *
-			 *    This is a representation of the input
-			 *    crystal clock frequency going into the
-			 *    ESP on this machine.  Any operation whose
-			 *    timing is longer than 400ns depends on this
-			 *    value being correct.  For example, you'll
-			 *    get blips for arbitration/selection during
-			 *    high load or with multiple targets if this
-			 *    is not set correctly.
-			 *
-			 * b) Selection Time-Out
-			 *
-			 *    The ESP isn't very bright and will arbitrate
-			 *    for the bus and try to select a target
-			 *    forever if you let it.  This value tells
-			 *    the ESP when it has taken too long to
-			 *    negotiate and that it should interrupt
-			 *    the CPU so we can see what happened.
-			 *    The value is computed as follows (from
-			 *    NCR/Symbios chip docs).
-			 *
-			 *          (Time Out Period) *  (Input Clock)
-			 *    STO = ----------------------------------
-			 *          (8192) * (Clock Conversion Factor)
-			 *
-			 *    You usually want the time out period to be
-			 *    around 250ms, I think we'll set it a little
-			 *    bit higher to account for fully loaded SCSI
-			 *    bus's and slow devices that don't respond so
-			 *    quickly to selection attempts. (yeah, I know
-			 *    this is out of spec. but there is a lot of
-			 *    buggy pieces of firmware out there so bite me)
-			 *
-			 * c) Imperical constants for synchronous offset
-			 *    and transfer period register values
-			 *
-			 *    This entails the smallest and largest sync
-			 *    period we could ever handle on this ESP.
-			 */
-
-			fmhz = prom_getintdefault(esp->prom_node,
-						  "clock-frequency",
-						  -1);
-			if(fmhz==-1)
-				fmhz = prom_getintdefault(esp->edev->my_bus->prom_node,
-							  "clock-frequency",
-							  -1);
-			if(fmhz <= (5000000))
-				ccf = 0;
-			else
-				ccf = (((5000000 - 1) + (fmhz))/(5000000));
-			if(!ccf || ccf > 8) {
-				/* If we can't find anything reasonable,
-				 * just assume 20MHZ.  This is the clock
-				 * frequency of the older sun4c's where I've
-				 * been unable to find the clock-frequency
-				 * PROM property.  All other machines provide
-				 * useful values it seems.
-				 */
-				ccf = ESP_CCF_F4;
-				fmhz = (20000000);
-			}
-			if(ccf==(ESP_CCF_F7+1))
-				esp->cfact = ESP_CCF_F0;
-			else if(ccf == ESP_CCF_NEVER)
-				esp->cfact = ESP_CCF_F2;
-			else
-				esp->cfact = ccf;
-			esp->cfreq = fmhz;
-			esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
-			esp->ctick = ESP_TICK(ccf, esp->ccycle);
-			esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
-			esp->sync_defp = SYNC_DEFP_SLOW;
-			printk("SCSI ID %d  Clock %d MHz CCF=%d Time-Out %d ",
-			       esp->scsi_id, (fmhz / 1000000),
-			       ccf, (int) esp->neg_defp);
-
-			/* Find the burst sizes this dma/sbus/esp supports. */
-			bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
-			bsizes &= 0xff;
-			if(espdma) {
-				bsizes_more = prom_getintdefault(
-						  espdma->prom_node,
-						  "burst-sizes", 0xff);
-				if(bsizes_more != 0xff)
-					bsizes &= bsizes_more;
-			}
-			bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node,
-							 "burst-sizes", 0xff);
-			if(bsizes_more != 0xff)
-				bsizes &= bsizes_more;
-
-			if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
-			   (bsizes & DMA_BURST32)==0)
-				bsizes = (DMA_BURST32 - 1);
-
-			esp->bursts = bsizes;
-
-			/* Probe the revision of this esp */
-			esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
-			esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
-			eregs->esp_cfg2 = esp->config2;
-			if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
-			   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
-				printk("NCR53C90(esp100) detected\n");
-				esp->erev = esp100;
-			} else {
-				eregs->esp_cfg2 = esp->config2 = 0;
-				eregs->esp_cfg3 = 0;
-				eregs->esp_cfg3 = esp->config3[0] = 5;
-				if(eregs->esp_cfg3 != 5) {
-					printk("NCR53C90A(esp100a) detected\n");
-					esp->erev = esp100a;
-				} else {
-					int target;
-
-					for(target=0; target<8; target++)
-						esp->config3[target] = 0;
-					eregs->esp_cfg3 = 0;
-					if(ccf > ESP_CCF_F5) {
-						printk("NCR53C9XF(espfast) detected\n");
-						esp->erev = fast;
-						eregs->esp_cfg2 = esp->config2 = 0;
-						esp->sync_defp = SYNC_DEFP_FAST;
-					} else {
-						printk("NCR53C9x(esp236) detected\n");
-						esp->erev = esp236;
-						eregs->esp_cfg2 = esp->config2 = 0;
-					}
-				}
-			}				
-
-			/* Initialize the command queues */
-			esp->current_SC = 0;
-			esp->disconnected_SC = 0;
-			esp->issue_SC = 0;
-
-			/* Clear the state machines. */
-			esp->targets_present = 0;
-			esp->resetting_bus = 0;
-			esp->snip = 0;
-			esp->targets_present = 0;
-			for(i = 0; i < 32; i++)
-				esp->espcmdlog[i] = 0;
-			esp->espcmdent = 0;
-			for(i = 0; i < 16; i++) {
-				esp->cur_msgout[i] = 0;
-				esp->cur_msgin[i] = 0;
-			}
-			esp->prevmsgout = esp->prevmsgin = 0;
-			esp->msgout_len = esp->msgin_len = 0;
-
-			/* Reset the thing before we try anything... */
-			esp_bootup_reset(esp, eregs);
-
+				
 			esps_in_use++;
 		} /* for each sbusdev */
 	} /* for each sbus */
@@ -1016,6 +1068,8 @@
 	return esps_in_use;
 }
 
+#endif /* !CONFIG_SUN4 */
+
 /* The info function will return whatever useful
  * information the developer sees fit.  If not provided, then
  * the name field will be used instead.
@@ -4040,24 +4094,17 @@
 	return;
 }
 
-static void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-	esp_intr(irq, dev_id, pregs);
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
 #ifndef __sparc_v9__
 
 #ifndef __SMP__
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct Sparc_ESP *esp;
+	unsigned long flags;
 	int again;
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
+	spin_lock_irqsave(&io_request_lock, flags);
 repeat:
 	again = 0;
 	for_each_esp(esp) {
@@ -4077,14 +4124,17 @@
 	}
 	if(again)
 		goto repeat;
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #else
 /* For SMP we only service one ESP on the list list at our IRQ level! */
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct Sparc_ESP *esp;
+	unsigned long flags;
 
 	/* Handle all ESP interrupts showing at this IRQ level. */
+	spin_lock_irqsave(&io_request_lock, flags);
 	for_each_esp(esp) {
 		if(((esp)->irq & 0xf) == irq) {
 			if(DMA_IRQ_P(esp->dregs)) {
@@ -4096,19 +4146,41 @@
 				ESPIRQ((")"));
 
 				DMA_INTSON(esp->dregs);
-				return;
+				goto out;
 			}
 		}
 	}
+out:
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 #endif
 
+static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs)
+{
+	struct Sparc_ESP *esp = dev_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	if(DMA_IRQ_P(esp->dregs)) {
+		DMA_INTSOFF(esp->dregs);
+
+		ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id));
+		esp_handle(esp);
+		ESPIRQ((")"));
+
+		DMA_INTSON(esp->dregs);
+	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
 #else /* __sparc_v9__ */
 
 static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct Sparc_ESP *esp = dev_id;
+	unsigned long flags;
 
+	spin_lock_irqsave(&io_request_lock, flags);
 	if(DMA_IRQ_P(esp->dregs)) {
 		DMA_INTSOFF(esp->dregs);
 
@@ -4118,6 +4190,6 @@
 
 		DMA_INTSON(esp->dregs);
 	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
-
 #endif
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/fastlane.c linux/drivers/scsi/fastlane.c
--- v2.1.100/linux/drivers/scsi/fastlane.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/fastlane.c	Fri May  8 00:22:12 1998
@@ -0,0 +1,343 @@
+/* fastlane.c: Driver for Phase5's Fastlane SCSI Controller.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * This driver is based on the CyberStorm driver, hence the occasional
+ * reference to CyberStorm.
+ *
+ * Betatesting & crucial adjustments by Patrik Rak 
+ * (prak3264@ss1000.ms.mff.cuni.cz)
+ *
+ */
+
+/* TODO:
+ *
+ * o According to the doc from laire, it is required to reset the DMA when
+ *   the transfer is done. ATM we reset DMA just before every new 
+ *   dma_init_(read|write).
+ *
+ * 1) Figure out how to make a cleaner merge with the sparc driver with regard
+ *    to the caches and the Sparc MMU mapping.
+ * 2) Make as few routines required outside the generic driver. A lot of the
+ *    routines in this file used to be inline!
+ */
+
+#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 "fastlane.h"
+
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#include <asm/pgtable.h>
+
+/* Let this defined unless you really need to enable DMA IRQ one day */
+#define NODMAIRQ
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
+static inline void dma_clear(struct NCR_ESP *esp);
+static void dma_dump_state(struct NCR_ESP *esp);
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddr, 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 void dma_led_off(struct NCR_ESP *esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+
+static unsigned char ctrl_data = 0;	/* Keep backup of the stuff written
+				 * to ctrl_reg. Always write a copy
+				 * to this register when writing to
+				 * the hardware register!
+				 */
+
+volatile unsigned char cmd_buffer[16];
+				/* This is where all commands are put
+				 * before they are trasfered to the ESP chip
+				 * via PIO.
+				 */
+
+/***************************************************************** Detection */
+int fastlane_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	const struct ConfigDev *esp_dev;
+	unsigned int key;
+	unsigned long address;
+
+	if ((key = zorro_find(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, 0, 0))){
+
+		esp_dev = zorro_get_board(key);
+
+		/* Check if this is really a fastlane controller. The problem
+		 * is that also the cyberstorm and blizzard controllers use
+		 * this ID value. Fortunately only Fastlane maps in Z3 space
+		 */
+		if((unsigned long)esp_dev->cd_BoardAddr < 0x1000000)
+			return 0;
+
+		esp = esp_allocate(tpnt, (void *) esp_dev);
+
+		/* Do command transfer with programmed I/O */
+		esp->do_pio_cmds = 1;
+
+		/* Required functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = &dma_init_read;
+		esp->dma_init_write = &dma_init_write;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+		esp->dma_irq_p = &dma_irq_p;
+		esp->dma_ports_p = &dma_ports_p;
+		esp->dma_setup = &dma_setup;
+
+		/* Optional functions */
+		esp->dma_barrier = 0;
+		esp->dma_drain = 0;
+		esp->dma_invalidate = 0;
+		esp->dma_irq_entry = 0;
+		esp->dma_irq_exit = 0;
+		esp->dma_led_on = &dma_led_on;
+		esp->dma_led_off = &dma_led_off;
+		esp->dma_poll = 0;
+		esp->dma_reset = 0;
+
+		/* Initialize the portBits (enable IRQs) */
+		ctrl_data = (FASTLANE_DMA_FCODE |
+#ifndef NODMAIRQ
+			     FASTLANE_DMA_EDI |
+#endif
+			     FASTLANE_DMA_ESI);
+			
+
+		/* SCSI chip clock */
+		esp->cfreq = 40000000;
+
+
+		/* Map the physical address space into virtual kernel space */
+		address = (unsigned long)
+			kernel_map((unsigned long)esp_dev->cd_BoardAddr,
+				   esp_dev->cd_BoardSize,
+				   KERNELMAP_NOCACHE_SER,
+				   NULL);
+
+		if(!address){
+			printk("Could not remap Fastlane controller memory!");
+			scsi_unregister (esp->ehost);
+			return 0;
+		}
+
+
+		/* The DMA registers on the Fastlane are mapped
+		 * relative to the device (i.e. in the same Zorro
+		 * I/O block).
+		 */
+		esp->dregs = (void *)(address + FASTLANE_DMA_ADDR);
+
+		/* ESP register base */
+		esp->eregs = (struct ESP_regs *)(address + FASTLANE_ESP_ADDR);
+
+		/* Board base */
+		esp->edev = (void *) address;
+		
+		/* Set the command buffer */
+		esp->esp_command_dvma = VTOP((unsigned long) cmd_buffer);
+
+		esp->irq = IRQ_AMIGA_PORTS;
+		request_irq(IRQ_AMIGA_PORTS, esp_intr, 0, 
+			    "Fastlane SCSI", esp_intr);
+
+		/* Controller ID */
+		esp->scsi_id = 7;
+		
+		/* Check for differential SCSI-bus */
+		/* What is this stuff? */
+		esp->diff = 0;
+
+		dma_clear(esp);
+		esp_initialize(esp);
+
+		zorro_config_board(key, 0);
+
+		printk("\nESP: 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 int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Since the Fastlane DMA is fully dedicated to the ESP chip,
+	 * the number of bytes sent (to the ESP chip) equals the number
+	 * of bytes in the FIFO - there is no buffering in the DMA controller.
+	 * XXXX Do I read this right? It is from host to ESP, right?
+	 */
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > 0xfffc)
+		sz = 0xfffc;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
+		esp->esp_id, ((struct fastlane_dma_registers *)
+			      (esp->dregs))->cond_reg));
+	ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
+		custom.intreqr, custom.intenar));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct fastlane_dma_registers *dregs = 
+		(struct fastlane_dma_registers *) (esp->dregs);
+	unsigned long *t;
+	
+	cache_clear(addr, length);
+
+	dma_clear(esp);
+
+	t = (unsigned long *)((addr & 0x00ffffff) + esp->edev);
+
+	dregs->clear_strobe = 0;
+	*t = addr;
+
+	ctrl_data = (ctrl_data & FASTLANE_DMA_MASK) | FASTLANE_DMA_ENABLE;
+	dregs->ctrl_reg = ctrl_data;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	struct fastlane_dma_registers *dregs = 
+		(struct fastlane_dma_registers *) (esp->dregs);
+	unsigned long *t;
+
+	cache_push(addr, length);
+
+	dma_clear(esp);
+
+	t = (unsigned long *)((addr & 0x00ffffff) + (esp->edev));
+
+	dregs->clear_strobe = 0;
+	*t = addr;
+
+	ctrl_data = ((ctrl_data & FASTLANE_DMA_MASK) | 
+		     FASTLANE_DMA_ENABLE |
+		     FASTLANE_DMA_WRITE);
+	dregs->ctrl_reg = ctrl_data;
+}
+
+static inline void dma_clear(struct NCR_ESP *esp)
+{
+	struct fastlane_dma_registers *dregs = 
+		(struct fastlane_dma_registers *) (esp->dregs);
+	unsigned long *t;
+
+	ctrl_data = (ctrl_data & FASTLANE_DMA_MASK);
+	dregs->ctrl_reg = ctrl_data;
+
+	t = (unsigned long *)(esp->edev);
+
+	dregs->clear_strobe = 0;
+	*t = 0 ;
+}
+
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	disable_irq(esp->irq);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	enable_irq(esp->irq);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	struct fastlane_dma_registers *dregs = 
+		(struct fastlane_dma_registers *) (esp->dregs);
+#if 0
+	unsigned char dma_status;
+	int r = 0;
+
+	dma_status = dregs->cond_reg;
+
+	if(dma_status & FASTLANE_DMA_IACT)
+		return 0;	/* not our IRQ */
+
+	/* Return 1 if ESP requested IRQ */
+	if(
+#ifndef NODMAIRQ
+	   (dma_status & FASTLANE_DMA_CREQ) &&
+#endif
+	   (!(dma_status & FASTLANE_DMA_MINT)) &&
+	   ((((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR))
+		r = 1;
+
+	dregs->ctrl_reg = (ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI) );
+	dregs->ctrl_reg = ctrl_data;
+
+	return r;
+#else
+	int r;
+	r = (((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR;
+	dregs->ctrl_reg = ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI);
+	dregs->ctrl_reg = ctrl_data;
+	return r;
+#endif
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+	ctrl_data &= ~FASTLANE_DMA_LED;
+	((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
+}
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+	ctrl_data |= FASTLANE_DMA_LED;
+	((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	return ((custom.intenar) & IF_PORTS);
+}
+
+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);
+	}
+}
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/fastlane.h linux/drivers/scsi/fastlane.h
--- v2.1.100/linux/drivers/scsi/fastlane.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/fastlane.h	Fri May  8 00:22:12 1998
@@ -0,0 +1,73 @@
+/* fastlane.h: Defines and structures for the Fastlane SCSI driver.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef FASTLANE_H
+#define FASTLANE_H
+
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define FASTLANE_ESP_ADDR 0x1000001
+#define FASTLANE_DMA_ADDR 0x1000041
+
+
+/* The Fastlane DMA interface */
+struct fastlane_dma_registers {
+	volatile unsigned char cond_reg;	/* DMA status  (ro) [0x0000] */
+#define ctrl_reg  cond_reg			/* DMA control (wo) [0x0000] */
+	unsigned char dmapad1[0x3f];
+	volatile unsigned char clear_strobe;    /* DMA clear   (wo) [0x0040] */
+};
+
+
+/* DMA status bits */
+#define FASTLANE_DMA_MINT  0x80
+#define FASTLANE_DMA_IACT  0x40
+#define FASTLANE_DMA_CREQ  0x20
+
+/* DMA control bits */
+#define FASTLANE_DMA_FCODE 0xa0
+#define FASTLANE_DMA_MASK  0xf3
+#define FASTLANE_DMA_LED   0x10	/* HD led control 1 = on */
+#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */
+#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */
+#define FASTLANE_DMA_EDI   0x02	/* Enable DMA IRQ ? */
+#define FASTLANE_DMA_ESI   0x01	/* Enable SCSI IRQ */
+
+extern int fastlane_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_FASTLANE {                                                               \
+/* struct SHT *next */                                         NULL,                   \
+/* long *usage_count */                                        NULL,                   \
+/* struct proc_dir_entry *proc_dir */                          &proc_scsi_esp,         \
+/* int (*proc_info)(char *, char **, off_t, int, int, int) */  &esp_proc_info,                   \
+/* const char *name */                                         "Fastlane SCSI", \
+/* int detect(struct SHT *) */                                 fastlane_esp_detect,  \
+/* int release(struct Scsi_Host *) */                          NULL,                   \
+/* const char *info(struct Scsi_Host *) */                     esp_info,               \
+/* int command(Scsi_Cmnd *) */                                 esp_command,            \
+/* int queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)) */ esp_queue,              \
+/* int abort(Scsi_Cmnd *) */                                   esp_abort,              \
+/* int reset(Scsi_Cmnd *) */                                   esp_reset,              \
+/* int slave_attach(int, int) */                               NULL,                   \
+/* int bios_param(Disk *, kdev_t, int[]) */                    NULL,                   \
+/* int can_queue */                                            7,                      \
+/* int this_id */                                              7,                      \
+/* short unsigned int sg_tablesize */                          SG_ALL,                 \
+/* short cmd_per_lun */                                        1,                      \
+/* unsigned char present */                                    0,                      \
+/* unsigned unchecked_isa_dma:1 */                             0,                      \
+/* unsigned use_clustering:1 */                                DISABLE_CLUSTERING, }
+
+#endif /* FASTLANE_H */
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.1.100/linux/drivers/scsi/hosts.c	Thu Apr 23 20:21:35 1998
+++ linux/drivers/scsi/hosts.c	Fri May  8 00:22:12 1998
@@ -57,6 +57,26 @@
 #include "gvp11.h"
 #endif
 
+#ifdef CONFIG_CYBERSTORM_SCSI
+#include "cyberstorm.h"
+#endif
+
+#ifdef CONFIG_CYBERSTORMII_SCSI
+#include "cyberstormII.h"
+#endif
+
+#ifdef CONFIG_BLZ2060_SCSI
+#include "blz2060.h"
+#endif
+
+#ifdef CONFIG_BLZ1230_SCSI
+#include "blz1230.h"
+#endif
+
+#ifdef CONFIG_FASTLANE_SCSI
+#include "fastlane.h"
+#endif
+
 #ifdef CONFIG_ATARI_SCSI
 #include "atari_scsi.h"
 #endif
@@ -263,6 +283,21 @@
 #endif
 #ifdef CONFIG_GVP11_SCSI
 	GVP11_SCSI,
+#endif
+#ifdef CONFIG_CYBERSTORM_SCSI
+	SCSI_CYBERSTORM,
+#endif
+#ifdef CONFIG_CYBERSTORMII_SCSI
+	SCSI_CYBERSTORMII,
+#endif
+#ifdef CONFIG_BLZ2060_SCSI
+	SCSI_BLZ2060,
+#endif
+#ifdef CONFIG_BLZ1230_SCSI
+	SCSI_BLZ1230,
+#endif
+#ifdef CONFIG_FASTLANE_SCSI
+	SCSI_FASTLANE,
 #endif
 #endif
 
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.1.100/linux/drivers/scsi/hosts.h	Sat Apr 25 18:13:11 1998
+++ linux/drivers/scsi/hosts.h	Fri May  8 18:22:24 1998
@@ -345,8 +345,8 @@
     unsigned char *base;
     unsigned long io_port;
     unsigned char n_io_port;
-    unsigned char irq;
     unsigned char dma_channel;
+    unsigned int  irq;
 
     /*
      * This is a unique identifier that must be assigned so that we
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c
--- v2.1.100/linux/drivers/scsi/mac53c94.c	Tue Apr 14 14:29:22 1998
+++ linux/drivers/scsi/mac53c94.c	Fri May  8 00:22:12 1998
@@ -17,6 +17,7 @@
 #include <linux/stat.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
+#include <asm/pgtable.h>
 #include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/spinlock.h>
@@ -91,11 +92,11 @@
 			panic("no 53c94 state");
 		state->host = host;
 		state->regs = (volatile struct mac53c94_regs *)
-			node->addrs[0].address;
-		state->intr = node->intrs[0];
+			ioremap(node->addrs[0].address, 0x1000);
+		state->intr = node->intrs[0].line;
 		state->dma = (volatile struct dbdma_regs *)
-			node->addrs[1].address;
-		state->dmaintr = node->intrs[1];
+			ioremap(node->addrs[1].address, 0x1000);
+		state->dmaintr = node->intrs[1].line;
 
 		clkprop = get_property(node, "clock-frequency", &proplen);
 		if (clkprop == NULL || proplen != sizeof(int)) {
@@ -504,9 +505,36 @@
 data_goes_out(Scsi_Cmnd *cmd)
 {
 	switch (cmd->cmnd[0]) {
-	case WRITE_6:
-	case WRITE_10:
-	case WRITE_12:		/* any others? */
+	case CHANGE_DEFINITION: 
+	case COMPARE:	  
+	case COPY:
+	case COPY_VERIFY:	    
+	case FORMAT_UNIT:	 
+	case LOG_SELECT:
+	case MEDIUM_SCAN:	  
+	case MODE_SELECT:
+	case MODE_SELECT_10:
+	case REASSIGN_BLOCKS: 
+	case RESERVE:
+	case SEARCH_EQUAL:	  
+	case SEARCH_EQUAL_12: 
+	case SEARCH_HIGH:	 
+	case SEARCH_HIGH_12:  
+	case SEARCH_LOW:
+	case SEARCH_LOW_12:
+	case SEND_DIAGNOSTIC: 
+	case SEND_VOLUME_TAG:	     
+	case SET_WINDOW: 
+	case UPDATE_BLOCK:	
+	case WRITE_BUFFER:
+ 	case WRITE_6:	
+	case WRITE_10:	
+	case WRITE_12:	  
+	case WRITE_LONG:	
+	case WRITE_LONG_2:      /* alternate code for WRITE_LONG */
+	case WRITE_SAME:	
+	case WRITE_VERIFY:
+	case WRITE_VERIFY_12:
 		return 1;
 	default:
 		return 0;
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
--- v2.1.100/linux/drivers/scsi/mesh.c	Tue Apr 14 14:29:22 1998
+++ linux/drivers/scsi/mesh.c	Fri May  8 00:22:12 1998
@@ -21,15 +21,25 @@
 #include <linux/reboot.h>
 #include <asm/dbdma.h>
 #include <asm/io.h>
+#include <asm/pgtable.h>
 #include <asm/prom.h>
 #include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/processor.h>
 #include <asm/spinlock.h>
 
 #include "scsi.h"
 #include "hosts.h"
 #include "mesh.h"
 
-#if 0
+/*
+ * To do:
+ * - handle aborts correctly
+ * - retry arbitration if lost (unless higher levels do this for us)
+ */
+
+#if 1
 #undef KERN_DEBUG
 #define KERN_DEBUG KERN_WARNING
 #endif
@@ -56,6 +66,22 @@
 	S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
+#define MESH_DBG
+#define N_DBG_LOG	50
+#define N_DBG_SLOG	20
+#define NUM_DBG_EVENTS	13
+#undef	DBG_USE_TB		/* bombs on 601 */
+
+struct dbglog {
+	char	*fmt;
+	u32	tb;
+	u8	phase;
+	u8	bs0;
+	u8	bs1;
+	u8	tgt;
+	int	d;
+};
+
 enum mesh_phase {
 	idle,
 	arbitrating,
@@ -74,6 +100,7 @@
 	msg_out_xxx,
 	msg_out_last,
 	msg_in,
+	msg_in_bad,
 };
 
 enum sdtr_phase {
@@ -84,11 +111,16 @@
 
 struct mesh_target {
 	enum sdtr_phase sdtr_state;
-	enum mesh_phase phase;
 	int	sync_params;
-	int	data_goes_out;
+	int	data_goes_out;		/* guess as to data direction */
 	Scsi_Cmnd *current_req;
 	u32	saved_ptr;
+	int	want_abort;
+#ifdef MESH_DBG
+	int	log_ix;
+	int	n_log;
+	struct dbglog log[N_DBG_LOG];
+#endif
 };
 
 struct mesh_state {
@@ -105,9 +137,10 @@
 	int	conn_tgt;		/* target we're connected to */
 	Scsi_Cmnd *current_req;		/* req we're currently working on */
 	int	data_ptr;
-	int	data_goes_out;		/* guess as to data direction */
 	int	dma_started;
 	int	dma_count;
+	int	stat;
+	int	aborting;
 	int	expect_reply;
 	int	n_msgin;
 	u8	msgin[16];
@@ -116,18 +149,41 @@
 	u8	msgout[16];
 	struct dbdma_cmd *dma_cmds;	/* space for dbdma commands, aligned */
 	int	clk_freq;
-	struct mesh_target tgts[8];
-	struct tq_struct tqueue;
 	Scsi_Cmnd *completed_q;
 	Scsi_Cmnd *completed_qtail;
+	struct mesh_target tgts[8];
+	struct tq_struct tqueue;
+#ifdef MESH_DBG
+	int	log_ix;
+	int	n_log;
+	struct dbglog log[N_DBG_SLOG];
+#endif
 };
 
+#ifdef MESH_DBG
+
+static void dlog(struct mesh_state *ms, char *fmt, int a);
+static void dumplog(struct mesh_state *ms, int tgt);
+static void dumpslog(struct mesh_state *ms);
+#define MKWORD(a, b, c, d)	(((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
+
+#else
+static inline void dlog(struct mesh_state *ms, char *fmt, int a)
+{}
+static inline void dumplog(struct mesh_state *ms, int tgt)
+{}
+static inline void dumpslog(struct mesh_state *ms)
+{}
+
+#endif /* MESH_DBG */
+
 static struct mesh_state *all_meshes;
 
 static void mesh_init(struct mesh_state *);
 static int mesh_notify_reboot(struct notifier_block *, unsigned long, void *);
 static void mesh_dump_regs(struct mesh_state *);
 static void mesh_start(struct mesh_state *);
+static void mesh_start_cmd(struct mesh_state *, Scsi_Cmnd *);
 static void finish_cmds(void *);
 static void add_sdtr_msg(struct mesh_state *);
 static void set_sdtr(struct mesh_state *, int, int);
@@ -138,14 +194,17 @@
 static void phase_mismatch(struct mesh_state *);
 static void reselected(struct mesh_state *);
 static void handle_reset(struct mesh_state *);
+static void handle_error(struct mesh_state *);
+static void handle_exception(struct mesh_state *);
 static void mesh_interrupt(int, void *, struct pt_regs *);
 static void do_mesh_interrupt(int, void *, struct pt_regs *);
 static void handle_msgin(struct mesh_state *);
-static void mesh_done(struct mesh_state *);
+static void mesh_done(struct mesh_state *, int);
 static void mesh_completed(struct mesh_state *, Scsi_Cmnd *);
 static void set_dma_cmds(struct mesh_state *, Scsi_Cmnd *);
 static void halt_dma(struct mesh_state *);
 static int data_goes_out(Scsi_Cmnd *);
+static void do_abort(struct mesh_state *ms);
 
 static struct notifier_block mesh_notifier = {
 	mesh_notify_reboot,
@@ -164,13 +223,25 @@
 
 	nmeshes = 0;
 	prev_statep = &all_meshes;
-	for (mesh = find_devices("mesh"); mesh != 0; mesh = mesh->next) {
-		if (mesh->n_addrs != 2 || mesh->n_intrs != 2)
-			panic("mesh: expected 2 addrs and intrs (got %d/%d)",
-			      mesh->n_addrs, mesh->n_intrs);
+	/*
+	 * On powermacs, the MESH node has device_type "mesh".
+	 * On chrp machines, its device_type is "scsi" with
+	 * "chrp,mesh0" as its `compatible' property.
+	 */
+	mesh = find_devices("mesh");
+	if (mesh == 0)
+		mesh = find_compatible_devices("scsi", "chrp,mesh0");
+	for (; mesh != 0; mesh = mesh->next) {
+		if (mesh->n_addrs != 2 || mesh->n_intrs != 2) {
+			printk(KERN_ERR "mesh: expected 2 addrs and 2 intrs"
+			       " (got %d,%d)", mesh->n_addrs, mesh->n_intrs);
+			continue;
+		}
 		mesh_host = scsi_register(tp, sizeof(struct mesh_state));
-		if (mesh_host == 0)
-			panic("couldn't register mesh host");
+		if (mesh_host == 0) {
+			printk(KERN_ERR "mesh: couldn't register host");
+			continue;
+		}
 		mesh_host->unique_id = nmeshes;
 		note_scsi_host(mesh, mesh_host);
 
@@ -180,11 +251,11 @@
 		memset(ms, 0, sizeof(*ms));
 		ms->host = mesh_host;
 		ms->mesh = (volatile struct mesh_regs *)
-			mesh->addrs[0].address;
-		ms->meshintr = mesh->intrs[0];
+			ioremap(mesh->addrs[0].address, 0x1000);
 		ms->dma = (volatile struct dbdma_regs *)
-			mesh->addrs[1].address;
-		ms->dmaintr = mesh->intrs[1];
+			ioremap(mesh->addrs[1].address, 0x1000);
+		ms->meshintr = mesh->intrs[0].line;
+		ms->dmaintr = mesh->intrs[1].line;
 
 		/* Space for dma command list: +1 for stop command,
 		   +1 to allow for aligning. */
@@ -213,8 +284,8 @@
 			printk(KERN_ERR "MESH: can't get irq %d\n", ms->meshintr);
 		}
 
-		cfp = (int *) get_property(mesh, "clock-frequency", NULL);
-		if (cfp) {
+		if ((cfp = (int *) get_property(mesh, "clock-frequency",
+						NULL))) {
 			ms->clk_freq = *cfp;
 		} else {
 			printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n");
@@ -230,7 +301,7 @@
 
 		++nmeshes;
 	}
-	if (nmeshes > 0)
+	if (_machine == _MACH_Pmac && nmeshes > 0)
 		register_reboot_notifier(&mesh_notifier);
 
 	return nmeshes;
@@ -242,16 +313,6 @@
 	unsigned long flags;
 	struct mesh_state *ms;
 
-#if 0
-	if (data_goes_out(cmd)) {
-		printk(KERN_DEBUG "mesh_queue %p: command is", cmd);
-		for (i = 0; i < cmd->cmd_len; ++i)
-			printk(" %.2x", cmd->cmnd[i]);
-		printk("\n" KERN_DEBUG "use_sg=%d request_bufflen=%d request_buffer=%p\n",
-		       cmd->use_sg, cmd->request_bufflen, cmd->request_buffer);
-	}
-#endif
-
 	cmd->scsi_done = done;
 	cmd->host_scribble = NULL;
 
@@ -275,8 +336,12 @@
 int
 mesh_abort(Scsi_Cmnd *cmd)
 {
+	struct mesh_state *ms = (struct mesh_state *) cmd->host->hostdata;
+
 	printk(KERN_DEBUG "mesh_abort(%p)\n", cmd);
-	mesh_dump_regs((struct mesh_state *)(cmd->host->hostdata));
+	mesh_dump_regs(ms);
+	dumplog(ms, cmd->target);
+	dumpslog(ms);
 	return SCSI_ABORT_SNOOZE;
 }
 
@@ -290,22 +355,24 @@
 
 	printk(KERN_DEBUG "mesh: state at %p, regs at %p, dma at %p\n",
 	       ms, mr, md);
-	printk(KERN_DEBUG "    ct=%4x seq=%2x bs=%4x fc=%2x exc=%2x err=%2x sp=%2x\n",
+	printk(KERN_DEBUG "    ct=%4x seq=%2x bs=%4x fc=%2x "
+	       "exc=%2x err=%2x im=%2x int=%2x sp=%2x\n",
 	       (mr->count_hi << 8) + mr->count_lo, mr->sequence,
 	       (mr->bus_status1 << 8) + mr->bus_status0, mr->fifo_count,
-	       mr->exception, mr->error, mr->sync_params);
+	       mr->exception, mr->error, mr->intr_mask, mr->interrupt,
+	       mr->sync_params);
 	printk(KERN_DEBUG "    dma stat=%x cmdptr=%x\n",
 	       in_le32(&md->status), in_le32(&md->cmdptr));
 	printk(KERN_DEBUG "    phase=%d msgphase=%d conn_tgt=%d data_ptr=%d\n",
 	       ms->phase, ms->msgphase, ms->conn_tgt, ms->data_ptr);
-	printk(KERN_DEBUG "    goes_out=%d dma_st=%d dma_ct=%d n_msgout=%d\n",
-	       ms->data_goes_out, ms->dma_started, ms->dma_count, ms->n_msgout);
+	printk(KERN_DEBUG "    dma_st=%d dma_ct=%d n_msgout=%d\n",
+	       ms->dma_started, ms->dma_count, ms->n_msgout);
 	for (t = 0; t < 8; ++t) {
 		tp = &ms->tgts[t];
 		if (tp->current_req == NULL)
 			continue;
-		printk(KERN_DEBUG "    target %d: req=%p phase=%d saved_ptr=%d\n",
-		       t, tp->current_req, tp->phase, tp->saved_ptr);
+		printk(KERN_DEBUG "    target %d: req=%p goes_out=%d saved_ptr=%d\n",
+		       t, tp->current_req, tp->data_goes_out, tp->saved_ptr);
 	}
 }
 
@@ -322,14 +389,17 @@
 	ret = SCSI_RESET_BUS_RESET;
 	save_flags(flags);
 	cli();
+	out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16);	/* stop dma */
 	out_8(&mr->exception, 0xff);	/* clear all exception bits */
 	out_8(&mr->error, 0xff);	/* clear all error bits */
-	out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
 	if (how & SCSI_RESET_SUGGEST_HOST_RESET) {
 		out_8(&mr->sequence, SEQ_RESETMESH);
 		ret |= SCSI_RESET_HOST_RESET;
 		udelay(1);
 		out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+		out_8(&mr->source_id, ms->host->this_id);
+		out_8(&mr->sel_timeout, 25);	/* 250ms */
+		out_8(&mr->sync_params, ASYNC_PARAMS);
 	}
 	out_8(&mr->bus_status1, BS1_RST);	/* assert RST */
 	udelay(30);			/* leave it on for >= 25us */
@@ -341,7 +411,6 @@
 	} else
 #endif
 	{
-		out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
 		handle_reset(ms);
 		restore_flags(flags);
 		finish_cmds(ms);
@@ -361,7 +430,7 @@
 	struct mesh_state *ms;
 	volatile struct mesh_regs *mr;
 
-	if (code == SYS_DOWN || code == SYS_HALT) {
+	if (code == SYS_DOWN) {
 		printk(KERN_INFO "resetting MESH scsi bus(es)\n");
 		for (ms = all_meshes; ms != 0; ms = ms->next) {
 			mr = ms->mesh;
@@ -405,29 +474,42 @@
 mesh_start(struct mesh_state *ms)
 {
 	Scsi_Cmnd *cmd, *prev, *next;
-	volatile struct mesh_regs *mr = ms->mesh;
 
-	if (ms->phase != idle || ms->current_req != NULL)
-		panic("inappropriate mesh_start (ms=%p)", ms);
+	if (ms->phase != idle || ms->current_req != NULL) {
+		printk(KERN_ERR "inappropriate mesh_start (phase=%d, ms=%p)",
+		       ms->phase, ms);
+		return;
+	}
 
-	prev = NULL;
-	for (cmd = ms->request_q; ; cmd = (Scsi_Cmnd *) cmd->host_scribble) {
-		if (cmd == NULL)
-			return;
-		if (ms->tgts[cmd->target].current_req == NULL)
-			break;
-		prev = cmd;
+	while (ms->phase == idle) {
+		prev = NULL;
+		for (cmd = ms->request_q; ; cmd = (Scsi_Cmnd *) cmd->host_scribble) {
+			if (cmd == NULL)
+				return;
+			if (ms->tgts[cmd->target].current_req == NULL)
+				break;
+			prev = cmd;
+		}
+		next = (Scsi_Cmnd *) cmd->host_scribble;
+		if (prev == NULL)
+			ms->request_q = next;
+		else
+			prev->host_scribble = (void *) next;
+		if (next == NULL)
+			ms->request_qtail = prev;
+
+		mesh_start_cmd(ms, cmd);
 	}
-	next = (Scsi_Cmnd *) cmd->host_scribble;
-	if (prev == NULL)
-		ms->request_q = next;
-	else
-		prev->host_scribble = (void *) next;
-	if (next == NULL)
-		ms->request_qtail = prev;
+}
+
+static void
+mesh_start_cmd(struct mesh_state *ms, Scsi_Cmnd *cmd)
+{
+	volatile struct mesh_regs *mr = ms->mesh;
+	int t;
 
 	ms->current_req = cmd;
-	ms->data_goes_out = data_goes_out(cmd);
+	ms->tgts[cmd->target].data_goes_out = data_goes_out(cmd);
 	ms->tgts[cmd->target].current_req = cmd;
 
 #if 1
@@ -442,9 +524,6 @@
 	}
 #endif
 
-	/* Off we go */
-	out_8(&mr->sequence, SEQ_ARBITRATE);
-
 	ms->phase = arbitrating;
 	ms->msgphase = msg_none;
 	ms->data_ptr = 0;
@@ -454,6 +533,118 @@
 	ms->expect_reply = 0;
 	ms->conn_tgt = cmd->target;
 	ms->tgts[cmd->target].saved_ptr = 0;
+	ms->stat = DID_OK;
+	ms->aborting = 0;
+#ifdef MESH_DBG
+	ms->tgts[cmd->target].n_log = 0;
+	dlog(ms, "start cmd=%x", (int) cmd);
+#endif
+
+	/* Off we go */
+	dlog(ms, "about to arb, intr/exc/err/fc=%.8x",
+	     MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count));
+	out_8(&mr->interrupt, INT_CMDDONE);
+	out_8(&mr->sequence, SEQ_ENBRESEL);
+	udelay(1);
+
+	if (mr->bus_status1 & (BS1_BSY | BS1_SEL)) {
+		/*
+		 * Some other device has the bus or is arbitrating for it -
+		 * probably a target which is about to reselect us.
+		 */
+		dlog(ms, "busy b4 arb, intr/exc/err/fc=%.8x",
+		     MKWORD(mr->interrupt, mr->exception,
+			    mr->error, mr->fifo_count));
+		for (t = 100; t > 0; --t) {
+			if ((mr->bus_status1 & (BS1_BSY | BS1_SEL)) == 0)
+				break;
+			if (in_8(&mr->interrupt) != 0) {
+				dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x",
+				     MKWORD(mr->interrupt, mr->exception,
+					    mr->error, mr->fifo_count));
+				mesh_interrupt(0, (void *)ms, 0);
+				if (ms->phase != arbitrating)
+					return;
+			}
+			udelay(1);
+		}
+		if (mr->bus_status1 & (BS1_BSY | BS1_SEL)) {
+			/* XXX should try again in a little while */
+			ms->stat = DID_BUS_BUSY;
+			ms->phase = idle;
+			mesh_done(ms, 0);
+			return;
+		}
+	}
+
+	/*
+	 * Apparently the mesh has a bug where it will assert both its
+	 * own bit and the target's bit on the bus during arbitration.
+	 */
+	out_8(&mr->dest_id, mr->source_id);
+
+	/*
+	 * There appears to be a race with reselection sometimes,
+	 * where a target reselects us just as we issue the
+	 * arbitrate command.  It seems that then the arbitrate
+	 * command just hangs waiting for the bus to be free
+	 * without giving us a reselection exception.
+	 * The only way I have found to get it to respond correctly
+	 * is this: disable reselection before issuing the arbitrate
+	 * command, then after issuing it, if it looks like a target
+	 * is trying to reselect us, reset the mesh and then enable
+	 * reselection.
+	 */
+	out_8(&mr->sequence, SEQ_DISRESEL);
+	if (in_8(&mr->interrupt) != 0) {
+		dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x",
+		     MKWORD(mr->interrupt, mr->exception,
+			    mr->error, mr->fifo_count));
+		mesh_interrupt(0, (void *)ms, 0);
+		if (ms->phase != arbitrating)
+			return;
+		dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x",
+		     MKWORD(mr->interrupt, mr->exception,
+			    mr->error, mr->fifo_count));
+	}
+
+	out_8(&mr->sequence, SEQ_ARBITRATE);
+
+	for (t = 30; t > 0; --t) {
+		if (in_8(&mr->interrupt) != 0)
+			break;
+		udelay(1);
+	}
+	dlog(ms, "after arb, intr/exc/err/fc=%.8x",
+	     MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count));
+	if (mr->interrupt == 0 && (mr->bus_status1 & BS1_SEL)
+	    && (mr->bus_status0 & BS0_IO)) {
+		/* looks like a reselection - try resetting the mesh */
+		dlog(ms, "resel? after arb, intr/exc/err/fc=%.8x",
+		     MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count));
+		out_8(&mr->sequence, SEQ_RESETMESH);
+		udelay(10);
+		out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+		out_8(&mr->intr_mask, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+		out_8(&mr->sequence, SEQ_ENBRESEL);
+		for (t = 10; t > 0 && mr->interrupt == 0; --t)
+			udelay(1);
+		dlog(ms, "tried reset after arb, intr/exc/err/fc=%.8x",
+		     MKWORD(mr->interrupt, mr->exception, mr->error, mr->fifo_count));
+#ifndef MESH_MULTIPLE_HOSTS
+		if (mr->interrupt == 0 && (mr->bus_status1 & BS1_SEL)
+		    && (mr->bus_status0 & BS0_IO)) {
+			printk(KERN_ERR "mesh: controller not responding"
+			       " to reselection!\n");
+			/*
+			 * If this is a target reselecting us, and the
+			 * mesh isn't responding, the higher levels of
+			 * the scsi code will eventually time out and
+			 * reset the bus.
+			 */
+		}
+#endif
+	}
 }
 
 static void
@@ -541,10 +732,9 @@
 	Scsi_Cmnd *cmd = ms->current_req;
 	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];
 
-	if (cmd == 0) {
-		printk(KERN_ERR "mesh: start_phase but no cmd?\n");
-		return;
-	}
+	dlog(ms, "start_phase err/exc/fc/seq = %.8x",
+	     MKWORD(mr->error, mr->exception, mr->fifo_count, mr->sequence));
+	out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
 	seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0);
 	switch (ms->msgphase) {
 	case msg_none:
@@ -563,20 +753,44 @@
 		 * the last byte of the message, we have to do the
 		 * last byte specially.
 		 */
-		if (DEBUG_TARGET(cmd)) {
+		if (ms->n_msgout <= 0) {
+			printk(KERN_ERR "mesh: msg_out but n_msgout=%d\n",
+			       ms->n_msgout);
+			mesh_dump_regs(ms);
+			ms->msgphase = msg_none;
+			break;
+		}
+		if (ALLOW_DEBUG(ms->conn_tgt)) {
 			printk(KERN_DEBUG "mesh: sending %d msg bytes:",
 			       ms->n_msgout);
 			for (i = 0; i < ms->n_msgout; ++i)
 				printk(" %x", ms->msgout[i]);
 			printk("\n");
 		}
+		dlog(ms, "msgout msg=%.8x", MKWORD(ms->n_msgout, ms->msgout[0],
+						ms->msgout[1], ms->msgout[2]));
 		out_8(&mr->count_hi, 0);
-		if (ms->n_msgout == 1) {
-			out_8(&mr->count_lo, 1);
-			out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG);
+		out_8(&mr->sequence, SEQ_FLUSHFIFO);
+		udelay(1);
+		/*
+		 * If ATN is not already asserted, we assert it, then
+		 * issue a SEQ_MSGOUT to get the mesh to drop ACK.
+		 */
+		if ((mr->bus_status0 & BS0_ATN) == 0) {
+			out_8(&mr->bus_status0, BS0_ATN); /* explicit ATN */
 			udelay(1);
-			out_8(&mr->fifo, ms->msgout[0]);
-			ms->msgphase = msg_out_last;
+			out_8(&mr->count_lo, 1);
+			out_8(&mr->sequence, SEQ_MSGOUT + seq);
+			out_8(&mr->bus_status0, 0); /* release explicit ATN */
+		}
+		if (ms->n_msgout == 1) {
+			/*
+			 * We can't issue the SEQ_MSGOUT without ATN
+			 * until the target has asserted REQ.  The logic
+			 * in cmd_complete handles both situations:
+			 * REQ already asserted or not.
+			 */
+			cmd_complete(ms);
 		} else {
 			out_8(&mr->count_lo, ms->n_msgout - 1);
 			out_8(&mr->sequence, SEQ_MSGOUT + seq);
@@ -592,16 +806,23 @@
 
 	switch (ms->phase) {
 	case selecting:
-		out_8(&mr->dest_id, cmd->target);
+		out_8(&mr->dest_id, ms->conn_tgt);
 		out_8(&mr->sequence, SEQ_SELECT + SEQ_ATN);
 		break;
 	case commanding:
 		out_8(&mr->sync_params, tp->sync_params);
 		out_8(&mr->count_hi, 0);
-		out_8(&mr->count_lo, cmd->cmd_len);
-		out_8(&mr->sequence, SEQ_COMMAND + seq);
-		for (i = 0; i < cmd->cmd_len; ++i)
-			out_8(&mr->fifo, cmd->cmnd[i]);
+		if (cmd) {
+			out_8(&mr->count_lo, cmd->cmd_len);
+			out_8(&mr->sequence, SEQ_COMMAND + seq);
+			for (i = 0; i < cmd->cmd_len; ++i)
+				out_8(&mr->fifo, cmd->cmnd[i]);
+		} else {
+			out_8(&mr->count_lo, 6);
+			out_8(&mr->sequence, SEQ_COMMAND + seq);
+			for (i = 0; i < 6; ++i)
+				out_8(&mr->fifo, 0);
+		}
 		break;
 	case dataing:
 		/* transfer data, if any */
@@ -618,7 +839,7 @@
 		ms->data_ptr += nb;
 		out_8(&mr->count_lo, nb);
 		out_8(&mr->count_hi, nb >> 8);
-		out_8(&mr->sequence, (ms->data_goes_out?
+		out_8(&mr->sequence, (tp->data_goes_out?
 				SEQ_DATAOUT: SEQ_DATAIN) + SEQ_DMA_MODE + seq);
 		break;
 	case statusing:
@@ -630,11 +851,15 @@
 	case disconnecting:
 		out_8(&mr->sequence, SEQ_ENBRESEL);
 		udelay(1);
+		dlog(ms, "enbresel intr/exc/err/fc=%.8x",
+		     MKWORD(mr->interrupt, mr->exception, mr->error,
+			    mr->fifo_count));
 		out_8(&mr->sequence, SEQ_BUSFREE);
 		break;
 	default:
 		printk(KERN_ERR "mesh: start_phase called with phase=%d\n",
 		       ms->phase);
+		dumpslog(ms);
 	}
 
 }
@@ -681,6 +906,7 @@
 	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];
 	int seq, n, t;
 
+	dlog(ms, "cmd_complete fc=%x", mr->fifo_count);
 	seq = SEQ_ACTIVE_NEG + (ms->n_msgout? SEQ_ATN: 0);
 	switch (ms->msgphase) {
 	case msg_out_xxx:
@@ -703,6 +929,13 @@
 		}
 		break;
 
+	case msg_in_bad:
+		out_8(&mr->sequence, SEQ_FLUSHFIFO);
+		udelay(1);
+		out_8(&mr->count_lo, 1);
+		out_8(&mr->sequence, SEQ_MSGIN + SEQ_ATN + SEQ_ACTIVE_NEG);
+		break;
+
 	case msg_out:
 		/*
 		 * To get the right timing on ATN wrt ACK, we have
@@ -720,6 +953,28 @@
 		t = 30;		/* wait up to 30us */
 		while ((mr->bus_status0 & BS0_REQ) == 0 && --t >= 0)
 			udelay(1);
+		dlog(ms, "last_mbyte err/exc/fc/cl=%.8x",
+		     MKWORD(mr->error, mr->exception,
+			    mr->fifo_count, mr->count_lo));
+		if (in_8(&mr->interrupt) & (INT_ERROR | INT_EXCEPTION)) {
+			/* whoops, target didn't do what we expected */
+			ms->last_n_msgout = ms->n_msgout;
+			ms->n_msgout = 0;
+			if (in_8(&mr->interrupt) & INT_ERROR) {
+				printk(KERN_ERR "mesh: error %x in msg_out\n",
+				       in_8(&mr->error));
+				handle_error(ms);
+				return;
+			}
+			if (in_8(&mr->exception) != EXC_PHASEMM)
+				printk(KERN_ERR "mesh: exc %x in msg_out\n",
+				       in_8(&mr->exception));
+			else
+				printk(KERN_DEBUG "mesh: bs0=%x in msg_out\n",
+				       in_8(&mr->bus_status0));
+			handle_exception(ms);
+			return;
+		}
 		if (mr->bus_status0 & BS0_REQ) {
 			out_8(&mr->sequence, SEQ_MSGOUT + SEQ_ACTIVE_NEG);
 			udelay(1);
@@ -740,11 +995,19 @@
 
 	case msg_none:
 		switch (ms->phase) {
+		case idle:
+			printk(KERN_ERR "mesh: interrupt in idle phase?\n");
+			dumpslog(ms);
+			return;
 		case selecting:
-			ms->msgout[0] = IDENTIFY(ALLOW_RESEL(cmd->target), cmd->lun);
+			ms->msgout[0] = IDENTIFY(ALLOW_RESEL(ms->conn_tgt),
+						 (cmd? cmd->lun: 0));
 			ms->n_msgout = 1;
 			ms->expect_reply = 0;
-			if (tp->sdtr_state == do_sdtr) {
+			if (ms->aborting) {
+				ms->msgout[0] = ABORT;
+				ms->n_msgout++;
+			} else if (tp->sdtr_state == do_sdtr) {
 				/* add SDTR message */
 				add_sdtr_msg(ms);
 				ms->expect_reply = 1;
@@ -772,18 +1035,32 @@
 				start_phase(ms);
 				return;
 			}
+			/*
+			 * We can get a phase mismatch here if the target
+			 * changes to the status phase, even though we have
+			 * had a command complete interrupt.  Then, if we
+			 * issue the SEQ_STATUS command, we'll get a sequence
+			 * error interrupt.  Which isn't so bad except that
+			 * occasionally the mesh actually executes the
+			 * SEQ_STATUS *as well as* giving us the sequence
+			 * error and phase mismatch exception.
+			 */
+			out_8(&mr->sequence, 0);
+			out_8(&mr->interrupt,
+			      INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
 			halt_dma(ms);
 			break;
 		case statusing:
-			cmd->SCp.Status = mr->fifo;
-			cmd->result = (DID_OK << 16) + cmd->SCp.Status;
+			if (cmd) {
+				cmd->SCp.Status = mr->fifo;
+				if (DEBUG_TARGET(cmd))
+					printk(KERN_DEBUG "mesh: status is %x\n",
+					       cmd->SCp.Status);
+			}
 			ms->msgphase = msg_in;
-			if (DEBUG_TARGET(cmd))
-				printk(KERN_DEBUG "mesh: status is %x\n",
-				       cmd->SCp.Status);
 			break;
 		case busfreeing:
-			mesh_done(ms);
+			mesh_done(ms, 1);
 			return;
 		case disconnecting:
 			ms->current_req = 0;
@@ -804,6 +1081,8 @@
 	volatile struct mesh_regs *mr = ms->mesh;
 	int phase;
 
+	dlog(ms, "phasemm ch/cl/seq/fc=%.8x",
+	     MKWORD(mr->count_hi, mr->count_lo, mr->sequence, mr->fifo_count));
 	phase = mr->bus_status0 & BS0_PHASE;
 	if (ms->msgphase == msg_out_xxx && phase == BP_MSGOUT) {
 		/* output the last byte of the message, without ATN */
@@ -831,11 +1110,11 @@
 	ms->msgphase = msg_none;
 	switch (phase) {
 	case BP_DATAIN:
-		ms->data_goes_out = 0;
+		ms->tgts[ms->conn_tgt].data_goes_out = 0;
 		ms->phase = dataing;
 		break;
 	case BP_DATAOUT:
-		ms->data_goes_out = 1;
+		ms->tgts[ms->conn_tgt].data_goes_out = 1;
 		ms->phase = dataing;
 		break;
 	case BP_COMMAND:
@@ -851,18 +1130,23 @@
 	case BP_MSGOUT:
 		ms->msgphase = msg_out;
 		if (ms->n_msgout == 0) {
-			if (ms->last_n_msgout == 0) {
-				printk(KERN_DEBUG "mesh: no msg to repeat\n");
-				ms->msgout[0] = NOP;
-				ms->last_n_msgout = 1;
+			if (ms->aborting) {
+				do_abort(ms);
+			} else {
+				if (ms->last_n_msgout == 0) {
+					printk(KERN_DEBUG
+					       "mesh: no msg to repeat\n");
+					ms->msgout[0] = NOP;
+					ms->last_n_msgout = 1;
+				}
+				ms->n_msgout = ms->last_n_msgout;
 			}
-			ms->n_msgout = ms->last_n_msgout;
 		}
 		break;
 	default:
 		printk(KERN_DEBUG "mesh: unknown scsi phase %x\n", phase);
-		ms->current_req->result = DID_ERROR << 16;
-		mesh_done(ms);
+		ms->stat = DID_ERROR;
+		mesh_done(ms, 1);
 		return;
 	}
 
@@ -873,82 +1157,126 @@
 reselected(struct mesh_state *ms)
 {
 	volatile struct mesh_regs *mr = ms->mesh;
-	Scsi_Cmnd *cmd = ms->current_req;
+	Scsi_Cmnd *cmd;
 	struct mesh_target *tp;
-	int b, t;
+	int b, t, prev;
 
 	switch (ms->phase) {
 	case idle:
+		break;
 	case arbitrating:
+		if ((cmd = ms->current_req) != NULL) {
+			/* put the command back on the queue */
+			cmd->host_scribble = (void *) ms->request_q;
+			if (ms->request_q == NULL)
+				ms->request_qtail = cmd;
+			ms->request_q = cmd;
+			tp = &ms->tgts[cmd->target];
+			tp->current_req = NULL;
+		}
 		break;
 	case busfreeing:
 		ms->phase = reselecting;
-		mesh_done(ms);
-		cmd = NULL;
+		mesh_done(ms, 0);
 		break;
 	case disconnecting:
-		cmd = NULL;
 		break;
 	default:
-		printk(KERN_ERR "mesh: reselected in phase %d/%d\n",
-		       ms->msgphase, ms->phase);
-	}
-	if (cmd) {
-		/* put the command back on the queue */
-		cmd->host_scribble = (void *) ms->request_q;
-		if (ms->request_q == NULL)
-			ms->request_qtail = cmd;
-		ms->request_q = cmd;
-		tp = &ms->tgts[cmd->target];
-		tp->current_req = NULL;
-		ms->current_req = NULL;
+		printk(KERN_ERR "mesh: reselected in phase %d/%d tgt %d\n",
+		       ms->msgphase, ms->phase, ms->conn_tgt);
+		dumplog(ms, ms->conn_tgt);
+		dumpslog(ms);
 	}
 
+	ms->current_req = NULL;
+	ms->phase = dataing;
+	ms->msgphase = msg_in;
+	ms->dma_started = 0;
+	ms->n_msgout = 0;
+	ms->last_n_msgout = 0;
+	prev = ms->conn_tgt;
+
+	/*
+	 * We seem to get abortive reselections sometimes.
+	 */
+	while ((mr->bus_status1 & BS1_BSY) == 0) {
+		static int mesh_aborted_resels;
+		mesh_aborted_resels++;
+		out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+		udelay(1);
+		out_8(&mr->sequence, SEQ_ENBRESEL);
+		udelay(5);
+		dlog(ms, "extra resel err/exc/fc = %.6x",
+		     MKWORD(0, mr->error, mr->exception, mr->fifo_count));
+	}
+	out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+	udelay(1);
+	out_8(&mr->sequence, SEQ_ENBRESEL);
+	udelay(1);
+	out_8(&mr->sync_params, ASYNC_PARAMS);
+
 	/*
 	 * Find out who reselected us.
 	 */
 	if (mr->fifo_count == 0) {
 		printk(KERN_ERR "mesh: reselection but nothing in fifo?\n");
-		return;
+		ms->conn_tgt = ms->host->this_id;
+		goto bogus;
 	}
 	/* get the last byte in the fifo */
 	do {
 		b = in_8(&mr->fifo);
+		dlog(ms, "reseldata %x", b);
 	} while (in_8(&mr->fifo_count));
 	for (t = 0; t < 8; ++t)
 		if ((b & (1 << t)) != 0 && t != ms->host->this_id)
 			break;
 	if (b != (1 << t) + (1 << ms->host->this_id)) {
 		printk(KERN_ERR "mesh: bad reselection data %x\n", b);
-		return;
+		ms->conn_tgt = ms->host->this_id;
+		goto bogus;
 	}
 
+
 	/*
 	 * Set up to continue with that target's transfer.
 	 */
+	ms->conn_tgt = t;
 	tp = &ms->tgts[t];
+	out_8(&mr->sync_params, tp->sync_params);
 	if (ALLOW_DEBUG(t)) {
 		printk(KERN_DEBUG "mesh: reselected by target %d\n", t);
-		printk(KERN_DEBUG "mesh: saved_ptr=%x phase=%d cmd=%p\n",
-		       tp->saved_ptr, tp->phase, tp->current_req);
+		printk(KERN_DEBUG "mesh: saved_ptr=%x goes_out=%d cmd=%p\n",
+		       tp->saved_ptr, tp->data_goes_out, tp->current_req);
 	}
+	ms->current_req = tp->current_req;
 	if (tp->current_req == NULL) {
 		printk(KERN_ERR "mesh: reselected by tgt %d but no cmd!\n", t);
-		return;
+		goto bogus;
 	}
-	ms->current_req = tp->current_req;
-	ms->phase = tp->phase;
-	ms->msgphase = msg_in;
-	ms->data_goes_out = tp->data_goes_out;
 	ms->data_ptr = tp->saved_ptr;
-	ms->conn_tgt = t;
-	ms->dma_started = 0;
-	ms->n_msgout = 0;
-	ms->last_n_msgout = 0;
-	out_8(&mr->sync_params, tp->sync_params);
+	dlog(ms, "resel prev tgt=%d", prev);
+	dlog(ms, "resel err/exc=%.4x", MKWORD(0, 0, mr->error, mr->exception));
+	start_phase(ms);
+	return;
+
+bogus:
+	dumplog(ms, ms->conn_tgt);
+	dumpslog(ms);
+	ms->data_ptr = 0;
+	ms->aborting = 1;
 	start_phase(ms);
 }
 
+static void do_abort(struct mesh_state *ms)
+{
+	ms->msgout[0] = ABORT;
+	ms->n_msgout = 1;
+	ms->aborting = 1;
+	ms->stat = DID_ABORT;
+	dlog(ms, "abort", 0);
+}
+
 static void
 handle_reset(struct mesh_state *ms)
 {
@@ -974,7 +1302,12 @@
 		mesh_completed(ms, cmd);
 	}
 	ms->phase = idle;
+	ms->msgphase = msg_none;
+	out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+	out_8(&mr->sequence, SEQ_FLUSHFIFO);
+	udelay(1);
 	out_8(&mr->sync_params, ASYNC_PARAMS);
+	out_8(&mr->sequence, SEQ_ENBRESEL);
 }
 
 static void
@@ -987,90 +1320,153 @@
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
+static void handle_error(struct mesh_state *ms)
+{
+	int err, exc, count;
+	volatile struct mesh_regs *mr = ms->mesh;
+
+	err = in_8(&mr->error);
+	exc = in_8(&mr->exception);
+	out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
+	dlog(ms, "error err/exc/fc/cl=%.8x",
+	     MKWORD(err, exc, mr->fifo_count, mr->count_lo));
+	if (err & ERR_SCSIRESET) {
+		/* SCSI bus was reset */
+		printk(KERN_INFO "mesh: SCSI bus reset detected: "
+		       "waiting for end...");
+		while ((mr->bus_status1 & BS1_RST) != 0)
+			udelay(1);
+		printk("done\n");
+		handle_reset(ms);
+		/* request_q is empty, no point in mesh_start() */
+		return;
+	}
+	if (err & ERR_UNEXPDISC) {
+		/* Unexpected disconnect */
+		if (exc & EXC_RESELECTED) {
+			reselected(ms);
+			return;
+		}
+		if (!ms->aborting) {
+			printk(KERN_WARNING "mesh: target %d aborted\n",
+			       ms->conn_tgt);
+			dumplog(ms, ms->conn_tgt);
+			dumpslog(ms);
+		}
+		out_8(&mr->interrupt, INT_CMDDONE);
+		ms->stat = DID_ABORT;
+		mesh_done(ms, 1);
+		return;
+	}
+	if (err & ERR_PARITY) {
+		if (ms->msgphase == msg_in) {
+			printk(KERN_ERR "mesh: msg parity error, target %d\n",
+			       ms->conn_tgt);
+			ms->msgout[0] = MSG_PARITY_ERROR;
+			ms->n_msgout = 1;
+			ms->msgphase = msg_in_bad;
+			cmd_complete(ms);
+			return;
+		}
+		if (ms->stat == DID_OK) {
+			printk(KERN_ERR "mesh: parity error, target %d\n",
+			       ms->conn_tgt);
+			ms->stat = DID_PARITY;
+		}
+		count = (mr->count_hi << 8) + mr->count_lo;
+		if (count == 0) {
+			cmd_complete(ms);
+		} else {
+			/* reissue the data transfer command */
+			out_8(&mr->sequence, mr->sequence);
+		}
+		return;
+	}
+	if (err & ERR_SEQERR) {
+		if (exc & EXC_RESELECTED) {
+			/* This can happen if we issue a command to
+			   get the bus just after the target reselects us. */
+			static int mesh_resel_seqerr;
+			mesh_resel_seqerr++;
+			reselected(ms);
+			return;
+		}
+		if (exc == EXC_PHASEMM) {
+			static int mesh_phasemm_seqerr;
+			mesh_phasemm_seqerr++;
+			phase_mismatch(ms);
+			return;
+		}
+		printk(KERN_ERR "mesh: sequence error (err=%x exc=%x)\n",
+		       err, exc);
+	} else {
+		printk(KERN_ERR "mesh: unknown error %x (exc=%x)\n", err, exc);
+	}
+	mesh_dump_regs(ms);
+	dumplog(ms, ms->conn_tgt);
+	if (ms->phase > selecting && (mr->bus_status1 & BS1_BSY)) {
+		/* try to do what the target wants */
+		do_abort(ms);
+		phase_mismatch(ms);
+		return;
+	}
+	ms->stat = DID_ERROR;
+	mesh_done(ms, 1);
+}
+
+static void handle_exception(struct mesh_state *ms)
+{
+	int exc;
+	volatile struct mesh_regs *mr = ms->mesh;
+
+	exc = in_8(&mr->exception);
+	out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE);
+	if (exc & EXC_RESELECTED) {
+		static int mesh_resel_exc;
+		mesh_resel_exc++;
+		reselected(ms);
+	} else if (exc == EXC_ARBLOST) {
+		printk(KERN_DEBUG "mesh: lost arbitration\n");
+		ms->stat = DID_BUS_BUSY;
+		mesh_done(ms, 1);
+	} else if (exc == EXC_SELTO) {
+		/* selection timed out */
+		ms->stat = DID_BAD_TARGET;
+		mesh_done(ms, 1);
+	} else if (exc == EXC_PHASEMM) {
+		/* target wants to do something different:
+		   find out what it wants and do it. */
+		phase_mismatch(ms);
+	} else {
+		printk(KERN_ERR "mesh: can't cope with exception %x\n", exc);
+		mesh_dump_regs(ms);
+		dumplog(ms, ms->conn_tgt);
+		do_abort(ms);
+		phase_mismatch(ms);
+	}
+}
+
 static void
 mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
 {
 	struct mesh_state *ms = (struct mesh_state *) dev_id;
 	volatile struct mesh_regs *mr = ms->mesh;
-	Scsi_Cmnd *cmd = ms->current_req;
-	int stat, exc, err, intr;
+	int intr;
 
 #if 0
-	if (DEBUG_TARGET(cmd))
-		printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x phase=%d msgphase=%d\n",
-		       mr->bus_status0, mr->interrupt, mr->exception, mr->error, ms->phase, ms->msgphase);
+	if (ALLOW_DEBUG(ms->conn_tgt))
+		printk(KERN_DEBUG "mesh_intr, bs0=%x int=%x exc=%x err=%x "
+		       "phase=%d msgphase=%d\n", mr->bus_status0,
+		       mr->interrupt, mr->exception, mr->error,
+		       ms->phase, ms->msgphase);
 #endif
 	while ((intr = in_8(&mr->interrupt)) != 0) {
+		dlog(ms, "interrupt intr/err/exc/seq=%.8x", 
+		     MKWORD(intr, mr->error, mr->exception, mr->sequence));
 		if (intr & INT_ERROR) {
-			stat = DID_BAD_INTR << 16;
-			err = in_8(&mr->error);
-			exc = in_8(&mr->exception);
-			out_8(&mr->interrupt, INT_ERROR | INT_EXCEPTION | INT_CMDDONE);
-			if (err & ERR_SCSIRESET) {
-				/* SCSI bus was reset */
-				printk(KERN_INFO "mesh: SCSI bus reset detected: "
-				       "waiting for end...");
-				while ((mr->bus_status1 & BS1_RST) != 0)
-					udelay(1);
-				printk("done\n");
-				handle_reset(ms);
-				/* request_q is empty, no point in mesh_start() */
-				continue;
-			} else if (err & ERR_UNEXPDISC) {
-				/* Unexpected disconnect */
-				printk(KERN_WARNING "mesh: target %d aborted\n",
-				       ms->conn_tgt);
-				stat = DID_ABORT << 16;
-			} else if (err & ERR_PARITY) {
-				printk(KERN_ERR "mesh: parity error\n");
-				stat = DID_PARITY << 16;
-			} else if ((err & ERR_SEQERR) && (exc & EXC_RESELECTED)
-				   && ms->phase == arbitrating) {
-				/* This can happen if we issue a command to
-				   get the bus just after the target
-				   reselects us. */
-				static int mesh_resel_seqerr;
-				mesh_resel_seqerr++;
-				reselected(ms);
-				continue;
-			} else {
-				printk(KERN_ERR "mesh: error %x (exc = %x)\n",
-				       err, exc);
-				mesh_dump_regs(ms);
-			}
-			if (cmd != 0) {
-				cmd->result = stat;
-				mesh_done(ms);
-			}
-
+			handle_error(ms);
 		} else if (intr & INT_EXCEPTION) {
-			exc = in_8(&mr->exception);
-			out_8(&mr->interrupt, INT_EXCEPTION | INT_CMDDONE);
-			if (exc & EXC_RESELECTED) {
-				static int mesh_resel_exc;
-				mesh_resel_exc++;
-				reselected(ms);
-			} else if (cmd && exc == EXC_ARBLOST
-				   && ms->phase == arbitrating) {
-				printk(KERN_DEBUG "mesh: lost arbitration\n");
-				cmd->result = DID_BUS_BUSY << 16;
-				mesh_done(ms);
-			} else if (cmd && exc == EXC_SELTO && ms->phase == selecting) {
-				/* selection timed out */
-				cmd->result = DID_BAD_TARGET << 16;
-				mesh_done(ms);
-			} else if (cmd && exc == EXC_PHASEMM
-				   && (mr->bus_status0 & BS0_REQ) != 0) {
-				/* target wants to do something different:
-			   find out what it wants and do it. */
-				phase_mismatch(ms);
-			} else {
-				printk(KERN_ERR "mesh: can't cope with exception %x\n",
-				       exc);
-				cmd->result = DID_ERROR << 16;
-				mesh_done(ms);
-			}
-
+			handle_exception(ms);
 		} else if (intr & INT_CMDDONE) {
 			out_8(&mr->interrupt, INT_CMDDONE);
 			cmd_complete(ms);
@@ -1081,26 +1477,29 @@
 static void
 handle_msgin(struct mesh_state *ms)
 {
-	int i;
+	int i, code;
 	Scsi_Cmnd *cmd = ms->current_req;
 	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];
 
 	if (ms->n_msgin == 0)
 		return;
-	if (DEBUG_TARGET(cmd)) {
+	code = ms->msgin[0];
+	if (ALLOW_DEBUG(ms->conn_tgt)) {
 		printk(KERN_DEBUG "got %d message bytes:", ms->n_msgin);
 		for (i = 0; i < ms->n_msgin; ++i)
 			printk(" %x", ms->msgin[i]);
 		printk("\n");
 	}
+	dlog(ms, "msgin msg=%.8x",
+	     MKWORD(ms->n_msgin, code, ms->msgin[1], ms->msgin[2]));
 
 	ms->expect_reply = 0;
 	ms->n_msgout = 0;
 	if (ms->n_msgin < msgin_length(ms))
 		goto reject;
 	if (cmd)
-		cmd->SCp.Message = ms->msgin[0];
-	switch (ms->msgin[0]) {
+		cmd->SCp.Message = code;
+	switch (code) {
 	case COMMAND_COMPLETE:
 		break;
 	case EXTENDED_MESSAGE:
@@ -1136,8 +1535,6 @@
 		ms->data_ptr = tp->saved_ptr;
 		break;
 	case DISCONNECT:
-		tp->phase = ms->phase;
-		tp->data_goes_out = ms->data_goes_out;
 		ms->phase = disconnecting;
 		break;
 	case ABORT:
@@ -1149,14 +1546,16 @@
 	case NOP:
 		break;
 	default:
-		if (cmd && IDENTIFY_BASE <= ms->msgin[0]
-		    && ms->msgin[0] <= IDENTIFY_BASE + 7) {
-			i = ms->msgin[0] - IDENTIFY_BASE;
-			if (i != cmd->lun)
+		if (IDENTIFY_BASE <= code && code <= IDENTIFY_BASE + 7) {
+			if (cmd == NULL) {
+				do_abort(ms);
+				ms->msgphase = msg_out;
+			} else if (code != cmd->lun + IDENTIFY_BASE) {
 				printk(KERN_WARNING "mesh: lun mismatch "
 				       "(%d != %d) on reselection from "
 				       "target %d\n", i, cmd->lun,
 				       ms->conn_tgt);
+			}
 			break;
 		}
 		goto reject;
@@ -1164,35 +1563,45 @@
 	return;
 
  reject:
-	printk(KERN_WARNING "mesh: rejecting message %x from target %d\n",
-	       ms->msgin[0], ms->conn_tgt);
+	printk(KERN_WARNING "mesh: rejecting message from target %d:",
+	       ms->conn_tgt);
+	for (i = 0; i < ms->n_msgin; ++i)
+		printk(" %x", ms->msgin[i]);
+	printk("\n");
 	ms->msgout[0] = MESSAGE_REJECT;
 	ms->n_msgout = 1;
 	ms->msgphase = msg_out;
 }
 
 static void
-mesh_done(struct mesh_state *ms)
+mesh_done(struct mesh_state *ms, int start_next)
 {
 	Scsi_Cmnd *cmd;
 	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];
 
 	cmd = ms->current_req;
-	if (DEBUG_TARGET(cmd)) {
-		printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n",
-		       cmd->result, ms->data_ptr, cmd->request_bufflen);
-		if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3)
-		    && cmd->request_buffer != 0) {
-			unsigned char *b = cmd->request_buffer;
-			printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n",
-			       b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+	ms->current_req = 0;
+	tp->current_req = 0;
+	if (cmd) {
+		cmd->result = (ms->stat << 16) + cmd->SCp.Status;
+		if (ms->stat == DID_OK)
+			cmd->result += (cmd->SCp.Message << 8);
+		if (DEBUG_TARGET(cmd)) {
+			printk(KERN_DEBUG "mesh_done: result = %x, data_ptr=%d, buflen=%d\n",
+			       cmd->result, ms->data_ptr, cmd->request_bufflen);
+			if ((cmd->cmnd[0] == 0 || cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 3)
+			    && cmd->request_buffer != 0) {
+				unsigned char *b = cmd->request_buffer;
+				printk(KERN_DEBUG "buffer = %x %x %x %x %x %x %x %x\n",
+				       b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+			}
 		}
+		cmd->SCp.this_residual -= ms->data_ptr;
+		mesh_completed(ms, cmd);
 	}
-	tp->current_req = 0;
-	cmd->SCp.this_residual -= ms->data_ptr;
-	ms->current_req = NULL;
-	mesh_completed(ms, cmd);
-	if (ms->phase != reselecting) {
+	if (start_next) {
+		out_8(&ms->mesh->sequence, SEQ_ENBRESEL);
+		udelay(1);
 		ms->phase = idle;
 		mesh_start(ms);
 	}
@@ -1221,51 +1630,49 @@
 	struct scatterlist *scl;
 	struct dbdma_cmd *dcmds;
 
-	dma_cmd = ms->data_goes_out? OUTPUT_MORE: INPUT_MORE;
+	dma_cmd = ms->tgts[ms->conn_tgt].data_goes_out?
+		OUTPUT_MORE: INPUT_MORE;
 	dcmds = ms->dma_cmds;
 	dtot = 0;
-	cmd->SCp.this_residual = cmd->request_bufflen;
-	if (cmd->use_sg > 0) {
-		total = 0;
-		scl = (struct scatterlist *) cmd->buffer;
-		off = ms->data_ptr;
-		for (i = 0; i < cmd->use_sg; ++i, ++scl) {
-			total += scl->length;
-			if (off >= scl->length) {
-				off -= scl->length;
-				continue;
+	if (cmd) {
+		cmd->SCp.this_residual = cmd->request_bufflen;
+		if (cmd->use_sg > 0) {
+			total = 0;
+			scl = (struct scatterlist *) cmd->buffer;
+			off = ms->data_ptr;
+			for (i = 0; i < cmd->use_sg; ++i, ++scl) {
+				total += scl->length;
+				if (off >= scl->length) {
+					off -= scl->length;
+					continue;
+				}
+				if (scl->length > 0xffff)
+					panic("mesh: scatterlist element >= 64k");
+				st_le16(&dcmds->req_count, scl->length - off);
+				st_le16(&dcmds->command, dma_cmd);
+				st_le32(&dcmds->phy_addr,
+					virt_to_phys(scl->address) + off);
+				dcmds->xfer_status = 0;
+				++dcmds;
+				dtot += scl->length - off;
+				off = 0;
 			}
-			if (scl->length > 0xffff)
-				panic("mesh: scatterlist element >= 64k");
-			st_le16(&dcmds->req_count, scl->length - off);
-			st_le16(&dcmds->command, dma_cmd);
+		} else if (ms->data_ptr < cmd->request_bufflen) {
+			dtot = cmd->request_bufflen - ms->data_ptr;
+			if (dtot > 0xffff)
+				panic("mesh: transfer size >= 64k");
+			st_le16(&dcmds->req_count, dtot);
 			st_le32(&dcmds->phy_addr,
-				virt_to_phys(scl->address) + off);
+				virt_to_phys(cmd->request_buffer) + ms->data_ptr);
 			dcmds->xfer_status = 0;
 			++dcmds;
-			dtot += scl->length - off;
-			off = 0;
 		}
-	} else if (ms->data_ptr < cmd->request_bufflen) {
-		dtot = cmd->request_bufflen - ms->data_ptr;
-		if (dtot > 0xffff)
-			panic("mesh: transfer size >= 64k");
-		st_le16(&dcmds->req_count, dtot);
-		st_le32(&dcmds->phy_addr,
-			virt_to_phys(cmd->request_buffer) + ms->data_ptr);
-		dcmds->xfer_status = 0;
-		++dcmds;
 	}
 	if (dtot == 0) {
 		/* Either the target has overrun our buffer,
 		   or the caller didn't provide a buffer. */
 		static char mesh_extra_buf[64];
 
-		if (cmd->request_bufflen != 0)
-			printk(KERN_DEBUG "mesh: target %d overrun, "
-			       "data_ptr=%x total=%x goes_out=%d\n",
-			       ms->conn_tgt, ms->data_ptr,
-			       cmd->request_bufflen, ms->data_goes_out);
 		dtot = sizeof(mesh_extra_buf);
 		st_le16(&dcmds->req_count, dtot);
 		st_le32(&dcmds->phy_addr, virt_to_phys(mesh_extra_buf));
@@ -1284,9 +1691,10 @@
 {
 	volatile struct dbdma_regs *md = ms->dma;
 	volatile struct mesh_regs *mr = ms->mesh;
+	Scsi_Cmnd *cmd = ms->current_req;
 	int t, nb;
 
-	if (!ms->data_goes_out) {
+	if (!ms->tgts[ms->conn_tgt].data_goes_out) {
 		/* wait a little while until the fifo drains */
 		t = 50;
 		while (t > 0 && mr->fifo_count != 0
@@ -1297,15 +1705,28 @@
 	}
 	out_le32(&md->control, RUN << 16);	/* turn off RUN bit */
 	nb = (mr->count_hi << 8) + mr->count_lo;
-	if (ms->data_goes_out)
+	dlog(ms, "halt_dma fc/count=%.6x",
+	     MKWORD(0, mr->fifo_count, 0, nb));
+	if (ms->tgts[ms->conn_tgt].data_goes_out)
 		nb += mr->fifo_count;
 	/* nb is the number of bytes not yet transferred
 	   to/from the target. */
 	ms->data_ptr -= nb;
+	dlog(ms, "data_ptr %x", ms->data_ptr);
 	if (ms->data_ptr < 0) {
 		printk(KERN_ERR "mesh: halt_dma: data_ptr=%d (nb=%d, ms=%p)\n",
 		       ms->data_ptr, nb, ms);
 		ms->data_ptr = 0;
+#ifdef MESH_DBG
+		dumplog(ms, ms->conn_tgt);
+		dumpslog(ms);
+#endif /* MESH_DBG */
+	} else if (cmd && cmd->request_bufflen != 0 &&
+		   ms->data_ptr > cmd->request_bufflen) {
+		printk(KERN_DEBUG "mesh: target %d overrun, "
+		       "data_ptr=%x total=%x goes_out=%d\n",
+		       ms->conn_tgt, ms->data_ptr, cmd->request_bufflen,
+		       ms->tgts[ms->conn_tgt].data_goes_out);
 	}
 	ms->dma_started = 0;
 }
@@ -1319,13 +1740,129 @@
 data_goes_out(Scsi_Cmnd *cmd)
 {
 	switch (cmd->cmnd[0]) {
+	case CHANGE_DEFINITION: 
+	case COMPARE:	  
+	case COPY:
+	case COPY_VERIFY:	    
+	case FORMAT_UNIT:	 
+	case LOG_SELECT:
+	case MEDIUM_SCAN:	  
 	case MODE_SELECT:
 	case MODE_SELECT_10:
-	case WRITE_6:
-	case WRITE_10:
-	case WRITE_12:		/* any others? */
+	case REASSIGN_BLOCKS: 
+	case RESERVE:
+	case SEARCH_EQUAL:	  
+	case SEARCH_EQUAL_12: 
+	case SEARCH_HIGH:	 
+	case SEARCH_HIGH_12:  
+	case SEARCH_LOW:
+	case SEARCH_LOW_12:
+	case SEND_DIAGNOSTIC: 
+	case SEND_VOLUME_TAG:	     
+	case SET_WINDOW: 
+	case UPDATE_BLOCK:	
+	case WRITE_BUFFER:
+ 	case WRITE_6:	
+	case WRITE_10:	
+	case WRITE_12:	  
+	case WRITE_LONG:	
+	case WRITE_LONG_2:      /* alternate code for WRITE_LONG */
+	case WRITE_SAME:	
+	case WRITE_VERIFY:
+	case WRITE_VERIFY_12:
 		return 1;
 	default:
 		return 0;
 	}
 }
+
+#ifdef MESH_DBG
+static inline u32 readtb(void)
+{
+	u32 tb;
+
+#ifdef DBG_USE_TB
+	/* Beware: if you enable this, it will crash on 601s. */
+	asm ("mftb %0" : "=r" (tb) : );
+#else
+	tb = 0;
+#endif
+	return tb;
+}
+
+static void dlog(struct mesh_state *ms, char *fmt, int a)
+{
+	struct mesh_target *tp = &ms->tgts[ms->conn_tgt];
+	struct dbglog *tlp, *slp;
+
+	tlp = &tp->log[tp->log_ix];
+	slp = &ms->log[ms->log_ix];
+	tlp->fmt = fmt;
+	tlp->tb = readtb();
+	tlp->phase = (ms->msgphase << 4) + ms->phase;
+	tlp->bs0 = ms->mesh->bus_status0;
+	tlp->bs1 = ms->mesh->bus_status1;
+	tlp->tgt = ms->conn_tgt;
+	tlp->d = a;
+	*slp = *tlp;
+	if (++tp->log_ix >= N_DBG_LOG)
+		tp->log_ix = 0;
+	if (tp->n_log < N_DBG_LOG)
+		++tp->n_log;
+	if (++ms->log_ix >= N_DBG_SLOG)
+		ms->log_ix = 0;
+	if (ms->n_log < N_DBG_SLOG)
+		++ms->n_log;
+}
+
+static void dumplog(struct mesh_state *ms, int t)
+{
+	struct mesh_target *tp = &ms->tgts[t];
+	struct dbglog *lp;
+	int i;
+
+	if (tp->n_log == 0)
+		return;
+	i = tp->log_ix - tp->n_log;
+	if (i < 0)
+		i += N_DBG_LOG;
+	tp->n_log = 0;
+	do {
+		lp = &tp->log[i];
+		printk(KERN_DEBUG "mesh log %d: bs=%.2x%.2x ph=%.2x ",
+		       t, lp->bs1, lp->bs0, lp->phase);
+#ifdef DBG_USE_TB
+		printk("tb=%10u ", lp->tb);
+#endif
+		printk(lp->fmt, lp->d);
+		printk("\n");
+		if (++i >= N_DBG_LOG)
+			i = 0;
+	} while (i != tp->log_ix);
+}
+
+static void dumpslog(struct mesh_state *ms)
+{
+	struct dbglog *lp;
+	int i;
+
+	if (ms->n_log == 0)
+		return;
+	i = ms->log_ix - ms->n_log;
+	if (i < 0)
+		i += N_DBG_SLOG;
+	ms->n_log = 0;
+	do {
+		lp = &ms->log[i];
+		printk(KERN_DEBUG "mesh log: bs=%.2x%.2x ph=%.2x t%d ",
+		       lp->bs1, lp->bs0, lp->phase, lp->tgt);
+#ifdef DBG_USE_TB
+		printk("tb=%10u ", lp->tb);
+#endif
+		printk(lp->fmt, lp->d);
+		printk("\n");
+		if (++i >= N_DBG_SLOG)
+			i = 0;
+	} while (i != ms->log_ix);
+}
+#endif /* MESH_DBG */
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.100/linux/drivers/scsi/ncr53c8xx.c	Tue Apr 14 14:29:22 1998
+++ linux/drivers/scsi/ncr53c8xx.c	Fri May  8 00:22:12 1998
@@ -4638,12 +4638,27 @@
 	**	Then enable disconnects.
 	*/
 	save_flags(flags); cli();
-	if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) {
-		printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, TERMINATION, DEVICE POWER etc.!\n", ncr_name(np));
-		restore_flags(flags);
-		goto attach_error;
-	}
-	ncr_exception (np);
+	do {
+		if (ncr_reset_scsi_bus(np, 1, driver_setup.settle_delay) != 0) {
+			printf("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, "
+			       "TERMINATION, DEVICE POWER etc.!\n",
+			       ncr_name(np));
+			restore_flags(flags);
+			goto attach_error;
+		}
+
+		/*
+		** On Ultra/AXi, the NCR53C876 sometimes does not get the
+		** RST bit set in SIST the first time, so retry resetting
+		** the SCSI bus until the chip is properly initialized.
+		*/
+		np->disc = 1;
+		ncr_exception (np);
+		if (np->disc) {
+			printk("%s: Chip not responding to CRST, retrying\n",
+			       ncr_name(np));
+		}
+	} while (np->disc);
 	restore_flags(flags);
 
 	np->disc = 1;
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.1.100/linux/drivers/scsi/qlogicisp.c	Tue Apr 14 14:29:23 1998
+++ linux/drivers/scsi/qlogicisp.c	Fri May  8 00:22:12 1998
@@ -55,6 +55,8 @@
 
 #define DEFAULT_LOOP_COUNT	1000000
 
+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+
 /* End Configuration section *************************************************/
 
 #include <linux/module.h>
@@ -1160,7 +1162,7 @@
 
 static int isp1020_init(struct Scsi_Host *sh)
 {
-	u_int io_base;
+	u_long io_base;
 	struct isp1020_hostdata *hostdata;
 	u_char revision;
 	u_int irq;
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.1.100/linux/drivers/scsi/qlogicpti.c	Thu Apr 23 20:21:35 1998
+++ linux/drivers/scsi/qlogicpti.c	Fri May  8 00:22:12 1998
@@ -563,7 +563,6 @@
 	}
 }
 
-static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
 static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
 
 /* Detect all PTI Qlogic ISP's in the machine. */
@@ -1051,18 +1050,10 @@
 	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
 }
 
-static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-	qlogicpti_intr_handler(irq, dev_id, regs);
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
 #ifndef __sparc_v9__
 
-static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id,
+					      struct pt_regs *regs)
 {
 	static int running = 0;
 	Scsi_Cmnd *Cmnd;
@@ -1150,7 +1141,8 @@
 
 #else /* __sparc_v9__ */
 
-static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id,
+					      struct pt_regs *regs)
 {
 	struct qlogicpti *qpti = dev_id;
 	Scsi_Cmnd *Cmnd;
@@ -1217,6 +1209,15 @@
 }
 
 #endif
+
+static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	qlogicpti_intr_handler(irq, dev_id, regs);
+	spin_unlock_irqrestore(&io_request_lock, flags);
+}
 
 int qlogicpti_abort(Scsi_Cmnd *Cmnd)
 {
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/sgiwd93.c linux/drivers/scsi/sgiwd93.c
--- v2.1.100/linux/drivers/scsi/sgiwd93.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sgiwd93.c	Fri May  8 00:22:12 1998
@@ -0,0 +1,273 @@
+/*
+ * sgiwd93.c: SGI WD93 scsi driver.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * (In all truth, Jed Schimmel wrote all this code.)
+ *
+ * $Id: sgiwd93.c,v 1.1 1998/05/01 01:35:42 ralf Exp $
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/version.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/sgi.h>
+#include <asm/sgialib.h>
+#include <asm/sgimc.h>
+#include <asm/sgihpc.h>
+#include <asm/sgint23.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "wd33c93.h"
+#include "sgiwd93.h"
+
+#include <linux/stat.h>
+
+struct hpc_chunk {
+	struct hpc_dma_desc desc;
+	unsigned long padding;
+};
+
+struct proc_dir_entry proc_scsi_sgiwd93 = {
+	PROC_SCSI_SGIWD93, 5, "SGIWD93",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+struct Scsi_Host *sgiwd93_host = NULL;
+
+/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
+static inline void write_wd33c93_count(wd33c93_regs *regp, unsigned long value)
+{
+	regp->SASR = WD_TRANSFER_COUNT_MSB;
+	regp->SCMD = ((value >> 16) & 0xff);
+	regp->SCMD = ((value >>  8) & 0xff);
+	regp->SCMD = ((value >>  0) & 0xff);
+}
+
+static inline unsigned long read_wd33c93_count(wd33c93_regs *regp)
+{
+	unsigned long value;
+
+	regp->SASR = WD_TRANSFER_COUNT_MSB;
+	value =  ((regp->SCMD & 0xff) << 16);
+	value |= ((regp->SCMD & 0xff) <<  8);
+	value |= ((regp->SCMD & 0xff) <<  0);
+	return value;
+}
+
+/* XXX woof! */
+static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	wd33c93_intr(sgiwd93_host);
+}
+
+#undef DEBUG_DMA
+
+static int dma_setup(Scsi_Cmnd *cmd, int datainp)
+{
+	struct WD33C93_hostdata *hdata = CMDHOSTDATA(cmd);
+	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;
+
+#ifdef DEBUG_DMA
+	printk("dma_setup: datainp<%d> hcp<%p> ",
+	       datainp, hcp);
+#endif
+
+	hdata->dma_dir = datainp;
+
+	if(cmd->use_sg) {
+		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++) {
+#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);
+			totlen += slp[i].length;
+		}
+#ifdef DEBUG_DMA
+		printk(">tlen<%d>", totlen);
+#endif
+		hdata->dma_bounce_len = totlen; /* a trick... */
+		write_wd33c93_count(regp, totlen);
+	} else {
+		/* Non-scattered dma. */
+#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++;
+		write_wd33c93_count(regp, cmd->SCp.this_residual);
+	}
+
+	/* To make sure, if we trip an HPC bug, that we transfer
+	 * every single byte, we tag on an extra zero length dma
+	 * descriptor at the end of the chain.
+	 */
+	hcp->desc.pbuf = 0;
+	hcp->desc.cntinfo = (HPCDMA_EOX);
+
+#ifdef DEBUG_DMA
+	printk(" HPCGO\n");
+#endif
+
+	/* Start up the HPC. */
+	hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer);
+	if(datainp)
+		hregs->ctrl = (HPC3_SCTRL_ACTIVE);
+	else
+		hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR);
+	return 0;
+}
+
+static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
+		     int status)
+{
+	struct WD33C93_hostdata *hdata = INSTHOSTDATA(instance);
+	wd33c93_regs *regp = hdata->regp;
+	struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) SCpnt->host->base;
+
+#ifdef DEBUG_DMA
+	printk("dma_stop: status<%d> ", status);
+#endif
+
+	/* First stop the HPC and flush it's FIFO. */
+	if(hdata->dma_dir) {
+		hregs->ctrl |= HPC3_SCTRL_FLUSH;
+		while(hregs->ctrl & HPC3_SCTRL_ACTIVE)
+			barrier();
+	}
+	hregs->ctrl = 0;
+
+	/* See how far we got and update scatterlist state if necessary. */
+	if(SCpnt->use_sg) {
+		struct scatterlist *slp = SCpnt->SCp.buffer;
+		int totlen, wd93_residual, transferred, i;
+
+		/* Yep, we were doing the scatterlist thang. */
+		totlen = hdata->dma_bounce_len;
+		wd93_residual = read_wd33c93_count(regp);
+		transferred = totlen - wd93_residual;
+
+#ifdef DEBUG_DMA
+		printk("tlen<%d>resid<%d>transf<%d> ",
+		       totlen, wd93_residual, transferred);
+#endif
+
+		/* Avoid long winded partial-transfer search for common case. */
+		if(transferred != totlen) {
+			/* This is the nut case. */
+#ifdef DEBUG_DMA
+			printk("Jed was here...");
+#endif
+			for(i = 0; i <= (SCpnt->use_sg - 1); i++) {
+				if(slp[i].length >= transferred)
+					break;
+				transferred -= slp[i].length;
+			}
+		} else {
+			/* This is the common case. */
+#ifdef DEBUG_DMA
+			printk("did it all...");
+#endif
+			i = (SCpnt->use_sg - 1);
+		}
+		SCpnt->SCp.buffer = &slp[i];
+		SCpnt->SCp.buffers_residual = (SCpnt->use_sg - 1 - i);
+		SCpnt->SCp.ptr = (char *) slp[i].address;
+		SCpnt->SCp.this_residual = slp[i].length;
+	}
+#ifdef DEBUG_DMA
+	printk("\n");
+#endif
+}
+
+static inline void init_hpc_chain(uchar *buf)
+{
+	struct hpc_chunk *hcp = (struct hpc_chunk *) buf;
+	unsigned long start, end;
+
+	start = (unsigned long) buf;
+	end = start + PAGE_SIZE;
+	while(start < end) {
+		hcp->desc.pnext = PHYSADDR((hcp + 1));
+		hcp->desc.cntinfo = HPCDMA_EOX;
+		hcp++;
+		start += sizeof(struct hpc_chunk);
+	};
+	hcp--;
+	hcp->desc.pnext = PHYSADDR(buf);
+}
+
+__initfunc(int sgiwd93_detect(Scsi_Host_Template *HPsUX))
+{
+	static unsigned char called = 0;
+	struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0;
+	struct WD33C93_hostdata *hdata;
+	uchar *buf;
+
+	if(called)
+		return 0; /* Should bitch on the console about this... */
+
+	HPsUX->proc_dir = &proc_scsi_sgiwd93;
+
+	sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata));
+	sgiwd93_host->base = (unsigned char *) hregs;
+
+	buf = (uchar *) get_free_page(GFP_KERNEL);
+	init_hpc_chain(buf);
+	dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
+
+	wd33c93_init(sgiwd93_host, (wd33c93_regs *) 0xbfbc0003,
+		     dma_setup, dma_stop, WD33C93_FS_16_20);
+
+	hdata = INSTHOSTDATA(sgiwd93_host);
+	hdata->no_sync = 0;
+	hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
+	dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
+
+	request_irq(1, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host);
+	called = 1;
+
+	return 1; /* Found one. */
+}
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "sgiwd93.h"
+
+Scsi_Host_Template driver_template = SGIWD93_SCSI;
+
+#include "scsi_module.c"
+
+#endif
+
+int sgiwd93_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+	free_irq(1, sgiwd93_intr);
+	free_page(KSEG0ADDR(hdata->dma_bounce_buffer));
+	wd33c93_release();
+#endif
+	return 1;
+}
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/sgiwd93.h linux/drivers/scsi/sgiwd93.h
--- v2.1.100/linux/drivers/scsi/sgiwd93.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/sgiwd93.h	Fri May  8 00:22:12 1998
@@ -0,0 +1,43 @@
+/* $Id: sgiwd93.h,v 1.2 1998/05/04 09:18:49 ralf Exp $
+ * sgiwd93.h: SGI WD93 scsi definitions.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#ifndef _SGIWD93_H
+#define _SGIWD93_H
+
+#ifndef NULL
+#define NULL        0
+#endif
+
+#ifndef CMD_PER_LUN
+#define CMD_PER_LUN 8
+#endif
+
+#ifndef CAN_QUEUE
+#define CAN_QUEUE   16
+#endif
+
+int sgiwd93_detect(Scsi_Host_Template *);
+int sgiwd93_release(struct Scsi_Host *instance);
+const char *wd33c93_info(void);
+int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int wd33c93_abort(Scsi_Cmnd *);
+int wd33c93_reset(Scsi_Cmnd *, unsigned int);
+
+extern struct proc_dir_entry proc_scsi_sgiwd93;
+
+#define SGIWD93_SCSI {proc_dir:		   &proc_scsi_sgiwd93, \
+		      name:                "SGI WD93", \
+		      detect:              sgiwd93_detect,    \
+		      release:             sgiwd93_release,   \
+		      queuecommand:        wd33c93_queuecommand, \
+		      abort:               wd33c93_abort,   \
+		      reset:               wd33c93_reset,   \
+		      can_queue:           CAN_QUEUE,       \
+		      this_id:             7,               \
+		      sg_tablesize:        SG_ALL,          \
+		      cmd_per_lun:	   CMD_PER_LUN,     \
+		      use_clustering:      DISABLE_CLUSTERING }
+
+#endif /* !(_SGIWD93_H) */
diff -u --recursive --new-file v2.1.100/linux/drivers/sgi/char/cons_newport.c linux/drivers/sgi/char/cons_newport.c
--- v2.1.100/linux/drivers/sgi/char/cons_newport.c	Wed Dec 10 10:31:11 1997
+++ linux/drivers/sgi/char/cons_newport.c	Fri May  8 00:23:41 1998
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: cons_newport.c,v 1.1 1997/12/02 02:28:23 ralf Exp $
+ * $Id: cons_newport.c,v 1.1 1998/01/10 19:05:47 ecd Exp $
  */
 
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.100/linux/drivers/sgi/char/newport.h linux/drivers/sgi/char/newport.h
--- v2.1.100/linux/drivers/sgi/char/newport.h	Wed Dec 10 10:31:11 1997
+++ linux/drivers/sgi/char/newport.h	Fri May  8 00:23:41 1998
@@ -1,4 +1,4 @@
-/* $Id: newport.h,v 1.2 1996/06/10 16:38:34 dm Exp $
+/* $Id: newport.h,v 1.1 1998/01/10 19:05:58 ecd Exp $
  * newport.h: Defines and register layout for NEWPORT graphics
  *            hardware.
  *
diff -u --recursive --new-file v2.1.100/linux/drivers/sgi/char/sgiserial.c linux/drivers/sgi/char/sgiserial.c
--- v2.1.100/linux/drivers/sgi/char/sgiserial.c	Thu May  7 22:51:51 1998
+++ linux/drivers/sgi/char/sgiserial.c	Fri May  8 00:23:41 1998
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
+#include <linux/console.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -52,6 +53,19 @@
 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 */
@@ -960,14 +974,14 @@
 /*
  * zs_console_print is registered for printk.
  */
-static void zs_console_print(const char *p)
+
+static void zs_console_print(struct console *co, const char *str, unsigned int count)
 {
-	char c;
 
-	while((c=*(p++)) != 0) {
-		if(c == '\n')
+	while(count--) {
+		if(*str == '\n')
 			rs_put_char('\r');
-		rs_put_char(c);
+		rs_put_char(*str++);
 	}
 
 	/* Comment this if you want to have a strict interrupt-driven output */
@@ -1712,7 +1726,7 @@
 
 }
 
-extern void register_console(void (*proc)(const char *));
+
 
 static inline void
 rs_cons_check(struct sgi_serial *ss, int channel)
@@ -1723,6 +1737,7 @@
 
 	i = o = io = 0;
 
+
 	/* Is this one of the serial console lines? */
 	if((zs_cons_chanout != channel) &&
 	   (zs_cons_chanin != channel))
@@ -1730,16 +1745,20 @@
 	zs_conschan = ss->zs_channel;
 	zs_consinfo = ss;
 
+
 	/* Register the console output putchar, if necessary */
 	if((zs_cons_chanout == channel)) {
 		o = 1;
 		/* double whee.. */
+
 		if(!consout_registered) {
-			register_console(zs_console_print);
+		  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().
 	 */
@@ -1756,6 +1775,7 @@
 		panic("Console baud rate weirdness");
 	}
 
+
 	/* Set flag variable for this port so that it cannot be
 	 * opened for other uses by accident.
 	 */
@@ -1766,9 +1786,11 @@
 			printk("zs%d: console I/O\n", ((channel>>1)&1));
 			msg_printed = 1;
 		}
+
 	} else {
 		printk("zs%d: console %s\n", ((channel>>1)&1),
 		       (i==1 ? "input" : (o==1 ? "output" : "WEIRD")));
+
 	}
 }
 
@@ -1780,6 +1802,7 @@
 	int chip, channel, i, flags;
 	struct sgi_serial *info;
 
+
 	/* Setup base handler, and timer table. */
 	init_bh(SERIAL_BH, do_serial_bh);
 	timer_table[RS_TIMER].fn = rs_timer;
@@ -1966,6 +1989,7 @@
 {
 	int channel;
 
+	
 	if(chip)
 		panic("rs_cons_hook called with chip not zero");
 	if(line != 1 && line != 2)
@@ -1981,10 +2005,11 @@
 	zs_soft[channel].change_needed = 0;
 	zs_soft[channel].clk_divisor = 16;
 	zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
-	if(out)
+	if(out) 
 		zs_cons_chanout = ((chip * 2) + channel);
-	else
+	else 
 		zs_cons_chanin = ((chip * 2) + channel);
+	
 	rs_cons_check(&zs_soft[channel], channel);
 }
 
diff -u --recursive --new-file v2.1.100/linux/fs/Makefile linux/fs/Makefile
--- v2.1.100/linux/fs/Makefile	Mon Apr  6 17:41:00 1998
+++ linux/fs/Makefile	Fri May  8 17:54:39 1998
@@ -13,21 +13,17 @@
 O_OBJS    = open.o read_write.o devices.o file_table.o buffer.o \
 		super.o  block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
 		ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
-		inode.o dcache.o attr.o bad_inode.o $(BINFMTS) 
+		dcache.o inode.o attr.o bad_inode.o $(BINFMTS) 
 
 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
+		nls devpts adfs
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
 else
 O_OBJS += noquot.o
-endif
-
-ifeq ($(CONFIG_TRANS_NAMES),y)
-O_OBJS += nametrans.o
 endif
 
 ifeq ($(CONFIG_CODA_FS),y)
diff -u --recursive --new-file v2.1.100/linux/fs/affs/Changes linux/fs/affs/Changes
--- v2.1.100/linux/fs/affs/Changes	Tue Mar 10 10:03:33 1998
+++ linux/fs/affs/Changes	Thu May  7 22:58:04 1998
@@ -28,6 +28,26 @@
 
 Please direct bug reports to: hjw@zvw.de
 
+Version 3.9
+-----------
+
+- Moved cleanup from release_file() to put_inode().
+  This makes the the first one obsolete.
+
+- truncate() zeroes the unused remainder of a
+  partially used last block when a file is truncated.
+  It also marks the inode dirty now (which is not
+  really neccessary as notify_change() will do
+  it anyway).
+
+- Added a few comments, fixed some typos (and
+  introduced some new ones), made the debug messages
+  more consistent. Changed a bad example in the
+  doc file (affs.txt).
+
+- Sets the NOEXEC flag in read_super() for old file
+  systems, since you can't run programs on them.
+
 Version 3.8
 -----------
 Bill Hawes kindly reviewed the affs and sent me the
diff -u --recursive --new-file v2.1.100/linux/fs/affs/amigaffs.c linux/fs/affs/amigaffs.c
--- v2.1.100/linux/fs/affs/amigaffs.c	Tue Dec  2 22:25:07 1997
+++ linux/fs/affs/amigaffs.c	Thu May  7 22:58:04 1998
@@ -24,7 +24,6 @@
 
 /*
  * Functions for accessing Amiga-FFS structures.
- *
  */
 
 /* Set *NAME to point to the file name in a file header block in memory
@@ -85,7 +84,7 @@
 
 	return 0;
 }
-/* Remove a header block from it's hash table (directory).
+/* Remove a header block from its hash table (directory).
  * 'inode' may be any inode on the partition, it's only
  * used for calculating the block size and superblock
  * reference.
@@ -226,7 +225,7 @@
 
 	orig_ino = be32_to_cpu(FILE_END(bh->b_data,inode)->original);
 	if (orig_ino) {		/* This is just a link. Nothing much to do. */
-		pr_debug("      Removing link.\n");
+		pr_debug("AFFS: Removing link.\n");
 		if ((error = affs_remove_link(bh,inode)))
 			return error;
 		if ((error = affs_remove_hash(bh,inode)))
@@ -237,7 +236,7 @@
 	
 	link_ino = be32_to_cpu(FILE_END(bh->b_data,inode)->link_chain);
 	if (link_ino) {		/* This is the complicated case. Yuck. */
-		pr_debug("      Removing original with links to it.\n");
+		pr_debug("AFFS: Removing original with links to it.\n");
 		/* Unlink the object and its first link from their directories. */
 		if ((error = affs_remove_hash(bh,inode)))
 			return error;
@@ -275,7 +274,7 @@
 		return 1;
 	}
 	/* Plain file/dir. This is the simplest case. */
-	pr_debug("      Removing plain file/dir.\n");
+	pr_debug("AFFS: Removing plain file/dir.\n");
 	if ((error = affs_remove_hash(bh,inode)))
 		return error;
 	return 0;
@@ -307,6 +306,11 @@
 		sum += be32_to_cpu(*p++);
 	return sum;
 }
+
+/*
+ * Calculate the checksum of a disk block and store it
+ * at the indicated position.
+ */
 
 void
 affs_fix_checksum(int bsize, void *data, int cspos)
diff -u --recursive --new-file v2.1.100/linux/fs/affs/bitmap.c linux/fs/affs/bitmap.c
--- v2.1.100/linux/fs/affs/bitmap.c	Tue Mar 10 10:03:33 1998
+++ linux/fs/affs/bitmap.c	Thu May  7 22:58:04 1998
@@ -103,6 +103,15 @@
 	unlock_super(sb);
 }
 
+/*
+ * Allocate a block in the given allocation zone.
+ * Since we have to byte-swap the bitmap on little-endian
+ * machines, this is rather expensive. Therefor we will
+ * preallocate up to 16 blocks from the same word, if
+ * possible. We are not doing preallocations in the
+ * header zone, though.
+ */
+
 static s32
 affs_balloc(struct inode *inode, int zone_no)
 {
@@ -174,6 +183,8 @@
 	return block;
 }
 
+/* Find a new allocation zone, starting at zone_no. */
+
 static int
 affs_find_new_zone(struct super_block *sb, int zone_no)
 {
@@ -257,12 +268,14 @@
 	zone->z_end   = zone->z_start + az->az_size;
 	zone->z_az_no = i;
 	zone->z_lru_time = jiffies;
-	pr_debug("  ++ found zone (%d) in bm %d at lw offset %d with %d free blocks\n",
+	pr_debug("AFFS: found zone (%d) in bm %d at lw offset %d with %d free blocks\n",
 		 i,(i >> (sb->s_blocksize_bits - 7)),zone->z_start,az->az_free);
 	unlock_super(sb);
 	return az->az_free;
 }
 
+/* Allocate a new header block. */
+
 s32
 affs_new_header(struct inode *inode)
 {
@@ -292,6 +305,8 @@
 	return block;
 }
 
+/* Allocate a new data block. */
+
 s32
 affs_new_data(struct inode *inode)
 {
@@ -378,9 +393,7 @@
 	pr_debug("AFFS: make_zones(): num_zones=%d\n",sb->u.affs_sb.s_num_az);
 
 	mid = (sb->u.affs_sb.s_num_az + 1) / 2;
-	sb->u.affs_sb.s_zones[0].z_az_no = mid;
-	affs_find_new_zone(sb,0);
-	for (i = 1; i < MAX_ZONES; i++) {
+	for (i = 0; i < MAX_ZONES; i++) {
 		sb->u.affs_sb.s_zones[i].z_az_no = mid;
 		affs_find_new_zone(sb,i);
 	}
diff -u --recursive --new-file v2.1.100/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.1.100/linux/fs/affs/file.c	Tue Mar 10 10:03:33 1998
+++ linux/fs/affs/file.c	Thu May  7 22:58:04 1998
@@ -41,7 +41,6 @@
 static ssize_t affs_file_read_ofs(struct file *filp, char *buf, size_t count, loff_t *ppos);
 static ssize_t affs_file_write(struct file *filp, const char *buf, size_t count, loff_t *ppos);
 static ssize_t affs_file_write_ofs(struct file *filp, const char *buf, size_t cnt, loff_t *ppos);
-static int affs_release_file(struct inode *inode, struct file *filp);
 static int alloc_ext_cache(struct inode *inode);
 
 static struct file_operations affs_file_operations = {
@@ -53,7 +52,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open */
-	affs_release_file,	/* release */
+	NULL,			/* release */
 	file_fsync,		/* brute force, but works */
 	NULL,			/* fasync */
 	NULL,			/* check_media_change */
@@ -93,7 +92,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open */
-	affs_release_file,	/* release */
+	NULL,			/* release */
 	file_fsync,		/* brute force, but works */
 	NULL,			/* fasync */
 	NULL,			/* check_media_change */
@@ -184,7 +183,7 @@
 }
 
 /* Now the other way round: Calculate the sequence
- * number of a extension block of a key at the
+ * number of an extension block of a key at the
  * given index in the cache.
  */
 
@@ -545,7 +544,7 @@
 	}
 	blocksize = AFFS_I2BSIZE(inode) - 24;
 	if (!(S_ISREG(inode->i_mode))) {
-		pr_debug("affs_file_read: mode = %07o",inode->i_mode);
+		pr_debug("AFFS: file_read: mode = %07o",inode->i_mode);
 		return -EINVAL;
 	}
 	if (*ppos >= inode->i_size || count <= 0)
@@ -680,11 +679,8 @@
 			   inode->i_mode);
 		return -EINVAL;
 	}
-	if (!inode->u.affs_i.i_ec) {
-		if (alloc_ext_cache(inode)) {
-			return -ENOMEM;
-		}
-	}
+	if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode))
+		return -ENOMEM;
 	if (filp->f_flags & O_APPEND)
 		pos = inode->i_size;
 	else
@@ -740,11 +736,13 @@
 	return written;
 }
 
-/* Free any preallocated blocks */
+/* Free any preallocated blocks. */
+
 void
 affs_free_prealloc(struct inode *inode)
 {
-	struct super_block *sb = inode->i_sb;
+	struct super_block	*sb = inode->i_sb;
+	struct affs_zone	*zone;
 	int block;
 
 	pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);
@@ -755,123 +753,141 @@
 		inode->u.affs_i.i_pa_cnt--;
 		affs_free_block(sb, block);
 	}
+	if (inode->u.affs_i.i_zone) {
+		zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
+		if (zone->z_ino == inode->i_ino)
+			zone->z_ino = 0;
+	}
 }
 
+/* Truncate (or enlarge) a file to the requested size. */
+
 void
 affs_truncate(struct inode *inode)
 {
-	struct buffer_head	*bh;
-	struct buffer_head	*ebh;
-	struct affs_zone	*zone;
-	int	 first;
+	struct buffer_head	*bh = NULL;
+	int	 first;			/* First block to be thrown away	*/
 	int	 block;
 	s32	 key;
 	s32	*keyp;
 	s32	 ekey;
 	s32	 ptype, stype;
 	int	 freethis;
-	int	 blocksize;
+	int	 net_blocksize;
+	int	 blocksize = AFFS_I2BSIZE(inode);
 	int	 rem;
 	int	 ext;
 
 	pr_debug("AFFS: truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
 
-	blocksize = AFFS_I2BSIZE(inode) - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);
-	first = (inode->i_size + blocksize - 1) / blocksize;
+	net_blocksize = blocksize - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);
+	first = (inode->i_size + net_blocksize - 1) / net_blocksize;
 	if (inode->u.affs_i.i_lastblock < first - 1) {
-		if (!inode->u.affs_i.i_ec) {
-			if (alloc_ext_cache(inode)) {
-				/* Fine! No way to indicate an error. What can we do? */
-				return;
-			}
+		/* There has to be at least one new block to be allocated */
+		if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) {
+			/* XXX Fine! No way to indicate an error. */
+			return /* -ENOSPC */;
 		}
 		bh = affs_getblock(inode,first - 1);
-
-		affs_free_prealloc(inode);
-		if (inode->u.affs_i.i_zone) {
-			lock_super(inode->i_sb);
-			zone = &inode->i_sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
-			if (zone->z_ino == inode->i_ino)
-				zone->z_ino = 0;
-			unlock_super(inode->i_sb);
-		}
 		if (!bh) {
 			affs_warning(inode->i_sb,"truncate","Cannot extend file");
-			inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1);
+			inode->i_size = net_blocksize * (inode->u.affs_i.i_lastblock + 1);
 		} else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
-			rem = inode->i_size % blocksize;
-			DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : blocksize);
-			affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
+			rem = inode->i_size % net_blocksize;
+			DATA_FRONT(bh)->data_size = cpu_to_be32(rem ? rem : net_blocksize);
+			affs_fix_checksum(blocksize,bh->b_data,5);
 			mark_buffer_dirty(bh,0);
 		}
-		affs_brelse(bh);
-		return;
+		goto out_truncate;
 	}
-	ekey  = inode->i_ino;
-	ext   = 0;
+	ekey = inode->i_ino;
+	ext  = 0;
 
+	/* Free all blocks starting at 'first' and all then-empty
+	 * extension blocks. Do not free the header block, though.
+	 */
 	while (ekey) {
-		if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) {
+		if (!(bh = affs_bread(inode->i_dev,ekey,blocksize))) {
 			affs_error(inode->i_sb,"truncate","Cannot read block %d",ekey);
-			break;
+			goto out_truncate;
 		}
-		ptype = be32_to_cpu(((struct file_front *)bh->b_data)->primary_type);
-		stype = be32_to_cpu(FILE_END(bh->b_data,inode)->secondary_type);
-		if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
-			affs_error(inode->i_sb,"truncate","Bad block (ptype=%d, stype=%d)",
-			           ptype,stype);
-			affs_brelse(bh);
-			break;
+		if (affs_checksum_block(blocksize,bh->b_data,&ptype,&stype)) {
+			affs_error(inode->i_sb,"truncate","Checksum error in header/ext block %d",
+				   ekey);
+			goto out_truncate;
 		}
-		/* Do not throw away file header */
+		if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
+			affs_error(inode->i_sb,"truncate",
+				   "Bad block (key=%d, ptype=%d, stype=%d)",ekey,ptype,stype);
+			goto out_truncate;
+		}
+		/* Do we have to free this extension block after
+		 * freeing the data blocks pointed to?
+		 */
 		freethis = first == 0 && ekey != inode->i_ino;
+
+		/* Free the data blocks. 'first' is relative to this
+		 * extension block and may well lie behind this block.
+		 */
 		for (block = first; block < AFFS_I2HSIZE(inode); block++) {
 			keyp = &AFFS_BLOCK(bh->b_data,inode,block);
 			key  = be32_to_cpu(*keyp);
 			if (key) {
 				*keyp = 0;
 				affs_free_block(inode->i_sb,key);
-			} else {
-				block = AFFS_I2HSIZE(inode);
+			} else
 				break;
-			}
 		}
-		keyp = &GET_END_PTR(struct file_end,bh->b_data,AFFS_I2BSIZE(inode))->extension;
+		keyp = &GET_END_PTR(struct file_end,bh->b_data,blocksize)->extension;
 		key  = be32_to_cpu(*keyp);
+
+		/* If 'first' is in this block or is the first
+		 * in the next one, this will be the last in
+		 * the list, thus we have to adjust the count
+		 * and zero the pointer to the next ext block.
+		 */
 		if (first <= AFFS_I2HSIZE(inode)) {
-			((struct file_front *)bh->b_data)->block_count = be32_to_cpu(first);
+			((struct file_front *)bh->b_data)->block_count = cpu_to_be32(first);
 			first = 0;
 			*keyp = 0;
-			if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) && first > 0) {
-				block = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,first - 1));
-				if ((ebh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
-					if(!(affs_checksum_block(AFFS_I2BSIZE(inode),ebh->b_data,
-					     &ptype,NULL))) {
-						rem = inode->i_size % blocksize;
-						rem = cpu_to_be32(rem ? blocksize : rem);
-						((struct data_front *)ebh->b_data)->data_size = rem;
-						((struct data_front *)ebh->b_data)->next_data = 0;
-						affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);
-						mark_buffer_dirty(ebh,1);
-					}
-					affs_brelse(ebh);
-				}
-			}
-		} else {
+			affs_fix_checksum(blocksize,bh->b_data,5);
+			mark_buffer_dirty(bh,1);
+		} else
 			first -= AFFS_I2HSIZE(inode);
-		}
-		if (freethis) {		/* Don't bother fixing checksum */
-			affs_brelse(bh);
+		affs_brelse(bh);
+		bh = NULL;
+		if (freethis)			/* Don't bother fixing checksum */
 			affs_free_block(inode->i_sb,ekey);
-		} else {
-			affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
-			mark_buffer_dirty(bh,1);
-			affs_brelse(bh);
-		}
 		ekey = key;
 	}
-	inode->u.affs_i.i_lastblock = ((inode->i_size + blocksize - 1) / blocksize) - 1;
+	block = ((inode->i_size + net_blocksize - 1) / net_blocksize) - 1;
+	inode->u.affs_i.i_lastblock = block;
+
+	/* If the file is not truncated to a block boundary,
+	 * the partial block after the EOF must be zeroed
+	 * so it cannot become accessible again.
+	 */
+
+	rem = inode->i_size % net_blocksize;
+	if (rem) {
+		if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) 
+			rem += 24;
+		pr_debug("AFFS: Zeroing from offset %d in block %d\n",rem,block);
+		bh = affs_getblock(inode,block);
+		if (bh) {
+			memset(bh->b_data + rem,0,blocksize - rem);
+			if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS)) {
+				((struct data_front *)bh->b_data)->data_size = cpu_to_be32(rem);
+				((struct data_front *)bh->b_data)->next_data = 0;
+				affs_fix_checksum(blocksize,bh->b_data,5);
+			}
+			mark_buffer_dirty(bh,1);
+		} else 
+			affs_error(inode->i_sb,"truncate","Cannot read block %d",block);
+	}
 
+out_truncate:
+	affs_brelse(bh);
 	/* Invalidate cache */
 	if (inode->u.affs_i.i_ec) {
 		inode->u.affs_i.i_ec->max_ext = 0;
@@ -880,31 +896,13 @@
 			inode->u.affs_i.i_ec->kc[key].kc_last     = -1;
 		}
 	}
-
-}
-
-static int
-affs_release_file(struct inode *inode, struct file *filp)
-{
-	struct super_block *sb = inode->i_sb;
-	struct affs_zone	*zone;
-
-	pr_debug("AFFS: release_file(ino=%lu)\n",inode->i_ino);
-
-	if (filp->f_mode & 2) {		/* Free preallocated blocks */
-		affs_free_prealloc(inode);
-		if (inode->u.affs_i.i_zone) {
-			zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
-			if (zone->z_ino == inode->i_ino)
-				zone->z_ino = 0;
-		}
-	}
-	return 0;
+	mark_inode_dirty(inode);
 }
 
 /*
  * Called only when we need to allocate the extension cache.
  */
+
 static int
 alloc_ext_cache(struct inode *inode)
 {
@@ -928,9 +926,7 @@
 	/* We only have to initialize non-zero values.
 	 * get_free_page() zeroed the page already.
 	 */
-	key = inode->u.affs_i.i_original;
-	if (!inode->u.affs_i.i_original)
-		key = inode->i_ino;
+	key = inode->i_ino;
 	inode->u.affs_i.i_ec->ec[0] = key;
 	for (i = 0; i < 4; i++) {
 		inode->u.affs_i.i_ec->kc[i].kc_this_key = key;
diff -u --recursive --new-file v2.1.100/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.1.100/linux/fs/affs/inode.c	Tue Mar 10 10:03:33 1998
+++ linux/fs/affs/inode.c	Thu May  7 22:58:04 1998
@@ -255,6 +255,8 @@
 {
 	pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",
 		inode->i_ino,inode->i_nlink);
+
+	affs_free_prealloc(inode);
 	if (inode->i_count == 1) {
 		unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec;
 		if (cache_page) {
@@ -323,6 +325,11 @@
 
 	return inode;
 }
+
+/*
+ * Add an entry to a directory. Create the header block
+ * and insert it into the hash table.
+ */
 
 int
 affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
diff -u --recursive --new-file v2.1.100/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.1.100/linux/fs/affs/namei.c	Thu May  7 22:51:51 1998
+++ linux/fs/affs/namei.c	Thu May  7 22:58:04 1998
@@ -253,6 +253,7 @@
 	
 	inode->i_nlink = retval;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	dir->i_version = ++event;
 	mark_inode_dirty(inode);
 	d_delete(dentry);
 	mark_inode_dirty(dir);
@@ -277,7 +278,7 @@
 	if (!inode)
 		goto out;
 
-	pr_debug(" -- ino=%lu\n",inode->i_ino);
+	pr_debug("AFFS: ino=%lu\n",inode->i_ino);
 	if (dir->i_sb->u.affs_sb.s_flags & SF_OFS)
 		inode->i_op = &affs_file_inode_operations_ofs;
 	else
@@ -390,6 +391,7 @@
 	inode->i_nlink = retval;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	retval         = 0;
+	dir->i_version = ++event;
 	mark_inode_dirty(dir);
 	mark_inode_dirty(inode);
 	d_delete(dentry);
@@ -546,7 +548,7 @@
 	unsigned long		 new_ino;
 	int			 retval;
 
-	pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p) )\n",
+	pr_debug("AFFS: rename(old=%lu,\"%*s\" (inode=%p) to new=%lu,\"%*s\" (inode=%p))\n",
 		 old_dir->i_ino,old_dentry->d_name.len,old_dentry->d_name.name,old_inode,
 		 new_dir->i_ino,new_dentry->d_name.len,new_dentry->d_name.name,new_inode);
 	
diff -u --recursive --new-file v2.1.100/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.1.100/linux/fs/affs/super.c	Mon Apr  6 17:41:00 1998
+++ linux/fs/affs/super.c	Thu May  7 22:58:04 1998
@@ -44,7 +44,7 @@
 {
 	int	 i;
 
-	pr_debug("affs_put_super()\n");
+	pr_debug("AFFS: put_super()\n");
 
 	for (i = 0; i < sb->u.affs_sb.s_bm_count; i++)
 		affs_brelse(sb->u.affs_sb.s_bitmap[i].bm_bh);
@@ -262,7 +262,7 @@
 	unsigned long		 mount_flags;
 	unsigned long		 offset;
 
-	pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options");
+	pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
 
 	MOD_INC_USE_COUNT;
 	lock_super(s);
@@ -396,6 +396,7 @@
 			/* fall thru */
 		case FS_OFS:
 			s->u.affs_sb.s_flags |= SF_OFS;
+			s->s_flags |= MS_NOEXEC;
 			break;
 		case MUFS_DCOFS:
 		case MUFS_INTLOFS:
@@ -403,6 +404,7 @@
 		case FS_DCOFS:
 		case FS_INTLOFS:
 			s->u.affs_sb.s_flags |= SF_INTL | SF_OFS;
+			s->s_flags |= MS_NOEXEC;
 			break;
 		default:
 			goto out_unknown_fs;
@@ -433,7 +435,7 @@
 	ptype  = num_bm * sizeof(struct affs_bm_info) +
 		 az_no * sizeof(struct affs_alloc_zone) +
 		 MAX_ZONES * sizeof(struct affs_zone);
-	pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);
+	pr_debug("AFFS: num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype);
 	if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype, GFP_KERNEL)))
 		goto out_no_bitmap;
 	memset(s->u.affs_sb.s_bitmap,0,ptype);
@@ -597,7 +599,7 @@
 		mapidx, num_bm);
 	goto out_free_bitmap;
 out_no_root:
-	printk(KERN_ERR "AFFS: get root inode failed\n");
+	printk(KERN_ERR "AFFS: Get root inode failed\n");
 
 	/*
 	 * Begin the cascaded cleanup ...
diff -u --recursive --new-file v2.1.100/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.100/linux/fs/buffer.c	Thu May  7 22:51:52 1998
+++ linux/fs/buffer.c	Fri May  8 17:54:39 1998
@@ -38,6 +38,7 @@
 #include <linux/blkdev.h>
 #include <linux/sysrq.h>
 #include <linux/file.h>
+#include <linux/quotaops.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -266,9 +267,9 @@
 	sync_supers(dev);
 	sync_inodes(dev);
 	sync_buffers(dev, 0);
-	sync_dquots(dev, -1);
-	/* 
-	 * FIXME(eric) we need to sync the physical devices here. 
+	DQUOT_SYNC(dev);
+	/*
+	 * FIXME(eric) we need to sync the physical devices here.
 	 * This is because some (scsi) controllers have huge amounts of
 	 * cache onboard (hundreds of Mb), and we need to instruct
 	 * them to commit all of the dirty memory to disk, and we should
@@ -285,7 +286,7 @@
 	sync_buffers(dev, 0);
 	sync_supers(dev);
 	sync_inodes(dev);
-	sync_dquots(dev, -1);
+	DQUOT_SYNC(dev);
 	return sync_buffers(dev, 1);
 }
 
diff -u --recursive --new-file v2.1.100/linux/fs/dquot.c linux/fs/dquot.c
--- v2.1.100/linux/fs/dquot.c	Thu May  7 22:51:53 1998
+++ linux/fs/dquot.c	Fri May  8 17:54:39 1998
@@ -9,33 +9,22 @@
  * have a consistent diskquota tracking system. The ideas of both
  * user and group quotas are based on the Melbourne quota system as
  * used on BSD derived systems. The internal implementation is 
- * based on the LINUX inode-subsystem with added complexity of the
- * diskquota system. This implementation is not based on any BSD
- * kernel sourcecode.
+ * based on one of the several variants of the LINUX inode-subsystem
+ * with added complexity of the diskquota system.
  * 
- * Version: $Id: dquot.c,v 1.11 1997/01/06 06:53:02 davem Exp $
+ * Version: $Id: dquot.c,v 6.3 1996/11/17 18:35:34 mvw Exp mvw $
  * 
- * Author:  Marco van Wieringen <mvw@mcs.ow.nl> <mvw@tnix.net>
- * 
- * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
- *	    removed race conditions in dqput(), dqget() and iput(). 
- *          Andi Kleen removed all verify_area() calls, 31 Dec 96  
- *          Nick Kralevich <nickkral@cal.alumni.berkeley.edu>, 21 Jul 97
- *          Fixed a condition where user and group quotas could get mixed up.
+ * Author:	Marco van Wieringen <mvw@planets.elm.net>
  *
- *          Chris Rankin <rankinc@bellsouth.net>, 31 Dec 97, 2-4 Jan 98
- *          Fixed kernel API so that the user can get the quota for any
- *          group s/he belongs to. Also return useful error codes when
- *          turning quotas off, and fixed sync_dquot() so that all devices
- *          are synced when dev==NODEV. 
- *
- * (C) Copyright 1994, 1995 Marco van Wieringen 
+ * Fixes:   Dmitry Gorodchanin <pgmdsg@ibi.com>, 11 Feb 96
  *
+ * (C) Copyright 1994 - 1997 Marco van Wieringen 
  */
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
@@ -46,129 +35,153 @@
 #include <linux/mount.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 
-#define __DQUOT_VERSION__	"dquot_5.6.0"
+#define __DQUOT_VERSION__	"dquot_6.4.0"
+
+int nr_dquots = 0, nr_free_dquots = 0;
+int max_dquots = NR_DQUOTS;
 
 static char quotamessage[MAX_QUOTA_MESSAGE];
 static char *quotatypes[] = INITQFNAMES;
 
-static int nr_dquots = 0, nr_free_dquots = 0;
-static struct dquot *hash_table[NR_DQHASH];
-static struct dquot *first_dquot;
+static kmem_cache_t *dquot_cachep;
+
+static struct dquot *dquot_hash[NR_DQHASH];
+static struct free_dquot_queue {
+	struct dquot *head;
+	struct dquot **last;
+} free_dquots = { NULL, &free_dquots.head };
+static struct dquot *inuse_list = NULL;
+static int dquot_updating[NR_DQHASH];
+
 static struct dqstats dqstats;
+static struct wait_queue *dquot_wait = (struct wait_queue *)NULL,
+                         *update_wait = (struct wait_queue *)NULL;
 
-static struct wait_queue *dquot_wait = (struct wait_queue *)NULL;
+static inline char is_enabled(struct vfsmount *vfsmnt, short type)
+{
+	switch (type) {
+		case USRQUOTA:
+			return((vfsmnt->mnt_dquot.flags & DQUOT_USR_ENABLED) != 0);
+		case GRPQUOTA:
+			return((vfsmnt->mnt_dquot.flags & DQUOT_GRP_ENABLED) != 0);
+	}
+	return(0);
+}
 
-extern void add_dquot_ref(kdev_t dev, short type);
-extern void reset_dquot_ptrs(kdev_t dev, short type);
+static inline char sb_has_quota_enabled(struct super_block *sb, short type)
+{
+	struct vfsmount *vfsmnt;
 
-#ifndef min
-#define min(a,b) ((a) < (b)) ? (a) : (b)
-#endif
+	return((vfsmnt = lookup_vfsmnt(sb->s_dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type));
+}
 
-/*
- * Functions for management of the hashlist.
- */
-static inline int const hashfn(kdev_t dev, unsigned int id, short type)
+static inline char dev_has_quota_enabled(kdev_t dev, short type)
 {
-	return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
+	struct vfsmount *vfsmnt;
+
+	return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type));
 }
 
-static inline struct dquot **const hash(kdev_t dev, unsigned int id, short type)
+static inline int const hashfn(kdev_t dev, unsigned int id, short type)
 {
-	return(hash_table + hashfn(dev, id, type));
+	return((HASHDEV(dev) ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
 }
 
-static inline int has_quota_enabled(kdev_t dev, short type)
+static inline void insert_dquot_hash(struct dquot *dquot)
 {
-	struct vfsmount *vfsmnt;
+	struct dquot **htable;
 
-	return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL &&
-	       (vfsmnt->mnt_quotas[type] != (struct file *)NULL));
+	htable = &dquot_hash[hashfn(dquot->dq_dev, dquot->dq_id, dquot->dq_type)];
+	if ((dquot->dq_hash_next = *htable) != NULL)
+		(*htable)->dq_hash_pprev = &dquot->dq_hash_next;
+	*htable = dquot;
+	dquot->dq_hash_pprev = htable;
 }
 
-static void insert_dquot_free(struct dquot *dquot)
+static inline void hash_dquot(struct dquot *dquot)
 {
-	dquot->dq_next = first_dquot;
-	dquot->dq_prev = first_dquot->dq_prev;
-	dquot->dq_next->dq_prev = dquot;
-	dquot->dq_prev->dq_next = dquot;
-	first_dquot = dquot;
+	insert_dquot_hash(dquot);
 }
 
-static void remove_dquot_free(struct dquot *dquot)
+static inline void unhash_dquot(struct dquot *dquot)
 {
-	if (first_dquot == dquot)
-		first_dquot = first_dquot->dq_next;
-	if (dquot->dq_next)
-		dquot->dq_next->dq_prev = dquot->dq_prev;
-	if (dquot->dq_prev)
-		dquot->dq_prev->dq_next = dquot->dq_next;
-	dquot->dq_next = dquot->dq_prev = NODQUOT;
+	if (dquot->dq_hash_pprev) {
+		if (dquot->dq_hash_next)
+			dquot->dq_hash_next->dq_hash_pprev = dquot->dq_hash_pprev;
+		*(dquot->dq_hash_pprev) = dquot->dq_hash_next;
+		dquot->dq_hash_pprev = NULL;
+	}
 }
 
-static void insert_dquot_hash(struct dquot *dquot)
+static inline struct dquot *find_dquot(unsigned int hashent, kdev_t dev, unsigned int id, short type)
 {
-	struct dquot **hash_ent;
+	struct dquot *dquot;
 
-	hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
-	dquot->dq_hash_next = *hash_ent;
-	dquot->dq_hash_prev = NODQUOT;
-	if (dquot->dq_hash_next)
-		dquot->dq_hash_next->dq_hash_prev = dquot;
-	*hash_ent = dquot;
+	for (dquot = dquot_hash[hashent]; dquot; dquot = dquot->dq_hash_next)
+		if (dquot->dq_dev == dev && dquot->dq_id == id && dquot->dq_type == type)
+			break;
+	return dquot;
 }
 
-static void remove_dquot_hash(struct dquot *dquot)
+static inline void put_dquot_head(struct dquot *dquot)
 {
-	struct dquot **hash_ent;
+	if ((dquot->dq_next = free_dquots.head) != NULL)
+		free_dquots.head->dq_pprev = &dquot->dq_next;
+	else
+		free_dquots.last = &dquot->dq_next;
+	free_dquots.head = dquot;
+	dquot->dq_pprev = &free_dquots.head;
+	nr_free_dquots++;
+}
 
-	hash_ent = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
-	if (*hash_ent == dquot)
-		*hash_ent = dquot->dq_hash_next;
-	if (dquot->dq_hash_next)
-		dquot->dq_hash_next->dq_hash_prev = dquot->dq_hash_prev;
-	if (dquot->dq_hash_prev)
-		dquot->dq_hash_prev->dq_hash_next = dquot->dq_hash_next;
-	dquot->dq_hash_prev = dquot->dq_hash_next = NODQUOT;
+static inline void put_dquot_last(struct dquot *dquot)
+{
+	dquot->dq_next = NULL;
+	dquot->dq_pprev = free_dquots.last;
+	*free_dquots.last = dquot;
+	free_dquots.last = &dquot->dq_next;
+	nr_free_dquots++;
 }
 
-static void put_last_free(struct dquot *dquot)
+static inline void remove_free_dquot(struct dquot *dquot)
 {
-	remove_dquot_free(dquot);
-	dquot->dq_prev = first_dquot->dq_prev;
-	dquot->dq_prev->dq_next = dquot;
-	dquot->dq_next = first_dquot;
-	dquot->dq_next->dq_prev = dquot;
+	if (dquot->dq_pprev) {
+		if (dquot->dq_next)
+			dquot->dq_next->dq_pprev = dquot->dq_pprev;
+		else
+			free_dquots.last = dquot->dq_pprev;
+		*dquot->dq_pprev = dquot->dq_next;
+		dquot->dq_pprev = NULL;
+		nr_free_dquots--;
+	}
 }
 
-static void grow_dquots(void)
+static inline void put_inuse(struct dquot *dquot)
 {
-	struct dquot *dquot;
-	int cnt;
+	if ((dquot->dq_next = inuse_list) != NULL)
+		inuse_list->dq_pprev = &dquot->dq_next;
+	inuse_list = dquot;
+	dquot->dq_pprev = &inuse_list;
+}
 
-	if (!(dquot = (struct dquot*) get_free_page(GFP_KERNEL)))
-		return;
-	dqstats.pages_allocated++;
-	cnt = PAGE_SIZE / sizeof(struct dquot);
-	nr_dquots += cnt;
-	nr_free_dquots += cnt;
-	if (!first_dquot) {
-		dquot->dq_next = dquot->dq_prev = first_dquot = dquot++;
-		cnt--;
+static inline void remove_inuse(struct dquot *dquot)
+{
+	if (dquot->dq_pprev) {
+		if (dquot->dq_next)
+			dquot->dq_next->dq_pprev = dquot->dq_pprev;
+		*dquot->dq_pprev = dquot->dq_next;
+		dquot->dq_pprev = NULL;
 	}
-	for (; cnt; cnt--)
-		insert_dquot_free(dquot++);
 }
 
-/*
- * Functions for locking and waiting on dquots.
- */
 static void __wait_on_dquot(struct dquot *dquot)
 {
-	struct wait_queue wait = {current, NULL};
+	struct wait_queue wait = { current, NULL };
 
 	add_wait_queue(&dquot->dq_wait, &wait);
 repeat:
@@ -202,39 +215,22 @@
 		wake_up(&dquot->dq_wait);
 	}
 }
-/*
- * Note that we don't want to disturb any wait-queues when we discard
- * an dquot.
- *
- * FIXME: As soon as we have a nice solution for the inode problem we
- *		  can also fix this one. I.e. the volatile part.
- */
-static void clear_dquot(struct dquot * dquot)
-{
-	struct wait_queue *wait;
-
-	wait_on_dquot(dquot);
-	remove_dquot_hash(dquot);
-	remove_dquot_free(dquot);
-	wait = ((volatile struct dquot *) dquot)->dq_wait;
-	if (dquot->dq_count)
-		nr_free_dquots++;
-	memset(dquot, 0, sizeof(*dquot));
-	((volatile struct dquot *) dquot)->dq_wait = wait;
-	insert_dquot_free(dquot);
-}
 
 static void write_dquot(struct dquot *dquot)
 {
-	short type = dquot->dq_type;
-	struct file *filp = dquot->dq_mnt->mnt_quotas[type];
+	short type;
+	struct file *filp;
 	mm_segment_t fs;
 	loff_t offset;
 
+	type = dquot->dq_type;
+	filp = dquot->dq_mnt->mnt_dquot.files[type];
+
 	if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)NULL))
 		return;
+
 	lock_dquot(dquot);
-	down(&dquot->dq_mnt->mnt_sem);
+	down(&dquot->dq_mnt->mnt_dquot.semaphore);
 	offset = dqoff(dquot->dq_id);
 	fs = get_fs();
 	set_fs(KERNEL_DS);
@@ -242,29 +238,35 @@
 	if (filp->f_op->write(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset) == sizeof(struct dqblk))
 		dquot->dq_flags &= ~DQ_MOD;
 
-	up(&dquot->dq_mnt->mnt_sem);
+	up(&dquot->dq_mnt->mnt_dquot.semaphore);
 	set_fs(fs);
+
 	unlock_dquot(dquot);
 	dqstats.writes++;
 }
 
 static void read_dquot(struct dquot *dquot)
 {
-	short type = dquot->dq_type;
-	struct file *filp = dquot->dq_mnt->mnt_quotas[type];
+	short 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_sem);
+	down(&dquot->dq_mnt->mnt_dquot.semaphore);
 	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_sem);
+	up(&dquot->dq_mnt->mnt_dquot.semaphore);
 	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;
@@ -272,46 +274,292 @@
 	dqstats.reads++;
 }
 
+void clear_dquot(struct dquot *dquot)
+{
+        struct wait_queue *wait;
+
+        /* So we don't disappear. */
+        dquot->dq_count++;
+
+        wait_on_dquot(dquot);
+
+        if (--dquot->dq_count > 0)
+                remove_inuse(dquot);
+        else
+                remove_free_dquot(dquot);
+        unhash_dquot(dquot);
+        wait = dquot->dq_wait;
+        memset(dquot, 0, sizeof(*dquot)); barrier();
+        dquot->dq_wait = wait;
+        put_dquot_head(dquot);
+}
+
+void invalidate_dquots(kdev_t dev, short type)
+{
+	struct dquot *dquot, *next = NULL;
+	int pass = 0;
+
+	dquot = free_dquots.head;
+repeat:
+	while (dquot) {
+		next = dquot->dq_next;
+		if (dquot->dq_dev != dev || dquot->dq_type != type)
+			goto next;
+		clear_dquot(dquot);
+	next:
+		dquot = next;
+	}
+
+	if (pass == 0) {
+		dquot = inuse_list;
+		pass = 1;
+		goto repeat;
+	}
+}
+
 int sync_dquots(kdev_t dev, short type)
 {
-	struct dquot *dquot = first_dquot;
-	int i;
+	struct dquot *dquot, *next;
+	int pass = 0;
 
-	dqstats.syncs++;
-	for (i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) {
-		if ((dev != NODEV && dquot->dq_dev != dev) || dquot->dq_count == 0 )
-			continue;
-		if (type != -1 && dquot->dq_type != type)
-			continue;
+	dquot = free_dquots.head;
+repeat:
+	while (dquot) {
+		next = dquot->dq_next;
+		if ((dev && dquot->dq_dev != dev) ||
+                    (type != -1 && dquot->dq_type != type))
+			goto next;
 		wait_on_dquot(dquot);
 		if (dquot->dq_flags & DQ_MOD)
 			write_dquot(dquot);
+	next:
+		dquot = next;
+	}
+
+	if (pass == 0) {
+		dquot = inuse_list;
+		pass = 1;
+		goto repeat;
 	}
+	dqstats.syncs++;
 	return(0);
 }
 
-/*
- * Trash the cache for a certain type on a device.
- */
-void invalidate_dquots(kdev_t dev, short type)
+void dqput(struct dquot *dquot)
 {
-	struct dquot *dquot, *next;
-	int cnt;
+	if (!dquot)
+		return;
 
-	next = first_dquot;
-	for (cnt = nr_dquots ; cnt > 0 ; cnt--) {
-		dquot = next;
-		next = dquot->dq_next;
-		if (dquot->dq_dev != dev || dquot->dq_type != type)
+	/*
+	 * If the dq_mnt pointer isn't initialized this entry needs no
+	 * checking and doesn't need to be written. It just an empty
+	 * dquot that is put back on to the freelist.
+	 */
+	if (dquot->dq_mnt != (struct vfsmount *)NULL) {
+		dqstats.drops++;
+		wait_on_dquot(dquot);
+
+		if (!dquot->dq_count) {
+			printk("VFS: dqput: trying to free free dquot\n");
+			printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev),
+			       quotatypes[dquot->dq_type], dquot->dq_id);
+			return;
+		}
+we_slept:
+		if (dquot->dq_count > 1) {
+			dquot->dq_count--;
+			return;
+		} else {
+			wake_up(&dquot_wait);
+
+			if (dquot->dq_flags & DQ_MOD) {
+				write_dquot(dquot);
+				wait_on_dquot(dquot);
+				goto we_slept;
+			}
+		}
+	}
+
+	if (--dquot->dq_count == 0) {
+		remove_inuse(dquot);
+		put_dquot_last(dquot); /* Place at end of LRU free queue */
+	}
+
+	return;
+}
+
+static void grow_dquots(void)
+{
+	struct dquot *dquot;
+	int cnt = 32;
+
+	while (cnt > 0) {
+		dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
+		if(!dquot)
+			return;
+
+		nr_dquots++;
+		memset((caddr_t)dquot, 0, sizeof(struct dquot));
+		put_dquot_head(dquot);
+		cnt--;
+	}
+}
+
+static struct dquot *find_best_candidate_weighted(struct dquot *dquot)
+{
+	int limit, myscore;
+	unsigned long bestscore;
+	struct dquot *best = NULL;
+
+	if (dquot) {
+		bestscore = 2147483647;
+		limit = nr_free_dquots >> 2;
+		do {
+			if (!((dquot->dq_flags & DQ_LOCKED) || (dquot->dq_flags & DQ_MOD))) {
+				myscore = dquot->dq_referenced;
+				if (myscore < bestscore) {
+					bestscore = myscore;
+					best = dquot;
+				}
+			}
+			dquot = dquot->dq_next;
+		} while (dquot && --limit);
+	}
+	return best;
+}
+
+static inline struct dquot *find_best_free(struct dquot *dquot)
+{
+	int limit;
+
+	if (dquot) {
+		limit = nr_free_dquots >> 5;
+		do {
+			if (dquot->dq_referenced == 0)
+				return dquot;
+			dquot = dquot->dq_next;
+		} while (dquot && --limit);
+	}
+	return NULL;
+}
+
+struct dquot *get_empty_dquot(void)
+{
+	struct dquot *dquot;
+
+repeat:
+	dquot = find_best_free(free_dquots.head);
+	if (!dquot)
+		goto pressure;
+got_it:
+	dquot->dq_count++;
+	wait_on_dquot(dquot);
+	unhash_dquot(dquot);
+	remove_free_dquot(dquot);
+
+	memset(dquot, 0, sizeof(*dquot));
+	dquot->dq_count = 1;
+
+	put_inuse(dquot);
+	return dquot;
+pressure:
+	if (nr_dquots < max_dquots) {
+		grow_dquots();
+		goto repeat;
+	}
+
+	dquot = find_best_candidate_weighted(free_dquots.head);
+	if (!dquot) {
+		printk("VFS: No free dquots, contact mvw@planets.elm.net\n");
+		sleep_on(&dquot_wait);
+		goto repeat;
+	}
+	if (dquot->dq_flags & DQ_LOCKED) {
+		wait_on_dquot(dquot);
+		goto repeat;
+	} else if (dquot->dq_flags & DQ_MOD) {
+		write_dquot(dquot);
+		goto repeat;
+	}
+	goto got_it;
+}
+
+struct dquot *dqget(kdev_t dev, unsigned int id, short type)
+{
+	unsigned int hashent = hashfn(dev, id, type);
+	struct dquot *dquot, *empty = NULL;
+	struct vfsmount *vfsmnt;
+
+        if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || is_enabled(vfsmnt, type) == 0)
+                return(NODQUOT);
+
+we_slept:
+	if ((dquot = find_dquot(hashent, dev, id, type)) == NULL) {
+		if (empty == NULL) {
+			dquot_updating[hashent]++;
+			empty = get_empty_dquot();
+			if (!--dquot_updating[hashent])
+				wake_up(&update_wait);
+			goto we_slept;
+		}
+		dquot = empty;
+        	dquot->dq_id = id;
+        	dquot->dq_type = type;
+        	dquot->dq_dev = dev;
+        	dquot->dq_mnt = vfsmnt;
+        	read_dquot(dquot);
+		hash_dquot(dquot);
+	} else {
+		if (!dquot->dq_count++) {
+			remove_free_dquot(dquot);
+			put_inuse(dquot);
+		} else
+			dqstats.cache_hits++;
+		wait_on_dquot(dquot);
+		if (empty)
+			dqput(empty);
+	}
+
+	while (dquot_updating[hashent])
+		sleep_on(&update_wait);
+
+	dquot->dq_referenced++;
+	dqstats.lookups++;
+
+	return dquot;
+}
+
+static void add_dquot_ref(kdev_t dev, short type)
+{
+	struct file *filp;
+	struct inode *inode;
+
+	for (filp = inuse_filps; filp; filp = filp->f_next) {
+		inode = filp->f_dentry->d_inode;
+		if (!inode || inode->i_dev != dev)
 			continue;
-		if (dquot->dq_flags & DQ_LOCKED) {
-			printk("VFS: dquot busy on removed device %s\n", kdevname(dev));
+		if (filp->f_mode & FMODE_WRITE && inode->i_sb && inode->i_sb->dq_op) {
+			inode->i_sb->dq_op->initialize(inode, type);
+			inode->i_flags |= S_QUOTA;
+		}
+	}
+}
+
+static void reset_dquot_ptrs(kdev_t dev, short type)
+{
+	struct file *filp;
+	struct inode *inode;
+
+	for (filp = inuse_filps; filp; filp = filp->f_next) {
+		inode = filp->f_dentry->d_inode;
+		if (!inode || inode->i_dev != dev)
 			continue;
+		if (IS_QUOTAINIT(inode)) {
+			if (inode->i_sb && inode->i_sb->dq_op)
+				inode->i_sb->dq_op->drop(inode);
+			inode->i_dquot[type] = NODQUOT;
+			inode->i_flags &= ~S_QUOTA;
 		}
-		if (dquot->dq_flags & DQ_MOD)
-			write_dquot(dquot);
-		dqstats.drops++;
-		clear_dquot(dquot);
 	}
 }
 
@@ -359,229 +607,108 @@
 	unlock_dquot(dquot);
 }
 
-static inline int need_print_warning(short type, struct dquot *dquot)
+static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot)
 {
 	switch (type) {
 		case USRQUOTA:
-			return(current->fsuid == dquot->dq_id);
+			return(initiator == dquot->dq_id);
 		case GRPQUOTA:
-			return(current->fsgid == dquot->dq_id);
+			return(initiator == dquot->dq_id);
 	}
 	return(0);
 }
 
-static int check_idq(struct dquot *dquot, short type, u_long short inodes)
+static inline char ignore_hardlimit(struct dquot *dquot, uid_t initiator)
+{
+	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, struct tty_struct *tty)
 {
 	if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
 		return(QUOTA_OK);
+
 	if (dquot->dq_ihardlimit &&
-	   (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && 
-	    !capable(CAP_SYS_RESOURCE)) {
+	   (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&
+            !ignore_hardlimit(dquot, initiator)) {
 		if ((dquot->dq_flags & DQ_INODES) == 0 &&
-                     need_print_warning(type, dquot)) {
-			sprintf(quotamessage, "%s: write failed, %s file limit reached\r\n",
+                     need_print_warning(type, initiator, dquot)) {
+			sprintf(quotamessage, "%s: write failed, %s file limit reached\n",
 			        dquot->dq_mnt->mnt_dirname, quotatypes[type]);
-			tty_write_message(current->tty, quotamessage);
+			tty_write_message(tty, quotamessage);
 			dquot->dq_flags |= DQ_INODES;
 		}
 		return(NO_QUOTA);
 	}
+
 	if (dquot->dq_isoftlimit &&
 	   (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
-	    dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && 
-	    !capable(CAP_SYS_RESOURCE)) {
-                if (need_print_warning(type, dquot)) {
-			sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\r\n",
+	    dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&
+            !ignore_hardlimit(dquot, initiator)) {
+                if (need_print_warning(type, initiator, dquot)) {
+			sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\n",
 		        	dquot->dq_mnt->mnt_dirname, quotatypes[type]);
-			tty_write_message(current->tty, quotamessage);
+			tty_write_message(tty, quotamessage);
 		}
 		return(NO_QUOTA);
 	}
+
 	if (dquot->dq_isoftlimit &&
 	   (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
-	    dquot->dq_itime == 0 && 
-	    !capable(CAP_SYS_RESOURCE)) {
-                if (need_print_warning(type, dquot)) {
-			sprintf(quotamessage, "%s: warning, %s file quota exceeded\r\n",
+	    dquot->dq_itime == 0) {
+                if (need_print_warning(type, initiator, dquot)) {
+			sprintf(quotamessage, "%s: warning, %s file quota exceeded\n",
 		        	dquot->dq_mnt->mnt_dirname, quotatypes[type]);
-			tty_write_message(current->tty, quotamessage);
+			tty_write_message(tty, quotamessage);
 		}
-		dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
+		dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
 	}
+
 	return(QUOTA_OK);
 }
 
-static int check_bdq(struct dquot *dquot, short type, u_long blocks)
+static int check_bdq(struct dquot *dquot, short type, u_long blocks, uid_t initiator, struct tty_struct *tty, char warn)
 {
 	if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
 		return(QUOTA_OK);
+
 	if (dquot->dq_bhardlimit &&
-	   (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && 
-	    !capable(CAP_SYS_RESOURCE)) {
-		if ((dquot->dq_flags & DQ_BLKS) == 0 &&
-                     need_print_warning(type, dquot)) {
-			sprintf(quotamessage, "%s: write failed, %s disk limit reached.\r\n",
+	   (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&
+            !ignore_hardlimit(dquot, initiator)) {
+		if (warn && (dquot->dq_flags & DQ_BLKS) == 0 &&
+                     need_print_warning(type, initiator, dquot)) {
+			sprintf(quotamessage, "%s: write failed, %s disk limit reached.\n",
 			        dquot->dq_mnt->mnt_dirname, quotatypes[type]);
-			tty_write_message(current->tty, quotamessage);
+			tty_write_message(tty, quotamessage);
 			dquot->dq_flags |= DQ_BLKS;
 		}
 		return(NO_QUOTA);
 	}
+
 	if (dquot->dq_bsoftlimit &&
 	   (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
-	    dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && 
-	    !capable(CAP_SYS_RESOURCE)) {
-                if (need_print_warning(type, dquot)) {
-			sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\r\n",
+	    dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&
+            !ignore_hardlimit(dquot, initiator)) {
+                if (warn && need_print_warning(type, initiator, dquot)) {
+			sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\n",
 		        	dquot->dq_mnt->mnt_dirname, quotatypes[type]);
-			tty_write_message(current->tty, quotamessage);
+			tty_write_message(tty, quotamessage);
 		}
 		return(NO_QUOTA);
 	}
+
 	if (dquot->dq_bsoftlimit &&
 	   (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
-	    dquot->dq_btime == 0 && 
-	    !capable(CAP_SYS_RESOURCE)) {
-                if (need_print_warning(type, dquot)) {
-			sprintf(quotamessage, "%s: warning, %s disk quota exceeded\r\n",
+	    dquot->dq_btime == 0) {
+                if (warn && need_print_warning(type, initiator, dquot)) {
+			sprintf(quotamessage, "%s: warning, %s disk quota exceeded\n",
 		        	dquot->dq_mnt->mnt_dirname, quotatypes[type]);
-			tty_write_message(current->tty, quotamessage);
-		}
-		dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
-	}
-	return(QUOTA_OK);
-}
-
-static void dqput(struct dquot *dquot)
-{
-	if (!dquot)
-		return;
-	/*
-	 * If the dq_mnt pointer isn't initialized this entry needs no
-	 * checking and doesn't need to be written. It just an empty
-	 * dquot that is put back into the freelist.
-	 */
-	if (dquot->dq_mnt != (struct vfsmount *)NULL) {
-		dqstats.drops++;
-		wait_on_dquot(dquot);
-		if (!dquot->dq_count) {
-			printk("VFS: dqput: trying to free free dquot\n");
-			printk("VFS: device %s, dquot of %s %d\n", kdevname(dquot->dq_dev),
-			       quotatypes[dquot->dq_type], dquot->dq_id);
-			return;
+			tty_write_message(tty, quotamessage);
 		}
-repeat:
-		if (dquot->dq_count > 1) {
-			dquot->dq_count--;
-			return;
-		}
-		wake_up(&dquot_wait);
-		if (dquot->dq_flags & DQ_MOD) {
-			write_dquot(dquot);	/* we can sleep - so do again */
-			wait_on_dquot(dquot);
-			goto repeat;
-		}
-	}
-	if (dquot->dq_count) {
-		dquot->dq_count--;
-		nr_free_dquots++;
+		dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
 	}
-	return;
-}
-
-static struct dquot *get_empty_dquot(void)
-{
-	struct dquot *dquot, *best;
-	int cnt;
-
-	if (nr_dquots < NR_DQUOTS && nr_free_dquots < (nr_dquots >> 2))
-		grow_dquots();
 
-repeat:
-	dquot = first_dquot;
-	best = NODQUOT;
-	for (cnt = 0; cnt < nr_dquots; dquot = dquot->dq_next, cnt++) {
-		if (!dquot->dq_count) {
-			if (!best)
-				best = dquot;
-			if (!(dquot->dq_flags & DQ_MOD) && !(dquot->dq_flags & DQ_LOCKED)) {
-				best = dquot;
-				break;
-			}
-		}
-	}
-	if (!best || best->dq_flags & DQ_MOD || best->dq_flags & DQ_LOCKED)
-		if (nr_dquots < NR_DQUOTS) {
-			grow_dquots();
-			goto repeat;
-		}
-	dquot = best;
-	if (!dquot) {
-		printk("VFS: No free dquots - contact mvw@mcs.ow.org\n");
-		sleep_on(&dquot_wait);
-		goto repeat;
-	}
-	if (dquot->dq_flags & DQ_LOCKED) {
-		wait_on_dquot(dquot);
-		goto repeat;
-	}
-	if (dquot->dq_flags & DQ_MOD) {
-		write_dquot(dquot);
-		goto repeat;
-	}
-	if (dquot->dq_count)
-		goto repeat;
-	clear_dquot(dquot);
-	dquot->dq_count = 1;
-	nr_free_dquots--;
-	if (nr_free_dquots < 0) {
-		printk ("VFS: get_empty_dquot: bad free dquot count.\n");
-		nr_free_dquots = 0;
-	}
-	return(dquot);
-}
-
-static struct dquot *dqget(kdev_t dev, unsigned int id, short type)
-{
-	struct dquot *dquot, *empty;
-	struct vfsmount *vfsmnt;
-
-	if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL ||
-	    (vfsmnt->mnt_quotas[type] == (struct file *)0))
-		return(NODQUOT);
-	dqstats.lookups++;
-	empty = get_empty_dquot();
-repeat:
-	dquot = *(hash(dev, id, type));
-	while (dquot) {
-		if (dquot->dq_dev != dev || dquot->dq_id != id ||
-		    dquot->dq_type != type) {
-			dquot = dquot->dq_hash_next;
-			continue;
-		}
-		wait_on_dquot(dquot);
-		if (dquot->dq_dev != dev || dquot->dq_id != id ||
-		    dquot->dq_type != type)
-			goto repeat;
-		if (!dquot->dq_count)
-			nr_free_dquots--;
-		dquot->dq_count++;
-		if (empty)
-			dqput(empty);
-		dqstats.cache_hits++;
-		return(dquot);
-	}
-	if (!empty)
-		return(NODQUOT);
-	dquot = empty;
-	dquot->dq_id = id;
-	dquot->dq_type = type;
-	dquot->dq_dev = dev;
-	dquot->dq_mnt = vfsmnt;
-	put_last_free(dquot);
-	insert_dquot_hash(dquot);
-	read_dquot(dquot);
-	return(dquot);
+	return(QUOTA_OK);
 }
 
 /*
@@ -590,54 +717,57 @@
  */ 
 static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk)
 {
+	int error;
 	struct dquot *dquot;
 	struct dqblk dq_dqblk;
 
 	if (dqblk == (struct dqblk *)NULL)
 		return(-EFAULT);
 
-	if (flags & QUOTA_SYSCALL) {
-		if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)))
-			return -EFAULT;	
-	} else {
-		memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk));
-	}
+	if (flags & QUOTA_SYSCALL)
+		if ((error = copy_from_user((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk))) != 0)
+			return(error);
+	else
+		memcpy((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk));
+
 	if ((dquot = dqget(dev, id, type)) != NODQUOT) {
 		lock_dquot(dquot);
-		if (id > 0 && (flags & (SET_QUOTA|SET_QLIMIT))) {
+
+		if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
 			dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
 			dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
 			dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
 			dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
 		}
-		if (flags & (SET_QUOTA|SET_USE)) {
+
+		if ((flags & SET_QUOTA) || (flags & SET_USE)) {
 			if (dquot->dq_isoftlimit &&
 			    dquot->dq_curinodes < dquot->dq_isoftlimit &&
 			    dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
-				dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
+				dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
 			dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
 			if (dquot->dq_curinodes < dquot->dq_isoftlimit)
 				dquot->dq_flags &= ~DQ_INODES;
 			if (dquot->dq_bsoftlimit &&
 			    dquot->dq_curblocks < dquot->dq_bsoftlimit &&
 			    dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
-				dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
+				dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
 			dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
 			if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
 				dquot->dq_flags &= ~DQ_BLKS;
 		}
+
 		if (id == 0) {
-			/* 
-			 * Change in expiretimes, change them in dq_mnt.
-			 */
-			dquot->dq_mnt->mnt_bexp[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
-			dquot->dq_mnt->mnt_iexp[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
+			dquot->dq_mnt->mnt_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
+			dquot->dq_mnt->mnt_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
 		}
+
 		if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
 		    dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
 			dquot->dq_flags |= DQ_FAKE;
 		else
 			dquot->dq_flags &= ~DQ_FAKE;
+
 		dquot->dq_flags |= DQ_MOD;
 		unlock_dquot(dquot);
 		dqput(dquot);
@@ -650,14 +780,14 @@
 	struct dquot *dquot;
 	int error;
 
-	if (has_quota_enabled(dev, type)) {
+	if (dev_has_quota_enabled(dev, type)) {
 		if (dqblk == (struct dqblk *)NULL)
 			return(-EFAULT);
 
 		if ((dquot = dqget(dev, id, type)) != NODQUOT) {
-			error = copy_to_user(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
+			error = copy_to_user((caddr_t)dqblk, (caddr_t)&dquot->dq_dqb, sizeof(struct dqblk));
 			dqput(dquot);
-			return error ? -EFAULT : 0;
+			return(error);
 		}
 	}
 	return(-ESRCH);
@@ -667,25 +797,67 @@
 {
 	dqstats.allocated_dquots = nr_dquots;
 	dqstats.free_dquots = nr_free_dquots;
-	return copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats)) 
-		? -EFAULT : 0; 
+	return(copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats)));
+}
+
+static int quota_root_squash(kdev_t dev, short type, int *addr)
+{
+	struct vfsmount *vfsmnt;
+	int new_value, error;
+
+	if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL)
+		return(-ENODEV);
+
+	if ((error = copy_from_user((caddr_t)&new_value, (caddr_t)addr, sizeof(int))) != 0)
+		return(error);
+
+	vfsmnt->mnt_dquot.rsquash[type] = new_value;
+	return(0);
 }
 
 /*
- * Initialize pointer in an inode to the right dquots.
+ * This is a simple algorithm that calculates the size of a file in blocks.
+ * This is only used on filesystems that do not have an i_blocks count.
+ */
+static u_long isize_to_blocks(size_t isize, size_t blksize)
+{
+	u_long blocks;
+	u_long indirect;
+
+	if (!blksize)
+		blksize = BLOCK_SIZE;
+	blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
+	if (blocks > 10) {
+		indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
+		if (blocks > (10 + 256)) {
+			indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
+			if (blocks > (10 + 256 + (256 << 8)))
+				indirect++; /* triple indirect blocks */
+		}
+		blocks += indirect;
+	}
+	return(blocks);
+}
+
+/*
+ * Externally referenced functions through dquot_operations in inode.
  */
 void dquot_initialize(struct inode *inode, short type)
 {
+	struct dquot *dquot;
 	unsigned int id = 0;
 	short cnt;
-	struct dquot *tmp;
 
-	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) {
+	if (S_ISREG(inode->i_mode) ||
+            S_ISDIR(inode->i_mode) ||
+            S_ISLNK(inode->i_mode)) {
 		for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 			if (type != -1 && cnt != type)
 				continue;
-			if (!has_quota_enabled(inode->i_dev, cnt))
+
+			if (!sb_has_quota_enabled(inode->i_sb, cnt))
 				continue;
+
 			if (inode->i_dquot[cnt] == NODQUOT) {
 				switch (cnt) {
 					case USRQUOTA:
@@ -695,17 +867,13 @@
 						id = inode->i_gid;
 						break;
 				}
-
-				tmp = dqget(inode->i_dev, id, cnt);
-				/* We may sleep in dqget(), so check it again.
-				 * 	Dmitry Gorodchanin 02/11/96
-				 */
+				dquot = dqget(inode->i_dev, id, cnt);
 				if (inode->i_dquot[cnt] != NODQUOT) {
-					dqput(tmp);
+					dqput(dquot);
 					continue;
 				} 
-				inode->i_dquot[cnt] = tmp;
-				inode->i_flags |= S_WRITE;
+				inode->i_dquot[cnt] = dquot;
+				inode->i_flags |= S_QUOTA;
 			}
 		}
 	}
@@ -713,82 +881,58 @@
 
 void dquot_drop(struct inode *inode)
 {
+	struct dquot *dquot;
 	short cnt;
-	struct dquot * tmp;
 
+	inode->i_flags &= ~S_QUOTA;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
-		/* We can sleep at dqput(). So we must do it this way.
-		 * 	Dmitry Gorodchanin 02/11/96
-		 */
-		tmp = inode->i_dquot[cnt];
+		dquot = inode->i_dquot[cnt];
 		inode->i_dquot[cnt] = NODQUOT;
-		dqput(tmp);
-	}
-	inode->i_flags &= ~S_WRITE;
-}
-
-/*
- * This is a simple algorithm that calculates the size of a file in blocks.
- * This is only used on filesystems that do not have an i_blocks count.
- */
-static u_long isize_to_blocks(size_t isize, size_t blksize)
-{
-	u_long blocks;
-	u_long indirect;
-
-	if (!blksize)
-		blksize = BLOCK_SIZE;
-	blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
-	if (blocks > 10) {
-		indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
-		if (blocks > (10 + 256)) {
-			indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
-			if (blocks > (10 + 256 + (256 << 8)))
-				indirect++; /* triple indirect blocks */
-		}
-		blocks += indirect;
+		dqput(dquot);
 	}
-	return(blocks);
 }
 
-/*
- * Externally referenced functions through dquot_operations.
- */
-int dquot_alloc_block(const struct inode *inode, unsigned long number)
+int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator, char warn)
 {
 	unsigned short cnt;
+	struct tty_struct *tty = current->tty;
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
-		if (check_bdq(inode->i_dquot[cnt], cnt, number))
+		if (check_bdq(inode->i_dquot[cnt], cnt, number, initiator, tty, warn))
 			return(NO_QUOTA);
 	}
+
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
 		dquot_incr_blocks(inode->i_dquot[cnt], number);
 	}
+
 	return(QUOTA_OK);
 }
 
-int dquot_alloc_inode(const struct inode *inode, unsigned long number)
+int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator)
 {
 	unsigned short cnt;
+	struct tty_struct *tty = current->tty;
 
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
-		if (check_idq(inode->i_dquot[cnt], cnt, number))
+		if (check_idq(inode->i_dquot[cnt], cnt, number, initiator, tty))
 			return(NO_QUOTA);
 	}
+
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (inode->i_dquot[cnt] == NODQUOT)
 			continue;
 		dquot_incr_inodes(inode->i_dquot[cnt], number);
 	}
+
 	return(QUOTA_OK);
 }
 
@@ -817,11 +961,12 @@
 /*
  * Transfer the number of inode and blocks from one diskquota to an other.
  */
-int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction)
+int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid_t initiator)
 {
 	unsigned long blocks;
 	struct dquot *transfer_from[MAXQUOTAS];
 	struct dquot *transfer_to[MAXQUOTAS];
+	struct tty_struct *tty = current->tty;
 	short cnt, disc;
 
 	/*
@@ -840,7 +985,7 @@
 		transfer_from[cnt] = NODQUOT;
 		transfer_to[cnt] = NODQUOT;
 
-		if (!has_quota_enabled(inode->i_dev, cnt))
+		if (!sb_has_quota_enabled(inode->i_sb, cnt))
 			continue;
 
 		switch (cnt) {
@@ -858,8 +1003,8 @@
 				break;
 		}
 
-		if (check_idq(transfer_to[cnt], cnt, 1) == NO_QUOTA ||
-		    check_bdq(transfer_to[cnt], cnt, blocks) == NO_QUOTA) {
+		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]);
@@ -883,10 +1028,12 @@
 			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);
 		}
+
 		if (inode->i_dquot[cnt] != NODQUOT) {
 			dqput(transfer_from[cnt]);
 			dqput(inode->i_dquot[cnt]);
@@ -896,16 +1043,24 @@
 			dqput(transfer_to[cnt]);
 		}
 	}
+
 	return(QUOTA_OK);
 }
 
-void dquot_init(void)
+
+__initfunc(void dquot_init_hash(void))
 {
-	printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\r\n",
-	       __DQUOT_VERSION__);
-	memset(hash_table, 0, sizeof(hash_table));
+	printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
+
+	dquot_cachep = kmem_cache_create("dquot", sizeof(struct dquot),
+					 sizeof(unsigned long) * 4,
+					 SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+	if (!dquot_cachep)
+		panic("Cannot create dquot SLAB cache\n");
+
+	memset(dquot_hash, 0, sizeof(dquot_hash));
 	memset((caddr_t)&dqstats, 0, sizeof(dqstats));
-	first_dquot = NODQUOT;
 }
 
 /*
@@ -921,6 +1076,30 @@
 	dquot_transfer
 };
 
+static inline void set_enable_flags(struct vfsmount *vfsmnt, short type)
+{
+	switch (type) {
+		case USRQUOTA:
+			vfsmnt->mnt_dquot.flags |= DQUOT_USR_ENABLED;
+			break;
+		case GRPQUOTA:
+			vfsmnt->mnt_dquot.flags |= DQUOT_GRP_ENABLED;
+			break;
+	}
+}
+
+static inline void reset_enable_flags(struct vfsmount *vfsmnt, short type)
+{
+	switch (type) {
+		case USRQUOTA:
+			vfsmnt->mnt_dquot.flags &= ~DQUOT_USR_ENABLED;
+			break;
+		case GRPQUOTA:
+			vfsmnt->mnt_dquot.flags &= ~DQUOT_GRP_ENABLED;
+			break;
+	}
+}
+
 /*
  * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  */
@@ -929,25 +1108,28 @@
 	struct vfsmount *vfsmnt;
 	short cnt;
 
-	if ( !(vfsmnt = lookup_vfsmnt(dev)) )
-		return -ENODEV;
-
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 		if (type != -1 && cnt != type)
 			continue;
-		if (vfsmnt->mnt_quotas[cnt] == (struct file *)NULL)
-		{
-			if(type == -1)
-				continue;
-			return -ESRCH;
-		}
+
+		if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL ||
+                    is_enabled(vfsmnt, cnt) == 0 ||
+                    vfsmnt->mnt_sb == (struct super_block *)NULL) 
+			continue;
+
 		vfsmnt->mnt_sb->dq_op = (struct dquot_operations *)NULL;
+
 		reset_dquot_ptrs(dev, cnt);
 		invalidate_dquots(dev, cnt);
-		fput(vfsmnt->mnt_quotas[cnt]);
-		vfsmnt->mnt_quotas[cnt] = (struct file *)NULL;
-		vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)NULL;
+
+		fput(vfsmnt->mnt_dquot.files[cnt]);
+
+		reset_enable_flags(vfsmnt, cnt);
+		vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL;
+		vfsmnt->mnt_dquot.inode_expire[cnt] = 0;
+		vfsmnt->mnt_dquot.block_expire[cnt] = 0;
 	}
+
 	return(0);
 }
 
@@ -962,11 +1144,11 @@
 	int error;
 
 	vfsmnt = lookup_vfsmnt(dev);
-	if (vfsmnt == NULL)
+	if (vfsmnt == (struct vfsmount *)NULL)
 		return -ENODEV;
 
-	if (vfsmnt->mnt_quotas[type] != NULL)
-		return -EBUSY;
+	if (is_enabled(vfsmnt, type))
+		return(-EBUSY);
 
 	tmp = getname(path);
 	error = PTR_ERR(tmp);
@@ -986,8 +1168,13 @@
 		return -EACCES;
 	}
 
+	if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0) {
+		iput(inode);
+		return(-EINVAL);
+	}
+
 	filp = get_empty_filp();
-	if (filp != NULL) {
+	if (filp != (struct file *)NULL) {
 		filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
 		filp->f_flags = O_RDWR;
 		filp->f_dentry = dentry;
@@ -1000,14 +1187,18 @@
 				if (filp->f_op && filp->f_op->open)
 					error = filp->f_op->open(inode, filp);
 				if (!error) {
-					vfsmnt->mnt_quotas[type] = filp;
+					set_enable_flags(vfsmnt, type);
+					vfsmnt->mnt_dquot.files[type] = filp;
+
 					dquot = dqget(dev, 0, type);
-					vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
-					vfsmnt->mnt_bexp[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
+					vfsmnt->mnt_dquot.inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
+					vfsmnt->mnt_dquot.block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
 					dqput(dquot);
+
 					vfsmnt->mnt_sb->dq_op = &dquot_operations;
 					add_dquot_ref(dev, type);
-					return 0;
+
+					return(0);
 				}
 				put_write_access(inode);
 			}
@@ -1016,8 +1207,10 @@
 		put_filp(filp);
 	} else
 		error = -EMFILE;
+
 	dput(dentry);
-	return error;
+
+	return(error);
 }
 
 /*
@@ -1045,17 +1238,17 @@
 			break;
 		case Q_GETQUOTA:
 			if (((type == USRQUOTA && current->uid != id) ||
-			     (type == GRPQUOTA && in_group_p(id))) && 
-			    !capable(CAP_SYS_ADMIN))
+			     (type == GRPQUOTA && current->gid != id)) &&
+			    !capable(CAP_SYS_RESOURCE))
 				goto out;
 			break;
 		default:
-			if (!capable(CAP_SYS_ADMIN))
+			if (!capable(CAP_SYS_RESOURCE))
 				goto out;
 	}
 
 	ret = -EINVAL;
-	dev = NODEV;
+	dev = 0;
 	if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
 		mode_t mode;
 		struct dentry * dentry;
@@ -1098,12 +1291,17 @@
 			goto out;
 		case Q_GETSTATS:
 			ret = get_stats(addr);
+			goto out;
+		case Q_RSQUASH:
+			ret = quota_root_squash(dev, type, (int *) addr);
+			goto out;
 		default:
 			goto out;
 	}
 
 	flags |= QUOTA_SYSCALL;
-	if (has_quota_enabled(dev, type))
+
+	if (dev_has_quota_enabled(dev, type))
 		ret = set_dqblk(dev, id, type, flags, (struct dqblk *) addr);
 	else
 		ret = -ESRCH;
diff -u --recursive --new-file v2.1.100/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.1.100/linux/fs/ext2/balloc.c	Thu May  7 22:51:53 1998
+++ linux/fs/ext2/balloc.c	Fri May  8 17:54:39 1998
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/locks.h>
+#include <linux/quotaops.h>
 
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
@@ -321,8 +322,7 @@
 				      "bit already cleared for block %lu", 
 				      block);
 		else {
-			if (sb->dq_op)
-				sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize));
+			DQUOT_FREE_BLOCK(sb, inode, 1);
 			gdp->bg_free_blocks_count =
 				cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
 			es->s_free_blocks_count =
@@ -524,12 +524,7 @@
 	/*
 	 * Check quota for allocation of this block.
 	 */
-	if (sb->dq_op)
-		if (sb->dq_op->alloc_block (inode, fs_to_dq_blocks(1, sb->s_blocksize))) {
-			unlock_super (sb);
-			*err = -EDQUOT;
-			return 0;
-		}
+	DQUOT_ALLOC_BLOCK(sb, inode, 1);
 
 	tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + le32_to_cpu(es->s_first_data_block);
 
@@ -544,8 +539,7 @@
 	if (ext2_set_bit (j, bh->b_data)) {
 		ext2_warning (sb, "ext2_new_block",
 			      "bit already set for block %d", j);
-		if (sb->dq_op)
-			sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize));
+		DQUOT_FREE_BLOCK(sb, inode, 1);
 		goto repeat;
 	}
 
@@ -566,12 +560,9 @@
 		for (k = 1;
 		     k < prealloc_goal && (j + k) < EXT2_BLOCKS_PER_GROUP(sb);
 		     k++) {
-			if (sb->dq_op)
-				if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(1, sb->s_blocksize)))
-					break;
+			DQUOT_PREALLOC_BLOCK(sb, inode, 1);
 			if (ext2_set_bit (j + k, bh->b_data)) {
-				if (sb->dq_op)
-					sb->dq_op->free_block(inode, fs_to_dq_blocks(1, sb->s_blocksize));
+				DQUOT_FREE_BLOCK(sb, inode, 1);
  				break;
 			}
 			(*prealloc_count)++;
diff -u --recursive --new-file v2.1.100/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.1.100/linux/fs/ext2/ialloc.c	Mon Apr  6 17:41:00 1998
+++ linux/fs/ext2/ialloc.c	Fri May  8 17:54:39 1998
@@ -33,6 +33,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
+#include <linux/quotaops.h>
 
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
@@ -231,8 +232,7 @@
 	is_directory = S_ISDIR(inode->i_mode);
 
 	/* Do this BEFORE marking the inode not in use */
-	if (sb->dq_op)
-		sb->dq_op->free_inode (inode, 1);
+	DQUOT_FREE_INODE(sb, inode);
 	clear_inode (inode);
 
 	/* Ok, now we can actually update the inode bitmaps.. */
@@ -493,17 +493,7 @@
 	inc_inode_version (inode, gdp, mode);
 
 	unlock_super (sb);
-	if (sb->dq_op) {
-		sb->dq_op->initialize (inode, -1);
-		if (sb->dq_op->alloc_inode (inode, 1)) {
-			sb->dq_op->drop (inode);
-			inode->i_nlink = 0;
-			iput (inode);
-			*err = -EDQUOT;
-			return NULL;
-		}
-		inode->i_flags |= S_WRITE;
-	}
+	DQUOT_ALLOC_INODE(sb, inode);
 	ext2_debug ("allocating inode %lu\n", inode->i_ino);
 
 	*err = 0;
diff -u --recursive --new-file v2.1.100/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.1.100/linux/fs/ext2/namei.c	Thu May  7 22:51:53 1998
+++ linux/fs/ext2/namei.c	Fri May  8 17:54:39 1998
@@ -28,6 +28,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
+#include <linux/quotaops.h>
 
 
 /*
@@ -625,8 +626,7 @@
 		goto end_rmdir;
 
 	inode = dentry->d_inode;
-	if (inode->i_sb->dq_op)
-		inode->i_sb->dq_op->initialize (inode, -1);
+	DQUOT_INIT(inode);
 
 	retval = -EPERM;
 	if ((dir->i_mode & S_ISVTX) && 
@@ -715,8 +715,7 @@
 		goto end_unlink;
 
 	inode = dentry->d_inode;
-	if (inode->i_sb->dq_op)
-		inode->i_sb->dq_op->initialize (inode, -1);
+	DQUOT_INIT(inode);
 
 	retval = -EPERM;
 	if (S_ISDIR(inode->i_mode))
@@ -936,8 +935,7 @@
 			brelse (new_bh);
 			new_bh = NULL;
 		} else {
-			if (new_inode->i_sb->dq_op)
-				new_inode->i_sb->dq_op->initialize (new_inode, -1);
+			DQUOT_INIT(new_inode);
 		}
 	}
 	retval = 0;
diff -u --recursive --new-file v2.1.100/linux/fs/file_table.c linux/fs/file_table.c
--- v2.1.100/linux/fs/file_table.c	Sun Oct 12 10:10:40 1997
+++ linux/fs/file_table.c	Fri May  8 17:54:39 1998
@@ -5,7 +5,6 @@
  *  Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -122,43 +121,3 @@
 	else
 		return 0;
 }
-
-#ifdef CONFIG_QUOTA
-
-void add_dquot_ref(kdev_t dev, short type)
-{
-	struct file *filp;
-
-	for (filp = inuse_filps; filp; filp = filp->f_next) {
-		struct inode * inode;
-		if (!filp->f_dentry)
-			continue;
-		inode = filp->f_dentry->d_inode;
-		if (!inode || inode->i_dev != dev)
-			continue;
-		if (filp->f_mode & FMODE_WRITE && inode->i_sb->dq_op) {
-			inode->i_sb->dq_op->initialize(inode, type);
-			inode->i_flags |= S_WRITE;
-		}
-	}
-}
-
-void reset_dquot_ptrs(kdev_t dev, short type)
-{
-	struct file *filp;
-
-	for (filp = inuse_filps; filp; filp = filp->f_next) {
-		struct inode * inode;
-		if (!filp->f_dentry)
-			continue;
-		inode = filp->f_dentry->d_inode;
-		if (!inode || inode->i_dev != dev)
-			continue;
-		if (IS_WRITABLE(inode)) {
-			inode->i_dquot[type] = NODQUOT;
-			inode->i_flags &= ~S_WRITE;
-		}
-	}
-}
-
-#endif
diff -u --recursive --new-file v2.1.100/linux/fs/inode.c linux/fs/inode.c
--- v2.1.100/linux/fs/inode.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/inode.c	Fri May  8 17:54:39 1998
@@ -8,6 +8,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/dcache.h>
+#include <linux/quotaops.h>
 
 /*
  * New inode.c implementation.
@@ -190,6 +191,7 @@
 			continue;
 
 		sync_list(&sb->s_dirty);
+
 		if (dev)
 			break;
 	}
@@ -223,8 +225,8 @@
 	if (inode->i_nrpages)
 		truncate_inode_pages(inode, 0);
 	wait_on_inode(inode);
-	if (IS_WRITABLE(inode) && inode->i_sb && inode->i_sb->dq_op)
-		inode->i_sb->dq_op->drop(inode);
+	if (IS_QUOTAINIT(inode))
+		DQUOT_DROP(inode);
 	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->clear_inode)
 		inode->i_sb->s_op->clear_inode(inode);
 
diff -u --recursive --new-file v2.1.100/linux/fs/namei.c linux/fs/namei.c
--- v2.1.100/linux/fs/namei.c	Thu May  7 22:51:53 1998
+++ linux/fs/namei.c	Fri May  8 17:54:39 1998
@@ -22,10 +22,12 @@
 #include <linux/proc_fs.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/quotaops.h>
 
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 #include <asm/semaphore.h>
+#include <asm/spinlock.h>
 #include <asm/namei.h>
 
 /* This can be removed after the beta phase. */
@@ -84,48 +86,48 @@
  * semantics.  See the comments in "open_namei" and "do_link" below.
  */
 
-static char * quicklist = NULL;
-static int quickcount = 0;
-struct semaphore quicklock = MUTEX;
+char * getname_quicklist = NULL;
+int getname_quickcount = 0;
+spinlock_t getname_quicklock = SPIN_LOCK_UNLOCKED;
 
 /* Tuning: increase locality by reusing same pages again...
- * if quicklist becomes too long on low memory machines, either a limit
+ * if getname_quicklist becomes too long on low memory machines, either a limit
  * should be added or after a number of cycles some pages should
  * be released again ...
  */
 static inline char * get_page(void)
 {
 	char * res;
-	down(&quicklock);
-	res = quicklist;
+	spin_lock(&getname_quicklock);
+	res = getname_quicklist;
 	if (res) {
 #ifdef DEBUG
 		char * tmp = res;
 		int i;
-		for(i=0; i<quickcount; i++)
+		for(i=0; i<getname_quickcount; i++)
 			tmp = *(char**)tmp;
 		if (tmp)
 			printk("bad quicklist %x\n", (int)tmp);
 #endif
-		quicklist = *(char**)res;
-		quickcount--;
+		getname_quicklist = *(char**)res;
+		getname_quickcount--;
 	}
-	else
+	spin_unlock(&getname_quicklock);
+	if (!res)
 		res = (char*)__get_free_page(GFP_KERNEL);
-	up(&quicklock);
 	return res;
 }
 
 inline void putname(char * name)
 {
 	if (name) {
-		down(&quicklock);
-		*(char**)name = quicklist;
-		quicklist = name;
-		quickcount++;
-		up(&quicklock);
+		spin_lock(&getname_quicklock);
+		*(char**)name = getname_quicklist;
+		getname_quicklist = name;
+		getname_quickcount++;
+		spin_unlock(&getname_quicklock);
 	}
-	/* if a quicklist limit is necessary to introduce, call
+	/* if a getname_quicklist limit is necessary to introduce, call
 	 * free_page((unsigned long) name);
 	 */
 }
@@ -573,8 +575,7 @@
 		else if (!dir->d_inode->i_op || !dir->d_inode->i_op->create)
 			error = -EACCES;
 		else if ((error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC)) == 0) {
-			if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-				dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+			DQUOT_INIT(dir->d_inode);
 			error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode);
 			/* Don't check for write permission, don't truncate */
 			acc_mode = 0;
@@ -637,8 +638,7 @@
 		 */
 		error = locks_verify_locked(inode);
 		if (!error) {
-			if (inode->i_sb && inode->i_sb->dq_op)
-				inode->i_sb->dq_op->initialize(inode, -1);
+			DQUOT_INIT(inode);
 			
 			error = do_truncate(dentry, 0);
 		}
@@ -647,8 +647,7 @@
 			goto exit;
 	} else
 		if (flag & FMODE_WRITE)
-			if (inode->i_sb && inode->i_sb->dq_op)
-				inode->i_sb->dq_op->initialize(inode, -1);
+			DQUOT_INIT(inode);
 
 	return dentry;
 
@@ -690,8 +689,7 @@
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->mknod)
 		goto exit_lock;
 
-	if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-		dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+	DQUOT_INIT(dir->d_inode);
 	error = dir->d_inode->i_op->mknod(dir->d_inode, dentry, mode, dev);
 	retval = ERR_PTR(error);
 	if (!error)
@@ -775,8 +773,7 @@
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->mkdir)
 		goto exit_lock;
 
-	if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-		dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+	DQUOT_INIT(dir->d_inode);
 	mode &= 0777 & ~current->fs->umask;
 	error = dir->d_inode->i_op->mkdir(dir->d_inode, dentry, mode);
 
@@ -848,8 +845,7 @@
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->rmdir)
 		goto exit_lock;
 
-	if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-		dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+	DQUOT_INIT(dir->d_inode);
 
 	if (dentry->d_count > 1)
 		shrink_dcache_parent(dentry);
@@ -924,8 +920,7 @@
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink)
 		goto exit_lock;
 
-	if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-		dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+	DQUOT_INIT(dir->d_inode);
 
 	error = dir->d_inode->i_op->unlink(dir->d_inode, dentry);
 
@@ -986,8 +981,7 @@
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->symlink)
 		goto exit_lock;
 
-	if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-		dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+	DQUOT_INIT(dir->d_inode);
 	error = dir->d_inode->i_op->symlink(dir->d_inode, dentry, oldname);
 
 exit_lock:
@@ -1082,8 +1076,7 @@
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->link)
 		goto exit_lock;
 
-	if (dir->d_inode->i_sb && dir->d_inode->i_sb->dq_op)
-		dir->d_inode->i_sb->dq_op->initialize(dir->d_inode, -1);
+	DQUOT_INIT(dir->d_inode);
 	error = dir->d_inode->i_op->link(old_dentry, dir->d_inode, new_dentry);
 
 exit_lock:
@@ -1207,8 +1200,8 @@
 	if (!old_dir->d_inode->i_op || !old_dir->d_inode->i_op->rename)
 		goto exit_lock;
 
-	if (new_dir->d_inode->i_sb && new_dir->d_inode->i_sb->dq_op)
-		new_dir->d_inode->i_sb->dq_op->initialize(new_dir->d_inode, -1);
+	DQUOT_INIT(old_dir->d_inode);
+	DQUOT_INIT(new_dir->d_inode);
 	error = old_dir->d_inode->i_op->rename(old_dir->d_inode, old_dentry,
 					       new_dir->d_inode, new_dentry);
 
diff -u --recursive --new-file v2.1.100/linux/fs/nametrans.c linux/fs/nametrans.c
--- v2.1.100/linux/fs/nametrans.c	Mon Dec  1 10:34:11 1997
+++ linux/fs/nametrans.c	Wed Dec 31 16:00:00 1969
@@ -1,310 +0,0 @@
-/*
- * $Id: nametrans.c,v 1.2 1997/06/04 23:45:44 davem Exp $
- *
- * linux/fs/nametrans.c - context-dependend filename suffixes.
- * Copyright (C) 1997, Thomas Schoebel-Theuer,
- * <schoebel@informatik.uni-stuttgart.de>.
- *
- * translates names of the form "filename#host=myhost#" to "filename"
- * as if both names were hardlinked to the same file.
- * benefit: diskless clients can mount the / filesystem of the
- * server if /etc/fstab (and other config files) are organized using
- * context suffixes.
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/utsname.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/uaccess.h>
-#include <linux/nametrans.h>
-
-char  nametrans_txt[MAX_DEFAULT_TRANSLEN] = "";
-static struct translations * global_trans = NULL;
-static int default_trans = 1;
-static const char version[] = "revision: 2.3 <schoebel@informatik.uni-stuttgart.de>";
-int translations_dirty = 1;
-static char * transl_names[] = {
-#ifdef CONFIG_TR_NODENAME
-  "host=",        system_utsname.nodename,
-#endif
-#ifdef CONFIG_TR_KERNNAME
-  "kname=",  CONFIG_KERNNAME,
-#endif
-#ifdef CONFIG_TR_KERNTYPE
-  "ktype=",  CONFIG_KERNTYPE,
-#endif
-#ifdef CONFIG_TR_MACHINE
-  "machine=",     system_utsname.machine,
-#endif
-#ifdef CONFIG_TR_SYSNAME
-  "system=",      system_utsname.sysname,
-#endif
-  0, 0
-};
-
-/* Convert and do syntax checking. */
-static void convert(char * txt, struct translations * res)
-{
-	char * tmp = txt;
-	char * space = (char*)res + sizeof(struct translations);
-
-	res->count = 0;
-	while(*tmp) {
-		struct qstr * name = &res->name[res->count];
-		struct qstr * c_name = &res->c_name[res->count];
-		int len;
-		char * p = tmp;
-
-		if(*p++ != '#')
-			goto next;
-		while(*p && *p != '=' && *p != ':')
-			p++;
-		if(*p != '=')
-			goto next;
-		p++;
-		len = (unsigned long)p - (unsigned long)tmp;
-		c_name->name = space;
-		memcpy(space, tmp, len);
-		memcpy(space + len, "CREATE#", 8);
-		c_name->len = len + 7;
-		if(c_name->len >= MAX_TRANS_SUFFIX)
-			goto next;
-		while(*p && *p != '#' && *p != ':')
-			p++;
-		if(*p != '#')
-			goto next;
-		p++;
-		if(*p != ':' && *p)
-			goto next;
-		space += len + 8;
-		name->len = len = (unsigned long)p - (unsigned long)tmp;
-		if(len >= MAX_TRANS_SUFFIX)
-			goto next;
-		name->name = space;
-		memcpy(space, tmp, len);
-		space[len] = '\0';
-		space += len + 1;
-		res->count++;
-		if(res->count >= MAX_TRANSLATIONS ||
-		   (unsigned long)space - (unsigned long)res >= PAGE_SIZE-2*MAX_TRANS_SUFFIX)
-			return;
-	next:
-		while(*p && *p++ != ':') ;
-		tmp = p;
-	}
-}
-
-static inline void trans_to_string(struct translations * trans, char * buf, int maxlen)
-{
-	int i;
-
-	for(i = 0; i < trans->count; i++) {
-		int len = trans->name[i].len;
-		if(len < maxlen) {
-			memcpy(buf, trans->name[i].name, len);
-			buf += len;
-			maxlen -= len;
-			*buf++ = ':';
-			maxlen--;
-		}
-	}
-	buf--;
-	*buf = '\0';
-}
-
-static inline void default_nametrans(char * buf)
-{
-	char * res = buf;
-	char ** entry;
-	char * ptr;
-
-	for (entry = transl_names; *entry; entry++) {
-		*res++ = '#';
-		for(ptr = *entry; *ptr; ptr++)
-			*res++ = *ptr;
-		entry++;
-		for(ptr = *entry; *ptr; ptr++)
-			*res++ = *ptr;
-		*res++ = '#';
-		*res++ = ':';
-	}
-	res--;
-	*res = '\0';
-}
-
-void nametrans_setup(char * line)
-{
-	if(line) {
-		default_trans = (!line[0]);
-		if(!global_trans) {
-			/* This can happen at boot time, and there is no chance
-			 * to allocate memory at this early stage.
-			 */
-			strncpy(nametrans_txt, line, MAX_DEFAULT_TRANSLEN);
-		} else {
-			if(default_trans) {
-				default_nametrans(nametrans_txt);
-				line = nametrans_txt;
-			}
-			convert(line, global_trans);
-
-			/* Show what really was recognized after parsing... */
-			trans_to_string(global_trans, nametrans_txt, MAX_DEFAULT_TRANSLEN);
-		}
-	}
-}
-
-/* If the _first_ environment variable is "NAMETRANS", return
- * a pointer to the list of appendices.
- * You can set the first environment variable using
- * 'env - NAMETRANS=... "`env`" command ...'
- */
-char* env_transl(void)
-{
-	char* env;
-	int i;
-
-	if(current && current->mm && (env = (char*)current->mm->env_start)
-	   && !segment_eq(get_ds(), get_fs())
-	   && current->mm->env_end>=current->mm->env_start+10
-	   && !verify_area(VERIFY_READ,env,10)) {
-		for(i=0; i<10; i++) {
-			char c;
-
-			get_user(c, env++);
-			if(c != "NAMETRANS="[i])
-				return 0;
-		}
-		return env;
-	}
-	return 0;
-}
-
-/* If name has the correct suffix "#keyword=correct_context#",
- * return position of the suffix, else 0.
- */
-char *testname(int restricted, char* name)
-{
-	char * ptr = name;
-	char * cut;
-	char * env;
-	struct translations * trans;
-	int i, len;
-	char c, tmp;
-	
-	env = env_transl();
-#ifdef CONFIG_TRANS_RESTRICT
-	if(!env && restricted)
-		goto done;
-#else
-	(void)restricted; /* inhibit parameter usage warning */
-#endif
-	if(get_user(c, ptr))
-		goto done;
-	while(c && c != '#') {
-		ptr++;
-		__get_user(c, ptr);
-	}
-	if(!c)
-		goto done;
-	cut = ptr++;
-	if(get_user(c, ptr))
-		goto done;
-	while (c && c != '#') {
-		ptr++;
-		get_user(c, ptr);
-	}
-	if(!c)
-		goto done;
-	get_user(tmp, ptr);
-	if(tmp)
-		goto done;
-	trans = get_translations(env);
-	len = (unsigned long)ptr - (unsigned long)cut;
-	for(i = 0; i < trans->count; i++)
-		if(trans->name[i].len == len) {
-			const char * p1 = cut;
-			const char * p2 = trans->name[i].name;
-			get_user(c, p1);
-			while(c && c == *p2++) {
-				p1++;
-				get_user(c, p1);
-			}
-			if(!c)
-				return cut;
-		}
-done:
-	return NULL;
-}
-
-static inline void check_dirty(void)
-{
-	if(translations_dirty && default_trans) {
-		nametrans_setup("");
-		translations_dirty = 0;
-	}
-}
-
-struct translations * get_translations(char * env)
-{
-	struct translations * res;
-
-	if(env) {
-		char * env_txt = (char*)__get_free_page(GFP_KERNEL);
-
-		strncpy_from_user(env_txt, env, PAGE_SIZE);
-		res = (struct translations *)__get_free_page(GFP_KERNEL);
-		convert(env_txt, res);
-		free_page((unsigned long)env_txt);
-	} else {
-		check_dirty();
-		res = global_trans;
-	}
-	return res;
-}
-
-int nametrans_dostring(ctl_table * table, int write, struct file * filp,
-		       void * buffer, size_t * lenp)
-{
-	int res;
-	check_dirty();
-	res = proc_dostring(table, write, filp, buffer, lenp);
-	if(!res && write)
-		nametrans_setup(nametrans_txt);
-
-	return res;
-}
-
-int nametrans_string(ctl_table * table, int * name, int nlen,
-		     void * oldval, size_t * oldlenp,
-		     void * newval, size_t newlen, void ** context)
-{
-	int res;
-	check_dirty();
-	res = sysctl_string(table, name, nlen, oldval, oldlenp, newval, newlen, context);
-	if(!res && newval && newlen)
-		nametrans_setup(nametrans_txt);
-
-	return res;
-}
-
-void init_nametrans(void)
-{
-	if(!global_trans)
-		global_trans = (struct translations*)__get_free_page(GFP_KERNEL);
-	if(!global_trans) {
-		printk("NAMETRANS: No free memory\n");
-		return;
-	}
-	nametrans_setup(nametrans_txt);
-
-	/* Notify user for the default/supplied translations.
-	 * Extremely useful for finding translation problems.
-	 */
-	printk("Nametrans %s\nNametrans %s: %s\n", version,
-	       default_trans ? "default translations" : "external parameter",
-	       nametrans_txt);
-}
diff -u --recursive --new-file v2.1.100/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.100/linux/fs/nfsd/vfs.c	Fri Jan 30 11:28:08 1998
+++ linux/fs/nfsd/vfs.c	Fri May  8 17:54:39 1998
@@ -31,6 +31,7 @@
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
+#include <linux/quotaops.h>
 
 #if LINUX_VERSION_CODE >= 0x020100
 #include <asm/uaccess.h>
@@ -289,6 +290,9 @@
 	filp->f_mode  = wflag? FMODE_WRITE : FMODE_READ;
 	filp->f_dentry = dentry;
 
+	if (wflag)
+		DQUOT_INIT(inode);
+
 	err = 0;
 	if (filp->f_op && filp->f_op->open) {
 		err = filp->f_op->open(inode, filp);
@@ -325,8 +329,10 @@
 			dentry->d_parent->d_name.name, dentry->d_name.name);
 	if (filp->f_op && filp->f_op->release)
 		filp->f_op->release(inode, filp);
-	if (filp->f_mode & FMODE_WRITE)
+	if (filp->f_mode & FMODE_WRITE) {
 		put_write_access(inode);
+		DQUOT_DROP(inode);
+	}
 }
 
 /*
@@ -604,6 +610,7 @@
 
 	/* Looks good, lock the directory. */
 	fh_lock(fhp);
+	DQUOT_INIT(dirp);
 	switch (type) {
 	case S_IFREG:
 		err = dirp->i_op->create(dirp, dchild, iap->ia_mode);
@@ -617,6 +624,7 @@
 		err = dirp->i_op->mknod(dirp, dchild, iap->ia_mode, rdev);
 		break;
 	}
+	DQUOT_DROP(dirp);
 	fh_unlock(fhp);
 
 	if (err < 0)
@@ -674,6 +682,7 @@
 
 	/* Things look sane, lock and do it. */
 	fh_lock(fhp);
+	DQUOT_INIT(inode);
 	newattrs.ia_size = size;
 	newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 	err = notify_change(dentry, &newattrs);
@@ -683,6 +692,7 @@
 			inode->i_op->truncate(inode);
 	}
 	put_write_access(inode);
+	DQUOT_DROP(inode);
 	fh_unlock(fhp);
 out_nfserr:
 	if (err)
@@ -771,7 +781,9 @@
 	err = -EEXIST;
 	if (!dnew->d_inode) {
 		fh_lock(fhp);
+		DQUOT_INIT(dirp);
 		err = dirp->i_op->symlink(dirp, dnew, path);
+		DQUOT_DROP(dirp);
 		fh_unlock(fhp);
 		if (!err) {
 			if (EX_ISSYNC(fhp->fh_export))
@@ -840,7 +852,9 @@
 		goto dput_and_out;
 
 	fh_lock(ffhp);
+	DQUOT_INIT(dirp);
 	err = dirp->i_op->link(dold, dirp, dnew);
+	DQUOT_DROP(dirp);
 	fh_unlock(ffhp);
 
 	if (!err && EX_ISSYNC(ffhp->fh_export)) {
@@ -938,11 +952,16 @@
 	nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
 	/* N.B. check for parent changes after locking?? */
 
+	DQUOT_INIT(fdir);
+	DQUOT_INIT(tdir);
 	err = fdir->i_op->rename(fdir, odentry, tdir, ndentry);
 	if (!err && EX_ISSYNC(tfhp->fh_export)) {
 		write_inode_now(fdir);
 		write_inode_now(tdir);
 	}
+	DQUOT_DROP(fdir);
+	DQUOT_DROP(tdir);
+
 	nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
 	dput(ndentry);
 
@@ -987,6 +1006,7 @@
 		goto out_nfserr;
 
 	fh_lock(fhp);
+	DQUOT_INIT(dirp);
 	if (type == S_IFDIR) {
 		err = -ENOTDIR;
 		if (dirp->i_op && dirp->i_op->rmdir)
@@ -996,6 +1016,7 @@
 		if (dirp->i_op && dirp->i_op->unlink)
 			err = dirp->i_op->unlink(dirp, rdentry);
 	}
+	DQUOT_DROP(dirp);
 	fh_unlock(fhp);
 
 	dput(rdentry);
diff -u --recursive --new-file v2.1.100/linux/fs/noquot.c linux/fs/noquot.c
--- v2.1.100/linux/fs/noquot.c	Mon Oct 28 04:21:41 1996
+++ linux/fs/noquot.c	Fri May  8 17:54:39 1998
@@ -1,79 +1,15 @@
-/*
- *	A Non implementation of disk quotas. Chainsawed from dquot.c by
- *	Alan Cox <alan@lxorguk.ukuu.org.uk>. This saves us memory without
- *	having zillions of #ifdefs (Or if it had been done right one
- *	
- *	QUOTA_OP(inode,func)
- *
- *	macro.)
+/* noquot.c: Quota stubs necessary for when quotas are not
+ *           compiled into the kernel.
  */
 
-#include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/types.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/mount.h>
-
-#include <asm/uaccess.h>
-
-#ifndef min
-#define min(a,b) ((a) < (b)) ? (a) : (b)
-#endif
-
-int sync_dquots(kdev_t dev, short type)
-{
-	return(0);
-}
-
-/*
- * Trash the cache for a certain type on a device.
- */
-
-void invalidate_dquots(kdev_t dev, short type)
-{
-}
-
-/*
- * Initialize pointer in an inode to the right dquots.
- */
-void dquot_initialize(struct inode *inode, short type)
-{
-}
-
-void dquot_drop(struct inode *inode)
-{
-}
-
-void dquot_init(void)
-{
-}
-
-/*
- * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
- */
+#include <linux/errno.h>
 
-int quota_off(kdev_t dev, short type)
-{
-	return(0);
-}
+int nr_dquots = 0, nr_free_dquots = 0;
+int max_dquots = 0;
 
-int quota_on(kdev_t dev, short type, char *path)
-{
-	return(-ENOPKG);
-}
-
-/*
- * Ok this is the systemcall interface, this communicates with
- * the userlevel programs. Currently this only supports diskquota
- * calls. Maybe we need to add the process quotas etc in the future.
- * But we probably better use rlimits for that.
- */
 asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
 {
-	return(-ENOPKG);
+	return(-ENOSYS);
 }
diff -u --recursive --new-file v2.1.100/linux/fs/open.c linux/fs/open.c
--- v2.1.100/linux/fs/open.c	Thu May  7 22:51:53 1998
+++ linux/fs/open.c	Fri May  8 17:54:39 1998
@@ -20,6 +20,7 @@
 #include <linux/file.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/quotaops.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -134,8 +135,7 @@
 				  length < inode->i_size ? length : inode->i_size,
 				  abs(inode->i_size - length));
 	if (!error) {
-		if (inode->i_sb && inode->i_sb->dq_op)
-			inode->i_sb->dq_op->initialize(inode, -1);
+		DQUOT_INIT(inode);
 		error = do_truncate(dentry, length);
 	}
 	put_write_access(inode);
@@ -552,16 +552,7 @@
 		newattrs.ia_mode &= ~S_ISGID;
 		newattrs.ia_valid |= ATTR_MODE;
 	}
-	if (inode->i_sb && inode->i_sb->dq_op) {
-		inode->i_sb->dq_op->initialize(inode, -1);
-		error = -EDQUOT;
-		if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
-			goto out;
-		error = notify_change(dentry, &newattrs);
-		if (error)
-			inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
-	} else
-		error = notify_change(dentry, &newattrs);
+	DQUOT_TRANSFER(dentry, newattrs);
 out:
 	return error;
 }
@@ -599,6 +590,7 @@
 	unlock_kernel();
 	return error;
 }
+
 
 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
 {
diff -u --recursive --new-file v2.1.100/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v2.1.100/linux/fs/proc/fd.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/proc/fd.c	Fri May  8 18:10:30 1998
@@ -4,6 +4,10 @@
  *  Copyright (C) 1991, 1992 Linus Torvalds
  *
  *  proc fd directory handling functions
+ *
+ *  01-May-98 Edgar Toernig <froese@gmx.de>
+ *	Added support for more than 256 fds.
+ *	Limit raised to 32768.
  */
 
 #include <linux/errno.h>
@@ -91,7 +95,7 @@
 			goto out;
 		fd *= 10;
 		fd += c;
-		if (fd & 0xffff0000)
+		if (fd & 0xffff8000)
 			goto out;
 	}
 
@@ -111,8 +115,7 @@
 	if (!file || !file->f_dentry)
 		goto out;
 
-	/* N.B. What happens if fd > 255?? */
-	ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd;
+	ino = (pid << 16) + PROC_PID_FD_DIR + fd;
 	inode = proc_get_inode(dir->i_sb, ino, NULL);
 	if (inode) {
 		d_add(dentry, inode);
@@ -144,7 +147,7 @@
 		goto out;
 
 	for (fd = filp->f_pos; fd < 2; fd++, filp->f_pos++) {
-		unsigned long ino = inode->i_ino;
+		ino = inode->i_ino;
 		if (fd)
 			ino = (ino & 0xffff0000) | PROC_PID_INO;
 		if (filldir(dirent, "..", fd+1, fd, ino) < 0)
@@ -176,7 +179,7 @@
 		/* Drop the task lock, as the filldir function may block */
 		read_unlock(&tasklist_lock);
 
-		ino = (pid << 16) + (PROC_PID_FD_DIR << 8) + fd;
+		ino = (pid << 16) + PROC_PID_FD_DIR + fd;
 		if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
 			goto out;
 
diff -u --recursive --new-file v2.1.100/linux/fs/proc/inode-alloc.txt linux/fs/proc/inode-alloc.txt
--- v2.1.100/linux/fs/proc/inode-alloc.txt	Wed Dec 31 16:00:00 1969
+++ linux/fs/proc/inode-alloc.txt	Fri May  8 18:10:30 1998
@@ -0,0 +1,50 @@
+Inode allocations in the proc-fs (hex-numbers):
+
+  00000000		reserved
+  00000001-00000fff	static entries
+       001		root-ino
+       002		load-avg
+       003		uptime
+       ...
+       080		net/*
+       ...
+       100		scsi/*
+       ...
+       xxx		mca/*
+       ...
+       yyy		bus/*
+       ...
+       fff		end
+
+  00001000-00001fff	dynamic entries
+
+  00002000-00002fff	openprom entries
+
+  0001xxxx-7fffxxxx	pid-dir entries for pid 1-7fff
+      0000		unused
+      0001		unused
+      0002		pid
+      0003		pid/status
+       ...
+      0008		pid/fd
+       ...
+      00xx-00ff		unused
+      01xx		pid/fd/* for fd 0-ff
+       ...
+      01ff		end
+      0200-ffff		unused
+
+  80000000-ffffffff	unused
+
+
+
+New allocation:
+
+  00000000-0000ffff	unchanged
+
+  0001xxxx-7fffxxxx	pid-dir entries for pid 1-7fff
+      0000-00ff		unchanged
+      0100-7fff		unused
+      8000-ffff		pid/fd/* for fd 0-7fff
+
+  80000000-ffffffff	unchanged
diff -u --recursive --new-file v2.1.100/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.1.100/linux/fs/proc/inode.c	Thu May  7 22:51:54 1998
+++ linux/fs/proc/inode.c	Fri May  8 18:10:30 1998
@@ -382,10 +382,9 @@
 		inode->i_uid = p->euid;
 		inode->i_gid = p->egid;
 	}
-	switch (ino >> 8) {
+	if (ino & PROC_PID_FD_DIR) {
 		struct file * file;
-	case PROC_PID_FD_DIR:
-		ino &= 0xff;
+		ino &= 0x7fff;
 		file = fcheck_task(p, ino);
 		if (!file)
 			goto out_unlock;
diff -u --recursive --new-file v2.1.100/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.1.100/linux/fs/proc/link.c	Mon Apr  6 17:41:01 1998
+++ linux/fs/proc/link.c	Fri May  8 18:10:30 1998
@@ -111,10 +111,9 @@
 			goto out_unlock;
 		}
 		default:
-			switch (ino >> 8) {
+			if (ino & PROC_PID_FD_DIR) {
 				struct file * file;
-			case PROC_PID_FD_DIR:
-				ino &= 0xff;
+				ino &= 0x7fff;
 				file = fcheck_task(p, ino);
 				if (!file || !file->f_dentry)
 					goto out_unlock;
diff -u --recursive --new-file v2.1.100/linux/fs/read_write.c linux/fs/read_write.c
--- v2.1.100/linux/fs/read_write.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/read_write.c	Fri May  8 00:28:49 1998
@@ -79,7 +79,7 @@
 	return retval;
 }
 
-#if !defined(__alpha__) && !defined(__sparc_v9__)
+#if !defined(__alpha__)
 asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
 			  unsigned long offset_low, loff_t * result,
 			  unsigned int origin)
@@ -132,7 +132,6 @@
 	file = fget(fd);
 	if (!file)
 		goto bad_file;
-	ret = -EBADF;
 	if (!(file->f_mode & FMODE_READ))
 		goto out;
 	ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,
diff -u --recursive --new-file v2.1.100/linux/fs/super.c linux/fs/super.c
--- v2.1.100/linux/fs/super.c	Thu May  7 22:51:54 1998
+++ linux/fs/super.c	Fri May  8 17:54:39 1998
@@ -32,6 +32,7 @@
 #include <linux/smp_lock.h>
 #include <linux/fd.h>
 #include <linux/init.h>
+#include <linux/quotaops.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -109,7 +110,9 @@
 	lptr->mnt_sb = sb;
 	lptr->mnt_dev = sb->s_dev;
 	lptr->mnt_flags = sb->s_flags;
-	sema_init(&lptr->mnt_sem, 1);
+
+	sema_init(&lptr->mnt_dquot.semaphore, 1);
+	lptr->mnt_dquot.flags = 0;
 
 	/* N.B. Is it really OK to have a vfsmount without names? */
 	if (dev_name && !IS_ERR(tmp = getname(dev_name))) {
@@ -642,7 +645,11 @@
 	 * on the device. If the umount fails, too bad -- there
 	 * are no quotas running anymore. Just turn them on again.
 	 */
-	quota_off(dev, -1);
+	DQUOT_OFF(dev);
+
+#ifdef CONFIG_BSD_PROCESS_ACCT
+	(void) acct_auto_close(dev);
+#endif
 
 	/*
 	 * Shrink dcache, then fsync. This guarantees that if the
diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/delay.h linux/include/asm-alpha/delay.h
--- v2.1.100/linux/include/asm-alpha/delay.h	Fri Jun  2 03:51:16 1995
+++ linux/include/asm-alpha/delay.h	Fri May  8 00:29:45 1998
@@ -35,13 +35,4 @@
 	__delay(usecs);
 }
 
-/*
- * 64-bit integers means we don't have to worry about overflow as
- * on some other architectures..
- */
-extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
-{
-	return (a*b)/c;
-}
-
 #endif /* defined(__ALPHA_DELAY_H) */
diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/hardirq.h linux/include/asm-alpha/hardirq.h
--- v2.1.100/linux/include/asm-alpha/hardirq.h	Wed Apr  1 20:11:53 1998
+++ linux/include/asm-alpha/hardirq.h	Fri May  8 00:31:10 1998
@@ -4,6 +4,7 @@
 #include <linux/tasks.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
+#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0)
 
 #ifndef __SMP__
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/md.h linux/include/asm-alpha/md.h
--- v2.1.100/linux/include/asm-alpha/md.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/md.h	Fri May  8 00:17:13 1998
@@ -0,0 +1,13 @@
+/* $Id: md.h,v 1.1 1997/12/15 15:11:48 jj Exp $
+ * md.h: High speed xor_block operation for RAID4/5 
+ *
+ */
+ 
+#ifndef __ASM_MD_H
+#define __ASM_MD_H
+
+/* #define HAVE_ARCH_XORBLOCK */
+
+#define MD_XORBLOCK_ALIGNMENT	sizeof(long)
+
+#endif /* __ASM_MD_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-alpha/timex.h linux/include/asm-alpha/timex.h
--- v2.1.100/linux/include/asm-alpha/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,11 @@
+/*
+ * linux/include/asm-alpha/timex.h
+ *
+ * ALPHA architecture timex specifications
+ */
+#ifndef _ASMALPHA_TIMEX_H
+#define _ASMALPHA_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/a.out.h linux/include/asm-arm/arch-a5k/a.out.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/a.out.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/a.out.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-arm/arch-a5k/a.out.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifndef __ASM_ARCH_A_OUT_H
+#define __ASM_ARCH_A_OUT_H
+
+#ifdef __KERNEL__
+#define STACK_TOP		(0x01a00000)
+#define LIBRARY_START_TEXT	(0x00c00000)
+#endif
+
+#endif
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/dma.h linux/include/asm-arm/arch-a5k/dma.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/dma.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,101 @@
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS		0x03000000
+
+#ifdef KERNEL_ARCH_DMA
+
+static inline void arch_disable_dma (int dmanr)
+{
+    printk (dma_str, "arch_disable_dma", dmanr);
+}
+
+static inline void arch_enable_dma (int dmanr)
+{
+    printk (dma_str, "arch_enable_dma", dmanr);
+}
+
+static inline void arch_set_dma_addr (int dmanr, unsigned int addr)
+{
+    printk (dma_str, "arch_set_dma_addr", dmanr);
+}
+
+static inline void arch_set_dma_count (int dmanr, unsigned int count)
+{
+    printk (dma_str, "arch_set_dma_count", dmanr);
+}
+
+static inline void arch_set_dma_mode (int dmanr, char mode)
+{
+    printk (dma_str, "arch_set_dma_mode", dmanr);
+}
+
+static inline int arch_dma_count (int dmanr)
+{
+    printk (dma_str, "arch_dma_count", dmanr);
+    return 0;
+}
+
+#endif
+
+/* enable/disable a specific DMA channel */
+extern void enable_dma(unsigned int dmanr);
+
+static __inline__ void disable_dma(unsigned int dmanr)
+{
+    switch(dmanr) {
+	case 2:  disable_irq(64); break;
+	default: printk (dma_str, "disable_dma", dmanr); break;
+    }
+}
+
+/* Clear the 'DMA Pointer Flip Flop'.
+ * Write 0 for LSB/MSB, 1 for MSB/LSB access.
+ * Use this once to initialize the FF to a known state.
+ * After that, keep track of it. :-)
+ * --- In order to do that, the DMA routines below should ---
+ * --- only be used while interrupts are disabled! ---
+ */
+static __inline__ void clear_dma_ff(unsigned int dmanr)
+{
+    switch(dmanr) {
+	case 2:  break;
+	default: printk (dma_str, "clear_dma_ff", dmanr); break;
+    }
+}
+
+/* set mode (above) for a specific DMA channel */
+extern void set_dma_mode(unsigned int dmanr, char mode);
+
+/* Set only the page register bits of the transfer address.
+ * This is used for successive transfers when we know the contents of
+ * the lower 16 bits of the DMA current address register, but a 64k boundary
+ * may have been crossed.
+ */
+static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
+{
+    printk (dma_str, "set_dma_page", dmanr);
+}
+
+
+/* Set transfer address & page bits for specific DMA channel.
+ * Assumes dma flipflop is clear.
+ */
+extern void set_dma_addr(unsigned int dmanr, unsigned int addr);
+
+/* Set transfer size for a specific DMA channel.
+ */
+extern void set_dma_count(unsigned int dmanr, unsigned int count);
+
+/* Get DMA residue count. After a DMA transfer, this
+ * should return zero. Reading this while a DMA transfer is
+ * still in progress will return unpredictable results.
+ * If called before the channel has been used, it may return 1.
+ * Otherwise, it returns the number of _bytes_ left to transfer.
+ *
+ * Assumes DMA flip-flop is clear.
+ */
+extern int get_dma_residue(unsigned int dmanr);
+
+#endif /* _ASM_ARCH_DMA_H */
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/hardware.h linux/include/asm-arm/arch-a5k/hardware.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/hardware.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/hardware.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,81 @@
+/*
+ * linux/include/asm-arm/arch-a5k/hardware.h
+ *
+ * Copyright (C) 1996 Russell King.
+ *
+ * This file contains the hardware definitions of the A5000 series machines.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/*
+ * What hardware must be present
+ */
+#define HAS_IOC
+#define HAS_PCIO
+#define HAS_MEMC
+#define HAS_MEMC1A
+#define HAS_VIDC
+
+/*
+ * Optional hardware
+ */
+#define HAS_EXPMASK
+
+#ifndef __ASSEMBLER__
+
+/*
+ * for use with inb/outb
+ */
+#define VIDC_BASE		0x80100000
+#define IOCEC4IO_BASE		0x8009c000
+#define IOCECIO_BASE		0x80090000
+#define IOC_BASE		0x80080000
+#define MEMCECIO_BASE		0x80000000
+
+/*
+ * IO definitions
+ */
+#define EXPMASK_BASE		((volatile unsigned char *)0x03360000)
+#define IOEB_BASE		((volatile unsigned char *)0x03350050)
+#define PCIO_FLOPPYDMABASE	((volatile unsigned char *)0x0302a000)
+#define PCIO_BASE		0x03010000
+
+/*
+ * Mapping areas
+ */
+#define IO_END			0x03ffffff
+#define IO_BASE			0x03000000
+#define IO_SIZE			(IO_END - IO_BASE)
+#define IO_START		0x03000000
+
+/*
+ * Screen mapping information
+ */
+#define SCREEN2_END		0x02078000
+#define SCREEN2_BASE		0x02000000
+#define SCREEN1_END		SCREEN2_BASE
+#define SCREEN1_BASE		0x01f88000
+#define SCREEN_START		0x02000000
+
+/*
+ * RAM definitions
+ */
+#define MAPTOPHYS(a)		(((unsigned long)a & 0x007fffff) + PAGE_OFFSET)
+#define KERNTOPHYS(a)		((((unsigned long)(&a)) & 0x007fffff) + PAGE_OFFSET)
+#define GET_MEMORY_END(p)	(PAGE_OFFSET + (p->u1.s.page_size) * (p->u1.s.nr_pages))
+#define PARAMS_BASE		(PAGE_OFFSET + 0x7c000)
+#define KERNEL_BASE		(PAGE_OFFSET + 0x80000)
+
+#else
+
+#define IOEB_BASE		0x03350050
+#define IOC_BASE		0x03200000
+#define PCIO_FLOPPYDMABASE	0x0302a000
+#define PCIO_BASE		0x03010000
+#define IO_BASE			0x03000000
+
+#endif
+#endif
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/ide.h linux/include/asm-arm/arch-a5k/ide.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/ide.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,44 @@
+/*
+ * linux/include/asm-arm/arch-a5k/ide.h
+ *
+ * Copyright (c) 1997 Russell King
+ */
+
+static __inline__ int
+ide_default_irq(ide_ioreg_t base)
+{
+	if (base == 0x1f0)
+		return 11;
+	return 0;
+}
+
+static __inline__ ide_ioreg_t
+ide_default_io_base(int index)
+{
+	if (index == 0)
+		return 0x1f0;
+	return 0;
+}
+
+static __inline__ int
+ide_default_stepping(int index)
+{
+	return 0;
+}
+
+static __inline__ void
+ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq)
+{
+	ide_ioreg_t port = base;
+	ide_ioreg_t ctrl = base + 0x206;
+	int i;
+
+	i = 8;
+	while (i--) {
+		*p++ = port;
+		port += 1 << stepping;
+	}
+	*p++ = ctrl;
+	if (irq != NULL)
+		irq = 0;
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/io.h linux/include/asm-arm/arch-a5k/io.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/io.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,215 @@
+/*
+ * linux/include/asm-arm/arch-a5k/io.h
+ *
+ * Copyright (C) 1997 Russell King
+ *
+ * Modifications:
+ *  06-Dec-1997	RMK	Created.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define virt_to_bus(x)	((unsigned long)(x))
+#define bus_to_virt(x)	((void *)(x))
+
+/*
+ * This architecture does not require any delayed IO, and
+ * has the constant-optimised IO
+ */
+#undef	ARCH_IO_DELAY
+
+/*
+ * We use two different types of addressing - PC style addresses, and ARM
+ * addresses.  PC style accesses the PC hardware with the normal PC IO
+ * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
+ * and are translated to the start of IO.  Note that all addresses are
+ * shifted left!
+ */
+#define __PORT_PCIO(x)	(!((x) & 0x80000000))
+
+/*
+ * Dynamic IO functions - let the compiler
+ * optimize the expressions
+ */
+extern __inline__ void __outb (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"strb	%1, [%0, %2, lsl #2]"
+	: "=&r" (temp)
+	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+extern __inline__ void __outw (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"str	%1, [%0, %2, lsl #2]"
+	: "=&r" (temp)
+	: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+extern __inline__ void __outl (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"str	%1, [%0, %2, lsl #2]"
+	: "=&r" (temp)
+	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+#define DECLARE_DYN_IN(sz,fnsuffix,instr)					\
+extern __inline__ unsigned sz __in##fnsuffix (unsigned int port)		\
+{										\
+	unsigned long temp, value;						\
+	__asm__ __volatile__(							\
+	"tst	%2, #0x80000000\n\t"						\
+	"mov	%0, %4\n\t"							\
+	"addeq	%0, %0, %3\n\t"							\
+	"ldr" ##instr## "	%1, [%0, %2, lsl #2]"				\
+	: "=&r" (temp), "=r" (value)						\
+	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
+	: "cc");								\
+	return (unsigned sz)value;						\
+}
+
+extern __inline__ unsigned int __ioaddr (unsigned int port)			\
+{										\
+	if (__PORT_PCIO(port))							\
+		return (unsigned int)(PCIO_BASE + (port << 2));			\
+	else									\
+		return (unsigned int)(IO_BASE + (port << 2));			\
+}
+
+#define DECLARE_IO(sz,fnsuffix,instr)	\
+	DECLARE_DYN_IN(sz,fnsuffix,instr)
+
+DECLARE_IO(char,b,"b")
+DECLARE_IO(short,w,"")
+DECLARE_IO(long,l,"")
+
+#undef DECLARE_IO
+#undef DECLARE_DYN_IN
+
+/*
+ * Constant address IO functions
+ *
+ * These have to be macros for the 'J' constraint to work -
+ * +/-4096 immediate operand.
+ */
+#define __outbc(value,port)							\
+({										\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"strb	%0, [%1, %2]"						\
+		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"strb	%0, [%1, %2]"						\
+		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
+})
+
+#define __inbc(port)								\
+({										\
+	unsigned char result;							\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"ldrb	%0, [%1, %2]"						\
+		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"ldrb	%0, [%1, %2]"						\
+		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
+	result;									\
+})
+
+#define __outwc(value,port)							\
+({										\
+	unsigned long v = value;						\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]"						\
+		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
+	else									\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]"						\
+		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
+})
+
+#define __inwc(port)								\
+({										\
+	unsigned short result;							\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]"						\
+		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]"						\
+		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
+	result & 0xffff;							\
+})
+
+#define __outlc(v,p) __outwc((v),(p))
+
+#define __inlc(port)								\
+({										\
+	unsigned long result;							\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]"						\
+		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]"						\
+		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
+	result;									\
+})
+
+#define __ioaddrc(port)								\
+({										\
+	unsigned long addr;							\
+	if (__PORT_PCIO((port)))						\
+		addr = PCIO_BASE + ((port) << 2);				\
+	else									\
+		addr = IO_BASE + ((port) << 2);					\
+	addr;									\
+})
+
+/*
+ * Translated address IO functions
+ *
+ * IO address has already been translated to a virtual address
+ */
+#define outb_t(v,p)								\
+	(*(volatile unsigned char *)(p) = (v))
+
+#define inb_t(p)								\
+	(*(volatile unsigned char *)(p))
+
+#define outl_t(v,p)								\
+	(*(volatile unsigned long *)(p) = (v))
+
+#define inl_t(p)								\
+	(*(volatile unsigned long *)(p))
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/irq.h linux/include/asm-arm/arch-a5k/irq.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/irq.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,130 @@
+/*
+ * include/asm-arm/arch-a5k/irq.h
+ *
+ * Copyright (C) 1996 Russell King
+ *
+ * Changelog:
+ *   24-09-1996	RMK	Created
+ *   10-10-1996	RMK	Brought up to date with arch-sa110eval
+ *   22-10-1996	RMK	Changed interrupt numbers & uses new inb/outb macros
+ *   11-01-1998	RMK	Added mask_and_ack_irq
+ */
+
+#define BUILD_IRQ(s,n,m) \
+	void IRQ##n##_interrupt(void); \
+	void fast_IRQ##n##_interrupt(void); \
+	void bad_IRQ##n##_interrupt(void); \
+	void probe_IRQ##n##_interrupt(void);
+
+/*
+ * The timer is a special interrupt
+ */
+#define IRQ5_interrupt		timer_IRQ_interrupt
+
+#define IRQ_INTERRUPT(n)	IRQ##n##_interrupt
+#define FAST_INTERRUPT(n)	fast_IRQ##n##_interrupt
+#define BAD_INTERRUPT(n)	bad_IRQ##n##_interrupt
+#define PROBE_INTERRUPT(n)	probe_IRQ##n##_interrupt
+                                
+#define X(x) (x)|0x01, (x)|0x02, (x)|0x04, (x)|0x08, (x)|0x10, (x)|0x20, (x)|0x40, (x)|0x80
+#define Z(x) (x), (x), (x), (x), (x), (x), (x), (x)
+
+static __inline__ void mask_and_ack_irq(unsigned int irq)
+{
+	static const int addrmasks[] = {
+		X((IOC_IRQMASKA - IOC_BASE)<<18 | (1 << 15)),
+		X((IOC_IRQMASKB - IOC_BASE)<<18),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0),
+		X((IOC_FIQMASK - IOC_BASE)<<18),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0),
+		Z(0)
+	};
+	unsigned int temp1, temp2;
+
+	__asm__ __volatile__(
+"	ldr	%1, [%5, %3, lsl #2]\n"
+"	teq	%1, #0\n"
+"	beq	2f\n"
+"	ldrb	%0, [%2, %1, lsr #16]\n"
+"	bic	%0, %0, %1\n"
+"	strb	%0, [%2, %1, lsr #16]\n"
+"	tst	%1, #0x8000\n"			/* do we need an IRQ clear? */
+"	strneb	%1, [%2, %4]\n"
+"2:"
+	: "=&r" (temp1), "=&r" (temp2)
+	: "r" (ioaddr(IOC_BASE)), "r" (irq),
+	  "I" ((IOC_IRQCLRA - IOC_BASE) << 2), "r" (addrmasks));
+}
+
+#undef X
+#undef Z
+
+static __inline__ void mask_irq(unsigned int irq)
+{
+	extern void ecard_disableirq (unsigned int);
+	extern void ecard_disablefiq (unsigned int);
+	unsigned char mask = 1 << (irq & 7);
+
+	switch (irq >> 3) {
+	case 0:
+		outb(inb(IOC_IRQMASKA) & ~mask, IOC_IRQMASKA);
+		break;
+	case 1:
+		outb(inb(IOC_IRQMASKB) & ~mask, IOC_IRQMASKB);
+		break;
+	case 4:
+		ecard_disableirq (irq & 7);
+		break;
+	case 8:
+		outb(inb(IOC_FIQMASK) & ~mask, IOC_FIQMASK);
+		break;
+	case 12:
+		ecard_disablefiq (irq & 7);
+	}
+}
+
+static __inline__ void unmask_irq(unsigned int irq)
+{
+	extern void ecard_enableirq (unsigned int);
+	extern void ecard_enablefiq (unsigned int);
+	unsigned char mask = 1 << (irq & 7);
+
+	switch (irq >> 3) {
+	case 0:
+		outb(inb(IOC_IRQMASKA) | mask, IOC_IRQMASKA);
+		break;
+	case 1:
+		outb(inb(IOC_IRQMASKB) | mask, IOC_IRQMASKB);
+		break;
+	case 4:
+		ecard_enableirq (irq & 7);
+		break;
+	case 8:
+		outb(inb(IOC_FIQMASK) | mask, IOC_FIQMASK);
+		break;
+	case 12:
+		ecard_enablefiq (irq & 7);
+	}
+}
+
+static __inline__ unsigned long get_enabled_irqs(void)
+{
+	return inb(IOC_IRQMASKA) | inb(IOC_IRQMASKB) << 8;
+}
+
+static __inline__ void irq_init_irq(void)
+{
+	outb(0, IOC_IRQMASKA);
+	outb(0, IOC_IRQMASKB);
+	outb(0, IOC_FIQMASK);
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/irqs.h linux/include/asm-arm/arch-a5k/irqs.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/irqs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/irqs.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,28 @@
+/*
+ * linux/include/asm-arm/arch-a5k/irqs.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#define IRQ_PRINTER		0
+#define IRQ_BATLOW		1
+#define IRQ_FLOPPYINDEX		2
+#define IRQ_VSYNCPULSE		3
+#define IRQ_POWERON		4
+#define IRQ_TIMER0		5
+#define IRQ_TIMER1		6
+#define IRQ_IMMEDIATE		7
+#define IRQ_EXPCARDFIQ		8
+#define IRQ_SOUNDCHANGE		9
+#define IRQ_SERIALPORT		10
+#define IRQ_HARDDISK		11
+#define IRQ_FLOPPYDISK		12
+#define IRQ_EXPANSIONCARD	13
+#define IRQ_KEYBOARDTX		14
+#define IRQ_KEYBOARDRX		15
+
+#define FIQ_FLOPPYDATA		0
+#define FIQ_ECONET		2
+#define FIQ_SERIALPORT		4
+#define FIQ_EXPANSIONCARD	6
+#define FIQ_FORCE		7
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/mmu.h linux/include/asm-arm/arch-a5k/mmu.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/mmu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/mmu.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-arm/arch-a5k/mmu.h
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  22-11-1996	RMK	Created
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+#define __virt_to_phys(vpage) vpage
+#define __phys_to_virt(ppage) ppage
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/oldlatches.h linux/include/asm-arm/arch-a5k/oldlatches.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/oldlatches.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/oldlatches.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,9 @@
+/*
+ * Dummy oldlatches.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#ifdef __need_oldlatches
+#error "Old latches not present in this (a5k) machine"
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/processor.h linux/include/asm-arm/arch-a5k/processor.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/processor.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,35 @@
+/*
+ * linux/include/asm-arm/arch-a5k/processor.h
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  10-09-1996	RMK	Created
+ */
+
+#ifndef __ASM_ARCH_PROCESSOR_H
+#define __ASM_ARCH_PROCESSOR_H
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/*
+ * User space: 26MB
+ */
+#define TASK_SIZE	(0x01a00000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
+
+#define INIT_MMAP \
+{ &init_mm, 0, 0x02000000, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/serial.h linux/include/asm-arm/arch-a5k/serial.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/serial.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,40 @@
+/*
+ * linux/include/asm-arm/arch-a5k/serial.h
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  15-10-1996	RMK	Created
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD (1843200 / 16)
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+     /* UART CLK        PORT  IRQ     FLAGS        */
+#define RS_UARTS \
+	{ 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS3 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS13 */
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/shmparam.h linux/include/asm-arm/arch-a5k/shmparam.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/shmparam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/shmparam.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,5 @@
+/*
+ * linux/include/asm-arm/arch-a5k/shmparam.h
+ *
+ * Copyright (c) 1996 Russell King.
+ */
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/system.h linux/include/asm-arm/arch-a5k/system.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/system.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,30 @@
+/*
+ * linux/include/asm-arm/arch-a5k/system.h
+ *
+ * Copyright (c) 1996 Russell King
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+extern __inline__ void arch_hard_reset (void)
+{
+	extern void ecard_reset (int card);
+
+	/*
+	 * Reset all expansion cards.
+	 */
+	ecard_reset (-1);
+
+	/*
+	 * copy branch instruction to reset location and call it
+	 */
+	*(unsigned long *)0 = *(unsigned long *)0x03800000;
+	((void(*)(void))0)();
+
+	/*
+	 * If that didn't work, loop endlessly
+	 */
+	while (1);
+}
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/time.h linux/include/asm-arm/arch-a5k/time.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/time.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/time.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,96 @@
+/*
+ * linux/include/asm-arm/arch-a5k/time.h
+ *
+ * Copyright (c) 1996 Russell King.
+ *
+ * Changelog:
+ *  24-Sep-1996	RMK	Created
+ *  10-Oct-1996	RMK	Brought up to date with arch-sa110eval
+ *  04-Dec-1997	RMK	Updated for new arch/arm/time.c
+ */
+
+extern __inline__ unsigned long gettimeoffset (void)
+{
+	unsigned int count1, count2, status1, status2;
+	unsigned long offset = 0;
+
+	status1 = IOC_IRQREQA;
+	barrier ();
+	outb (0, IOC_T0LATCH);
+	barrier ();
+	count1 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
+	barrier ();
+	status2 = inb(IOC_IRQREQA);
+	barrier ();
+	outb (0, IOC_T0LATCH);
+	barrier ();
+	count2 = inb(IOC_T0CNTL) | (inb(IOC_T0CNTH) << 8);
+
+	if (count2 < count1) {
+		/*
+		 * This means that we haven't just had an interrupt
+		 * while reading into status2.
+		 */
+		if (status2 & (1 << 5))
+			offset = tick;
+		count1 = count2;
+	} else if (count2 > count1) {
+		/*
+		 * We have just had another interrupt while reading
+		 * status2.
+		 */
+		offset += tick;
+		count1 = count2;
+	}
+
+	count1 = LATCH - count1;
+	/*
+	 * count1 = number of clock ticks since last interrupt
+	 */
+	offset += count1 * tick / LATCH;
+	return offset;
+}
+
+/*
+ * No need to reset the timer at every irq
+ */
+#define reset_timer() 1
+
+/*
+ * Updating of the RTC.  We don't currently write the time to the
+ * CMOS clock.
+ */
+#define update_rtc()
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+extern __inline__ unsigned long setup_timer (void)
+{
+	extern int iic_control (unsigned char, int, char *, int);
+	unsigned int year, mon, day, hour, min, sec;
+	char buf[8];
+
+	outb(LATCH & 255, IOC_T0LTCHL);
+	outb(LATCH >> 8, IOC_T0LTCHH);
+	outb(0, IOC_T0GO);
+
+	iic_control (0xa0, 0xc0, buf, 1);
+	year = buf[0];
+	if ((year += 1900) < 1970)
+		year += 100;
+
+	iic_control (0xa0, 2, buf, 5);
+	mon  = buf[4] & 0x1f;
+	day  = buf[3] & 0x3f;
+	hour = buf[2];
+	min  = buf[1];
+	sec  = buf[0];
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(sec);
+
+	return mktime(year, mon, day, hour, min, sec);
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/timex.h linux/include/asm-arm/arch-a5k/timex.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/timex.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,13 @@
+/*
+ * linux/include/asm-arm/arch-a5k/timex.h
+ *
+ * A5000 architecture timex specifications
+ *
+ * Copyright (C) 1997, 1998 Russell King
+ */
+
+/*
+ * On the RiscPC, the clock ticks at 2MHz.
+ */
+#define CLOCK_TICK_RATE		2000000
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-a5k/uncompress.h linux/include/asm-arm/arch-a5k/uncompress.h
--- v2.1.100/linux/include/asm-arm/arch-a5k/uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-a5k/uncompress.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,104 @@
+/*
+ * linux/include/asm-arm/arch-a5k/uncompress.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+#define VIDMEM ((char *)0x02000000)
+ 
+#include "../arch/arm/drivers/char/font.h"
+
+int video_num_columns, video_num_lines, video_size_row;
+int white, bytes_per_char_h;
+extern unsigned long con_charconvtable[256];
+
+struct param_struct {
+	unsigned long page_size;
+	unsigned long nr_pages;
+	unsigned long ramdisk_size;
+	unsigned long mountrootrdonly;
+	unsigned long rootdev;
+	unsigned long video_num_cols;
+	unsigned long video_num_rows;
+	unsigned long video_x;
+	unsigned long video_y;
+	unsigned long memc_control_reg;
+	unsigned char sounddefault;
+	unsigned char adfsdrives;
+	unsigned char bytes_per_char_h;
+	unsigned char bytes_per_char_v;
+	unsigned long unused[256/4-11];
+};
+
+static struct param_struct *params = (struct param_struct *)0x0207c000;
+ 
+/*
+ * This does not append a newline
+ */
+static void puts(const char *s)
+{
+	extern void ll_write_char(char *, unsigned long);
+	int x,y;
+	unsigned char c;
+	char *ptr;
+
+	x = params->video_x;
+	y = params->video_y;
+
+	while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
+		if ( c == '\n' ) {
+			x = 0;
+			if ( ++y >= video_num_lines ) {
+				y--;
+			}
+		} else {
+			ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
+			ll_write_char(ptr, c|(white<<8));
+			if ( ++x >= video_num_columns ) {
+				x = 0;
+				if ( ++y >= video_num_lines ) {
+					y--;
+				}
+			}
+		}
+	}
+
+	params->video_x = x;
+	params->video_y = y;
+}
+
+static void error(char *x);
+
+/*
+ * Setup for decompression
+ */
+static void arch_decomp_setup(void)
+{
+	int i;
+	
+	video_num_lines = params->video_num_rows;
+	video_num_columns = params->video_num_cols;
+	bytes_per_char_h = params->bytes_per_char_h;
+	video_size_row = video_num_columns * bytes_per_char_h;
+	if (bytes_per_char_h == 4)
+		for (i = 0; i < 256; i++)
+			con_charconvtable[i] =
+				(i & 128 ? 1 << 0  : 0) |
+				(i & 64  ? 1 << 4  : 0) |
+				(i & 32  ? 1 << 8  : 0) |
+				(i & 16  ? 1 << 12 : 0) |
+				(i & 8   ? 1 << 16 : 0) |
+				(i & 4   ? 1 << 20 : 0) |
+				(i & 2   ? 1 << 24 : 0) |
+				(i & 1   ? 1 << 28 : 0);
+	else
+		for (i = 0; i < 16; i++)
+			con_charconvtable[i] =
+				(i & 8   ? 1 << 0  : 0) |
+				(i & 4   ? 1 << 8  : 0) |
+				(i & 2   ? 1 << 16 : 0) |
+				(i & 1   ? 1 << 24 : 0);
+
+	white = bytes_per_char_h == 8 ? 0xfc : 7;
+
+	if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/ide.h linux/include/asm-arm/arch-arc/ide.h
--- v2.1.100/linux/include/asm-arm/arch-arc/ide.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/ide.h	Fri May  8 00:42:39 1998
@@ -11,13 +11,14 @@
  */
 
 #include <linux/config.h>
+#include <asm/irq.h>
 
 static __inline__ int
 ide_default_irq(ide_ioreg_t base)
 {
 #ifdef CONFIG_ARCH_A5K
 	if (base == 0x1f0)
-		return 11;
+		return IRQ_HARDDISK;
 #endif
 	return 0;
 }
@@ -52,5 +53,5 @@
 	}
 	*p++ = ctrl;
 	if (irq != NULL)
-		irq = 0;
+		*irq = 0;
 }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/irqs.h linux/include/asm-arm/arch-arc/irqs.h
--- v2.1.100/linux/include/asm-arm/arch-arc/irqs.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/irqs.h	Fri May  8 00:42:39 1998
@@ -47,3 +47,5 @@
 #define FIQ_FORCE		7
 
 #define IRQ_TIMER		IRQ_TIMER0
+
+#define irq_cannonicalize(i)	(i)
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h
--- v2.1.100/linux/include/asm-arm/arch-arc/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/processor.h	Fri May  8 00:42:39 1998
@@ -26,7 +26,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/serial.h linux/include/asm-arm/arch-arc/serial.h
--- v2.1.100/linux/include/asm-arm/arch-arc/serial.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/serial.h	Fri May  8 00:42:39 1998
@@ -25,7 +25,7 @@
 
 #if defined(CONFIG_ARCH_A5K)
      /* UART CLK        PORT  IRQ     FLAGS        */
-#define RS_UARTS \
+#define SERIAL_PORT_DFNS \
 	{ 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
@@ -44,7 +44,7 @@
 #elif defined(CONFIG_ARCH_ARC)
 
      /* UART CLK        PORT  IRQ     FLAGS        */
-#define RS_UARTS \
+#define SERIAL_PORT_DFNS \
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-arc/uncompress.h linux/include/asm-arm/arch-arc/uncompress.h
--- v2.1.100/linux/include/asm-arm/arch-arc/uncompress.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/uncompress.h	Fri May  8 00:42:39 1998
@@ -52,7 +52,7 @@
 			}
 		} else {
 			ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
-			ll_write_char(ptr, c|(white<<8));
+			ll_write_char(ptr, c|(white<<16));
 			if ( ++x >= video_num_columns ) {
 				x = 0;
 				if ( ++y >= video_num_lines ) {
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/irqs.h linux/include/asm-arm/arch-ebsa110/irqs.h
--- v2.1.100/linux/include/asm-arm/arch-ebsa110/irqs.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa110/irqs.h	Fri May  8 00:42:39 1998
@@ -14,3 +14,6 @@
 #define IRQ_IMMEDIATE		7
 
 #define IRQ_TIMER		IRQ_TIMER0
+
+#define irq_cannonicalize(i)	(i)
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/mmap.h linux/include/asm-arm/arch-ebsa110/mmap.h
--- v2.1.100/linux/include/asm-arm/arch-ebsa110/mmap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-ebsa110/mmap.h	Fri May  8 00:42:39 1998
@@ -0,0 +1,10 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/mmap.h
+ *
+ * Copyright (C) 1996,1997,1998 Russell King
+ */
+
+/*
+ * Use SRAM for cache flushing
+ */
+#define SAFE_ADDR	0x40000000
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h
--- v2.1.100/linux/include/asm-arm/arch-ebsa110/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa110/processor.h	Fri May  8 00:42:39 1998
@@ -23,7 +23,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa110/serial.h linux/include/asm-arm/arch-ebsa110/serial.h
--- v2.1.100/linux/include/asm-arm/arch-ebsa110/serial.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-ebsa110/serial.h	Fri May  8 00:42:39 1998
@@ -21,7 +21,7 @@
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
      /* UART CLK        PORT  IRQ     FLAGS        */
-#define RS_UARTS \
+#define SERIAL_PORT_DFNS \
 	{ 0, BASE_BAUD, 0x3F8,  1, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8,  2, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa285/irqs.h linux/include/asm-arm/arch-ebsa285/irqs.h
--- v2.1.100/linux/include/asm-arm/arch-ebsa285/irqs.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/irqs.h	Fri May  8 00:42:40 1998
@@ -43,3 +43,6 @@
  * Now map them to the Linux interrupts
  */
 #define IRQ_TIMER		IRQ_TIMER1
+
+#define irq_cannonicalize(i)	(i)
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-ebsa285/processor.h linux/include/asm-arm/arch-ebsa285/processor.h
--- v2.1.100/linux/include/asm-arm/arch-ebsa285/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/processor.h	Fri May  8 00:42:40 1998
@@ -23,7 +23,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/a.out.h linux/include/asm-arm/arch-nexuspci/a.out.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/a.out.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-nexuspci/a.out.h	Fri May  8 00:42:40 1998
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-ebsa/a.out.h
+ * linux/include/asm-arm/arch-nexuspci/a.out.h
  *
  * Copyright (C) 1996 Russell King
  */
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/dma.h linux/include/asm-arm/arch-nexuspci/dma.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/dma.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-nexuspci/dma.h	Fri May  8 00:42:40 1998
@@ -1,17 +1,12 @@
 /*
  * linux/include/asm-arm/arch-nexuspci/dma.h
  *
- * Architecture DMA routines
+ * Architecture DMA routines - NexusPCI has no DMA, so this file is very
+ * simple. :-)
  *
  * Copyright (C) 1998 Philip Blundell
  */
 
-#ifndef __ASM_ARCH_DMA_H
-#define __ASM_ARCH_DMA_H
-
-/* NexusPCI has no DMA */
-
-#warning No DMA on this platform
-
-#endif /* _ASM_ARCH_DMA_H */
+/* Need this to keep <asm/dma.h> happy. */
+typedef unsigned int dmamode_t;
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/hardware.h linux/include/asm-arm/arch-nexuspci/hardware.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/hardware.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-nexuspci/hardware.h	Fri May  8 00:42:40 1998
@@ -1,11 +1,19 @@
 /*
  * linux/include/asm-arm/arch-nexuspci/hardware.h
  *
- * Copyright (C) 1997 Philip Blundell
+ * Copyright (C) 1998 Philip Blundell
  *
  * This file contains the hardware definitions of the Nexus PCI card.
  */
 
+/*    Logical    Physical
+ * 0xfff00000	0x10000000	SCC2691 DUART
+ * 0xffe00000	0x20000000	INTCONT
+ * 0xffd00000	0x30000000	Status
+ * 0xffc00000	0x60000000	PLX registers
+ * 0xfe000000	0x70000000	PCI I/O
+ */
+ 
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
@@ -13,29 +21,21 @@
  * What hardware must be present
  */
 
-#ifndef __ASSEMBLER__
+#define HAS_PCIO
+#define PCIO_BASE		0xfe000000
 
 /*
  * Mapping areas
  */
 #define IO_END			0xffffffff
-#define IO_BASE			0xd0000000
+#define IO_BASE			0xfe000000
 #define IO_SIZE			(IO_END - IO_BASE)
-#define IO_START		0xd0000000
 
 /*
  * RAM definitions
  */
 #define RAM_BASE		0x40000000
-#define MAPTOPHYS(a)		((unsigned long)(a) - PAGE_OFFSET + RAM_BASE)
 #define KERNTOPHYS(a)		((unsigned long)(&a))
-#define KERNEL_BASE		(0xc0008000)
 #define SAFE_ADDR		0x40000000
 
-#else
-
-#define IO_BASE			0
-
 #endif
-#endif
-
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/io.h linux/include/asm-arm/arch-nexuspci/io.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-nexuspci/io.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,143 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/io.h
+ *
+ * Copyright (C) 1997,1998 Russell King
+ *
+ * Modifications:
+ *  06-Dec-1997	RMK	Created.
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+/*
+ * This architecture does not require any delayed IO, and
+ * has the constant-optimised IO
+ */
+#undef	ARCH_IO_DELAY
+
+/*
+ * Dynamic IO functions - let the compiler
+ * optimize the expressions
+ */
+#define DECLARE_DYN_OUT(fnsuffix,instr,typ)					\
+extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port)	\
+{										\
+	__asm__ __volatile__(							\
+	"str" ##instr## "	%0, [%1, %2]"					\
+	: 									\
+	: "r" (value), "r" (PCIO_BASE), typ (port));				\
+}
+
+#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ)					\
+extern __inline__ unsigned sz __in##fnsuffix (unsigned int port)		\
+{										\
+	unsigned long value;							\
+	__asm__ __volatile__(							\
+	"ldr" ##instr## "	%0, [%1, %2]"					\
+	: "=&r" (value)								\
+	: "r" (PCIO_BASE), typ (port));						\
+	return (unsigned sz)value;						\
+}
+
+extern __inline__ unsigned int __ioaddr (unsigned int port)			\
+{										\
+	return (unsigned int)(PCIO_BASE + port);				\
+}
+
+#define DECLARE_IO(sz,fnsuffix,instr,typ)	\
+	DECLARE_DYN_OUT(fnsuffix,instr,typ)	\
+	DECLARE_DYN_IN(sz,fnsuffix,instr,typ)
+
+DECLARE_IO(char,b,"b","Jr")
+DECLARE_IO(short,w,"h","r")
+DECLARE_IO(long,l,"","Jr")
+
+#undef DECLARE_IO
+#undef DECLARE_DYN_OUT
+#undef DECLARE_DYN_IN
+
+/*
+ * Constant address IO functions
+ *
+ * These have to be macros for the 'J' constraint to work -
+ * +/-4096 immediate operand.
+ */
+#define __outbc(value,port)							\
+({										\
+	__asm__ __volatile__(							\
+	"strb	%0, [%1, %2]"							\
+	:									\
+	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
+})
+
+#define __inbc(port)								\
+({										\
+	unsigned char result;							\
+	__asm__ __volatile__(							\
+	"ldrb	%0, [%1, %2]"							\
+	: "=r" (result)								\
+	: "r" (PCIO_BASE), "Jr" (port));					\
+	result;									\
+})
+
+#define __outwc(value,port)							\
+({										\
+	__asm__ __volatile__(							\
+	"strh	%0, [%1, %2]"							\
+	:									\
+	: "r" (value), "r" (PCIO_BASE), "r" (port));				\
+})
+
+#define __inwc(port)								\
+({										\
+	unsigned short result;							\
+	__asm__ __volatile__(							\
+	"ldrh	%0, [%1, %2]"							\
+	: "=r" (result)								\
+	: "r" (PCIO_BASE), "r" (port));						\
+	result & 0xffff;							\
+})
+
+#define __outlc(value,port)							\
+({										\
+	__asm__ __volatile__(							\
+	"str	%0, [%1, %2]"							\
+	:									\
+	: "r" (value), "r" (PCIO_BASE), "Jr" (port));				\
+})
+
+#define __inlc(port)								\
+({										\
+	unsigned long result;							\
+	__asm__ __volatile__(							\
+	"ldr	%0, [%1, %2]"							\
+	: "=r" (result)								\
+	: "r" (PCIO_BASE), "Jr" (port));					\
+	result;									\
+})
+
+#define __ioaddrc(port)								\
+({										\
+	unsigned long addr;							\
+	addr = PCIO_BASE + port;						\
+	addr;									\
+})
+
+/*
+ * Translated address IO functions
+ *
+ * IO address has already been translated to a virtual address
+ */
+#define outb_t(v,p)								\
+	(*(volatile unsigned char *)(p) = (v))
+
+#define inb_t(p)								\
+	(*(volatile unsigned char *)(p))
+
+#define outl_t(v,p)								\
+	(*(volatile unsigned long *)(p) = (v))
+
+#define inl_t(p)								\
+	(*(volatile unsigned long *)(p))
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/irq.h linux/include/asm-arm/arch-nexuspci/irq.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/irq.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-nexuspci/irq.h	Fri May  8 00:42:40 1998
@@ -1,29 +1,27 @@
 /*
- * include/asm-arm/arch-ebsa110/irq.h
+ * include/asm-arm/arch-nexuspci/irq.h
  *
- * Copyright (C) 1996,1997,1998 Russell King
+ * Copyright (C) 1998 Philip Blundell
  */
 
-#define IRQ_MCLR	((volatile unsigned char *)0xf3000000)
-#define IRQ_MSET	((volatile unsigned char *)0xf2c00000)
-#define IRQ_MASK	((volatile unsigned char *)0xf2c00000)
+#define INT_RESET	((volatile unsigned char *)0xfff00000)
+#define INT_ENABLE	((volatile unsigned char *)0xfff00000)
+#define INT_DISABLE	((volatile unsigned char *)0xfff00000)
 
 static __inline__ void mask_and_ack_irq(unsigned int irq)
 {
-	if (irq < 8)
-		*IRQ_MCLR = 1 << irq;
+	INT_DISABLE[irq << 2] = 0;
+	INT_RESET[irq << 2] = 0;
 }
 
 static __inline__ void mask_irq(unsigned int irq)
 {
-	if (irq < 8)
-		*IRQ_MCLR = 1 << irq;
+	INT_DISABLE[irq << 2] = 0;
 }
 
 static __inline__ void unmask_irq(unsigned int irq)
 {
-	if (irq < 8)
-		*IRQ_MSET = 1 << irq;
+	INT_ENABLE[irq << 2] = 0;
 }
  
 static __inline__ unsigned long get_enabled_irqs(void)
@@ -33,14 +31,8 @@
 
 static __inline__ void irq_init_irq(void)
 {
-	unsigned long flags;
-
-	save_flags_cli (flags);
-	*IRQ_MCLR = 0xff;
-	*IRQ_MSET = 0x55;
-	*IRQ_MSET = 0x00;
-	if (*IRQ_MASK != 0x55)
-		while (1);
-	*IRQ_MCLR = 0xff;		/* clear all interrupt enables */
-	restore_flags (flags);
+	unsigned int i;
+	/* Disable all interrupts initially. */
+	for (i = 0; i < 8; i++)
+		mask_irq(i);
 }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/irqs.h linux/include/asm-arm/arch-nexuspci/irqs.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/irqs.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-nexuspci/irqs.h	Fri May  8 00:42:40 1998
@@ -14,3 +14,6 @@
 
 /* timer is part of the DUART */
 #define IRQ_TIMER		IRQ_DUART
+
+#define irq_cannonicalize(i)	(i)
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/mmap.h linux/include/asm-arm/arch-nexuspci/mmap.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/mmap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-nexuspci/mmap.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,10 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/mmap.h
+ *
+ * Copyright (C) 1996,1997,1998 Russell King
+ */
+
+/*
+ * Use SRAM for cache flushing
+ */
+#define SAFE_ADDR	0x40000000
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/mmu.h linux/include/asm-arm/arch-nexuspci/mmu.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/mmu.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-nexuspci/mmu.h	Fri May  8 00:42:40 1998
@@ -1,16 +1,26 @@
 /*
  * linux/include/asm-arm/arch-nexuspci/mmu.h
  *
- * Copyright (c) 1997 Philip Blundell.
+ * Copyright (c) 1997, 1998 Philip Blundell.
  *
  */
 #ifndef __ASM_ARCH_MMU_H
 #define __ASM_ARCH_MMU_H
 
 /*
- * On NexusPCI, the dram is contiguous
+ * On NexusPCI, the DRAM is contiguous
  */
 #define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
 #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
+#define __virt_to_phys__is_a_macro
+#define __phys_to_virt__is_a_macro
+
+/*
+ * These are exactly the same as the physical memory view.
+ */
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
 
 #endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-nexuspci/processor.h	Fri May  8 00:42:40 1998
@@ -24,7 +24,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/serial.h linux/include/asm-arm/arch-nexuspci/serial.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-nexuspci/serial.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,41 @@
+/*
+ * linux/include/asm-arm/arch-ebsa110/serial.h
+ *
+ * Copyright (c) 1996,1997,1998 Russell King.
+ *
+ * Changelog:
+ *  15-10-1996	RMK	Created
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD (1843200 / 16)
+
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+
+     /* UART CLK        PORT  IRQ     FLAGS        */
+#define RS_UARTS \
+	{ 0, BASE_BAUD, 0x3F8,  1, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8,  2, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS3 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS13 */
+
+#endif
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/shmparam.h linux/include/asm-arm/arch-nexuspci/shmparam.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/shmparam.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-nexuspci/shmparam.h	Fri May  8 00:42:40 1998
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-ebsa110/shmparam.h
+ * linux/include/asm-arm/arch-nexuspci/shmparam.h
  *
  * Copyright (c) 1996 Russell King.
  */
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/system.h linux/include/asm-arm/arch-nexuspci/system.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/system.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-nexuspci/system.h	Fri May  8 00:42:40 1998
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-ebsa110/system.h
+ * linux/include/asm-arm/arch-nexuspci/system.h
  *
  * Copyright (c) 1996,1997,1998 Russell King.
  */
@@ -9,7 +9,7 @@
 extern __inline__ void arch_hard_reset (void)
 {
 	/*
-	 * loop endlessly
+	 * loop endlessly - the watchdog will reset us if it's enabled.
 	 */
 	cli();
 	while (1);
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/time.h linux/include/asm-arm/arch-nexuspci/time.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/time.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-nexuspci/time.h	Fri May  8 00:42:40 1998
@@ -7,6 +7,8 @@
  *
  */
 
+#define update_rtc()
+
 extern __inline__ unsigned long gettimeoffset (void)
 {
 	return 0;
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-nexuspci/timex.h linux/include/asm-arm/arch-nexuspci/timex.h
--- v2.1.100/linux/include/asm-arm/arch-nexuspci/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-nexuspci/timex.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,8 @@
+/*
+ * linux/include/asm-arm/arch-nexuspci/timex.h
+ *
+ * NexusPCI StrongARM card timex specifications
+ *
+ * Copyright (C) 1998 Philip Blundell
+ */
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/ide.h linux/include/asm-arm/arch-rpc/ide.h
--- v2.1.100/linux/include/asm-arm/arch-rpc/ide.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-rpc/ide.h	Fri May  8 00:42:40 1998
@@ -3,12 +3,13 @@
  *
  * Copyright (c) 1997 Russell King
  */
+#include <asm/irq.h>
 
 static __inline__ int
 ide_default_irq(ide_ioreg_t base)
 {
 	if (base == 0x1f0)
-		return 9;
+		return IRQ_HARDDISK;
 	return 0;
 }
 
@@ -40,5 +41,5 @@
 	}
 	*p++ = ctrl;
 	if (irq != NULL)
-		irq = 0;
+		*irq = 0;
 }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/irqs.h linux/include/asm-arm/arch-rpc/irqs.h
--- v2.1.100/linux/include/asm-arm/arch-rpc/irqs.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/irqs.h	Fri May  8 00:42:40 1998
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-a5k/irqs.h
+ * linux/include/asm-arm/arch-rpc/irqs.h
  *
  * Copyright (C) 1996 Russell King
  */
@@ -13,9 +13,8 @@
 #define IRQ_TIMER1		6
 #define IRQ_IMMEDIATE		7
 #define IRQ_EXPCARDFIQ		8
-#define IRQ_SOUNDCHANGE		9
+#define IRQ_HARDDISK		9
 #define IRQ_SERIALPORT		10
-#define IRQ_HARDDISK		11
 #define IRQ_FLOPPYDISK		12
 #define IRQ_EXPANSIONCARD	13
 #define IRQ_KEYBOARDTX		14
@@ -35,3 +34,6 @@
 #define FIQ_FORCE		7
 
 #define IRQ_TIMER		IRQ_TIMER0
+
+#define irq_cannonicalize(i)	(i)
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/mmap.h linux/include/asm-arm/arch-rpc/mmap.h
--- v2.1.100/linux/include/asm-arm/arch-rpc/mmap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-rpc/mmap.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,48 @@
+/*
+ * linux/include/asm-arm/arch-rpc/mmap.h
+ *
+ * Copyright (C) 1996 Russell King
+ */
+
+#define HAVE_MAP_VID_MEM
+#define SAFE_ADDR 0x00000000	/* ROM */
+
+unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update)
+{
+	static int updated = 0;
+	unsigned long address;
+	pgd_t *pgd;
+
+	if (updated)
+		return 0;
+	updated = update;
+
+	address = SCREEN_START | PMD_TYPE_SECT | PMD_DOMAIN(DOMAIN_KERNEL) | PMD_SECT_AP_WRITE;
+	pgd = swapper_pg_dir + (SCREEN2_BASE >> PGDIR_SHIFT);
+	pgd_val(pgd[0]) = address;
+	pgd_val(pgd[1]) = address + (1 << PGDIR_SHIFT);
+
+	if (update) {
+		unsigned long pgtable = PAGE_ALIGN(kmem), *p;
+		int i;
+
+		memzero ((void *)pgtable, 4096);
+		
+		pgd_val(pgd[-2]) = virt_to_phys(pgtable) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL);
+		pgd_val(pgd[-1]) = virt_to_phys(pgtable + PTRS_PER_PTE*4) | PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL);
+		p = (unsigned long *)pgtable;
+
+		i = PTRS_PER_PTE * 2 - ((SCREEN1_END - log_start) >> PAGE_SHIFT);
+		address = SCREEN_START | PTE_TYPE_SMALL | PTE_AP_WRITE;
+
+		while (i < PTRS_PER_PTE * 2) {
+			p[i++] = address;
+			address += PAGE_SIZE;
+		}
+
+		flush_page_to_ram(pgtable);
+
+		kmem = pgtable + PAGE_SIZE;
+	}
+	return kmem;
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h
--- v2.1.100/linux/include/asm-arm/arch-rpc/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-rpc/processor.h	Fri May  8 00:42:40 1998
@@ -26,7 +26,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/arch-rpc/serial.h linux/include/asm-arm/arch-rpc/serial.h
--- v2.1.100/linux/include/asm-arm/arch-rpc/serial.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/arch-rpc/serial.h	Fri May  8 00:42:40 1998
@@ -21,7 +21,7 @@
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
      /* UART CLK        PORT  IRQ     FLAGS        */
-#define RS_UARTS \
+#define SERIAL_PORT_DFNS \
 	{ 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS },	/* ttyS1 */	\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/checksum.h linux/include/asm-arm/checksum.h
--- v2.1.100/linux/include/asm-arm/checksum.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/checksum.h	Fri May  8 00:42:40 1998
@@ -35,14 +35,19 @@
  * better 64-bit) boundary
  */
 
-extern
-unsigned int csum_partial_copy_from_user (const char *src, char *dst, int len, int sum, int *err_ptr);
+unsigned int
+csum_partial_copy_nocheck(const char *src, char *dst, int len, int sum);
 
+unsigned int
+csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
+
+#if 0
 /*
  * This combination is currently not used, but possible:
  */
-extern
-unsigned int csum_partial_copy_to_user (const char *src, char *dst, int len, int sum, int *err_ptr);
+unsigned int
+csum_partial_copy_to_user(const char *src, char *dst, int len, int sum, int *err_ptr);
+#endif
 
 /*
  * These are the old (and unsafe) way of doing checksums, a warning message will be
@@ -51,7 +56,8 @@
  * these functions should go away after some time.
  */
 #define csum_partial_copy_fromuser csum_partial_copy
-unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum);
+unsigned int
+csum_partial_copy(const char *src, char *dst, int len, int sum);
 
 /*
  *	This is a version of ip_compute_csum() optimized for IP headers,
@@ -62,8 +68,9 @@
  *	Note: the order that the LDM registers are loaded with respect to
  *	the adc's doesn't matter.
  */
-static inline unsigned short ip_fast_csum(unsigned char * iph,
-					  unsigned int ihl) {
+static inline unsigned short
+ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
 	unsigned int sum, tmp1;
 
     __asm__ __volatile__("
@@ -92,63 +99,64 @@
 }
 
 /*
- * computes the checksum of the TCP/UDP pseudo-header
- * returns a 16-bit checksum, already complemented
- */
-static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
-						   unsigned long daddr,
-						   unsigned short len,
-						   unsigned short proto,
-						   unsigned int sum) {
-    __asm__ __volatile__("
-    adds	%0, %0, %1
-    adcs	%0, %0, %4
-    adcs	%0, %0, %5
-    adc		%0, %0, #0
-    adds	%0, %0, %0, lsl #16
-    addcs	%0, %0, #0x10000
-    mvn		%0, %0
-    mov		%0, %0, lsr #16
-	"
-	: "=&r" (sum), "=&r" (saddr)
-	: "0" (daddr), "1"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum));
-	return((unsigned short)sum);
-}
-
-/*
  * 	Fold a partial checksum without adding pseudo headers
  */
-static inline unsigned int csum_fold(unsigned int sum)
+static inline unsigned int
+csum_fold(unsigned int sum)
 {
-    __asm__ __volatile__("
-    adds	%0, %0, %0, lsl #16
-    addcs	%0, %0, #0x10000
-    mvn		%0, %0
-    mov		%0, %0, lsr #16
-	"
+	__asm__("
+	adds	%0, %0, %0, lsl #16
+	addcs	%0, %0, #0x10000"
 	: "=r" (sum)
 	: "0" (sum));
+	return (~sum) >> 16;
+}
+
+static inline unsigned long
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
+		   unsigned short proto, unsigned int sum)
+{
+	__asm__("
+	adds	%0, %0, %1
+	adcs	%0, %0, %2
+	adcs	%0, %0, %3
+	adc	%0, %0, #0"
+	: "=&r"(sum)
+	: "r" (daddr), "r" (saddr), "r" ((ntohs(len)<<16)+proto*256), "0" (sum));
 	return sum;
 }	
-	
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int
+csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
+		  unsigned short proto, unsigned int sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
 
 /*
  * this routine is used for miscellaneous IP-like checksums, mainly
  * in icmp.c
  */
-
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
-    unsigned int sum;
-
-    __asm__ __volatile__("
-    adds	%0, %0, %0, lsl #16
-    addcs	%0, %0, #0x10000
-    mvn		%0, %0
-    mov		%0, %0, lsr #16
-	"
-	: "=r"(sum)
-	: "0" (csum_partial(buff, len, 0)));
-	return(sum);
+static inline unsigned short
+ip_compute_csum(unsigned char * buff, int len)
+{
+	return csum_fold(csum_partial(buff, len, 0));
 }
 
+#define _HAVE_ARCH_IPV6_CSUM
+extern unsigned long
+__csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
+		__u32 proto, unsigned int sum);
+
+extern __inline__ unsigned short int
+csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len,
+		unsigned short proto, unsigned int sum)
+{
+	return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl((__u32)len),
+					   htonl(proto), sum));
+}
 #endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/ecard.h linux/include/asm-arm/ecard.h
--- v2.1.100/linux/include/asm-arm/ecard.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/ecard.h	Fri May  8 00:42:40 1998
@@ -64,6 +64,8 @@
 #define MANU_EESOX		0x0064
 #define PROD_EESOX_SCSI2		0x008c
 
+#define MANU_YELLOWSTONE	0x0096
+#define PROD_YELLOWSTONE_RAPIDE32	0x0120
 
 #ifdef ECARD_C
 #define CONST
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/elf.h linux/include/asm-arm/elf.h
--- v2.1.100/linux/include/asm-arm/elf.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/elf.h	Fri May  8 00:42:40 1998
@@ -6,6 +6,7 @@
  */
 
 #include <asm/ptrace.h>
+#include <asm/procinfo.h>
 
 typedef unsigned long elf_greg_t;
 
@@ -48,7 +49,15 @@
    specific libraries for optimization.  This is more specific in
    intent than poking at uname or /proc/cpuinfo. */
 
-#define ELF_PLATFORM	(NULL)
+/* For now we just provide a fairly general string that describes the
+   processor family.  This could be made more specific later if someone
+   implemented optimisations that require it.  26-bit CPUs give you
+   "arm2" for ARM2 (no SWP) and "arm3" for anything else (ARM1 isn't
+   supported).  32-bit CPUs give you "arm6" for anything based on an
+   ARM6 or ARM7 core and "sa1x" for anything based on a StrongARM-1
+   core.  */
+
+#define ELF_PLATFORM	(armidlist[armidindex].optname)
 
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex,ibcs2) \
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/ioctl.h linux/include/asm-arm/ioctl.h
--- v2.1.100/linux/include/asm-arm/ioctl.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/ioctl.h	Fri May  8 00:42:40 1998
@@ -1,4 +1,4 @@
-/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
+/* $Id: ioctl.h,v 1.1 1998/01/28 09:56:22 ecd Exp $
  *
  * linux/ioctl.h for Linux by H.H. Bergman.
  */
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/irq-no.h linux/include/asm-arm/irq-no.h
--- v2.1.100/linux/include/asm-arm/irq-no.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/irq-no.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,11 @@
+/*
+ * linux/include/asm-arm/irq-no.h
+ *
+ * Machine independent interrupt numbers
+ */
+
+#include <asm/arch/irqs.h>
+
+#ifndef NR_IRQS
+#define NR_IRQS		128
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/linux_logo.h linux/include/asm-arm/linux_logo.h
--- v2.1.100/linux/include/asm-arm/linux_logo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/linux_logo.h	Fri May  8 00:42:40 1998
@@ -0,0 +1,49 @@
+/*
+ * linux/include/asm-arm/linux_logo.h
+ *
+ * Copyright (C) 1998 Russell King
+ *
+ * Linux console driver logo definitions for ARM
+ */
+
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "ARM Linux version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS	0
+
+unsigned char linux_logo_red[] __initdata = { };
+unsigned char linux_logo_green[] __initdata = { };
+unsigned char linux_logo_blue[] __initdata = { };
+
+unsigned char linux_logo16_red[] __initdata = { };
+unsigned char linux_logo16_green[] __initdata = { };
+unsigned char linux_logo16_blue[] __initdata = { };
+
+unsigned char linux_logo[] __initdata = { };
+unsigned char linux_logo16[] __initdata = { };
+unsigned char linux_logo_bw[] __initdata = { };
+
+/* Painted by Johnny Stenback <jst@uwasa.fi>
+ * Modified by Russell King for ARM
+ */
+unsigned char *linux_serial_image __initdata = "\n"
+"         .u$e.\n"
+"       .$$$$$:S\n"
+"       $\"*$/\"*$$\n"
+"       $.`$ . ^F\n"
+"       4k+#+T.$F\n"
+"       4P+++\"$\"$\n"
+"       :R\"+  t$$B\n"
+"    ___#       $$$\n"
+"    |  |       R$$k\n"
+"   dd. | Linux  $!$\n"
+"   ddd |   ARM  $9$F\n"
+" '!!!!!$       !!#!`\n"
+"  !!!!!*     .!!!!!`\n"
+"'!!!!!!!W..e$$!!!!!!`    %s\n"
+" \"~^^~         ^~~^\n"
+"\n";
+
+extern int (*console_show_logo)(void);
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/namei.h linux/include/asm-arm/namei.h
--- v2.1.100/linux/include/asm-arm/namei.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/namei.h	Fri May  8 00:42:40 1998
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.1 1996/12/13 14:48:21 jj Exp $
+/* $Id: namei.h,v 1.1 1998/01/28 09:56:37 ecd Exp $
  * linux/include/asm-i386/namei.h
  *
  * Included from linux/fs/namei.c
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/page.h linux/include/asm-arm/page.h
--- v2.1.100/linux/include/asm-arm/page.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/page.h	Fri May  8 00:42:40 1998
@@ -6,6 +6,8 @@
 
 #ifdef __KERNEL__
 
+#define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)	free_page(addr)
 #define clear_page(page)	memzero((void *)(page), PAGE_SIZE)
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h
--- v2.1.100/linux/include/asm-arm/posix_types.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/posix_types.h	Fri May  8 00:42:40 1998
@@ -9,51 +9,61 @@
 #ifndef __ARCH_ARM_POSIX_TYPES_H
 #define __ARCH_ARM_POSIX_TYPES_H
 
+#include <linux/config.h>
+
 /*
  * This file is generally used by user-level software, so you need to
  * be a little careful about namespace pollution etc.  Also, we cannot
  * assume GCC is being used.
  */
 
-typedef unsigned short	__kernel_dev_t;
-typedef unsigned long	__kernel_ino_t;
-typedef unsigned short	__kernel_mode_t;
-typedef unsigned short	__kernel_nlink_t;
-typedef long		__kernel_off_t;
-typedef int		__kernel_pid_t;
-typedef unsigned short	__kernel_ipc_pid_t;
-typedef unsigned short	__kernel_uid_t;
-typedef unsigned short	__kernel_gid_t;
-typedef unsigned int	__kernel_size_t;
-typedef int		__kernel_ssize_t;
-typedef int		__kernel_ptrdiff_t;
-typedef long		__kernel_time_t;
-typedef long		__kernel_suseconds_t;
-typedef long		__kernel_clock_t;
-typedef int		__kernel_daddr_t;
-typedef char *		__kernel_caddr_t;
+typedef unsigned short		__kernel_dev_t;
+typedef unsigned long		__kernel_ino_t;
+typedef unsigned short		__kernel_mode_t;
+typedef unsigned short		__kernel_nlink_t;
+typedef long			__kernel_off_t;
+typedef int			__kernel_pid_t;
+typedef unsigned short		__kernel_ipc_pid_t;
+typedef unsigned short		__kernel_uid_t;
+typedef unsigned short		__kernel_gid_t;
+#ifdef CONFIG_BINUTILS_NEW
+typedef long unsigned int	__kernel_size_t;
+#else
+typedef unsigned int		__kernel_size_t;
+#endif
+typedef int			__kernel_ssize_t;
+typedef int			__kernel_ptrdiff_t;
+typedef long			__kernel_time_t;
+typedef long			__kernel_suseconds_t;
+typedef long			__kernel_clock_t;
+typedef int			__kernel_daddr_t;
+typedef char *			__kernel_caddr_t;
 
 #ifdef __GNUC__
-typedef long long	__kernel_loff_t;
+typedef long long		__kernel_loff_t;
 #endif
 
 typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
 	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
 } __kernel_fsid_t;
 
-#undef  __FD_SET
+#undef	__FD_SET
 #define __FD_SET(fd, fdsetp) \
 		(((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
 
-#undef  __FD_CLR
+#undef	__FD_CLR
 #define __FD_CLR(fd, fdsetp) \
 		(((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
 
-#undef  __FD_ISSET
+#undef	__FD_ISSET
 #define __FD_ISSET(fd, fdsetp) \
 		((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
 
-#undef  __FD_ZERO
+#undef	__FD_ZERO
 #define __FD_ZERO(fdsetp) \
 		(memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/mm-init.h linux/include/asm-arm/proc-armo/mm-init.h
--- v2.1.100/linux/include/asm-arm/proc-armo/mm-init.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/proc-armo/mm-init.h	Fri May  8 00:42:40 1998
@@ -8,8 +8,8 @@
  * some more work to get it to fit into our separate processor and
  * architecture structure.
  */
-
-static unsigned long phys_screen_end;
+extern unsigned long phys_screen_end;
+extern unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update);
 int page_nr;
 
 #define setup_processor_functions()
@@ -18,76 +18,6 @@
 static inline void setup_swapper_dir (int index, pte_t *ptep)
 {
 	set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep));
-}
-
-/*
- * This routine needs more work to make it dynamically release/allocate mem!
- */
-unsigned long map_screen_mem(unsigned long log_start, unsigned long kmem, int update)
-{
-	static int updated = 0;
-
-	if (updated)
-		return 0;
-
-	updated = update;
-
-	if (update) {
-		unsigned long address = log_start, offset;
-		pgd_t *pgdp;
-
-		kmem = (kmem + 3) & ~3;
-
-		pgdp = pgd_offset (&init_mm, address);				/* +31 */
-		offset = SCREEN_START;
-		while (address < SCREEN1_END) {
-			unsigned long addr_pmd, end_pmd;
-			pmd_t *pmdp;
-
-			/* if (pgd_none (*pgdp)) alloc pmd */
-			pmdp = pmd_offset (pgdp, address);			/* +0 */
-			addr_pmd = address & ~PGDIR_MASK;			/* 088000 */
-			end_pmd = addr_pmd + SCREEN1_END - address;		/* 100000 */
-			if (end_pmd > PGDIR_SIZE)
-				end_pmd = PGDIR_SIZE;
-
-			do {
-				unsigned long addr_pte, end_pte;
-				pte_t *ptep;
-
-				if (pmd_none (*pmdp)) {
-					pte_t *new_pte = (pte_t *)kmem;
-					kmem += PTRS_PER_PTE * BYTES_PER_PTR;
-					memzero (new_pte, PTRS_PER_PTE * BYTES_PER_PTR);
-					set_pmd (pmdp, mk_pmd(new_pte));
-				}
-
-				ptep = pte_offset (pmdp, addr_pmd);		/* +11 */
-				addr_pte = addr_pmd & ~PMD_MASK;		/* 088000 */
-				end_pte = addr_pte + end_pmd - addr_pmd;	/* 100000 */
-				if (end_pte > PMD_SIZE)
-					end_pte = PMD_SIZE;
-
-				do {
-					set_pte (ptep, mk_pte(offset, PAGE_KERNEL));
-					addr_pte += PAGE_SIZE;
-					offset += PAGE_SIZE;
-					ptep++;
-				} while (addr_pte < end_pte);
-
-				pmdp++;
-				addr_pmd = (addr_pmd + PMD_SIZE) & PMD_MASK;
-			} while (addr_pmd < end_pmd);
-
-			address = (address + PGDIR_SIZE) & PGDIR_MASK;
-			pgdp ++;
-		}
-
-		phys_screen_end = offset;
-		flush_tlb_all ();
-		update_mm_cache_all ();
-	}
-	return kmem;
 }
 
 static inline unsigned long setup_pagetables(unsigned long start_mem, unsigned long end_mem)
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/page.h linux/include/asm-arm/proc-armo/page.h
--- v2.1.100/linux/include/asm-arm/proc-armo/page.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/proc-armo/page.h	Fri May  8 00:42:40 1998
@@ -7,8 +7,16 @@
 #ifndef __ASM_PROC_PAGE_H
 #define __ASM_PROC_PAGE_H
 
-/* PAGE_SHIFT determines the page size */
-#define PAGE_SHIFT	15
+#include <linux/config.h>
+
+/* PAGE_SHIFT determines the page size.  This is configurable. */
+#if defined(CONFIG_PAGESIZE_8)
+#define PAGE_SHIFT	13		/* 8K */
+#elif defined(CONFIG_PAGESIZE_16)
+#define PAGE_SHIFT	14		/* 16K */
+#else		/* default */
+#define PAGE_SHIFT	15		/* 32K */
+#endif
 #define PAGE_SIZE       (1UL << PAGE_SHIFT)
 #define PAGE_MASK       (~(PAGE_SIZE-1))
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.1.100/linux/include/asm-arm/proc-armo/pgtable.h	Wed Apr  8 19:36:28 1998
+++ linux/include/asm-arm/proc-armo/pgtable.h	Fri May  8 00:42:40 1998
@@ -41,7 +41,7 @@
 /*
  * We have a mem map cache...
  */
-extern __inline__ void update_mm_cache_all(void)
+extern __inline__ void update_memc_all(void)
 {
 	struct task_struct *p;
 
@@ -54,7 +54,7 @@
 	processor.u.armv2._remap_memc (current);
 }
 
-extern __inline__ void update_mm_cache_task(struct task_struct *tsk)
+extern __inline__ void update_memc_task(struct task_struct *tsk)
 {
 	processor.u.armv2._update_map(tsk);
 
@@ -62,7 +62,7 @@
 		processor.u.armv2._remap_memc (tsk);
 }
 
-extern __inline__ void update_mm_cache_mm(struct mm_struct *mm)
+extern __inline__ void update_memc_mm(struct mm_struct *mm)
 {
 	struct task_struct *p;
 
@@ -77,7 +77,7 @@
 		processor.u.armv2._remap_memc (current);
 }
 
-extern __inline__ void update_mm_cache_mm_addr(struct mm_struct *mm, unsigned long addr, pte_t pte)
+extern __inline__ void update_memc_addr(struct mm_struct *mm, unsigned long addr, pte_t pte)
 {
 	struct task_struct *p;
 
@@ -117,7 +117,6 @@
 #define PTRS_PER_PTE    32
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    32
-#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SHIFT)
 
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
@@ -407,7 +406,8 @@
 {
 }
 
-extern void __bad_pte(pmd_t *pmd);
+extern void __bad_pmd(pmd_t *pmd);
+extern void __bad_pmd_kernel(pmd_t *pmd);
 
 #define pte_free_kernel(pte)    free_pte_fast(pte)
 #define pte_free(pte)           free_pte_fast(pte)
@@ -427,7 +427,7 @@
 		return page + address;
 	}
 	if (pmd_bad (*pmd)) {
-		__bad_pte(pmd);
+		__bad_pmd(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + address;
@@ -450,6 +450,7 @@
 #define pmd_alloc_kernel        pmd_alloc
 #define pte_alloc_kernel        pte_alloc
 
+#if 0
 extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
 	struct task_struct * p;
@@ -463,8 +464,9 @@
 	}
 	read_unlock(&tasklist_lock);
 	for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
-		pgd[address >> PGDIR_SHIFT)] = entry;
+		pgd[address >> PGDIR_SHIFT] = entry;
 }
+#endif
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armo/uaccess.h linux/include/asm-arm/proc-armo/uaccess.h
--- v2.1.100/linux/include/asm-arm/proc-armo/uaccess.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/proc-armo/uaccess.h	Fri May  8 00:42:40 1998
@@ -33,7 +33,7 @@
 
 #define __range_ok(addr,size) ({					\
 	unsigned long flag, sum;					\
-	__asm__ __volatile__("adds %1, %2, %3; cmpls %1, %0; movls %0, #0" \
+	__asm__ __volatile__("subs %1, %0, %3; cmpcs %1, %2; movcs %0, #0" \
 		: "=&r" (flag), "=&r" (sum)				\
 		: "r" (addr), "Ir" (size), "0" (current->addr_limit)	\
 		: "cc");						\
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h
--- v2.1.100/linux/include/asm-arm/proc-armv/pgtable.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/proc-armv/pgtable.h	Fri May  8 00:42:40 1998
@@ -45,12 +45,12 @@
 	processor.u.armv3v4._flush_icache_area((_start), (_end))
 
 /*
- * We don't have a mem map cache...
+ * We don't have a MEMC chip...
  */
-#define update_mm_cache_all()			do { } while (0)
-#define update_mm_cache_task(tsk)		do { } while (0)
-#define update_mm_cache_mm(mm)			do { } while (0)
-#define update_mm_cache_mm_addr(mm,addr,pte)	do { } while (0)
+#define update_memc_all()		do { } while (0)
+#define update_memc_task(tsk)		do { } while (0)
+#define update_memc_mm(mm)		do { } while (0)
+#define update_memc_addr(mm,addr,pte)	do { } while (0)
 
 /*
  * This flushes back any buffered write data.  We have to clean and flush the entries
@@ -133,7 +133,6 @@
 #define PTRS_PER_PTE    256
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    4096
-#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/processor.h linux/include/asm-arm/processor.h
--- v2.1.100/linux/include/asm-arm/processor.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/processor.h	Fri May  8 00:42:40 1998
@@ -42,8 +42,18 @@
 	EXTRA_THREAD_STRUCT_INIT	\
 }
 
+/* Forward declaration, a strange C thing */
+struct mm_struct;
+
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
+
+/* Copy and release all segment info associated with a VM */
+extern void copy_segments(int nr, struct task_struct *p, struct mm_struct * mm);
+extern void release_segments(struct mm_struct * mm);
+
+#define copy_segments(nr, tsk, mm)	do { } while (0)
+#define release_segments(mm)		do { } while (0)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/procinfo.h linux/include/asm-arm/procinfo.h
--- v2.1.100/linux/include/asm-arm/procinfo.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/procinfo.h	Fri May  8 00:42:40 1998
@@ -18,13 +18,17 @@
 #ifndef __ASSEMBLER__
 
 struct armversions {
-	unsigned long id;
-	unsigned long mask;
-	unsigned long features;
-	const char *manu;
-	const char *name;
-	const struct processor *proc;
+	unsigned long id;		/* Processor ID			*/
+	unsigned long mask;		/* Processor ID mask		*/
+	unsigned long features;		/* Features (see above)		*/
+	const char *manu;		/* Manufacturer			*/
+	const char *name;		/* Processor name		*/
+	const struct processor *proc;	/* Processor-specific ASM	*/
+	const char *optname;		/* Optimisation name		*/
 };
+
+extern struct armversions armidlist[];
+extern int armidindex;
 
 #endif
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-arm/stat.h linux/include/asm-arm/stat.h
--- v2.1.100/linux/include/asm-arm/stat.h	Wed Apr  8 19:36:28 1998
+++ linux/include/asm-arm/stat.h	Fri May  8 00:42:40 1998
@@ -38,6 +38,7 @@
 	unsigned long  __unused5;
 };
 
+#if 0
 typedef struct {
 	unsigned int	minor;
 	unsigned int	major;
@@ -73,5 +74,5 @@
 #define __XSTAT_VER_TYPEMASK	0xff00
 
 #define __XMKNOD_VER_1		1
-
+#endif
 #endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h
--- v2.1.100/linux/include/asm-i386/hardirq.h	Fri Jan 30 15:50:57 1998
+++ linux/include/asm-i386/hardirq.h	Fri May  8 00:31:10 1998
@@ -5,6 +5,12 @@
 
 extern unsigned int local_irq_count[NR_CPUS];
 
+/*
+ * Are we in an interrupt context? Either doing bottom half
+ * or hardware interrupt processing?
+ */
+#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0)
+
 #ifndef __SMP__
 
 #define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/md.h linux/include/asm-i386/md.h
--- v2.1.100/linux/include/asm-i386/md.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/md.h	Fri May  8 00:17:13 1998
@@ -0,0 +1,13 @@
+/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $
+ * md.h: High speed xor_block operation for RAID4/5 
+ *
+ */
+ 
+#ifndef __ASM_MD_H
+#define __ASM_MD_H
+
+/* #define HAVE_ARCH_XORBLOCK */
+
+#define MD_XORBLOCK_ALIGNMENT	sizeof(long)
+
+#endif /* __ASM_MD_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.1.100/linux/include/asm-i386/smp.h	Sat May  2 14:19:54 1998
+++ linux/include/asm-i386/smp.h	Fri May  8 00:45:50 1998
@@ -184,6 +184,7 @@
 extern void smp_callin(void);
 extern void smp_boot_cpus(void);
 extern void smp_store_cpu_info(int id);		/* Store per cpu info (like the initial udelay numbers */
+extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
 
 extern volatile unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */
 extern volatile int smp_process_available;
diff -u --recursive --new-file v2.1.100/linux/include/asm-i386/timex.h linux/include/asm-i386/timex.h
--- v2.1.100/linux/include/asm-i386/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-i386/timex.h
+ *
+ * i386 architecture timex specifications
+ */
+#ifndef _ASMi386_TIMEX_H
+#define _ASMi386_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#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)
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/adb.h linux/include/asm-m68k/adb.h
--- v2.1.100/linux/include/asm-m68k/adb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/adb.h	Fri May  8 00:15:22 1998
@@ -0,0 +1,75 @@
+/*
+ * Definitions for talking to ADB and CUDA.  The CUDA is a microcontroller
+ * which controls the ADB, system power, RTC, and various other things on
+ * later Macintoshes
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+
+/* First byte sent to or received from CUDA */
+#define ADB_PACKET	0
+#define CUDA_PACKET	1
+#define ERROR_PACKET	2
+#define TIMER_PACKET	3
+#define POWER_PACKET	4
+#define MACIIC_PACKET	5
+
+/* ADB commands (2nd byte) */
+#define ADB_BUSRESET		0
+#define ADB_FLUSH(id)		(1 + ((id) << 4))
+#define ADB_WRITEREG(id, reg)	(8 + (reg) + ((id) << 4))
+#define ADB_READREG(id, reg)	(0xc + (reg) + ((id) << 4))
+
+/* ADB default device IDs (upper 4 bits of 2nd byte) */
+#define ADB_DONGLE	1	/* "software execution control" devices */
+#define ADB_KEYBOARD	2
+#define ADB_MOUSE	3
+#define ADB_TABLET	4
+#define ADB_MODEM	5
+#define ADB_MISC	7	/* maybe a monitor */
+
+/* CUDA commands (2nd byte) */
+#define CUDA_WARM_START		0
+#define CUDA_AUTOPOLL		1
+#define CUDA_GET_6805_ADDR	2
+#define CUDA_GET_TIME		3
+#define CUDA_GET_PRAM		7
+#define CUDA_SET_6805_ADDR	8
+#define CUDA_SET_TIME		9
+#define CUDA_POWERDOWN		0xa
+#define CUDA_POWERUP_TIME	0xb
+#define CUDA_SET_PRAM		0xc
+#define CUDA_MS_RESET		0xd
+#define CUDA_SEND_DFAC		0xe
+#define CUDA_RESET_SYSTEM	0x11
+#define CUDA_SET_IPL		0x12
+#define CUDA_SET_AUTO_RATE	0x14
+#define CUDA_GET_AUTO_RATE	0x16
+#define CUDA_SET_DEVICE_LIST	0x19
+#define CUDA_GET_DEVICE_LIST	0x1a
+#define CUDA_GET_SET_IIC	0x22
+
+#ifdef __KERNEL__
+
+struct adb_request {
+    unsigned char data[16];
+    int nbytes;
+    unsigned char reply[16];
+    int reply_len;
+    unsigned char reply_expected;
+    unsigned char sent;
+    unsigned char got_reply;
+    void (*done)(struct adb_request *);
+    void *arg;
+    struct adb_request *next;
+};
+
+void via_adb_init(void);
+int adb_request(struct adb_request *req,
+		 void (*done)(struct adb_request *), int nbytes, ...);
+int adb_send_request(struct adb_request *req);
+void adb_poll(void);
+int adb_register(int default_id,
+		 void (*handler)(unsigned char *, int, struct pt_regs *));
+
+#endif	/* __KERNEL */
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/linux_logo.h linux/include/asm-m68k/linux_logo.h
--- v2.1.100/linux/include/asm-m68k/linux_logo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/linux_logo.h	Fri May  8 00:15:22 1998
@@ -0,0 +1,69 @@
+/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $
+ * include/asm-m68k/linux_logo.h: This is a linux logo
+ *                                 to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ *	     linux_logo_green[0],
+ *	     linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+ 
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/m68k version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 221
+
+#ifdef INCLUDE_LINUX_LOGO_DATA
+
+#define INCLUDE_LINUX_LOGO16
+#include <linux/linux_logo.h>
+
+/* Painted by Johnny Stenback <jst@uwasa.fi> */
+
+unsigned char *linux_serial_image __initdata = "\n"
+"         .u$e.\n"
+"       .$$$$$:S\n"
+"       $\"*$/\"*$$\n"
+"       $.`$ . ^F\n"
+"       4k+#+T.$F\n"
+"       4P+++\"$\"$\n"
+"       :R\"+  t$$B\n"
+"    ___#       $$$\n"
+"    |  |       R$$k\n"
+"   dd. | Linux  $!$\n"
+"   ddd |  m68k  $9$F\n"
+" '!!!!!$       !!#!`\n"
+"  !!!!!*     .!!!!!`\n"
+"'!!!!!!!W..e$$!!!!!!`    %s\n"
+" \"~^^~         ^~~^\n"
+"\n";
+
+#else
+
+/* prototypes only */
+extern unsigned char linux_logo_red[];
+extern unsigned char linux_logo_green[];
+extern unsigned char linux_logo_blue[];
+extern unsigned char linux_logo[];
+extern unsigned char linux_logo_bw[];
+extern unsigned char linux_logo16_red[];
+extern unsigned char linux_logo16_green[];
+extern unsigned char linux_logo16_blue[];
+extern unsigned char linux_logo16[];
+extern unsigned char *linux_serial_image;
+
+extern int (*console_show_logo)(void);
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/macintosh.h linux/include/asm-m68k/macintosh.h
--- v2.1.100/linux/include/asm-m68k/macintosh.h	Tue Feb 17 13:12:49 1998
+++ linux/include/asm-m68k/macintosh.h	Fri May  8 00:15:22 1998
@@ -56,6 +56,8 @@
 #define MAC_ADB_II		1
 #define MAC_ADB_IISI		2
 #define MAC_ADB_CUDA		3
+#define MAC_ADB_PB1		4
+#define MAC_ADB_PB2		5
 
 #define MAC_VIA_II		1
 #define MAC_VIA_IIci		2
@@ -93,7 +95,7 @@
 #define MAC_MODEL_IIFX		13	/* And well numbered it is too */
 #define MAC_MODEL_IISI		18
 #define MAC_MODEL_Q900		20
-#define MAC_MODEL_PB170		25
+#define MAC_MODEL_PB170		21
 #define MAC_MODEL_Q700		22
 #define MAC_MODEL_CLII		23
 #define MAC_MODEL_PB140		25
@@ -109,6 +111,7 @@
 #define MAC_MODEL_LCII		37	/* aka: P400/405/410/430 */
 #define MAC_MODEL_PB250		38
 #define MAC_MODEL_IIVI		44
+#define MAC_MODEL_P600		45
 #define MAC_MODEL_IIVX		48
 #define MAC_MODEL_CCL		49
 #define MAC_MODEL_PB165C	50
@@ -123,6 +126,7 @@
 #define MAC_MODEL_PB270C	77
 #define MAC_MODEL_Q840		78
 #define MAC_MODEL_P550		80
+#define MAC_MODEL_CCLII		83
 #define MAC_MODEL_PB165		84
 #define MAC_MODEL_PB190 	85
 #define MAC_MODEL_TV		88
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/macints.h linux/include/asm-m68k/macints.h
--- v2.1.100/linux/include/asm-m68k/macints.h	Tue Feb 17 13:12:49 1998
+++ linux/include/asm-m68k/macints.h	Fri May  8 00:15:22 1998
@@ -143,7 +143,7 @@
 void mac_turnoff_irq( unsigned irq );
 void mac_clear_pending_irq( unsigned irq );
 int  mac_irq_pending( unsigned irq );
-int  nubus_request_irq(int slot, void (*handler)(int,void *,struct pt_regs *));
+int  nubus_request_irq(int slot, void *dev_id, void (*handler)(int,void *,struct pt_regs *));
 int  nubus_free_irq(int slot);
 
 unsigned long mac_register_nubus_int( void );
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/md.h linux/include/asm-m68k/md.h
--- v2.1.100/linux/include/asm-m68k/md.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/md.h	Fri May  8 00:15:22 1998
@@ -0,0 +1,13 @@
+/* $Id: md.h,v 1.1 1997/12/15 15:12:04 jj Exp $
+ * md.h: High speed xor_block operation for RAID4/5 
+ *
+ */
+ 
+#ifndef __ASM_MD_H
+#define __ASM_MD_H
+
+/* #define HAVE_ARCH_XORBLOCK */
+
+#define MD_XORBLOCK_ALIGNMENT	sizeof(long)
+
+#endif /* __ASM_MD_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h
--- v2.1.100/linux/include/asm-m68k/page.h	Wed Apr 23 19:01:27 1997
+++ linux/include/asm-m68k/page.h	Fri May  8 00:15:22 1998
@@ -12,6 +12,9 @@
 
 #define STRICT_MM_TYPECHECKS
 
+#define get_user_page(vaddr)	__get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)	free_page(addr)
+
 /*
  * We don't need to check for alignment etc.
  */
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h
--- v2.1.100/linux/include/asm-m68k/pgtable.h	Tue Feb 17 13:12:49 1998
+++ linux/include/asm-m68k/pgtable.h	Fri May  8 00:15:22 1998
@@ -5,6 +5,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/processor.h>	/* For TASK_SIZE */
+
 /*
  * This file contains the functions and defines necessary to modify and use
  * the m68k page table tree.
@@ -263,6 +265,7 @@
 #define PTRS_PER_PTE	1024
 #define PTRS_PER_PMD	8
 #define PTRS_PER_PGD	128
+#define USER_PTRS_PER_PGD	(TASK_SIZE / PGDIR_SIZE)
 
 /* the no. of pointers that fit on a page: this will go away */
 #define PTRS_PER_PAGE	(PAGE_SIZE/sizeof(void*))
@@ -584,40 +587,94 @@
 	}
 }
 
+extern struct pgtable_cache_struct {
+	unsigned long *pte_cache;
+	unsigned long pgtable_cache_sz;
+} quicklists;
+#define pgd_quicklist ((unsigned long *)0)
+#define pmd_quicklist ((unsigned long *)0)
+#define pte_quicklist (quicklists.pte_cache)
+#define pgtable_cache_size (quicklists.pgtable_cache_sz)
+
+/* We don't use pgd cache yet, so this is a dummy routine */
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+	return (pgd_t *)0;
+}
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+}
+
+/* We don't use pmd cache yet, so this is a dummy routine */
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+	return (pmd_t *)0;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+}
+
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+
+extern __inline__ pte_t *get_pte_fast(void)
+{
+        unsigned long *ret;
+
+        if((ret = (unsigned long *)pte_quicklist) != NULL) {
+                pte_quicklist = (unsigned long *)(*ret);
+                ret[0] = ret[1];
+                pgtable_cache_size--;
+        }
+        return (pte_t *)ret;
+}
+
+extern __inline__ void free_pte_fast(pte_t *pte)
+{
+        *(unsigned long *)pte = (unsigned long) pte_quicklist;
+        pte_quicklist = (unsigned long *) pte;
+        pgtable_cache_size++;
+}
+
+extern __inline__ void free_pte_slow(pte_t *pte)
+{
+	cache_page((unsigned long)pte);
+	free_page((unsigned long)pte);
+}
+
+extern void __bad_pte(pmd_t *pmd);
 
 extern const char PgtabStr_bad_pmd[];
 extern const char PgtabStr_bad_pgd[];
 extern const char PgtabStr_bad_pmdk[];
 extern const char PgtabStr_bad_pgdk[];
 
-extern inline void pte_free(pte_t * pte)
-{
-	cache_page((unsigned long)pte);
-	free_page((unsigned long) pte);
-}
+#define pte_free		free_pte_fast
+#define pte_free_kernel		free_pte_fast
+#define pte_alloc_kernel	pte_alloc
 
 extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
 {
 	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
 	if (pmd_none(*pmd)) {
-		pte_t * page = (pte_t *)__get_free_page(GFP_KERNEL);
-		if (pmd_none(*pmd)) {
-			if (page) {
-				memset((void *) page, 0, PAGE_SIZE);
-				flush_page_to_ram((unsigned long)page);
-				flush_tlb_kernel_page((unsigned long)page);
-				nocache_page((unsigned long)page);
-				pmd_set(pmd,page);
-				return page + address;
-			}
-			pmd_set(pmd, BAD_PAGETABLE);
-			return NULL;
-		}
-		free_page((unsigned long)page);
+		pte_t * page = (pte_t *)get_pte_fast();
+		
+		if (!page)
+			return get_pte_slow(pmd, address);
+		pmd_set(pmd,page);
+		return page + address;
 	}
 	if (pmd_bad(*pmd)) {
-		printk(PgtabStr_bad_pmd, pmd_val(*pmd));
-		pmd_set(pmd, BAD_PAGETABLE);
+		__bad_pte(pmd);
 		return NULL;
 	}
 	return (pte_t *) pmd_page(*pmd) + address;
@@ -656,37 +713,6 @@
 	return (pmd_t *) pgd_page(*pgd) + address;
 }
 
-extern inline void pte_free_kernel(pte_t * pte)
-{
-	cache_page((unsigned long)pte);
-	free_page((unsigned long) pte);
-}
-
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
-{
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-	if (pmd_none(*pmd)) {
-		pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
-		if (pmd_none(*pmd)) {
-			if (page) {
-				flush_tlb_kernel_page((unsigned long)page);
-				nocache_page((unsigned long)page);
-				pmd_set(pmd, page);
-				return page + address;
-			}
-			pmd_set(pmd, BAD_PAGETABLE);
-			return NULL;
-		}
-		free_page((unsigned long) page);
-	}
-	if (pmd_bad(*pmd)) {
-		printk(PgtabStr_bad_pmdk, pmd_val(*pmd));
-		pmd_set(pmd, BAD_PAGETABLE);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
-}
-
 extern inline void pmd_free_kernel(pmd_t * pmd)
 {
 	free_kpointer_table(pmd);
@@ -722,7 +748,21 @@
 
 extern inline pgd_t * pgd_alloc(void)
 {
-	return (pgd_t *)get_pointer_table ();
+	pgd_t *ret = (pgd_t *)get_pointer_table ();
+	
+	if (ret) {
+		pgd_t * init;
+
+		init = pgd_offset(&init_mm, 0);
+		memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof (pgd_t));
+	}
+	return ret;
+}
+
+extern inline void set_pgdir(unsigned long address, pgd_t entry)
+{
+	/* Nothing to do on m68k */
 }
 
 /*
@@ -777,9 +817,13 @@
 #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << PAGE_SHIFT))
 #endif
 
-#endif /* __ASSEMBLY__ */
-
 #define module_map      vmalloc
 #define module_unmap    vfree
+#define module_shrink	vshrink
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page)		(0)
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _M68K_PGTABLE_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.1.100/linux/include/asm-m68k/processor.h	Tue Feb 17 13:12:49 1998
+++ linux/include/asm-m68k/processor.h	Fri May  8 00:15:22 1998
@@ -19,7 +19,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	0xC0000000UL
+#define TASK_UNMAPPED_BASE(off)	0xC0000000UL
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 /*
  * Bus types
@@ -93,6 +94,9 @@
 	else
 		return sw->retpc;
 }
+
+#define copy_segments(nr, tsk, mm)	do { } while (0)
+#define release_segments(mm)		do { } while (0)
 
 /* Allocation and freeing of basic task resources. */
 #define alloc_task_struct() \
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/stat.h linux/include/asm-m68k/stat.h
--- v2.1.100/linux/include/asm-m68k/stat.h	Fri Nov 22 05:56:36 1996
+++ linux/include/asm-m68k/stat.h	Fri May  8 00:15:22 1998
@@ -38,4 +38,40 @@
 	unsigned long  __unused5;
 };
 
+typedef struct {
+	unsigned int	major;
+	unsigned int	minor;
+} __new_dev_t;
+
+struct stat64 {
+	__new_dev_t	st_dev;
+	__u64		st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+	unsigned int	st_uid;
+	unsigned int	st_gid;
+	__new_dev_t	st_rdev;
+	__s64		st_size;
+	__u64		st_blocks;
+	unsigned long	st_atime;
+	unsigned long	__unused1;
+	unsigned long	st_mtime;
+	unsigned long	__unused2;
+	unsigned long	st_ctime;
+	unsigned long	__unused3;
+	unsigned long	st_blksize;
+	unsigned long	__unused4;
+};
+
+#define __XSTAT_VER_1		1
+#define __XSTAT_VER_2		2
+#define __XSTAT_VER_MASK	0xff
+
+#define __XSTAT_VER_XSTAT	0x000
+#define __XSTAT_VER_LXSTAT	0x100
+#define __XSTAT_VER_FXSTAT	0x200
+#define __XSTAT_VER_TYPEMASK	0xff00
+
+#define __XMKNOD_VER_1		1
+
 #endif /* _M68K_STAT_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/timex.h linux/include/asm-m68k/timex.h
--- v2.1.100/linux/include/asm-m68k/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-m68k/timex.h
+ *
+ * m68k architecture timex specifications
+ */
+#ifndef _ASMm68k_TIMEX_H
+#define _ASMm68k_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#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)
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-m68k/xstat.h linux/include/asm-m68k/xstat.h
--- v2.1.100/linux/include/asm-m68k/xstat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/xstat.h	Fri May  8 00:15:22 1998
@@ -0,0 +1,35 @@
+/* $Id: xstat.h,v 1.1 1998/02/06 12:51:30 jj Exp $
+ * xstat.h: sys_xstat/xmknod architecture dependent stuff.
+ *
+ * Copyright (C) 1998  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
+ */
+ 
+extern __inline__ int cp_xstat(struct inode *inode, struct stat64 *s, unsigned long blocks, int blksize)
+{
+	struct stat64 tmp;
+	
+	memset (&tmp, 0, sizeof(tmp));
+	tmp.st_dev.major = MAJOR(inode->i_dev);
+	tmp.st_dev.minor = MINOR(inode->i_dev);
+	tmp.st_ino = inode->i_ino;
+	tmp.st_mode = inode->i_mode;
+	tmp.st_nlink = inode->i_nlink;
+	tmp.st_uid = inode->i_uid;
+	tmp.st_gid = inode->i_gid;
+	tmp.st_rdev.major = MAJOR(inode->i_rdev);
+	tmp.st_rdev.minor = MINOR(inode->i_rdev);
+	tmp.st_size = inode->i_size;
+	tmp.st_blksize = blksize;
+	tmp.st_blocks = blocks;
+	tmp.st_atime = inode->i_atime;
+	tmp.st_mtime = inode->i_mtime;
+	tmp.st_ctime = inode->i_ctime;
+	return copy_to_user(s,&tmp,sizeof(tmp));
+}
+
+extern __inline__ int get_user_new_dev_t(kdev_t *kdev, __new_dev_t *udev) {
+	__new_dev_t ndev;
+	if (copy_from_user (&ndev, udev, sizeof(__new_dev_t))) return -EFAULT;
+	*kdev = MKDEV(ndev.major, ndev.minor);
+	return 0;
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h
--- v2.1.100/linux/include/asm-mips/asmmacro.h	Wed Dec 10 10:31:10 1997
+++ linux/include/asm-mips/asmmacro.h	Fri May  8 00:13:26 1998
@@ -1,89 +1,161 @@
-/* $Id: asmmacro.h,v 1.1.1.1 1997/06/01 03:17:13 ralf Exp $
+/*
  * asmmacro.h: Assembler macros to make things easier to read.
  *
  * 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 $
  */
-
 #ifndef __MIPS_ASMMACRO_H
 #define __MIPS_ASMMACRO_H
 
 #include <asm/offset.h>
 
-#define FPU_SAVE_16ODD(thread) \
-	swc1	$f1,  (THREAD_FPU + 0x08)(thread); \
-	swc1	$f3,  (THREAD_FPU + 0x18)(thread); \
-	swc1	$f5,  (THREAD_FPU + 0x28)(thread); \
-	swc1	$f7,  (THREAD_FPU + 0x38)(thread); \
-	swc1	$f9,  (THREAD_FPU + 0x48)(thread); \
-	swc1	$f11, (THREAD_FPU + 0x58)(thread); \
-	swc1	$f13, (THREAD_FPU + 0x68)(thread); \
-	swc1	$f15, (THREAD_FPU + 0x78)(thread); \
-	swc1	$f17, (THREAD_FPU + 0x88)(thread); \
-	swc1	$f19, (THREAD_FPU + 0x98)(thread); \
-	swc1	$f21, (THREAD_FPU + 0xa8)(thread); \
-	swc1	$f23, (THREAD_FPU + 0xb8)(thread); \
-	swc1	$f25, (THREAD_FPU + 0xc8)(thread); \
-	swc1	$f27, (THREAD_FPU + 0xd8)(thread); \
-	swc1	$f29, (THREAD_FPU + 0xe8)(thread); \
-	swc1	$f31, (THREAD_FPU + 0xf8)(thread);
-
-
-#define FPU_RESTORE_16ODD(thread)  \
-	lwc1	$f1,  (THREAD_FPU + 0x08)(thread); \
-	lwc1	$f3,  (THREAD_FPU + 0x18)(thread); \
-	lwc1	$f5,  (THREAD_FPU + 0x28)(thread); \
-	lwc1	$f7,  (THREAD_FPU + 0x38)(thread); \
-	lwc1	$f9,  (THREAD_FPU + 0x48)(thread); \
-	lwc1	$f11, (THREAD_FPU + 0x58)(thread); \
-	lwc1	$f13, (THREAD_FPU + 0x68)(thread); \
-	lwc1	$f15, (THREAD_FPU + 0x78)(thread); \
-	lwc1	$f17, (THREAD_FPU + 0x88)(thread); \
-	lwc1	$f19, (THREAD_FPU + 0x98)(thread); \
-	lwc1	$f21, (THREAD_FPU + 0xa8)(thread); \
-	lwc1	$f23, (THREAD_FPU + 0xb8)(thread); \
-	lwc1	$f25, (THREAD_FPU + 0xc8)(thread); \
-	lwc1	$f27, (THREAD_FPU + 0xd8)(thread); \
-	lwc1	$f29, (THREAD_FPU + 0xe8)(thread); \
-	lwc1	$f31, (THREAD_FPU + 0xf8)(thread);
-
 #define FPU_SAVE_16EVEN(thread, tmp) \
 	cfc1	tmp,  fcr31;                    \
+	sdc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	sdc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	sdc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	sdc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	sdc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	sdc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	sdc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	sdc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	sdc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	sdc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	sdc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	sdc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	sdc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	sdc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	sdc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	sw	tmp,  (THREAD_FPU + 0x100)(thread)
+
+#define FPU_SAVE_16ODD(thread) \
+	sdc1	$f1,  (THREAD_FPU + 0x08)(thread); \
+	sdc1	$f3,  (THREAD_FPU + 0x18)(thread); \
+	sdc1	$f5,  (THREAD_FPU + 0x28)(thread); \
+	sdc1	$f7,  (THREAD_FPU + 0x38)(thread); \
+	sdc1	$f9,  (THREAD_FPU + 0x48)(thread); \
+	sdc1	$f11, (THREAD_FPU + 0x58)(thread); \
+	sdc1	$f13, (THREAD_FPU + 0x68)(thread); \
+	sdc1	$f15, (THREAD_FPU + 0x78)(thread); \
+	sdc1	$f17, (THREAD_FPU + 0x88)(thread); \
+	sdc1	$f19, (THREAD_FPU + 0x98)(thread); \
+	sdc1	$f21, (THREAD_FPU + 0xa8)(thread); \
+	sdc1	$f23, (THREAD_FPU + 0xb8)(thread); \
+	sdc1	$f25, (THREAD_FPU + 0xc8)(thread); \
+	sdc1	$f27, (THREAD_FPU + 0xd8)(thread); \
+	sdc1	$f29, (THREAD_FPU + 0xe8)(thread); \
+	sdc1	$f31, (THREAD_FPU + 0xf8)(thread)
+
+#define FPU_SAVE(thread,tmp)                        \
+	cfc1	tmp,  fcr31;                        \
+	swc1	$f0,  (THREAD_FPU + 0x000)(thread); \
+	swc1	$f1,  (THREAD_FPU + 0x008)(thread); \
 	swc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	swc1	$f3,  (THREAD_FPU + 0x018)(thread); \
 	swc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	swc1	$f5,  (THREAD_FPU + 0x028)(thread); \
 	swc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	swc1	$f7,  (THREAD_FPU + 0x038)(thread); \
 	swc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	swc1	$f9,  (THREAD_FPU + 0x048)(thread); \
 	swc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	swc1	$f11, (THREAD_FPU + 0x058)(thread); \
 	swc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	swc1	$f13, (THREAD_FPU + 0x068)(thread); \
 	swc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	swc1	$f15, (THREAD_FPU + 0x078)(thread); \
 	swc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	swc1	$f17, (THREAD_FPU + 0x088)(thread); \
 	swc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	swc1	$f19, (THREAD_FPU + 0x098)(thread); \
 	swc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	swc1	$f21, (THREAD_FPU + 0x0a8)(thread); \
 	swc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	swc1	$f23, (THREAD_FPU + 0x0b8)(thread); \
 	swc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	swc1	$f25, (THREAD_FPU + 0x0c8)(thread); \
 	swc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	swc1	$f27, (THREAD_FPU + 0x0d8)(thread); \
 	swc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	swc1	$f29, (THREAD_FPU + 0x0e8)(thread); \
 	swc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
-	sw	tmp,  (THREAD_FPU + 0x100)(thread);
-
+	swc1	$f31, (THREAD_FPU + 0x0f8)(thread); \
+	sw	tmp,  (THREAD_FPU + 0x100)(thread)
 
 #define FPU_RESTORE_16EVEN(thread, tmp) \
 	lw	tmp,  (THREAD_FPU + 0x100)(thread); \
+	ldc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	ldc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	ldc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	ldc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	ldc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	ldc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	ldc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	ldc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	ldc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	ldc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	ldc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	ldc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	ldc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	ldc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	ldc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
+	ctc1	tmp,  fcr31
+
+#define FPU_RESTORE_16ODD(thread)  \
+	ldc1	$f1,  (THREAD_FPU + 0x08)(thread); \
+	ldc1	$f3,  (THREAD_FPU + 0x18)(thread); \
+	ldc1	$f5,  (THREAD_FPU + 0x28)(thread); \
+	ldc1	$f7,  (THREAD_FPU + 0x38)(thread); \
+	ldc1	$f9,  (THREAD_FPU + 0x48)(thread); \
+	ldc1	$f11, (THREAD_FPU + 0x58)(thread); \
+	ldc1	$f13, (THREAD_FPU + 0x68)(thread); \
+	ldc1	$f15, (THREAD_FPU + 0x78)(thread); \
+	ldc1	$f17, (THREAD_FPU + 0x88)(thread); \
+	ldc1	$f19, (THREAD_FPU + 0x98)(thread); \
+	ldc1	$f21, (THREAD_FPU + 0xa8)(thread); \
+	ldc1	$f23, (THREAD_FPU + 0xb8)(thread); \
+	ldc1	$f25, (THREAD_FPU + 0xc8)(thread); \
+	ldc1	$f27, (THREAD_FPU + 0xd8)(thread); \
+	ldc1	$f29, (THREAD_FPU + 0xe8)(thread); \
+	ldc1	$f31, (THREAD_FPU + 0xf8)(thread)
+
+#define FPU_RESTORE(thread,tmp)                     \
+	lw	tmp,  (THREAD_FPU + 0x100)(thread); \
+	lwc1	$f0,  (THREAD_FPU + 0x000)(thread); \
+	lwc1	$f1,  (THREAD_FPU + 0x008)(thread); \
 	lwc1	$f2,  (THREAD_FPU + 0x010)(thread); \
+	lwc1	$f3,  (THREAD_FPU + 0x018)(thread); \
 	lwc1	$f4,  (THREAD_FPU + 0x020)(thread); \
+	lwc1	$f5,  (THREAD_FPU + 0x028)(thread); \
 	lwc1	$f6,  (THREAD_FPU + 0x030)(thread); \
+	lwc1	$f7,  (THREAD_FPU + 0x038)(thread); \
 	lwc1	$f8,  (THREAD_FPU + 0x040)(thread); \
+	lwc1	$f9,  (THREAD_FPU + 0x048)(thread); \
 	lwc1	$f10, (THREAD_FPU + 0x050)(thread); \
+	lwc1	$f11, (THREAD_FPU + 0x058)(thread); \
 	lwc1	$f12, (THREAD_FPU + 0x060)(thread); \
+	lwc1	$f13, (THREAD_FPU + 0x068)(thread); \
 	lwc1	$f14, (THREAD_FPU + 0x070)(thread); \
+	lwc1	$f15, (THREAD_FPU + 0x078)(thread); \
 	lwc1	$f16, (THREAD_FPU + 0x080)(thread); \
+	lwc1	$f17, (THREAD_FPU + 0x088)(thread); \
 	lwc1	$f18, (THREAD_FPU + 0x090)(thread); \
+	lwc1	$f19, (THREAD_FPU + 0x098)(thread); \
 	lwc1	$f20, (THREAD_FPU + 0x0a0)(thread); \
+	lwc1	$f21, (THREAD_FPU + 0x0a8)(thread); \
 	lwc1	$f22, (THREAD_FPU + 0x0b0)(thread); \
+	lwc1	$f23, (THREAD_FPU + 0x0b8)(thread); \
 	lwc1	$f24, (THREAD_FPU + 0x0c0)(thread); \
+	lwc1	$f25, (THREAD_FPU + 0x0c8)(thread); \
 	lwc1	$f26, (THREAD_FPU + 0x0d0)(thread); \
+	lwc1	$f27, (THREAD_FPU + 0x0d8)(thread); \
 	lwc1	$f28, (THREAD_FPU + 0x0e0)(thread); \
+	lwc1	$f29, (THREAD_FPU + 0x0e8)(thread); \
 	lwc1	$f30, (THREAD_FPU + 0x0f0)(thread); \
-	ctc1	tmp,  fcr31;
+	lwc1	$f31, (THREAD_FPU + 0x0f8)(thread); \
+	ctc1	tmp,  fcr31
 
 #define CPU_SAVE_NONSCRATCH(thread) \
 	sw	s0, THREAD_REG16(thread); \
@@ -94,9 +166,8 @@
 	sw	s5, THREAD_REG21(thread); \
 	sw	s6, THREAD_REG22(thread); \
 	sw	s7, THREAD_REG23(thread); \
-	sw	gp, THREAD_REG28(thread); \
 	sw	sp, THREAD_REG29(thread); \
-	sw	fp, THREAD_REG30(thread);
+	sw	fp, THREAD_REG30(thread)
 
 #define CPU_RESTORE_NONSCRATCH(thread) \
 	lw	s0, THREAD_REG16(thread); \
@@ -107,9 +178,8 @@
 	lw	s5, THREAD_REG21(thread); \
 	lw	s6, THREAD_REG22(thread); \
 	lw	s7, THREAD_REG23(thread); \
-	lw	gp, THREAD_REG28(thread); \
 	lw	sp, THREAD_REG29(thread); \
 	lw	fp, THREAD_REG30(thread); \
-	lw	ra, THREAD_REG31(thread);
+	lw	ra, THREAD_REG31(thread)
 
 #endif /* !(__MIPS_ASMMACRO_H) */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h
--- v2.1.100/linux/include/asm-mips/atomic.h	Tue Dec 16 12:45:55 1997
+++ linux/include/asm-mips/atomic.h	Fri May  8 00:13:26 1998
@@ -9,9 +9,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: atomic.h,v 1.2 1997/06/20 03:05:12 ralf Exp $
+ * $Id: atomic.h,v 1.4 1998/05/01 01:35:45 ralf Exp $
  */
 #ifndef __ASM_MIPS_ATOMIC_H
 #define __ASM_MIPS_ATOMIC_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/bcache.h linux/include/asm-mips/bcache.h
--- v2.1.100/linux/include/asm-mips/bcache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/bcache.h	Fri May  8 00:13:26 1998
@@ -0,0 +1,22 @@
+/*
+ * include/asm-mips/bcache.h
+ *
+ * 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: bcache.h,v 1.1 1998/05/01 01:35:46 ralf Exp $
+ */
+struct bcache_ops {
+	void (*bc_enable)(void);
+	void (*bc_disable)(void);
+	void (*bc_wback_inv)(unsigned long page, unsigned long size);
+	void (*bc_inv)(unsigned long page, unsigned long size);
+};
+
+extern void indy_sc_init(void);
+extern void sni_pcimt_sc_init(void);
+
+extern struct bcache_ops *bcops;
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h
--- v2.1.100/linux/include/asm-mips/bootinfo.h	Tue Dec 16 12:45:55 1997
+++ linux/include/asm-mips/bootinfo.h	Fri May  8 00:13:26 1998
@@ -8,7 +8,7 @@
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
- * $Id: bootinfo.h,v 1.3 1997/09/19 08:37:44 ralf Exp $
+ * $Id: bootinfo.h,v 1.7 1998/05/01 01:35:46 ralf Exp $
  */
 #ifndef __ASM_MIPS_BOOTINFO_H
 #define __ASM_MIPS_BOOTINFO_H
@@ -26,9 +26,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 GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", \
-                      "SNI", "ACN", "SGI" }
+                      "SNI", "ACN", "SGI", "NSA" }
 
 /*
  * Valid machtype values for group unknown (low order halfword of mips_machtype)
@@ -81,8 +82,6 @@
  * Valid machtype for group SGI
  */
 #define MACH_SGI_INDY		0	/* R4?K and R5K Indy workstaions */
-
-#define GROUP_SGI_NAMES { "Indy" }
 
 #define GROUP_SGI_NAMES { "Indy" }
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/branch.h linux/include/asm-mips/branch.h
--- v2.1.100/linux/include/asm-mips/branch.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/branch.h	Fri May  8 00:13:26 1998
@@ -5,7 +5,9 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
+ *
+ * $Id: branch.h,v 1.2 1998/05/04 09:18:56 ralf Exp $
  */
 #include <asm/ptrace.h>
 
@@ -15,12 +17,13 @@
 }
 
 extern int __compute_return_epc(struct pt_regs *regs);
+
 extern inline int compute_return_epc(struct pt_regs *regs)
 {
-	if (delay_slot(regs)) {
-		return __compute_return_epc(regs);
+	if (!delay_slot(regs)) {
+		regs->cp0_epc += 4;
+		return 0;
 	}
 
-	regs->cp0_epc += 4;
-	return 0;
+	return __compute_return_epc(regs);
 }
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h
--- v2.1.100/linux/include/asm-mips/bugs.h	Tue Dec 16 12:45:55 1997
+++ linux/include/asm-mips/bugs.h	Fri May  8 00:13:26 1998
@@ -4,7 +4,7 @@
  *  Copyright (C) 1995  Waldorf Electronics
  *  Copyright (C) 1997  Ralf Baechle
  *
- * $Id: bugs.h,v 1.2 1997/09/07 04:13:53 ralf Exp $
+ * $Id: bugs.h,v 1.4 1998/05/01 01:35:47 ralf Exp $
  */
 #include <asm/bootinfo.h>
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h
--- v2.1.100/linux/include/asm-mips/cpu.h	Wed Dec 10 10:31:10 1997
+++ linux/include/asm-mips/cpu.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: cpu.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
+/* $Id: cpu.h,v 1.2 1998/05/01 01:35:49 ralf Exp $
  * cpu.h: Values of the PRId register used to match up
  *        various MIPS cpu types.
  *
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/current.h linux/include/asm-mips/current.h
--- v2.1.100/linux/include/asm-mips/current.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/current.h	Fri May  8 00:13:26 1998
@@ -3,33 +3,13 @@
 
 #ifdef __LANGUAGE_C__
 
-static inline struct task_struct *__get_current(void)
-{
-	struct task_struct *__current;
-
-	__asm__("ori\t%0,$29,%1\n\t"
-	        "xori\t%0,%1"
-		 :"=r" (__current)
-	         :"ir" (8191UL));
-
-	return __current;
-}
-
-#define current __get_current()
+/* MIPS rules... */
+register struct task_struct *current asm("$28");
 
 #endif /* __LANGUAGE_C__ */
 #ifdef __LANGUAGE_ASSEMBLY__
 
 /*
- * Get current task pointer
- */
-#define GET_CURRENT(reg)			\
-	lui	reg, %hi(kernelsp);		\
-	lw	reg, %lo(kernelsp)(reg);	\
-	ori	reg, 8191;			\
-	xori	reg, 8191
-
-/*
  * Special variant for use by exception handlers when the stack pointer
  * is not loaded.
  */
@@ -41,7 +21,6 @@
 	.set	pop;				\
 	ori	reg, 8191;			\
 	xori	reg, 8191
-
 
 #endif
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h
--- v2.1.100/linux/include/asm-mips/elf.h	Tue Dec 16 12:46:01 1997
+++ linux/include/asm-mips/elf.h	Fri May  8 00:13:26 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: elf.h,v 1.4 1997/12/16 05:36:40 ralf Exp $
+ * $Id: elf.h,v 1.10 1998/05/01 01:35:51 ralf Exp $
  */
 #ifndef __ASM_MIPS_ELF_H
 #define __ASM_MIPS_ELF_H
@@ -38,6 +38,21 @@
 	memcpy((char *) &_dest, (char *) _regs,			\
 	       sizeof(struct pt_regs));
 
+/* This yields a mask that user programs can use to figure out what
+   instruction set this cpu supports.  This could be done in userspace,
+   but it's not easy, and we've already done it here.  */
+
+#define ELF_HWCAP       (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.
+
+   For the moment, we have only optimizations for the Intel generations,
+   but that could change... */
+
+#define ELF_PLATFORM  (NULL)
+
 /* See comments in asm-alpha/elf.h, this is the same thing
  * on the MIPS.
  */
@@ -49,5 +64,10 @@
    that it will "exec", and that there is sufficient room for the brk.  */
 
 #define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex,ibcs2) \
+	current->personality = (ibcs2 ? PER_SVR4 : PER_LINUX)
+#endif
 
 #endif /* __ASM_MIPS_ELF_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/errno.h linux/include/asm-mips/errno.h
--- v2.1.100/linux/include/asm-mips/errno.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/errno.h	Fri May  8 00:13:26 1998
@@ -156,4 +156,7 @@
 #define	EDQUOT		1133	/* Quota exceeded */
 #define ENFSREMOTE	1134	/* ??? */
 
+/* The biggest error number defined here or in <linux/errno.h>. */
+#define EMAXERRNO	1134
+
 #endif /* __ASM_MIPS_ERRNO_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h
--- v2.1.100/linux/include/asm-mips/floppy.h	Tue Dec 16 12:46:01 1997
+++ linux/include/asm-mips/floppy.h	Fri May  8 00:13:26 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1995, 1996, 1997 Ralf Baechle
  *
- * $Id: floppy.h,v 1.3 1997/09/07 03:59:02 ralf Exp $
+ * $Id: floppy.h,v 1.14 1998/05/01 01:35:52 ralf Exp $
  */
 #ifndef __ASM_MIPS_FLOPPY_H
 #define __ASM_MIPS_FLOPPY_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h
--- v2.1.100/linux/include/asm-mips/hardirq.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/hardirq.h	Fri May  8 00:13:26 1998
@@ -4,7 +4,6 @@
 #include <linux/tasks.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
-#define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
 
 #ifndef __SMP__
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h
--- v2.1.100/linux/include/asm-mips/ide.h	Thu May  7 22:51:54 1998
+++ linux/include/asm-mips/ide.h	Fri May  8 00:13:26 1998
@@ -21,40 +21,36 @@
 
 #define ide__sti()	__sti()
 
+struct ide_ops {
+	int (*ide_default_irq)(ide_ioreg_t base);
+	ide_ioreg_t (*ide_default_io_base)(int index);
+	void (*ide_init_hwif_ports)(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+	int (*ide_request_irq)(unsigned int irq, void (*handler)(int, void *,
+	                       struct pt_regs *), unsigned long flags,
+	                       const char *device, void *dev_id);
+	void (*ide_free_irq)(unsigned int irq, void *dev_id);
+	int (*ide_check_region) (ide_ioreg_t from, unsigned int extent);
+	void (*ide_request_region)(ide_ioreg_t from, unsigned int extent,
+	                        const char *name);
+	void (*ide_release_region)(ide_ioreg_t from, unsigned int extent);
+};
+
+extern struct ide_ops *ide_ops;
+
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
-	switch (base) {
-		case 0x1f0: return 14;
-		case 0x170: return 15;
-		case 0x1e8: return 11;
-		case 0x168: return 10;
-		default:
-			return 0;
-	}
+	return ide_ops->ide_default_irq(base);
 }
 
 static __inline__ ide_ioreg_t ide_default_io_base(int index)
 {
-	switch (index) {
-		case 0:	return 0x1f0;
-		case 1:	return 0x170;
-		case 2: return 0x1e8;
-		case 3: return 0x168;
-		default:
-			return 0;
-	}
-}
-
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
-{
-	ide_ioreg_t port = base;
-	int i = 8;
-
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
-	if (irq != NULL)
-		*irq = 0;
+	return ide_ops->ide_default_io_base(index);
+}
+
+static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
+                                           int *irq)
+{
+	ide_ops->ide_init_hwif_ports(p, base, irq);
 }
 
 typedef union {
@@ -68,38 +64,41 @@
 	} b;
 	} select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int,void *, struct pt_regs *),
 			unsigned long flags, const char *device, void *dev_id)
 {
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
+	return ide_ops->ide_request_irq(irq, handler, flags, device, dev_id);
+}
 
 static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
 {
-	free_irq(irq, dev_id);
+	ide_ops->ide_free_irq(irq, dev_id);
 }
 
 static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
 {
-	return check_region(from, extent);
+	return ide_ops->ide_check_region(from, extent);
 }
 
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
+static __inline__ void ide_request_region(ide_ioreg_t from,
+                                          unsigned int extent, const char *name)
 {
-	request_region(from, extent, name);
+	ide_ops->ide_request_region(from, extent, name);
 }
 
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
+static __inline__ void ide_release_region(ide_ioreg_t from,
+                                          unsigned int extent)
 {
-	release_region(from, extent);
+	ide_ops->ide_release_region(from, extent);
 }
 
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
+static __inline__ int ide_ack_intr (ide_ioreg_t status_port,
+                                    ide_ioreg_t irq_port)
 {
-	return(1);
+	return 1;
 }
 
 static __inline__ void ide_fix_driveid(struct hd_driveid *id)
@@ -110,7 +109,10 @@
 {
 }
 
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
+static __inline__ void ide_get_lock (int *ide_lock,
+                                     void (*handler)(int, void *,
+                                                    struct pt_regs *),
+                                     void *data)
 {
 }
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/init.h linux/include/asm-mips/init.h
--- v2.1.100/linux/include/asm-mips/init.h	Thu Jun 26 12:33:39 1997
+++ linux/include/asm-mips/init.h	Fri May  8 00:13:26 1998
@@ -1,14 +1,30 @@
-#ifndef __ASM_MIPS_INIT_H
-#define __ASM_MIPS_INIT_H
+/*
+ * include/asm-mips/init.h
+ *
+ * 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 $
+ */
+#ifndef __MIPS_INIT_H
+#define __MIPS_INIT_H
 
-/* Throwing the initialization code and data out is not supported yet... */
+#define __init __attribute__ ((__section__ (".text.init")))
+#define __initdata __attribute__ ((__section__ (".data.init")))
+#define __initfunc(__arginit) \
+	__arginit __init; \
+	__arginit
+
+#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 8
+#define __initlocaldata  __initdata
+#else
+#define __initlocaldata
+#endif
 
-#define	__init
-#define __initdata
-#define __initfunc(__arginit) __arginit
 /* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
+#define __INIT		.section	.text.init,"ax"
+#define __FINIT		.previous
+#define __INITDATA	.section	.data.init,"a"
 
-#endif /* __ASM_MIPS_INIT_H */
+#endif /* __MIPS_INIT_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/inventory.h linux/include/asm-mips/inventory.h
--- v2.1.100/linux/include/asm-mips/inventory.h	Mon Feb 23 18:12:11 1998
+++ linux/include/asm-mips/inventory.h	Fri May  8 00:13:26 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: inventory.h,v 1.2 1997/12/06 23:55:49 ralf Exp $
+ * $Id: inventory.h,v 1.2 1998/05/01 01:35:54 ralf Exp $
  */
 #ifndef __ASM_MIPS_INVENTORY_H
 #define __ASM_MIPS_INVENTORY_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/io.h linux/include/asm-mips/io.h
--- v2.1.100/linux/include/asm-mips/io.h	Tue Dec 16 12:46:07 1997
+++ linux/include/asm-mips/io.h	Fri May  8 00:13:26 1998
@@ -42,16 +42,6 @@
 extern unsigned long mips_io_port_base;
 
 /*
- * On MIPS I/O ports are memory mapped, so we access them using normal
- * load/store instructions. mips_io_port_base is the virtual address to
- * which all ports are being mapped.  For sake of efficiency some code
- * assumes that this is an address that can be loaded with a single lui
- * instruction, so the lower 16 bits must be zero.  Should be true on
- * on any sane architecture; generic code does not use this assumption.
- */
-extern unsigned long mips_io_port_base;
-
-/*
  * Thanks to James van Artsdalen for a better timing-fix than
  * the two short jumps: using outb's to a nonexistent port seems
  * to guarantee better timings even on fast machines.
@@ -381,5 +371,22 @@
 ((__builtin_constant_p((port)) && (port) < 32768) ? \
 	__inslc((port),(addr),(count)) : \
 	__insl((port),(addr),(count)))
+
+/*
+ * The caches on some architectures aren't dma-coherent and have need to
+ * handle this in software.  There are two types of operations that
+ * can be applied to dma buffers.
+ *
+ *  - dma_cache_wback_inv(start, size) makes caches and coherent by
+ *    writing the content of the caches back to memory, if necessary.
+ *    The function also invalidates the affected part of the caches as
+ *    necessary before DMA transfers from outside to memory.
+ *  - dma_cache_inv(start, size) invalidates the affected parts of the
+ *    caches.  Dirty lines of the caches may be written back or simply
+ *    be discarded.  This operation is necessary before dma operations
+ *    to the memory.
+ */
+extern void (*dma_cache_wback_inv)(unsigned long start, unsigned long size);
+extern void (*dma_cache_inv)(unsigned long start, unsigned long size);
 
 #endif /* __ASM_MIPS_IO_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- v2.1.100/linux/include/asm-mips/ioctls.h	Tue Feb 17 13:12:49 1998
+++ linux/include/asm-mips/ioctls.h	Fri May  8 00:13:26 1998
@@ -98,7 +98,7 @@
 #define TIOCTTYGSTRUCT	0x5487  /* For debugging only */
 #define TIOCSBRK	0x5427  /* BSD compatibility */
 #define TIOCCBRK	0x5428  /* BSD compatibility */
-#define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TIOCGSID	0x7416  /* Return the session ID of FD */
 #define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h
--- v2.1.100/linux/include/asm-mips/irq.h	Tue Dec 16 12:46:08 1997
+++ linux/include/asm-mips/irq.h	Fri May  8 00:13:26 1998
@@ -33,13 +33,4 @@
 #define irq_exit(cpu, irq)      (--local_irq_count[cpu])
 #endif
 
-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
-
 #endif /* __ASM_MIPS_IRQ_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h
--- v2.1.100/linux/include/asm-mips/jazz.h	Tue Dec 16 12:46:08 1997
+++ linux/include/asm-mips/jazz.h	Fri May  8 00:13:26 1998
@@ -9,7 +9,7 @@
  *
  * This file is a mess. It really needs some reorganisation!
  *
- * $Id: jazz.h,v 1.5 1997/12/01 21:26:48 ralf Exp $
+ * $Id: jazz.h,v 1.6 1998/05/01 01:35:56 ralf Exp $
  */
 #ifndef __ASM_MIPS_JAZZ_H 
 #define __ASM_MIPS_JAZZ_H 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h
--- v2.1.100/linux/include/asm-mips/jazzdma.h	Tue Dec 16 12:46:09 1997
+++ linux/include/asm-mips/jazzdma.h	Fri May  8 00:13:26 1998
@@ -1,5 +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 $
  */
 #ifndef __ASM_MIPS_JAZZDMA_H
 #define __ASM_MIPS_JAZZDMA_H
@@ -21,6 +23,7 @@
 void vdma_set_addr(int channel, long addr);
 void vdma_set_count(int channel, int count);
 int vdma_get_residue(int channel);
+int vdma_get_enable(int channel);
 
 /*
  * some definitions used by the driver functions
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h
--- v2.1.100/linux/include/asm-mips/keyboard.h	Tue Dec 16 12:46:09 1997
+++ linux/include/asm-mips/keyboard.h	Fri May  8 00:13:26 1998
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * $Id: keyboard.h,v 1.8 1997/12/02 05:51:14 ralf Exp $
+ * $Id: keyboard.h,v 1.7 1998/05/01 01:35:57 ralf Exp $
  */
 #ifndef __ASM_MIPS_KEYBOARD_H
 #define __ASM_MIPS_KEYBOARD_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/md.h linux/include/asm-mips/md.h
--- v2.1.100/linux/include/asm-mips/md.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/md.h	Fri May  8 00:13:26 1998
@@ -0,0 +1,13 @@
+/* $Id: md.h,v 1.1 1997/12/15 15:12:09 jj Exp $
+ * md.h: High speed xor_block operation for RAID4/5 
+ *
+ */
+ 
+#ifndef __ASM_MD_H
+#define __ASM_MD_H
+
+/* #define HAVE_ARCH_XORBLOCK */
+
+#define MD_XORBLOCK_ALIGNMENT	sizeof(long)
+
+#endif /* __ASM_MD_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- v2.1.100/linux/include/asm-mips/mipsregs.h	Tue Dec 16 12:46:10 1997
+++ linux/include/asm-mips/mipsregs.h	Fri May  8 00:13:26 1998
@@ -8,7 +8,7 @@
  * Copyright (C) 1994, 1995, 1996, 1997 by Ralf Baechle
  * Modified for further R[236]000 support by Paul M. Antoine, 1996.
  *
- * $Id: mipsregs.h,v 1.4 1997/09/20 19:02:46 root Exp $
+ * $Id: mipsregs.h,v 1.6 1998/05/01 01:35:58 ralf Exp $
  */
 #ifndef __ASM_MIPS_MIPSREGS_H
 #define __ASM_MIPS_MIPSREGS_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h
--- v2.1.100/linux/include/asm-mips/namei.h	Tue Dec 16 12:46:10 1997
+++ linux/include/asm-mips/namei.h	Fri May  8 00:13:26 1998
@@ -3,7 +3,7 @@
  *
  * Included from linux/fs/namei.c
  *
- * $Id: namei.h,v 1.6 1997/09/18 07:59:31 root Exp $
+ * $Id: namei.h,v 1.9 1998/05/01 01:35:59 ralf Exp $
  */
 #ifndef __ASM_MIPS_NAMEI_H
 #define __ASM_MIPS_NAMEI_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ng1.h linux/include/asm-mips/ng1.h
--- v2.1.100/linux/include/asm-mips/ng1.h	Tue Mar 10 10:03:34 1998
+++ linux/include/asm-mips/ng1.h	Fri May  8 00:13:26 1998
@@ -46,3 +46,5 @@
         unsigned char green [256];
         unsigned char blue  [256];
 };
+
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/offset.h linux/include/asm-mips/offset.h
--- v2.1.100/linux/include/asm-mips/offset.h	Tue Dec 16 12:46:10 1997
+++ linux/include/asm-mips/offset.h	Fri May  8 00:13:26 1998
@@ -38,52 +38,48 @@
 #define PT_R31    148
 #define PT_LO     152
 #define PT_HI     156
-#define PT_OR2    160
-#define PT_OR7    164
-#define PT_EPC    168
-#define PT_BVADDR 172
-#define PT_STATUS 176
-#define PT_CAUSE  180
-#define PT_SIZE   184
+#define PT_EPC    160
+#define PT_BVADDR 164
+#define PT_STATUS 168
+#define PT_CAUSE  172
+#define PT_SIZE   176
 
 /* MIPS task_struct offsets. */
 #define TASK_STATE         0
-#define TASK_COUNTER       4
-#define TASK_PRIORITY      8
-#define TASK_SIGNAL        12
-#define TASK_BLOCKED       16
-#define TASK_FLAGS         20
-#define TASK_MM            920
+#define TASK_COUNTER       52
+#define TASK_PRIORITY      56
+#define TASK_FLAGS         4
+#define TASK_SIGPENDING    8
+#define TASK_MM            928
 
 /* MIPS specific thread_struct offsets. */
-#define THREAD_REG16   552
-#define THREAD_REG17   556
-#define THREAD_REG18   560
-#define THREAD_REG19   564
-#define THREAD_REG20   568
-#define THREAD_REG21   572
-#define THREAD_REG22   576
-#define THREAD_REG23   580
-#define THREAD_REG28   584
-#define THREAD_REG29   588
-#define THREAD_REG30   592
-#define THREAD_REG31   596
-#define THREAD_STATUS  600
-#define THREAD_FPU     608
-#define THREAD_BVADDR  872
-#define THREAD_ECODE   876
-#define THREAD_TRAPNO  880
-#define THREAD_KSP     884
-#define THREAD_PGDIR   888
-#define THREAD_MFLAGS  892
-#define THREAD_CURDS   896
-#define THREAD_TRAMP   900
-#define THREAD_OLDCTX  904
+#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
 
 /* Linux mm_struct offsets. */
 #define MM_COUNT      12
 #define MM_PGD        8
-#define MM_CONTEXT    28
+#define MM_CONTEXT    32
 
 /* Linux sigcontext offsets. */
 #define SC_REGMASK    0
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/page.h linux/include/asm-mips/page.h
--- v2.1.100/linux/include/asm-mips/page.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/page.h	Fri May  8 00:13:26 1998
@@ -21,6 +21,8 @@
 
 #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);
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- v2.1.100/linux/include/asm-mips/pci.h	Tue Dec 16 12:46:10 1997
+++ linux/include/asm-mips/pci.h	Fri May  8 00:13:26 1998
@@ -5,7 +5,7 @@
  *
  * Declarations for the MIPS specific implementation of the PCI BIOS32 services.
  *
- * $Id: pci.h,v 1.2 1997/09/20 21:16:37 ralf Exp $
+ * $Id: pci.h,v 1.3 1998/05/01 01:36:00 ralf Exp $
  */
 #ifndef __ASM_MIPS_PCI_H
 #define __ASM_MIPS_PCI_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h
--- v2.1.100/linux/include/asm-mips/pgtable.h	Tue Dec 16 12:46:11 1997
+++ linux/include/asm-mips/pgtable.h	Fri May  8 00:13:26 1998
@@ -26,12 +26,6 @@
 extern void (*flush_page_to_ram)(unsigned long page);
 #define flush_icache_range(start, end) flush_cache_all()
 
-/*
- * Prototype of the DMA related cacheflushing stuff.
- */
-extern void (*flush_cache_pre_dma_out)(unsigned long start, unsigned long size);
-extern void (*flush_cache_post_dma_in)(unsigned long start, unsigned long size);
-
 /* TLB flushing:
  *
  *  - flush_tlb_all() flushes all processes TLB entries
@@ -127,8 +121,7 @@
 
 #define _PAGE_CHG_MASK  (PAGE_MASK | __READABLE | __WRITEABLE | _CACHE_MASK)
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
-                        _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_NONE	__pgprot(0)
 #define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
 			_CACHE_CACHABLE_NONCOHERENT)
 #define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_READ | \
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/prctl.h linux/include/asm-mips/prctl.h
--- v2.1.100/linux/include/asm-mips/prctl.h	Tue Mar 10 10:03:35 1998
+++ linux/include/asm-mips/prctl.h	Fri May  8 00:13:26 1998
@@ -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.2 1998/05/01 01:36:02 ralf Exp $
  */
 
 #ifndef __PRCTL_H__
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.1.100/linux/include/asm-mips/processor.h	Fri Jan 16 20:32:53 1998
+++ linux/include/asm-mips/processor.h	Fri May  8 00:13:26 1998
@@ -5,7 +5,7 @@
  * written by Ralf Baechle
  * Modified further for R[236]000 compatibility by Paul M. Antoine
  *
- * $Id: processor.h,v 1.5 1997/12/01 16:48:39 ralf Exp $
+ * $Id: processor.h,v 1.20 1998/05/04 09:18:59 ralf Exp $
  */
 #ifndef __ASM_MIPS_PROCESSOR_H
 #define __ASM_MIPS_PROCESSOR_H
@@ -51,7 +51,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 /*
  * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
@@ -90,21 +91,21 @@
  */
 struct thread_struct {
         /* Saved main processor registers. */
-        unsigned long reg16 __attribute__ ((aligned (8)));
+        unsigned long reg16;
 	unsigned long reg17, reg18, reg19, reg20, reg21, reg22, reg23;
-        unsigned long reg28, reg29, reg30, reg31;
+        unsigned long reg29, reg30, reg31;
 
 	/* Saved cp0 stuff. */
 	unsigned long cp0_status;
 
 	/* Saved fpu/fpu emulator stuff. */
-	union mips_fpu_union fpu __attribute__ ((aligned (8)));
+	union mips_fpu_union fpu;
 
 	/* Other stuff associated with the thread. */
-	unsigned long cp0_badvaddr;
+	unsigned long cp0_badvaddr;	/* Last user fault */
+	unsigned long cp0_baduaddr;	/* Last kernel fault accessing USEG */
 	unsigned long error_code;
 	unsigned long trap_no;
-	unsigned long ksp;			/* Top of kernel stack   */
 	unsigned long pg_dir;                   /* used in tlb refill    */
 #define MF_FIXADE 1			/* Fix address errors in software */
 #define MF_LOGADE 2			/* Log address errors to syslog */
@@ -124,7 +125,7 @@
          * saved main processor registers \
          */ \
 	0, 0, 0, 0, 0, 0, 0, 0, \
-	            0, 0, 0, 0, \
+	               0, 0, 0, \
 	/* \
 	 * saved cp0 stuff \
 	 */ \
@@ -136,12 +137,11 @@
 	/* \
 	 * Other stuff associated with the process \
 	 */ \
-	0, 0, 0, (unsigned long)&init_task_union + KERNEL_STACK_SIZE - 32, \
-	(unsigned long) swapper_pg_dir, \
+	0, 0, 0, 0, (unsigned long) swapper_pg_dir, \
 	/* \
 	 * For now the default is to fix address errors \
 	 */ \
-	MF_FIXADE, 0, 0, 0 \
+	MF_FIXADE, { 0 }, 0, 0 \
 }
 
 #ifdef __KERNEL__
@@ -167,16 +167,12 @@
 	return ((unsigned long*)t->reg29)[17];
 }
 
+extern int (*user_mode)(struct pt_regs *);
+
 /*
  * Do necessary setup to start up a newly executed thread.
  */
 extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
-
-/*
- * Does the process account for user or for system time?
- */
-extern int (*running_in_user_mode)(void);
-#define USES_USER_TIME(regs) running_in_user_mode()
 
 /* Allocation and freeing of basic task resources. */
 /*
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h
--- v2.1.100/linux/include/asm-mips/ptrace.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/ptrace.h	Fri May  8 00:13:26 1998
@@ -30,8 +30,6 @@
 	/* Other saved registers. */
 	unsigned long lo;
 	unsigned long hi;
-	unsigned long orig_reg2;
-	unsigned long orig_reg7;
 
 	/*
 	 * saved cp0 registers
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/r4kcache.h linux/include/asm-mips/r4kcache.h
--- v2.1.100/linux/include/asm-mips/r4kcache.h	Tue Dec 16 12:46:12 1997
+++ linux/include/asm-mips/r4kcache.h	Fri May  8 00:13:26 1998
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r4kcache.h,v 1.5 1997/12/01 16:47:05 ralf Exp $
+ * $Id: r4kcache.h,v 1.5 1998/05/01 01:36:03 ralf Exp $
  *
  * FIXME: Handle split L2 caches.
  */
@@ -104,32 +104,6 @@
 		  "i" (Hit_Invalidate_SD));
 }
 
-extern inline void invalidate_dcache_line(unsigned long addr)
-{
-	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n\t"
-		"cache %1, (%0)\n\t"
-		".set mips0\n\t"
-		".set reorder"
-		:
-		: "r" (addr),
-		  "i" (Hit_Invalidate_D));
-}
-
-extern inline void invalidate_scache_line(unsigned long addr)
-{
-	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n\t"
-		"cache %1, (%0)\n\t"
-		".set mips0\n\t"
-		".set reorder"
-		:
-		: "r" (addr),
-		  "i" (Hit_Invalidate_SD));
-}
-
 extern inline void flush_scache_line(unsigned long addr)
 {
 	__asm__ __volatile__(
@@ -178,40 +152,31 @@
 		  "i" (Hit_Writeback_D));
 }
 
-/*
- * The next two are for badland addresses like signal trampolines.
- */
-extern inline void protected_flush_icache_line(unsigned long addr)
-{
-	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n"
-		"1:\tcache %1,(%0)\n"
-		"2:\t.set mips0\n\t"
-		".set reorder\n\t"
-		".section\t__ex_table,\"a\"\n\t"
-		STR(PTR)"\t1b,2b\n\t"
-		".previous"
-		:
-		: "r" (addr),
-		  "i" (Hit_Invalidate_I));
-}
-
-extern inline void protected_writeback_dcache_line(unsigned long addr)
-{
-	__asm__ __volatile__(
-		".set noreorder\n\t"
-		".set mips3\n"
-		"1:\tcache %1,(%0)\n"
-		"2:\t.set mips0\n\t"
-		".set reorder\n\t"
-		".section\t__ex_table,\"a\"\n\t"
-		STR(PTR)"\t1b,2b\n\t"
-		".previous"
-		:
-		: "r" (addr),
-		  "i" (Hit_Writeback_D));
-}
+#define cache16_unroll32(base,op)				\
+	__asm__ __volatile__("					\
+		.set noreorder;					\
+		.set mips3;					\
+		cache %1, 0x000(%0); cache %1, 0x010(%0);	\
+		cache %1, 0x020(%0); cache %1, 0x030(%0);	\
+		cache %1, 0x040(%0); cache %1, 0x050(%0);	\
+		cache %1, 0x060(%0); cache %1, 0x070(%0);	\
+		cache %1, 0x080(%0); cache %1, 0x090(%0);	\
+		cache %1, 0x0a0(%0); cache %1, 0x0b0(%0);	\
+		cache %1, 0x0c0(%0); cache %1, 0x0d0(%0);	\
+		cache %1, 0x0e0(%0); cache %1, 0x0f0(%0);	\
+		cache %1, 0x100(%0); cache %1, 0x110(%0);	\
+		cache %1, 0x120(%0); cache %1, 0x130(%0);	\
+		cache %1, 0x140(%0); cache %1, 0x150(%0);	\
+		cache %1, 0x160(%0); cache %1, 0x170(%0);	\
+		cache %1, 0x180(%0); cache %1, 0x190(%0);	\
+		cache %1, 0x1a0(%0); cache %1, 0x1b0(%0);	\
+		cache %1, 0x1c0(%0); cache %1, 0x1d0(%0);	\
+		cache %1, 0x1e0(%0); cache %1, 0x1f0(%0);	\
+		.set mips0;					\
+		.set reorder"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
 
 extern inline void blast_dcache16(void)
 {
@@ -219,30 +184,7 @@
 	unsigned long end = (start + dcache_size);
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x010(%0)
-			cache %1, 0x020(%0); cache %1, 0x030(%0)
-			cache %1, 0x040(%0); cache %1, 0x050(%0)
-			cache %1, 0x060(%0); cache %1, 0x070(%0)
-			cache %1, 0x080(%0); cache %1, 0x090(%0)
-			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
-			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
-			cache %1, 0x100(%0); cache %1, 0x110(%0)
-			cache %1, 0x120(%0); cache %1, 0x130(%0)
-			cache %1, 0x140(%0); cache %1, 0x150(%0)
-			cache %1, 0x160(%0); cache %1, 0x170(%0)
-			cache %1, 0x180(%0); cache %1, 0x190(%0)
-			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
-			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_D));
+		cache16_unroll32(start,Index_Writeback_Inv_D);
 		start += 0x200;
 	}
 }
@@ -253,79 +195,8 @@
 	unsigned long end = (start + PAGE_SIZE);
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x010(%0)
-			cache %1, 0x020(%0); cache %1, 0x030(%0)
-			cache %1, 0x040(%0); cache %1, 0x050(%0)
-			cache %1, 0x060(%0); cache %1, 0x070(%0)
-			cache %1, 0x080(%0); cache %1, 0x090(%0)
-			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
-			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
-			cache %1, 0x100(%0); cache %1, 0x110(%0)
-			cache %1, 0x120(%0); cache %1, 0x130(%0)
-			cache %1, 0x140(%0); cache %1, 0x150(%0)
-			cache %1, 0x160(%0); cache %1, 0x170(%0)
-			cache %1, 0x180(%0); cache %1, 0x190(%0)
-			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
-			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
-			cache %1, 0x200(%0); cache %1, 0x210(%0)
-			cache %1, 0x220(%0); cache %1, 0x230(%0)
-			cache %1, 0x240(%0); cache %1, 0x250(%0)
-			cache %1, 0x260(%0); cache %1, 0x270(%0)
-			cache %1, 0x280(%0); cache %1, 0x290(%0)
-			cache %1, 0x2a0(%0); cache %1, 0x2b0(%0)
-			cache %1, 0x2c0(%0); cache %1, 0x2d0(%0)
-			cache %1, 0x2e0(%0); cache %1, 0x2f0(%0)
-			cache %1, 0x300(%0); cache %1, 0x310(%0)
-			cache %1, 0x320(%0); cache %1, 0x330(%0)
-			cache %1, 0x340(%0); cache %1, 0x350(%0)
-			cache %1, 0x360(%0); cache %1, 0x370(%0)
-			cache %1, 0x380(%0); cache %1, 0x390(%0)
-			cache %1, 0x3a0(%0); cache %1, 0x3b0(%0)
-			cache %1, 0x3c0(%0); cache %1, 0x3d0(%0)
-			cache %1, 0x3e0(%0); cache %1, 0x3f0(%0)
-			cache %1, 0x400(%0); cache %1, 0x410(%0)
-			cache %1, 0x420(%0); cache %1, 0x430(%0)
-			cache %1, 0x440(%0); cache %1, 0x450(%0)
-			cache %1, 0x460(%0); cache %1, 0x470(%0)
-			cache %1, 0x480(%0); cache %1, 0x490(%0)
-			cache %1, 0x4a0(%0); cache %1, 0x4b0(%0)
-			cache %1, 0x4c0(%0); cache %1, 0x4d0(%0)
-			cache %1, 0x4e0(%0); cache %1, 0x4f0(%0)
-			cache %1, 0x500(%0); cache %1, 0x510(%0)
-			cache %1, 0x520(%0); cache %1, 0x530(%0)
-			cache %1, 0x540(%0); cache %1, 0x550(%0)
-			cache %1, 0x560(%0); cache %1, 0x570(%0)
-			cache %1, 0x580(%0); cache %1, 0x590(%0)
-			cache %1, 0x5a0(%0); cache %1, 0x5b0(%0)
-			cache %1, 0x5c0(%0); cache %1, 0x5d0(%0)
-			cache %1, 0x5e0(%0); cache %1, 0x5f0(%0)
-			cache %1, 0x600(%0); cache %1, 0x610(%0)
-			cache %1, 0x620(%0); cache %1, 0x630(%0)
-			cache %1, 0x640(%0); cache %1, 0x650(%0)
-			cache %1, 0x660(%0); cache %1, 0x670(%0)
-			cache %1, 0x680(%0); cache %1, 0x690(%0)
-			cache %1, 0x6a0(%0); cache %1, 0x6b0(%0)
-			cache %1, 0x6c0(%0); cache %1, 0x6d0(%0)
-			cache %1, 0x6e0(%0); cache %1, 0x6f0(%0)
-			cache %1, 0x700(%0); cache %1, 0x710(%0)
-			cache %1, 0x720(%0); cache %1, 0x730(%0)
-			cache %1, 0x740(%0); cache %1, 0x750(%0)
-			cache %1, 0x760(%0); cache %1, 0x770(%0)
-			cache %1, 0x780(%0); cache %1, 0x790(%0)
-			cache %1, 0x7a0(%0); cache %1, 0x7b0(%0)
-			cache %1, 0x7c0(%0); cache %1, 0x7d0(%0)
-			cache %1, 0x7e0(%0); cache %1, 0x7f0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Hit_Writeback_Inv_D));
-		start += 0x800;
+		cache16_unroll32(start,Hit_Writeback_Inv_D);
+		start += 0x200;
 	}
 }
 
@@ -335,571 +206,184 @@
 	unsigned long end = (start + PAGE_SIZE);
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x010(%0)
-			cache %1, 0x020(%0); cache %1, 0x030(%0)
-			cache %1, 0x040(%0); cache %1, 0x050(%0)
-			cache %1, 0x060(%0); cache %1, 0x070(%0)
-			cache %1, 0x080(%0); cache %1, 0x090(%0)
-			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
-			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
-			cache %1, 0x100(%0); cache %1, 0x110(%0)
-			cache %1, 0x120(%0); cache %1, 0x130(%0)
-			cache %1, 0x140(%0); cache %1, 0x150(%0)
-			cache %1, 0x160(%0); cache %1, 0x170(%0)
-			cache %1, 0x180(%0); cache %1, 0x190(%0)
-			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
-			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
-			cache %1, 0x200(%0); cache %1, 0x210(%0)
-			cache %1, 0x220(%0); cache %1, 0x230(%0)
-			cache %1, 0x240(%0); cache %1, 0x250(%0)
-			cache %1, 0x260(%0); cache %1, 0x270(%0)
-			cache %1, 0x280(%0); cache %1, 0x290(%0)
-			cache %1, 0x2a0(%0); cache %1, 0x2b0(%0)
-			cache %1, 0x2c0(%0); cache %1, 0x2d0(%0)
-			cache %1, 0x2e0(%0); cache %1, 0x2f0(%0)
-			cache %1, 0x300(%0); cache %1, 0x310(%0)
-			cache %1, 0x320(%0); cache %1, 0x330(%0)
-			cache %1, 0x340(%0); cache %1, 0x350(%0)
-			cache %1, 0x360(%0); cache %1, 0x370(%0)
-			cache %1, 0x380(%0); cache %1, 0x390(%0)
-			cache %1, 0x3a0(%0); cache %1, 0x3b0(%0)
-			cache %1, 0x3c0(%0); cache %1, 0x3d0(%0)
-			cache %1, 0x3e0(%0); cache %1, 0x3f0(%0)
-			cache %1, 0x400(%0); cache %1, 0x410(%0)
-			cache %1, 0x420(%0); cache %1, 0x430(%0)
-			cache %1, 0x440(%0); cache %1, 0x450(%0)
-			cache %1, 0x460(%0); cache %1, 0x470(%0)
-			cache %1, 0x480(%0); cache %1, 0x490(%0)
-			cache %1, 0x4a0(%0); cache %1, 0x4b0(%0)
-			cache %1, 0x4c0(%0); cache %1, 0x4d0(%0)
-			cache %1, 0x4e0(%0); cache %1, 0x4f0(%0)
-			cache %1, 0x500(%0); cache %1, 0x510(%0)
-			cache %1, 0x520(%0); cache %1, 0x530(%0)
-			cache %1, 0x540(%0); cache %1, 0x550(%0)
-			cache %1, 0x560(%0); cache %1, 0x570(%0)
-			cache %1, 0x580(%0); cache %1, 0x590(%0)
-			cache %1, 0x5a0(%0); cache %1, 0x5b0(%0)
-			cache %1, 0x5c0(%0); cache %1, 0x5d0(%0)
-			cache %1, 0x5e0(%0); cache %1, 0x5f0(%0)
-			cache %1, 0x600(%0); cache %1, 0x610(%0)
-			cache %1, 0x620(%0); cache %1, 0x630(%0)
-			cache %1, 0x640(%0); cache %1, 0x650(%0)
-			cache %1, 0x660(%0); cache %1, 0x670(%0)
-			cache %1, 0x680(%0); cache %1, 0x690(%0)
-			cache %1, 0x6a0(%0); cache %1, 0x6b0(%0)
-			cache %1, 0x6c0(%0); cache %1, 0x6d0(%0)
-			cache %1, 0x6e0(%0); cache %1, 0x6f0(%0)
-			cache %1, 0x700(%0); cache %1, 0x710(%0)
-			cache %1, 0x720(%0); cache %1, 0x730(%0)
-			cache %1, 0x740(%0); cache %1, 0x750(%0)
-			cache %1, 0x760(%0); cache %1, 0x770(%0)
-			cache %1, 0x780(%0); cache %1, 0x790(%0)
-			cache %1, 0x7a0(%0); cache %1, 0x7b0(%0)
-			cache %1, 0x7c0(%0); cache %1, 0x7d0(%0)
-			cache %1, 0x7e0(%0); cache %1, 0x7f0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_D));
-		start += 0x800;
+		cache16_unroll32(start,Index_Writeback_Inv_D);
+		start += 0x200;
 	}
 }
 
-extern inline void blast_dcache32(void)
+extern inline void blast_icache16(void)
 {
 	unsigned long start = KSEG0;
-	unsigned long end = (start + dcache_size);
+	unsigned long end = (start + icache_size);
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x020(%0)
-			cache %1, 0x040(%0); cache %1, 0x060(%0)
-			cache %1, 0x080(%0); cache %1, 0x0a0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)
-			cache %1, 0x100(%0); cache %1, 0x120(%0)
-			cache %1, 0x140(%0); cache %1, 0x160(%0)
-			cache %1, 0x180(%0); cache %1, 0x1a0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)
-			cache %1, 0x200(%0); cache %1, 0x220(%0)
-			cache %1, 0x240(%0); cache %1, 0x260(%0)
-			cache %1, 0x280(%0); cache %1, 0x2a0(%0)
-			cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)
-			cache %1, 0x300(%0); cache %1, 0x320(%0)
-			cache %1, 0x340(%0); cache %1, 0x360(%0)
-			cache %1, 0x380(%0); cache %1, 0x3a0(%0)
-			cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)
-			cache %1, 0x400(%0); cache %1, 0x420(%0)
-			cache %1, 0x440(%0); cache %1, 0x460(%0)
-			cache %1, 0x480(%0); cache %1, 0x4a0(%0)
-			cache %1, 0x4c0(%0); cache %1, 0x4e0(%0)
-			cache %1, 0x500(%0); cache %1, 0x520(%0)
-			cache %1, 0x540(%0); cache %1, 0x560(%0)
-			cache %1, 0x580(%0); cache %1, 0x5a0(%0)
-			cache %1, 0x5c0(%0); cache %1, 0x5e0(%0)
-			cache %1, 0x600(%0); cache %1, 0x620(%0)
-			cache %1, 0x640(%0); cache %1, 0x660(%0)
-			cache %1, 0x680(%0); cache %1, 0x6a0(%0)
-			cache %1, 0x6c0(%0); cache %1, 0x6e0(%0)
-			cache %1, 0x700(%0); cache %1, 0x720(%0)
-			cache %1, 0x740(%0); cache %1, 0x760(%0)
-			cache %1, 0x780(%0); cache %1, 0x7a0(%0)
-			cache %1, 0x7c0(%0); cache %1, 0x7e0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_D));
-		start += 0x400;
+		cache16_unroll32(start,Index_Invalidate_I);
+		start += 0x200;
 	}
 }
 
-/*
- * Call this function only with interrupts disabled or R4600 V2.0 may blow
- * you up.
- *
- * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D,
- * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only
- * operate correctly if the internal data cache refill buffer is empty.  These
- * CACHE instructions should be separated from any potential data cache miss
- * by a load instruction to an uncached address to empty the response buffer."
- * (Revision 2.0 device errata from IDT available on http://www.idt.com/
- * in .pdf format.)
- */
-extern inline void blast_dcache32_page(unsigned long page)
+extern inline void blast_icache16_page(unsigned long page)
 {
 	unsigned long start = page;
 	unsigned long end = (start + PAGE_SIZE);
 
-	/*
-	 * Sigh ... workaround for R4600 v1.7 bug.  Explanation see above.
-	 */
-	*(volatile unsigned long *)KSEG1;
-
-	__asm__ __volatile__("nop;nop;nop;nop");
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x020(%0)
-			cache %1, 0x040(%0); cache %1, 0x060(%0)
-			cache %1, 0x080(%0); cache %1, 0x0a0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)
-			cache %1, 0x100(%0); cache %1, 0x120(%0)
-			cache %1, 0x140(%0); cache %1, 0x160(%0)
-			cache %1, 0x180(%0); cache %1, 0x1a0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)
-			cache %1, 0x200(%0); cache %1, 0x220(%0)
-			cache %1, 0x240(%0); cache %1, 0x260(%0)
-			cache %1, 0x280(%0); cache %1, 0x2a0(%0)
-			cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)
-			cache %1, 0x300(%0); cache %1, 0x320(%0)
-			cache %1, 0x340(%0); cache %1, 0x360(%0)
-			cache %1, 0x380(%0); cache %1, 0x3a0(%0)
-			cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)
-			cache %1, 0x400(%0); cache %1, 0x420(%0)
-			cache %1, 0x440(%0); cache %1, 0x460(%0)
-			cache %1, 0x480(%0); cache %1, 0x4a0(%0)
-			cache %1, 0x4c0(%0); cache %1, 0x4e0(%0)
-			cache %1, 0x500(%0); cache %1, 0x520(%0)
-			cache %1, 0x540(%0); cache %1, 0x560(%0)
-			cache %1, 0x580(%0); cache %1, 0x5a0(%0)
-			cache %1, 0x5c0(%0); cache %1, 0x5e0(%0)
-			cache %1, 0x600(%0); cache %1, 0x620(%0)
-			cache %1, 0x640(%0); cache %1, 0x660(%0)
-			cache %1, 0x680(%0); cache %1, 0x6a0(%0)
-			cache %1, 0x6c0(%0); cache %1, 0x6e0(%0)
-			cache %1, 0x700(%0); cache %1, 0x720(%0)
-			cache %1, 0x740(%0); cache %1, 0x760(%0)
-			cache %1, 0x780(%0); cache %1, 0x7a0(%0)
-			cache %1, 0x7c0(%0); cache %1, 0x7e0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Hit_Writeback_Inv_D));
-		start += 0x800;
+		cache16_unroll32(start,Hit_Invalidate_I);
+		start += 0x200;
 	}
 }
 
-extern inline void blast_dcache32_page_indexed(unsigned long page)
+extern inline void blast_icache16_page_indexed(unsigned long page)
 {
 	unsigned long start = page;
 	unsigned long end = (start + PAGE_SIZE);
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x020(%0)
-			cache %1, 0x040(%0); cache %1, 0x060(%0)
-			cache %1, 0x080(%0); cache %1, 0x0a0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0e0(%0)
-			cache %1, 0x100(%0); cache %1, 0x120(%0)
-			cache %1, 0x140(%0); cache %1, 0x160(%0)
-			cache %1, 0x180(%0); cache %1, 0x1a0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1e0(%0)
-			cache %1, 0x200(%0); cache %1, 0x220(%0)
-			cache %1, 0x240(%0); cache %1, 0x260(%0)
-			cache %1, 0x280(%0); cache %1, 0x2a0(%0)
-			cache %1, 0x2c0(%0); cache %1, 0x2e0(%0)
-			cache %1, 0x300(%0); cache %1, 0x320(%0)
-			cache %1, 0x340(%0); cache %1, 0x360(%0)
-			cache %1, 0x380(%0); cache %1, 0x3a0(%0)
-			cache %1, 0x3c0(%0); cache %1, 0x3e0(%0)
-			cache %1, 0x400(%0); cache %1, 0x420(%0)
-			cache %1, 0x440(%0); cache %1, 0x460(%0)
-			cache %1, 0x480(%0); cache %1, 0x4a0(%0)
-			cache %1, 0x4c0(%0); cache %1, 0x4e0(%0)
-			cache %1, 0x500(%0); cache %1, 0x520(%0)
-			cache %1, 0x540(%0); cache %1, 0x560(%0)
-			cache %1, 0x580(%0); cache %1, 0x5a0(%0)
-			cache %1, 0x5c0(%0); cache %1, 0x5e0(%0)
-			cache %1, 0x600(%0); cache %1, 0x620(%0)
-			cache %1, 0x640(%0); cache %1, 0x660(%0)
-			cache %1, 0x680(%0); cache %1, 0x6a0(%0)
-			cache %1, 0x6c0(%0); cache %1, 0x6e0(%0)
-			cache %1, 0x700(%0); cache %1, 0x720(%0)
-			cache %1, 0x740(%0); cache %1, 0x760(%0)
-			cache %1, 0x780(%0); cache %1, 0x7a0(%0)
-			cache %1, 0x7c0(%0); cache %1, 0x7e0(%0) 
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_D));
-		start += 0x800;
+		cache16_unroll32(start,Index_Invalidate_I);
+		start += 0x200;
 	}
 }
 
-extern inline void blast_icache16(void)
+extern inline void blast_scache16(void)
 {
 	unsigned long start = KSEG0;
-	unsigned long end = (start + icache_size);
+	unsigned long end = KSEG0 + scache_size;
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x010(%0)
-			cache %1, 0x020(%0); cache %1, 0x030(%0)
-			cache %1, 0x040(%0); cache %1, 0x050(%0)
-			cache %1, 0x060(%0); cache %1, 0x070(%0)
-			cache %1, 0x080(%0); cache %1, 0x090(%0)
-			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
-			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
-			cache %1, 0x100(%0); cache %1, 0x110(%0)
-			cache %1, 0x120(%0); cache %1, 0x130(%0)
-			cache %1, 0x140(%0); cache %1, 0x150(%0)
-			cache %1, 0x160(%0); cache %1, 0x170(%0)
-			cache %1, 0x180(%0); cache %1, 0x190(%0)
-			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
-			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Invalidate_I));
+		cache16_unroll32(start,Index_Writeback_Inv_SD);
 		start += 0x200;
 	}
 }
 
-extern inline void blast_icache16_page(unsigned long page)
+extern inline void blast_scache16_page(unsigned long page)
 {
 	unsigned long start = page;
-	unsigned long end = (start + PAGE_SIZE);
+	unsigned long end = page + PAGE_SIZE;
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x010(%0)
-			cache %1, 0x020(%0); cache %1, 0x030(%0)
-			cache %1, 0x040(%0); cache %1, 0x050(%0)
-			cache %1, 0x060(%0); cache %1, 0x070(%0)
-			cache %1, 0x080(%0); cache %1, 0x090(%0)
-			cache %1, 0x0a0(%0); cache %1, 0x0b0(%0)
-			cache %1, 0x0c0(%0); cache %1, 0x0d0(%0)
-			cache %1, 0x0e0(%0); cache %1, 0x0f0(%0)
-			cache %1, 0x100(%0); cache %1, 0x110(%0)
-			cache %1, 0x120(%0); cache %1, 0x130(%0)
-			cache %1, 0x140(%0); cache %1, 0x150(%0)
-			cache %1, 0x160(%0); cache %1, 0x170(%0)
-			cache %1, 0x180(%0); cache %1, 0x190(%0)
-			cache %1, 0x1a0(%0); cache %1, 0x1b0(%0)
-			cache %1, 0x1c0(%0); cache %1, 0x1d0(%0)
-			cache %1, 0x1e0(%0); cache %1, 0x1f0(%0)
-			cache %1, 0x200(%0); cache %1, 0x210(%0)
-			cache %1, 0x220(%0); cache %1, 0x230(%0)
-			cache %1, 0x240(%0); cache %1, 0x250(%0)
-			cache %1, 0x260(%0); cache %1, 0x270(%0)
-			cache %1, 0x280(%0); cache %1, 0x290(%0)
-			cache %1, 0x2a0(%0); cache %1, 0x2b0(%0)
-			cache %1, 0x2c0(%0); cache %1, 0x2d0(%0)
-			cache %1, 0x2e0(%0); cache %1, 0x2f0(%0)
-			cache %1, 0x300(%0); cache %1, 0x310(%0)
-			cache %1, 0x320(%0); cache %1, 0x330(%0)
-			cache %1, 0x340(%0); cache %1, 0x350(%0)
-			cache %1, 0x360(%0); cache %1, 0x370(%0)
-			cache %1, 0x380(%0); cache %1, 0x390(%0)
-			cache %1, 0x3a0(%0); cache %1, 0x3b0(%0)
-			cache %1, 0x3c0(%0); cache %1, 0x3d0(%0)
-			cache %1, 0x3e0(%0); cache %1, 0x3f0(%0)
-			cache %1, 0x400(%0); cache %1, 0x410(%0)
-			cache %1, 0x420(%0); cache %1, 0x430(%0)
-			cache %1, 0x440(%0); cache %1, 0x450(%0)
-			cache %1, 0x460(%0); cache %1, 0x470(%0)
-			cache %1, 0x480(%0); cache %1, 0x490(%0)
-			cache %1, 0x4a0(%0); cache %1, 0x4b0(%0)
-			cache %1, 0x4c0(%0); cache %1, 0x4d0(%0)
-			cache %1, 0x4e0(%0); cache %1, 0x4f0(%0)
-			cache %1, 0x500(%0); cache %1, 0x510(%0)
-			cache %1, 0x520(%0); cache %1, 0x530(%0)
-			cache %1, 0x540(%0); cache %1, 0x550(%0)
-			cache %1, 0x560(%0); cache %1, 0x570(%0)
-			cache %1, 0x580(%0); cache %1, 0x590(%0)
-			cache %1, 0x5a0(%0); cache %1, 0x5b0(%0)
-			cache %1, 0x5c0(%0); cache %1, 0x5d0(%0)
-			cache %1, 0x5e0(%0); cache %1, 0x5f0(%0)
-			cache %1, 0x600(%0); cache %1, 0x610(%0)
-			cache %1, 0x620(%0); cache %1, 0x630(%0)
-			cache %1, 0x640(%0); cache %1, 0x650(%0)
-			cache %1, 0x660(%0); cache %1, 0x670(%0)
-			cache %1, 0x680(%0); cache %1, 0x690(%0)
-			cache %1, 0x6a0(%0); cache %1, 0x6b0(%0)
-			cache %1, 0x6c0(%0); cache %1, 0x6d0(%0)
-			cache %1, 0x6e0(%0); cache %1, 0x6f0(%0)
-			cache %1, 0x700(%0); cache %1, 0x710(%0)
-			cache %1, 0x720(%0); cache %1, 0x730(%0)
-			cache %1, 0x740(%0); cache %1, 0x750(%0)
-			cache %1, 0x760(%0); cache %1, 0x770(%0)
-			cache %1, 0x780(%0); cache %1, 0x790(%0)
-			cache %1, 0x7a0(%0); cache %1, 0x7b0(%0)
-			cache %1, 0x7c0(%0); cache %1, 0x7d0(%0)
-			cache %1, 0x7e0(%0); cache %1, 0x7f0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Hit_Invalidate_I));
-		start += 0x800;
+		cache16_unroll32(start,Hit_Writeback_Inv_SD);
+		start += 0x200;
 	}
 }
 
-extern inline void blast_icache16_page_indexed(unsigned long page)
+extern inline void blast_scache16_page_indexed(unsigned long page)
 {
 	unsigned long start = page;
-	unsigned long end = (start + PAGE_SIZE);
+	unsigned long end = page + PAGE_SIZE;
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 0, 0x000(%0); cache 0, 0x010(%0); cache 0, 0x020(%0); cache 0, 0x030(%0)
-cache 0, 0x040(%0); cache 0, 0x050(%0); cache 0, 0x060(%0); cache 0, 0x070(%0)
-cache 0, 0x080(%0); cache 0, 0x090(%0); cache 0, 0x0a0(%0); cache 0, 0x0b0(%0)
-cache 0, 0x0c0(%0); cache 0, 0x0d0(%0); cache 0, 0x0e0(%0); cache 0, 0x0f0(%0)
-cache 0, 0x100(%0); cache 0, 0x110(%0); cache 0, 0x120(%0); cache 0, 0x130(%0)
-cache 0, 0x140(%0); cache 0, 0x150(%0); cache 0, 0x160(%0); cache 0, 0x170(%0)
-cache 0, 0x180(%0); cache 0, 0x190(%0); cache 0, 0x1a0(%0); cache 0, 0x1b0(%0)
-cache 0, 0x1c0(%0); cache 0, 0x1d0(%0); cache 0, 0x1e0(%0); cache 0, 0x1f0(%0)
-cache 0, 0x200(%0); cache 0, 0x210(%0); cache 0, 0x220(%0); cache 0, 0x230(%0)
-cache 0, 0x240(%0); cache 0, 0x250(%0); cache 0, 0x260(%0); cache 0, 0x270(%0)
-cache 0, 0x280(%0); cache 0, 0x290(%0); cache 0, 0x2a0(%0); cache 0, 0x2b0(%0)
-cache 0, 0x2c0(%0); cache 0, 0x2d0(%0); cache 0, 0x2e0(%0); cache 0, 0x2f0(%0)
-cache 0, 0x300(%0); cache 0, 0x310(%0); cache 0, 0x320(%0); cache 0, 0x330(%0)
-cache 0, 0x340(%0); cache 0, 0x350(%0); cache 0, 0x360(%0); cache 0, 0x370(%0)
-cache 0, 0x380(%0); cache 0, 0x390(%0); cache 0, 0x3a0(%0); cache 0, 0x3b0(%0)
-cache 0, 0x3c0(%0); cache 0, 0x3d0(%0); cache 0, 0x3e0(%0); cache 0, 0x3f0(%0)
-cache 0, 0x400(%0); cache 0, 0x410(%0); cache 0, 0x420(%0); cache 0, 0x430(%0)
-cache 0, 0x440(%0); cache 0, 0x450(%0); cache 0, 0x460(%0); cache 0, 0x470(%0)
-cache 0, 0x480(%0); cache 0, 0x490(%0); cache 0, 0x4a0(%0); cache 0, 0x4b0(%0)
-cache 0, 0x4c0(%0); cache 0, 0x4d0(%0); cache 0, 0x4e0(%0); cache 0, 0x4f0(%0)
-cache 0, 0x500(%0); cache 0, 0x510(%0); cache 0, 0x520(%0); cache 0, 0x530(%0)
-cache 0, 0x540(%0); cache 0, 0x550(%0); cache 0, 0x560(%0); cache 0, 0x570(%0)
-cache 0, 0x580(%0); cache 0, 0x590(%0); cache 0, 0x5a0(%0); cache 0, 0x5b0(%0)
-cache 0, 0x5c0(%0); cache 0, 0x5d0(%0); cache 0, 0x5e0(%0); cache 0, 0x5f0(%0)
-cache 0, 0x600(%0); cache 0, 0x610(%0); cache 0, 0x620(%0); cache 0, 0x630(%0)
-cache 0, 0x640(%0); cache 0, 0x650(%0); cache 0, 0x660(%0); cache 0, 0x670(%0)
-cache 0, 0x680(%0); cache 0, 0x690(%0); cache 0, 0x6a0(%0); cache 0, 0x6b0(%0)
-cache 0, 0x6c0(%0); cache 0, 0x6d0(%0); cache 0, 0x6e0(%0); cache 0, 0x6f0(%0)
-cache 0, 0x700(%0); cache 0, 0x710(%0); cache 0, 0x720(%0); cache 0, 0x730(%0)
-cache 0, 0x740(%0); cache 0, 0x750(%0); cache 0, 0x760(%0); cache 0, 0x770(%0)
-cache 0, 0x780(%0); cache 0, 0x790(%0); cache 0, 0x7a0(%0); cache 0, 0x7b0(%0)
-cache 0, 0x7c0(%0); cache 0, 0x7d0(%0); cache 0, 0x7e0(%0); cache 0, 0x7f0(%0)
-.set mips0
-.set reorder
-                " : : "r" (start));
-		start += 0x800;
+		cache16_unroll32(start,Index_Writeback_Inv_SD);
+		start += 0x200;
 	}
 }
 
-extern inline void blast_icache32(void)
+#define cache32_unroll32(base,op)				\
+	__asm__ __volatile__("					\
+		.set noreorder;					\
+		.set mips3;					\
+		cache %1, 0x000(%0); cache %1, 0x020(%0);	\
+		cache %1, 0x040(%0); cache %1, 0x060(%0);	\
+		cache %1, 0x080(%0); cache %1, 0x0a0(%0);	\
+		cache %1, 0x0c0(%0); cache %1, 0x0e0(%0);	\
+		cache %1, 0x100(%0); cache %1, 0x120(%0);	\
+		cache %1, 0x140(%0); cache %1, 0x160(%0);	\
+		cache %1, 0x180(%0); cache %1, 0x1a0(%0);	\
+		cache %1, 0x1c0(%0); cache %1, 0x1e0(%0);	\
+		cache %1, 0x200(%0); cache %1, 0x220(%0);	\
+		cache %1, 0x240(%0); cache %1, 0x260(%0);	\
+		cache %1, 0x280(%0); cache %1, 0x2a0(%0);	\
+		cache %1, 0x2c0(%0); cache %1, 0x2e0(%0);	\
+		cache %1, 0x300(%0); cache %1, 0x320(%0);	\
+		cache %1, 0x340(%0); cache %1, 0x360(%0);	\
+		cache %1, 0x380(%0); cache %1, 0x3a0(%0);	\
+		cache %1, 0x3c0(%0); cache %1, 0x3e0(%0);	\
+		.set mips0;					\
+		.set reorder"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
+extern inline void blast_dcache32(void)
 {
 	unsigned long start = KSEG0;
-	unsigned long end = (start + icache_size);
+	unsigned long end = (start + dcache_size);
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0);
-cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0);
-cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0);
-cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0);
-cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0);
-cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0);
-cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0);
-cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0);
-.set mips0
-.set reorder
-                " : : "r" (start));
+		cache32_unroll32(start,Index_Writeback_Inv_D);
 		start += 0x400;
 	}
 }
 
-extern inline void blast_icache32_page(unsigned long page)
+/*
+ * Call this function only with interrupts disabled or R4600 V2.0 may blow
+ * up on you.
+ *
+ * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D,
+ * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Excl_D will only
+ * operate correctly if the internal data cache refill buffer is empty.  These
+ * CACHE instructions should be separated from any potential data cache miss
+ * by a load instruction to an uncached address to empty the response buffer."
+ * (Revision 2.0 device errata from IDT available on http://www.idt.com/
+ * in .pdf format.)
+ */
+extern inline void blast_dcache32_page(unsigned long page)
 {
 	unsigned long start = page;
 	unsigned long end = (start + PAGE_SIZE);
 
+	/*
+	 * Sigh ... workaround for R4600 v1.7 bug.  Explanation see above.
+	 */
+	*(volatile unsigned long *)KSEG1;
+
+	__asm__ __volatile__("nop;nop;nop;nop");
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 16, 0x000(%0); cache 16, 0x020(%0); cache 16, 0x040(%0); cache 16, 0x060(%0);
-cache 16, 0x080(%0); cache 16, 0x0a0(%0); cache 16, 0x0c0(%0); cache 16, 0x0e0(%0);
-cache 16, 0x100(%0); cache 16, 0x120(%0); cache 16, 0x140(%0); cache 16, 0x160(%0);
-cache 16, 0x180(%0); cache 16, 0x1a0(%0); cache 16, 0x1c0(%0); cache 16, 0x1e0(%0);
-cache 16, 0x200(%0); cache 16, 0x220(%0); cache 16, 0x240(%0); cache 16, 0x260(%0);
-cache 16, 0x280(%0); cache 16, 0x2a0(%0); cache 16, 0x2c0(%0); cache 16, 0x2e0(%0);
-cache 16, 0x300(%0); cache 16, 0x320(%0); cache 16, 0x340(%0); cache 16, 0x360(%0);
-cache 16, 0x380(%0); cache 16, 0x3a0(%0); cache 16, 0x3c0(%0); cache 16, 0x3e0(%0);
-cache 16, 0x400(%0); cache 16, 0x420(%0); cache 16, 0x440(%0); cache 16, 0x460(%0);
-cache 16, 0x480(%0); cache 16, 0x4a0(%0); cache 16, 0x4c0(%0); cache 16, 0x4e0(%0);
-cache 16, 0x500(%0); cache 16, 0x520(%0); cache 16, 0x540(%0); cache 16, 0x560(%0);
-cache 16, 0x580(%0); cache 16, 0x5a0(%0); cache 16, 0x5c0(%0); cache 16, 0x5e0(%0);
-cache 16, 0x600(%0); cache 16, 0x620(%0); cache 16, 0x640(%0); cache 16, 0x660(%0);
-cache 16, 0x680(%0); cache 16, 0x6a0(%0); cache 16, 0x6c0(%0); cache 16, 0x6e0(%0);
-cache 16, 0x700(%0); cache 16, 0x720(%0); cache 16, 0x740(%0); cache 16, 0x760(%0);
-cache 16, 0x780(%0); cache 16, 0x7a0(%0); cache 16, 0x7c0(%0); cache 16, 0x7e0(%0);
-.set mips0
-.set reorder
-                " : : "r" (start));
-		start += 0x800;
+		cache32_unroll32(start,Hit_Writeback_Inv_D);
+		start += 0x400;
 	}
 }
 
-extern inline void blast_icache32_page_indexed(unsigned long page)
+extern inline void blast_dcache32_page_indexed(unsigned long page)
 {
 	unsigned long start = page;
 	unsigned long end = (start + PAGE_SIZE);
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 0, 0x000(%0); cache 0, 0x020(%0); cache 0, 0x040(%0); cache 0, 0x060(%0);
-cache 0, 0x080(%0); cache 0, 0x0a0(%0); cache 0, 0x0c0(%0); cache 0, 0x0e0(%0);
-cache 0, 0x100(%0); cache 0, 0x120(%0); cache 0, 0x140(%0); cache 0, 0x160(%0);
-cache 0, 0x180(%0); cache 0, 0x1a0(%0); cache 0, 0x1c0(%0); cache 0, 0x1e0(%0);
-cache 0, 0x200(%0); cache 0, 0x220(%0); cache 0, 0x240(%0); cache 0, 0x260(%0);
-cache 0, 0x280(%0); cache 0, 0x2a0(%0); cache 0, 0x2c0(%0); cache 0, 0x2e0(%0);
-cache 0, 0x300(%0); cache 0, 0x320(%0); cache 0, 0x340(%0); cache 0, 0x360(%0);
-cache 0, 0x380(%0); cache 0, 0x3a0(%0); cache 0, 0x3c0(%0); cache 0, 0x3e0(%0);
-cache 0, 0x400(%0); cache 0, 0x420(%0); cache 0, 0x440(%0); cache 0, 0x460(%0);
-cache 0, 0x480(%0); cache 0, 0x4a0(%0); cache 0, 0x4c0(%0); cache 0, 0x4e0(%0);
-cache 0, 0x500(%0); cache 0, 0x520(%0); cache 0, 0x540(%0); cache 0, 0x560(%0);
-cache 0, 0x580(%0); cache 0, 0x5a0(%0); cache 0, 0x5c0(%0); cache 0, 0x5e0(%0);
-cache 0, 0x600(%0); cache 0, 0x620(%0); cache 0, 0x640(%0); cache 0, 0x660(%0);
-cache 0, 0x680(%0); cache 0, 0x6a0(%0); cache 0, 0x6c0(%0); cache 0, 0x6e0(%0);
-cache 0, 0x700(%0); cache 0, 0x720(%0); cache 0, 0x740(%0); cache 0, 0x760(%0);
-cache 0, 0x780(%0); cache 0, 0x7a0(%0); cache 0, 0x7c0(%0); cache 0, 0x7e0(%0);
-.set mips0
-.set reorder
-                " : : "r" (start));
-		start += 0x800;
+		cache32_unroll32(start,Index_Writeback_Inv_D);
+		start += 0x400;
 	}
 }
 
-extern inline void blast_scache16(void)
+extern inline void blast_icache32(void)
 {
 	unsigned long start = KSEG0;
-	unsigned long end = KSEG0 + scache_size;
+	unsigned long end = (start + icache_size);
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0)
-cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0)
-cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0)
-cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0)
-cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0)
-cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0)
-cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0)
-cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0)
-.set mips0
-.set reorder
-                " : : "r" (start));
-		start += 0x200;
+		cache32_unroll32(start,Index_Invalidate_I);
+		start += 0x400;
 	}
 }
 
-extern inline void blast_scache16_page(unsigned long page)
+extern inline void blast_icache32_page(unsigned long page)
 {
 	unsigned long start = page;
-	unsigned long end = page + PAGE_SIZE;
+	unsigned long end = (start + PAGE_SIZE);
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 23, 0x000(%0); cache 23, 0x010(%0); cache 23, 0x020(%0); cache 23, 0x030(%0)
-cache 23, 0x040(%0); cache 23, 0x050(%0); cache 23, 0x060(%0); cache 23, 0x070(%0)
-cache 23, 0x080(%0); cache 23, 0x090(%0); cache 23, 0x0a0(%0); cache 23, 0x0b0(%0)
-cache 23, 0x0c0(%0); cache 23, 0x0d0(%0); cache 23, 0x0e0(%0); cache 23, 0x0f0(%0)
-cache 23, 0x100(%0); cache 23, 0x110(%0); cache 23, 0x120(%0); cache 23, 0x130(%0)
-cache 23, 0x140(%0); cache 23, 0x150(%0); cache 23, 0x160(%0); cache 23, 0x170(%0)
-cache 23, 0x180(%0); cache 23, 0x190(%0); cache 23, 0x1a0(%0); cache 23, 0x1b0(%0)
-cache 23, 0x1c0(%0); cache 23, 0x1d0(%0); cache 23, 0x1e0(%0); cache 23, 0x1f0(%0)
-.set mips0
-.set reorder
-                " : : "r" (start));
-		start += 0x200;
+		cache32_unroll32(start,Hit_Invalidate_I);
+		start += 0x400;
 	}
 }
 
-extern inline void blast_scache16_page_indexed(unsigned long page)
+extern inline void blast_icache32_page_indexed(unsigned long page)
 {
 	unsigned long start = page;
-	unsigned long end = page + PAGE_SIZE;
+	unsigned long end = (start + PAGE_SIZE);
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 3, 0x000(%0); cache 3, 0x010(%0); cache 3, 0x020(%0); cache 3, 0x030(%0)
-cache 3, 0x040(%0); cache 3, 0x050(%0); cache 3, 0x060(%0); cache 3, 0x070(%0)
-cache 3, 0x080(%0); cache 3, 0x090(%0); cache 3, 0x0a0(%0); cache 3, 0x0b0(%0)
-cache 3, 0x0c0(%0); cache 3, 0x0d0(%0); cache 3, 0x0e0(%0); cache 3, 0x0f0(%0)
-cache 3, 0x100(%0); cache 3, 0x110(%0); cache 3, 0x120(%0); cache 3, 0x130(%0)
-cache 3, 0x140(%0); cache 3, 0x150(%0); cache 3, 0x160(%0); cache 3, 0x170(%0)
-cache 3, 0x180(%0); cache 3, 0x190(%0); cache 3, 0x1a0(%0); cache 3, 0x1b0(%0)
-cache 3, 0x1c0(%0); cache 3, 0x1d0(%0); cache 3, 0x1e0(%0); cache 3, 0x1f0(%0)
-.set mips0
-.set reorder
-                " : : "r" (start));
-		start += 0x200;
+		cache32_unroll32(start,Index_Invalidate_I);
+		start += 0x400;
 	}
 }
 
@@ -909,20 +393,7 @@
 	unsigned long end = KSEG0 + scache_size;
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0);
-cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0);
-cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0);
-cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0);
-cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0);
-cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0);
-cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0);
-cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0);
-.set mips0
-.set reorder
-                " : : "r" (start));
+		cache32_unroll32(start,Index_Writeback_Inv_SD);
 		start += 0x400;
 	}
 }
@@ -933,20 +404,7 @@
 	unsigned long end = page + PAGE_SIZE;
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 23, 0x000(%0); cache 23, 0x020(%0); cache 23, 0x040(%0); cache 23, 0x060(%0);
-cache 23, 0x080(%0); cache 23, 0x0a0(%0); cache 23, 0x0c0(%0); cache 23, 0x0e0(%0);
-cache 23, 0x100(%0); cache 23, 0x120(%0); cache 23, 0x140(%0); cache 23, 0x160(%0);
-cache 23, 0x180(%0); cache 23, 0x1a0(%0); cache 23, 0x1c0(%0); cache 23, 0x1e0(%0);
-cache 23, 0x200(%0); cache 23, 0x220(%0); cache 23, 0x240(%0); cache 23, 0x260(%0);
-cache 23, 0x280(%0); cache 23, 0x2a0(%0); cache 23, 0x2c0(%0); cache 23, 0x2e0(%0);
-cache 23, 0x300(%0); cache 23, 0x320(%0); cache 23, 0x340(%0); cache 23, 0x360(%0);
-cache 23, 0x380(%0); cache 23, 0x3a0(%0); cache 23, 0x3c0(%0); cache 23, 0x3e0(%0);
-.set mips0
-.set reorder
-                " : : "r" (start));
+		cache32_unroll32(start,Hit_Writeback_Inv_SD);
 		start += 0x400;
 	}
 }
@@ -957,54 +415,44 @@
 	unsigned long end = page + PAGE_SIZE;
 
 	while(start < end) {
-		__asm__ __volatile__("
-.set noreorder
-.set mips3
-cache 3, 0x000(%0); cache 3, 0x020(%0); cache 3, 0x040(%0); cache 3, 0x060(%0);
-cache 3, 0x080(%0); cache 3, 0x0a0(%0); cache 3, 0x0c0(%0); cache 3, 0x0e0(%0);
-cache 3, 0x100(%0); cache 3, 0x120(%0); cache 3, 0x140(%0); cache 3, 0x160(%0);
-cache 3, 0x180(%0); cache 3, 0x1a0(%0); cache 3, 0x1c0(%0); cache 3, 0x1e0(%0);
-cache 3, 0x200(%0); cache 3, 0x220(%0); cache 3, 0x240(%0); cache 3, 0x260(%0);
-cache 3, 0x280(%0); cache 3, 0x2a0(%0); cache 3, 0x2c0(%0); cache 3, 0x2e0(%0);
-cache 3, 0x300(%0); cache 3, 0x320(%0); cache 3, 0x340(%0); cache 3, 0x360(%0);
-cache 3, 0x380(%0); cache 3, 0x3a0(%0); cache 3, 0x3c0(%0); cache 3, 0x3e0(%0);
-.set mips0
-.set reorder
-                " : : "r" (start));
+		cache32_unroll32(start,Index_Writeback_Inv_SD);
 		start += 0x400;
 	}
 }
 
+#define cache64_unroll32(base,op)				\
+	__asm__ __volatile__("					\
+		.set noreorder;					\
+		.set mips3;					\
+		cache %1, 0x000(%0); cache %1, 0x040(%0);	\
+		cache %1, 0x080(%0); cache %1, 0x0c0(%0);	\
+		cache %1, 0x100(%0); cache %1, 0x140(%0);	\
+		cache %1, 0x180(%0); cache %1, 0x1c0(%0);	\
+		cache %1, 0x200(%0); cache %1, 0x240(%0);	\
+		cache %1, 0x280(%0); cache %1, 0x2c0(%0);	\
+		cache %1, 0x300(%0); cache %1, 0x340(%0);	\
+		cache %1, 0x380(%0); cache %1, 0x3c0(%0);	\
+		cache %1, 0x400(%0); cache %1, 0x440(%0);	\
+		cache %1, 0x480(%0); cache %1, 0x4c0(%0);	\
+		cache %1, 0x500(%0); cache %1, 0x540(%0);	\
+		cache %1, 0x580(%0); cache %1, 0x5c0(%0);	\
+		cache %1, 0x600(%0); cache %1, 0x640(%0);	\
+		cache %1, 0x680(%0); cache %1, 0x6c0(%0);	\
+		cache %1, 0x700(%0); cache %1, 0x740(%0);	\
+		cache %1, 0x780(%0); cache %1, 0x7c0(%0);	\
+		.set mips0;					\
+		.set reorder"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
 extern inline void blast_scache64(void)
 {
 	unsigned long start = KSEG0;
 	unsigned long end = KSEG0 + scache_size;
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x040(%0)
-			cache %1, 0x080(%0); cache %1, 0x0c0(%0)
-			cache %1, 0x100(%0); cache %1, 0x140(%0)
-			cache %1, 0x180(%0); cache %1, 0x1c0(%0)
-			cache %1, 0x200(%0); cache %1, 0x240(%0)
-			cache %1, 0x280(%0); cache %1, 0x2c0(%0)
-			cache %1, 0x300(%0); cache %1, 0x340(%0)
-			cache %1, 0x380(%0); cache %1, 0x3c0(%0)
-			cache %1, 0x400(%0); cache %1, 0x440(%0)
-			cache %1, 0x480(%0); cache %1, 0x4c0(%0)
-			cache %1, 0x500(%0); cache %1, 0x540(%0)
-			cache %1, 0x580(%0); cache %1, 0x5c0(%0)
-			cache %1, 0x600(%0); cache %1, 0x640(%0)
-			cache %1, 0x680(%0); cache %1, 0x6c0(%0)
-			cache %1, 0x700(%0); cache %1, 0x740(%0)
-			cache %1, 0x780(%0); cache %1, 0x7c0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_SD));
+		cache64_unroll32(start,Index_Writeback_Inv_SD);
 		start += 0x800;
 	}
 }
@@ -1015,30 +463,7 @@
 	unsigned long end = page + PAGE_SIZE;
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x040(%0)
-			cache %1, 0x080(%0); cache %1, 0x0c0(%0)
-			cache %1, 0x100(%0); cache %1, 0x140(%0)
-			cache %1, 0x180(%0); cache %1, 0x1c0(%0)
-			cache %1, 0x200(%0); cache %1, 0x240(%0)
-			cache %1, 0x280(%0); cache %1, 0x2c0(%0)
-			cache %1, 0x300(%0); cache %1, 0x340(%0)
-			cache %1, 0x380(%0); cache %1, 0x3c0(%0)
-			cache %1, 0x400(%0); cache %1, 0x440(%0)
-			cache %1, 0x480(%0); cache %1, 0x4c0(%0)
-			cache %1, 0x500(%0); cache %1, 0x540(%0)
-			cache %1, 0x580(%0); cache %1, 0x5c0(%0)
-			cache %1, 0x600(%0); cache %1, 0x640(%0)
-			cache %1, 0x680(%0); cache %1, 0x6c0(%0)
-			cache %1, 0x700(%0); cache %1, 0x740(%0)
-			cache %1, 0x780(%0); cache %1, 0x7c0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Hit_Writeback_Inv_D));
+		cache64_unroll32(start,Hit_Writeback_Inv_SD);
 		start += 0x800;
 	}
 }
@@ -1049,122 +474,56 @@
 	unsigned long end = page + PAGE_SIZE;
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x040(%0)
-			cache %1, 0x080(%0); cache %1, 0x0c0(%0)
-			cache %1, 0x100(%0); cache %1, 0x140(%0)
-			cache %1, 0x180(%0); cache %1, 0x1c0(%0)
-			cache %1, 0x200(%0); cache %1, 0x240(%0)
-			cache %1, 0x280(%0); cache %1, 0x2c0(%0)
-			cache %1, 0x300(%0); cache %1, 0x340(%0)
-			cache %1, 0x380(%0); cache %1, 0x3c0(%0)
-			cache %1, 0x400(%0); cache %1, 0x440(%0)
-			cache %1, 0x480(%0); cache %1, 0x4c0(%0)
-			cache %1, 0x500(%0); cache %1, 0x540(%0)
-			cache %1, 0x580(%0); cache %1, 0x5c0(%0)
-			cache %1, 0x600(%0); cache %1, 0x640(%0)
-			cache %1, 0x680(%0); cache %1, 0x6c0(%0)
-			cache %1, 0x700(%0); cache %1, 0x740(%0)
-			cache %1, 0x780(%0); cache %1, 0x7c0(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_SD));
+		cache64_unroll32(start,Index_Writeback_Inv_SD);
 		start += 0x800;
 	}
 }
 
+#define cache128_unroll32(base,op)				\
+	__asm__ __volatile__("					\
+		.set noreorder;					\
+		.set mips3;					\
+		cache %1, 0x000(%0); cache %1, 0x080(%0);	\
+		cache %1, 0x100(%0); cache %1, 0x180(%0);	\
+		cache %1, 0x200(%0); cache %1, 0x280(%0);	\
+		cache %1, 0x300(%0); cache %1, 0x380(%0);	\
+		cache %1, 0x400(%0); cache %1, 0x480(%0);	\
+		cache %1, 0x500(%0); cache %1, 0x580(%0);	\
+		cache %1, 0x600(%0); cache %1, 0x680(%0);	\
+		cache %1, 0x700(%0); cache %1, 0x780(%0);	\
+		cache %1, 0x800(%0); cache %1, 0x880(%0);	\
+		cache %1, 0x900(%0); cache %1, 0x980(%0);	\
+		cache %1, 0xa00(%0); cache %1, 0xa80(%0);	\
+		cache %1, 0xb00(%0); cache %1, 0xb80(%0);	\
+		cache %1, 0xc00(%0); cache %1, 0xc80(%0);	\
+		cache %1, 0xd00(%0); cache %1, 0xd80(%0);	\
+		cache %1, 0xe00(%0); cache %1, 0xe80(%0);	\
+		cache %1, 0xf00(%0); cache %1, 0xf80(%0);	\
+		.set mips0;					\
+		.set reorder"					\
+		:						\
+		: "r" (base),					\
+		  "i" (op));
+
 extern inline void blast_scache128(void)
 {
 	unsigned long start = KSEG0;
 	unsigned long end = KSEG0 + scache_size;
 
 	while(start < end) {
-		__asm__ __volatile__("
-			.set noreorder
-			.set mips3
-			cache %1, 0x000(%0); cache %1, 0x080(%0)
-			cache %1, 0x100(%0); cache %1, 0x180(%0)
-			cache %1, 0x200(%0); cache %1, 0x280(%0)
-			cache %1, 0x300(%0); cache %1, 0x380(%0)
-			cache %1, 0x400(%0); cache %1, 0x480(%0)
-			cache %1, 0x500(%0); cache %1, 0x580(%0)
-			cache %1, 0x600(%0); cache %1, 0x680(%0)
-			cache %1, 0x700(%0); cache %1, 0x780(%0)
-			cache %1, 0x800(%0); cache %1, 0x880(%0)
-			cache %1, 0x900(%0); cache %1, 0x980(%0)
-			cache %1, 0xa00(%0); cache %1, 0xa80(%0)
-			cache %1, 0xb00(%0); cache %1, 0xb80(%0)
-			cache %1, 0xc00(%0); cache %1, 0xc80(%0)
-			cache %1, 0xd00(%0); cache %1, 0xd80(%0)
-			cache %1, 0xe00(%0); cache %1, 0xe80(%0)
-			cache %1, 0xf00(%0); cache %1, 0xf80(%0)
-			.set mips0
-			.set reorder"
-			:
-			: "r" (start),
-			  "i" (Index_Writeback_Inv_SD));
+		cache128_unroll32(start,Index_Writeback_Inv_SD);
 		start += 0x1000;
 	}
 }
 
 extern inline void blast_scache128_page(unsigned long page)
 {
-	__asm__ __volatile__("
-		.set noreorder
-		.set mips3
-		cache %1, 0x000(%0); cache %1, 0x080(%0)
-		cache %1, 0x100(%0); cache %1, 0x180(%0)
-		cache %1, 0x200(%0); cache %1, 0x280(%0)
-		cache %1, 0x300(%0); cache %1, 0x380(%0)
-		cache %1, 0x400(%0); cache %1, 0x480(%0)
-		cache %1, 0x500(%0); cache %1, 0x580(%0)
-		cache %1, 0x600(%0); cache %1, 0x680(%0)
-		cache %1, 0x700(%0); cache %1, 0x780(%0)
-		cache %1, 0x800(%0); cache %1, 0x880(%0)
-		cache %1, 0x900(%0); cache %1, 0x980(%0)
-		cache %1, 0xa00(%0); cache %1, 0xa80(%0)
-		cache %1, 0xb00(%0); cache %1, 0xb80(%0)
-		cache %1, 0xc00(%0); cache %1, 0xc80(%0)
-		cache %1, 0xd00(%0); cache %1, 0xd80(%0)
-		cache %1, 0xe00(%0); cache %1, 0xe80(%0)
-		cache %1, 0xf00(%0); cache %1, 0xf80(%0)
-		.set mips0
-		.set reorder"
-		:
-		: "r" (page),
-		  "i" (Hit_Writeback_Inv_D));
+	cache128_unroll32(page,Hit_Writeback_Inv_SD);
 }
 
 extern inline void blast_scache128_page_indexed(unsigned long page)
 {
-	__asm__ __volatile__("
-		.set noreorder
-		.set mips3
-		cache %1, 0x000(%0); cache %1, 0x080(%0)
-		cache %1, 0x100(%0); cache %1, 0x180(%0)
-		cache %1, 0x200(%0); cache %1, 0x280(%0)
-		cache %1, 0x300(%0); cache %1, 0x380(%0)
-		cache %1, 0x400(%0); cache %1, 0x480(%0)
-		cache %1, 0x500(%0); cache %1, 0x580(%0)
-		cache %1, 0x600(%0); cache %1, 0x680(%0)
-		cache %1, 0x700(%0); cache %1, 0x780(%0)
-		cache %1, 0x800(%0); cache %1, 0x880(%0)
-		cache %1, 0x900(%0); cache %1, 0x980(%0)
-		cache %1, 0xa00(%0); cache %1, 0xa80(%0)
-		cache %1, 0xb00(%0); cache %1, 0xb80(%0)
-		cache %1, 0xc00(%0); cache %1, 0xc80(%0)
-		cache %1, 0xd00(%0); cache %1, 0xd80(%0)
-		cache %1, 0xe00(%0); cache %1, 0xe80(%0)
-		cache %1, 0xf00(%0); cache %1, 0xf80(%0)
-		.set mips0
-		.set reorder"
-		:
-		: "r" (page),
-		  "i" (Index_Writeback_Inv_SD));
+	cache128_unroll32(page,Index_Writeback_Inv_SD);
 }
 
 #endif /* !(_MIPS_R4KCACHE_H) */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- v2.1.100/linux/include/asm-mips/semaphore.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/semaphore.h	Fri May  8 00:13:26 1998
@@ -10,7 +10,9 @@
 #ifndef __ASM_MIPS_SEMAPHORE_H
 #define __ASM_MIPS_SEMAPHORE_H
 
+#include <asm/system.h>
 #include <asm/atomic.h>
+#include <asm/spinlock.h>
 
 struct semaphore {
 	atomic_t count;
@@ -24,6 +26,8 @@
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
 
 #define sema_init(sem, val)	atomic_set(&((sem)->count), val)
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgi.h linux/include/asm-mips/sgi.h
--- v2.1.100/linux/include/asm-mips/sgi.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/sgi.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: sgi.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
+/* $Id: sgi.h,v 1.2 1998/05/01 01:36:05 ralf Exp $
  * sgi.h: Definitions specific to SGI machines.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h
--- v2.1.100/linux/include/asm-mips/sgialib.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/sgialib.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: sgialib.h,v 1.1.1.1 1997/06/01 03:17:13 ralf Exp $
+/* $Id: sgialib.h,v 1.2 1998/05/01 01:36:06 ralf Exp $
  * sgialib.h: SGI ARCS firmware interface library for the Linux kernel.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgiarcs.h linux/include/asm-mips/sgiarcs.h
--- v2.1.100/linux/include/asm-mips/sgiarcs.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/sgiarcs.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: sgiarcs.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
+/* $Id: sgiarcs.h,v 1.2 1998/05/01 01:36:07 ralf Exp $
  * SGI ARCS firmware interface defines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgihpc.h linux/include/asm-mips/sgihpc.h
--- v2.1.100/linux/include/asm-mips/sgihpc.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/sgihpc.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: sgihpc.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
+/* $Id: sgihpc.h,v 1.2 1998/05/01 01:36:07 ralf Exp $
  * sgihpc.h: Various HPC I/O controller defines.  The HPC is basically
  *           the approximate functional equivalent of the Sun SYSIO
  *           on SGI INDY machines.
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgimc.h linux/include/asm-mips/sgimc.h
--- v2.1.100/linux/include/asm-mips/sgimc.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/sgimc.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: sgimc.h,v 1.1.1.1 1997/06/01 03:17:13 ralf Exp $
+/* $Id: sgimc.h,v 1.2 1998/05/01 01:36:08 ralf Exp $
  * sgimc.h: Definitions for memory controller hardware found on
  *          SGI IP20, IP22, IP26, and IP28 machines.
  *
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sgint23.h linux/include/asm-mips/sgint23.h
--- v2.1.100/linux/include/asm-mips/sgint23.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/sgint23.h	Fri May  8 00:13:26 1998
@@ -1,4 +1,4 @@
-/* $Id: sgint23.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
+/* $Id: sgint23.h,v 1.2 1998/05/01 01:36:09 ralf Exp $
  * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -126,7 +126,7 @@
 #define SGINT_TCWORD_CNT2   0x80 /* Select counter two */
 #define SGINT_TCWORD_CRBCK  0xc0 /* Readback command */
 
-#define SGINT_TCSAMP_COUNTER  0x164
+#define SGINT_TCSAMP_COUNTER  10255
 
 struct sgi_int2_regs {
 	struct sgi_ioc_ints ints;
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h
--- v2.1.100/linux/include/asm-mips/sigcontext.h	Tue Dec 16 12:46:14 1997
+++ linux/include/asm-mips/sigcontext.h	Fri May  8 00:13:26 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: sigcontext.h,v 1.4 1997/12/01 16:46:19 ralf Exp $
+ * $Id: sigcontext.h,v 1.6 1998/05/01 01:36:10 ralf Exp $
  */
 #ifndef __ASM_MIPS_SIGCONTEXT_H
 #define __ASM_MIPS_SIGCONTEXT_H
@@ -32,8 +32,7 @@
 	unsigned int       sc_cause;		/* Unused */
 	unsigned int       sc_badvaddr;		/* Unused */
 
-	unsigned long      sc_sigset;		/* kernel's sigset_t */
-	unsigned long      __pad0[3];		/* pad for constant size */
+	unsigned long      sc_sigset[4];	/* kernel's sigset_t */
 };
 
 #endif /* __ASM_MIPS_SIGCONTEXT_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h
--- v2.1.100/linux/include/asm-mips/signal.h	Tue Dec 16 12:46:14 1997
+++ linux/include/asm-mips/signal.h	Fri May  8 00:13:26 1998
@@ -7,17 +7,22 @@
  *
  * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
- * $Id: signal.h,v 1.2 1997/09/07 05:27:50 ralf Exp $
+ * $Id: signal.h,v 1.8 1998/05/01 01:36:11 ralf Exp $
  */
 #ifndef __ASM_MIPS_SIGNAL_H
 #define __ASM_MIPS_SIGNAL_H
 
-#include <asm/sgidefs.h>
+#include <linux/types.h>
 
-typedef unsigned long sigset_t;
+#define _NSIG		128
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
 
-#define _NSIG		32
-#define NSIG		_NSIG
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
 
 #define SIGHUP		 1	/* Hangup (POSIX).  */
 #define SIGINT		 2	/* Interrupt (ANSI).  */
@@ -54,34 +59,48 @@
 #define SIGXCPU		30	/* CPU limit exceeded (4.2 BSD).  */
 #define SIGXFSZ		31	/* File size limit exceeded (4.2 BSD).  */
 
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	(_NSIG-1)
+
 /*
- * sa_flags values: SA_STACK is not currently supported, but will allow the
- * usage of signal stacks by using the (now obsolete) sa_restorer field in
- * the sigaction structure as a stack pointer. This is now possible due to
- * the changes in signal handling. LBT 010493.
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
  * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
  * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
  */
-#define SA_STACK	0x1
-#define SA_ONSTACK	SA_STACK
-#define SA_RESTART	0x4
-#define SA_NOCLDSTOP	0x20000
-/* Non ABI signals */
-#define SA_INTERRUPT	0x01000000
-#define SA_NOMASK	0x02000000
-#define SA_ONESHOT	0x04000000
-#define SA_SHIRQ	0x08000000
+#define SA_STACK	0x00000001
+#define SA_RESETHAND	0x00000002
+#define SA_RESTART	0x00000004
+#define SA_SIGINFO	0x00000008
+#define SA_NODEFER	0x00000010
+#define SA_NOCLDWAIT	0x00010000	/* Not supported yet */
+#define SA_NOCLDSTOP	0x00020000
+
+#define SA_NOMASK	SA_NODEFER	/* DANGER: was 0x02000000 */
+#define SA_ONESHOT	SA_RESETHAND	/* DANGER: was 0x04000000 */
 
 #ifdef __KERNEL__
 /*
  * These values of sa_flags are used only by the kernel as part of the
  * irq handling routines.
  *
- * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_SHIRQ flag is for shared interrupt support on PCI and EISA.
  */
-#define SA_PROBE SA_ONESHOT
-#define SA_SAMPLE_RANDOM SA_RESTART
+#define SA_INTERRUPT		0x01000000	/* interrupt handling */
+#define SA_SHIRQ		0x08000000
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
 #endif /* __KERNEL__ */
 
 #define SIG_BLOCK	1	/* for blocking signals */
@@ -102,17 +121,13 @@
 	unsigned int	sa_flags;
 	__sighandler_t	sa_handler;
 	sigset_t	sa_mask;
-	unsigned int	__pad0[3];	/* reserved, keep size constant */
+	int		sa_resv[2];	/* reserved */
+};
 
-	/* Abi says here follows reserved int[2] */
-	void		(*sa_restorer)(void);
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
-	/*
-	 * For 32 bit code we have to pad struct sigaction to get
-	 * constant size for the ABI
-	 */
-	int		__pad1[1];	/* reserved */
-#endif
+/* XXX use sa_rev for storing ka_restorer */
+struct k_sigaction {
+	struct sigaction sa;
+	void (*ka_restorer)(void);
 };
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/smp.h linux/include/asm-mips/smp.h
--- v2.1.100/linux/include/asm-mips/smp.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/smp.h	Fri May  8 00:13:26 1998
@@ -1,6 +1,6 @@
 #ifndef __ASM_MIPS_SMP_H
 #define __ASM_MIPS_SMP_H
 
-/* We'll get here eventually.. */
+#define cpu_logical_map(cpu)	(cpu)
 
 #endif /* __ASM_MIPS_SMP_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- v2.1.100/linux/include/asm-mips/socket.h	Sun Dec 21 17:41:24 1997
+++ linux/include/asm-mips/socket.h	Fri May  8 00:13:26 1998
@@ -1,8 +1,5 @@
 /*
- * $Id: socket.h,v 1.4 1997/12/06 20:32:40 ralf Exp $
- */
-/*
- * $Id: socket.h,v 1.4 1997/12/06 23:55:49 ralf Exp $
+ * $Id: socket.h,v 1.10 1998/05/01 01:36:12 ralf Exp $
  */
 #ifndef __ASM_MIPS_SOCKET_H
 #define __ASM_MIPS_SOCKET_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/softirq.h linux/include/asm-mips/softirq.h
--- v2.1.100/linux/include/asm-mips/softirq.h	Thu Jun 26 12:33:40 1997
+++ linux/include/asm-mips/softirq.h	Fri May  8 00:13:26 1998
@@ -1,3 +1,14 @@
+/*
+ * include/asm-mips/softirq.h
+ *
+ * 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
+ *
+ * $Id: softirq.h,v 1.2 1998/05/01 01:36:13 ralf Exp $
+ */
 #ifndef __ASM_MIPS_SOFTIRQ_H
 #define __ASM_MIPS_SOFTIRQ_H
 
@@ -7,6 +18,8 @@
  */
 extern atomic_t __mips_bh_counter;
 
+extern unsigned int local_bh_count[NR_CPUS];
+
 #define get_active_bhs()	(bh_mask & bh_active)
 
 static inline void clear_active_bhs(unsigned long x)
@@ -20,7 +33,7 @@
 		"beqz\t%0,1b"
 		:"=&r" (temp),
 		 "=m" (bh_active)
-		:"Ir" (x),
+		:"Ir" (~x),
 		 "m" (bh_active));
 }
 
@@ -58,36 +71,21 @@
 		bh_mask |= 1 << nr;
 }
 
-/*
- * start_bh_atomic/end_bh_atomic also nest
- * naturally by using a counter
- */
 extern inline void start_bh_atomic(void)
 {
-#ifdef __SMP__
-	atomic_inc(&__mips_bh_counter);
-	synchronize_irq();
-#else
-	atomic_inc(&__mips_bh_counter);
-#endif
+	local_bh_count[smp_processor_id()]++;
+	barrier();
 }
 
 extern inline void end_bh_atomic(void)
 {
-	atomic_dec(&__mips_bh_counter);
+	barrier();
+	local_bh_count[smp_processor_id()]--;
 }
 
-#ifndef __SMP__
-
 /* These are for the irq's testing the lock */
-#define softirq_trylock()	(atomic_read(&__mips_bh_counter) ? \
-				0 : \
-				((atomic_set(&__mips_bh_counter,1)),1))
-#define softirq_endlock()	(atomic_set(&__mips_bh_counter, 0))
-
-#else
-
-#error FIXME
+#define softirq_trylock(cpu)	(local_bh_count[cpu] ? 0 : (local_bh_count[cpu] = 1))
+#define softirq_endlock(cpu)	(local_bh_count[cpu] = 0)
+#define synchronize_bh()	do { } while (0)
 
-#endif /* __SMP__ */
 #endif /* __ASM_MIPS_SOFTIRQ_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h
--- v2.1.100/linux/include/asm-mips/stackframe.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/stackframe.h	Fri May  8 00:13:26 1998
@@ -2,6 +2,8 @@
  *  include/asm-mips/stackframe.h
  *
  *  Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine.
+ *
+ * $Id: stackframe.h,v 1.6 1998/05/04 09:19:00 ralf Exp $
  */
 #ifndef __ASM_MIPS_STACKFRAME_H
 #define __ASM_MIPS_STACKFRAME_H
@@ -9,14 +11,61 @@
 #include <asm/asm.h>
 #include <asm/offset.h>
 
-#define SAVE_ALL                                         \
+#define SAVE_AT                                          \
+		sw	$1, PT_R1(sp)
+
+#define SAVE_TEMP                                        \
+		mfhi	v1;                              \
+		sw	$8, PT_R8(sp);                   \
+		sw	$9, PT_R9(sp);                   \
+		sw	v1, PT_HI(sp);                   \
+		mflo	v1;                              \
+		sw	$10,PT_R10(sp);                  \
+		sw	$11, PT_R11(sp);                 \
+		sw	v1,  PT_LO(sp);                  \
+		sw	$12, PT_R12(sp);                 \
+		sw	$13, PT_R13(sp);                 \
+		sw	$14, PT_R14(sp);                 \
+		sw	$15, PT_R15(sp);                 \
+		sw	$24, PT_R24(sp)
+
+#define SAVE_STATIC                                      \
+		sw	$16, PT_R16(sp);                 \
+		sw	$17, PT_R17(sp);                 \
+		sw	$18, PT_R18(sp);                 \
+		sw	$19, PT_R19(sp);                 \
+		sw	$20, PT_R20(sp);                 \
+		sw	$21, PT_R21(sp);                 \
+		sw	$22, PT_R22(sp);                 \
+		sw	$23, PT_R23(sp);                 \
+		sw	$30, PT_R30(sp)
+
+#define __str2(x) #x
+#define __str(x) __str2(x)
+
+#define save_static(frame)                               \
+	__asm__ __volatile__(                            \
+		"sw\t$16,"__str(PT_R16)"(%0)\n\t"        \
+		"sw\t$17,"__str(PT_R17)"(%0)\n\t"        \
+		"sw\t$18,"__str(PT_R18)"(%0)\n\t"        \
+		"sw\t$19,"__str(PT_R19)"(%0)\n\t"        \
+		"sw\t$20,"__str(PT_R20)"(%0)\n\t"        \
+		"sw\t$21,"__str(PT_R21)"(%0)\n\t"        \
+		"sw\t$22,"__str(PT_R22)"(%0)\n\t"        \
+		"sw\t$23,"__str(PT_R23)"(%0)\n\t"        \
+		"sw\t$30,"__str(PT_R30)"(%0)\n\t"        \
+		: /* No outputs */                       \
+		: "r" (frame))
+
+#define SAVE_SOME                                        \
 		.set	push;                            \
 		.set	reorder;                         \
 		mfc0	k0, CP0_STATUS;                  \
 		sll	k0, 3;     /* extract cu0 bit */ \
-		.set	pop;                             \
+		.set	noreorder;                       \
 		bltz	k0, 8f;                          \
 		 move	k1, sp;                          \
+		.set	reorder;                         \
 		/* Called from user mode, new stack. */  \
 		lui	k1, %hi(kernelsp);               \
 		lw	k1, %lo(kernelsp)(k1);           \
@@ -24,53 +73,65 @@
 		move	k0, sp;                          \
 		subu	sp, k1, PT_SIZE;                 \
 		sw	k0, PT_R29(sp);                  \
-		sw	$2, PT_R2(sp);                   \
-		sw	$1, PT_R1(sp);                   \
-		sw	$2, PT_OR2(sp);                  \
-		sw	$0, PT_R0(sp);			 \
-		mfc0	v0, CP0_STATUS;                  \
 		sw	$3, PT_R3(sp);                   \
-		sw	v0, PT_STATUS(sp);               \
+		sw	$0, PT_R0(sp);			 \
+		mfc0	v1, CP0_STATUS;                  \
+		sw	$2, PT_R2(sp);                   \
+		sw	v1, PT_STATUS(sp);               \
 		sw	$4, PT_R4(sp);                   \
-		mfc0	v0, CP0_CAUSE;                   \
+		mfc0	v1, CP0_CAUSE;                   \
 		sw	$5, PT_R5(sp);                   \
-		sw	v0, PT_CAUSE(sp);                \
+		sw	v1, PT_CAUSE(sp);                \
 		sw	$6, PT_R6(sp);                   \
-		mfc0	v0, CP0_EPC;                     \
+		mfc0	v1, CP0_EPC;                     \
 		sw	$7, PT_R7(sp);                   \
-		sw	v0, PT_EPC(sp);                  \
-		sw	$7, PT_OR7(sp);                  \
-		sw	$8, PT_R8(sp);                   \
-		mfhi	v0;                              \
-		sw	$9, PT_R9(sp);                   \
-		sw	v0, PT_HI(sp);                   \
-		sw	$10,PT_R10(sp);                  \
-		mflo	v0;                              \
-		sw	$11, PT_R11(sp);                 \
-		sw	v0,  PT_LO(sp);                  \
-		sw	$12, PT_R12(sp);                 \
-		sw	$13, PT_R13(sp);                 \
-		sw	$14, PT_R14(sp);                 \
-		sw	$15, PT_R15(sp);                 \
-		sw	$16, PT_R16(sp);                 \
-		sw	$17, PT_R17(sp);                 \
-		sw	$18, PT_R18(sp);                 \
-		sw	$19, PT_R19(sp);                 \
-		sw	$20, PT_R20(sp);                 \
-		sw	$21, PT_R21(sp);                 \
-		sw	$22, PT_R22(sp);                 \
-		sw	$23, PT_R23(sp);                 \
-		sw	$24, PT_R24(sp);                 \
+		sw	v1, PT_EPC(sp);                  \
 		sw	$25, PT_R25(sp);                 \
 		sw	$28, PT_R28(sp);                 \
-		sw	$30, PT_R30(sp);                 \
-		sw	$31, PT_R31(sp);
+		sw	$31, PT_R31(sp);                 \
+		ori	$28, sp, 0x1fff;                 \
+		xori	$28, 0x1fff;                     \
+		.set	pop
 
-/*
- * Note that we restore the IE flags from stack. This means
- * that a modified IE mask will be nullified.
- */
-#define RESTORE_ALL                                      \
+#define SAVE_ALL                                         \
+		SAVE_SOME;                               \
+		SAVE_AT;                                 \
+		SAVE_TEMP;                               \
+		SAVE_STATIC
+
+#define RESTORE_AT                                       \
+		lw	$1,  PT_R1(sp);                  \
+
+#define RESTORE_SP                                       \
+		lw	sp,  PT_R29(sp)
+
+#define RESTORE_TEMP                                     \
+		lw	$24, PT_LO(sp);                  \
+		lw	$8, PT_R8(sp);                   \
+		lw	$9, PT_R9(sp);                   \
+		mtlo	$24;                             \
+		lw	$24, PT_HI(sp);                  \
+		lw	$10,PT_R10(sp);                  \
+		lw	$11, PT_R11(sp);                 \
+		mthi	$24;                             \
+		lw	$12, PT_R12(sp);                 \
+		lw	$13, PT_R13(sp);                 \
+		lw	$14, PT_R14(sp);                 \
+		lw	$15, PT_R15(sp);                 \
+		lw	$24, PT_R24(sp)
+
+#define RESTORE_STATIC                                   \
+		lw	$16, PT_R16(sp);                 \
+		lw	$17, PT_R17(sp);                 \
+		lw	$18, PT_R18(sp);                 \
+		lw	$19, PT_R19(sp);                 \
+		lw	$20, PT_R20(sp);                 \
+		lw	$21, PT_R21(sp);                 \
+		lw	$22, PT_R22(sp);                 \
+		lw	$23, PT_R23(sp);                 \
+		lw	$30, PT_R30(sp)
+
+#define RESTORE_SOME                                     \
 		.set	push;                            \
 		.set	reorder;                         \
 		mfc0	t0, CP0_STATUS;                  \
@@ -79,42 +140,25 @@
 		xori	t0, 0x1f;                        \
 		mtc0	t0, CP0_STATUS;                  \
 		lw	v0, PT_STATUS(sp);               \
-		lw	v1, PT_LO(sp);                   \
 		mtc0	v0, CP0_STATUS;                  \
-		mtlo	v1;                              \
-		lw	v0, PT_HI(sp);                   \
 		lw	v1, PT_EPC(sp);                  \
-		mthi	v0;                              \
 		mtc0	v1, CP0_EPC;                     \
 		lw	$31, PT_R31(sp);                 \
-		lw	$30, PT_R30(sp);                 \
 		lw	$28, PT_R28(sp);                 \
 		lw	$25, PT_R25(sp);                 \
-		lw	$24, PT_R24(sp);                 \
-		lw	$23, PT_R23(sp);                 \
-		lw	$22, PT_R22(sp);                 \
-		lw	$21, PT_R21(sp);                 \
-		lw	$20, PT_R20(sp);                 \
-		lw	$19, PT_R19(sp);                 \
-		lw	$18, PT_R18(sp);                 \
-		lw	$17, PT_R17(sp);                 \
-		lw	$16, PT_R16(sp);                 \
-		lw	$15, PT_R15(sp);                 \
-		lw	$14, PT_R14(sp);                 \
-		lw	$13, PT_R13(sp);                 \
-		lw	$12, PT_R12(sp);                 \
-		lw	$11, PT_R11(sp);                 \
-		lw	$10, PT_R10(sp);                 \
-		lw	$9,  PT_R9(sp);                  \
-		lw	$8,  PT_R8(sp);                  \
 		lw	$7,  PT_R7(sp);                  \
 		lw	$6,  PT_R6(sp);                  \
 		lw	$5,  PT_R5(sp);                  \
 		lw	$4,  PT_R4(sp);                  \
 		lw	$3,  PT_R3(sp);                  \
-		lw	$2,  PT_R2(sp);                  \
-		lw	$1,  PT_R1(sp);                  \
-		lw	sp,  PT_R29(sp);
+		lw	$2,  PT_R2(sp)
+
+#define RESTORE_ALL                                      \
+		RESTORE_SOME;                            \
+		RESTORE_AT;                              \
+		RESTORE_TEMP;                            \
+		RESTORE_STATIC;                          \
+		RESTORE_SP
 
 /*
  * Move to kernel mode and disable interrupts.
@@ -130,14 +174,21 @@
 /*
  * Move to kernel mode and enable interrupts.
  * Set cp0 enable bit as sign that we're running on the kernel stack
- *
- * Note that the mtc0 will be effective on R4000 pipeline stage 7. This
- * means that another three instructions will be executed with interrupts
- * disabled.  Arch/mips/mips3/r4xx0.S makes use of this fact.
  */
 #define STI                                             \
 		mfc0	t0,CP0_STATUS;                  \
 		li	t1,ST0_CU0|0x1f;                \
+		or	t0,t1;                          \
+		xori	t0,0x1e;                        \
+		mtc0	t0,CP0_STATUS
+
+/*
+ * Just move to kernel mode and leave interrupts as they are.
+ * Set cp0 enable bit as sign that we're running on the kernel stack
+ */
+#define KMODE                                           \
+		mfc0	t0,CP0_STATUS;                  \
+		li	t1,ST0_CU0|0x1e;                \
 		or	t0,t1;                          \
 		xori	t0,0x1e;                        \
 		mtc0	t0,CP0_STATUS
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/string.h linux/include/asm-mips/string.h
--- v2.1.100/linux/include/asm-mips/string.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/string.h	Fri May  8 00:13:26 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, 1995, 1996, 1997 by Ralf Baechle
  *
- * $Id: string.h,v 1.3 1997/08/11 04:11:53 ralf Exp $
+ * $Id: string.h,v 1.7 1998/05/04 09:19:02 ralf Exp $
  */
 #ifndef __ASM_MIPS_STRING_H
 #define __ASM_MIPS_STRING_H
@@ -128,29 +128,23 @@
 extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
 
 #define __HAVE_ARCH_BCOPY
-extern char * bcopy(const char * src, char * dest, int count);
+extern __inline__ char * bcopy(const char * src, char * dest, int count)
+{
+	memmove(dest, src, count);
+}
 
 #define __HAVE_ARCH_MEMSCAN
 extern __inline__ void *memscan(void *__addr, int __c, size_t __size)
 {
 	char *__end = (char *)__addr + __size;
 
-	if (!__size)
-		return __addr;
-	__asm__(".set\tnoreorder\n\t"
-		".set\tnoat\n"
-		"1:\tlbu\t$1,(%0)\n\t"
-#if _MIPS_ISA == _MIPS_ISA_MIPS1
-		"nop\n\t"
-#endif
-		"beq\t$1,%3,2f\n\t"
+	__asm__(".set\tnoat\n"
+		"1:\tbeq\t%0,%1,2f\n\t"
 		"addiu\t%0,1\n\t"
-		"bne\t%0,%2,1b\n\t"
-		"nop\n\t"
-		".set\tat\n\t"
-		".set\treorder\n"
-		"2:"
-		: "=r" (__addr)
+		"lb\t$1,-1(%0)\n\t"
+		"bne\t$1,%4,1b\n"
+		"2:\t.set\tat"
+		: "=r" (__addr), "=r" (__end)
 		: "0" (__addr), "1" (__end), "r" (__c)
 		: "$1");
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/system.h linux/include/asm-mips/system.h
--- v2.1.100/linux/include/asm-mips/system.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/system.h	Fri May  8 00:13:26 1998
@@ -7,6 +7,8 @@
  *
  * Copyright (C) 1994, 1995 by Ralf Baechle
  * Modified further for R[236]000 by Paul M. Antoine, 1996
+ *
+ * $Id: system.h,v 1.7 1998/05/04 09:19:03 ralf Exp $
  */
 #ifndef __ASM_MIPS_SYSTEM_H
 #define __ASM_MIPS_SYSTEM_H
@@ -17,18 +19,18 @@
 extern __inline__ void
 __sti(void)
 {
-    __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t$1,$12\n\t"
-	"ori\t$1,0x1f\n\t"
-	"xori\t$1,0x1e\n\t"
-	"mtc0\t$1,$12\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-	: /* no outputs */
-	: /* no inputs */
-	: "$1", "memory");
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		"mfc0\t$1,$12\n\t"
+		"ori\t$1,0x1f\n\t"
+		"xori\t$1,0x1e\n\t"
+		"mtc0\t$1,$12\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		: /* no outputs */
+		: /* no inputs */
+		: "$1", "memory");
 }
 
 /*
@@ -41,21 +43,21 @@
 extern __inline__ void
 __cli(void)
 {
-    __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n\t"
-	"mfc0\t$1,$12\n\t"
-	"ori\t$1,1\n\t"
-	"xori\t$1,1\n\t"
-	"mtc0\t$1,$12\n\t"
-	"nop\n\t"
-	"nop\n\t"
-	"nop\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-	: /* no outputs */
-	: /* no inputs */
-	: "$1", "memory");
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		".set\tnoat\n\t"
+		"mfc0\t$1,$12\n\t"
+		"ori\t$1,1\n\t"
+		"xori\t$1,1\n\t"
+		"mtc0\t$1,$12\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		".set\tat\n\t"
+		".set\treorder"
+		: /* no outputs */
+		: /* no inputs */
+		: "$1", "memory");
 }
 
 #define __save_flags(x)                  \
@@ -87,16 +89,16 @@
 extern void __inline__
 __restore_flags(int flags)
 {
-    __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	"mtc0\t%0,$12\n\t"
-	"nop\n\t"
-	"nop\n\t"
-	"nop\n\t"
-	".set\treorder"
-	: /* no output */
-	: "r" (flags)
-	: "memory");
+	__asm__ __volatile__(
+		".set\tnoreorder\n\t"
+		"mtc0\t%0,$12\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		"nop\n\t"
+		".set\treorder"
+		: /* no output */
+		: "r" (flags)
+		: "memory");
 }
 
 /*
@@ -113,7 +115,7 @@
 	"# prevent instructions being moved around\n\t"	\
 	".set\tnoreorder\n\t"				\
 	".set\treorder"					\
-        : /* no output */				\
+	: /* no output */				\
 	: /* no input */				\
 	: "memory")
 
@@ -125,47 +127,12 @@
 extern asmlinkage void (*resume)(void *tsk);
 #endif /* !defined (__LANGUAGE_ASSEMBLY__) */
 
-/*
- * FIXME: resume() assumes current == prev
- */
 #define switch_to(prev,next) \
 do { \
-	prev->tss.current_ds = active_ds; \
-        active_ds = next->tss.current_ds; \
-        resume(next); \
+	resume(next); \
 } while(0)
 
 /*
- * The 8 and 16 bit variants have to disable interrupts temporarily.
- * Both are currently unused.
- */
-extern __inline__ unsigned long xchg_u8(volatile char * m, unsigned long val)
-{
-	unsigned long flags, retval;
-
-	save_flags(flags);
-	cli();
-	retval = *m;
-	*m = val;
-	restore_flags(flags);
-
-	return retval;
-}
-
-extern __inline__ unsigned long xchg_u16(volatile short * m, unsigned long val)
-{
-	unsigned long flags, retval;
-
-	save_flags(flags);
-	cli();
-	retval = *m;
-	*m = val;
-	restore_flags(flags);
-
-	return retval;
-}
-
-/*
  * For 32 and 64 bit operands we can take advantage of ll and sc.
  * FIXME: This doesn't work for R3000 machines.
  */
@@ -186,8 +153,9 @@
 		".set\tat\n\t"
 		".set\treorder"
 		: "=r" (val), "=r" (m), "=r" (dummy)
-		: "1" (m), "2" (val));
-#else /* FIXME: Brain-dead approach, but then again, I AM hacking - PMA */
+		: "1" (m), "2" (val)
+		: "memory");
+#else
 	unsigned long flags, retval;
 
 	save_flags(flags);
@@ -218,7 +186,8 @@
 		".set\tat\n\t"
 		".set\treorder"
 		: "=r" (val), "=r" (m), "=r" (dummy)
-		: "1" (m), "2" (val));
+		: "1" (m), "2" (val)
+		: "memory");
 
 	return val;
 }
@@ -239,14 +208,12 @@
 static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
 	switch (size) {
-		case 1:
-			return xchg_u8(ptr, x);
-		case 2:
-			return xchg_u16(ptr, x);
 		case 4:
 			return xchg_u32(ptr, x);
+#if defined(__mips64)
 		case 8:
 			return xchg_u64(ptr, x);
+#endif
 	}
 	__xchg_called_with_bad_pointer();
 	return x;
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.1.100/linux/include/asm-mips/termios.h	Wed Apr  8 19:36:29 1998
+++ linux/include/asm-mips/termios.h	Fri May  8 00:13:26 1998
@@ -92,7 +92,6 @@
 #define N_STRIP		4
 #define N_AX25		5
 #define N_X25		6		/* X.25 async */
-#define N_6PACK		7
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/timex.h linux/include/asm-mips/timex.h
--- v2.1.100/linux/include/asm-mips/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-mips/timex.h
+ *
+ * mips architecture timex specifications
+ */
+#ifndef _ASMmips_TIMEX_H
+#define _ASMmips_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#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)
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/types.h linux/include/asm-mips/types.h
--- v2.1.100/linux/include/asm-mips/types.h	Fri Jan 30 11:28:09 1998
+++ linux/include/asm-mips/types.h	Fri May  8 00:13:26 1998
@@ -60,15 +60,14 @@
 typedef __signed__ long long s64;
 typedef unsigned long long u64;
 #endif
-#define BITS_PER_LONG 32
   
 #else
   
 typedef __signed__ long s64;
 typedef unsigned long u64;
-#define BITS_PER_LONG 64
 
 #endif
+#define BITS_PER_LONG _MIPS_SZLONG
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/uaccess.h linux/include/asm-mips/uaccess.h
--- v2.1.100/linux/include/asm-mips/uaccess.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/uaccess.h	Fri May  8 00:13:26 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: uaccess.h,v 1.5 1997/12/01 16:44:08 ralf Exp $
+ * $Id: uaccess.h,v 1.9 1998/05/04 09:19:05 ralf Exp $
  */
 #ifndef __ASM_MIPS_UACCESS_H
 #define __ASM_MIPS_UACCESS_H
@@ -26,21 +26,18 @@
  *
  * For historical reasons, these macros are grossly misnamed.
  */
-#define KERNEL_DS 0
-#define USER_DS 1
+#define KERNEL_DS	((mm_segment_t) { 0UL })
+#define USER_DS		((mm_segment_t) { 1UL })
 
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
-extern int active_ds;
+#define get_fs()        (current->tss.current_ds)
+#define get_ds()	(KERNEL_DS)
+#define set_fs(x)       (current->tss.current_ds=(x))
 
-#define get_fs()        active_ds
-#define set_fs(x)       (active_ds=(x))
+#define segment_eq(a,b)	((a).seg == (b).seg)
 
-static inline unsigned long get_ds(void)
-{
-	return KERNEL_DS;
-}
 
 /*
  * Is a address valid? This does a straighforward calculation rather
@@ -53,8 +50,8 @@
  *  - OR we are in kernel mode.
  */
 #define __access_ok(addr,size,mask) \
-	(((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0)
-#define __access_mask (-(long)get_fs())
+        (((__signed__ long)((mask)&(addr | size | (addr+size)))) >= 0)
+#define __access_mask (-(long)(get_fs().seg))
 
 #define access_ok(type,addr,size) \
 __access_ok(((unsigned long)(addr)),(size),__access_mask)
@@ -108,24 +105,6 @@
 struct __large_struct { unsigned long buf[100]; };
 #define __m(x) (*(struct __large_struct *)(x))
 
-#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
-#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
-
-extern size_t __copy_user(void *__to, const void *__from, size_t __n);
-
-#define __copy_tofrom_user(to,from,n,v) ({ \
-	void * __cu_to; \
-	const void * __cu_from; \
-	long __cu_len; \
-	\
-	__cu_to = (to); \
-	__cu_from = (from); \
-	__cu_len = (n); \
-	if (__access_ok(((unsigned long)(v)),__cu_len,__access_mask)) \
-		__cu_len = __copy_user(__cu_to, __cu_from, __cu_len); \
-	__cu_len; \
-})
-
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
  * for 32 bit mode and old iron.
@@ -174,18 +153,15 @@
 	"move\t%0,$0\n" \
 	"2:\n\t" \
 	".section\t.fixup,\"ax\"\n" \
-	"3:\t.set\tnoat\n\t" \
-	"la\t$1,2b\n\t" \
-	"li\t%0,%3\n\t" \
-	"jr\t$1\n\t" \
-	".set\tat\n\t" \
+	"3:\tli\t%0,%3\n\t" \
+	"move\t%1,$0\n\t" \
+	"j\t2b\n\t" \
 	".previous\n\t" \
 	".section\t__ex_table,\"a\"\n\t" \
-	STR(PTR)"\t1b,3b\n\t" \
+	".word\t1b,3b\n\t" \
 	".previous" \
 	:"=r" (__gu_err), "=r" (__gu_val) \
-	:"o" (__m(__gu_addr)), "i" (-EFAULT) \
-	:"$1"); })
+	:"o" (__m(__gu_addr)), "i" (-EFAULT)); })
 
 /*
  * Get a long long 64 using 32 bit registers.
@@ -197,20 +173,18 @@
 	"2:\tlw\t%D1,%3\n\t" \
 	"move\t%0,$0\n" \
 	"3:\t.section\t.fixup,\"ax\"\n" \
-	"4:\t.set\tnoat\n\t" \
-	"la\t$1,3b\n\t" \
-	"li\t%0,%4\n\t" \
-	"jr\t$1\n\t" \
-	".set\tat\n\t" \
+	"4:\tli\t%0,%4\n\t" \
+	"move\t%1,$0\n\t" \
+	"move\t%D1,$0\n\t" \
+	"j\t3b\n\t" \
 	".previous\n\t" \
 	".section\t__ex_table,\"a\"\n\t" \
-	STR(PTR)"\t1b,4b\n\t" \
-	STR(PTR)"\t2b,4b\n\t" \
+	".word\t1b,4b\n\t" \
+	".word\t2b,4b\n\t" \
 	".previous" \
 	:"=r" (__gu_err), "=&r" (__gu_val) \
 	:"o" (__m(__gu_addr)), "o" (__m(__gu_addr + 4)), \
-	 "i" (-EFAULT) \
-	:"$1"); })
+	 "i" (-EFAULT)); })
 
 extern void __get_user_unknown(void);
 
@@ -262,18 +236,14 @@
 	"move\t%0,$0\n" \
 	"2:\n\t" \
 	".section\t.fixup,\"ax\"\n" \
-	"3:\t.set\tnoat\n\t" \
-	"la\t$1,2b\n\t" \
-	"li\t%0,%3\n\t" \
-	"jr\t$1\n\t" \
-	".set\tat\n\t" \
+	"3:\tli\t%0,%3\n\t" \
+	"j\t2b\n\t" \
 	".previous\n\t" \
 	".section\t__ex_table,\"a\"\n\t" \
-	STR(PTR)"\t1b,3b\n\t" \
+	".word\t1b,3b\n\t" \
 	".previous" \
 	:"=r" (__pu_err) \
-	:"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT) \
-	:"$1"); })
+	:"r" (__pu_val), "o" (__m(__pu_addr)), "i" (-EFAULT)); })
 
 #define __put_user_asm_ll32 \
 ({ \
@@ -283,20 +253,16 @@
 	"move\t%0,$0\n" \
 	"3:\n\t" \
 	".section\t.fixup,\"ax\"\n" \
-	"4:\t.set\tnoat\n\t" \
-	"la\t$1,3b\n\t" \
-	"li\t%0,%4\n\t" \
-	"jr\t$1\n\t" \
-	".set\tat\n\t" \
+	"4:\tli\t%0,%4\n\t" \
+	"j\t3b\n\t" \
 	".previous\n\t" \
 	".section\t__ex_table,\"a\"\n\t" \
-	STR(PTR)"\t1b,4b\n\t" \
-	STR(PTR)"\t2b,4b\n\t" \
+	".word\t1b,4b\n\t" \
+	".word\t2b,4b\n\t" \
 	".previous" \
 	:"=r" (__pu_err) \
 	:"r" (__pu_val), "o" (__m(__pu_addr)), "o" (__m(__pu_addr + 4)), \
-	 "i" (-EFAULT) \
-	:"$1"); })
+	 "i" (-EFAULT)); })
 
 extern void __put_user_unknown(void);
 
@@ -310,62 +276,195 @@
         return retval; \
 })
 
-#define __copy_to_user(to,from,n)                       \
-         __copy_user((to),(from),(n))
+extern size_t __copy_user(void *__to, const void *__from, size_t __n);
 
-#define __copy_from_user(to,from,n)                     \
-         __copy_user((to),(from),(n))
+#define __copy_to_user(to,from,n) ({ \
+	void *__cu_to; \
+	const void *__cu_from; \
+	long __cu_len; \
+	\
+	__cu_to = (to); \
+	__cu_from = (from); \
+	__cu_len = (n); \
+	__asm__ __volatile__( \
+		"move\t$4, %1\n\t" \
+		"move\t$5, %2\n\t" \
+		"move\t$6, %3\n\t" \
+		"jal\t__copy_user\n\t" \
+		"move\t%0, $6" \
+		: "=r" (__cu_len) \
+		: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+		: "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \
+		  "$24", "$31","memory"); \
+	__cu_len; \
+})
 
-#define __clear_user(addr,size) \
-({ \
-	void *__cu_end; \
+#define __copy_from_user(to,from,n) ({ \
+	void *__cu_to; \
+	const void *__cu_from; \
+	long __cu_len; \
+	\
+	__cu_to = (to); \
+	__cu_from = (from); \
+	__cu_len = (n); \
 	__asm__ __volatile__( \
-		".set\tnoreorder\n\t" \
-		"1:\taddiu\t%0,1\n" \
-		"bne\t%0,%1,1b\n\t" \
-		"sb\t$0,-1(%0)\n\t" \
-		"2:\t.set\treorder\n\t" \
-		".section\t.fixup,\"ax\"\n" \
-		"3:\t.set\tnoat\n\t" \
-		"subu\t%0,1\n\t" \
-		"j\t2b\n\t" \
+		"move\t$4, %1\n\t" \
+		"move\t$5, %2\n\t" \
+		"move\t$6, %3\n\t" \
+		".set\tnoat\n\t" \
+		"addu\t$1, %2, %3\n\t" \
 		".set\tat\n\t" \
-		".previous\n\t" \
-		".section\t__ex_table,\"a\"\n\t" \
-		STR(PTR)"\t1b,3b\n\t" \
-		".previous" \
-		:"=r" (addr), "=r" (__cu_end) \
-		:"0" (addr), "1" (addr + size), "i" (-EFAULT) \
-		:"$1","memory"); \
-		size = __cu_end - (addr); \
+		"jal\t__copy_user\n\t" \
+		"move\t%0, $6" \
+		: "=r" (__cu_len) \
+		: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+		: "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", "$15", \
+		  "$24", "$31","memory"); \
+	__cu_len; \
 })
 
+#define copy_to_user(to,from,n) ({ \
+	void *__cu_to; \
+	const void *__cu_from; \
+	long __cu_len; \
+	\
+	__cu_to = (to); \
+	__cu_from = (from); \
+	__cu_len = (n); \
+	if (access_ok(VERIFY_WRITE, __cu_to, __cu_len)) \
+		__asm__ __volatile__( \
+			"move\t$4, %1\n\t" \
+			"move\t$5, %2\n\t" \
+			"move\t$6, %3\n\t" \
+			"jal\t__copy_user\n\t" \
+			"move\t%0, $6" \
+			: "=r" (__cu_len) \
+			: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+			: "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \
+			  "$15", "$24", "$31","memory"); \
+	__cu_len; \
+})
+
+#define copy_from_user(to,from,n) ({ \
+	void *__cu_to; \
+	const void *__cu_from; \
+	long __cu_len; \
+	\
+	__cu_to = (to); \
+	__cu_from = (from); \
+	__cu_len = (n); \
+	if (access_ok(VERIFY_READ, __cu_from, __cu_len)) \
+		__asm__ __volatile__( \
+			"move\t$4, %1\n\t" \
+			"move\t$5, %2\n\t" \
+			"move\t$6, %3\n\t" \
+			".set\tnoat\n\t" \
+			"addu\t$1, %2, %3\n\t" \
+			".set\tat\n\t" \
+			"jal\t__copy_user\n\t" \
+			"move\t%0, $6" \
+			: "=r" (__cu_len) \
+			: "r" (__cu_to), "r" (__cu_from), "r" (__cu_len) \
+			: "$4", "$5", "$6", "$8", "$9", "$10", "$11", "$12", \
+			  "$15", "$24", "$31","memory"); \
+	__cu_len; \
+})
+
+extern inline __kernel_size_t
+__clear_user(void *addr, __kernel_size_t size)
+{
+	__kernel_size_t res;
+
+	__asm__ __volatile__(
+		"move\t$4, %1\n\t"
+		"move\t$5, $0\n\t"
+		"move\t$6, %2\n\t"
+		"jal\t__bzero\n\t"
+		"move\t%0, $6"
+		: "=r" (res)
+		: "r" (addr), "r" (size)
+		: "$4", "$5", "$6", "$8", "$9", "$31");
+
+	return res;
+}
+
 #define clear_user(addr,n) ({ \
 void * __cl_addr = (addr); \
 unsigned long __cl_size = (n); \
 if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
-__clear_user(__cl_addr, __cl_size); \
+__cl_size = __clear_user(__cl_addr, __cl_size); \
 __cl_size; })
 
 /*
  * Returns: -EFAULT if exception before terminator, N if the entire
  * buffer filled, else strlen.
  */
-extern long __strncpy_from_user(char *__to, const char *__from, long __to_len);
+extern inline long
+__strncpy_from_user(char *__to, const char *__from, long __len)
+{
+	long res;
+
+	__asm__ __volatile__(
+		"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"
+		"move\t%0, $2"
+		: "=r" (res)
+		: "r" (__to), "r" (__from), "r" (__len)
+		: "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
+
+	return res;
+}
+
+extern inline long
+strncpy_from_user(char *__to, const char *__from, long __len)
+{
+	long res;
+
+	__asm__ __volatile__(
+		"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"
+		"move\t%0, $2"
+		: "=r" (res)
+		: "r" (__to), "r" (__from), "r" (__len)
+		: "$2", "$3", "$4", "$5", "$6", "$8", "$31", "memory");
+
+	return res;
+}
 
-#define strncpy_from_user(dest,src,count) ({                            \
-	const void * __sc_src = (src);                                  \
-	long __sc_res = -EFAULT;                                        \
-	if (access_ok(VERIFY_READ, __sc_src, 0)) {                      \
-		__sc_res = __strncpy_from_user(dest, __sc_src, count);  \
-} __sc_res; })
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
-extern long __strlen_user(const char *);
+extern inline long __strlen_user(const char *s)
+{
+	long res;
+
+	__asm__ __volatile__(
+		"move\t$4, %1\n\t"
+		"jal\t__strlen_user_nocheck_asm\n\t"
+		"move\t%0, $2"
+		: "=r" (res)
+		: "r" (s)
+		: "$2", "$4", "$8", "$31");
 
-extern inline long strlen_user(const char *str)
+	return res;
+}
+
+extern inline long strlen_user(const char *s)
 {
-	return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0;
+	long res;
+
+	__asm__ __volatile__(
+		"move\t$4, %1\n\t"
+		"jal\t__strlen_user_asm\n\t"
+		"move\t%0, $2"
+		: "=r" (res)
+		: "r" (s)
+		: "$2", "$4", "$8", "$31");
+
+	return res;
 }
 
 struct exception_table_entry
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/ucontext.h linux/include/asm-mips/ucontext.h
--- v2.1.100/linux/include/asm-mips/ucontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/ucontext.h	Fri May  8 00:13:26 1998
@@ -0,0 +1,12 @@
+#ifndef __ASM_MIPS_UCONTEXT_H
+#define __ASM_MIPS_UCONTEXT_H
+
+struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	struct sigcontext uc_mcontext;
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+#endif /* __ASM_MIPS_UCONTEXT_H */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- v2.1.100/linux/include/asm-mips/unistd.h	Wed Apr  8 19:36:29 1998
+++ linux/include/asm-mips/unistd.h	Fri May  8 00:13:26 1998
@@ -1003,7 +1003,7 @@
 #define __NR_time			(__NR_Linux +  13)
 #define __NR_mknod			(__NR_Linux +  14)
 #define __NR_chmod			(__NR_Linux +  15)
-#define __NR_chown			(__NR_Linux +  16)
+#define __NR_lchown			(__NR_Linux +  16)
 #define __NR_break			(__NR_Linux +  17)
 #define __NR_oldstat			(__NR_Linux +  18)
 #define __NR_lseek			(__NR_Linux +  19)
@@ -1180,11 +1180,21 @@
 #define __NR_setresgid			(__NR_Linux + 190)
 #define __NR_getresgid			(__NR_Linux + 191)
 #define __NR_prctl			(__NR_Linux + 192)
+#define __NR_rt_sigreturn		(__NR_Linux + 193)
+#define __NR_rt_sigaction		(__NR_Linux + 194)
+#define __NR_rt_sigprocmask		(__NR_Linux + 195)
+#define __NR_rt_sigpending		(__NR_Linux + 196)
+#define __NR_rt_sigtimedwait		(__NR_Linux + 197)
+#define __NR_rt_sigqueueinfo		(__NR_Linux + 198)
+#define __NR_rt_sigsuspend		(__NR_Linux + 199)
+#define __NR_pread			(__NR_Linux + 200)
+#define __NR_pwrite			(__NR_Linux + 201)
+#define __NR_chown			(__NR_Linux + 202)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		192
+#define __NR_Linux_syscalls		202
 
 #ifndef __LANGUAGE_ASSEMBLY__
 
@@ -1197,7 +1207,8 @@
 __asm__ volatile ("li\t$2,%2\n\t" \
 		  "syscall" \
                   : "=r" (__res), "=r" (__err) \
-                  : "i" (__NR_##name)); \
+                  : "i" (__NR_##name) \
+                  : "$8","$9","$10","$11","$12","$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1218,7 +1229,7 @@
                   "syscall" \
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)) \
-                  : "$4"); \
+                  : "$4","$8","$9","$10","$11","$12","$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1237,7 +1248,8 @@
                   : "=r" (__res), "=r" (__err) \
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)) \
-                  : "$4","$5"); \
+                  : "$4","$5","$8","$9","$10","$11","$12","$13","$14","$15", \
+                    "$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1258,7 +1270,8 @@
                   : "i" (__NR_##name),"r" ((long)(a)), \
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)) \
-                  : "$4","$5","$6"); \
+                  : "$4","$5","$6","$8","$9","$10","$11","$12","$13","$14", \
+                    "$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1281,7 +1294,8 @@
                                       "r" ((long)(b)), \
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)) \
-                  : "$4","$5","$6"); \
+                  : "$4","$5","$6""$8","$9","$10","$11","$12","$13","$14", \
+                    "$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1309,7 +1323,8 @@
                                       "r" ((long)(c)), \
                                       "r" ((long)(d)), \
                                       "m" ((long)(e)) \
-                  : "$2","$4","$5","$6","$7"); \
+                  : "$2","$4","$5","$6","$7","$8","$9","$10","$11","$12", \
+                    "$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1340,7 +1355,8 @@
                                       "r" ((long)(d)), \
                                       "m" ((long)(e)), \
                                       "m" ((long)(f)) \
-                  : "$2","$3","$4","$5","$6","$7"); \
+                  : "$2","$3","$4","$5","$6","$7","$8","$9","$10","$11", \
+                    "$12","$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1374,7 +1390,8 @@
                                       "m" ((long)(e)), \
                                       "m" ((long)(f)), \
                                       "m" ((long)(g)) \
-                  : "$2","$3","$4","$5","$6","$7"); \
+                  : "$2","$3","$4","$5","$6","$7","$8","$9","$10","$11", \
+                    "$12","$13","$14","$15","$24"); \
 if (__err == 0) \
 	return (type) __res; \
 errno = __res; \
@@ -1397,6 +1414,8 @@
  */
 #define __NR__exit __NR_exit
 static inline _syscall0(int,idle)
+static inline _syscall0(int,fork)
+static inline _syscall2(int,clone,unsigned long,flags,char *,esp)
 static inline _syscall0(int,pause)
 static inline _syscall1(int,setup,int,magic)
 static inline _syscall0(int,sync)
@@ -1429,11 +1448,11 @@
 
 	__asm__ __volatile__(
 		".set\tnoreorder\n\t"
-		"move\t$8,$sp\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$8,$sp,1f\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 */
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/watch.h linux/include/asm-mips/watch.h
--- v2.1.100/linux/include/asm-mips/watch.h	Wed Dec 10 10:31:11 1997
+++ linux/include/asm-mips/watch.h	Fri May  8 00:13:26 1998
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: watch.h,v 1.2 1997/09/19 08:37:44 ralf Exp $
+ * $Id: watch.h,v 1.3 1998/05/01 01:36:18 ralf Exp $
  */
 #ifndef __ASM_WATCH_H
 #define __ASM_WATCH_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-mips/xstat.h linux/include/asm-mips/xstat.h
--- v2.1.100/linux/include/asm-mips/xstat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/xstat.h	Fri May  8 00:13:26 1998
@@ -0,0 +1,35 @@
+/* $Id: xstat.h,v 1.1 1998/02/06 12:51:41 jj Exp $
+ * xstat.h: sys_xstat/xmknod architecture dependent stuff.
+ *
+ * Copyright (C) 1998  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
+ */
+ 
+extern __inline__ int cp_xstat(struct inode *inode, struct stat64 *s, unsigned long blocks, int blksize)
+{
+	struct stat64 tmp;
+	memset (&tmp, 0, sizeof(tmp));
+	tmp.st_dev = (((__u64)MAJOR(inode->i_dev)) << 32) | MINOR(inode->i_dev);
+	tmp.st_ino = inode->i_ino;
+	tmp.st_mode = inode->i_mode;
+	tmp.st_nlink = inode->i_nlink;
+	tmp.st_uid = inode->i_uid;
+	tmp.st_gid = inode->i_gid;
+	tmp.st_rdev = (((__u64)MAJOR(inode->i_rdev)) << 32) | MINOR(inode->i_rdev);
+	tmp.st_size = inode->i_size;
+	tmp.st_atim.tv_sec = inode->i_atime;
+	tmp.st_mtim.tv_sec = inode->i_mtime;
+	tmp.st_ctim.tv_sec = inode->i_ctime;
+	tmp.st_blksize = blksize;
+	tmp.st_blocks = blocks;
+	/* Should I check if all fs names are < 16? All in the kernel tree are */
+	if (inode->i_sb)
+		strcpy(tmp.st_fstype, inode->i_sb->s_type->name);
+	return copy_to_user(s,&tmp,sizeof(tmp));
+}
+
+extern __inline__ int get_user_new_dev_t(kdev_t *kdev, __new_dev_t *udev) {
+	__new_dev_t ndev;
+	if (copy_from_user (&ndev, udev, sizeof(__new_dev_t))) return -EFAULT;
+	*kdev = MKDEV((ndev >> 32), (__u32)ndev);
+	return 0;
+}
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h
--- v2.1.100/linux/include/asm-ppc/byteorder.h	Fri Dec  5 12:47:08 1997
+++ linux/include/asm-ppc/byteorder.h	Fri May  8 00:18:23 1998
@@ -31,6 +31,10 @@
 	asm volatile("stwbrx %0,0,%1" : : "r" (val), "r" (addr) : "memory");
 }
 
+/* alas, egcs sounds like it has a bug in this code that doesn't use the
+   inline asm correctly, and can cause file corruption. Until I hear that
+   it's fixed, I can live without the extra speed. I hope. */
+#if !(__GNUC__ >= 2 && __GNUC_MINOR__ >= 90)
 #if 0
 #  define __arch_swab16(x) ld_le16(&x)
 #  define __arch_swab32(x) ld_le32(&x)
@@ -59,6 +63,8 @@
 #define __arch__swab32(x) ___arch__swab32(x)
 #define __arch__swab16(x) ___arch__swab16(x)
 #endif /* 0 */
+
+#endif
 
 /* The same, but returns converted value from the location pointer by addr. */
 #define __arch__swab16p(addr) ld_le16(addr)
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/cuda.h linux/include/asm-ppc/cuda.h
--- v2.1.100/linux/include/asm-ppc/cuda.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/cuda.h	Fri May  8 00:18:23 1998
@@ -37,6 +37,7 @@
 
 #ifdef __KERNEL__
 
+void find_via_cuda(void);
 void via_cuda_init(void);
 int cuda_request(struct adb_request *req,
 		 void (*done)(struct adb_request *), int nbytes, ...);
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/init.h linux/include/asm-ppc/init.h
--- v2.1.100/linux/include/asm-ppc/init.h	Thu Jul 31 13:09:18 1997
+++ linux/include/asm-ppc/init.h	Fri May  8 00:18:23 1998
@@ -1,23 +1,56 @@
 #ifndef _PPC_INIT_H
 #define _PPC_INIT_H
 
-#define __init
-#define __initdata
-#define __initfunc(x) x
-/*
+#if __GNUC__ > 2 || __GNUC_MINOR__ >= 90 /* egcs */
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
 #define __initfunc(__arginit) \
 	__arginit __init; \
 	__arginit
-*/
-	/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-/*	
+
+#define __pmac __attribute__ ((__section__ (".text.pmac")))
+#define __pmacdata __attribute__ ((__section__ (".data.pmac")))
+#define __pmacfunc(__argpmac) \
+	__argpmac __pmac; \
+	__argpmac
+	
+#define __prep __attribute__ ((__section__ (".text.prep")))
+#define __prepdata __attribute__ ((__section__ (".data.prep")))
+#define __prepfunc(__argprep) \
+	__argprep __prep; \
+	__argprep
+
+/* this is actually just common chrp/pmac code, not OF code -- Cort */
+#define __openfirmware __attribute__ ((__section__ (".text.openfirmware")))
+#define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware")))
+#define __openfirmwarefunc(__argopenfirmware) \
+	__argopenfirmware __openfirmware; \
+	__argopenfirmware
+	
 #define __INIT		.section	".text.init",#alloc,#execinstr
 #define __FINIT	.previous
 #define __INITDATA	.section	".data.init",#alloc,#write
-*/
+
+#else /* not egcs */
+
+#define __init
+#define __initdata
+#define __initfunc(x) x
+	
+#define __INIT
+#define __FINIT
+#define __INITDATA
+	
+#define __pmac
+#define __pmacdata
+#define __pmacfunc(x) x
+	
+#define __prep
+#define __prepdata
+#define __prepfunc(x) x
+
+#define __openfirmware
+#define __openfirmwaredata
+#define __openfirmwarefunc(x) x
+#endif /* egcs */
 #endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.1.100/linux/include/asm-ppc/irq.h	Sat Apr 25 18:13:12 1998
+++ linux/include/asm-ppc/irq.h	Fri May  8 00:18:23 1998
@@ -3,6 +3,8 @@
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
+#include <asm/processor.h>		/* for is_prep() */
+
 #ifndef CONFIG_8xx
 /*
  * this is the # irq's for all ppc arch's (pmac/chrp/prep)
@@ -18,13 +20,19 @@
 #define irq_to_openpic(n)	((n)-NUM_8259_INTERRUPTS)
 #define IRQ_8259_CASCADE	NUM_8259_INTERRUPTS
 
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+
+/*
+ * This gets called from serial.c, which is now used on
+ * powermacs as well as prep/chrp boxes.
+ * Prep and chrp both have cascaded 8259 PICs.
+ */
 static __inline__ int irq_cannonicalize(int irq)
 {
-	return irq;
+	return (((is_prep || is_chrp) && irq == 2) ? 9 : irq);
 }
 
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
 
 #else /* CONFIG_8xx */
 
@@ -79,6 +87,12 @@
 #define COMM_L_INT	SIU_IRQ6	/* MBX Comm expansion connector pin */
 #define STOP_ABRT_INT	SIU_IRQ7	/* Stop/Abort header pin */
 #endif /* CONFIG_MBX */
+
+/* always the same on MBX -- Cort */
+static __inline__ int irq_cannonicalize(int irq)
+{
+	return irq;
+}
 
 #endif /* CONFIG_8xx */
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h
--- v2.1.100/linux/include/asm-ppc/linux_logo.h	Mon Jan 12 15:18:13 1998
+++ linux/include/asm-ppc/linux_logo.h	Fri May  8 00:18:24 1998
@@ -20,1422 +20,9 @@
 #define LINUX_LOGO_COLORS	221
 
 #ifdef INCLUDE_LINUX_LOGO_DATA
-unsigned char linux_logo_red[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
-  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
-  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
-  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
-  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
-  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
-  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
-  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
-  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
-  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
-  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
-  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
-  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
-  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
-  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
-  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
-  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
 
-unsigned char linux_logo_green[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
-  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
-  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
-  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
-  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
-  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
-  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
-  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
-  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
-  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
-  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
-  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
-  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
-  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
-  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
-  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
-  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo_blue[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
-  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
-  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
-  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
-  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
-  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
-  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
-  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
-  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
-  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
-  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
-  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
-  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
-  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
-  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
-  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
-  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
-  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo[] __initdata = {
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
-  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
-  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
-  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
-  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
-  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
-  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
-  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
-  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
-  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
-  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
-  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
-  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
-  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
-  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
-  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
-  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
-  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
-  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
-  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
-  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
-  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
-  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
-  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
-  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
-  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
-  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
-  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
-  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
-  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
-  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
-  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
-  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
-  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
-  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
-  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
-  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
-  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
-  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
-  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
-  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
-  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
-  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
-  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
-  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
-  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
-  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
-  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
-  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
-  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
-  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
-  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
-  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
-  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
-  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
-  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
-  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
-  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
-  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
-  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
-  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
-  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
-  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
-  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
-  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
-  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
-  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
-  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
-  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
-  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
-  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
-  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
-  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
-  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
-  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
-  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
-  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
-  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
-  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
-  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
-  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
-  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
-  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
-  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
-  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
-  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
-  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
-  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
-  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
-  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
-  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
-  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
-  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
-  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
-  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
-  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
-  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
-  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
-  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
-  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
-  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
-  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
-  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
-  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
-  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
-  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
-  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
-  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
-  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
-  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
-  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
-  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
-  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
-  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
-  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
-  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
-  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
-  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
-  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
-  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
-  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
-  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
-  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
-  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
-  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
-  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
-  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
-  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
-  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
-  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
-  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
-  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
-  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
-  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
-  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
-  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
-  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
-  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
-  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
-  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
-  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
-  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
-  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
-  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
-  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
-  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
-  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
-  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
-  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
-  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
-  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
-  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
-  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
-  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
-  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
-  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
-  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
-  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
-  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
-  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
-  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
-  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
-  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
-  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
-  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
-  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
-  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
-  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
-  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
-  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
-  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
-  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
-  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
-  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
-  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
-  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
-  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
-  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
-  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
-  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
-  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
-  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
-  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
-  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
-  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
-  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
-  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
-  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
-  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
-  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
-  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
-  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
-  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
-  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
-  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
-  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
-  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
-  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
-  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
-  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
-  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
-  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
-  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
-  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
-  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
-  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
-  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
-  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
-  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
-  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
-  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
-  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
-  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
-  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
-  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
-  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
-  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
-  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
-  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
-  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
-  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
-  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
-  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
-  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
-  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
-  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
-  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
-  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
-  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
-  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
-  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
-  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
-  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
-  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
-  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
-  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
-  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
-  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
-  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
-  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
-  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
-  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
-  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
-  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
-  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
-  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
-  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
-  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
-  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
-  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
-  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
-  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
-  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
-  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
-  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
-  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
-  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
-  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
-  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
-  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
-  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
-  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
-  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
-  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
-  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
-  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
-  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
-  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
-  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
-  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
-  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
-  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
-  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
-  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
-  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
-  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
-  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
-  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
-  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
-  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
-  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
-  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
-  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
-  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
-  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
-  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
-  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
-  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
-  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
-  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
-  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
-  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
-  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
-  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
-  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
-  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
-  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
-  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
-  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
-  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
-  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
-  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
-  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
-  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
-  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
-  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
-  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
-  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
-  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
-  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
-  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
-  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
-  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
-  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
-  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
-  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
-  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
-  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
-  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
-  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
-  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
-  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
-  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
-  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
-  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
-  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
-  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
-  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
-  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
-  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
-  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
-  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
-  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
-  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
-  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
-  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
-  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
-  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
-  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
-  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
-  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
-  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
-  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
-  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
-  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
-  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
-  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
-  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
-  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
-  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
-  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
-  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
-  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
-  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
-  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
-  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
-  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
-  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
-  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
-  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
-  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
-  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
-  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
-  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
-  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
-  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
-  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
-  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
-  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
-  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
-  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
-  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
-  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
-  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
-  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
-  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
-  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
-  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
-  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
-  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
-  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
-  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
-  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
-  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
-  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
-  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
-  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
-  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
-  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
-  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
-  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
-  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
-  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
-  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
-  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
-  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
-  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
-  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
-  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
-  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
-  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
-  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
-  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
-  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
-  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
-  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
-  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
-  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
-  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
-  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
-  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
-  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
-  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
-  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
-  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
-  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
-  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
-  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
-  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
-  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
-  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
-  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
-  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
-  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
-  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
-  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
-  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
-  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
-  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
-  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
-  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
-  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
-  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
-  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
-  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
-  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
-  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
-  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
-  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
-  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
-  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
-  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
-  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
-  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
-  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
-  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
-  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
-  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
-  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
-  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
-  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
-  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
-  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
-  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
-  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
-  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
-  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
-  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
-  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
-  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
-  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
-  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
-  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
-  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
-  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
-  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
-  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
-  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
-  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
-  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
-  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
-  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
-  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
-  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
-  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
-  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
-  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
-  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
-  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
-  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
-  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
-  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
-  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
-  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
-  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
-  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
-  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
-  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
-  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
-  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
-  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
-  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
-  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
-  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
-  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
-  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
-  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
-  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
-  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
-  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
-  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
-  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
-  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
-  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
-  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
-  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
-  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
-  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
-  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
-  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
-  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
-  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
-  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
-  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
-  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
-  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
-  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
-  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
-  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
-  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
-  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
-  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
-  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
-  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
-  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
-  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
-  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
-  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
-  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
-  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
-  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
-  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
-  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
-  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
-  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
-  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
-  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
-  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
-  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
-  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
-  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
-  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
-  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
-  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
-  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
-  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
-  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
-  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
-  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
-  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
-  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
-  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
-  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
-  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
-  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
-  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
-  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
-  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
-  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
-  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
-  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
-  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
-  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
-  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
-  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
-  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
-  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
-  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
-  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
-  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
-  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
-  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
-  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
-  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
-  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
-  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
-  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
-  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
-  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
-  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
-  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
-  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
-  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
-  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
-  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
-  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
-  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
-  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
-  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
-  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
-  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
-  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
-  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
-  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
-  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
-  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
-  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
-  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
-  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
-  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
-  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
-  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
-  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
-  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
-  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
-  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
-  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
-  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
-  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
-};
-
-unsigned char linux_logo_bw[] __initdata = {
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
-  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
-  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
-  0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
-  0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
-  0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
-  0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
-  0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
-  0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
-  0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
-  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
-  0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
-  0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
-  0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
-  0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
-  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
-  0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
-  0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
-  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
-  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
-  0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
-  0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
-  0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
-  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
-  0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
-  0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
-  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
-  0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
-  0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
-  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
-  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
-  0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
-  0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
-  0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
-  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
-  0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
-  0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
-  0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
-  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
-  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
-  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
-  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
-  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
-  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
-  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
-  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
-  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
-  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
-  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
-  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
-  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
-  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
-  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
-  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
-  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
-  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 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, 0xFF, 0xFF,
-};
-
-unsigned char linux_logo16_red[] __initdata = {
-    0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x35, 0x83, 0xa5,
-    0x65, 0x8f, 0x98, 0xc9, 0xdb, 0xe1, 0xe7, 0xf8
-};
-
-unsigned char linux_logo16_green[] __initdata = {
-    0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x2e, 0x83, 0xa5,
-    0x65, 0x6e, 0x98, 0x89, 0xbf, 0xac, 0xda, 0xf8
-};
-
-unsigned char linux_logo16_blue[] __initdata = {
-    0x00, 0x90, 0xaf, 0x9c, 0xf7, 0x2b, 0x82, 0xa5,
-    0x65, 0x41, 0x97, 0x1e, 0x60, 0x29, 0xa5, 0xf8
-};
-
-unsigned char linux_logo16[] __initdata = {
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa1, 0x11, 0x11,
-    0x61, 0x16, 0x66, 0x66, 0x11, 0x11, 0x11, 0x11,
-    0x11, 0x11, 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0xa8, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77,
-    0x77, 0x77, 0x73, 0x33, 0x33, 0x3a, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
-    0x77, 0x27, 0x77, 0x77, 0x77, 0x33, 0x3a, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xa3, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x55, 0x50, 0x08, 0x33, 0x77, 0x77,
-    0x77, 0x72, 0x72, 0x27, 0x77, 0x77, 0x33, 0x33,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xa3, 0x33, 0x33, 0x77, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x58, 0x85, 0x00, 0x11, 0x11, 0xaa,
-    0xa3, 0x37, 0x77, 0x72, 0x22, 0x22, 0x77, 0x73,
-    0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3,
-    0x33, 0x37, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x56, 0x85, 0x00, 0x06, 0x66, 0x11,
-    0x11, 0x1a, 0xa3, 0x37, 0x77, 0x72, 0x22, 0x77,
-    0x73, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33,
-    0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x55, 0x00, 0x00, 0x06, 0x66, 0x66,
-    0x66, 0x66, 0x11, 0x1a, 0xa3, 0x77, 0x72, 0x22,
-    0x77, 0x73, 0x3a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33,
-    0x33, 0x33, 0x33, 0xa0, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,
-    0x66, 0x66, 0x66, 0x66, 0x11, 0xa3, 0x77, 0x22,
-    0x22, 0x77, 0x33, 0x33, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33,
-    0x33, 0x3a, 0xa1, 0x10, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x33,
-    0xaa, 0x11, 0x16, 0x66, 0x66, 0x61, 0x1a, 0x37,
-    0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x33,
-    0x3a, 0xa1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x22,
-    0x22, 0x77, 0x3a, 0x11, 0x66, 0x66, 0x66, 0x1a,
-    0x37, 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, 0x3a,
-    0xa1, 0x11, 0x11, 0x10, 0x00, 0x00, 0x50, 0x00,
-    0x00, 0x05, 0x80, 0x50, 0x00, 0x00, 0x07, 0x72,
-    0x22, 0x22, 0x22, 0x73, 0xa1, 0x66, 0x66, 0x61,
-    0x1a, 0x77, 0x22, 0x27, 0x73, 0x33, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x3a, 0xaa,
-    0x11, 0x11, 0x1a, 0xa0, 0x08, 0x71, 0x05, 0x00,
-    0x00, 0x12, 0x22, 0x50, 0x00, 0x00, 0x07, 0x77,
-    0x77, 0x72, 0x22, 0x22, 0x27, 0x31, 0x16, 0x66,
-    0x61, 0x13, 0x77, 0x22, 0x77, 0x33, 0x3a, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xa1,
-    0x11, 0x1a, 0x33, 0x70, 0x07, 0x2e, 0x70, 0x00,
-    0x01, 0x44, 0x42, 0x60, 0x00, 0x00, 0x02, 0x22,
-    0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x31, 0x66,
-    0x66, 0x61, 0xa3, 0x72, 0x22, 0x77, 0x33, 0xaa,
-    0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xaa, 0x11,
-    0x1a, 0x33, 0x77, 0x30, 0x04, 0x82, 0x40, 0x00,
-    0x54, 0x48, 0x54, 0x40, 0x00, 0x00, 0x01, 0xaa,
-    0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31,
-    0x66, 0x66, 0x11, 0x37, 0x22, 0x27, 0x73, 0x3a,
-    0xaa, 0xaa, 0xa3, 0x33, 0x3a, 0xaa, 0xaa, 0xaa,
-    0xa3, 0x77, 0xaa, 0x10, 0x50, 0x08, 0x46, 0x05,
-    0x54, 0x80, 0x50, 0x42, 0x00, 0x00, 0x08, 0x66,
-    0x66, 0x1a, 0x32, 0x22, 0x22, 0x22, 0x22, 0x27,
-    0x31, 0x66, 0x66, 0x13, 0x72, 0x22, 0x77, 0x33,
-    0xaa, 0xaa, 0xaa, 0x33, 0xaa, 0xa1, 0xaa, 0xa3,
-    0x37, 0xa1, 0x1a, 0x30, 0x50, 0x06, 0x26, 0x00,
-    0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0xe2,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, 0x22,
-    0x27, 0xa6, 0x66, 0x61, 0xa7, 0x72, 0x27, 0x73,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33,
-    0x31, 0x11, 0x37, 0x70, 0x02, 0x00, 0xab, 0xbb,
-    0xb6, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xee, 0xee,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22,
-    0x22, 0x23, 0x16, 0x66, 0x1a, 0x37, 0x22, 0x77,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x3a,
-    0x11, 0xa7, 0x33, 0x10, 0x04, 0x09, 0xbd, 0xdd,
-    0xbd, 0xd0, 0x04, 0x45, 0x00, 0x0e, 0xee, 0xee,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22,
-    0x22, 0x22, 0x71, 0x66, 0x66, 0x13, 0x72, 0x27,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x11,
-    0xa3, 0x73, 0xa1, 0x60, 0x08, 0xbd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdb, 0x90, 0x00, 0x02, 0xec, 0xee,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0x22,
-    0x22, 0x22, 0x27, 0xa6, 0x66, 0x61, 0x37, 0x27,
-    0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x1a,
-    0x33, 0xa1, 0x16, 0x60, 0x0b, 0xbd, 0xdd, 0xdd,
-    0xcd, 0xdd, 0xdd, 0xd9, 0x00, 0x00, 0xec, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xa2,
-    0x22, 0x22, 0x22, 0x7a, 0x66, 0x66, 0x13, 0x77,
-    0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x11, 0x33,
-    0xaa, 0x11, 0x66, 0x60, 0x9b, 0xdd, 0xdd, 0xdd,
-    0xcd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0xec, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x61,
-    0x72, 0x22, 0x22, 0x22, 0xa1, 0x66, 0x61, 0x37,
-    0x1a, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x13, 0x3a,
-    0x11, 0x11, 0x11, 0x10, 0x5b, 0xdd, 0xdd, 0xdc,
-    0xdd, 0xdd, 0xbd, 0xd9, 0x00, 0x00, 0xec, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x86,
-    0x17, 0x22, 0x22, 0x22, 0x23, 0x16, 0x66, 0xaa,
-    0xaa, 0xa3, 0x3a, 0xaa, 0xaa, 0x1a, 0x3a, 0xa1,
-    0x11, 0x11, 0x1a, 0x70, 0x05, 0xbd, 0xdd, 0xdd,
-    0xdb, 0x5b, 0xdd, 0xb0, 0x00, 0x60, 0x2e, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe6, 0x88,
-    0x66, 0x32, 0x22, 0x22, 0x22, 0x36, 0x66, 0x11,
-    0x33, 0x33, 0x3a, 0xaa, 0x11, 0xaa, 0xaa, 0xa1,
-    0x11, 0x1a, 0x3a, 0x60, 0x02, 0x99, 0xbb, 0xb9,
-    0x9b, 0xbb, 0xbc, 0x22, 0x00, 0x86, 0x5e, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe1, 0x68,
-    0x86, 0x63, 0x22, 0x22, 0x22, 0x2a, 0x66, 0x66,
-    0x33, 0x33, 0xaa, 0xaa, 0x1a, 0xaa, 0xaa, 0x11,
-    0x1a, 0xa7, 0x68, 0x80, 0x02, 0x2b, 0xbd, 0xbb,
-    0xbb, 0xb9, 0x22, 0x22, 0x00, 0x06, 0x6e, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0xa6,
-    0x88, 0x86, 0x32, 0x22, 0x22, 0x27, 0xa6, 0x66,
-    0x33, 0x3a, 0xaa, 0xa1, 0xaa, 0xaa, 0xa1, 0x11,
-    0xa3, 0xa6, 0x88, 0x80, 0x02, 0x22, 0x9b, 0xbb,
-    0xbb, 0x22, 0x24, 0xf4, 0x60, 0x00, 0x0c, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc2, 0x21,
-    0x68, 0x88, 0x63, 0x22, 0x22, 0x22, 0x71, 0x66,
-    0x33, 0x3a, 0x11, 0x11, 0xaa, 0xaa, 0x11, 0xaa,
-    0x71, 0x88, 0x88, 0x00, 0x02, 0xe2, 0x26, 0x99,
-    0x22, 0x22, 0x4f, 0xf4, 0x40, 0x00, 0x0c, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x22, 0x22,
-    0x16, 0x88, 0x86, 0xa2, 0x22, 0x22, 0x27, 0x11,
-    0x33, 0xa1, 0x11, 0x11, 0xaa, 0x31, 0x1a, 0xa3,
-    0x68, 0x88, 0x81, 0x00, 0x54, 0x42, 0x22, 0x22,
-    0x22, 0x44, 0xff, 0xff, 0x48, 0x00, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x22,
-    0x21, 0x88, 0x88, 0x6a, 0x22, 0x22, 0x22, 0x31,
-    0x3a, 0xa1, 0x11, 0x1a, 0xa3, 0x11, 0x33, 0x36,
-    0x88, 0x86, 0x30, 0x00, 0x4f, 0x44, 0x22, 0x22,
-    0x24, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x95, 0x22, 0x72,
-    0x22, 0x18, 0x88, 0x86, 0x32, 0x22, 0x22, 0x27,
-    0xaa, 0x11, 0x11, 0x1a, 0x31, 0x13, 0x33, 0x68,
-    0x88, 0x6a, 0x00, 0x02, 0x4f, 0x4f, 0x42, 0x24,
-    0x4f, 0xff, 0xff, 0xff, 0xf4, 0x50, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x73,
-    0x72, 0x26, 0x88, 0x88, 0x63, 0x22, 0x22, 0x22,
-    0x11, 0x11, 0x11, 0xa3, 0xa1, 0x73, 0xa6, 0x88,
-    0x81, 0xa5, 0x00, 0x04, 0x4f, 0x4f, 0x44, 0x4f,
-    0xff, 0xff, 0xff, 0xff, 0xf4, 0x40, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x12, 0x27,
-    0xaa, 0x22, 0x68, 0x55, 0x86, 0x72, 0x22, 0x22,
-    0x11, 0x11, 0x1a, 0x33, 0x13, 0x3a, 0x18, 0x88,
-    0x1a, 0x10, 0x00, 0x44, 0x4f, 0x4f, 0xff, 0x4f,
-    0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x61, 0x22,
-    0x3a, 0xa2, 0x26, 0x85, 0x58, 0x67, 0x22, 0x22,
-    0x61, 0x61, 0x1a, 0x7a, 0x37, 0x31, 0x88, 0x81,
-    0x11, 0x00, 0x05, 0xe4, 0x44, 0xff, 0xff, 0xff,
-    0x4f, 0xf4, 0x44, 0xff, 0xff, 0xf5, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x12,
-    0x2a, 0xaa, 0x72, 0x68, 0x55, 0x81, 0x22, 0x22,
-    0x66, 0x61, 0xa3, 0x33, 0x73, 0x16, 0x88, 0x11,
-    0x10, 0x00, 0x08, 0x74, 0x44, 0x4f, 0x44, 0x44,
-    0xf4, 0xf4, 0x44, 0x44, 0xe2, 0x44, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x81,
-    0x22, 0xaa, 0xa7, 0x26, 0x85, 0x88, 0x12, 0x22,
-    0x66, 0x61, 0x37, 0xa7, 0x3a, 0x66, 0x66, 0x11,
-    0x80, 0x00, 0x0a, 0x72, 0x44, 0x4f, 0x44, 0x4f,
-    0xff, 0x44, 0x44, 0x22, 0x22, 0x24, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x85, 0x88,
-    0x12, 0x2a, 0xaa, 0x22, 0x68, 0x58, 0x63, 0x22,
-    0x66, 0x1a, 0x73, 0x77, 0x31, 0x66, 0x61, 0x11,
-    0x00, 0x00, 0x07, 0x44, 0xff, 0x4f, 0xf4, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0x42, 0x22, 0x40, 0x9b,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x85, 0x55,
-    0x81, 0x27, 0xaa, 0xa2, 0x78, 0x88, 0x86, 0x72,
-    0x66, 0x13, 0x77, 0x73, 0x11, 0x66, 0x61, 0x76,
-    0x00, 0x50, 0x84, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x42, 0x40, 0x9b,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x68, 0x55,
-    0x58, 0x12, 0x3a, 0xaa, 0x23, 0x88, 0x88, 0xa7,
-    0x66, 0xa7, 0x77, 0x7a, 0x16, 0x66, 0x1a, 0x15,
-    0x05, 0x00, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0x24, 0x9b,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x26, 0x55,
-    0x55, 0x81, 0x23, 0xaa, 0x32, 0x18, 0x88, 0x6a,
-    0x61, 0x37, 0x77, 0x31, 0x66, 0x66, 0x17, 0x60,
-    0x05, 0x08, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4e, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0xa2, 0x65,
-    0x55, 0x58, 0xa2, 0x7a, 0xa2, 0x26, 0x88, 0x61,
-    0x61, 0x32, 0x27, 0xa1, 0x66, 0x61, 0x31, 0x60,
-    0x00, 0x04, 0x4f, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x9b, 0xaa, 0x26,
-    0x55, 0x55, 0x87, 0x27, 0x33, 0x27, 0x68, 0x61,
-    0x1a, 0x72, 0x27, 0xa6, 0x66, 0x6a, 0x71, 0x00,
-    0x80, 0x84, 0xff, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99,
-    0x9b, 0x9b, 0x99, 0xb9, 0xb9, 0x99, 0xaa, 0xa2,
-    0x85, 0x55, 0x56, 0x22, 0x27, 0x22, 0x36, 0x66,
-    0x13, 0x22, 0x23, 0x16, 0x86, 0x63, 0x73, 0x00,
-    0x00, 0x44, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4f, 0x99,
-    0x9b, 0x99, 0x99, 0x99, 0xb9, 0x99, 0xaa, 0xaa,
-    0x28, 0x55, 0x58, 0x12, 0x22, 0x22, 0x21, 0x11,
-    0xa3, 0x27, 0x7a, 0x66, 0x86, 0x17, 0x75, 0x05,
-    0x05, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x44, 0x4f, 0x99,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3a, 0xaa,
-    0xa2, 0x85, 0x58, 0x67, 0x72, 0x22, 0x27, 0xa1,
-    0x37, 0x27, 0x7a, 0x68, 0x86, 0xa2, 0x70, 0x00,
-    0x02, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xf4, 0x99,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x23, 0xaa,
-    0xa7, 0x78, 0x88, 0x81, 0x77, 0x22, 0x27, 0x3a,
-    0x72, 0x73, 0x71, 0x68, 0x66, 0x32, 0x50, 0x00,
-    0x04, 0x4f, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x95,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x55, 0x12, 0x3a,
-    0xaa, 0x21, 0x88, 0x81, 0x77, 0x27, 0x73, 0x73,
-    0x72, 0x33, 0x36, 0x86, 0x61, 0x72, 0x00, 0x00,
-    0x04, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0x55,
-    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x27,
-    0xaa, 0x77, 0x68, 0x61, 0x23, 0x71, 0x11, 0x3a,
-    0x27, 0xa3, 0x36, 0x86, 0x61, 0x20, 0x00, 0x00,
-    0x04, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x59,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x95, 0x58, 0x77,
-    0x27, 0x32, 0x36, 0x63, 0x23, 0x71, 0x66, 0x11,
-    0x27, 0x13, 0xa6, 0x86, 0x6a, 0x20, 0x00, 0x50,
-    0x04, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x99,
-    0x9b, 0xbb, 0xbb, 0xbb, 0xb9, 0x99, 0x68, 0x13,
-    0x32, 0x22, 0x73, 0xa7, 0x2a, 0x31, 0x88, 0x66,
-    0x7a, 0x13, 0x18, 0x66, 0x63, 0x20, 0x00, 0x06,
-    0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x49, 0x95,
-    0xa9, 0xa9, 0x99, 0x97, 0x92, 0x99, 0x65, 0x6a,
-    0x17, 0x22, 0x23, 0x72, 0x27, 0xaa, 0x88, 0x88,
-    0xa1, 0x17, 0x68, 0x66, 0x67, 0x70, 0x00, 0x05,
-    0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x49, 0x9c,
-    0x2e, 0xee, 0xee, 0xee, 0xee, 0xa9, 0x65, 0x8a,
-    0x1a, 0xaa, 0x37, 0x72, 0x27, 0x37, 0x88, 0x88,
-    0x11, 0x17, 0x68, 0x66, 0x67, 0x10, 0x9d, 0xd0,
-    0x84, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0xf4, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x4f, 0x69,
-    0xcc, 0xee, 0xee, 0xee, 0xec, 0x99, 0x88, 0x63,
-    0x61, 0x68, 0x61, 0x72, 0x22, 0x7a, 0x68, 0x88,
-    0x11, 0x17, 0x88, 0x66, 0x12, 0x1b, 0xdd, 0xdd,
-    0x02, 0x44, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0xff, 0x4f, 0x4c, 0xc5,
-    0x0c, 0xc1, 0x11, 0x1c, 0xc0, 0x26, 0x66, 0x17,
-    0x66, 0x88, 0x88, 0x12, 0x22, 0x23, 0xa8, 0x88,
-    0x11, 0x13, 0x88, 0x66, 0x17, 0xbb, 0xdd, 0xdd,
-    0xd0, 0x8f, 0xff, 0xf4, 0xf4, 0x44, 0xf4, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0x4f, 0x44, 0xdd, 0xdd,
-    0x00, 0x00, 0x00, 0x05, 0x9d, 0x21, 0x66, 0x27,
-    0xa6, 0x65, 0x58, 0x67, 0x22, 0x27, 0x28, 0x88,
-    0x11, 0xaa, 0x86, 0x68, 0x1a, 0xbb, 0xdd, 0xdd,
-    0xdb, 0x05, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xdd, 0xdb,
-    0x00, 0x00, 0x00, 0x00, 0xdd, 0xda, 0x66, 0x22,
-    0x71, 0x15, 0x55, 0x81, 0x22, 0x22, 0x76, 0x88,
-    0x11, 0x31, 0x88, 0x88, 0xab, 0xbd, 0xdd, 0xdd,
-    0xdd, 0x00, 0x04, 0x44, 0xff, 0xff, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0x44, 0xdd, 0xdb,
-    0x00, 0x00, 0x00, 0x0b, 0xdd, 0xda, 0x11, 0x22,
-    0x23, 0x68, 0x55, 0x86, 0x22, 0x22, 0x7a, 0x88,
-    0x1a, 0x71, 0x88, 0x89, 0xbb, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xd0, 0x00, 0x4f, 0x44, 0xff, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xff, 0xe2, 0xdd, 0xdb,
-    0x90, 0x00, 0x05, 0xbd, 0xdd, 0xb8, 0x63, 0x22,
-    0x27, 0xa6, 0x55, 0x88, 0x77, 0x22, 0x22, 0x88,
-    0x1a, 0x28, 0xbd, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdb, 0x00, 0x07, 0x44, 0x4f, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x22, 0xdd, 0xdb,
-    0xbb, 0x9b, 0xbb, 0xbd, 0xdd, 0xd5, 0x86, 0x22,
-    0x22, 0x77, 0x85, 0x88, 0x17, 0x22, 0x22, 0x88,
-    0xaa, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0x00, 0x00, 0x54, 0x4f, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0x44, 0x22, 0xbd, 0xdd,
-    0xbb, 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0x88, 0x72,
-    0x27, 0x22, 0x88, 0x88, 0x67, 0x72, 0x22, 0x18,
-    0x33, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xd0, 0x00, 0x05, 0x4f, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0x44, 0x4f, 0x22, 0xbd, 0xdd,
-    0xdb, 0xbb, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x17,
-    0x27, 0x72, 0x68, 0x88, 0x87, 0x32, 0x22, 0x36,
-    0x37, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xd5, 0x00, 0x00, 0x4f, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0xf4, 0xf4, 0x22, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x67,
-    0x72, 0x77, 0x38, 0x88, 0x83, 0x37, 0x22, 0x26,
-    0x72, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x4f, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0xf4, 0x44, 0x25, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd3,
-    0x32, 0x73, 0x76, 0x88, 0x81, 0x33, 0x22, 0x2a,
-    0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xb0, 0x54, 0x4f, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0xff, 0x44, 0x00, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xa7, 0x73, 0x26, 0x88, 0x86, 0x7a, 0x72, 0x27,
-    0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0xff, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0x44, 0x40, 0x05, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0x13, 0x23, 0x21, 0x68, 0x86, 0x17, 0x72, 0x22,
-    0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0x4f, 0x4f, 0x4f,
-    0xff, 0xff, 0x44, 0x42, 0x00, 0x05, 0xbd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0x87, 0x27, 0x27, 0x16, 0x66, 0x67, 0x22, 0x22,
-    0x72, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0x94, 0x44, 0x44, 0x44,
-    0x44, 0x44, 0x44, 0x00, 0x00, 0x05, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb8,
-    0x86, 0x22, 0x22, 0x7a, 0x68, 0x81, 0x22, 0x22,
-    0x37, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x44, 0x44, 0x44,
-    0x44, 0x47, 0x00, 0x00, 0x00, 0x05, 0xbd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x68,
-    0x58, 0x72, 0x22, 0x27, 0x18, 0x86, 0x72, 0x22,
-    0x1a, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x18, 0x85,
-    0x58, 0x12, 0x22, 0x36, 0x18, 0x88, 0x32, 0x22,
-    0x61, 0x3b, 0xbb, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x7a, 0x68, 0x85,
-    0x88, 0x62, 0x27, 0x16, 0x18, 0x88, 0x12, 0x27,
-    0x86, 0x18, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd,
-    0xdd, 0xdd, 0xdd, 0xbb, 0xb5, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xbd,
-    0xdd, 0xdd, 0xdb, 0xbb, 0x87, 0x31, 0x68, 0x65,
-    0x88, 0x82, 0x23, 0x16, 0x18, 0x88, 0x12, 0x23,
-    0x88, 0x67, 0x27, 0xa8, 0x9b, 0xbb, 0xbb, 0xbb,
-    0xbd, 0xdd, 0xbb, 0xbb, 0x95, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9b, 0xbb,
-    0xbb, 0xbb, 0xbb, 0x96, 0x87, 0x16, 0x68, 0x18,
-    0x88, 0x62, 0x31, 0x66, 0x18, 0x88, 0x62, 0x73,
-    0x88, 0x63, 0x27, 0x33, 0x65, 0x55, 0x99, 0x9b,
-    0xbb, 0xbb, 0xbb, 0x99, 0x55, 0x0a, 0xa1, 0x86,
-    0x81, 0x68, 0x88, 0x55, 0x58, 0x85, 0x9b, 0xbb,
-    0xbb, 0xbb, 0x95, 0x88, 0x83, 0x66, 0x66, 0x18,
-    0x66, 0x82, 0xa1, 0x66, 0x18, 0x88, 0x62, 0x33,
-    0x88, 0x81, 0x27, 0x7a, 0x18, 0x58, 0x86, 0x85,
-    0x99, 0x99, 0x99, 0x95, 0x53, 0x2a, 0xaa, 0x88,
-    0x67, 0x31, 0x68, 0x55, 0x58, 0x85, 0x59, 0xbb,
-    0xbb, 0xb9, 0x58, 0x68, 0x83, 0x66, 0x61, 0x16,
-    0x66, 0x62, 0x16, 0x66, 0x68, 0x88, 0x62, 0xaa,
-    0x88, 0x86, 0x27, 0x77, 0x78, 0x55, 0x88, 0x22,
-    0x25, 0x55, 0x95, 0x55, 0x6a, 0xa2, 0x2a, 0x88,
-    0x62, 0x27, 0x37, 0x38, 0x88, 0x87, 0x55, 0x59,
-    0x95, 0x58, 0x16, 0x88, 0x8a, 0x66, 0x63, 0x68,
-    0x86, 0x67, 0x66, 0x66, 0x68, 0x88, 0x12, 0x11,
-    0x88, 0x88, 0x72, 0x77, 0x78, 0x85, 0x58, 0x17,
-    0x23, 0x32, 0x55, 0x55, 0x81, 0x13, 0x73, 0x66,
-    0x62, 0x7a, 0xaa, 0x38, 0x88, 0x58, 0x27, 0x55,
-    0x58, 0x32, 0x38, 0x88, 0x81, 0x66, 0xa2, 0x88,
-    0x86, 0x61, 0x66, 0x61, 0x66, 0x68, 0x13, 0x11,
-    0x88, 0x88, 0x12, 0x22, 0x71, 0x85, 0x58, 0x62,
-    0x23, 0xa2, 0x68, 0x88, 0x81, 0x66, 0x88, 0x88,
-    0x63, 0x2a, 0xaa, 0x28, 0x88, 0x55, 0x86, 0x61,
-    0x66, 0x66, 0x68, 0x88, 0x66, 0x66, 0x77, 0x88,
-    0x68, 0x16, 0x66, 0x62, 0x66, 0x68, 0xa1, 0x61,
-    0x88, 0x88, 0x62, 0x22, 0x22, 0x85, 0x55, 0x83,
-    0x72, 0x37, 0xa8, 0x88, 0x61, 0x66, 0x85, 0x55,
-    0x86, 0x23, 0xaa, 0x71, 0x88, 0x85, 0x88, 0x66,
-    0x88, 0x86, 0x88, 0x88, 0x16, 0x61, 0x21, 0x88,
-    0x66, 0xa6, 0x86, 0x17, 0x66, 0x66, 0x31, 0x61,
-    0x88, 0x88, 0x87, 0x72, 0x22, 0x68, 0x55, 0x86,
-    0x77, 0x77, 0x36, 0x88, 0x13, 0x68, 0x85, 0x55,
-    0x58, 0x12, 0x73, 0x72, 0x76, 0x88, 0x88, 0x68,
-    0x88, 0x88, 0x88, 0x66, 0x36, 0x63, 0x26, 0x86,
-    0x86, 0x36, 0x86, 0x11, 0x66, 0x66, 0x76, 0x61,
-    0x88, 0x88, 0x81, 0x22, 0x22, 0x38, 0x85, 0x58,
-    0x37, 0x22, 0x21, 0x68, 0xa2, 0x31, 0x68, 0x55,
-    0x55, 0x81, 0x22, 0x22, 0xa8, 0x88, 0x88, 0x68,
-    0x86, 0x88, 0x68, 0x81, 0x36, 0x17, 0x21, 0x68,
-    0x86, 0x16, 0x66, 0x26, 0x66, 0x61, 0x36, 0x66,
-    0x68, 0x88, 0x86, 0x27, 0x22, 0x28, 0x88, 0x88,
-    0x17, 0x72, 0x2a, 0x66, 0xa2, 0x22, 0x36, 0x55,
-    0x55, 0x58, 0x37, 0x3a, 0x16, 0x66, 0x66, 0x66,
-    0x66, 0x18, 0x88, 0x67, 0x16, 0x12, 0x71, 0x68,
-    0x81, 0x68, 0x61, 0x76, 0x66, 0x6a, 0x16, 0x66,
-    0x88, 0x88, 0x86, 0x77, 0x22, 0x26, 0x88, 0x88,
-    0x13, 0x37, 0x71, 0x66, 0xa2, 0x33, 0x2a, 0x85,
-    0x55, 0x55, 0x17, 0x73, 0x16, 0x66, 0x66, 0x68,
-    0x63, 0x88, 0x88, 0xa2, 0x66, 0xa2, 0xa6, 0x88,
-    0x61, 0x68, 0x6a, 0x76, 0x66, 0x6a, 0x66, 0x6a
-};
+#define INCLUDE_LINUX_LOGO16
+#include <linux/linux_logo.h>
 
 /* Painted by Johnny Stenback <jst@uwasa.fi> */
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h
--- v2.1.100/linux/include/asm-ppc/page.h	Sat Apr 25 18:13:12 1998
+++ linux/include/asm-ppc/page.h	Fri May  8 00:18:24 1998
@@ -64,6 +64,8 @@
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
 
+#define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)	free_page(addr)
 #define clear_page(page)        memset((void *)(page), 0, PAGE_SIZE)
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 /* map phys->virtual and virtual->phys for RAM pages */
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/pmu.h linux/include/asm-ppc/pmu.h
--- v2.1.100/linux/include/asm-ppc/pmu.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/pmu.h	Fri May  8 00:18:24 1998
@@ -16,12 +16,18 @@
 #define PMU_READ_NVRAM		0x3b	/* read non-volatile RAM */
 #define PMU_SET_RTC		0x30	/* set real-time clock */
 #define PMU_READ_RTC		0x38	/* read real-time clock */
+#define PMU_SET_VOLBUTTON	0x40	/* set volume up/down position */
 #define PMU_BACKLIGHT_BRIGHT	0x41	/* set backlight brightness */
+#define PMU_GET_VOLBUTTON	0x48	/* get volume up/down position */
+#define PMU_PCEJECT		0x4c	/* eject PC-card from slot */
+#define PMU_BATTERY_STATE	0x6b	/* report battery state etc. */
 #define PMU_SET_INTR_MASK	0x70	/* set PMU interrupt mask */
 #define PMU_INT_ACK		0x78	/* read interrupt bits */
 #define PMU_SHUTDOWN		0x7e	/* turn power off */
 #define PMU_SLEEP		0x7f	/* put CPU to sleep */
 #define PMU_RESET		0xd0	/* reset CPU */
+#define PMU_GET_BRIGHTBUTTON	0xd9	/* report brightness up/down pos */
+#define PMU_GET_COVER		0xdc	/* report cover open/closed */
 
 /* Bits in PMU interrupt and interrupt mask bytes */
 #define PMU_INT_ADB_AUTO	0x04	/* ADB autopoll, when PMU_INT_ADB */
@@ -31,6 +37,7 @@
 #define PMU_INT_TICK		0x80	/* 1-second tick interrupt */
 
 #ifdef __KERNEL__
+void find_via_pmu(void);
 void via_pmu_init(void);
 int pmu_request(struct adb_request *req,
 		void (*done)(struct adb_request *), int nbytes, ...);
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.1.100/linux/include/asm-ppc/processor.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/processor.h	Fri May  8 00:18:24 1998
@@ -234,7 +234,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     (TASK_SIZE / 8 * 3)
+#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 8 * 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define COPY_TASK_STRUCT(dst, src) 	\
 do {					\
@@ -284,6 +285,9 @@
 {
 	return (t->regs) ? t->regs->nip : 0;
 }
+
+#define copy_segments(nr, tsk, mm)	do { } while (0)
+#define release_segments(mm)		do { } while (0)
 
 /*
  * NOTE! The task struct and the stack go together
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/serial.h linux/include/asm-ppc/serial.h
--- v2.1.100/linux/include/asm-ppc/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/serial.h	Fri May  8 00:18:24 1998
@@ -0,0 +1,116 @@
+/*
+ * include/asm-ppc/serial.h
+ */
+
+/*
+ * This assumes you have a 1.8432 MHz clock for your UART.
+ *
+ * It'd be nice if someone built a serial card with a 24.576 MHz
+ * clock, since the 16550A is capable of handling a top speed of 1.5
+ * megabits/second; but this requires the faster clock.
+ */
+#define BASE_BAUD ( 1843200 / 16 )
+
+/* Standard COM flags (except for COM4, because of the 8514 problem) */
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF
+#endif
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define FOURPORT_FLAGS ASYNC_FOURPORT
+#define ACCENT_FLAGS 0
+#define BOCA_FLAGS 0
+#define HUB6_FLAGS 0
+#endif
+	
+/*
+ * The following define the access methods for the HUB6 card. All
+ * access is through two ports for all 24 possible chips. The card is
+ * selected through the high 2 bits, the port on that card with the
+ * "middle" 3 bits, and the register on that port with the bottom
+ * 3 bits.
+ *
+ * While the access port and interrupt is configurable, the default
+ * port locations are 0x302 for the port control register, and 0x303
+ * for the data read/write register. Normally, the interrupt is at irq3
+ * but can be anything from 3 to 7 inclusive. Note that using 3 will
+ * require disabling com2.
+ */
+
+#define C_P(card,port) (((card)<<6|(port)<<3) + 1)
+
+#define STD_SERIAL_PORT_DEFNS			\
+	/* UART CLK   PORT IRQ     FLAGS        */			\
+	{ 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },	/* ttyS3 */
+
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define EXTRA_SERIAL_PORT_DEFNS			\
+	{ 0, BASE_BAUD, 0x1A0, 9, FOURPORT_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0x1A8, 9, FOURPORT_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0x1B0, 9, FOURPORT_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0x1B8, 9, FOURPORT_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0x2A0, 5, FOURPORT_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0x2A8, 5, FOURPORT_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0x2B0, 5, FOURPORT_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0x2B8, 5, FOURPORT_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0x330, 4, ACCENT_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0x338, 4, ACCENT_FLAGS },	/* ttyS13 */	\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS14 (spare) */		\
+	{ 0, BASE_BAUD, 0x000, 0, 0 },	/* ttyS15 (spare) */		\
+	{ 0, BASE_BAUD, 0x100, 12, BOCA_FLAGS },	/* ttyS16 */	\
+	{ 0, BASE_BAUD, 0x108, 12, BOCA_FLAGS },	/* ttyS17 */	\
+	{ 0, BASE_BAUD, 0x110, 12, BOCA_FLAGS },	/* ttyS18 */	\
+	{ 0, BASE_BAUD, 0x118, 12, BOCA_FLAGS },	/* ttyS19 */	\
+	{ 0, BASE_BAUD, 0x120, 12, BOCA_FLAGS },	/* ttyS20 */	\
+	{ 0, BASE_BAUD, 0x128, 12, BOCA_FLAGS },	/* ttyS21 */	\
+	{ 0, BASE_BAUD, 0x130, 12, BOCA_FLAGS },	/* ttyS22 */	\
+	{ 0, BASE_BAUD, 0x138, 12, BOCA_FLAGS },	/* ttyS23 */	\
+	{ 0, BASE_BAUD, 0x140, 12, BOCA_FLAGS },	/* ttyS24 */	\
+	{ 0, BASE_BAUD, 0x148, 12, BOCA_FLAGS },	/* ttyS25 */	\
+	{ 0, BASE_BAUD, 0x150, 12, BOCA_FLAGS },	/* ttyS26 */	\
+	{ 0, BASE_BAUD, 0x158, 12, BOCA_FLAGS },	/* ttyS27 */	\
+	{ 0, BASE_BAUD, 0x160, 12, BOCA_FLAGS },	/* ttyS28 */	\
+	{ 0, BASE_BAUD, 0x168, 12, BOCA_FLAGS },	/* ttyS29 */	\
+	{ 0, BASE_BAUD, 0x170, 12, BOCA_FLAGS },	/* ttyS30 */	\
+	{ 0, BASE_BAUD, 0x178, 12, BOCA_FLAGS },	/* ttyS31 */
+#else
+#define EXTRA_SERIAL_PORT_DEFNS
+#endif
+
+/* You can have up to four HUB6's in the system, but I've only
+ * included two cards here for a total of twelve ports.
+ */
+#if (defined(CONFIG_HUB6) && defined(CONFIG_SERIAL_MANY_PORTS))
+#define HUB6_SERIAL_PORT_DFNS		\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,0) },  /* ttyS32 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,1) },  /* ttyS33 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,2) },  /* ttyS34 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,3) },  /* ttyS35 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,4) },  /* ttyS36 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(0,5) },  /* ttyS37 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,0) },  /* ttyS38 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,1) },  /* ttyS39 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,2) },  /* ttyS40 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,3) },  /* ttyS41 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,4) },  /* ttyS42 */	\
+	{ 0, BASE_BAUD, 0x302, 3, HUB6_FLAGS, C_P(1,5) },  /* ttyS43 */
+#else
+#define HUB6_SERIAL_PORT_DFNS
+#endif
+
+#define MCA_SERIAL_PORT_DFNS
+
+#define SERIAL_PORT_DFNS		\
+	STD_SERIAL_PORT_DEFNS		\
+	EXTRA_SERIAL_PORT_DEFNS		\
+	HUB6_SERIAL_PORT_DFNS		\
+	MCA_SERIAL_PORT_DFNS
+
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/spinlock.h linux/include/asm-ppc/spinlock.h
--- v2.1.100/linux/include/asm-ppc/spinlock.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/spinlock.h	Fri May  8 00:18:24 1998
@@ -64,8 +64,7 @@
 } spinlock_t;
 
 #define SPIN_LOCK_UNLOCKED	{ 0, 0, 0 }
-#define spin_lock_init(lp) \
-do { spinlock_t *p = (lp); p->owner_pc = p->owner_cpu = p->lock = 0; } while(0)
+#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
 #define spin_unlock_wait(lp)	do { barrier(); } while((lp)->lock)
 
 extern void _spin_lock(spinlock_t *lock);
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/timex.h linux/include/asm-ppc/timex.h
--- v2.1.100/linux/include/asm-ppc/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-ppc/timex.h
+ *
+ * ppc architecture timex specifications
+ */
+#ifndef _ASMppc_TIMEX_H
+#define _ASMppc_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#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)
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h
--- v2.1.100/linux/include/asm-ppc/unistd.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/unistd.h	Fri May  8 00:18:24 1998
@@ -21,7 +21,7 @@
 #define __NR_time		 13
 #define __NR_mknod		 14
 #define __NR_chmod		 15
-#define __NR_chown		 16
+#define __NR_lchown		 16
 #define __NR_break		 17
 #define __NR_oldstat		 18
 #define __NR_lseek		 19
@@ -177,8 +177,19 @@
 #define __NR_setresgid		169
 #define __NR_getresgid		170
 #define __NR_prctl		171
-#define __NR_xstat		172
-#define __NR_xmknod		173
+#define __NR_rt_sigreturn	172
+#define __NR_rt_sigaction	173
+#define __NR_rt_sigprocmask	174
+#define __NR_rt_sigpending	175
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread		180
+#define __NR_pwrite		181
+#define __NR_chown		182
+#define __NR_getcwd		183
+#define __NR_xstat		184
+#define __NR_xmknod		185
 
 #define __NR(n)	#n
 #define __do_syscall(n) \
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h
--- v2.1.100/linux/include/asm-sparc/asm_offsets.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/asm_offsets.h	Fri May  8 00:11:29 1998
@@ -48,108 +48,110 @@
 #define ASIZ_task_session	0x00000004
 #define AOFF_task_leader	0x00000074
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_ngroups	0x00000078
-#define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x0000007c
-#define ASIZ_task_groups	0x00000040
-#define AOFF_task_p_opptr	0x000000bc
+#define AOFF_task_p_opptr	0x00000078
 #define ASIZ_task_p_opptr	0x00000004
-#define AOFF_task_p_pptr	0x000000c0
+#define AOFF_task_p_pptr	0x0000007c
 #define ASIZ_task_p_pptr	0x00000004
-#define AOFF_task_p_cptr	0x000000c4
+#define AOFF_task_p_cptr	0x00000080
 #define ASIZ_task_p_cptr	0x00000004
-#define AOFF_task_p_ysptr	0x000000c8
+#define AOFF_task_p_ysptr	0x00000084
 #define ASIZ_task_p_ysptr	0x00000004
-#define AOFF_task_p_osptr	0x000000cc
+#define AOFF_task_p_osptr	0x00000088
 #define ASIZ_task_p_osptr	0x00000004
-#define AOFF_task_pidhash_next	0x000000d0
+#define AOFF_task_pidhash_next	0x0000008c
 #define ASIZ_task_pidhash_next	0x00000004
-#define AOFF_task_pidhash_pprev	0x000000d4
+#define AOFF_task_pidhash_pprev	0x00000090
 #define ASIZ_task_pidhash_pprev	0x00000004
-#define AOFF_task_tarray_ptr	0x000000d8
+#define AOFF_task_tarray_ptr	0x00000094
 #define ASIZ_task_tarray_ptr	0x00000004
-#define AOFF_task_wait_chldexit	0x000000dc
+#define AOFF_task_wait_chldexit	0x00000098
 #define ASIZ_task_wait_chldexit	0x00000004
-#define AOFF_task_uid	0x000000e0
-#define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x000000e2
-#define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x000000e4
-#define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x000000e6
-#define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x000000e8
-#define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x000000ea
-#define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x000000ec
-#define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x000000ee
-#define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_timeout	0x000000f0
+#define AOFF_task_timeout	0x0000009c
 #define ASIZ_task_timeout	0x00000004
-#define AOFF_task_policy	0x000000f4
+#define AOFF_task_policy	0x000000a0
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000f8
+#define AOFF_task_rt_priority	0x000000a4
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000fc
+#define AOFF_task_it_real_value	0x000000a8
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x00000100
+#define AOFF_task_it_prof_value	0x000000ac
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x00000104
+#define AOFF_task_it_virt_value	0x000000b0
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x00000108
+#define AOFF_task_it_real_incr	0x000000b4
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x0000010c
+#define AOFF_task_it_prof_incr	0x000000b8
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x00000110
+#define AOFF_task_it_virt_incr	0x000000bc
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x00000114
+#define AOFF_task_real_timer	0x000000c0
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x00000128
+#define AOFF_task_times	0x000000d4
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x00000138
+#define AOFF_task_start_time	0x000000e4
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x0000013c
+#define AOFF_task_per_cpu_utime	0x000000e8
 #define ASIZ_task_per_cpu_utime	0x00000004
-#define AOFF_task_min_flt	0x00000144
+#define AOFF_task_min_flt	0x000000f0
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x00000148
+#define AOFF_task_maj_flt	0x000000f4
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x0000014c
+#define AOFF_task_nswap	0x000000f8
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x00000150
+#define AOFF_task_cmin_flt	0x000000fc
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x00000154
+#define AOFF_task_cmaj_flt	0x00000100
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x00000158
+#define AOFF_task_cnswap	0x00000104
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_swap_address	0x00000160
+#define AOFF_task_swap_address	0x0000010c
 #define ASIZ_task_swap_address	0x00000004
-#define AOFF_task_old_maj_flt	0x00000164
+#define AOFF_task_old_maj_flt	0x00000110
 #define ASIZ_task_old_maj_flt	0x00000004
-#define AOFF_task_dec_flt	0x00000168
+#define AOFF_task_dec_flt	0x00000114
 #define ASIZ_task_dec_flt	0x00000004
-#define AOFF_task_swap_cnt	0x0000016c
+#define AOFF_task_swap_cnt	0x00000118
 #define ASIZ_task_swap_cnt	0x00000004
-#define AOFF_task_rlim	0x00000170
+#define AOFF_task_uid	0x0000011c
+#define ASIZ_task_uid	0x00000002
+#define AOFF_task_euid	0x0000011e
+#define ASIZ_task_euid	0x00000002
+#define AOFF_task_suid	0x00000120
+#define ASIZ_task_suid	0x00000002
+#define AOFF_task_fsuid	0x00000122
+#define ASIZ_task_fsuid	0x00000002
+#define AOFF_task_gid	0x00000124
+#define ASIZ_task_gid	0x00000002
+#define AOFF_task_egid	0x00000126
+#define ASIZ_task_egid	0x00000002
+#define AOFF_task_sgid	0x00000128
+#define ASIZ_task_sgid	0x00000002
+#define AOFF_task_fsgid	0x0000012a
+#define ASIZ_task_fsgid	0x00000002
+#define AOFF_task_ngroups	0x0000012c
+#define ASIZ_task_ngroups	0x00000004
+#define AOFF_task_groups	0x00000130
+#define ASIZ_task_groups	0x00000040
+#define AOFF_task_cap_effective	0x00000170
+#define ASIZ_task_cap_effective	0x00000004
+#define AOFF_task_cap_inheritable	0x00000174
+#define ASIZ_task_cap_inheritable	0x00000004
+#define AOFF_task_cap_permitted	0x00000178
+#define ASIZ_task_cap_permitted	0x00000004
+#define AOFF_task_rlim	0x0000017c
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000001c0
+#define AOFF_task_used_math	0x000001cc
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_io_usage	0x000001c4
-#define ASIZ_task_io_usage	0x00000004
-#define AOFF_task_comm	0x000001c8
+#define AOFF_task_comm	0x000001ce
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000001d8
+#define AOFF_task_link_count	0x000001e0
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000001dc
+#define AOFF_task_tty	0x000001e4
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000001e0
+#define AOFF_task_semundo	0x000001e8
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000001e4
+#define AOFF_task_semsleeping	0x000001ec
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_ldt	0x000001e8
-#define ASIZ_task_ldt	0x00000004
 #define AOFF_task_tss	0x000001f0
 #define ASIZ_task_tss	0x00000390
 #define AOFF_task_fs	0x00000580
@@ -224,6 +226,8 @@
 #define ASIZ_mm_def_flags	0x00000004
 #define AOFF_mm_cpu_vm_mask	0x00000060
 #define ASIZ_mm_cpu_vm_mask	0x00000004
+#define AOFF_mm_segments	0x00000064
+#define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
 #define AOFF_thread_kregs	0x00000004
@@ -315,108 +319,110 @@
 #define ASIZ_task_session	0x00000004
 #define AOFF_task_leader	0x00000074
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_ngroups	0x00000078
-#define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x0000007c
-#define ASIZ_task_groups	0x00000040
-#define AOFF_task_p_opptr	0x000000bc
+#define AOFF_task_p_opptr	0x00000078
 #define ASIZ_task_p_opptr	0x00000004
-#define AOFF_task_p_pptr	0x000000c0
+#define AOFF_task_p_pptr	0x0000007c
 #define ASIZ_task_p_pptr	0x00000004
-#define AOFF_task_p_cptr	0x000000c4
+#define AOFF_task_p_cptr	0x00000080
 #define ASIZ_task_p_cptr	0x00000004
-#define AOFF_task_p_ysptr	0x000000c8
+#define AOFF_task_p_ysptr	0x00000084
 #define ASIZ_task_p_ysptr	0x00000004
-#define AOFF_task_p_osptr	0x000000cc
+#define AOFF_task_p_osptr	0x00000088
 #define ASIZ_task_p_osptr	0x00000004
-#define AOFF_task_pidhash_next	0x000000d0
+#define AOFF_task_pidhash_next	0x0000008c
 #define ASIZ_task_pidhash_next	0x00000004
-#define AOFF_task_pidhash_pprev	0x000000d4
+#define AOFF_task_pidhash_pprev	0x00000090
 #define ASIZ_task_pidhash_pprev	0x00000004
-#define AOFF_task_tarray_ptr	0x000000d8
+#define AOFF_task_tarray_ptr	0x00000094
 #define ASIZ_task_tarray_ptr	0x00000004
-#define AOFF_task_wait_chldexit	0x000000dc
+#define AOFF_task_wait_chldexit	0x00000098
 #define ASIZ_task_wait_chldexit	0x00000004
-#define AOFF_task_uid	0x000000e0
-#define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x000000e2
-#define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x000000e4
-#define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x000000e6
-#define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x000000e8
-#define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x000000ea
-#define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x000000ec
-#define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x000000ee
-#define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_timeout	0x000000f0
+#define AOFF_task_timeout	0x0000009c
 #define ASIZ_task_timeout	0x00000004
-#define AOFF_task_policy	0x000000f4
+#define AOFF_task_policy	0x000000a0
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000f8
+#define AOFF_task_rt_priority	0x000000a4
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000fc
+#define AOFF_task_it_real_value	0x000000a8
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x00000100
+#define AOFF_task_it_prof_value	0x000000ac
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x00000104
+#define AOFF_task_it_virt_value	0x000000b0
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x00000108
+#define AOFF_task_it_real_incr	0x000000b4
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x0000010c
+#define AOFF_task_it_prof_incr	0x000000b8
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x00000110
+#define AOFF_task_it_virt_incr	0x000000bc
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x00000114
+#define AOFF_task_real_timer	0x000000c0
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x00000128
+#define AOFF_task_times	0x000000d4
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x00000138
+#define AOFF_task_start_time	0x000000e4
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x0000013c
+#define AOFF_task_per_cpu_utime	0x000000e8
 #define ASIZ_task_per_cpu_utime	0x00000080
-#define AOFF_task_min_flt	0x0000023c
+#define AOFF_task_min_flt	0x000001e8
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x00000240
+#define AOFF_task_maj_flt	0x000001ec
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x00000244
+#define AOFF_task_nswap	0x000001f0
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x00000248
+#define AOFF_task_cmin_flt	0x000001f4
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x0000024c
+#define AOFF_task_cmaj_flt	0x000001f8
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x00000250
+#define AOFF_task_cnswap	0x000001fc
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_swap_address	0x00000258
+#define AOFF_task_swap_address	0x00000204
 #define ASIZ_task_swap_address	0x00000004
-#define AOFF_task_old_maj_flt	0x0000025c
+#define AOFF_task_old_maj_flt	0x00000208
 #define ASIZ_task_old_maj_flt	0x00000004
-#define AOFF_task_dec_flt	0x00000260
+#define AOFF_task_dec_flt	0x0000020c
 #define ASIZ_task_dec_flt	0x00000004
-#define AOFF_task_swap_cnt	0x00000264
+#define AOFF_task_swap_cnt	0x00000210
 #define ASIZ_task_swap_cnt	0x00000004
-#define AOFF_task_rlim	0x00000268
+#define AOFF_task_uid	0x00000214
+#define ASIZ_task_uid	0x00000002
+#define AOFF_task_euid	0x00000216
+#define ASIZ_task_euid	0x00000002
+#define AOFF_task_suid	0x00000218
+#define ASIZ_task_suid	0x00000002
+#define AOFF_task_fsuid	0x0000021a
+#define ASIZ_task_fsuid	0x00000002
+#define AOFF_task_gid	0x0000021c
+#define ASIZ_task_gid	0x00000002
+#define AOFF_task_egid	0x0000021e
+#define ASIZ_task_egid	0x00000002
+#define AOFF_task_sgid	0x00000220
+#define ASIZ_task_sgid	0x00000002
+#define AOFF_task_fsgid	0x00000222
+#define ASIZ_task_fsgid	0x00000002
+#define AOFF_task_ngroups	0x00000224
+#define ASIZ_task_ngroups	0x00000004
+#define AOFF_task_groups	0x00000228
+#define ASIZ_task_groups	0x00000040
+#define AOFF_task_cap_effective	0x00000268
+#define ASIZ_task_cap_effective	0x00000004
+#define AOFF_task_cap_inheritable	0x0000026c
+#define ASIZ_task_cap_inheritable	0x00000004
+#define AOFF_task_cap_permitted	0x00000270
+#define ASIZ_task_cap_permitted	0x00000004
+#define AOFF_task_rlim	0x00000274
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000002b8
+#define AOFF_task_used_math	0x000002c4
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_io_usage	0x000002bc
-#define ASIZ_task_io_usage	0x00000004
-#define AOFF_task_comm	0x000002c0
+#define AOFF_task_comm	0x000002c6
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000002d0
+#define AOFF_task_link_count	0x000002d8
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000002d4
+#define AOFF_task_tty	0x000002dc
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000002d8
+#define AOFF_task_semundo	0x000002e0
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000002dc
+#define AOFF_task_semsleeping	0x000002e4
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_ldt	0x000002e0
-#define ASIZ_task_ldt	0x00000004
 #define AOFF_task_tss	0x000002e8
 #define ASIZ_task_tss	0x00000390
 #define AOFF_task_fs	0x00000678
@@ -491,6 +497,8 @@
 #define ASIZ_mm_def_flags	0x00000004
 #define AOFF_mm_cpu_vm_mask	0x00000060
 #define ASIZ_mm_cpu_vm_mask	0x00000004
+#define AOFF_mm_segments	0x00000064
+#define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
 #define AOFF_thread_kregs	0x00000004
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/audioio.h linux/include/asm-sparc/audioio.h
--- v2.1.100/linux/include/asm-sparc/audioio.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/audioio.h	Fri May  8 00:11:29 1998
@@ -0,0 +1,409 @@
+/*
+ * include/asm-sparc/audioio.h
+ *
+ * Sparc Audio Midlayer
+ * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
+ */
+
+#ifndef _AUDIOIO_H_
+#define _AUDIOIO_H_
+
+/*
+ *	SunOS/Solaris /dev/audio interface
+ */
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/ioctl.h>
+
+/*
+ * This structure contains state information for audio device IO streams.
+ */
+typedef struct audio_prinfo {
+	/*
+	 * The following values describe the audio data encoding.
+	 */
+	unsigned int sample_rate;	/* samples per second */
+	unsigned int channels;	/* number of interleaved channels */
+	unsigned int precision;	/* bit-width of each sample */
+	unsigned int encoding;	/* data encoding method */
+
+	/*
+	 * The following values control audio device configuration
+	 */
+	unsigned int gain;		/* gain level: 0 - 255 */
+	unsigned int port;		/* selected I/O port (see below) */
+	unsigned int avail_ports;	/* available I/O ports (see below) */
+	unsigned int _xxx[2];		/* Reserved for future use */
+
+	unsigned int buffer_size;	/* I/O buffer size */
+
+	/*
+	 * The following values describe driver state
+	 */
+	unsigned int samples;		/* number of samples converted */
+	unsigned int eof;		/* End Of File counter (play only) */
+
+	unsigned char	pause;		/* non-zero for pause, zero to resume */
+	unsigned char	error;		/* non-zero if overflow/underflow */
+	unsigned char	waiting;	/* non-zero if a process wants access */
+	unsigned char balance;	/* stereo channel balance */
+
+	unsigned short minordev;
+
+	/*
+	 * The following values are read-only state flags
+	 */
+	unsigned char open;		/* non-zero if open access permitted */
+	unsigned char active;		/* non-zero if I/O is active */
+} audio_prinfo_t;
+
+
+/*
+ * This structure describes the current state of the audio device.
+ */
+typedef struct audio_info {
+	/*
+	 * Per-stream information
+	 */
+	audio_prinfo_t play;	/* output status information */
+	audio_prinfo_t record;	/* input status information */
+
+	/*
+	 * Per-unit/channel information
+	 */
+	unsigned int monitor_gain;	/* input to output mix: 0 - 255 */
+	unsigned char output_muted;	/* non-zero if output is muted */
+	unsigned char _xxx[3];	/* Reserved for future use */
+	unsigned int _yyy[3];		/* Reserved for future use */
+} audio_info_t;
+
+
+/*
+ * Audio encoding types
+ */
+#define	AUDIO_ENCODING_NONE	(0)	/* no encoding assigned	  */
+#define	AUDIO_ENCODING_ULAW	(1)	/* u-law encoding	  */
+#define	AUDIO_ENCODING_ALAW	(2)	/* A-law encoding	  */
+#define	AUDIO_ENCODING_LINEAR	(3)	/* Linear PCM encoding	  */
+#define	AUDIO_ENCODING_DVI	(104)	/* DVI ADPCM		  */
+#define	AUDIO_ENCODING_LINEAR8	(105)	/* 8 bit UNSIGNED	  */
+#define	AUDIO_ENCODING_LINEARLE	(106)	/* Linear PCM LE encoding */
+
+/*
+ * These ranges apply to record, play, and monitor gain values
+ */
+#define	AUDIO_MIN_GAIN	(0)	/* minimum gain value */
+#define	AUDIO_MAX_GAIN	(255)	/* maximum gain value */
+
+/*
+ * These values apply to the balance field to adjust channel gain values
+ */
+#define	AUDIO_LEFT_BALANCE	(0)	/* left channel only	*/
+#define	AUDIO_MID_BALANCE	(32)	/* equal left/right channel */
+#define	AUDIO_RIGHT_BALANCE	(64)	/* right channel only	*/
+#define	AUDIO_BALANCE_SHIFT	(3)
+
+/*
+ * Generic minimum/maximum limits for number of channels, both modes
+ */
+#define	AUDIO_MIN_PLAY_CHANNELS	(1)
+#define	AUDIO_MAX_PLAY_CHANNELS	(4)
+#define	AUDIO_MIN_REC_CHANNELS	(1)
+#define	AUDIO_MAX_REC_CHANNELS	(4)
+
+/*
+ * Generic minimum/maximum limits for sample precision
+ */
+#define	AUDIO_MIN_PLAY_PRECISION	(8)
+#define	AUDIO_MAX_PLAY_PRECISION	(32)
+#define	AUDIO_MIN_REC_PRECISION		(8)
+#define	AUDIO_MAX_REC_PRECISION		(32)
+
+/*
+ * Define some convenient names for typical audio ports
+ */
+/*
+ * output ports (several may be enabled simultaneously)
+ */
+#define	AUDIO_SPEAKER		0x01	/* output to built-in speaker */
+#define	AUDIO_HEADPHONE		0x02	/* output to headphone jack */
+#define	AUDIO_LINE_OUT		0x04	/* output to line out	 */
+
+/*
+ * input ports (usually only one at a time)
+ */
+#define	AUDIO_MICROPHONE	0x01	/* input from microphone */
+#define	AUDIO_LINE_IN		0x02	/* input from line in	 */
+#define	AUDIO_CD		0x04	/* input from on-board CD inputs */
+#define	AUDIO_INTERNAL_CD_IN	AUDIO_CD	/* input from internal CDROM */
+/* Supposedly an undocumented feature of the 4231 */
+#define AUDIO_ANALOG_LOOPBACK   0x40
+
+
+/*
+ * This macro initializes an audio_info structure to 'harmless' values.
+ * Note that (~0) might not be a harmless value for a flag that was
+ * a signed int.
+ */
+#define	AUDIO_INITINFO(i)	{					\
+	unsigned int	*__x__;						\
+	for (__x__ = (unsigned int *)(i);				\
+	    (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t));	\
+	    *__x__++ = ~0);						\
+}
+
+/*
+ * These allow testing for what the user wants to set 
+ */
+#define AUD_INITVALUE   (~0)
+#define Modify(X)       ((unsigned int)(X) != AUD_INITVALUE)
+#define Modifys(X)      ((X) != (unsigned short)AUD_INITVALUE)
+#define Modifyc(X)      ((X) != (unsigned char)AUD_INITVALUE)
+
+/*
+ * Parameter for the AUDIO_GETDEV ioctl to determine current
+ * audio devices.
+ */
+#define	MAX_AUDIO_DEV_LEN	(16)
+typedef struct audio_device {
+	char name[MAX_AUDIO_DEV_LEN];
+	char version[MAX_AUDIO_DEV_LEN];
+	char config[MAX_AUDIO_DEV_LEN];
+} audio_device_t;
+
+
+/*
+ * Ioctl calls for the audio device.
+ */
+
+/*
+ * AUDIO_GETINFO retrieves the current state of the audio device.
+ *
+ * AUDIO_SETINFO copies all fields of the audio_info structure whose
+ * values are not set to the initialized value (-1) to the device state.
+ * It performs an implicit AUDIO_GETINFO to return the new state of the
+ * device.  Note that the record.samples and play.samples fields are set
+ * to the last value before the AUDIO_SETINFO took effect.  This allows
+ * an application to reset the counters while atomically retrieving the
+ * last value.
+ *
+ * AUDIO_DRAIN suspends the calling process until the write buffers are
+ * empty.
+ *
+ * AUDIO_GETDEV returns a structure of type audio_device_t which contains
+ * three strings.  The string "name" is a short identifying string (for
+ * example, the SBus Fcode name string), the string "version" identifies
+ * the current version of the device, and the "config" string identifies
+ * the specific configuration of the audio stream.  All fields are
+ * device-dependent -- see the device specific manual pages for details.
+ *
+ * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined 
+ * herein (making it not too portable)
+ *
+ * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, 
+ * resets error counters, and restarts recording and playback as appropriate
+ * for the current sampling mode.
+ */
+#define	AUDIO_GETINFO	_IOR('A', 1, audio_info_t)
+#define	AUDIO_SETINFO	_IOWR('A', 2, audio_info_t)
+#define	AUDIO_DRAIN	_IO('A', 3)
+#define	AUDIO_GETDEV	_IOR('A', 4, audio_device_t)
+#define	AUDIO_GETDEV_SUNOS	_IOR('A', 4, int)
+#define AUDIO_FLUSH     _IO('A', 5)
+
+/* Define possible audio hardware configurations for 
+ * old SunOS-style AUDIO_GETDEV ioctl */
+#define AUDIO_DEV_UNKNOWN       (0)     /* not defined */
+#define AUDIO_DEV_AMD           (1)     /* audioamd device */
+#define AUDIO_DEV_SPEAKERBOX    (2)     /* dbri device with speakerbox */
+#define AUDIO_DEV_CODEC         (3)     /* dbri device (internal speaker) */
+#define AUDIO_DEV_CS4231        (5)     /* cs4231 device */
+
+/*
+ * The following ioctl sets the audio device into an internal loopback mode,
+ * if the hardware supports this.  The argument is TRUE to set loopback,
+ * FALSE to reset to normal operation.  If the hardware does not support
+ * internal loopback, the ioctl should fail with EINVAL.
+ */
+#define	AUDIO_DIAG_LOOPBACK	_IOW('A', 101, int)
+
+#ifdef notneeded
+/*
+ * Structure sent up as a M_PROTO message on trace streams
+ */
+typedef struct audtrace_hdr audtrace_hdr_t;
+struct audtrace_hdr {
+	unsigned int seq;		/* Sequence number (per-aud_stream) */
+	int type;		/* device-dependent */
+	struct timeval timestamp;
+	char _f[8];		/* filler */
+};
+#endif
+
+/*
+ *	Linux kernel internal implementation.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/tqueue.h>
+#include <linux/wait.h>
+
+#define	SDF_OPEN_WRITE	0x00000001
+#define	SDF_OPEN_READ	0x00000002
+
+struct sparcaudio_driver
+{
+	const char * name;
+	struct sparcaudio_operations *ops;
+	void *private;
+	unsigned long flags;
+
+	/* Processes blocked on open() sit here. */
+	struct wait_queue *open_wait;
+
+	/* Task queue for this driver's bottom half. */
+	struct tq_struct tqueue;
+
+	/* Support for a circular queue of output buffers. */
+	__u8 **output_buffers;
+	size_t *output_sizes, output_size;
+	int num_output_buffers, output_front, output_rear;
+	int output_count, output_active, playing_count;
+	struct wait_queue *output_write_wait, *output_drain_wait;
+
+        /* Support for a circular queue of input buffers. */
+        __u8 **input_buffers;
+        int input_offset;
+        int num_input_buffers, input_front, input_rear;
+        int input_count, input_active, recording_count;
+        struct wait_queue *input_read_wait;
+};
+
+struct sparcaudio_operations
+{
+	int (*open)(struct inode *, struct file *, struct sparcaudio_driver *);
+	void (*release)(struct inode *, struct file *, struct sparcaudio_driver *);
+	int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long,
+		     struct sparcaudio_driver *);
+
+	/* Ask driver to begin playing a buffer. */
+	void (*start_output)(struct sparcaudio_driver *, __u8 *, unsigned long);
+
+	/* Ask driver to stop playing a buffer. */
+	void (*stop_output)(struct sparcaudio_driver *);
+
+	/* Ask driver to begin recording into a buffer. */
+	void (*start_input)(struct sparcaudio_driver *, __u8 *, unsigned long);
+
+	/* Ask driver to stop recording. */
+	void (*stop_input)(struct sparcaudio_driver *);
+
+	/* Return driver name/version to caller. (/dev/audio specific) */
+	void (*sunaudio_getdev)(struct sparcaudio_driver *, audio_device_t *);
+
+        /* Get and set the output volume. (0-255) */
+        int (*set_output_volume)(struct sparcaudio_driver *, int);
+        int (*get_output_volume)(struct sparcaudio_driver *);
+
+        /* Get and set the input volume. (0-255) */
+        int (*set_input_volume)(struct sparcaudio_driver *, int);
+        int (*get_input_volume)(struct sparcaudio_driver *);
+
+        /* Get and set the monitor volume. (0-255) */
+        int (*set_monitor_volume)(struct sparcaudio_driver *, int);
+        int (*get_monitor_volume)(struct sparcaudio_driver *);
+
+        /* Get and set the output balance. (0-64) */
+        int (*set_output_balance)(struct sparcaudio_driver *, int);
+        int (*get_output_balance)(struct sparcaudio_driver *);
+
+        /* Get and set the input balance. (0-64) */
+        int (*set_input_balance)(struct sparcaudio_driver *, int);
+        int (*get_input_balance)(struct sparcaudio_driver *);
+
+        /* Get and set the output channels. (1-4) */
+        int (*set_output_channels)(struct sparcaudio_driver *, int);
+        int (*get_output_channels)(struct sparcaudio_driver *);
+
+        /* Get and set the input channels. (1-4) */
+        int (*set_input_channels)(struct sparcaudio_driver *, int);
+        int (*get_input_channels)(struct sparcaudio_driver *);
+
+        /* Get and set the output precision. (8-32) */
+        int (*set_output_precision)(struct sparcaudio_driver *, int);
+        int (*get_output_precision)(struct sparcaudio_driver *);
+
+        /* Get and set the input precision. (8-32) */
+        int (*set_input_precision)(struct sparcaudio_driver *, int);
+        int (*get_input_precision)(struct sparcaudio_driver *);
+
+        /* Get and set the output port. () */
+        int (*set_output_port)(struct sparcaudio_driver *, int);
+        int (*get_output_port)(struct sparcaudio_driver *);
+
+        /* Get and set the input port. () */
+        int (*set_input_port)(struct sparcaudio_driver *, int);
+        int (*get_input_port)(struct sparcaudio_driver *);
+
+        /* Get and set the output encoding. () */
+        int (*set_output_encoding)(struct sparcaudio_driver *, int);
+        int (*get_output_encoding)(struct sparcaudio_driver *);
+
+        /* Get and set the input encoding. () */
+        int (*set_input_encoding)(struct sparcaudio_driver *, int);
+        int (*get_input_encoding)(struct sparcaudio_driver *);
+
+        /* Get and set the output rate. () */
+        int (*set_output_rate)(struct sparcaudio_driver *, int);
+        int (*get_output_rate)(struct sparcaudio_driver *);
+
+        /* Get and set the input rate. () */
+        int (*set_input_rate)(struct sparcaudio_driver *, int);
+        int (*get_input_rate)(struct sparcaudio_driver *);
+
+	/* Return driver number to caller. (SunOS /dev/audio specific) */
+	int (*sunaudio_getdev_sunos)(struct sparcaudio_driver *);
+
+        /* Get available ports */
+        int (*get_output_ports)(struct sparcaudio_driver *);
+        int (*get_input_ports)(struct sparcaudio_driver *);
+
+        /* Get and set output mute */
+        int (*set_output_muted)(struct sparcaudio_driver *, int);
+        int (*get_output_muted)(struct sparcaudio_driver *);
+};
+
+extern int register_sparcaudio_driver(struct sparcaudio_driver *);
+extern int unregister_sparcaudio_driver(struct sparcaudio_driver *);
+extern void sparcaudio_output_done(struct sparcaudio_driver *, int);
+extern void sparcaudio_input_done(struct sparcaudio_driver *);
+extern int sparcaudio_init(void);
+extern int amd7930_init(void);
+extern int cs4231_init(void);
+
+#endif
+
+/* Macros to convert between mixer stereo volumes and gain (mono) */
+#define s_to_m(a) (((((a) >> 8) & 0x7f) + ((a) & 0x7f)) / 2)
+#define m_to_s(a) (((a) << 8) + (a))
+
+/* convert mixer stereo volume to balance */
+#define s_to_b(a) (AUDIO_RIGHT_BALANCE * ((((a) >> 8) & 0xff) /  (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2)))
+
+/* convert mixer stereo volume to audio gain */
+#define s_to_g(a) (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2)
+
+/* convert gain a and balance b to mixer volume */
+#define b_to_s(a,b) ((a * (b / AUDIO_RIGHT_BALANCE) << 8) + (a * (1 - (b / AUDIO_RIGHT_BALANCE))))
+
+#define SPARCAUDIO_MIXER_MINOR 0
+#define SPARCAUDIO_DSP16_MINOR 1
+#define SPARCAUDIO_DSP_MINOR   3
+#define SPARCAUDIO_AUDIO_MINOR 4
+#define SPARCAUDIO_AUDIOCTL_MINOR 5
+#define SPARCAUDIO_STATUS_MINOR 6
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h
--- v2.1.100/linux/include/asm-sparc/dma.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/dma.h	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.25 1998/02/09 13:27:01 jj Exp $
+/* $Id: dma.h,v 1.26 1998/04/13 07:27:05 davem Exp $
  * include/asm-sparc/dma.h
  *
  * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
@@ -82,7 +82,7 @@
 #define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
 
 /* Main routines in dma.c */
-extern unsigned long dvma_init(struct linux_sbus *, unsigned long);
+extern void dvma_init(struct linux_sbus *);
 
 /* Fields in the cond_reg register */
 /* First, the version identification bits */
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/elf.h linux/include/asm-sparc/elf.h
--- v2.1.100/linux/include/asm-sparc/elf.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/elf.h	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.15 1998/03/23 08:41:32 jj Exp $ */
+/* $Id: elf.h,v 1.16 1998/05/01 16:28:47 davem Exp $ */
 #ifndef __ASMSPARC_ELF_H
 #define __ASMSPARC_ELF_H
 
@@ -42,7 +42,7 @@
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE + 0x1000000)
+#define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE(0) + 0x1000000)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  This can NOT be done in userspace
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h
--- v2.1.100/linux/include/asm-sparc/irq.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/irq.h	Fri May  8 00:11:29 1998
@@ -67,11 +67,6 @@
 #define irq_exit(cpu, irq)		(local_irq_count[cpu]--)
 #endif
 
-static __inline__ int irq_cannonicalize(int irq)
-{
-	return irq;
-}
-
 /* Dave Redman (djhr@tadpole.co.uk)
  * changed these to function pointers.. it saves cycles and will allow
  * the irq dependencies to be split into different files at a later date
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/linux_logo.h linux/include/asm-sparc/linux_logo.h
--- v2.1.100/linux/include/asm-sparc/linux_logo.h	Tue May 13 22:41:18 1997
+++ linux/include/asm-sparc/linux_logo.h	Fri May  8 00:11:29 1998
@@ -1,4 +1,4 @@
-/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $
+/* $Id: linux_logo.h,v 1.2 1998/05/04 14:20:59 jj Exp $
  * include/asm-sparc/linux_logo.h: This is a linux logo
  *                                 to be displayed on boot.
  *
@@ -25,1004 +25,7 @@
 
 #define LINUX_LOGO_COLORS 221
 
-unsigned char linux_logo_red[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
-  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
-  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
-  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
-  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
-  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
-  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
-  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
-  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
-  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
-  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
-  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
-  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
-  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
-  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
-  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
-  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo_green[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
-  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
-  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
-  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
-  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
-  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
-  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
-  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
-  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
-  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
-  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
-  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
-  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
-  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
-  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
-  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
-  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo_blue[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
-  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
-  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
-  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
-  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
-  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
-  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
-  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
-  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
-  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
-  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
-  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
-  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
-  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
-  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
-  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
-  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
-  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo[] __initdata = {
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
-  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
-  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
-  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
-  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
-  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
-  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
-  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
-  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
-  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
-  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
-  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
-  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
-  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
-  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
-  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
-  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
-  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
-  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
-  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
-  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
-  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
-  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
-  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
-  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
-  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
-  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
-  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
-  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
-  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
-  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
-  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
-  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
-  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
-  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
-  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
-  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
-  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
-  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
-  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
-  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
-  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
-  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
-  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
-  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
-  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
-  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
-  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
-  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
-  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
-  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
-  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
-  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
-  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
-  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
-  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
-  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
-  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
-  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
-  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
-  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
-  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
-  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
-  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
-  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
-  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
-  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
-  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
-  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
-  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
-  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
-  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
-  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
-  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
-  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
-  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
-  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
-  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
-  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
-  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
-  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
-  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
-  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
-  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
-  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
-  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
-  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
-  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
-  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
-  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
-  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
-  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
-  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
-  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
-  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
-  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
-  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
-  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
-  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
-  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
-  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
-  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
-  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
-  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
-  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
-  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
-  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
-  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
-  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
-  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
-  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
-  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
-  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
-  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
-  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
-  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
-  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
-  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
-  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
-  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
-  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
-  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
-  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
-  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
-  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
-  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
-  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
-  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
-  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
-  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
-  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
-  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
-  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
-  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
-  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
-  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
-  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
-  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
-  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
-  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
-  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
-  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
-  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
-  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
-  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
-  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
-  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
-  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
-  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
-  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
-  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
-  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
-  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
-  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
-  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
-  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
-  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
-  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
-  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
-  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
-  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
-  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
-  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
-  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
-  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
-  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
-  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
-  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
-  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
-  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
-  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
-  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
-  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
-  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
-  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
-  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
-  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
-  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
-  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
-  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
-  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
-  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
-  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
-  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
-  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
-  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
-  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
-  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
-  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
-  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
-  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
-  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
-  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
-  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
-  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
-  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
-  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
-  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
-  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
-  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
-  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
-  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
-  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
-  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
-  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
-  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
-  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
-  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
-  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
-  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
-  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
-  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
-  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
-  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
-  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
-  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
-  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
-  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
-  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
-  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
-  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
-  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
-  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
-  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
-  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
-  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
-  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
-  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
-  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
-  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
-  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
-  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
-  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
-  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
-  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
-  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
-  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
-  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
-  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
-  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
-  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
-  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
-  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
-  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
-  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
-  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
-  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
-  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
-  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
-  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
-  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
-  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
-  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
-  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
-  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
-  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
-  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
-  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
-  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
-  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
-  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
-  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
-  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
-  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
-  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
-  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
-  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
-  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
-  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
-  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
-  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
-  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
-  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
-  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
-  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
-  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
-  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
-  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
-  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
-  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
-  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
-  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
-  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
-  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
-  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
-  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
-  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
-  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
-  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
-  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
-  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
-  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
-  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
-  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
-  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
-  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
-  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
-  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
-  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
-  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
-  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
-  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
-  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
-  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
-  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
-  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
-  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
-  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
-  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
-  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
-  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
-  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
-  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
-  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
-  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
-  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
-  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
-  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
-  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
-  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
-  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
-  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
-  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
-  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
-  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
-  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
-  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
-  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
-  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
-  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
-  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
-  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
-  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
-  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
-  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
-  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
-  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
-  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
-  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
-  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
-  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
-  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
-  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
-  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
-  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
-  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
-  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
-  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
-  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
-  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
-  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
-  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
-  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
-  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
-  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
-  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
-  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
-  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
-  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
-  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
-  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
-  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
-  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
-  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
-  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
-  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
-  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
-  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
-  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
-  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
-  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
-  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
-  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
-  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
-  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
-  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
-  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
-  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
-  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
-  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
-  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
-  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
-  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
-  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
-  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
-  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
-  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
-  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
-  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
-  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
-  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
-  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
-  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
-  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
-  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
-  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
-  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
-  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
-  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
-  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
-  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
-  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
-  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
-  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
-  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
-  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
-  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
-  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
-  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
-  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
-  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
-  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
-  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
-  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
-  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
-  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
-  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
-  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
-  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
-  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
-  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
-  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
-  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
-  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
-  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
-  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
-  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
-  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
-  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
-  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
-  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
-  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
-  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
-  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
-  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
-  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
-  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
-  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
-  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
-  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
-  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
-  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
-  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
-  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
-  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
-  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
-  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
-  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
-  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
-  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
-  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
-  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
-  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
-  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
-  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
-  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
-  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
-  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
-  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
-  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
-  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
-  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
-  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
-  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
-  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
-  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
-  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
-  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
-  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
-  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
-  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
-  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
-  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
-  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
-  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
-  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
-  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
-  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
-  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
-  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
-  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
-  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
-  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
-  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
-  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
-  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
-  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
-  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
-  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
-  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
-  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
-  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
-  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
-  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
-  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
-  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
-  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
-  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
-  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
-  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
-  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
-  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
-  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
-  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
-  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
-  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
-  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
-  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
-  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
-  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
-  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
-  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
-  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
-  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
-  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
-  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
-  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
-  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
-  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
-  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
-  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
-  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
-  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
-  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
-  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
-  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
-  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
-  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
-  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
-  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
-  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
-  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
-  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
-  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
-  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
-  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
-  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
-  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
-  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
-  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
-  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
-  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
-  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
-  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
-  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
-  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
-  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
-  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
-  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
-  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
-  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
-  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
-  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
-  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
-  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
-  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
-  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
-  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
-  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
-  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
-  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
-  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
-  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
-  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
-  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
-  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
-  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
-  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
-  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
-  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
-  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
-  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
-  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
-  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
-  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
-  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
-  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
-  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
-  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
-  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
-  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
-  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
-  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
-  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
-  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
-  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
-  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
-  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
-  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
-  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
-  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
-  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
-  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
-  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
-  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
-  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
-  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
-  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
-  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
-  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
-  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
-  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
-  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
-  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
-  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
-  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
-  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
-  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
-  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
-};
-
-unsigned char linux_logo_bw[] __initdata = {
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
-  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
-  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
-  0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
-  0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
-  0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
-  0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
-  0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
-  0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
-  0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
-  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
-  0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
-  0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
-  0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
-  0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
-  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
-  0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
-  0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
-  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
-  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
-  0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
-  0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
-  0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
-  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
-  0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
-  0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
-  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
-  0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
-  0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
-  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
-  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
-  0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
-  0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
-  0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
-  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
-  0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
-  0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
-  0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
-  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
-  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
-  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
-  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
-  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
-  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
-  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
-  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
-  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
-  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
-  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
-  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
-  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
-  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
-  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
-  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
-  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
-  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 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, 0xFF, 0xFF,
-};
+#include <linux/linux_logo.h>
 
 /* Painted by Johnny Stenback <jst@uwasa.fi> */
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v2.1.100/linux/include/asm-sparc/page.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/page.h	Fri May  8 00:11:35 1998
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.40 1998/02/06 14:14:46 jj Exp $
+/* $Id: page.h,v 1.42 1998/05/01 13:55:21 mj Exp $
  * page.h:  Various defines and such for MMU operations on the Sparc for
  *          the Linux kernel.
  *
@@ -28,6 +28,8 @@
 
 #ifndef __ASSEMBLY__
 
+#define get_user_page(vaddr)		__get_free_page(GFP_KERNEL)
+#define free_user_page(page, addr)	free_page(addr)
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 
@@ -268,7 +270,8 @@
 
 BTFIXUPDEF_SETHI(sparc_unmapped_base)
 
-#define TASK_UNMAPPED_BASE	BTFIXUP_SETHI(sparc_unmapped_base)
+#define TASK_UNMAPPED_BASE(off)	BTFIXUP_SETHI(sparc_unmapped_base)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.1.100/linux/include/asm-sparc/processor.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/processor.h	Fri May  8 00:11:35 1998
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.62 1998/02/05 14:20:02 jj Exp $
+/* $Id: processor.h,v 1.63 1998/04/23 08:26:22 davem Exp $
  * include/asm-sparc/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -153,6 +153,9 @@
 
 /* Free all resources held by a thread. */
 #define release_thread(tsk)		do { } while(0)
+
+#define copy_segments(nr, tsk, mm)	do { } while (0)
+#define release_segments(mm)		do { } while (0)
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.1.100/linux/include/asm-sparc/system.h	Sat Apr 25 18:13:12 1998
+++ linux/include/asm-sparc/system.h	Fri May  8 00:11:35 1998
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.68 1998/03/09 14:04:51 jj Exp $ */
+/* $Id: system.h,v 1.69 1998/04/24 12:30:19 davem Exp $ */
 #include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.1.100/linux/include/asm-sparc/termios.h	Wed Apr  8 19:36:29 1998
+++ linux/include/asm-sparc/termios.h	Fri May  8 00:11:35 1998
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.25 1997/03/04 19:36:18 davem Exp $ */
+/* $Id: termios.h,v 1.26 1998/04/12 06:27:19 davem Exp $ */
 #ifndef _SPARC_TERMIOS_H
 #define _SPARC_TERMIOS_H
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/timer.h linux/include/asm-sparc/timer.h
--- v2.1.100/linux/include/asm-sparc/timer.h	Sat Apr 25 18:13:12 1998
+++ linux/include/asm-sparc/timer.h	Fri May  8 00:11:35 1998
@@ -1,4 +1,4 @@
-/* $Id: timer.h,v 1.16 1998/01/30 10:59:59 jj Exp $
+/* $Id: timer.h,v 1.17 1998/04/24 12:30:19 davem Exp $
  * timer.h:  Definitions for the timer chips on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/timex.h linux/include/asm-sparc/timex.h
--- v2.1.100/linux/include/asm-sparc/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-sparc/timex.h
+ *
+ * sparc architecture timex specifications
+ */
+#ifndef _ASMsparc_TIMEX_H
+#define _ASMsparc_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#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)
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v2.1.100/linux/include/asm-sparc/unistd.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/unistd.h	Fri May  8 00:11:35 1998
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.38 1998/03/27 07:01:56 davem Exp $ */
+/* $Id: unistd.h,v 1.40 1998/04/14 13:49:55 jj Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -135,7 +135,7 @@
 #define __NR_gettimeofday       116 /* Common                                      */
 #define __NR_getrusage          117 /* Common                                      */
 #define __NR_getsockopt         118 /* Common                                      */
-/* #define __NR_ni_syscall      119    ENOSYS under SunOS                          */
+#define __NR_getcwd      	119 /* Linux Specific                              */
 #define __NR_readv              120 /* Common                                      */
 #define __NR_writev             121 /* Common                                      */
 #define __NR_settimeofday       122 /* Common                                      */
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.1.100/linux/include/asm-sparc64/asm_offsets.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/asm_offsets.h	Fri May  8 00:11:36 1998
@@ -48,135 +48,137 @@
 #define ASIZ_task_session	0x00000004
 #define AOFF_task_leader	0x000000cc
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_ngroups	0x000000d0
-#define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x000000d4
-#define ASIZ_task_groups	0x00000080
-#define AOFF_task_p_opptr	0x00000158
+#define AOFF_task_p_opptr	0x000000d0
 #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x00000160
+#define AOFF_task_p_pptr	0x000000d8
 #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x00000168
+#define AOFF_task_p_cptr	0x000000e0
 #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x00000170
+#define AOFF_task_p_ysptr	0x000000e8
 #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x00000178
+#define AOFF_task_p_osptr	0x000000f0
 #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x00000180
+#define AOFF_task_pidhash_next	0x000000f8
 #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x00000188
+#define AOFF_task_pidhash_pprev	0x00000100
 #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_tarray_ptr	0x00000190
+#define AOFF_task_tarray_ptr	0x00000108
 #define ASIZ_task_tarray_ptr	0x00000008
-#define AOFF_task_wait_chldexit	0x00000198
+#define AOFF_task_wait_chldexit	0x00000110
 #define ASIZ_task_wait_chldexit	0x00000008
-#define AOFF_task_uid	0x000001a0
-#define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000001a4
-#define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000001a8
-#define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000001ac
-#define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000001b0
-#define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000001b4
-#define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000001b8
-#define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000001bc
-#define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_timeout	0x000001c0
+#define AOFF_task_timeout	0x00000118
 #define ASIZ_task_timeout	0x00000008
-#define AOFF_task_policy	0x000001c8
+#define AOFF_task_policy	0x00000120
 #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x000001d0
+#define AOFF_task_rt_priority	0x00000128
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x000001d8
+#define AOFF_task_it_real_value	0x00000130
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x000001e0
+#define AOFF_task_it_prof_value	0x00000138
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x000001e8
+#define AOFF_task_it_virt_value	0x00000140
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x000001f0
+#define AOFF_task_it_real_incr	0x00000148
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x000001f8
+#define AOFF_task_it_prof_incr	0x00000150
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000200
+#define AOFF_task_it_virt_incr	0x00000158
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000208
+#define AOFF_task_real_timer	0x00000160
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000230
+#define AOFF_task_times	0x00000188
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000250
+#define AOFF_task_start_time	0x000001a8
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x00000258
+#define AOFF_task_per_cpu_utime	0x000001b0
 #define ASIZ_task_per_cpu_utime	0x00000008
-#define AOFF_task_min_flt	0x00000268
+#define AOFF_task_min_flt	0x000001c0
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x00000270
+#define AOFF_task_maj_flt	0x000001c8
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x00000278
+#define AOFF_task_nswap	0x000001d0
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x00000280
+#define AOFF_task_cmin_flt	0x000001d8
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x00000288
+#define AOFF_task_cmaj_flt	0x000001e0
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x00000290
+#define AOFF_task_cnswap	0x000001e8
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_swap_address	0x000002a0
+#define AOFF_task_swap_address	0x000001f8
 #define ASIZ_task_swap_address	0x00000008
-#define AOFF_task_old_maj_flt	0x000002a8
+#define AOFF_task_old_maj_flt	0x00000200
 #define ASIZ_task_old_maj_flt	0x00000008
-#define AOFF_task_dec_flt	0x000002b0
+#define AOFF_task_dec_flt	0x00000208
 #define ASIZ_task_dec_flt	0x00000008
-#define AOFF_task_swap_cnt	0x000002b8
+#define AOFF_task_swap_cnt	0x00000210
 #define ASIZ_task_swap_cnt	0x00000008
-#define AOFF_task_rlim	0x000002c0
+#define AOFF_task_uid	0x00000218
+#define ASIZ_task_uid	0x00000004
+#define AOFF_task_euid	0x0000021c
+#define ASIZ_task_euid	0x00000004
+#define AOFF_task_suid	0x00000220
+#define ASIZ_task_suid	0x00000004
+#define AOFF_task_fsuid	0x00000224
+#define ASIZ_task_fsuid	0x00000004
+#define AOFF_task_gid	0x00000228
+#define ASIZ_task_gid	0x00000004
+#define AOFF_task_egid	0x0000022c
+#define ASIZ_task_egid	0x00000004
+#define AOFF_task_sgid	0x00000230
+#define ASIZ_task_sgid	0x00000004
+#define AOFF_task_fsgid	0x00000234
+#define ASIZ_task_fsgid	0x00000004
+#define AOFF_task_ngroups	0x00000238
+#define ASIZ_task_ngroups	0x00000004
+#define AOFF_task_groups	0x0000023c
+#define ASIZ_task_groups	0x00000080
+#define AOFF_task_cap_effective	0x000002bc
+#define ASIZ_task_cap_effective	0x00000004
+#define AOFF_task_cap_inheritable	0x000002c0
+#define ASIZ_task_cap_inheritable	0x00000004
+#define AOFF_task_cap_permitted	0x000002c4
+#define ASIZ_task_cap_permitted	0x00000004
+#define AOFF_task_rlim	0x000002c8
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000360
+#define AOFF_task_used_math	0x00000368
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_io_usage	0x00000368
-#define ASIZ_task_io_usage	0x00000008
-#define AOFF_task_comm	0x00000370
+#define AOFF_task_comm	0x0000036a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000380
+#define AOFF_task_link_count	0x0000037c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000388
+#define AOFF_task_tty	0x00000380
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000390
+#define AOFF_task_semundo	0x00000388
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000398
+#define AOFF_task_semsleeping	0x00000390
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_ldt	0x000003a0
-#define ASIZ_task_ldt	0x00000008
-#define AOFF_task_tss	0x000003b0
+#define AOFF_task_tss	0x000003a0
 #define ASIZ_task_tss	0x00000490
-#define AOFF_task_fs	0x00000840
+#define AOFF_task_fs	0x00000830
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x00000848
+#define AOFF_task_files	0x00000838
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x00000850
+#define AOFF_task_mm	0x00000840
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sig	0x00000858
+#define AOFF_task_sig	0x00000848
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x00000860
+#define AOFF_task_signal	0x00000850
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000868
+#define AOFF_task_blocked	0x00000858
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000870
+#define AOFF_task_sigqueue	0x00000860
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000878
+#define AOFF_task_sigqueue_tail	0x00000868
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_has_cpu	0x00000880
+#define AOFF_task_has_cpu	0x00000870
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000884
+#define AOFF_task_processor	0x00000874
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000888
+#define AOFF_task_last_processor	0x00000878
 #define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x0000088c
+#define AOFF_task_lock_depth	0x0000087c
 #define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_sigmask_lock	0x00000890
+#define AOFF_task_sigmask_lock	0x00000880
 #define ASIZ_task_sigmask_lock	0x00000000
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
@@ -224,6 +226,8 @@
 #define ASIZ_mm_def_flags	0x00000008
 #define AOFF_mm_cpu_vm_mask	0x000000b0
 #define ASIZ_mm_cpu_vm_mask	0x00000008
+#define AOFF_mm_segments	0x000000b8
+#define ASIZ_mm_segments	0x00000008
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_kpc	0x00000008
@@ -303,135 +307,137 @@
 #define ASIZ_task_session	0x00000004
 #define AOFF_task_leader	0x000000cc
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_ngroups	0x000000d0
-#define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x000000d4
-#define ASIZ_task_groups	0x00000080
-#define AOFF_task_p_opptr	0x00000158
+#define AOFF_task_p_opptr	0x000000d0
 #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x00000160
+#define AOFF_task_p_pptr	0x000000d8
 #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x00000168
+#define AOFF_task_p_cptr	0x000000e0
 #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x00000170
+#define AOFF_task_p_ysptr	0x000000e8
 #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x00000178
+#define AOFF_task_p_osptr	0x000000f0
 #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x00000180
+#define AOFF_task_pidhash_next	0x000000f8
 #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x00000188
+#define AOFF_task_pidhash_pprev	0x00000100
 #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_tarray_ptr	0x00000190
+#define AOFF_task_tarray_ptr	0x00000108
 #define ASIZ_task_tarray_ptr	0x00000008
-#define AOFF_task_wait_chldexit	0x00000198
+#define AOFF_task_wait_chldexit	0x00000110
 #define ASIZ_task_wait_chldexit	0x00000008
-#define AOFF_task_uid	0x000001a0
-#define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000001a4
-#define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000001a8
-#define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000001ac
-#define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000001b0
-#define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000001b4
-#define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000001b8
-#define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000001bc
-#define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_timeout	0x000001c0
+#define AOFF_task_timeout	0x00000118
 #define ASIZ_task_timeout	0x00000008
-#define AOFF_task_policy	0x000001c8
+#define AOFF_task_policy	0x00000120
 #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x000001d0
+#define AOFF_task_rt_priority	0x00000128
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x000001d8
+#define AOFF_task_it_real_value	0x00000130
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x000001e0
+#define AOFF_task_it_prof_value	0x00000138
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x000001e8
+#define AOFF_task_it_virt_value	0x00000140
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x000001f0
+#define AOFF_task_it_real_incr	0x00000148
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x000001f8
+#define AOFF_task_it_prof_incr	0x00000150
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000200
+#define AOFF_task_it_virt_incr	0x00000158
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000208
+#define AOFF_task_real_timer	0x00000160
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000230
+#define AOFF_task_times	0x00000188
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000250
+#define AOFF_task_start_time	0x000001a8
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x00000258
+#define AOFF_task_per_cpu_utime	0x000001b0
 #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x00000458
+#define AOFF_task_min_flt	0x000003b0
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x00000460
+#define AOFF_task_maj_flt	0x000003b8
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x00000468
+#define AOFF_task_nswap	0x000003c0
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x00000470
+#define AOFF_task_cmin_flt	0x000003c8
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x00000478
+#define AOFF_task_cmaj_flt	0x000003d0
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x00000480
+#define AOFF_task_cnswap	0x000003d8
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_swap_address	0x00000490
+#define AOFF_task_swap_address	0x000003e8
 #define ASIZ_task_swap_address	0x00000008
-#define AOFF_task_old_maj_flt	0x00000498
+#define AOFF_task_old_maj_flt	0x000003f0
 #define ASIZ_task_old_maj_flt	0x00000008
-#define AOFF_task_dec_flt	0x000004a0
+#define AOFF_task_dec_flt	0x000003f8
 #define ASIZ_task_dec_flt	0x00000008
-#define AOFF_task_swap_cnt	0x000004a8
+#define AOFF_task_swap_cnt	0x00000400
 #define ASIZ_task_swap_cnt	0x00000008
-#define AOFF_task_rlim	0x000004b0
+#define AOFF_task_uid	0x00000408
+#define ASIZ_task_uid	0x00000004
+#define AOFF_task_euid	0x0000040c
+#define ASIZ_task_euid	0x00000004
+#define AOFF_task_suid	0x00000410
+#define ASIZ_task_suid	0x00000004
+#define AOFF_task_fsuid	0x00000414
+#define ASIZ_task_fsuid	0x00000004
+#define AOFF_task_gid	0x00000418
+#define ASIZ_task_gid	0x00000004
+#define AOFF_task_egid	0x0000041c
+#define ASIZ_task_egid	0x00000004
+#define AOFF_task_sgid	0x00000420
+#define ASIZ_task_sgid	0x00000004
+#define AOFF_task_fsgid	0x00000424
+#define ASIZ_task_fsgid	0x00000004
+#define AOFF_task_ngroups	0x00000428
+#define ASIZ_task_ngroups	0x00000004
+#define AOFF_task_groups	0x0000042c
+#define ASIZ_task_groups	0x00000080
+#define AOFF_task_cap_effective	0x000004ac
+#define ASIZ_task_cap_effective	0x00000004
+#define AOFF_task_cap_inheritable	0x000004b0
+#define ASIZ_task_cap_inheritable	0x00000004
+#define AOFF_task_cap_permitted	0x000004b4
+#define ASIZ_task_cap_permitted	0x00000004
+#define AOFF_task_rlim	0x000004b8
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000550
+#define AOFF_task_used_math	0x00000558
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_io_usage	0x00000558
-#define ASIZ_task_io_usage	0x00000008
-#define AOFF_task_comm	0x00000560
+#define AOFF_task_comm	0x0000055a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000570
+#define AOFF_task_link_count	0x0000056c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000578
+#define AOFF_task_tty	0x00000570
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000580
+#define AOFF_task_semundo	0x00000578
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000588
+#define AOFF_task_semsleeping	0x00000580
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_ldt	0x00000590
-#define ASIZ_task_ldt	0x00000008
-#define AOFF_task_tss	0x000005a0
+#define AOFF_task_tss	0x00000590
 #define ASIZ_task_tss	0x00000490
-#define AOFF_task_fs	0x00000a30
+#define AOFF_task_fs	0x00000a20
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x00000a38
+#define AOFF_task_files	0x00000a28
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x00000a40
+#define AOFF_task_mm	0x00000a30
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sig	0x00000a48
+#define AOFF_task_sig	0x00000a38
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x00000a50
+#define AOFF_task_signal	0x00000a40
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000a58
+#define AOFF_task_blocked	0x00000a48
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000a60
+#define AOFF_task_sigqueue	0x00000a50
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000a68
+#define AOFF_task_sigqueue_tail	0x00000a58
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_has_cpu	0x00000a70
+#define AOFF_task_has_cpu	0x00000a60
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000a74
+#define AOFF_task_processor	0x00000a64
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000a78
+#define AOFF_task_last_processor	0x00000a68
 #define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x00000a7c
+#define AOFF_task_lock_depth	0x00000a6c
 #define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_sigmask_lock	0x00000a80
+#define AOFF_task_sigmask_lock	0x00000a70
 #define ASIZ_task_sigmask_lock	0x00000001
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
@@ -479,6 +485,8 @@
 #define ASIZ_mm_def_flags	0x00000008
 #define AOFF_mm_cpu_vm_mask	0x000000b0
 #define ASIZ_mm_cpu_vm_mask	0x00000008
+#define AOFF_mm_segments	0x000000b8
+#define ASIZ_mm_segments	0x00000008
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_kpc	0x00000008
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/audioio.h linux/include/asm-sparc64/audioio.h
--- v2.1.100/linux/include/asm-sparc64/audioio.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/audioio.h	Fri May  8 00:11:36 1998
@@ -0,0 +1,409 @@
+/*
+ * include/asm-sparc/audioio.h
+ *
+ * Sparc Audio Midlayer
+ * Copyright (C) 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
+ */
+
+#ifndef _AUDIOIO_H_
+#define _AUDIOIO_H_
+
+/*
+ *	SunOS/Solaris /dev/audio interface
+ */
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/ioctl.h>
+
+/*
+ * This structure contains state information for audio device IO streams.
+ */
+typedef struct audio_prinfo {
+	/*
+	 * The following values describe the audio data encoding.
+	 */
+	unsigned int sample_rate;	/* samples per second */
+	unsigned int channels;	/* number of interleaved channels */
+	unsigned int precision;	/* bit-width of each sample */
+	unsigned int encoding;	/* data encoding method */
+
+	/*
+	 * The following values control audio device configuration
+	 */
+	unsigned int gain;		/* gain level: 0 - 255 */
+	unsigned int port;		/* selected I/O port (see below) */
+	unsigned int avail_ports;	/* available I/O ports (see below) */
+	unsigned int _xxx[2];		/* Reserved for future use */
+
+	unsigned int buffer_size;	/* I/O buffer size */
+
+	/*
+	 * The following values describe driver state
+	 */
+	unsigned int samples;		/* number of samples converted */
+	unsigned int eof;		/* End Of File counter (play only) */
+
+	unsigned char	pause;		/* non-zero for pause, zero to resume */
+	unsigned char	error;		/* non-zero if overflow/underflow */
+	unsigned char	waiting;	/* non-zero if a process wants access */
+	unsigned char balance;	/* stereo channel balance */
+
+	unsigned short minordev;
+
+	/*
+	 * The following values are read-only state flags
+	 */
+	unsigned char open;		/* non-zero if open access permitted */
+	unsigned char active;		/* non-zero if I/O is active */
+} audio_prinfo_t;
+
+
+/*
+ * This structure describes the current state of the audio device.
+ */
+typedef struct audio_info {
+	/*
+	 * Per-stream information
+	 */
+	audio_prinfo_t play;	/* output status information */
+	audio_prinfo_t record;	/* input status information */
+
+	/*
+	 * Per-unit/channel information
+	 */
+	unsigned int monitor_gain;	/* input to output mix: 0 - 255 */
+	unsigned char output_muted;	/* non-zero if output is muted */
+	unsigned char _xxx[3];	/* Reserved for future use */
+	unsigned int _yyy[3];		/* Reserved for future use */
+} audio_info_t;
+
+
+/*
+ * Audio encoding types
+ */
+#define	AUDIO_ENCODING_NONE	(0)	/* no encoding assigned	  */
+#define	AUDIO_ENCODING_ULAW	(1)	/* u-law encoding	  */
+#define	AUDIO_ENCODING_ALAW	(2)	/* A-law encoding	  */
+#define	AUDIO_ENCODING_LINEAR	(3)	/* Linear PCM encoding	  */
+#define	AUDIO_ENCODING_DVI	(104)	/* DVI ADPCM		  */
+#define	AUDIO_ENCODING_LINEAR8	(105)	/* 8 bit UNSIGNED	  */
+#define	AUDIO_ENCODING_LINEARLE	(106)	/* Linear PCM LE encoding */
+
+/*
+ * These ranges apply to record, play, and monitor gain values
+ */
+#define	AUDIO_MIN_GAIN	(0)	/* minimum gain value */
+#define	AUDIO_MAX_GAIN	(255)	/* maximum gain value */
+
+/*
+ * These values apply to the balance field to adjust channel gain values
+ */
+#define	AUDIO_LEFT_BALANCE	(0)	/* left channel only	*/
+#define	AUDIO_MID_BALANCE	(32)	/* equal left/right channel */
+#define	AUDIO_RIGHT_BALANCE	(64)	/* right channel only	*/
+#define	AUDIO_BALANCE_SHIFT	(3)
+
+/*
+ * Generic minimum/maximum limits for number of channels, both modes
+ */
+#define	AUDIO_MIN_PLAY_CHANNELS	(1)
+#define	AUDIO_MAX_PLAY_CHANNELS	(4)
+#define	AUDIO_MIN_REC_CHANNELS	(1)
+#define	AUDIO_MAX_REC_CHANNELS	(4)
+
+/*
+ * Generic minimum/maximum limits for sample precision
+ */
+#define	AUDIO_MIN_PLAY_PRECISION	(8)
+#define	AUDIO_MAX_PLAY_PRECISION	(32)
+#define	AUDIO_MIN_REC_PRECISION		(8)
+#define	AUDIO_MAX_REC_PRECISION		(32)
+
+/*
+ * Define some convenient names for typical audio ports
+ */
+/*
+ * output ports (several may be enabled simultaneously)
+ */
+#define	AUDIO_SPEAKER		0x01	/* output to built-in speaker */
+#define	AUDIO_HEADPHONE		0x02	/* output to headphone jack */
+#define	AUDIO_LINE_OUT		0x04	/* output to line out	 */
+
+/*
+ * input ports (usually only one at a time)
+ */
+#define	AUDIO_MICROPHONE	0x01	/* input from microphone */
+#define	AUDIO_LINE_IN		0x02	/* input from line in	 */
+#define	AUDIO_CD		0x04	/* input from on-board CD inputs */
+#define	AUDIO_INTERNAL_CD_IN	AUDIO_CD	/* input from internal CDROM */
+/* Supposedly an undocumented feature of the 4231 */
+#define AUDIO_ANALOG_LOOPBACK   0x40
+
+
+/*
+ * This macro initializes an audio_info structure to 'harmless' values.
+ * Note that (~0) might not be a harmless value for a flag that was
+ * a signed int.
+ */
+#define	AUDIO_INITINFO(i)	{					\
+	unsigned int	*__x__;						\
+	for (__x__ = (unsigned int *)(i);				\
+	    (char *) __x__ < (((char *)(i)) + sizeof (audio_info_t));	\
+	    *__x__++ = ~0);						\
+}
+
+/*
+ * These allow testing for what the user wants to set 
+ */
+#define AUD_INITVALUE   (~0)
+#define Modify(X)       ((unsigned int)(X) != AUD_INITVALUE)
+#define Modifys(X)      ((X) != (unsigned short)AUD_INITVALUE)
+#define Modifyc(X)      ((X) != (unsigned char)AUD_INITVALUE)
+
+/*
+ * Parameter for the AUDIO_GETDEV ioctl to determine current
+ * audio devices.
+ */
+#define	MAX_AUDIO_DEV_LEN	(16)
+typedef struct audio_device {
+	char name[MAX_AUDIO_DEV_LEN];
+	char version[MAX_AUDIO_DEV_LEN];
+	char config[MAX_AUDIO_DEV_LEN];
+} audio_device_t;
+
+
+/*
+ * Ioctl calls for the audio device.
+ */
+
+/*
+ * AUDIO_GETINFO retrieves the current state of the audio device.
+ *
+ * AUDIO_SETINFO copies all fields of the audio_info structure whose
+ * values are not set to the initialized value (-1) to the device state.
+ * It performs an implicit AUDIO_GETINFO to return the new state of the
+ * device.  Note that the record.samples and play.samples fields are set
+ * to the last value before the AUDIO_SETINFO took effect.  This allows
+ * an application to reset the counters while atomically retrieving the
+ * last value.
+ *
+ * AUDIO_DRAIN suspends the calling process until the write buffers are
+ * empty.
+ *
+ * AUDIO_GETDEV returns a structure of type audio_device_t which contains
+ * three strings.  The string "name" is a short identifying string (for
+ * example, the SBus Fcode name string), the string "version" identifies
+ * the current version of the device, and the "config" string identifies
+ * the specific configuration of the audio stream.  All fields are
+ * device-dependent -- see the device specific manual pages for details.
+ *
+ * AUDIO_GETDEV_SUNOS returns a number which is an audio device defined 
+ * herein (making it not too portable)
+ *
+ * AUDIO_FLUSH stops all playback and recording, clears all queued buffers, 
+ * resets error counters, and restarts recording and playback as appropriate
+ * for the current sampling mode.
+ */
+#define	AUDIO_GETINFO	_IOR('A', 1, audio_info_t)
+#define	AUDIO_SETINFO	_IOWR('A', 2, audio_info_t)
+#define	AUDIO_DRAIN	_IO('A', 3)
+#define	AUDIO_GETDEV	_IOR('A', 4, audio_device_t)
+#define	AUDIO_GETDEV_SUNOS	_IOR('A', 4, int)
+#define AUDIO_FLUSH     _IO('A', 5)
+
+/* Define possible audio hardware configurations for 
+ * old SunOS-style AUDIO_GETDEV ioctl */
+#define AUDIO_DEV_UNKNOWN       (0)     /* not defined */
+#define AUDIO_DEV_AMD           (1)     /* audioamd device */
+#define AUDIO_DEV_SPEAKERBOX    (2)     /* dbri device with speakerbox */
+#define AUDIO_DEV_CODEC         (3)     /* dbri device (internal speaker) */
+#define AUDIO_DEV_CS4231        (5)     /* cs4231 device */
+
+/*
+ * The following ioctl sets the audio device into an internal loopback mode,
+ * if the hardware supports this.  The argument is TRUE to set loopback,
+ * FALSE to reset to normal operation.  If the hardware does not support
+ * internal loopback, the ioctl should fail with EINVAL.
+ */
+#define	AUDIO_DIAG_LOOPBACK	_IOW('A', 101, int)
+
+#ifdef notneeded
+/*
+ * Structure sent up as a M_PROTO message on trace streams
+ */
+typedef struct audtrace_hdr audtrace_hdr_t;
+struct audtrace_hdr {
+	unsigned int seq;		/* Sequence number (per-aud_stream) */
+	int type;		/* device-dependent */
+	struct timeval timestamp;
+	char _f[8];		/* filler */
+};
+#endif
+
+/*
+ *	Linux kernel internal implementation.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/tqueue.h>
+#include <linux/wait.h>
+
+#define	SDF_OPEN_WRITE	0x00000001
+#define	SDF_OPEN_READ	0x00000002
+
+struct sparcaudio_driver
+{
+	const char * name;
+	struct sparcaudio_operations *ops;
+	void *private;
+	unsigned long flags;
+
+	/* Processes blocked on open() sit here. */
+	struct wait_queue *open_wait;
+
+	/* Task queue for this driver's bottom half. */
+	struct tq_struct tqueue;
+
+	/* Support for a circular queue of output buffers. */
+	__u8 **output_buffers;
+	size_t *output_sizes, output_size;
+	int num_output_buffers, output_front, output_rear;
+	int output_count, output_active, playing_count;
+	struct wait_queue *output_write_wait, *output_drain_wait;
+
+        /* Support for a circular queue of input buffers. */
+        __u8 **input_buffers;
+        int input_offset;
+        int num_input_buffers, input_front, input_rear;
+        int input_count, input_active, recording_count;
+        struct wait_queue *input_read_wait;
+};
+
+struct sparcaudio_operations
+{
+	int (*open)(struct inode *, struct file *, struct sparcaudio_driver *);
+	void (*release)(struct inode *, struct file *, struct sparcaudio_driver *);
+	int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long,
+		     struct sparcaudio_driver *);
+
+	/* Ask driver to begin playing a buffer. */
+	void (*start_output)(struct sparcaudio_driver *, __u8 *, unsigned long);
+
+	/* Ask driver to stop playing a buffer. */
+	void (*stop_output)(struct sparcaudio_driver *);
+
+	/* Ask driver to begin recording into a buffer. */
+	void (*start_input)(struct sparcaudio_driver *, __u8 *, unsigned long);
+
+	/* Ask driver to stop recording. */
+	void (*stop_input)(struct sparcaudio_driver *);
+
+	/* Return driver name/version to caller. (/dev/audio specific) */
+	void (*sunaudio_getdev)(struct sparcaudio_driver *, audio_device_t *);
+
+        /* Get and set the output volume. (0-255) */
+        int (*set_output_volume)(struct sparcaudio_driver *, int);
+        int (*get_output_volume)(struct sparcaudio_driver *);
+
+        /* Get and set the input volume. (0-255) */
+        int (*set_input_volume)(struct sparcaudio_driver *, int);
+        int (*get_input_volume)(struct sparcaudio_driver *);
+
+        /* Get and set the monitor volume. (0-255) */
+        int (*set_monitor_volume)(struct sparcaudio_driver *, int);
+        int (*get_monitor_volume)(struct sparcaudio_driver *);
+
+        /* Get and set the output balance. (0-64) */
+        int (*set_output_balance)(struct sparcaudio_driver *, int);
+        int (*get_output_balance)(struct sparcaudio_driver *);
+
+        /* Get and set the input balance. (0-64) */
+        int (*set_input_balance)(struct sparcaudio_driver *, int);
+        int (*get_input_balance)(struct sparcaudio_driver *);
+
+        /* Get and set the output channels. (1-4) */
+        int (*set_output_channels)(struct sparcaudio_driver *, int);
+        int (*get_output_channels)(struct sparcaudio_driver *);
+
+        /* Get and set the input channels. (1-4) */
+        int (*set_input_channels)(struct sparcaudio_driver *, int);
+        int (*get_input_channels)(struct sparcaudio_driver *);
+
+        /* Get and set the output precision. (8-32) */
+        int (*set_output_precision)(struct sparcaudio_driver *, int);
+        int (*get_output_precision)(struct sparcaudio_driver *);
+
+        /* Get and set the input precision. (8-32) */
+        int (*set_input_precision)(struct sparcaudio_driver *, int);
+        int (*get_input_precision)(struct sparcaudio_driver *);
+
+        /* Get and set the output port. () */
+        int (*set_output_port)(struct sparcaudio_driver *, int);
+        int (*get_output_port)(struct sparcaudio_driver *);
+
+        /* Get and set the input port. () */
+        int (*set_input_port)(struct sparcaudio_driver *, int);
+        int (*get_input_port)(struct sparcaudio_driver *);
+
+        /* Get and set the output encoding. () */
+        int (*set_output_encoding)(struct sparcaudio_driver *, int);
+        int (*get_output_encoding)(struct sparcaudio_driver *);
+
+        /* Get and set the input encoding. () */
+        int (*set_input_encoding)(struct sparcaudio_driver *, int);
+        int (*get_input_encoding)(struct sparcaudio_driver *);
+
+        /* Get and set the output rate. () */
+        int (*set_output_rate)(struct sparcaudio_driver *, int);
+        int (*get_output_rate)(struct sparcaudio_driver *);
+
+        /* Get and set the input rate. () */
+        int (*set_input_rate)(struct sparcaudio_driver *, int);
+        int (*get_input_rate)(struct sparcaudio_driver *);
+
+	/* Return driver number to caller. (SunOS /dev/audio specific) */
+	int (*sunaudio_getdev_sunos)(struct sparcaudio_driver *);
+
+        /* Get available ports */
+        int (*get_output_ports)(struct sparcaudio_driver *);
+        int (*get_input_ports)(struct sparcaudio_driver *);
+
+        /* Get and set output mute */
+        int (*set_output_muted)(struct sparcaudio_driver *, int);
+        int (*get_output_muted)(struct sparcaudio_driver *);
+};
+
+extern int register_sparcaudio_driver(struct sparcaudio_driver *);
+extern int unregister_sparcaudio_driver(struct sparcaudio_driver *);
+extern void sparcaudio_output_done(struct sparcaudio_driver *, int);
+extern void sparcaudio_input_done(struct sparcaudio_driver *);
+extern int sparcaudio_init(void);
+extern int amd7930_init(void);
+extern int cs4231_init(void);
+
+#endif
+
+/* Macros to convert between mixer stereo volumes and gain (mono) */
+#define s_to_m(a) (((((a) >> 8) & 0x7f) + ((a) & 0x7f)) / 2)
+#define m_to_s(a) (((a) << 8) + (a))
+
+/* convert mixer stereo volume to balance */
+#define s_to_b(a) (AUDIO_RIGHT_BALANCE * ((((a) >> 8) & 0xff) /  (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2)))
+
+/* convert mixer stereo volume to audio gain */
+#define s_to_g(a) (((((a) >> 8) & 0xff) + ((a) & 0xff)) / 2)
+
+/* convert gain a and balance b to mixer volume */
+#define b_to_s(a,b) ((a * (b / AUDIO_RIGHT_BALANCE) << 8) + (a * (1 - (b / AUDIO_RIGHT_BALANCE))))
+
+#define SPARCAUDIO_MIXER_MINOR 0
+#define SPARCAUDIO_DSP16_MINOR 1
+#define SPARCAUDIO_DSP_MINOR   3
+#define SPARCAUDIO_AUDIO_MINOR 4
+#define SPARCAUDIO_AUDIOCTL_MINOR 5
+#define SPARCAUDIO_STATUS_MINOR 6
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/dma.h linux/include/asm-sparc64/dma.h
--- v2.1.100/linux/include/asm-sparc64/dma.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/dma.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.7 1997/04/10 05:13:28 davem Exp $
+/* $Id: dma.h,v 1.8 1998/04/13 07:27:06 davem Exp $
  * include/asm-sparc64/dma.h
  *
  * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
@@ -74,7 +74,7 @@
 #define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
 
 /* Main routines in dma.c */
-extern unsigned long dvma_init(struct linux_sbus *, unsigned long);
+extern void dvma_init(struct linux_sbus *);
 
 /* Fields in the cond_reg register */
 /* First, the version identification bits */
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/ebus.h linux/include/asm-sparc64/ebus.h
--- v2.1.100/linux/include/asm-sparc64/ebus.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/ebus.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: ebus.h,v 1.5 1998/03/15 10:14:46 ecd Exp $
+/* $Id: ebus.h,v 1.6 1998/04/13 07:27:07 davem Exp $
  * ebus.h: PCI to Ebus pseudo driver software state.
  *
  * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
@@ -82,7 +82,7 @@
 
 extern struct linux_ebus		*ebus_chain;
 
-extern unsigned long ebus_init(unsigned long, unsigned long);
+extern void ebus_init(void);
 
 #define for_each_ebus(bus)						\
         for((bus) = ebus_chain; (bus); (bus) = (bus)->next)
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.1.100/linux/include/asm-sparc64/ide.h	Thu May  7 22:51:54 1998
+++ linux/include/asm-sparc64/ide.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.6 1998/03/15 13:29:13 ecd Exp $
+/* $Id: ide.h,v 1.8 1998/04/23 05:04:14 davem Exp $
  * ide.h: Ultra/PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -97,24 +97,43 @@
 
 /* From m68k code... */
 
+#ifdef insl
+#undef insl
+#endif
+#ifdef outsl
+#undef outsl
+#endif
+#ifdef insw
+#undef insw
+#endif
+#ifdef outsw
+#undef outsw
+#endif
+
 #define insl(data_reg, buffer, wcount) insw(data_reg, buffer, (wcount)<<1)
 #define outsl(data_reg, buffer, wcount) outsw(data_reg, buffer, (wcount)<<1)
 
 #define insw(port, buf, nr) ide_insw((port), (buf), (nr))
 #define outsw(port, buf, nr) ide_outsw((port), (buf), (nr))
 
+/* We need to use L1 cache bypassing to prevent dcache alias
+ * inconsistencies with user space.  -DaveM
+ */
 static __inline__ void ide_insw(unsigned long port,
 				void *dst,
 				unsigned long count)
 {
 	volatile unsigned short *data_port;
-	u16 *ps = dst;
+	u16 *ps = (u16 *)__pa(dst);
 	u32 *pi;
 
 	data_port = (volatile unsigned short *)port;
 
 	if(((u64)ps) & 0x2) {
-		*ps++ = *data_port;
+		__asm__ __volatile__("stha %0, [%1] %2"
+				     : /* no outputs */
+				     : "r" (*data_port), "r" (ps++),
+				       "i" (ASI_PHYS_USE_EC));
 		count--;
 	}
 	pi = (u32 *)ps;
@@ -123,12 +142,18 @@
 
 		w  = (*data_port) << 16;
 		w |= (*data_port);
-		*pi++ = w;
+		__asm__ __volatile__("stwa %0, [%1] %2"
+				     : /* no outputs */
+				     : "r" (w), "r" (pi++),
+				       "i" (ASI_PHYS_USE_EC));
 		count -= 2;
 	}
 	ps = (u16 *)pi;
 	if(count)
-		*ps = *data_port;
+		__asm__ __volatile__("stha %0, [%1] %2"
+				     : /* no outputs */
+				     : "r" (*data_port), "r" (ps),
+				       "i" (ASI_PHYS_USE_EC));
 }
 
 static __inline__ void ide_outsw(unsigned long port,
@@ -136,27 +161,37 @@
 				 unsigned long count)
 {
 	volatile unsigned short *data_port;
-	const u16 *ps = src;
+	const u16 *ps = (const u16 *)__pa(src);
 	const u32 *pi;
 
 	data_port = (volatile unsigned short *)port;
 
 	if(((u64)src) & 0x2) {
-		*data_port = *ps++;
+		u16 w;
+		__asm__ __volatile__("lduha [%1] %2, %0"
+				     : "=r" (w)
+				     : "r" (ps++), "i" (ASI_PHYS_USE_EC));
+		*data_port = w;
 		count--;
 	}
 	pi = (const u32 *)ps;
 	while(count >= 2) {
 		u32 w;
-
-		w = *pi++;
+		__asm__ __volatile__("lduwa [%1] %2, %0"
+				     : "=r" (w)
+				     : "r" (pi++), "i" (ASI_PHYS_USE_EC));
 		*data_port = (w >> 16);
 		*data_port = w;
 		count -= 2;
 	}
 	ps = (const u16 *)pi;
-	if(count)
-		*data_port = *ps;
+	if(count) {
+		u16 w;
+		__asm__ __volatile__("lduha [%1] %2, %0"
+				     : "=r" (w)
+				     : "r" (ps++), "i" (ASI_PHYS_USE_EC));
+		*data_port = w;
+	}
 }
 
 #define T_CHAR          (0x0000)        /* char:  don't touch  */
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h
--- v2.1.100/linux/include/asm-sparc64/irq.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/irq.h	Fri May  8 00:11:36 1998
@@ -76,9 +76,4 @@
 	return retval;
 }
 
-static __inline__ int irq_cannonicalize(int irq)
-{
-	return irq;
-}
-
 #endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.1.100/linux/include/asm-sparc64/mmu_context.h	Thu May  7 22:51:54 1998
+++ linux/include/asm-sparc64/mmu_context.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.20 1997/09/18 10:42:08 rth Exp $ */
+/* $Id: mmu_context.h,v 1.24 1998/05/06 02:07:54 paulus Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -6,38 +6,35 @@
 
 #include <asm/system.h>
 #include <asm/spitfire.h>
+#include <asm/spinlock.h>
 
 #define NO_CONTEXT     0
 
 #ifndef __ASSEMBLY__
 
 extern unsigned long tlb_context_cache;
+extern spinlock_t scheduler_lock;
+extern unsigned long mmu_context_bmap[];
 
-#define CTX_VERSION_SHIFT	PAGE_SHIFT
+#define CTX_VERSION_SHIFT	(PAGE_SHIFT - 3)
 #define CTX_VERSION_MASK	((~0UL) << CTX_VERSION_SHIFT)
 #define CTX_FIRST_VERSION	((1UL << CTX_VERSION_SHIFT) + 1UL)
 
-extern void get_new_mmu_context(struct mm_struct *mm, unsigned long *ctx);
+extern void get_new_mmu_context(struct mm_struct *mm);
 
 /* Initialize/destroy the context related info for a new mm_struct
  * instance.
  */
 #define init_new_context(mm)	((mm)->context = NO_CONTEXT)
-#define destroy_context(mm)	((mm)->context = NO_CONTEXT)
-
-#ifdef __SMP__
-#define LOCAL_FLUSH_PENDING(cpu)	\
-	((cpu_data[(cpu)].last_tlbversion_seen ^ tlb_context_cache) & CTX_VERSION_MASK)
-#define DO_LOCAL_FLUSH(cpu)		do { __flush_tlb_all();				\
-					     cpu_data[cpu].last_tlbversion_seen =	\
-					     tlb_context_cache & CTX_VERSION_MASK;	\
-					} while(0)
-#else
-#define LOCAL_FLUSH_PENDING(cpu)	0
-#define DO_LOCAL_FLUSH(cpu)		do { __flush_tlb_all(); } while(0)
-#endif
-
-extern void __flush_tlb_all(void);
+#define destroy_context(mm)	do { 								\
+	if ((mm)->context != NO_CONTEXT) { 							\
+		spin_lock(&scheduler_lock); 							\
+		if (!(((mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK))			\
+			clear_bit((mm)->context & ~(CTX_VERSION_MASK), mmu_context_bmap);	\
+		spin_unlock(&scheduler_lock); 							\
+		(mm)->context = NO_CONTEXT; 							\
+	} 											\
+} while (0)
 
 extern __inline__ void get_mmu_context(struct task_struct *tsk)
 {
@@ -45,18 +42,22 @@
 	struct mm_struct *mm = tsk->mm;
 
 	flushw_user();
-	if(LOCAL_FLUSH_PENDING(current->processor))
-		DO_LOCAL_FLUSH(current->processor);
 	if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD)	&&
 	   !(tsk->flags & PF_EXITING)) {
 		unsigned long ctx = tlb_context_cache;
 		if((mm->context ^ ctx) & CTX_VERSION_MASK)
-			get_new_mmu_context(mm, &tlb_context_cache);
-
+			get_new_mmu_context(mm);
+		if(!(mm->cpu_vm_mask & (1UL<<smp_processor_id()))) {
+			spitfire_set_secondary_context(mm->context & 0x3ff);
+			__asm__ __volatile__("flush %g6");
+			spitfire_flush_dtlb_secondary_context();
+			spitfire_flush_itlb_secondary_context();
+			__asm__ __volatile__("flush %g6");
+		}
 		/* Don't worry, set_fs() will restore it... */
 		/* Sigh, damned include loops... just poke seg directly.  */
 		tsk->tss.ctx = (tsk->tss.current_ds.seg ?
-				(mm->context & 0x1fff) : 0);
+				(mm->context & 0x3ff) : 0);
 	} else
 		tsk->tss.ctx = 0;
 	spitfire_set_secondary_context(tsk->tss.ctx);
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/page.h linux/include/asm-sparc64/page.h
--- v2.1.100/linux/include/asm-sparc64/page.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/page.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.17 1998/01/14 17:16:28 jj Exp $ */
+/* $Id: page.h,v 1.18 1998/05/01 09:33:50 davem Exp $ */
 
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
@@ -13,10 +13,62 @@
 
 #define PAGE_MASK    (~(PAGE_SIZE-1))
 
+
 #ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 
+#define PAGE_ALIAS_BITS		(PAGE_SIZE)	/* 16K Dcache, 8K pages */
+#ifdef __SMP__
+#define ULOCK_DECLARE extern spinlock_t user_page_lock;
+#else
+#define ULOCK_DECLARE
+#endif
+struct upcache {
+	struct page *list;
+	unsigned long count;
+};
+extern struct upcache user_page_cache[2];
+#define USER_PAGE_WATER		16
+
+extern unsigned long get_user_page_slow(int which);
+#define get_user_page(__vaddr) \
+({ \
+	ULOCK_DECLARE \
+	int which = ((__vaddr) & PAGE_ALIAS_BITS) ? 1 : 0; \
+	struct upcache *up = &user_page_cache[which]; \
+	struct page *p; \
+	unsigned long ret; \
+	spin_lock(&user_page_lock); \
+	if((p = up->list) != NULL) { \
+		up->list = p->next; \
+		up->count--; \
+	} \
+	spin_unlock(&user_page_lock); \
+	if(p != NULL) \
+		ret = PAGE_OFFSET+PAGE_SIZE*p->map_nr; \
+	else \
+		ret = get_user_page_slow(which); \
+	ret; \
+})
+
+#define free_user_page(__page, __addr) \
+do { \
+	ULOCK_DECLARE \
+	int which = ((__addr) & PAGE_ALIAS_BITS) ? 1 : 0; \
+	struct upcache *up = &user_page_cache[which]; \
+	if(atomic_read(&(__page)->count) == 1 && \
+           up->count < USER_PAGE_WATER) { \
+		spin_lock(&user_page_lock); \
+		(__page)->age = PAGE_INITIAL_AGE; \
+		(__page)->next = up->list; \
+		up->list = (__page); \
+		up->count++; \
+		spin_unlock(&user_page_lock); \
+	} else \
+		free_page(addr); \
+} while(0)
+
 #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
 
 extern void copy_page(unsigned long to, unsigned long from);
@@ -81,9 +133,15 @@
 
 #endif /* (STRICT_MM_TYPECHECKS) */
 
-#define TASK_UNMAPPED_BASE	((current->tss.flags & SPARC_FLAG_32BIT) ? \
-				 (0x0000000070000000UL) : \
-				 (0xfffff80000000000UL))
+#define TASK_UNMAPPED_BASE(__off)	(((current->tss.flags & SPARC_FLAG_32BIT) ? \
+				 	 (0x0000000070000000UL) : \
+				 	 (0xfffff80000000000UL)) + \
+					 (__off & PAGE_SIZE))
+
+/* On Ultra this aligns to the size of the L1 cache. */
+#define TASK_UNMAPPED_ALIGN(__addr, __off) \
+	((((__addr)+((PAGE_SIZE<<1UL)-1UL)) & ~((PAGE_SIZE << 1UL)-1UL)) + \
+	 (__off&PAGE_SIZE))
 
 #endif /* !(__ASSEMBLY__) */
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h
--- v2.1.100/linux/include/asm-sparc64/pbm.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/pbm.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: pbm.h,v 1.12 1998/04/10 12:29:55 ecd Exp $
+/* $Id: pbm.h,v 1.13 1998/04/20 07:15:11 ecd Exp $
  * pbm.h: U2P PCI bus module pseudo driver software state.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -90,20 +90,21 @@
  * irq registry layer, there is already enough crap in there due to sbus,
  * fhc, and dcookies.
  */
-#define PCI_IRQ_IDENT		0x80000000	/* This tells irq.c what we are        */
-#define PCI_IRQ_IMAP_OFF	0x7ff00000	/* Offset from first PSYCHO imap       */
+#define PCI_IRQ_IDENT		0x80000000	/* This tells irq.c what we are       */
+#define PCI_IRQ_IMAP_OFF	0x7ff00000	/* Offset from first PSYCHO imap      */
 #define PCI_IRQ_IMAP_OFF_SHFT	20
-#define PCI_IRQ_BUSNO		0x000fc000	/* PSYCHO instance                     */
+#define PCI_IRQ_BUSNO		0x000fc000	/* PSYCHO instance                    */
 #define PCI_IRQ_BUSNO_SHFT	14
-#define PCI_IRQ_IGN		0x000007c0	/* PSYCHO "Int Group Number"           */
-#define PCI_IRQ_INO		0x0000003f	/* PSYCHO INO                          */
+#define PCI_IRQ_DMA_SYNC	0x00001000	/* IRQ needs DMA sync for APB	      */
+#define PCI_IRQ_IGN		0x000007c0	/* PSYCHO "Int Group Number"          */
+#define PCI_IRQ_INO		0x0000003f	/* PSYCHO INO                         */
 
 #define PCI_IRQ_P(__irq)	(((__irq) & PCI_IRQ_IDENT) != 0)
 
 extern __inline__ unsigned int pci_irq_encode(unsigned long imap_off,
 					      unsigned long psycho_instance,
 					      unsigned long ign,
-					      unsigned long ino)
+					      unsigned long ino, int dma_sync)
 {
 	unsigned int irq;
 
@@ -112,8 +113,14 @@
 	irq |= ((psycho_instance << PCI_IRQ_BUSNO_SHFT) & PCI_IRQ_BUSNO);
 	irq |= ((ign << 6) & PCI_IRQ_IGN);
 	irq |= (ino & PCI_IRQ_INO);
+	irq |= dma_sync ? PCI_IRQ_DMA_SYNC : 0;
 
 	return irq;
 }
+
+/* Used by EBus */
+extern unsigned int psycho_irq_build(struct linux_pbm_info *pbm,
+				     struct pci_dev *pdev,
+				     unsigned int full_ino);
 
 #endif /* !(__SPARC64_PBM_H) */
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.1.100/linux/include/asm-sparc64/pgtable.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/pgtable.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.64 1998/02/16 14:06:44 jj Exp $
+/* $Id: pgtable.h,v 1.67 1998/05/01 09:33:53 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -186,14 +186,14 @@
 extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
 {
 	if(mm->context != NO_CONTEXT)
-		__flush_tlb_mm(mm->context & 0x1fff);
+		__flush_tlb_mm(mm->context & 0x3ff);
 }
 
 extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start,
 				       unsigned long end)
 {
 	if(mm->context != NO_CONTEXT)
-		__flush_tlb_range(mm->context & 0x1fff, start, end);
+		__flush_tlb_range(mm->context & 0x3ff, start, end);
 }
 
 extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -201,7 +201,7 @@
 	struct mm_struct *mm = vma->vm_mm;
 
 	if(mm->context != NO_CONTEXT)
-		__flush_tlb_page(mm->context & 0x1fff, page & PAGE_MASK);
+		__flush_tlb_page(mm->context & 0x3ff, page & PAGE_MASK);
 }
 
 #else /* __SMP__ */
@@ -355,28 +355,73 @@
 	unsigned long *pmd_cache;
 	unsigned long *pte_cache;
 	unsigned long pgcache_size;
+	unsigned long pgdcache_size;
 } pgt_quicklists;
 #endif
 #define pgd_quicklist		(pgt_quicklists.pgd_cache)
 #define pmd_quicklist		(pgt_quicklists.pmd_cache)
 #define pte_quicklist		(pgt_quicklists.pte_cache)
 #define pgtable_cache_size	(pgt_quicklists.pgcache_size)
+#define pgd_cache_size		(pgt_quicklists.pgdcache_size)
 
-extern pgd_t *get_pgd_slow(void);
+extern __inline__ void __init_pgd(pgd_t *pgdp)
+{
+	extern void __bfill64(void *, unsigned long *);
+	extern unsigned long two_null_pmd_table;
+	
+	__bfill64((void *)pgdp, &two_null_pmd_table);
+}
+
+#ifndef __SMP__
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+	struct page *page = mem_map + MAP_NR(pgd);
+
+	if (!page->pprev_hash) {
+		(unsigned long *)page->next_hash = pgd_quicklist;
+		pgd_quicklist = (unsigned long *)page;
+	}
+	(unsigned long)page->pprev_hash |= (((unsigned long)pgd & (PAGE_SIZE / 2)) ? 2 : 1);
+	pgd_cache_size++;
+}
 
 extern __inline__ pgd_t *get_pgd_fast(void)
 {
-	unsigned long *ret;
+        struct page *ret;
 
-	if((ret = pgd_quicklist) != NULL) {
-		pgd_quicklist = (unsigned long *)(*ret);
-		ret[0] = ret[1];
-		pgtable_cache_size--;
-	} else
-		ret = (unsigned long *)get_pgd_slow();
-	return (pgd_t *)ret;
+        if ((ret = (struct page *)pgd_quicklist) != NULL) {
+                unsigned long mask = (unsigned long)ret->pprev_hash;
+		unsigned long off = 0;
+
+		if (mask & 1)
+			mask &= ~1;
+		else {
+			off = PAGE_SIZE / 2;
+			mask &= ~2;
+		}
+		(unsigned long)ret->pprev_hash = mask;
+		if (!mask)
+			pgd_quicklist = (unsigned long *)ret->next_hash;
+                ret = (struct page *)(PAGE_OFFSET + (ret->map_nr << PAGE_SHIFT) + off);
+                pgd_cache_size--;
+        } else {
+		ret = (struct page *) __get_free_page(GFP_KERNEL);
+		if(ret) {
+			struct page *page = mem_map + MAP_NR(ret);
+			
+			__init_pgd((pgd_t *)ret);
+			(unsigned long)page->pprev_hash = 2;
+			(unsigned long *)page->next_hash = pgd_quicklist;
+			pgd_quicklist = (unsigned long *)page;
+			pgd_cache_size++;
+		}
+        }
+        return (pgd_t *)ret;
 }
 
+#else /* __SMP__ */
+
 extern __inline__ void free_pgd_fast(pgd_t *pgd)
 {
 	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
@@ -384,6 +429,23 @@
 	pgtable_cache_size++;
 }
 
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+	unsigned long *ret;
+
+	if((ret = pgd_quicklist) != NULL) {
+		pgd_quicklist = (unsigned long *)(*ret);
+		ret[0] = ret[1];
+		pgtable_cache_size--;
+	} else {
+		ret = (unsigned long *) __get_free_page(GFP_KERNEL);
+		if(ret)
+			__init_pgd((pgd_t *)ret);
+	}
+	return (pgd_t *)ret;
+}
+#endif /* __SMP__ */
+
 extern __inline__ void free_pgd_slow(pgd_t *pgd)
 {
 	free_page((unsigned long)pgd);
@@ -530,7 +592,7 @@
 					unsigned long address, pte_t pte)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	unsigned long ctx = mm->context & 0x1fff;
+	unsigned long ctx = mm->context & 0x3ff;
 	unsigned long tag_access;
 
 	tag_access = address | ctx;
@@ -549,7 +611,7 @@
 2:
 	wrpr	%%g1, 0x0, %%pstate
 "	: /* no outputs */
-	: "i" (PSTATE_IE), "r" (vma->vm_flags & VM_EXEC),
+	: "i" (PSTATE_IE), "r" (vma->vm_flags & VM_EXECUTABLE),
 	  "i" (TLB_TAG_ACCESS), "r" (tag_access), "r" (pte_val(pte)),
 	  "i" (ASI_IMMU), "i" (ASI_ITLB_DATA_IN),
 	  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_IN)
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.1.100/linux/include/asm-sparc64/processor.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/processor.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.42 1998/01/28 10:00:04 ecd Exp $
+/* $Id: processor.h,v 1.43 1998/04/23 08:26:30 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -205,6 +205,9 @@
 
 /* Free all resources held by a thread. */
 #define release_thread(tsk)		do { } while(0)
+
+#define copy_segments(nr, tsk, mm)	do { } while (0)
+#define release_segments(mm)		do { } while (0)
 
 #ifdef __KERNEL__
 /* Allocation and freeing of task_struct and kernel stack. */
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h
--- v2.1.100/linux/include/asm-sparc64/smp.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/smp.h	Fri May  8 00:11:36 1998
@@ -36,8 +36,8 @@
 	unsigned long	irq_count;
 	unsigned int	multiplier;
 	unsigned int	counter;
-	unsigned long	last_tlbversion_seen;
 	unsigned long	pgcache_size;
+	unsigned long	pgdcache_size;
 
 	/* Dcache line 2 */
 	unsigned long	*pgd_cache;
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/spitfire.h linux/include/asm-sparc64/spitfire.h
--- v2.1.100/linux/include/asm-sparc64/spitfire.h	Sat May 24 09:10:25 1997
+++ linux/include/asm-sparc64/spitfire.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: spitfire.h,v 1.8 1997/05/18 04:16:56 davem Exp $
+/* $Id: spitfire.h,v 1.9 1998/04/28 08:23:33 davem Exp $
  * spitfire.h: SpitFire/BlackBird/Cheetah inline MMU operations.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -85,7 +85,7 @@
 {
 	__asm__ __volatile__("stxa	%0, [%1] %2"
 			     : /* No outputs */
-			     : "r" (ctx & 0x1fff),
+			     : "r" (ctx & 0x3ff),
 			       "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU));
 	membar("#Sync");
 }
@@ -104,7 +104,7 @@
 {
 	__asm__ __volatile__("stxa	%0, [%1] %2"
 			     : /* No outputs */
-			     : "r" (ctx & 0x1fff),
+			     : "r" (ctx & 0x3ff),
 			       "r" (SECONDARY_CONTEXT), "i" (ASI_DMMU));
 	membar("#Sync");
 }
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- v2.1.100/linux/include/asm-sparc64/system.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/system.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.38 1998/01/30 11:00:11 jj Exp $ */
+/* $Id: system.h,v 1.39 1998/05/01 09:33:55 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
@@ -43,10 +43,10 @@
 	__asm__ __volatile__("wrpr	0, %%pil" : : : "memory")
 
 #define getipl() \
-({ int retval; __asm__ __volatile__("rdpr	%%pil, %0" : "=r" (retval)); retval; })
+({ unsigned long retval; __asm__ __volatile__("rdpr	%%pil, %0" : "=r" (retval)); retval; })
 
 #define swap_pil(__new_pil) \
-({	int retval; \
+({	unsigned long retval; \
 	__asm__ __volatile__("rdpr	%%pil, %0\n\t" \
 			     "wrpr	%1, %%pil" \
 			     : "=r" (retval) \
@@ -56,7 +56,7 @@
 })
 
 #define read_pil_and_cli() \
-({	int retval; \
+({	unsigned long retval; \
 	__asm__ __volatile__("rdpr	%%pil, %0\n\t" \
 			     "wrpr	15, %%pil" \
 			     : "=r" (retval) \
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.1.100/linux/include/asm-sparc64/termios.h	Wed Apr  8 19:36:29 1998
+++ linux/include/asm-sparc64/termios.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.4 1997/03/14 21:05:26 jj Exp $ */
+/* $Id: termios.h,v 1.5 1998/04/12 06:27:22 davem Exp $ */
 #ifndef _SPARC64_TERMIOS_H
 #define _SPARC64_TERMIOS_H
 
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/timex.h linux/include/asm-sparc64/timex.h
--- v2.1.100/linux/include/asm-sparc64/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/timex.h	Thu May  7 23:53:35 1998
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-sparc64/timex.h
+ *
+ * sparc64 architecture timex specifications
+ */
+#ifndef _ASMsparc64_TIMEX_H
+#define _ASMsparc64_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#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)
+
+#endif
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.1.100/linux/include/asm-sparc64/uaccess.h	Mon Jan 12 15:15:58 1998
+++ linux/include/asm-sparc64/uaccess.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.24 1997/12/15 15:05:14 jj Exp $ */
+/* $Id: uaccess.h,v 1.25 1998/04/28 08:23:34 davem Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
@@ -52,7 +52,7 @@
 			flushw_user ();						\
 			current->tss.ctx = 0;					\
 		} else {							\
-			current->tss.ctx = (current->mm->context & 0x1fff);	\
+			current->tss.ctx = (current->mm->context & 0x3ff);	\
 		}								\
 		spitfire_set_secondary_context(current->tss.ctx); 		\
 		__asm__ __volatile__("flush %g6");				\
diff -u --recursive --new-file v2.1.100/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.1.100/linux/include/asm-sparc64/unistd.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/unistd.h	Fri May  8 00:11:36 1998
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.17 1998/03/29 12:57:54 ecd Exp $ */
+/* $Id: unistd.h,v 1.18 1998/04/14 13:50:01 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -135,7 +135,7 @@
 #define __NR_gettimeofday       116 /* Common                                      */
 #define __NR_getrusage          117 /* Common                                      */
 #define __NR_getsockopt         118 /* Common                                      */
-/* #define __NR_ni_syscall      119    ENOSYS under SunOS                          */
+#define __NR_getcwd		119 /* Linux Specific				   */
 #define __NR_readv              120 /* Common                                      */
 #define __NR_writev             121 /* Common                                      */
 #define __NR_settimeofday       122 /* Common                                      */
diff -u --recursive --new-file v2.1.100/linux/include/linux/affs_fs.h linux/include/linux/affs_fs.h
--- v2.1.100/linux/include/linux/affs_fs.h	Fri Feb  6 15:34:49 1998
+++ linux/include/linux/affs_fs.h	Thu May  7 22:58:04 1998
@@ -93,7 +93,8 @@
 
 /* file.c */
 
-extern void   affs_truncate(struct inode *);
+void		affs_free_prealloc(struct inode *inode);
+extern void	affs_truncate(struct inode *);
 
 /* dir.c */
 
diff -u --recursive --new-file v2.1.100/linux/include/linux/blk.h linux/include/linux/blk.h
--- v2.1.100/linux/include/linux/blk.h	Thu May  7 22:51:54 1998
+++ linux/include/linux/blk.h	Fri May  8 18:21:47 1998
@@ -32,21 +32,6 @@
 (s1)->sector < (s2)->sector)))
 
 /*
- * These will have to be changed to be aware of different buffer
- * sizes etc.. It actually needs a major cleanup.
- */
-#if defined(IDE_DRIVER) || defined(MD_DRIVER)
-#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1)
-#else
-#define SECTOR_MASK (blksize_size[MAJOR_NR] &&     \
-	blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] ? \
-	((blksize_size[MAJOR_NR][MINOR(CURRENT->rq_dev)] >> 9) - 1) :  \
-	((BLOCK_SIZE >> 9)  -  1))
-#endif /* IDE_DRIVER */
-
-#define SUBSECTOR(block) (CURRENT->current_nr_sectors > 0)
-
-/*
  * Initialization functions.
  */
 extern int isp16_init(void);
@@ -65,12 +50,18 @@
 extern int hd_init(void);
 extern int ide_init(void);
 extern int xd_init(void);
+extern int mfm_init(void);
 extern int loop_init(void);
 extern int md_init(void);
 extern int ap_init(void);
 extern int ddv_init(void);
 extern int z2_init(void);
 extern int swim3_init(void);
+extern int amiga_floppy_init(void);
+extern int atari_floppy_init(void);
+extern int nbd_init(void);
+extern int ez_init(void);
+extern int bpcd_init(void);
 extern int ps2esdi_init(void);
 
 extern void set_device_ro(kdev_t dev,int flag);
@@ -112,6 +103,7 @@
 #define DEVICE_NR(device)	(MINOR(device) >> PARTN_BITS)
 #define DEVICE_ON(device)	/* nothing */
 #define DEVICE_OFF(device)	/* nothing */
+#define DEVICE_NAME "ide"
 
 #elif (MAJOR_NR == RAMDISK_MAJOR)
 
@@ -338,6 +330,23 @@
 #define DEVICE_ON(device) 
 #define DEVICE_OFF(device)
 
+#elif (MAJOR_NR == MFM_ACORN_MAJOR)
+
+#define DEVICE_NAME "mfm disk"
+#define DEVICE_INTR do_mfm
+#define DEVICE_REQUEST do_mfm_request
+#define DEVICE_NR(device) (MINOR(device) >> 6)
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+
+#elif (MAJOR_NR == NBD_MAJOR)
+
+#define DEVICE_NAME "nbd"
+#define DEVICE_REQUEST do_nbd_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device) 
+#define DEVICE_OFF(device)
+
 #endif /* MAJOR_NR == whatever */
 
 #if (MAJOR_NR != SCSI_TAPE_MAJOR)
@@ -347,11 +356,16 @@
 #define CURRENT (blk_dev[MAJOR_NR].current_request)
 #endif
 
+#ifndef DEVICE_NAME
+#define DEVICE_NAME "unknown"
+#endif
+
 #define CURRENT_DEV DEVICE_NR(CURRENT->rq_dev)
 
 #ifdef DEVICE_INTR
 static void (*DEVICE_INTR)(void) = NULL;
 #endif
+
 #ifdef DEVICE_TIMEOUT
 
 #define SET_TIMER \
@@ -395,89 +409,40 @@
 
 #endif /* !defined(IDE_DRIVER) */
 
-/* end_request() - SCSI devices have their own version */
-/*               - IDE drivers have their own copy too */
-
-#if ! SCSI_BLK_MAJOR(MAJOR_NR)
-
 /*
- * The [*_]end_request() handler has to be called with the request queue
- * spinlock aquired. All functions called within end_request() _must be_
- * atomic.
+ * 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.
  */
-#if defined(IDE_DRIVER) && !defined(_IDE_C) /* shared copy for IDE modules */
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
-#else
 
-#ifdef IDE_DRIVER
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) {
-	int nsect;
-	struct buffer_head *bh;
-	struct request *req;
-	unsigned long flags;
+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)
 
-	spin_lock_irqsave(&io_request_lock,flags);
-	req = hwgroup->rq;
-#else
 static void end_request(int uptodate) {
-	int nsect;
-	struct buffer_head *bh;
 	struct request *req = CURRENT;
 
-#endif /* IDE_DRIVER */
-	req->errors = 0;
-	if (!uptodate) {
-		printk("end_request: I/O error, dev %s, sector %lu\n",
-			kdevname(req->rq_dev), req->sector);
-		if ((bh = req->bh) != NULL) {
-			nsect = bh->b_size >> 9;
-			req->nr_sectors--;
-			req->nr_sectors &= ~(nsect - 1);
-			req->sector += nsect;
-			req->sector &= ~(nsect - 1);
-		}
-	}
+	if (end_that_request_first(req, uptodate, DEVICE_NAME))
+		return;
 
-	if ((bh = req->bh) != NULL) {
-		req->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-		bh->b_end_io(bh, uptodate);
-		if ((bh = req->bh) != NULL) {
-			req->current_nr_sectors = bh->b_size >> 9;
-			if (req->nr_sectors < req->current_nr_sectors) {
-				req->nr_sectors = req->current_nr_sectors;
-				printk("end_request: buffer-list destroyed\n");
-			}
-			req->buffer = bh->b_data;
-#ifdef IDE_DRIVER
-			spin_unlock_irqrestore(&io_request_lock,flags);
-#endif /* IDE_DRIVER */
-			return;
-		}
-	}
 #ifndef DEVICE_NO_RANDOM
 	add_blkdev_randomness(MAJOR(req->rq_dev));
 #endif
-#ifdef IDE_DRIVER
-	hwgroup->drive->queue = req->next;
-	blk_dev[MAJOR(req->rq_dev)].current_request = NULL;
-	hwgroup->rq = NULL;
-#else
 	DEVICE_OFF(req->rq_dev);
 	CURRENT = req->next;
-#endif /* IDE_DRIVER */
-	if (req->sem != NULL)
-		up(req->sem);
-	req->rq_status = RQ_INACTIVE;
-	wake_up(&wait_for_request);
-#ifdef IDE_DRIVER
-	spin_unlock_irqrestore(&io_request_lock,flags);
-#endif /* IDE_DRIVER */
+	end_that_request_last(req);
 }
-#endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */
+
 #endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
-#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */
+#endif /* LOCAL_END_REQUEST */
 
+#endif /* (MAJOR_NR != SCSI_TAPE_MAJOR) */
 #endif /* defined(MAJOR_NR) || defined(IDE_DRIVER) */
 
 #endif /* _BLK_H */
diff -u --recursive --new-file v2.1.100/linux/include/linux/elf.h linux/include/linux/elf.h
--- v2.1.100/linux/include/linux/elf.h	Tue Mar 10 10:03:35 1998
+++ linux/include/linux/elf.h	Fri May  8 00:13:22 1998
@@ -53,14 +53,14 @@
 
 #define EM_MIPS_RS4_BE 10	/* MIPS R4000 big-endian */
 
-#define EM_SPARC64     11	/* SPARC v9 (not official) 64-bit */
-
 #define EM_PARISC      15	/* HPPA */
 
 #define EM_SPARC32PLUS 18	/* Sun's "v8plus" */
 
 #define EM_PPC	       20	/* PowerPC */
 
+#define EM_SPARCV9     43	/* SPARC v9 64-bit */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
@@ -210,6 +210,7 @@
 #define HWCAP_SPARC_STBAR       2
 #define HWCAP_SPARC_SWAP        4
 #define HWCAP_SPARC_MULDIV      8
+#define HWCAP_SPARC_V9		16
 
 
 /*
diff -u --recursive --new-file v2.1.100/linux/include/linux/fd.h linux/include/linux/fd.h
--- v2.1.100/linux/include/linux/fd.h	Tue Jan 20 16:44:58 1998
+++ linux/include/linux/fd.h	Fri May  8 00:27:34 1998
@@ -189,7 +189,7 @@
  * Current drive state (not directly modifiable by user, readonly)
  */
 struct floppy_drive_struct {
-	signed char flags;
+	unsigned long flags;
 /* values for these flags */
 #define FD_NEED_TWADDLE (1 << FD_NEED_TWADDLE_BIT)
 #define FD_VERIFY (1 << FD_VERIFY_BIT)
diff -u --recursive --new-file v2.1.100/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.100/linux/include/linux/fs.h	Tue Mar 10 10:03:35 1998
+++ linux/include/linux/fs.h	Fri May  8 18:21:34 1998
@@ -21,7 +21,9 @@
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
+#include <asm/cache.h>
 
+struct poll_table_struct;
 
 
 /*
@@ -87,7 +89,7 @@
 #define MS_SYNCHRONOUS	16	/* Writes are synced at once */
 #define MS_REMOUNT	32	/* Alter flags of a mounted FS */
 #define MS_MANDLOCK	64	/* Allow mandatory locks on an FS */
-#define S_WRITE		128	/* Write on file/directory/symlink */
+#define S_QUOTA		128	/* Quota initialized for file/directory/symlink */
 #define S_APPEND	256	/* Append-only file */
 #define S_IMMUTABLE	512	/* Immutable file */
 #define MS_NOATIME	1024	/* Do not update access times. */
@@ -119,7 +121,7 @@
 #define IS_SYNC(inode) ((inode)->i_flags & MS_SYNCHRONOUS)
 #define IS_MANDLOCK(inode) ((inode)->i_flags & MS_MANDLOCK)
 
-#define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE)
+#define IS_QUOTAINIT(inode) ((inode)->i_flags & S_QUOTA)
 #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
 #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE)
 #define IS_NOATIME(inode) ((inode)->i_flags & MS_NOATIME)
@@ -316,7 +318,11 @@
 #define ATTR_FLAG_IMMUTABLE	8 	/* Immutable file */
 #define ATTR_FLAG_NODIRATIME	16 	/* Don't update atime for directory */
 
+/*
+ * Includes for diskquotas and mount structures.
+ */
 #include <linux/quota.h>
+#include <linux/mount.h>
 
 struct inode {
 	struct list_head	i_hash;
@@ -632,11 +638,11 @@
 struct dquot_operations {
 	void (*initialize) (struct inode *, short);
 	void (*drop) (struct inode *);
-	int (*alloc_block) (const struct inode *, unsigned long);
-	int (*alloc_inode) (const struct inode *, unsigned long);
+	int (*alloc_block) (const struct inode *, unsigned long, uid_t, char);
+	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);
+	int (*transfer) (struct inode *, struct iattr *, char, uid_t);
 };
 
 struct file_system_type {
diff -u --recursive --new-file v2.1.100/linux/include/linux/hippidevice.h linux/include/linux/hippidevice.h
--- v2.1.100/linux/include/linux/hippidevice.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/hippidevice.h	Fri May  8 18:22:18 1998
@@ -0,0 +1,56 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Definitions for the HIPPI handlers.
+ *
+ * Version:	@(#)hippidevice.h	1.0.0	05/26/97
+ *
+ * Author:	Jes Sorensen, <Jes.Sorensen@cern.ch>
+ *
+ *		hippidevice.h is based on previous fddidevice.h work by
+ *			Ross Biro, <bir7@leland.Stanford.Edu>
+ *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *			Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *			Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_HIPPIDEVICE_H
+#define _LINUX_HIPPIDEVICE_H
+
+#include <linux/if_hippi.h>
+
+#ifdef __KERNEL__
+extern int hippi_header(struct sk_buff *skb,
+			struct device *dev,
+			unsigned short type,
+			void *daddr,
+			void *saddr,
+			unsigned len);
+
+extern int hippi_rebuild_header(struct sk_buff *skb);
+
+extern unsigned short hippi_type_trans(struct sk_buff *skb,
+				       struct device *dev);
+
+extern void hippi_header_cache_bind(struct hh_cache ** hhp,
+				    struct device *dev,
+				    unsigned short htype,
+				    __u32 daddr);
+
+extern void hippi_header_cache_update(struct hh_cache *hh,
+				      struct device *dev,
+				      unsigned char * haddr);
+extern int hippi_header_parse(struct sk_buff *skb, unsigned char *haddr);
+
+extern void hippi_net_init(void);
+
+extern struct device *init_hippi_dev(struct device *, int);
+#endif
+
+#endif	/* _LINUX_HIPPIDEVICE_H */
diff -u --recursive --new-file v2.1.100/linux/include/linux/if_fddi.h linux/include/linux/if_fddi.h
--- v2.1.100/linux/include/linux/if_fddi.h	Mon Nov 18 01:31:32 1996
+++ linux/include/linux/if_fddi.h	Fri May  8 00:08:02 1998
@@ -107,6 +107,8 @@
 	{
 	__u32	rx_packets;				/* total packets received */
 	__u32	tx_packets;				/* total packets transmitted */
+	__u32	rx_bytes;				/* total bytes received	*/
+	__u32	tx_bytes;				/* total bytes transmitted */
 	__u32	rx_errors;				/* bad packets received	*/
 	__u32	tx_errors;				/* packet transmit problems	*/
 	__u32	rx_dropped;				/* no space in linux buffers */
@@ -114,6 +116,25 @@
 	__u32	multicast;				/* multicast packets received */
 	__u32	transmit_collision;		/* always 0 for FDDI */
 
+	/* detailed rx_errors */
+	__u32	rx_length_errors;
+	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
+	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
+	__u32	rx_frame_errors;	/* recv'd frame alignment error */
+	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
+	__u32	rx_missed_errors;	/* receiver missed packet	*/
+
+	/* detailed tx_errors */
+	__u32	tx_aborted_errors;
+	__u32	tx_carrier_errors;
+	__u32	tx_fifo_errors;
+	__u32	tx_heartbeat_errors;
+	__u32	tx_window_errors;
+	
+	/* for cslip etc */
+	__u32	rx_compressed;
+	__u32	tx_compressed;
+   
 	/* Detailed FDDI statistics.  Adopted from RFC 1512 */
 
 	__u8	smt_station_id[8];
diff -u --recursive --new-file v2.1.100/linux/include/linux/if_hippi.h linux/include/linux/if_hippi.h
--- v2.1.100/linux/include/linux/if_hippi.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/if_hippi.h	Fri May  8 18:22:17 1998
@@ -0,0 +1,157 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Global definitions for the HIPPI interface.
+ *
+ * Version:	@(#)if_hippi.h	1.0.0	05/26/97
+ *
+ * Author:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *		Donald Becker, <becker@super.org>
+ *		Alan Cox, <alan@cymru.net>
+ *		Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
+ *		Jes Sorensen, <Jes.Sorensen@cern.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.
+ */
+ 
+#ifndef _LINUX_IF_HIPPI_H
+#define _LINUX_IF_HIPPI_H
+
+#include <asm/byteorder.h>
+
+/*
+ *	HIPPI magic constants.
+ */
+
+#define HIPPI_ALEN	6		/* Bytes in one HIPPI hw-addr	   */
+#define HIPPI_HLEN	sizeof(struct hippi_hdr)
+#define HIPPI_ZLEN	0		/* Min. bytes in frame without FCS */
+#define HIPPI_DATA_LEN	65280		/* Max. bytes in payload	   */
+#define HIPPI_FRAME_LEN	(HIPPI_DATA_LEN + HIPPI_HLEN)
+					/* Max. bytes in frame without FCS */
+
+/*
+ * Define LLC and SNAP constants.
+ */
+#define HIPPI_EXTENDED_SAP	0xAA
+#define HIPPI_UI_CMD		0x03
+
+
+/*
+ *	Do we need to list some sort of ID's here?
+ */
+
+/*
+ *	HIPPI statistics collection data. 
+ */
+ 
+struct hipnet_statistics
+{
+	int	rx_packets;		/* total packets received	*/
+	int	tx_packets;		/* total packets transmitted	*/
+	int	rx_errors;		/* bad packets received		*/
+	int	tx_errors;		/* packet transmit problems	*/
+	int	rx_dropped;		/* no space in linux buffers	*/
+	int	tx_dropped;		/* no space available in linux	*/
+
+	/* detailed rx_errors: */
+	int	rx_length_errors;
+	int	rx_over_errors;		/* receiver ring buff overflow	*/
+	int	rx_crc_errors;		/* recved pkt with crc error	*/
+	int	rx_frame_errors;	/* recv'd frame alignment error */
+	int	rx_fifo_errors;		/* recv'r fifo overrun		*/
+	int	rx_missed_errors;	/* receiver missed packet	*/
+
+	/* detailed tx_errors */
+	int	tx_aborted_errors;
+	int	tx_carrier_errors;
+	int	tx_fifo_errors;
+	int	tx_heartbeat_errors;
+	int	tx_window_errors;
+};
+
+
+struct hippi_fp_hdr
+{
+#if 0
+	__u8		ulp;				/* must contain 4 */
+#if defined (__BIG_ENDIAN_BITFIELD)
+	__u8		d1_data_present:1;		/* must be 1 */
+	__u8		start_d2_burst_boundary:1;	/* must be zero */
+	__u8		reserved:6;			/* must be zero */
+#if 0
+	__u16		reserved1:5;
+	__u16		d1_area_size:8;			/* must be 3 */
+	__u16		d2_offset:3;			/* must be zero */
+#endif
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8		reserved:6;			/* must be zero */
+	__u8	 	start_d2_burst_boundary:1;	/* must be zero */
+	__u8		d1_data_present:1;		/* must be 1 */
+#if 0
+	__u16		d2_offset:3;			/* must be zero */
+	__u16		d1_area_size:8;			/* must be 3 */
+	__u16		reserved1:5;			/* must be zero */
+#endif
+#else
+#error	"Please fix <asm/byteorder.h>"
+#endif
+#else
+	__u32		fixed;
+#endif
+	__u32		d2_size;
+} __attribute__ ((packed));
+
+struct hippi_le_hdr
+{
+#if defined (__BIG_ENDIAN_BITFIELD)
+	unsigned long	fc:3;
+	unsigned long	double_wide:1;
+	unsigned long	message_type:4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	unsigned long	message_type:4;
+	unsigned long	double_wide:1;
+	unsigned long	fc:3;
+#endif
+	__u8		dest_switch_addr[3];
+#if defined (__BIG_ENDIAN_BITFIELD)
+	__u8		dest_addr_type:4,
+			src_addr_type:4;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8		src_addr_type:4,
+			dest_addr_type:4;
+#endif
+	__u8		src_switch_addr[3];
+	__u16		reserved;
+	__u8		daddr[HIPPI_ALEN];
+	__u16		locally_administered;
+	__u8		saddr[HIPPI_ALEN];
+} __attribute__ ((packed));
+
+#define HIPPI_OUI_LEN	3
+/*
+ * Looks like the dsap and ssap fields have been swapped by mistake in
+ * RFC 2067 "IP over HIPPI".
+ */
+struct hippi_snap_hdr
+{
+	__u8	dsap;			/* always 0xAA */
+	__u8	ssap;			/* always 0xAA */
+	__u8	ctrl;			/* always 0x03 */
+	__u8	oui[HIPPI_OUI_LEN];	/* organizational universal id (zero)*/
+	__u16	ethertype;		/* packet type ID field */
+} __attribute__ ((packed));
+
+struct hippi_hdr
+{
+	struct hippi_fp_hdr	fp;
+	struct hippi_le_hdr	le;
+	struct hippi_snap_hdr	snap;
+} __attribute__ ((packed));
+
+#endif	/* _LINUX_IF_HIPPI_H */
diff -u --recursive --new-file v2.1.100/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.1.100/linux/include/linux/interrupt.h	Fri Jan 30 15:50:57 1998
+++ linux/include/linux/interrupt.h	Fri May  8 18:21:34 1998
@@ -42,17 +42,12 @@
 	KEYBOARD_BH,
 	CYCLADES_BH,
 	CM206_BH,
-	JS_BH
+	JS_BH,
+	MACSERIAL_BH
 };
 
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
-
-/*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
- */
-#define in_interrupt() (local_irq_count[smp_processor_id()] + local_bh_count[smp_processor_id()] != 0)
 
 /*
  * Autoprobing for irqs:
diff -u --recursive --new-file v2.1.100/linux/include/linux/major.h linux/include/linux/major.h
--- v2.1.100/linux/include/linux/major.h	Wed Apr  1 20:11:54 1998
+++ linux/include/linux/major.h	Fri May  8 00:42:39 1998
@@ -40,6 +40,7 @@
 #define CYCLADES_MAJOR  19
 #define CYCLADESAUX_MAJOR 20
 #define MITSUMI_X_CDROM_MAJOR 20
+#define MFM_ACORN_MAJOR 21	/* ARM Linux /dev/mfm */
 #define SCSI_GENERIC_MAJOR 21
 #define Z8530_MAJOR 34
 #define DIGI_MAJOR 23
diff -u --recursive --new-file v2.1.100/linux/include/linux/md.h linux/include/linux/md.h
--- v2.1.100/linux/include/linux/md.h	Sat Nov  8 11:39:13 1997
+++ linux/include/linux/md.h	Fri May  8 00:17:13 1998
@@ -33,9 +33,10 @@
 #define MD_DEFAULT_DISK_READAHEAD	(256 * 1024)
 
 /* ioctls */
-#define REGISTER_DEV _IO (MD_MAJOR, 1)
-#define START_MD     _IO (MD_MAJOR, 2)
-#define STOP_MD      _IO (MD_MAJOR, 3)
+#define REGISTER_DEV 		_IO (MD_MAJOR, 1)
+#define START_MD     		_IO (MD_MAJOR, 2)
+#define STOP_MD      		_IO (MD_MAJOR, 3)
+#define REGISTER_DEV_NEW	_IO (MD_MAJOR, 4)
 
 /*
    personalities :
@@ -199,6 +200,7 @@
 #include <linux/mm.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
+#include <asm/semaphore.h>
 
 /*
  * Kernel-based reconstruction is mostly working, but still requires
@@ -209,12 +211,6 @@
 #define MAX_REAL     8		/* Max number of physical dev per md dev */
 #define MAX_MD_DEV   4		/* Max number of md dev */
 
-#if SUPPORT_RECONSTRUCTION
-#define MAX_MD_THREADS (MAX_MD_DEV * 3)	/* Max number of kernel threads */
-#else
-#define MAX_MD_THREADS (MAX_MD_DEV)	/* Max number of kernel threads */
-#endif /* SUPPORT_RECONSTRUCTION */
-
 #define FACTOR(a)         ((a)->repartition & FACTOR_MASK)
 #define MAX_FAULT(a)      (((a)->repartition & FAULT_MASK)>>8)
 #define PERSONALITY(a)    ((a)->repartition & PERSONALITY_MASK)
@@ -279,10 +275,12 @@
 	void			(*run) (void *data);
 	void			*data;
 	struct wait_queue	*wqueue;
-	__u32			flags;
+	unsigned long           flags;
+	struct semaphore	*sem;
+	struct task_struct	*tsk;
 };
 
-#define THREAD_WAKEUP	0
+#define THREAD_WAKEUP  0
 
 extern struct md_dev md_dev[MAX_MD_DEV];
 extern int md_size[MAX_MD_DEV];
diff -u --recursive --new-file v2.1.100/linux/include/linux/mount.h linux/include/linux/mount.h
--- v2.1.100/linux/include/linux/mount.h	Thu Dec 14 21:31:39 1995
+++ linux/include/linux/mount.h	Fri May  8 17:54:39 1998
@@ -3,26 +3,36 @@
  * Definitions for mount interface. This describes the in the kernel build 
  * linkedlist with mounted filesystems.
  *
- * Author:  Marco van Wieringen <mvw@mcs.ow.nl> <mvw@tnix.net> <mvw@cistron.nl>
+ * Author:  Marco van Wieringen <mvw@planets.elm.net>
  *
- * Version: $Id: mount.h,v 1.3 1994/07/20 22:01:00 mvw Exp mvw $
+ * Version: $Id: mount.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
  *
  */
 #ifndef _LINUX_MOUNT_H
 #define _LINUX_MOUNT_H
 
+#define DQUOT_USR_ENABLED	0x01		/* User diskquotas enabled */
+#define DQUOT_GRP_ENABLED	0x02		/* Group diskquotas enabled */
+
+struct quota_mount_options
+{
+	unsigned int flags;			/* Flags for diskquotas on this device */
+	struct semaphore semaphore;		/* lock device while I/O in progress */
+	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 */
+};
+
 struct vfsmount
 {
-   kdev_t mnt_dev;                     /* Device this applies to */
-   char *mnt_devname;                  /* Name of device e.g. /dev/dsk/hda1 */
-   char *mnt_dirname;                  /* Name of directory mounted on */
-   unsigned int mnt_flags;             /* Flags of this device */
-   struct semaphore mnt_sem;           /* lock device while I/O in progress */
-   struct super_block *mnt_sb;         /* pointer to superblock */
-   struct file *mnt_quotas[MAXQUOTAS]; /* fp's to quotafiles */
-   time_t mnt_iexp[MAXQUOTAS];         /* expiretime for inodes */
-   time_t mnt_bexp[MAXQUOTAS];         /* expiretime for blocks */
-   struct vfsmount *mnt_next;          /* pointer to next in linkedlist */
+  kdev_t mnt_dev;			/* Device this applies to */
+  char *mnt_devname;			/* Name of device e.g. /dev/dsk/hda1 */
+  char *mnt_dirname;			/* Name of directory mounted on */
+  unsigned int mnt_flags;		/* Flags of this device */
+  struct super_block *mnt_sb;		/* pointer to superblock */
+  struct quota_mount_options mnt_dquot;	/* Diskquota specific mount options */
+  struct vfsmount *mnt_next;		/* pointer to next in linkedlist */
 };
 
 struct vfsmount *lookup_vfsmnt(kdev_t dev);
diff -u --recursive --new-file v2.1.100/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.100/linux/include/linux/proc_fs.h	Thu May  7 22:51:55 1998
+++ linux/include/linux/proc_fs.h	Fri May  8 18:21:39 1998
@@ -74,7 +74,7 @@
 };
 
 enum pid_subdirectory_inos {
-	PROC_PID_FD_DIR = 1
+	PROC_PID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
 enum net_directory_inos {
diff -u --recursive --new-file v2.1.100/linux/include/linux/quota.h linux/include/linux/quota.h
--- v2.1.100/linux/include/linux/quota.h	Sat Nov  1 11:01:24 1997
+++ linux/include/linux/quota.h	Fri May  8 17:54:39 1998
@@ -33,7 +33,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * Version: $Id: quota.h,v 1.8 1995/03/11 11:43:07 mvw Exp mvw $
+ * Version: $Id: quota.h,v 2.0 1996/11/17 16:48:14 mvw Exp mvw $
  */
 
 #ifndef _LINUX_QUOTA_
@@ -43,7 +43,6 @@
 
 /*
  * Convert diskblocks to blocks and the other way around.
- * currently only to fool the BSD source. :-)
  */
 #define dbtob(num) (num << 10)
 #define btodb(num) (num >> 10)
@@ -74,16 +73,20 @@
  * Definitions for the default names of the quotas files.
  */
 #define INITQFNAMES { \
-   "user",      /* USRQUOTA */ \
-   "group",   /* GRPQUOTA */ \
-   "undefined", \
+	"user",    /* USRQUOTA */ \
+	"group",   /* GRPQUOTA */ \
+	"undefined", \
 };
 
 #define QUOTAFILENAME "quota"
 #define QUOTAGROUP "staff"
 
-#define NR_DQHASH 43            /* Just an arbitrary number any suggestions ? */
-#define NR_DQUOTS 256           /* Number of quotas active at one time */
+extern int nr_dquots, nr_free_dquots;
+extern int max_dquots;
+extern int dquot_root_squash;
+
+#define NR_DQHASH 43            /* Just an arbitrary number */
+#define NR_DQUOTS 256           /* Maximum number of quotas active at one time (Configurable from /proc/sys/fs) */
 
 /*
  * Command definitions for the 'quotactl' system call.
@@ -103,6 +106,7 @@
 #define Q_SYNC     0x0600	/* sync disk copy of a filesystems quotas */
 #define Q_SETQLIM  0x0700	/* set limits */
 #define Q_GETSTATS 0x0800	/* get collected stats */
+#define Q_RSQUASH  0x1000	/* set root_squash option */
 
 /*
  * The following structure defines the format of the disk quota file
@@ -110,14 +114,14 @@
  * indexed by user or group number.
  */
 struct dqblk {
-    __u32 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
-    __u32 dqb_bsoftlimit;	/* preferred limit on disk blks */
-    __u32 dqb_curblocks;	/* current block count */
-    __u32 dqb_ihardlimit;	/* maximum # allocated inodes */
-    __u32 dqb_isoftlimit;	/* preferred inode limit */
-    __u32 dqb_curinodes;	/* current # allocated inodes */
-    time_t dqb_btime;		/* time limit for excessive disk use */
-    time_t dqb_itime;		/* time limit for excessive files */
+	__u32 dqb_bhardlimit;	/* absolute limit on disk blks alloc */
+	__u32 dqb_bsoftlimit;	/* preferred limit on disk blks */
+	__u32 dqb_curblocks;	/* current block count */
+	__u32 dqb_ihardlimit;	/* absolute limit on allocated inodes */
+	__u32 dqb_isoftlimit;	/* preferred inode limit */
+	__u32 dqb_curinodes;	/* current # allocated inodes */
+	time_t dqb_btime;		/* time limit for excessive disk use */
+	time_t dqb_itime;		/* time limit for excessive inode use */
 };
 
 /*
@@ -135,21 +139,18 @@
 #define dqoff(UID)      ((loff_t)((UID) * sizeof (struct dqblk)))
 
 struct dqstats {
-   __u32 lookups;
-   __u32 drops;
-   __u32 reads;
-   __u32 writes;
-   __u32 cache_hits;
-   __u32 pages_allocated;
-   __u32 allocated_dquots;
-   __u32 free_dquots;
-   __u32 syncs;
+	__u32 lookups;
+	__u32 drops;
+	__u32 reads;
+	__u32 writes;
+	__u32 cache_hits;
+	__u32 allocated_dquots;
+	__u32 free_dquots;
+	__u32 syncs;
 };
 
 #ifdef __KERNEL__
 
-#include <linux/mount.h>
-
 /*
  * Maximum length of a message generated in the quota system,
  * that needs to be kicked onto the tty.
@@ -164,18 +165,19 @@
 #define DQ_FAKE       0x40	/* no limits only usage */
 
 struct dquot {
-   unsigned int dq_id;		/* id this applies to (uid, gid) */
-   short dq_type;		/* type of quota */
-   kdev_t dq_dev;                /* Device this applies to */
-   short dq_flags;		/* see DQ_* */
-   short dq_count;		/* reference count */
-   struct vfsmount *dq_mnt;     /* vfsmountpoint this applies to */
-   struct dqblk dq_dqb;         /* diskquota usage */
-   struct wait_queue *dq_wait;	/* pointer to waitqueue */
-   struct dquot *dq_prev;	/* pointer to prev dquot */
-   struct dquot *dq_next;	/* pointer to next dquot */
-   struct dquot *dq_hash_prev;	/* pointer to prev dquot */
-   struct dquot *dq_hash_next;	/* pointer to next dquot */
+	unsigned int dq_id;		/* ID this applies to (uid, gid) */
+	short dq_type;			/* Type of quota */
+	kdev_t dq_dev;			/* Device this applies to */
+	short dq_flags;			/* See DQ_* */
+	short dq_count;			/* Reference count */
+	unsigned long dq_referenced;	/* Number of times this dquot was referenced during its lifetime */
+	struct vfsmount *dq_mnt;	/* VFS_mount_point this applies to */
+	struct dqblk dq_dqb;		/* Diskquota usage */
+	struct wait_queue *dq_wait;	/* Pointer to waitqueue */
+	struct dquot *dq_next;		/* Pointer to next dquot */
+	struct dquot *dq_hash_next;	/* Pointer to next in dquot_hash */
+	struct dquot **dq_hash_pprev;	/* Pointer to previous in dquot_hash */
+	struct dquot **dq_pprev;
 };
 
 #define NODQUOT (struct dquot *)NULL
@@ -190,22 +192,6 @@
 
 #define QUOTA_OK          0
 #define NO_QUOTA          1
-
-/*
- * declaration of quota_function calls in kernel.
- */
-
-extern void dquot_initialize(struct inode *inode, short type);
-extern void dquot_drop(struct inode *inode);
-extern int dquot_alloc_block(const struct inode *inode, unsigned long number);
-extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
-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);
-
-extern void invalidate_dquots(kdev_t dev, short type);
-extern int quota_off(kdev_t dev, short type);
-extern int sync_dquots(kdev_t dev, short type);
 
 #else
 
diff -u --recursive --new-file v2.1.100/linux/include/linux/quotaops.h linux/include/linux/quotaops.h
--- v2.1.100/linux/include/linux/quotaops.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/quotaops.h	Fri May  8 18:22:50 1998
@@ -0,0 +1,144 @@
+/*
+ * Definitions for diskquota-operations. When diskquota is configured these
+ * macros expand to the right source-code.
+ *
+ * Author:  Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * Version: $Id: quotaops.h,v 1.2 1998/01/15 16:22:26 ecd Exp $
+ *
+ */
+#ifndef _LINUX_QUOTAOPS_
+#define _LINUX_QUOTAOPS_
+
+#include <linux/config.h>
+
+#if defined(CONFIG_QUOTA)
+
+/*
+ * declaration of quota_function calls in kernel.
+ */
+extern void dquot_initialize(struct inode *inode, short type);
+extern void dquot_drop(struct inode *inode);
+extern void invalidate_dquots(kdev_t dev, short type);
+extern int  quota_off(kdev_t dev, short type);
+extern int  sync_dquots(kdev_t dev, short type);
+
+extern int  dquot_alloc_block(const struct inode *inode, unsigned long number,
+                              uid_t initiator, char warn);
+extern int  dquot_alloc_inode(const struct inode *inode, unsigned long number,
+                              uid_t initiator);
+
+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);
+
+/*
+ * Operations supported for diskquotas.
+ */
+#define DQUOT_INIT(inode) \
+if (inode->i_sb && inode->i_sb->dq_op) { \
+	inode->i_sb->dq_op->initialize(inode, -1); \
+}
+
+#define DQUOT_DROP(inode) \
+if (IS_QUOTAINIT(inode)) { \
+	if (inode->i_sb && inode->i_sb->dq_op) \
+		inode->i_sb->dq_op->drop(inode); \
+}
+
+#define DQUOT_SAVE_DROP(inode) \
+if (IS_QUOTAINIT(inode)) { \
+	inode->i_lock = 1; \
+	if (inode->i_sb && inode->i_sb->dq_op) \
+		inode->i_sb->dq_op->drop(inode); \
+	unlock_inode(inode); \
+	goto we_slept; \
+}
+
+#define DQUOT_PREALLOC_BLOCK(sb, inode, nr) \
+if (sb->dq_op) { \
+	if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), \
+	                           current->euid, 0) == NO_QUOTA) \
+		break; \
+}
+
+#define DQUOT_ALLOC_BLOCK(sb, inode, nr) \
+if (sb->dq_op) { \
+	if (sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize), \
+	                           current->euid, 1) == NO_QUOTA) { \
+		unlock_super (sb); \
+		*err = -EDQUOT; \
+		return 0; \
+	} \
+}
+
+#define DQUOT_ALLOC_INODE(sb, inode) \
+if (sb->dq_op) { \
+	sb->dq_op->initialize (inode, -1); \
+	if (sb->dq_op->alloc_inode (inode, 1, current->euid)) { \
+		sb->dq_op->drop (inode); \
+		inode->i_nlink = 0; \
+		iput (inode); \
+		*err = -EDQUOT; \
+		return NULL; \
+	} \
+	inode->i_flags |= S_QUOTA; \
+}
+
+#define DQUOT_FREE_BLOCK(sb, inode, nr) \
+if (sb->dq_op) { \
+	sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, sb->s_blocksize)); \
+}
+
+#define DQUOT_FREE_INODE(sb, inode) \
+if (sb->dq_op) { \
+	sb->dq_op->free_inode(inode, 1); \
+}
+
+#define DQUOT_TRANSFER(dentry, iattr) \
+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->euid)) { \
+		error = -EDQUOT; \
+		goto out; \
+	} \
+	error = notify_change(dentry, &iattr); \
+	if (error) \
+		inode->i_sb->dq_op->transfer(dentry->d_inode, &iattr, 1, current->euid); \
+} else { \
+	error = notify_change(dentry, &iattr); \
+}
+
+#define DQUOT_SYNC(dev) \
+sync_dquots(dev, -1)
+
+#define DQUOT_OFF(dev) \
+quota_off(dev, -1)
+
+#else
+
+/*
+ * NO-OP when quota not configured.
+ */
+#define DQUOT_INIT(inode)
+#define DQUOT_DROP(inode)
+#define DQUOT_SAVE_DROP(inode)
+#define DQUOT_PREALLOC_BLOCK(sb, inode, nr)
+#define DQUOT_ALLOC_BLOCK(sb, inode, nr)
+#define DQUOT_ALLOC_INODE(sb, inode)
+#define DQUOT_FREE_BLOCK(sb, inode, nr)
+#define DQUOT_FREE_INODE(sb, inode)
+#define DQUOT_SYNC(dev)
+#define DQUOT_OFF(dev)
+
+/*
+ * Special case expands to a simple notify_change.
+ */
+#define DQUOT_TRANSFER(dentry, iattr) \
+error = notify_change(dentry, &iattr)
+
+#endif /* CONFIG_QUOTA */
+#endif /* _LINUX_QUOTAOPS_ */
diff -u --recursive --new-file v2.1.100/linux/include/linux/raid1.h linux/include/linux/raid1.h
--- v2.1.100/linux/include/linux/raid1.h	Sat Nov  8 11:39:13 1997
+++ linux/include/linux/raid1.h	Fri May  8 00:17:13 1998
@@ -37,8 +37,8 @@
 
 struct raid1_bh {
 	unsigned int		remaining;
-	unsigned int		state;
 	int			cmd;
+	unsigned long		state;
 	struct md_dev		*mddev;
 	struct buffer_head	*master_bh;
 	struct buffer_head	*mirror_bh [MD_SB_DISKS];
diff -u --recursive --new-file v2.1.100/linux/include/linux/raid5.h linux/include/linux/raid5.h
--- v2.1.100/linux/include/linux/raid5.h	Sat Nov  8 11:39:13 1997
+++ linux/include/linux/raid5.h	Fri May  8 00:17:13 1998
@@ -30,7 +30,7 @@
 	int			size;			/* buffers size */
 	int			pd_idx;			/* parity disk index */
 	int			nr_pending;		/* nr of pending cmds */
-	__u32			state;			/* state flags */
+	unsigned long		state;			/* state flags */
 	int			cmd;			/* stripe cmd */
 	int			count;			/* nr of waiters */
 	int			write_method;		/* reconstruct-write / read-modify-write */
diff -u --recursive --new-file v2.1.100/linux/include/linux/smp.h linux/include/linux/smp.h
--- v2.1.100/linux/include/linux/smp.h	Sat May  2 14:19:54 1998
+++ linux/include/linux/smp.h	Fri May  8 00:45:50 1998
@@ -10,9 +10,10 @@
 #include <asm/smp.h>
 
 /*
- * main IPI interface, handles INIT, TLB flush, STOP, etc.:
+ * main IPI interface, handles INIT, TLB flush, STOP, etc. (defined in asm header):
+ *
+ * extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
  */ 
-extern void smp_message_pass(int target, int msg, unsigned long data, int wait);
 
 /*
  * Boot processor call to load the other CPU's
diff -u --recursive --new-file v2.1.100/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.1.100/linux/include/linux/sysctl.h	Thu May  7 22:51:55 1998
+++ linux/include/linux/sysctl.h	Fri May  8 17:54:39 1998
@@ -27,7 +27,7 @@
 
 /* For internal pattern-matching use only: */
 #ifdef __KERNEL__
-#define CTL_ANY		-1	/* Matches any name */
+#define CTL_ANY		-1		/* Matches any name */
 #define CTL_NONE	0
 #endif
 
@@ -54,24 +54,19 @@
 	KERN_PROF,		/* table: profiling information */
 	KERN_NODENAME,
 	KERN_DOMAINNAME,
-	KERN_NRINODE,
-	KERN_MAXINODE,
-	KERN_NRFILE,
-	KERN_MAXFILE,
 	KERN_SECURELVL,		/* int: system security level */
 	KERN_PANIC,		/* int: panic timeout */
 	KERN_REALROOTDEV,	/* real root device to mount after initrd */
-	KERN_NFSRNAME,		/* NFS root name */
-	KERN_NFSRADDRS,		/* NFS root addresses */
 	KERN_JAVA_INTERPRETER,	/* path to Java(tm) interpreter */
 	KERN_JAVA_APPLETVIEWER,	/* path to Java(tm) appletviewer */
 	KERN_SPARC_REBOOT,	/* reboot command on Sparc */
 	KERN_CTLALTDEL,		/* int: allow ctl-alt-del to reboot */
 	KERN_PRINTK,            /* sturct: control printk logging parameters */
 	KERN_NAMETRANS,		/* Name translation */
-	KERN_STATINODE,
-	KERN_DENTRY,		/* dentry statistics */
+	KERN_PPC_HTABRECLAIM,	/* turn htab reclaimation on/off on PPC */
+	KERN_PPC_ZEROPAGED,	/* turn idle page zeroing on/off on PPC */
 	KERN_MODPROBE,
+	KERN_SG_BIG_BUFF
 };
 
 
@@ -360,6 +355,17 @@
 /* CTL_PROC names: */
 
 /* CTL_FS names: */
+enum
+{
+	FS_NRINODE=1,		/* int: current number of allocated inodes */
+	FS_STATINODE,
+	FS_MAXINODE,		/* int: maximum number of inodes that can be allocated */
+	FS_NRDQUOT,		/* int: current number of allocated dquots */
+	FS_MAXDQUOT,		/* int: maximum number of dquots that can be allocated */
+	FS_NRFILE,		/* int: current number of allocated filedescriptors */
+	FS_MAXFILE,		/* int: maximum number of filedescriptors that can be allocated */
+	FS_DENTRY,
+};
 
 /* CTL_DEBUG names: */
 
diff -u --recursive --new-file v2.1.100/linux/include/linux/timex.h linux/include/linux/timex.h
--- v2.1.100/linux/include/linux/timex.h	Wed Apr 16 14:15:00 1997
+++ linux/include/linux/timex.h	Thu May  7 23:53:35 1998
@@ -17,6 +17,10 @@
 /*
  * Modification history timex.h
  *
+ * 29 Dec 97	Russell King
+ *	Moved CLOCK_TICK_RATE, CLOCK_TICK_FACTOR and FINETUNE to asm/timex.h
+ *	for ARM machines
+ *
  *  9 Jan 97    Adrian Sun
  *      Shifted LATCH define to allow access to alpha machines.
  *
@@ -125,20 +129,13 @@
 #define PPS_VALID 120		/* pps signal watchdog max (s) */
 #define MAXGLITCH 30		/* pps signal glitch max (s) */
 
-/* LATCH is used in the interval timer and ftape setup. */
-#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
-#define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */
-
-#ifndef __alpha__
 /*
- * This definitively is wrong for the Alpha and none of the
- * kernel code seems to reference this anymore.
+ * Pick up the architecture specific timex specifications
  */
-#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
-#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)
-#endif /* !__alpha__ */
+#include <asm/timex.h>
+
+/* LATCH is used in the interval timer and ftape setup. */
+#define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */
 
 /*
  * syscall interface - used (mainly by NTP daemon)
diff -u --recursive --new-file v2.1.100/linux/init/main.c linux/init/main.c
--- v2.1.100/linux/init/main.c	Sat May  2 14:19:54 1998
+++ linux/init/main.c	Fri May  8 17:54:39 1998
@@ -64,7 +64,6 @@
 extern int kswapd(void *);
 extern void kswapd_setup(void);
 
-extern void dquot_init(void);
 extern void init_IRQ(void);
 extern void init_modules(void);
 extern long console_init(long, long);
@@ -284,6 +283,9 @@
 #if defined(CONFIG_SYSVIPC)
 extern void ipc_init(void);
 #endif
+#if defined(CONFIG_QUOTA)
+extern void dquot_init_hash(void);
+#endif
 
 #ifdef CONFIG_MD_BOOT
 extern void md_setup(char *str,int *ints) __init;
@@ -1060,7 +1062,9 @@
 #if defined(CONFIG_SYSVIPC)
 	ipc_init();
 #endif
-	dquot_init();
+#if defined(CONFIG_QUOTA)
+	dquot_init_hash();
+#endif
 	check_bugs();
 
 	printk("POSIX conformance testing by UNIFIX\n");
diff -u --recursive --new-file v2.1.100/linux/kernel/capability.c linux/kernel/capability.c
--- v2.1.100/linux/kernel/capability.c	Thu May  7 22:51:55 1998
+++ linux/kernel/capability.c	Thu May  7 23:44:25 1998
@@ -5,7 +5,6 @@
  * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@transmeta.com>
  */ 
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/capability.h>
diff -u --recursive --new-file v2.1.100/linux/kernel/exit.c linux/kernel/exit.c
--- v2.1.100/linux/kernel/exit.c	Wed Apr  1 20:11:54 1998
+++ linux/kernel/exit.c	Fri May  8 17:54:39 1998
@@ -20,7 +20,9 @@
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
+#endif
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -346,7 +348,9 @@
 		panic("Attempted to kill the idle task!");
 fake_volatile:
 	current->flags |= PF_EXITING;
+#ifdef CONFIG_BSD_PROCESS_ACCT
 	acct_process(code);
+#endif
 	del_timer(&current->real_timer);
 	sem_exit();
 	__exit_mm(current);
diff -u --recursive --new-file v2.1.100/linux/kernel/kmod.c linux/kernel/kmod.c
--- v2.1.100/linux/kernel/kmod.c	Sat May  2 14:19:54 1998
+++ linux/kernel/kmod.c	Fri May  8 15:58:13 1998
@@ -86,13 +86,12 @@
 	int pid;
 	int waitpid_result;
 
-	pid = kernel_thread(exec_modprobe, (void*) module_name,
-			    CLONE_FS | SIGCHLD);
+	pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS);
 	if (pid < 0) {
 		printk(KERN_ERR "kmod: fork failed, errno %d\n", -pid);
 		return pid;
 	}
-	waitpid_result = waitpid(pid, NULL, 0);
+	waitpid_result = waitpid(pid, NULL, __WCLONE);
 	if (waitpid_result != pid) {
 		printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n",
 			pid, waitpid_result);
diff -u --recursive --new-file v2.1.100/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.100/linux/kernel/ksyms.c	Mon Apr  6 17:41:01 1998
+++ linux/kernel/ksyms.c	Fri May  8 00:23:41 1998
@@ -269,8 +269,6 @@
 /* interrupt handling */
 EXPORT_SYMBOL(request_irq);
 EXPORT_SYMBOL(free_irq);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(probe_irq_on);
 EXPORT_SYMBOL(probe_irq_off);
 EXPORT_SYMBOL(bh_active);
diff -u --recursive --new-file v2.1.100/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.100/linux/kernel/sched.c	Thu May  7 22:51:55 1998
+++ linux/kernel/sched.c	Fri May  8 00:31:10 1998
@@ -399,9 +399,7 @@
 	need_resched = 0;
 	prev = current;
 	this_cpu = smp_processor_id();
-	if (local_irq_count[this_cpu])
-		goto scheduling_in_interrupt;
-	if (local_bh_count[this_cpu])
+	if (in_interrupt())
 		goto scheduling_in_interrupt;
 	release_kernel_lock(prev, this_cpu, lock_depth);
 	if (bh_active & bh_mask)
diff -u --recursive --new-file v2.1.100/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.100/linux/kernel/sys.c	Thu May  7 22:51:55 1998
+++ linux/kernel/sys.c	Fri May  8 00:27:35 1998
@@ -841,9 +841,6 @@
 	if(copy_from_user(system_utsname.nodename, name, len))
 		return -EFAULT;
 	system_utsname.nodename[len] = 0;
-#ifdef CONFIG_TRANS_NAMES
-	translations_dirty = 1;
-#endif
 	return 0;
 }
 
@@ -872,9 +869,6 @@
 	if(copy_from_user(system_utsname.domainname, name, len))
 		return -EFAULT;
 	system_utsname.domainname[len] = 0;
-#ifdef CONFIG_TRANS_NAMES
-	translations_dirty = 1;
-#endif
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.100/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.100/linux/kernel/sysctl.c	Thu May  7 22:51:55 1998
+++ linux/kernel/sysctl.c	Fri May  8 17:54:39 1998
@@ -51,6 +51,9 @@
 #ifdef __sparc__
 extern char reboot_command [];
 #endif
+#ifdef __powerpc__
+extern unsigned long htab_reclaim_on, zero_paged_on;
+#endif
 
 static int parse_table(int *, int, void *, size_t *, void *, size_t,
 		       ctl_table *, void **);
@@ -144,18 +147,6 @@
 	 0644, NULL, &proc_dostring, &sysctl_string},
 	{KERN_DOMAINNAME, "domainname", system_utsname.domainname, 64,
 	 0644, NULL, &proc_dostring, &sysctl_string},
-	{KERN_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
-	 0444, NULL, &proc_dointvec},
-	{KERN_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
-	 0444, NULL, &proc_dointvec},
-	{KERN_MAXINODE, "inode-max", &max_inodes, sizeof(int),
-	 0644, NULL, &proc_dointvec},
-	{KERN_NRFILE, "file-nr", &nr_files, 3*sizeof(int),
-	 0444, NULL, &proc_dointvec},
-	{KERN_MAXFILE, "file-max", &max_files, sizeof(int),
-	 0644, NULL, &proc_dointvec},
-	{KERN_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
-	 0444, NULL, &proc_dointvec},
 	{KERN_PANIC, "panic", &panic_timeout, sizeof(int),
 	 0644, NULL, &proc_dointvec},
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -172,6 +163,12 @@
 	{KERN_SPARC_REBOOT, "reboot-cmd", reboot_command,
 	 256, 0644, NULL, &proc_dostring, &sysctl_string },
 #endif
+#ifdef __powerpc__
+	{KERN_PPC_HTABRECLAIM, "htab-reclaim", &htab_reclaim_on, sizeof(int),
+	 0644, NULL, &proc_dointvec},
+	{KERN_PPC_ZEROPAGED, "zero-paged", &zero_paged_on, sizeof(int),
+	 0644, NULL, &proc_dointvec},
+#endif
 	{KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
 	 0644, NULL, &proc_dointvec},
 	{KERN_PRINTK, "printk", &console_loglevel, 4*sizeof(int),
@@ -181,7 +178,7 @@
 	 0644, NULL, &proc_dostring, &sysctl_string },
 #endif
 #ifdef CONFIG_CHR_DEV_SG
-	{KERN_NRFILE, "sg-big-buff", &sg_big_buff, sizeof (int),
+	{KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int),
 	 0444, NULL, &proc_dointvec},
 #endif
 	{0}
@@ -213,6 +210,22 @@
 };
 
 static ctl_table fs_table[] = {
+	{FS_NRINODE, "inode-nr", &inodes_stat, 2*sizeof(int),
+	 0444, NULL, &proc_dointvec},
+	{FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
+	 0444, NULL, &proc_dointvec},
+	{FS_MAXINODE, "inode-max", &max_inodes, sizeof(int),
+	 0644, NULL, &proc_dointvec},
+	{FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int),
+	 0444, NULL, &proc_dointvec},
+	{FS_MAXFILE, "file-max", &max_files, sizeof(int),
+	 0644, NULL, &proc_dointvec},
+	{FS_NRDQUOT, "dquot-nr", &nr_dquots, 2*sizeof(int),
+	 0444, NULL, &proc_dointvec},
+	{FS_MAXDQUOT, "dquot-max", &max_dquots, sizeof(int),
+	 0644, NULL, &proc_dointvec},
+	{FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
+	 0444, NULL, &proc_dointvec},
 	{0}
 };
 
@@ -892,9 +905,6 @@
 		if (len == table->maxlen)
 			len--;
 		((char *) table->data)[len] = 0;
-#ifdef CONFIG_TRANS_NAMES
-		translations_dirty = 1;
-#endif
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.1.100/linux/mm/mlock.c linux/mm/mlock.c
--- v2.1.100/linux/mm/mlock.c	Thu May  7 22:51:55 1998
+++ linux/mm/mlock.c	Fri May  8 00:32:31 1998
@@ -129,8 +129,8 @@
 
 		if (newflags & VM_LOCKED)
 			while (start < end) {
-				char c;
-				get_user(c,(char *) start);
+				int c;
+				get_user(c,(int *) start);
 				__asm__ __volatile__("": :"r" (c));
 				start += PAGE_SIZE;
 			}
diff -u --recursive --new-file v2.1.100/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.100/linux/mm/page_alloc.c	Thu May  7 22:51:55 1998
+++ linux/mm/page_alloc.c	Thu May  7 23:44:25 1998
@@ -98,7 +98,7 @@
  *
  * Hint: -mask = 1+~mask
  */
-static spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This routine is used by the kernel swap deamon to determine
diff -u --recursive --new-file v2.1.100/linux/net/802/Makefile linux/net/802/Makefile
--- v2.1.100/linux/net/802/Makefile	Tue Dec 23 13:52:02 1997
+++ linux/net/802/Makefile	Fri May  8 00:08:02 1998
@@ -29,6 +29,10 @@
 O_OBJS += fddi.o
 endif
 
+ifdef CONFIG_HIPPI
+O_OBJS += hippi.o
+endif
+
 ifdef CONFIG_IPX
 	SNAP=y
 endif
diff -u --recursive --new-file v2.1.100/linux/net/802/hippi.c linux/net/802/hippi.c
--- v2.1.100/linux/net/802/hippi.c	Wed Dec 31 16:00:00 1969
+++ linux/net/802/hippi.c	Fri May  8 00:08:02 1998
@@ -0,0 +1,162 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		HIPPI-type device handling.
+ *
+ * Version:	@(#)hippi.c	1.0.0	05/29/97
+ *
+ * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+ *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *		Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *		Florian  La Roche, <rzsfl@rz.uni-sb.de>
+ *		Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *		Jes Sorensen, <Jes.Sorensen@cern.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.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/hippidevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <net/arp.h>
+#include <net/sock.h>
+#include <asm/checksum.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+/*
+ * hippi_net_init()
+ *
+ * Do nothing, this is just to pursuade the stupid linker to behave.
+ */
+
+void hippi_net_init(void)
+{
+	return;
+}
+
+/*
+ * Create the HIPPI MAC header for an arbitrary protocol layer 
+ *
+ * saddr=NULL	means use device source address
+ * daddr=NULL	means leave destination address (eg unresolved arp)
+ */
+
+int hippi_header(struct sk_buff *skb, struct device *dev,
+		 unsigned short type, void *daddr, void *saddr,
+		 unsigned len)
+{
+	struct hippi_hdr *hip = (struct hippi_hdr *)skb_push(skb, HIPPI_HLEN);
+
+	if (!len){
+		len = skb->len - HIPPI_HLEN;
+		printk("hippi_header(): length not supplied\n");
+	}
+
+	/*
+	 * Due to the stupidity of the little endian byte-order we
+	 * have to set the fp field this way.
+	 */
+	hip->fp.fixed		= __constant_htonl(0x04800018);
+	hip->fp.d2_size		= htonl(len + 8);
+	hip->le.fc		= 0;
+	hip->le.double_wide	= 0;	/* only HIPPI 800 for the time being */
+	hip->le.message_type	= 0;	/* Data PDU */
+
+	hip->le.dest_addr_type	= 2;	/* 12 bit SC address */
+	hip->le.src_addr_type	= 2;	/* 12 bit SC address */
+
+#if 1
+	if (saddr)
+	{
+		printk("existing saddr - this should not happen, configure ARP please!\n");
+		memcpy(hip->le.src_switch_addr, saddr + 3, 3);
+	}else
+		memcpy(hip->le.src_switch_addr, dev->dev_addr + 3, 3);
+
+	memset(&hip->le.reserved, 0, 16);
+#endif
+
+	hip->snap.dsap		= HIPPI_EXTENDED_SAP;
+	hip->snap.ssap		= HIPPI_EXTENDED_SAP;
+	hip->snap.ctrl		= HIPPI_UI_CMD;
+	hip->snap.oui[0]	= 0x00;
+	hip->snap.oui[1]	= 0x00;
+	hip->snap.oui[2]	= 0x00;
+	hip->snap.ethertype	= htons(type);
+
+	if (daddr)
+	{
+		memcpy(hip->le.dest_switch_addr, daddr + 3, 3);
+		memcpy(&skb->private.ifield, daddr + 2, 4);
+		return(HIPPI_HLEN);
+	}
+	return -HIPPI_HLEN;
+}
+
+
+/*
+ * Rebuild the HIPPI MAC header. This is called after an ARP has
+ * completed on this sk_buff. We now let ARP fill in the other fields.
+ */
+
+int hippi_rebuild_header(struct sk_buff *skb)
+{
+	struct hippi_hdr *hip = (struct hippi_hdr *)skb->data;
+
+	/*
+	 * Only IP is currently supported
+	 */
+	 
+	if(hip->snap.ethertype != __constant_htons(ETH_P_IP)) 
+	{
+		printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype));
+		return 0;
+	}
+
+	/*
+	 * We don't support dynamic ARP on HIPPI, but we use the ARP
+	 * static ARP tables to hold the I-FIELDs.
+	 */
+	return arp_find(hip->le.daddr, skb);
+}
+
+
+/*
+ *	Determine the packet's protocol ID.
+ */
+ 
+unsigned short hippi_type_trans(struct sk_buff *skb, struct device *dev)
+{
+	struct hippi_hdr *hip;
+	
+	hip = (struct hippi_hdr *) skb->data;
+
+	/*
+	 * This is actually wrong ... question is if we really should
+	 * set the raw address here.
+	 */
+	 skb->mac.raw = skb->data;
+	 skb_pull(skb, HIPPI_HLEN);
+
+	/*
+	 * No fancy promisc stuff here now.
+	 */
+
+	return hip->snap.ethertype;
+}
diff -u --recursive --new-file v2.1.100/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.100/linux/net/appletalk/ddp.c	Thu May  7 22:51:55 1998
+++ linux/net/appletalk/ddp.c	Fri May  8 00:08:02 1998
@@ -990,7 +990,7 @@
 {
 	struct sock *sk;
 
-	sk = sk_alloc(AF_APPLETALK, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1);
 	if(sk == NULL)
 		return (-ENOMEM);
 
@@ -1304,7 +1304,7 @@
 		return (0);
 	}
 
-	if(call_in_firewall(AF_APPLETALK, skb->dev, ddp, NULL,&skb)!=FW_ACCEPT)
+	if(call_in_firewall(PF_APPLETALK, skb->dev, ddp, NULL,&skb)!=FW_ACCEPT)
 	{
 		kfree_skb(skb);
 		return (0);
@@ -1338,7 +1338,7 @@
 		/*
 		 * Check firewall allows this routing
 		 */
-		if(call_fw_firewall(AF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT)
+		if(call_fw_firewall(PF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT)
 		{
 			kfree_skb(skb);
 			return (0);
@@ -1452,10 +1452,7 @@
 	skb->sk = sock;
 
 	if(sock_queue_rcv_skb(sock, skb) < 0)
-	{
-		skb->sk = NULL;
 		kfree_skb(skb);
-	}
 
 	return (0);
 }
@@ -1611,8 +1608,8 @@
 	skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err);
 	if(skb == NULL)
 		return (err);
-
-	skb->sk  = sk;
+	
+	skb->sk = sk;
 	skb_reserve(skb, ddp_dl->header_length);
 	skb_reserve(skb, dev->hard_header_len);
 
@@ -1652,7 +1649,7 @@
 	else
 		ddp->deh_sum = atalk_checksum(ddp, len + sizeof(*ddp));
 
-	if(call_out_firewall(AF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT)
+	if(call_out_firewall(PF_APPLETALK, skb->dev, ddp, NULL, &skb) != FW_ACCEPT)
 	{
 		kfree_skb(skb);
 		return (-EPERM);
@@ -1859,13 +1856,13 @@
 
 static struct net_proto_family atalk_family_ops=
 {
-	AF_APPLETALK,
+	PF_APPLETALK,
 	atalk_create
 };
 
 static struct proto_ops atalk_dgram_ops=
 {
-	AF_APPLETALK,
+	PF_APPLETALK,
 
 	sock_no_dup,
 	atalk_release,
@@ -2014,7 +2011,7 @@
 	dev_remove_pack(&ltalk_packet_type);
 	dev_remove_pack(&ppptalk_packet_type);
 	unregister_snap_client(ddp_snap_id);
-	sock_unregister(atalk_family_ops.family);
+	sock_unregister(PF_APPLETALK);
 
 	return;
 }
diff -u --recursive --new-file v2.1.100/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.100/linux/net/ax25/af_ax25.c	Tue Apr 14 14:29:26 1998
+++ linux/net/ax25/af_ax25.c	Fri May  8 00:08:02 1998
@@ -787,13 +787,13 @@
 
 	switch (sock->type) {
 		case SOCK_DGRAM:
-			if (protocol == 0 || protocol == AF_AX25)
+			if (protocol == 0 || protocol == PF_AX25)
 				protocol = AX25_P_TEXT;
 			break;
 		case SOCK_SEQPACKET:
 			switch (protocol) {
 				case 0:
-				case AF_AX25:	/* For CLX */
+				case PF_AX25:	/* For CLX */
 					protocol = AX25_P_TEXT;
 					break;
 				case AX25_P_SEGMENT:
@@ -828,7 +828,7 @@
 			return -ESOCKTNOSUPPORT;
 	}
 
-	if ((sk = sk_alloc(AF_AX25, GFP_ATOMIC, 1)) == NULL)
+	if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL)
 		return -ENOMEM;
 
 	if ((ax25 = ax25_create_cb()) == NULL) {
@@ -854,7 +854,7 @@
 	struct sock *sk;
 	ax25_cb *ax25;
 
-	if ((sk = sk_alloc(AF_AX25, GFP_ATOMIC, 1)) == NULL)
+	if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, 1)) == NULL)
 		return NULL;
 
 	if ((ax25 = ax25_create_cb()) == NULL) {
@@ -1689,12 +1689,12 @@
 
 static struct net_proto_family ax25_family_ops =
 {
-	AF_AX25,
+	PF_AX25,
 	ax25_create
 };
 
 static struct proto_ops ax25_proto_ops = {
-	AF_AX25,
+	PF_AX25,
 
 	sock_no_dup,
 	ax25_release,
@@ -1820,7 +1820,7 @@
 	ax25_packet_type.type = htons(ETH_P_AX25);
 	dev_remove_pack(&ax25_packet_type);
 
-	sock_unregister(AF_AX25);
+	sock_unregister(PF_AX25);
 }
 #endif
 
diff -u --recursive --new-file v2.1.100/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c
--- v2.1.100/linux/net/core/rtnetlink.c	Sat May  2 14:19:54 1998
+++ linux/net/core/rtnetlink.c	Fri May  8 00:08:02 1998
@@ -246,7 +246,7 @@
 		s_idx = 1;
 	for (idx=1; idx<NPROTO; idx++) {
 		int type = cb->nlh->nlmsg_type-RTM_BASE;
-		if (idx < s_idx || idx == AF_PACKET)
+		if (idx < s_idx || idx == PF_PACKET)
 			continue;
 		if (rtnetlink_links[idx] == NULL ||
 		    rtnetlink_links[idx][type].dumpit == NULL)
@@ -336,7 +336,7 @@
 
 	link_tab = rtnetlink_links[family];
 	if (link_tab == NULL)
-		link_tab = rtnetlink_links[AF_UNSPEC];
+		link_tab = rtnetlink_links[PF_UNSPEC];
 	link = &link_tab[type];
 
 	sz_idx = type>>2;
@@ -349,7 +349,7 @@
 
 	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
 		if (link->dumpit == NULL)
-			link = &(rtnetlink_links[AF_UNSPEC][type]);
+			link = &(rtnetlink_links[PF_UNSPEC][type]);
 
 		if (link->dumpit == NULL)
 			goto err_inval;
@@ -398,7 +398,7 @@
 	}
 
 	if (link->doit == NULL)
-		link = &(rtnetlink_links[AF_UNSPEC][type]);
+		link = &(rtnetlink_links[PF_UNSPEC][type]);
 	if (link->doit == NULL)
 		goto err_inval;
 	err = link->doit(skb, nlh, (void *)&rta);
@@ -538,8 +538,8 @@
 	if (rtnl == NULL)
 		panic("rtnetlink_init: cannot initialize rtnetlink\n");
 	register_netdevice_notifier(&rtnetlink_dev_notifier);
-	rtnetlink_links[AF_UNSPEC] = link_rtnetlink_table;
-	rtnetlink_links[AF_PACKET] = link_rtnetlink_table;
+	rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table;
+	rtnetlink_links[PF_PACKET] = link_rtnetlink_table;
 }
 
 
diff -u --recursive --new-file v2.1.100/linux/net/econet/econet.c linux/net/econet/econet.c
--- v2.1.100/linux/net/econet/econet.c	Sat May  2 14:19:55 1998
+++ linux/net/econet/econet.c	Fri May  8 00:08:02 1998
@@ -557,7 +557,7 @@
 	MOD_INC_USE_COUNT;
 
 	err = -ENOBUFS;
-	sk = sk_alloc(AF_ECONET, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1);
 	if (sk == NULL)
 		goto out;
 
@@ -570,7 +570,7 @@
 		goto out_free;
 	memset(sk->protinfo.af_econet, 0, sizeof(struct econet_opt));
 	sk->zapped=0;
-	sk->family = AF_ECONET;
+	sk->family = PF_ECONET;
 	sk->num = protocol;
 
 	sklist_insert_socket(&econet_sklist, sk);
@@ -727,12 +727,12 @@
 }
 
 static struct net_proto_family econet_family_ops = {
-	AF_ECONET,
+	PF_ECONET,
 	econet_create
 };
 
 static struct proto_ops econet_ops = {
-	AF_ECONET,
+	PF_ECONET,
 
 	sock_no_dup,
 	econet_release,
@@ -1008,7 +1008,7 @@
 
 	/* We can count ourselves lucky Acorn machines are too dim to
 	   speak IPv6. :-) */
-	if ((error = sock_create(AF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
+	if ((error = sock_create(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
 	{
 		printk("AUN: socket error %d\n", -error);
 		return error;
diff -u --recursive --new-file v2.1.100/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.100/linux/net/ipv4/af_inet.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv4/af_inet.c	Fri May  8 00:08:02 1998
@@ -3,9 +3,9 @@
  *		operating system.  INET is implemented using the  BSD Socket
  *		interface as the means of communication with the user level.
  *
- *		AF_INET protocol family socket handler.
+ *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.71 1998/04/16 05:38:16 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.72 1998/05/03 14:30:49 alan Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -330,23 +330,23 @@
 	/* Compatibility */
 	if (sock->type == SOCK_PACKET) {
 		static int warned; 
-		if (net_families[AF_PACKET]==NULL)
+		if (net_families[PF_PACKET]==NULL)
 		{
 #if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
 			char module_name[30];
-			sprintf(module_name,"net-pf-%d", AF_PACKET);
+			sprintf(module_name,"net-pf-%d", PF_PACKET);
 			request_module(module_name);
-			if (net_families[AF_PACKET] == NULL)
+			if (net_families[PF_PACKET] == NULL)
 #endif
 			return -ESOCKTNOSUPPORT;
 		}
 		if (!warned++)
-			printk(KERN_INFO "%s uses obsolete (AF_INET,SOCK_PACKET)\n", current->comm);
-		return net_families[AF_PACKET]->create(sock, protocol);
+			printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
+		return net_families[PF_PACKET]->create(sock, protocol);
 	}
 
 	sock->state = SS_UNCONNECTED;
-	sk = sk_alloc(AF_INET, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_INET, GFP_KERNEL, 1);
 	if (sk == NULL) 
 		goto do_oom;
 
@@ -398,7 +398,7 @@
 #ifdef CONFIG_TCP_NAGLE_OFF
 	sk->nonagle = 1;
 #endif  
-	sk->family = AF_INET;
+	sk->family = PF_INET;
 	sk->protocol = protocol;
 
 	sk->prot = prot;
@@ -958,7 +958,7 @@
 }
 
 struct proto_ops inet_stream_ops = {
-	AF_INET,
+	PF_INET,
 
 	sock_no_dup,
 	inet_release,
@@ -979,7 +979,7 @@
 };
 
 struct proto_ops inet_dgram_ops = {
-	AF_INET,
+	PF_INET,
 
 	sock_no_dup,
 	inet_release,
@@ -1000,7 +1000,7 @@
 };
 
 struct net_proto_family inet_family_ops = {
-	AF_INET,
+	PF_INET,
 	inet_create
 };
 
diff -u --recursive --new-file v2.1.100/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.1.100/linux/net/ipv4/devinet.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv4/devinet.c	Fri May  8 00:08:02 1998
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.20 1998/03/27 07:02:44 davem Exp $
+ *	Version: $Id: devinet.c,v 1.21 1998/05/03 14:30:52 alan Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -1014,10 +1014,10 @@
 
 __initfunc(void devinet_init(void))
 {
-	register_gifconf(AF_INET, inet_gifconf);
+	register_gifconf(PF_INET, inet_gifconf);
 	register_netdevice_notifier(&ip_netdev_notifier);
 #ifdef CONFIG_RTNETLINK
-	rtnetlink_links[AF_INET] = inet_rtnetlink_table;
+	rtnetlink_links[PF_INET] = inet_rtnetlink_table;
 #endif
 #ifdef CONFIG_SYSCTL
 	devinet_sysctl.sysctl_header =
diff -u --recursive --new-file v2.1.100/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.1.100/linux/net/ipv4/ipconfig.c	Tue Mar 17 22:18:16 1998
+++ linux/net/ipv4/ipconfig.c	Fri May  8 00:08:02 1998
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.11 1998/02/12 07:43:16 davem Exp $
+ *  $Id: ipconfig.c,v 1.12 1998/05/03 14:30:53 alan Exp $
  *
  *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
  *  information to configure own IP address and routes.
@@ -552,7 +552,7 @@
 {
 	int err;
 
-	if ((err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP, sock)) < 0)
+	if ((err = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, sock)) < 0)
 		printk(KERN_ERR "BOOTP: Cannot open UDP socket!\n");
 	return err;
 }
diff -u --recursive --new-file v2.1.100/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.100/linux/net/ipv4/tcp_input.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv4/tcp_input.c	Fri May  8 00:08:02 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.116 1998/05/02 14:50:11 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.118 1998/05/06 04:53:48 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -593,7 +593,7 @@
 		 * connection startup slow start one packet too
 		 * quickly.  This is severely frowned upon behavior.
 		 */
-		if(sacked & TCPCB_SACKED_RETRANS && tp->retrans_out)
+		if((sacked & TCPCB_SACKED_RETRANS) && tp->retrans_out)
 			tp->retrans_out--;
 		if(!(scb->flags & TCPCB_FLAG_SYN)) {
 			acked |= FLAG_DATA_ACKED;
@@ -968,7 +968,7 @@
 		tw->af_specific	= sk->tp_pinfo.af_tcp.af_specific;
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-		if(tw->family == AF_INET6) {
+		if(tw->family == PF_INET6) {
 			memcpy(&tw->v6_daddr,
 			       &sk->net_pinfo.af_inet6.daddr,
 			       sizeof(struct in6_addr));
diff -u --recursive --new-file v2.1.100/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.100/linux/net/ipv4/tcp_ipv4.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv4/tcp_ipv4.c	Fri May  8 00:08:02 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.145 1998/05/02 12:47:13 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.146 1998/05/03 14:30:59 alan Exp $
  *
  *		IPv4 specific functions
  *
@@ -1155,7 +1155,7 @@
 struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, struct sk_buff *skb,
 				      int snd_mss)
 {
-	struct sock *newsk = sk_alloc(AF_INET, GFP_ATOMIC, 0);
+	struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, 0);
 
 	if(newsk != NULL) {
 		struct tcp_opt *newtp;
diff -u --recursive --new-file v2.1.100/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.1.100/linux/net/ipv4/tcp_output.c	Sat May  2 14:19:55 1998
+++ linux/net/ipv4/tcp_output.c	Fri May  8 00:08:02 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.87 1998/04/26 01:11:35 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.90 1998/05/06 04:59:15 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -415,8 +415,7 @@
 		}
 	
 		/* Update sequence range on original skb. */
-		TCP_SKB_CB(skb)->end_seq +=
-			TCP_SKB_CB(next_skb)->end_seq - TCP_SKB_CB(next_skb)->seq;
+		TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(next_skb)->end_seq;
 
 		/* Merge over control information. */
 		flags |= TCP_SKB_CB(next_skb)->flags; /* This moves PSH/FIN etc. over */
@@ -453,7 +452,9 @@
 	 * and not use it for RTT calculation in the absence of
 	 * the timestamp option.
 	 */
-	for (skb = skb_peek(&sk->write_queue); skb != tp->send_head;
+	for (skb = skb_peek(&sk->write_queue);
+	     ((skb != tp->send_head) &&
+	      (skb != (struct sk_buff *)&sk->write_queue));
 	     skb = skb->next) 
 		if (skb->len > mss)
 			tcp_retransmit_skb(sk, skb); 
@@ -536,6 +537,10 @@
 	if (tp->retrans_head == tp->send_head)
 		tp->retrans_head = NULL;
 
+	/* Each time, advance the retrans_head if we got
+	 * a packet out or we skipped one because it was
+	 * SACK'd.  -DaveM
+	 */
 	while ((skb = tp->retrans_head) != NULL) {
 		/* If it has been ack'd by a SACK block, we don't
 		 * retransmit it.
@@ -544,14 +549,17 @@
 			/* Send it out, punt if error occurred. */
 			if(tcp_retransmit_skb(sk, skb))
 				break;
+
+			update_retrans_head(sk);
 		
 			/* Stop retransmitting if we've hit the congestion
 			 * window limit.
 			 */
 			if (tp->retrans_out >= (tp->snd_cwnd >> TCP_CWND_SHIFT))
 				break;
+		} else {
+			update_retrans_head(sk);
 		}
-		update_retrans_head(sk);
 	}
 }
 
@@ -732,8 +740,6 @@
 		mss = min(mss, sk->user_mss);
 	if (req->tstamp_ok)
 		mss -= TCPOLEN_TSTAMP_ALIGNED;
-	else
-		req->mss += TCPOLEN_TSTAMP_ALIGNED;
 
 	/* Don't offer more than they did.
 	 * This way we don't have to memorize who said what.
diff -u --recursive --new-file v2.1.100/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.1.100/linux/net/ipv6/addrconf.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv6/addrconf.c	Fri May  8 00:08:02 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: addrconf.c,v 1.38 1998/03/20 09:12:14 davem Exp $
+ *	$Id: addrconf.c,v 1.39 1998/05/03 14:31:04 alan Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1808,7 +1808,7 @@
 	addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;
 	add_timer(&addr_chk_timer);
 #ifdef CONFIG_RTNETLINK
-	rtnetlink_links[AF_INET6] = inet6_rtnetlink_table;
+	rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
 #endif
 #ifdef CONFIG_SYSCTL
 	addrconf_sysctl.sysctl_header =
@@ -1825,7 +1825,7 @@
 	int i;
 
 #ifdef CONFIG_RTNETLINK
-	rtnetlink_links[AF_INET6] = NULL;
+	rtnetlink_links[PF_INET6] = NULL;
 #endif
 #ifdef CONFIG_SYSCTL
 	addrconf_sysctl_unregister(&ipv6_devconf_dflt);
diff -u --recursive --new-file v2.1.100/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.1.100/linux/net/ipv6/af_inet6.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv6/af_inet6.c	Fri May  8 00:08:02 1998
@@ -1,5 +1,5 @@
 /*
- *	AF_INET6 socket family
+ *	PF_INET6 socket protocol family
  *	Linux INET6 implementation 
  *
  *	Authors:
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.30 1998/03/25 00:23:05 davem Exp $
+ *	$Id: af_inet6.c,v 1.31 1998/05/03 14:31:06 alan Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -71,7 +71,7 @@
 	struct sock *sk;
 	struct proto *prot;
 
-	sk = sk_alloc(AF_INET6, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_INET6, GFP_KERNEL, 1);
 	if (sk == NULL) 
 		goto do_oom;
 
@@ -105,7 +105,7 @@
 
 	sk->destruct            = NULL;
 	sk->zapped		= 0;
-	sk->family		= AF_INET6;
+	sk->family		= PF_INET6;
 	sk->protocol		= protocol;
 
 	sk->prot		= prot;
@@ -336,7 +336,7 @@
 }
 
 struct proto_ops inet6_stream_ops = {
-	AF_INET6,
+	PF_INET6,
 
 	sock_no_dup,
 	inet6_release,
@@ -357,7 +357,7 @@
 };
 
 struct proto_ops inet6_dgram_ops = {
-	AF_INET6,
+	PF_INET6,
 
 	sock_no_dup,
 	inet6_release,
@@ -378,7 +378,7 @@
 };
 
 struct net_proto_family inet6_family_ops = {
-	AF_INET6,
+	PF_INET6,
 	inet6_create
 };
 
@@ -485,7 +485,7 @@
 {
 	sit_cleanup();
 	ipv6_cleanup();
-	sock_unregister(AF_INET6);
+	sock_unregister(PF_INET6);
 #ifdef CONFIG_PROC_FS
 	proc_net_unregister(proc_net_raw6.low_ino);
 	proc_net_unregister(proc_net_tcp6.low_ino);
diff -u --recursive --new-file v2.1.100/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c
--- v2.1.100/linux/net/ipv6/ipv6_sockglue.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv6/ipv6_sockglue.c	Fri May  8 00:08:02 1998
@@ -7,7 +7,7 @@
  *
  *	Based on linux/net/ipv4/ip_sockglue.c
  *
- *	$Id: ipv6_sockglue.c,v 1.19 1998/04/30 16:24:26 freitag Exp $
+ *	$Id: ipv6_sockglue.c,v 1.20 1998/05/03 14:31:07 alan Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -110,7 +110,7 @@
 				sk->prot = &tcp_prot;
 				tp->af_specific = &ipv4_specific;
 				sk->socket->ops = &inet_stream_ops;
-				sk->family = AF_INET;
+				sk->family = PF_INET;
 			} else {
 				sk->prot = &udp_prot;
 				sk->socket->ops = &inet_dgram_ops;
diff -u --recursive --new-file v2.1.100/linux/net/ipv6/protocol.c linux/net/ipv6/protocol.c
--- v2.1.100/linux/net/ipv6/protocol.c	Thu Mar 27 14:40:17 1997
+++ linux/net/ipv6/protocol.c	Fri May  8 00:08:02 1998
@@ -3,9 +3,9 @@
  *		operating system.  INET is implemented using the  BSD Socket
  *		interface as the means of communication with the user level.
  *
- *		AF_INET6 protocol dispatch tables.
+ *		PF_INET6 protocol dispatch tables.
  *
- * Version:	$Id: protocol.c,v 1.5 1997/03/18 18:24:44 davem Exp $
+ * Version:	$Id: protocol.c,v 1.6 1998/05/03 14:31:09 alan Exp $
  *
  * Authors:	Pedro Roque	<roque@di.fc.ul.pt>
  *
diff -u --recursive --new-file v2.1.100/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.1.100/linux/net/ipv6/tcp_ipv6.c	Thu May  7 22:51:56 1998
+++ linux/net/ipv6/tcp_ipv6.c	Fri May  8 00:08:02 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.80 1998/05/02 12:47:15 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.81 1998/05/03 14:31:10 alan Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -213,7 +213,7 @@
 	hiscore=0;
 	sk = tcp_listening_hash[tcp_lhashfn(hnum)];
 	for(; sk; sk = sk->next) {
-		if((sk->num == hnum) && (sk->family == AF_INET6)) {
+		if((sk->num == hnum) && (sk->family == PF_INET6)) {
 			struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
 			
 			score = 1;
@@ -272,7 +272,7 @@
 	/* Must check for a TIME_WAIT'er before going to listener hash. */
 	for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next) {
 		if(*((__u32 *)&(sk->dport))	== ports	&&
-		   sk->family			== AF_INET6) {
+		   sk->family			== PF_INET6) {
 			struct tcp_tw_bucket *tw = (struct tcp_tw_bucket *)sk;
 			if(!ipv6_addr_cmp(&tw->v6_daddr, saddr)	&&
 			   !ipv6_addr_cmp(&tw->v6_rcv_saddr, daddr) &&
diff -u --recursive --new-file v2.1.100/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.1.100/linux/net/ipv6/udp.c	Thu Mar 26 15:57:13 1998
+++ linux/net/ipv6/udp.c	Fri May  8 00:08:02 1998
@@ -7,7 +7,7 @@
  *
  *	Based on linux/ipv4/udp.c
  *
- *	$Id: udp.c,v 1.27 1998/03/21 07:28:06 davem Exp $
+ *	$Id: udp.c,v 1.28 1998/05/03 14:31:12 alan Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -147,7 +147,7 @@
 
 	for(sk = udp_hash[hnum & (UDP_HTABLE_SIZE - 1)]; sk != NULL; sk = sk->next) {
 		if((sk->num == hnum)		&&
-		   (sk->family == AF_INET6)	&&
+		   (sk->family == PF_INET6)	&&
 		   !(sk->dead && (sk->state == TCP_CLOSE))) {
 			struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
 			int score = 0;
diff -u --recursive --new-file v2.1.100/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.1.100/linux/net/ipx/af_ipx.c	Sat May  2 14:19:55 1998
+++ linux/net/ipx/af_ipx.c	Fri May  8 00:08:02 1998
@@ -1732,7 +1732,7 @@
 	switch(sock->type)
 	{
 		case SOCK_DGRAM:
-			sk=sk_alloc(AF_IPX, GFP_KERNEL, 1);
+			sk=sk_alloc(PF_IPX, GFP_KERNEL, 1);
 			if(sk==NULL)
 				return(-ENOMEM);
                         sock->ops = &ipx_dgram_ops;
@@ -2300,12 +2300,12 @@
  */
  
 static struct net_proto_family ipx_family_ops = {
-	AF_IPX,
+	PF_IPX,
 	ipx_create
 };
 
 static struct proto_ops ipx_dgram_ops = {
-	AF_IPX,
+	PF_IPX,
 	sock_no_dup,
 	ipx_release,
 	ipx_bind,
diff -u --recursive --new-file v2.1.100/linux/net/ipx/af_spx.c linux/net/ipx/af_spx.c
--- v2.1.100/linux/net/ipx/af_spx.c	Tue Apr 14 14:29:26 1998
+++ linux/net/ipx/af_spx.c	Fri May  8 00:08:02 1998
@@ -83,7 +83,7 @@
 {
 	struct sock *sk;
 
-	sk = sk_alloc(AF_IPX, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_IPX, GFP_KERNEL, 1);
 	if(sk == NULL)
                 return (-ENOMEM);
 
@@ -806,7 +806,7 @@
 }
 
 static struct proto_ops spx_operations = {
-        AF_IPX,
+        PF_IPX,
         sock_no_dup,
         spx_release,
         spx_bind,
@@ -827,7 +827,7 @@
 
 static struct net_proto_family spx_family_ops=
 {
-	AF_IPX,
+	PF_IPX,
 	spx_create
 };
 
@@ -842,7 +842,7 @@
         if (error)
                 printk(KERN_ERR "SPX: unable to register with IPX.\n");
 
-	/* route socket(AF_IPX, SOCK_SEQPACKET) calls through spx_create() */
+	/* route socket(PF_IPX, SOCK_SEQPACKET) calls through spx_create() */
 
 	printk(KERN_INFO "Sequenced Packet eXchange (SPX) 0.01 for Linux NET3.037\n");
 	return;
diff -u --recursive --new-file v2.1.100/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.1.100/linux/net/netlink/af_netlink.c	Tue Mar 17 22:18:16 1998
+++ linux/net/netlink/af_netlink.c	Fri May  8 00:08:02 1998
@@ -147,7 +147,7 @@
 
 	sock->ops = &netlink_ops;
 
-	sk = sk_alloc(AF_NETLINK, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1);
 	if (!sk)
 		return -ENOMEM;
 
@@ -980,7 +980,7 @@
 #endif
 
 struct proto_ops netlink_ops = {
-	AF_NETLINK,
+	PF_NETLINK,
 
 	sock_no_dup,
 	netlink_release,
@@ -1001,7 +1001,7 @@
 };
 
 struct net_proto_family netlink_family_ops = {
-	AF_NETLINK,
+	PF_NETLINK,
 	netlink_create
 };
 
diff -u --recursive --new-file v2.1.100/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- v2.1.100/linux/net/netlink/netlink_dev.c	Tue Mar 10 10:03:37 1998
+++ linux/net/netlink/netlink_dev.c	Fri May  8 00:08:02 1998
@@ -116,7 +116,7 @@
 	MOD_INC_USE_COUNT;
 	
 	err = -EINVAL;
-	if (net_families[AF_NETLINK]==NULL)
+	if (net_families[PF_NETLINK]==NULL)
   		goto out;
 
 	err = -ENFILE;
@@ -125,7 +125,7 @@
 
 	sock->type = SOCK_RAW;
 
-	if ((err = net_families[AF_NETLINK]->create(sock, minor)) < 0) 
+	if ((err = net_families[PF_NETLINK]->create(sock, minor)) < 0) 
 	{
 		sock_release(sock);
 		goto out;
diff -u --recursive --new-file v2.1.100/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.1.100/linux/net/netrom/af_netrom.c	Tue Apr 14 14:29:26 1998
+++ linux/net/netrom/af_netrom.c	Fri May  8 00:08:02 1998
@@ -98,7 +98,7 @@
 	struct sock *sk;
 	nr_cb *nr;
 
-	if ((sk = sk_alloc(AF_NETROM, GFP_ATOMIC, 1)) == NULL)
+	if ((sk = sk_alloc(PF_NETROM, GFP_ATOMIC, 1)) == NULL)
 		return NULL;
 
 	if ((nr = kmalloc(sizeof(*nr), GFP_ATOMIC)) == NULL) {
@@ -1235,12 +1235,12 @@
 
 static struct net_proto_family nr_family_ops = 
 {
-	AF_NETROM,
+	PF_NETROM,
 	nr_create
 };
 
 static struct proto_ops nr_proto_ops = {
-	AF_NETROM,
+	PF_NETROM,
 
 	sock_no_dup,
 	nr_release,
@@ -1363,7 +1363,7 @@
 #ifdef CONFIG_SYSCTL
 	nr_unregister_sysctl();
 #endif
-	sock_unregister(AF_NETROM);
+	sock_unregister(PF_NETROM);
 
 	for (i = 0; i < nr_ndevs; i++) {
 		if (dev_nr[i].priv != NULL) {
diff -u --recursive --new-file v2.1.100/linux/net/netsyms.c linux/net/netsyms.c
--- v2.1.100/linux/net/netsyms.c	Thu May  7 22:51:56 1998
+++ linux/net/netsyms.c	Fri May  8 00:08:02 1998
@@ -17,6 +17,10 @@
 #include <net/neighbour.h>
 #include <net/snmp.h>
 
+#ifdef CONFIG_BRIDGE
+#include <net/br.h>
+#endif
+
 #ifdef CONFIG_INET
 #include <linux/ip.h>
 #include <linux/etherdevice.h>
@@ -190,6 +194,10 @@
 EXPORT_SYMBOL(sklist_insert_socket);
 
 EXPORT_SYMBOL(scm_detach_fds);
+
+#ifdef CONFIG_BRIDGE 
+EXPORT_SYMBOL(br_ioctl);
+#endif
 
 #ifdef CONFIG_INET
 /* Internet layer registration */
diff -u --recursive --new-file v2.1.100/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.1.100/linux/net/packet/af_packet.c	Thu May  7 22:51:56 1998
+++ linux/net/packet/af_packet.c	Fri May  8 00:08:02 1998
@@ -704,7 +704,7 @@
 	MOD_INC_USE_COUNT;
 
 	err = -ENOBUFS;
-	sk = sk_alloc(AF_PACKET, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_PACKET, GFP_KERNEL, 1);
 	if (sk == NULL)
 		goto out;
 
@@ -721,7 +721,7 @@
 		goto out_free;
 	memset(sk->protinfo.af_packet, 0, sizeof(struct packet_opt));
 	sk->zapped=0;
-	sk->family = AF_PACKET;
+	sk->family = PF_PACKET;
 	sk->num = protocol;
 
 	/*
@@ -1176,7 +1176,7 @@
 
 #ifdef CONFIG_SOCK_PACKET
 struct proto_ops packet_ops_spkt = {
-	AF_PACKET,
+	PF_PACKET,
 
 	sock_no_dup,
 	packet_release,
@@ -1198,7 +1198,7 @@
 #endif
 
 struct proto_ops packet_ops = {
-	AF_PACKET,
+	PF_PACKET,
 
 	sock_no_dup,
 	packet_release,
@@ -1223,7 +1223,7 @@
 };
 
 static struct net_proto_family packet_family_ops = {
-	AF_PACKET,
+	PF_PACKET,
 	packet_create
 };
 
@@ -1238,7 +1238,7 @@
 void cleanup_module(void)
 {
 	unregister_netdevice_notifier(&packet_netdev_notifier);
-	sock_unregister(packet_family_ops.family);
+	sock_unregister(PF_PACKET);
 	return;
 }
 
diff -u --recursive --new-file v2.1.100/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.1.100/linux/net/rose/af_rose.c	Thu May  7 22:51:56 1998
+++ linux/net/rose/af_rose.c	Fri May  8 00:08:02 1998
@@ -149,7 +149,7 @@
 	struct sock *sk;
 	rose_cb *rose;
 
-	if ((sk = sk_alloc(AF_ROSE, GFP_ATOMIC, 1)) == NULL)
+	if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, 1)) == NULL)
 		return NULL;
 
 	if ((rose = kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) {
@@ -1320,12 +1320,12 @@
 } 
 
 static struct net_proto_family rose_family_ops = {
-	AF_ROSE,
+	PF_ROSE,
 	rose_create
 };
 
 static struct proto_ops rose_proto_ops = {
-	AF_ROSE,
+	PF_ROSE,
 
 	sock_no_dup,
 	rose_release,
@@ -1462,7 +1462,7 @@
 #endif
 	unregister_netdevice_notifier(&rose_dev_notifier);
 
-	sock_unregister(AF_ROSE);
+	sock_unregister(PF_ROSE);
 
 	for (i = 0; i < rose_ndevs; i++) {
 		if (dev_rose[i].priv != NULL) {
diff -u --recursive --new-file v2.1.100/linux/net/sched/cls_api.c linux/net/sched/cls_api.c
--- v2.1.100/linux/net/sched/cls_api.c	Sat May  2 14:19:55 1998
+++ linux/net/sched/cls_api.c	Fri May  8 00:08:02 1998
@@ -395,7 +395,7 @@
 __initfunc(int tc_filter_init(void))
 {
 #ifdef CONFIG_RTNETLINK
-	struct rtnetlink_link *link_p = rtnetlink_links[AF_UNSPEC];
+	struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC];
 
 	/* Setup rtnetlink links. It is made here to avoid
 	   exporting large number of public symbols.
diff -u --recursive --new-file v2.1.100/linux/net/sched/sch_api.c linux/net/sched/sch_api.c
--- v2.1.100/linux/net/sched/sch_api.c	Sat May  2 14:19:55 1998
+++ linux/net/sched/sch_api.c	Fri May  8 00:08:02 1998
@@ -928,7 +928,7 @@
 #endif
 
 #ifdef CONFIG_RTNETLINK
-	struct rtnetlink_link *link_p = rtnetlink_links[AF_UNSPEC];
+	struct rtnetlink_link *link_p = rtnetlink_links[PF_UNSPEC];
 
 	/* Setup rtnetlink links. It is made here to avoid
 	   exporting large number of public symbols.
diff -u --recursive --new-file v2.1.100/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.1.100/linux/net/sunrpc/svcsock.c	Thu Mar 26 15:57:25 1998
+++ linux/net/sunrpc/svcsock.c	Fri May  8 00:08:02 1998
@@ -905,7 +905,7 @@
 	}
 	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	if ((error = sock_create(AF_INET, type, protocol, &sock)) < 0)
+	if ((error = sock_create(PF_INET, type, protocol, &sock)) < 0)
 		return error;
 
 	if (sin != NULL) {
diff -u --recursive --new-file v2.1.100/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.1.100/linux/net/sunrpc/xprt.c	Tue Mar 10 10:03:37 1998
+++ linux/net/sunrpc/xprt.c	Fri May  8 00:08:02 1998
@@ -1231,7 +1231,7 @@
 	}
 
 	sock = &file->f_inode->u.socket_i;
-	if (sock->ops->family != AF_INET) {
+	if (sock->ops->family != PF_INET) {
 		printk(KERN_WARNING "RPC: only INET sockets supported\n");
 		return NULL;
 	}
@@ -1284,7 +1284,7 @@
 			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
 
 	type = (proto == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
-	if ((err = sock_create(AF_INET, type, proto, &sock)) < 0) {
+	if ((err = sock_create(PF_INET, type, proto, &sock)) < 0) {
 		printk("RPC: can't create socket (%d).\n", -err);
 		goto failed;
 	}
diff -u --recursive --new-file v2.1.100/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.100/linux/net/unix/af_unix.c	Thu Mar 26 15:57:25 1998
+++ linux/net/unix/af_unix.c	Fri May  8 00:08:02 1998
@@ -364,14 +364,14 @@
 		default:
 			return -ESOCKTNOSUPPORT;
 	}
-	sk = sk_alloc(AF_UNIX, GFP_KERNEL, 1);
+	sk = sk_alloc(PF_UNIX, GFP_KERNEL, 1);
 	if (!sk)
 		return -ENOMEM;
 
 	sock_init_data(sock,sk);
 
 	sk->destruct = unix_destruct_addr;
-	sk->protinfo.af_unix.family=AF_UNIX;
+	sk->protinfo.af_unix.family=PF_UNIX;
 	sk->protinfo.af_unix.dentry=NULL;
 	sk->sock_readers=1;			/* Us */
 	sk->protinfo.af_unix.readsem=MUTEX;	/* single task reading lock */
@@ -1446,7 +1446,7 @@
 #endif
 
 struct proto_ops unix_stream_ops = {
-	AF_UNIX,
+	PF_UNIX,
 	
 	sock_no_dup,
 	unix_release,
@@ -1467,7 +1467,7 @@
 };
 
 struct proto_ops unix_dgram_ops = {
-	AF_UNIX,
+	PF_UNIX,
 	
 	sock_no_dup,
 	unix_release,
@@ -1488,7 +1488,7 @@
 };
 
 struct net_proto_family unix_family_ops = {
-	AF_UNIX,
+	PF_UNIX,
 	unix_create
 };
 
@@ -1534,7 +1534,7 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
-	sock_unregister(AF_UNIX);
+	sock_unregister(PF_UNIX);
 #ifdef CONFIG_SYSCTL
 	unix_sysctl_unregister();
 #endif
diff -u --recursive --new-file v2.1.100/linux/net/unix/garbage.c linux/net/unix/garbage.c
--- v2.1.100/linux/net/unix/garbage.c	Tue Mar 10 10:03:37 1998
+++ linux/net/unix/garbage.c	Fri May  8 00:08:02 1998
@@ -72,9 +72,9 @@
 		struct sock * s = sock->sk;
 
 		/*
-		 *	AF_UNIX ?
+		 *	PF_UNIX ?
 		 */
-		if (s && sock->ops && sock->ops->family == AF_UNIX)
+		if (s && sock->ops && sock->ops->family == PF_UNIX)
 			u_sock = s;
 	}
 	return u_sock;
